#include #include #include "utility.h" #include "xml.h" class TLettore : public TObject { TXmlItem _trc; int _lines, _chars; TString _rseparator, _fseparator; TString_array _curr; protected: bool load_trc(const char* trc); char* get_line_buffer(int i, int size); bool read_record(istream& input); const TString& get_field(const TXmlItem& field) const; const TXmlItem* find_field(const TXmlItem& record, const TString& name) const; void evaluate(const TString& expr, const TXmlItem& recin, TString& val) const; void smart_trim(TString& val, int mode) const; public: int convert(const TFilename& src, const TFilename& trc, const TFilename& dst); int convert(const char* cmd); }; bool TLettore::load_trc(const char* t) { const TFilename trc = t; bool ok = trc.exist(); if (ok) { ifstream in(trc); ok = _trc.Read(in); } _curr.destroy(); // reset line sizes return ok; } char* TLettore::get_line_buffer(int i, int size) { TToken_string* str = (TToken_string*)_curr.objptr(i); if (str == NULL) { str = new TToken_string(size); _curr.add(str, i); } char* buff = str->get_buffer(size); *buff = '\0'; return buff; } bool TLettore::read_record(istream& input) { bool ok = true; if (_lines <= 1 && _chars > 0) // Record a lunghezza fissa { char* buff = get_line_buffer(0, _chars); input.read(buff, _chars); buff[_chars] = '\0'; } else { int size = _chars; if (size <= 0) size = 1024; for (int i = 0; i < _lines; i++) { char* buff = get_line_buffer(i, size); input.getline(buff, size); buff[size] = '\0'; } } return ok; } const TString& TLettore::get_field(const TXmlItem& field) const { int y = field.GetIntAttr("Y" ) - 1; if (y < 0) y = 0; int x = field.GetIntAttr("X" ) - 1; if (x < 0) x = 0; int l = field.GetIntAttr("Length"); const TString& str = _curr.row(y).mid(x, l); return str; } void TLettore::smart_trim(TString& val, int mode) const { switch (mode) { case 1: val.rtrim(); break; case 2: val.ltrim(); break; case 3: val.trim(); break; default: break; } } const TXmlItem* TLettore::find_field(const TXmlItem& record, const TString& name) const { for (int i = 0; i < record.GetChildren(); i++) { const TXmlItem* field = record.GetChild(i); if (field->GetAttr("Name") == name) return field; } return NULL; } void TLettore::evaluate(const TString& expr, const TXmlItem& recin, TString& val) const { TToken_string expression(expr, '+'); val.cut(0); TString str; FOR_EACH_TOKEN(expression, tok) { str = tok; str.trim(); if (str[0] == '\'' || str[0] == '"') { str.rtrim(1); str.ltrim(1); val << str; } else { bool trim = false; if (str.starts_with("TRIM(")) { str.ltrim(5); str.rtrim(1); str.trim(); trim = true; } const TXmlItem* infield = find_field(recin, str); if (infield != NULL) { str = get_field(*infield); if (trim) str.trim(); val << str; } } } } int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilename& dst) { if (!src.exist()) { error_box("Non esiste il file di input\n%s", (const char*)src); return 1; } if (!load_trc(trc)) { error_box("Non esiste il tracciato record\n%s", (const char*)trc); return 2; } if (dst.blank()) { error_box("File di output non valido:\n%s", (const char*)dst); return 3; } const TXmlItem* infile = _trc.FindFirst("Input"); const TXmlItem* outfile = _trc.FindFirst("Output"); if (infile == NULL || outfile == NULL) { error_box("Tracciato record non valido:\nNon esiste il tag o "); return 4; } const TXmlItem* recin = infile->FindFirst("Record"); const TXmlItem* recout = outfile->FindFirst("Record"); if (recin == NULL || recout == NULL) { error_box("Tracciato record non valido:\nNon esiste il tag "); return 4; } _lines = recin->GetIntAttr("Lines"); if (_lines <= 0) _lines = 1; _chars = recin->GetIntAttr("Chars"); _rseparator = esc(outfile->GetAttr("RecordSeparator")); _fseparator = esc(recout->GetAttr("FieldSeparator")); const int inmode = infile->GetIntAttr("Binary") != 0 ? (ios::in|ios::binary) : ios::in; ifstream input(src, inmode); const int outmode = outfile->GetIntAttr("Binary") != 0 ? (ios::out|ios::binary) : ios::out; ofstream output(dst, outmode); TString expr, val; while (!input.eof()) { read_record(input); for (int i = 0; i < recout->GetChildren(); i++) { const TXmlItem* outfield = recout->GetChild(i); outfield->GetEnclosedText(expr); if (expr.empty()) expr = outfield->GetAttr("Name"); evaluate(expr, *recin, val); smart_trim(val, outfield->GetIntAttr("Trim")); if (i > 0) output << _fseparator; output << val; } output << _rseparator; } return 0; } int TLettore::convert(const char* cmd) { TToken_string str(cmd, ' '); str.strip_d_spaces(); const TFilename src = str.get(); const TFilename trc = str.get(); const TFilename dst = str.get(); return convert(src, trc, dst); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { TLettore app; const int err = app.convert(lpCmdLine); return err; }