#include <string>
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

class Reader {
protected:
  string file;
  Reader(const std::string& _file): file(_file) {}
  virtual void read()=0;
  virtual void transform()=0;
  virtual void write(const std::string& out)=0;
  virtual ~Reader() {}

public:
  void tmpl(const std::string& out) {
    read();
    transform();
    write(out);
  }
};

class IniFile: public Reader {
  std::vector<string> key;
  std::vector<string> value;
  void read() {
    ifstream f(file.c_str());
    string str;
    while(std::getline(f, str)) {
      size_t position=str.find(":");
      key.push_back(str.substr(0,position));
      value.push_back(str.substr(position+1,str.size()));
    
    }
  } 
  void transform() {
    for (unsigned int i=0; i < key.size(); ++i) {
      string s;
      for (unsigned int j=0; j < key[i].size(); ++j) {
	s.push_back(toupper(key[i][j]));
      }
      key[i]=s;
    }
  }
  void write(const string& out) {
    ofstream o(out.c_str());
    for (unsigned i=0; i < key.size(); ++i)
      o << key[i] << ":" << value[i] <<endl;
  } 
    
public:
  IniFile(const string& o):Reader(o){}
};


class IniMaskFile: public Reader {
  std::vector<string> key;
  std::vector<string> value;
  void read() {
    ifstream f(file.c_str());
    string str;
    while(std::getline(f, str)) {
      size_t position=str.find(":");
      key.push_back(str.substr(0,position));
      value.push_back(str.substr(position+1,str.size()));
    
    }
  } 

  void transform() {
    for (unsigned int i=0; i < key.size(); ++i) {
      string s;
      for (unsigned int j=0; j < key[i].size(); ++j) {
	if (key[i]=="Test")
	  key[i]="XXXX";
      }

    }
  }

  void write(const string& out) {
    ofstream o(out.c_str());
    for (unsigned i=0; i < key.size(); ++i)
      o << key[i] << "__" << value[i] <<endl;
  } 
    
public:
  IniMaskFile(const string& o):Reader(o){}
};


int
main(int argc ,char **argv) {

  Reader* reader;
  if (argc > 1 && argv[1][0]=='a') 
    reader= new IniFile("./inifile");
  else
    reader= new IniMaskFile("./inifile");
  reader->tmpl("out");
  return 0;
}
