
// File "BDtest.cc".  By KWR.  Illustrates pointer semantics, inheritance,
// and dynamic dispatch ("virtual functions" in C++ lingo).  For CSE250 S'00.
// Read together with "BDtest.java" for Java-to-C++ translation examples.

#include<string>
#include<vector>
#include<iostream>
#include<typeinfo>   ///needed for "dynamic_cast" translating Java "instanceof"
using namespace std; ///redundant on our system?

///*--------------------------------Add these to your code-------------------
#include <stdio.h>  // for sprintf
string ftoa(double x) {  //Converts float or double to an ANSI string.
   char b[100]; sprintf(b, "%f", x); string s = b; return s;
}  //This code and itoa based on Cay Horstmann, /Computing Concepts with C++/
string itoa(long int x) {  //Converts [long, short] int to an ANSI string.
   char b[100]; sprintf(b, "%d", x); string s = b; return s;
}
bool isWhitespace(char c){return c==' ' || c=='\n' || c=='\t' || c=='\0';}
string trim(string str) {
   int i = 0; int j = str.length() - 1;  ///in C++, length is a method too.
   while (isWhitespace(str.at(i)) && i < j) i++;
   if (i==j) return ""; //string is all whitespace
   else {               //in this case str.at(i) != whitespace and acts as a
      while (isWhitespace(str.at(j))) j--; //sentinel, so need not say j >= i
      return str.substr(i,j-i+1);          //take j-i+1 chars from position i
   }
}
bool startsWith(string str, string prefix) {
   return str.find(prefix) == 0;
}
bool endsWith(string str, string suffix) {
   return str.rfind(suffix) == str.length()-1;
}
//*/--------------------------End of stuff to put in your code--------------


class Base {
   //int value = 0;  ///can do this in Java but NOT in C++...
   int value;        ///must initialize by construction OR "outside the class"
public:
   //Base() {}                 ///Legal in C++, but would not translate Java
   Base() : value(0) { }       ///since C++ does not default-initialize fields
   Base(int v) : value(v) { }  ///C++ initializer syntax not legal in Java
   ///destructor ~Base() not needed since class holds no pointers.
   virtual int getValue() const { return value; }
   virtual void setValue(int v) { value = v; }    ///a "mutator"---not const!

   virtual string toString() const { return "I'm from Base Class! "; }
   ///^^^Not an automatic conversion in C++ as in Java.  Here's the C++ lingo:
   virtual operator const char*() const { return "Base Class! "; }
   ///Alas, they haven't built-in automatic conversion to ANSI "string" type:
   virtual operator /*const*/ string() const { return "Class Base! "; }
   static string greeting() { return "Hello from Base"; }            
}; 

class Derived : public Base {
public:
   Derived() : Base() { }        ///C++ uses baseclass name instead of "super"
   Derived(int v) : Base(v) { }  ///super-call can only come before {...}
   /// This toString() overrides the one in Base.  Note "string" is lOWERCASE
   ///destructor ~Derived() not needed since class holds no pointers.
   virtual string toString() const {return "I'm from Derived Class! ";}
   virtual string derivedOnly() const {
      return "Method \"derivedOnly\" is not defined in the base class."; 
   }
   virtual operator const char*() const { return "Derived Class! "; }
   virtual operator /*const*/ string() const { return "Class Derived! "; }
   static string greeting() {return "Hello from Derived"; }   
};

void castCheck(Base* base) {                ///must come above main() in C++.
   Derived* dbase = dynamic_cast<Derived*>(base); ///this and next line 
   if (dbase != NULL) {                     ///translate Java "instanceof"
      //cout << dynamic_cast<Derived*>(base)->derivedOnly() << endl;
      cout << dbase->derivedOnly() << endl;
   } else {
      cout << "Duck! A run-time \"bad cast\" error is coming!" << endl
           << "Is the error message as helpful as the Java one was?" << endl;
      for (int i = 0; i <= 49994999; i++) {}    //just for visual delay
      cout << dynamic_cast<Derived*>(base)->derivedOnly() << endl;
      //cout << dbase->derivedOnly() << endl;
   }
   cerr << "Call to castCheck has terminated OK." << endl;
}

void stringTest() {
   string str1 = "New "; string str2 = string("James "); ///equivalent
   string str3; str3.assign(" Bond: ");                  ///another way
   //cout << str1 + str2 + str3 + 200 + 7 << endl; ///C++ "+" cannot do this.
   cout << str1 + str2 + str3 + "200" + "7" << endl; ///OK
   str1.append(str2);  ///fine: C++ strings are mutable.
   cout << "With the ANSI indexing convention you get \"" + str1.substr(4,7)
        << "\"" << endl;  ///substr(i,j) means take j chars starting at pos i,
                          ///OR take as many as you can if i+j > length!
   if (str1 == "New James ") {
      cout << str1 + "== \"New James \" as expected of objects" << endl;
   } else {
      cout << str1 + "!= \"New James \" because both are pointers!" << endl;
   }
   if (str3 < str2) {  ///C++ has "operator<" built-in for strings.
         cout << "Compare " +str3+str2+"= " + itoa(str3.compare(str2)) << endl;
   }
   if (str3 < str2) {  ///The usual comparison operators ARE available.
      cout << "Compare " + str3 + str2 + "= " << str3.compare(str2) << endl;
      }
      cout << "\"" + str3 + "\" gets a trim: \"" + trim(str3) + "\"" << endl;
      cout << ( startsWith(str3,"Bond") ? "C++ strings are mutable"//() needed!
                                        : "C++ strings are immutable" )
        << ", and the length of " + str3 + " is now " << str3.length() << endl;
      ///Note: "___?___:___" binds less than <<, so the () are needed.
}

int main(int argc, char** argv) {
   stringTest(); cout << endl;
   //Base* base1, base2;    ///Error: must be "Base *base1, *base2", or better
   Base* base1; Base* base2;///Can declare class pointers without initializing
   base1 = new Base();      ///and initialize them later, or declare & init.
   Derived* derived = new Derived();  ///...in one statement like this.
   base2 = derived;
   cout << "base1 says: " + base1->toString() << endl;
   cout << "base2 says: " + base2->toString() << endl;
      //since base2 holds a Derived instance, the Derived version is /run/.

   cout << "Note-(Derived*)base2 prints: " << ((Derived*)base2)->toString()
      << endl;;
   //cout << "but (*derived)+*base2 prints: " << ((*derived)+(*base2)) << endl;
   ///^^^Operator+ seems not to recognize "string" or "const char*" conversions
   cout << "but (*derived)+*base2 prints: " << (*derived) << *base2 << endl;
   cout << "and (derived) +*base1 prints: " << (derived) << *base1 << endl;
   
   cout << "Now, \"base2 = derived\" uses pointer semantics:" << endl;
   cout << "Value of \"derived\" now: " << derived->getValue() << endl;
   cout << "Executing derived->setValue(1); " << endl;
   derived->setValue(1);
   cout << "Now base2->getValue() = " << base2->getValue() << endl;

   cout << "base2 whispers: ";
   castCheck(base2);
   cout << "base1 screams:  ";
   castCheck(base1);

   cout << "Can we make a derived class object say \"base\"?" << endl;
   cout << base2->greeting() << endl;
}  //end of main
