#include "iomanip.h"
#include "iostream.h"
#include "string.h"
#include "algorithm.h"

void print_char(int i)
{
  cout << "'" << char(i) << "' ";
}

void debug_print(string const& s)
{
  cout << setw(3) << s.size();
  cout << setw(3) << s.length();
  cout << setw(3) << s.capacity();
  cout << " >" << s << "<" << endl;
}

int main()
{
  string s1;
  string s2("Hello world!");
  string s3("Hello world!", 7);
  string s4(s2);
  string s5(s2, 0);
  string s6(s2, 2);
  string s7(s2, 2, 5);
  string s8(s2, 2, 100);
  string s9(s2.begin(), s2.end());
  string s10(s2.begin()+1, s2.end()-1);

  for_each(s2.begin(), s2.end(), print_char);
  cout << endl;

  for_each(s2.rbegin(), s2.rend(), print_char);
  cout << endl;

  cout << endl;

  debug_print(s1);
  debug_print(s2);
  debug_print(s3);
  debug_print(s4);
  debug_print(s5);
  debug_print(s6);
  debug_print(s7);
  debug_print(s8);
  debug_print(s9);
  debug_print(s10);

  s1 = "Hello world!";
  string s11 = s2;

  s3 = "Hell";
  s4 = s2;

  cout << endl;

  debug_print(s2);
  debug_print(s1);
  debug_print(s11);
  debug_print(s3);
  debug_print(s4);

  cout << endl;

  string const& s12 = s11;

  debug_print(s1);
  debug_print(s2);
  debug_print(s3);
  debug_print(s4);
  debug_print(s5);
  debug_print(s6);
  debug_print(s7);
  debug_print(s8);
  debug_print(s9);
  debug_print(s10);
  debug_print(s11);
  debug_print(s12);

  cout << endl;

//  int i;
//  for(i = 0; i < s12.size(); ++i)
//    print_char(s12[i]);
//  cout << endl;

  s11[4] = '*';

//  for(i = 0; i < s12.size(); ++i)
//    print_char(s12[i]);
//  cout << endl;

//  cout << endl;

  debug_print(s1);
  debug_print(s2);
  debug_print(s3);
  debug_print(s4);
  debug_print(s5);
  debug_print(s6);
  debug_print(s7);
  debug_print(s8);
  debug_print(s9);
  debug_print(s10);
  debug_print(s11);
  debug_print(s12);

  string s13;
  s13.reserve(100);

  string s14;
  s14.resize(16, '*');

  string s15("Foo");
  s15.reserve(100);

  string s16("Bar");
  s16.resize(16, '*');

  string s17 = "Hello world!";
  s17.resize(4);

  debug_print(s13);
  debug_print(s14);
  debug_print(s15);
  debug_print(s16);
  debug_print(s17);

  cout << endl;

  debug_print(s1);
  debug_print(s2);
  s1 += " + some more stuff";
  debug_print(s1);
  s1 += "";
  debug_print(s1);
  s1 += s2;
  debug_print(s1);

  cout << endl;

  s1 = "Hello";
  s2 = " world";

  s1.append(s2);
  debug_print(s1);

  s1.append(s2, 2);
  debug_print(s1);

  s1.append(s2, 2, 100);
  debug_print(s1);

  s1.append("foobar");
  debug_print(s1);

  s1.append("foobar", 4);
  debug_print(s1);

  s1.append(s2.begin()+1, s2.end()-1);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "Goodbye cruel world!";
  debug_print(s1);

  s1.assign(s2);
  debug_print(s1);

  s1.assign(s2, 2);
  debug_print(s1);

  s1.assign(s2, 2, 2);
  debug_print(s1);

  s1.assign(s2, 2, 100);
  debug_print(s1);

  s1.assign("Foobar");
  debug_print(s1);

  s1.assign("Foobar", 4);
  debug_print(s1);

  s1.assign(s2.begin()+1, s2.end()-1);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "foo";
  debug_print(s1);

  s1.insert(0, s2);
  debug_print(s1);

  s1.insert(1, s2);
  debug_print(s1);

  s1.insert(s1.size()-1, s2);
  debug_print(s1);

  s1.insert(s1.size(), s2);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "foo";
  debug_print(s1);

  s1.insert(0, s2, 1);
  debug_print(s1);

  s1.insert(1, s2, 1);
  debug_print(s1);

  s1.insert(s1.size()-1, s2, 1);
  debug_print(s1);

  s1.insert(s1.size(), s2, 1);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "foo";
  debug_print(s1);

  s1.insert(0, s2, 1, 1);
  debug_print(s1);

  s1.insert(1, s2, 1, 1);
  debug_print(s1);

  s1.insert(s1.size()-1, s2, 1, 1);
  debug_print(s1);

  s1.insert(s1.size(), s2, 1, 1);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "foo";
  debug_print(s1);

  s1.insert(s1.begin()+2, '*');
  debug_print(s1);

  s1.insert(s1.begin()+1, s2.begin(), s2.end());
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  debug_print(s1);
  s1.erase();
  debug_print(s1);

  s1 = "Hello world!";
  s1.erase(4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.erase(4, 3);
  debug_print(s1);

  s1 = "Hello world!";
  s1.erase(s1.begin());
  debug_print(s1);

  s1 = "Hello world!";
  s1.erase(s1.end()-1);
  debug_print(s1);

  s1 = "Hello world!";
  s1.erase(s1.begin()+1, s1.end());
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "universe";
  debug_print(s1);

  s1.replace(0, size_t(0), s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, 5, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, s1.size(), s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 0, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 5, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, s1.size()-1, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 0, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 1, s2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size(), 0, s2);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "universe";
  debug_print(s1);

  s1.replace(0, 0, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, 5, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, s1.size(), s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 0, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 5, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, s1.size()-1, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 0, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 1, s2, 4);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size(), 0, s2, 4);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  s2 = "universe";
  debug_print(s1);

  s1.replace(0, 0, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, 5, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(0, s1.size(), s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 0, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, 5, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(1, s1.size()-1, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 0, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size()-1, 1, s2, 4, 2);
  debug_print(s1);

  s1 = "Hello world!";
  s1.replace(s1.size(), 0, s2, 4, 2);
  debug_print(s1);

  cout << endl;

  s1 = "Hello world!";
  char* buffer = new char[16];
  cout << hex;

  memset(buffer, 0xff, 16);
  s1.copy(buffer, 16);
  int i;
  for(i = 0; i < 16; ++i)
    if(buffer[i] < ' ' || buffer[i] >= 127)
      cout << int(buffer[i]) << ' ';
    else
      print_char(buffer[i]);
  cout << endl;

  memset(buffer, 0xff, 16);
  s1.copy(buffer, 5);
  for(i = 0; i < 16; ++i)
    if(buffer[i] < ' ' || buffer[i] >= 127)
      cout << int(buffer[i]) << ' ';
    else
      print_char(buffer[i]);
  cout << endl;

  cout << endl;
  cout << dec;

  s1 = "Hello world!";
  s2 = "Hello";
  s3 = "world!";
  s4 = "H";
  s5 = "!";

  cout << int(s1.find(s2)) << endl;
  cout << int(s1.find(s3)) << endl;
  cout << int(s1.find(s4)) << endl;
  cout << int(s1.find(s5)) << endl;

  cout << endl;

  cout << int(s1.find(s2, 3)) << endl;
  cout << int(s1.find(s3, 3)) << endl;
  cout << int(s1.find(s4, 3)) << endl;
  cout << int(s1.find(s5, 3)) << endl;

  cout << endl;

  cout << int(s1.find('H')) << endl;
  cout << int(s1.find('!')) << endl;
  cout << int(s1.find('H', 3)) << endl;
  cout << int(s1.find('!', 3)) << endl;

  cout << endl;

  cout << int(s1.find("Hells bells")) << endl;
  cout << int(s1.find("Hells bells", 0, 4)) << endl;

  cout << endl;

  s1 = "Hello ";
  s2 = "world!";

  debug_print(s1);
  debug_print(s2);
  debug_print(s1+s2);
  debug_print(s1+"foo");
  debug_print("foo"+s1);
  debug_print(s1+'*');
  debug_print('*'+s1);

  cout << endl;

  s1 = "Hello ";
  s2 = "Hello ";
  s3 = "world!";

  cout << (s1 == s2) << endl;
  cout << (s1 == s3) << endl;
  cout << (s1 == "Hello ") << endl;
  cout << (s1 == "world!") << endl;
  cout << ("Hello " == s1) << endl;
  cout << ("world!" == s1) << endl;

  cout << endl;

  cout << (s1 > s2) << endl;
  cout << (s1 > s3) << endl;
  cout << (s1 > "Hello ") << endl;
  cout << (s1 > "world!") << endl;
  cout << ("Hello " > s1) << endl;
  cout << ("world!" > s1) << endl;

  cout << endl;

  cout << (s1 < s2) << endl;
  cout << (s1 < s3) << endl;
  cout << (s1 < "Hello ") << endl;
  cout << (s1 < "world!") << endl;
  cout << ("Hello " < s1) << endl;
  cout << ("world!" < s1) << endl;
};
