From feb69c6dff30257d12188b5ecb51a578b339f01c Mon Sep 17 00:00:00 2001 From: guy Date: Thu, 11 Sep 2003 07:26:47 +0000 Subject: [PATCH] Patch level : 2.0 nopatch Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunti files per supporto ODBC via XML git-svn-id: svn://10.65.10.50/trunk@11403 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/codeb.c | 15 +- include/controls.cpp | 4 +- include/isam.cpp | 12 +- include/odbc.cpp | 652 +++++++++++++++++++++++++++++++++++++++++++ include/odbc_loc.cpp | 566 ------------------------------------- include/odbc_nul.cpp | 419 --------------------------- include/relation.cpp | 4 +- include/xml.cpp | 498 +++++++++++++++++++++++++++++++++ include/xml.h | 85 ++++++ 9 files changed, 1257 insertions(+), 998 deletions(-) create mode 100755 include/odbc.cpp delete mode 100755 include/odbc_loc.cpp delete mode 100755 include/odbc_nul.cpp create mode 100755 include/xml.cpp create mode 100755 include/xml.h diff --git a/include/codeb.c b/include/codeb.c index b75ae8615..4b350b840 100755 --- a/include/codeb.c +++ b/include/codeb.c @@ -14,13 +14,13 @@ */ +#ifdef CB6 + #define XVT_INCL_NATIVE #include #define S4OFF_REPORT -#ifdef CB6 - #if XVT_OS == XVT_OS_WIN32 #define S4DLL #define S4WIN32 @@ -336,7 +336,7 @@ int DB_eof(int handle) } /*------------------------------------------------------------------------- - torna 1 se tof, 0 altrimenti + torna 1 se bof, 0 altrimenti --------------------------------------------------------------------------*/ int DB_bof(int handle) { @@ -1181,7 +1181,12 @@ int DB_memowrite( const int handle, const char * fieldname, const char * data ) return ret; } -#else // CB6 +#endif + +#ifdef CB5 + +#define XVT_INCL_NATIVE +#include #if XVT_OS == XVT_OS_WIN32 #define S4DLL @@ -2441,4 +2446,4 @@ int DB_memowrite( const int handle, const char * fieldname, const char * data ) return ret; } -#endif // CB6 +#endif // CB5 diff --git a/include/controls.cpp b/include/controls.cpp index eec27f9e4..3a981d096 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -796,8 +796,8 @@ void TControl::coord2rct(WINDOW win, short x, short y, short dx, short dy, RCT & RCT max_rct; xvt_vobj_get_client_rect(win, &max_rct); xi_pu_to_fu(itf, (XinPoint *)&max_rct, 2); - const int& MAXX = max_rct.right; - const int& MAXY = max_rct.bottom; + const int MAXX = max_rct.right; + const int MAXY = max_rct.bottom; int width = XI_FU_MULTIPLE; if (dx > 0) diff --git a/include/isam.cpp b/include/isam.cpp index ec300e690..a9c2956b5 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -2854,7 +2854,7 @@ void TRectype::write_memo(TIsam_handle file, const TRecnotype recno) } } - CHECK( recno > 0, "Maiale! Non fare le GO con _recno < 0 " ); + CHECKD(recno >= 0, "Maiale! Non fare le GO con _recno < 0: ", recno); TCodeb_handle cb_handle = prefix().get_handle(file); DB_go( cb_handle, recno); for( int i = _memo_data->last( ); i > 0; i = _memo_data->pred( i ) ) @@ -3310,7 +3310,6 @@ void TRectype::zero(const char* fieldname) } void TRectype::zero(char c) - { memset(_rec, c, len()); recall(); @@ -3406,8 +3405,13 @@ void TRectype::renum_key(const char* field, const char* val) // Certified 99% TRectype& TRectype::operator =(const char* rec) { - memcpy(_rec, rec, _length); - setempty(FALSE); + if (rec && * rec) + { + memcpy(_rec, rec, _length); + setempty(FALSE); + } + else + zero(); return *this; } diff --git a/include/odbc.cpp b/include/odbc.cpp new file mode 100755 index 000000000..4d44aae01 --- /dev/null +++ b/include/odbc.cpp @@ -0,0 +1,652 @@ +#ifndef CB6 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class TDB_table : public TObject +{ + TString _study, _firm, _name; + int _logicnum; + int _mode, _index; + int _rec_len; + long _rec_count; + TString _query; + TString _query_name; + long _recno; // 0 = bof; 1 = first record; 2 second record + TXmlItem _record; + TString _record_buf, _key_buf; + +protected: + void build_soap_method(const char* strMethod, TXmlItem& method) const; + int fill_record(const TXmlItem* res); + +public: + virtual bool ok() const { return rec_len() > 0; } + + int select_tag(int t); + int tag() const { return _index; } + int rec_len() const; + long rec_count() const; + bool bof() const { return _recno <= 0; } + bool eof() const { return _recno > rec_count(); } + char* get_record(); + char* get_key(); + long recno() const { return _recno; } + + int go_to(long recno); + int skip_to(long recno, long offset); + int seek(const char* key); + + TDB_table(const char* file, int mode, int index); +}; + +class TDB_manager : public TSocketClient +{ + TString _server; + TArray _table; + int _error; + +protected: + +public: + TCodeb_handle open(const char* name, int mode, int index); + int close(TCodeb_handle h); + + TDB_table& table(TCodeb_handle h) const; + + int set_error(int e) { return _error = e; } + int get_error() const { return _error; } + + TXmlItem* call_soap(const TXmlItem& method, TXmlItem& answer); + + TDB_manager(); + ~TDB_manager(); +}; + +static TDB_manager* _db = NULL; + +/////////////////////////////////////////////////////////// +// TDB_table +/////////////////////////////////////////////////////////// + +void TDB_table::build_soap_method(const char* strMethod, TXmlItem& method) const +{ + CHECKS(strMethod[0] == 'm' && strMethod[1] == ':', "Missing m: in SOAP method", strMethod); + method.Destroy(); + method.SetTag(strMethod); + method.AddSoapString("Study", _study); + method.AddSoapString("Firm", _firm); + method.AddSoapString("Table", _name); + method.AddSoapInt("Index", _index); +} + +long TDB_table::rec_count() const +{ + if (_rec_count <= 0) + { + TXmlItem method, answer; + build_soap_method("m:TableRows", method); + const TXmlItem* res = _db->call_soap(method, answer); + if (res != NULL) + { + TString16 str; + res->GetEnclosedText(str); + (long&)_rec_count = atol(str); + } + } + return _rec_count; +} + +int TDB_table::fill_record(const TXmlItem* res) +{ + if (res != NULL) + { + const TXmlItem* rec = res->FindFirst("Record"); + + _recno = atol(rec->GetAttr("RecNo")); + if (_recno > _rec_count) + _rec_count = _recno; + + const RecDes& rd = prefix().get_recdes(_logicnum); + TString16 name; + TString value; + for (int i = 0; i < rec->GetChildren(); i++) + { + const TXmlItem& fld = *rec->GetChild(i); + name = fld.GetAttr("Name"); name.upper(); + const int index = findfld(&rd, name); + if (index != FIELDERR) + { + fld.GetEnclosedText(value); + switch (rd.Fd[index].TypeF) + { + case _boolfld: + value = value[0] == '1' ? "Y" : "N"; break; + case _intfld: + case _longfld: + case _intzerofld: + case _longzerofld: + value.right_just(rd.Fd[index].Len); break; + case _memofld: + value.cut(0); break; + default: + break; + } + _record_buf.overwrite(value, rd.Fd[index].RecOff); + } + } + return NOERR; + } + _recno = _rec_count*4+1; // EOF + return _db->set_error(5); +} + +int TDB_table::go_to(long recno) +{ + if (recno == _recno) + return NOERR; + + TXmlItem method; + build_soap_method("m:GetRecord", method); + method.AddSoapInt("RecNo", recno); + const TXmlItem* res = _db->call_soap(method, _record); + return fill_record(res); +} + +int TDB_table::skip_to(long recno, long offset) +{ + TXmlItem method; + build_soap_method("m:SkipRecord", method); + method.AddSoapInt("RecNo", recno); + method.AddSoapInt("Offset", offset); + const TXmlItem* res = _db->call_soap(method, _record); + return fill_record(res); +} + +char* TDB_table::get_record() +{ + return _record_buf.get_buffer(); +} + +char* TDB_table::get_key() +{ + _key_buf.cut(0); + if (_logicnum > 0 && _index > 0 && _recno > 0 && _recno <= rec_count()) + { + const TXmlItem* rec = _record.FindFirst("Record"); + if (rec != NULL) + { + const RecDes& rd = prefix().get_recdes(_logicnum); + const KeyDes& kd = rd.Ky[_index-1]; // Elenco dei campi della chiave + TString str; + for (int i = 0; i < kd.NkFields; i++) + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = rd.Fd[nf]; + for (int i = 0; i < rec->GetChildren(); i++) + { + const TXmlItem& fld = *rec->GetChild(i); + if (fld.GetAttr("Name").compare(rf.Name, -1, true) == 0) + { + fld.GetEnclosedText(str); + switch (rf.TypeF) + { + case _intfld: + case _longfld: + case _intzerofld: + case _longzerofld: + str.right_just(rf.Len); break; + default: + str.rpad(rf.Len); break; + } + _key_buf << str; + break; + } + } + } + } + } + return _key_buf.get_buffer(); +} + +int TDB_table::seek(const char* key) +{ +/* + TXmlItem method; + build_soap_method("m:SeekRecord", method); + method.AddSoapString("Key", key); + const TXmlItem* res = _db->call_soap(method, _record); + return fill_record(res); +*/ + return skip_to(0, 0); +} + +int TDB_table::rec_len() const +{ + if (_rec_len <= 0) + { + TXmlItem method, answer; + build_soap_method("m:GetRecordLength", method); + const TXmlItem* res = _db->call_soap(method, answer); + if (res != NULL) + { + TString16 str; + if (res->GetEnclosedText(str)) + (int&)_rec_len = atoi(str)+1; // Add deleted flag (1 byte) + } + } + return _rec_len; +} + +int TDB_table::select_tag(int t) +{ + int err = NOERR; + if (t != _index) + { + _index = t; + + if (ok()) + { + TXmlItem method, answer; + build_soap_method("m:CreateIndex", method); + + const RecDes& rd = prefix().get_recdes(_logicnum); + const KeyDes& kd = rd.Ky[_index-1]; // Elenco dei campi della chiave + for (int i = 0; i < kd.NkFields; i++) + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = rd.Fd[nf]; + TXmlItem& fld = method.AddChild("Field"); + fld.SetAttr("Name", rf.Name); + if (kd.FieldSeq[i] >= MaxFields) + fld.SetAttr("Upper", "1"); + } + + TString16 str; + const TXmlItem* res = _db->call_soap(method, answer); + if (res != NULL) + res->GetEnclosedText(str); + if (str != "1") + err = _db->set_error(883); // ??? + } + } + return err; +} + +TDB_table::TDB_table(const char* file, int mode, int index) + : _mode(mode), _index(index), _recno(-1), _rec_count(-1), _rec_len(-1), _logicnum(0) +{ + TToken_string tok(file, '/' ); + const int dot = tok.rfind('.'); + if (dot > 0) tok.cut(dot); + tok.replace('\\', '/'); + tok.upper(); + const int items = tok.items(); + tok.get(items-1, _name); + tok.get(items-2, _firm); + tok.get(items-3, _study); + + FileDes filedes; + memset(&filedes, 0, sizeof(filedes)); + for (int i = LF_USER; i < 100; i++) + { + CGetFile(i, &filedes, _nolock, _nordir); + if (_name.compare(filedes.SysName+1, -1, true) == 0) + { + _logicnum = i; + break; + } + } +} + +/////////////////////////////////////////////////////////// +// TDB_manager +/////////////////////////////////////////////////////////// + +TCodeb_handle TDB_manager::open(const char* name, int mode, int index) +{ + TCodeb_handle h = -1; // Inizializzo handle non valido + + // Crea tabella + TDB_table* t = new TDB_table(name, mode, index); + if (t->ok()) + { + // Cerca primo handle disponibile + for (h = 0; _table.objptr(h) != NULL; h++); + _table.add(t, h); + } + else + delete t; + + return h; +} + +int TDB_manager::close(TCodeb_handle h) +{ + const int err = _table.destroy(h) ? 0 : 2; + return err; +} + +TDB_table& TDB_manager::table(TCodeb_handle h) const +{ + TDB_table* t = (TDB_table*)_table.objptr(h); + CHECKD(t != NULL, "Invalid TABLE handle ", h); + return *t; +} + +TXmlItem* TDB_manager::call_soap(const TXmlItem& method, TXmlItem& answer) +{ + TXmlItem* result = NULL; + + CONNID conn = 0; + for (int i = 0; conn == 0 && i < 5; i++) + conn = QueryConnection("", _server); + if (conn != 0) + { + TString str(8192); + method.AsString(str); + if (HttpSoap(conn, str)) + { + size_t size; + char* buf = (char*)GetBuffer(size); + istrstream inf(buf, size); + if (answer.Read(inf)) + { + str = method.GetTag(); + str << "Result"; + result = answer.FindFirst(str); + } + } + else + error_box(FR("Impossible eseguire '%s' sul soap server '%s'"), + (const char*)method.GetTag(), (const char*)_server); + + RemoveConnection(conn); + } + else + error_box(FR("Impossible connettersi al soap server '%s'"), (const char*)_server); + + return result; +} + +TDB_manager::TDB_manager() +{ + TConfig ini(CONFIG_INSTALL, "Server"); + _server = ini.get("DataBase", NULL, -1, "127.0.0.1:3885"); +} + +TDB_manager::~TDB_manager() +{ } + + +/////////////////////////////////////////////////////////// +// codeb.h implementation +/////////////////////////////////////////////////////////// + +void DB_init(void) +{ + DB_exit(); + _db = new TDB_manager(); +} + +void DB_exit(void) +{ + if (_db != NULL) + { + delete _db; + _db = NULL; + } +} + +TCodeb_handle DB_open(const char *filename, int mode, int index) +{ + return _db->open(filename, mode, index); +} + +int DB_close(TCodeb_handle handle) +{ + return _db->close(handle); +} + +char* DB_getrecord(int handle) +{ + return _db->table(handle).get_record(); +} + +int DB_reclen(int handle) +{ + return _db->table(handle).rec_len(); +} + +int DB_keylen(int handle) +{ + return 0; +} + +long DB_recno(int handle) +{ + return _db->table(handle).recno(); +} + +long int DB_reccount(int handle) +{ + return _db->table(handle).rec_count(); +} + +int DB_tagselect(int handle,int index_no) +{ + return _db->table(handle).select_tag(index_no); +} + +int DB_tagget(int handle) +{ + return _db->table(handle).tag(); +} + +int DB_first(int handle) +{ + return _db->table(handle).skip_to(0, 0); +} + +int DB_last(int handle) +{ + return _db->table(handle).skip_to(-1, 0); +} + +int DB_next(int handle) +{ + return DB_skip(handle, +1); +} + +int DB_prev(int handle) +{ + return DB_skip(handle, -1); +} + +int DB_skip(int handle,long offset) +{ + TDB_table& tab = _db->table(handle); + return tab.skip_to(tab.recno(), offset); +} + +int DB_lock(int handle) +{ + return 0; +} + +int DB_unlock(int handle) +{ + return 0; +} + +int DB_seek(int handle,char *key) +{ + return _db->table(handle).seek(key); +} + +int DB_eof(int handle) +{ + return _db->table(handle).eof(); +} + +int DB_bof(int handle) +{ + return _db->table(handle).bof(); +} + +int DB_go(int handle,long recno) +{ + return _db->table(handle).go_to(recno); +} + +int DB_delete(int handle) +{ + return 0; +} + +int DB_recall(int handle) +{ + return 0; +} + +int DB_delkey(int handle, char* key, long recno) +{ + return 0; +} + +int DB_flush(int handle) +{ + return 0; +} + +int DB_rewrite(int handle) +{ + return 0; +} + +bool DB_has_memo(int handle) +{ + return false; +} + +int DB_add(int handle) +{ + return 0; +} + +int DB_lockfile(int handle) +{ + return 0; +} + +int DB_packfile(short vis, const char * filename, long eod) +{ + return 0; +} + +int DB_packmemo(short vis, const char * filename) +{ + return 0; +} + +int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask ) +{ + return 0; +} + +int DB_build(const char * filename, RecDes *r) +{ + return 0; +} + +int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys) +{ + return 0; +} + +int DB_get_error(void) +{ + return _db->get_error(); +} + +void DB_zero_error(void) +{ + _db->set_error(0); +} + +int DB_index_seek(int handle, char* from) +{ + return DB_seek(handle, from); +} + +long DB_index_recno(int handle) +{ + return DB_recno(handle); +} + +long DB_index_next(int handle) +{ + return DB_next(handle); +} + +char* DB_index_getkey(int handle) +{ + return _db->table(handle).get_key(); +} + +int DB_index_go(int handle, const char * key, long recno) +{ + return DB_go(handle, recno); +} + +char* DB_memoptr(const int handle, const char * fieldname ) +{ + return 0; +} + +int DB_memowrite(const int handle, const char * fieldname, const char * data ) +{ + return 0; +} + +int DB_index_eof(int handle) +{ + return DB_eof(handle); +} + +int DB_lock_rec(int handle,long nrec) +{ + return 0; +} + +int DB_file_locked(int handle) +{ + return 0; +} + +int DB_rec_locked(int handle,long nrec) +{ + return 0; +} + +long DB_getconf() +{ + return 0; +} + +long DB_changed(int handle) +{ + return 0; +} + +#endif diff --git a/include/odbc_loc.cpp b/include/odbc_loc.cpp deleted file mode 100755 index 2ce436eeb..000000000 --- a/include/odbc_loc.cpp +++ /dev/null @@ -1,566 +0,0 @@ -#include -#include -#include - -#include - -/////////////////////////////////////////////////////////// -// TDataBase -/////////////////////////////////////////////////////////// - -class TDataBase -{ - wxDbConnectInf m_ci; - wxDb* m_db; - -public: - bool Open(const wxString& dsn, const wxString& user, - const wxString& password, const wxString& path); - bool IsOpen() const; - void Close(); - wxDb& DataBase() { return *m_db; } - - TDataBase(); - virtual ~TDataBase(); -}; - -bool TDataBase::Open(const wxString& dsn, const wxString& user, - const wxString& password, const wxString& path) -{ - Close(); - - m_ci.SetDsn(dsn); - m_ci.SetUserID(user); - m_ci.SetPassword(password); - m_ci.SetDefaultDir(path); - - if (m_ci.AllocHenv()) - { - m_db = ::wxDbGetConnection(&m_ci, false); // Forward only? - if (m_db == NULL) - m_ci.FreeHenv(); - } - - return IsOpen(); -} - -void TDataBase::Close() -{ - if (m_db) - { - m_db->SetSqlLogging(sqlLogOFF); - ::wxDbFreeConnection(m_db); - m_db = NULL; - m_ci.FreeHenv(); - } -} - -bool TDataBase::IsOpen() const -{ - return m_db != NULL; -} - -TDataBase::TDataBase(), m_db(NULL) -{ - m_ci.Henv = 0; - DeleteContents(true); -} - -TDataBase::~TDataBase() -{ - Close(); -} - -/////////////////////////////////////////////////////////// -// TDataBaseList -/////////////////////////////////////////////////////////// - -class TDataBaseList : public wxHashTable -{ - wxString m_strUser, m_strPassword; - -protected: - wxString& User(); - wxString& Password(); - -public: - TDataBase& db(const wxString& path); - TDataBaseList() : wxHashTable(wxKEY_STRING) { } -}; - -static DataBaseList theDataBaseList; - -wxString& TDataBaseList::User() -{ - if (m_strUser.IsEmpty()) - { - // TBI Read user and password - } - return m_strUser; -} - -wxString& TDataBaseList::Password() -{ - if (m_strPassword.Isempty()) - User(); // Initialize both User and Password - return m_strPassword; -} - -wxString& TDataBaseList::Dsn(const wxString& dbpath) -{ - wxString study; - long firm = -1; - for (int i = dbpath.GetLength()-1; i >= 0; i--) - if (dbpath[i] == '\\' || dbpath[i] == '/') - { - firm = atol(dbpath.Mid(i+1)); - break; - } - for (int j = i-1; j >= 0; j--) - if (dbpath[j] == '\\' || dbpath[j] == '/') - { - study = dbpath.Mid(j+1, i-j); - break; - } - wxString dsn = study; - if (firm > 0) - dsn << firm; - return dsn; -} - -TDataBase& TDataBaseList::db(const wxString& dbpath) -{ - wxString dsn = Dsn(dbpath); - TDataBase* d = (TDataBase*)Get(dsn); - if (d == NULL) - { - d = new TDataBase; - Put(dsn, d); - bool ok = d->Open(dsn, User(), Password(), dbpath); - if (!ok) - { - wxString msg = wxString::Format("L'utente %s non è abilitato all'uso del database %s\n" - "corrispondente agli archivi in %s", - User(), dsn, dbpath); - wxMessageBox(msg, "Errore"); - exit(0); - } - } - return *d; -} - -/*-------------------------------------------------------------------------- - inizializzazione di CodeBase e delle variabili necessarie - questa funzione deve essere chiamata SOLO una volta all'interno - di ciascun eseguibile - --------------------------------------------------------------------------*/ -void DB_init(void) -{ -} - -/*-------------------------------------------------------------------------- - reset di CodeBase - questa funzione dovrebbe essere chiamata prima di uscire da un eseguibile - per una questione di correttezza formale. Non usandola comunque non acca- - de niente di drammatico - --------------------------------------------------------------------------*/ -void DB_exit(void) -{ - ::wxDbCloseConnections(); -} - -/*------------------------------------------------------------------------- - apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura - esclusiva. Il parametro index consente se == 0 l'apertura senza indici. - Ritorna l'handle del file aperto oppure -1 in caso di errore - --------------------------------------------------------------------------*/ -int DB_open(const char *filename,int mode,int index) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - chiusura del database inviduato da handle - torna -1 se il database non puo essere chiuso, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_close(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - torna il puntatore al buffer del record del database individuato da - handle. In caso di errore torna (char *) 0 - --------------------------------------------------------------------------*/ -char *DB_getrecord(int handle) -{ - return NULL; -} - -/*------------------------------------------------------------------------- - torna la lunghezza del record - --------------------------------------------------------------------------*/ -int DB_reclen(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna la lunghezza della chiave corrente - --------------------------------------------------------------------------*/ - -int DB_keylen(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - torna il numero del record attuale - --------------------------------------------------------------------------*/ -long int DB_recno(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna il numero complessivo dei records presenti nell'archivio - --------------------------------------------------------------------------*/ -long int DB_reccount(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - seleziona un indice sul database specificato - torna -1 se errore, altrimenti 0 - --------------------------------------------------------------------------*/ -int DB_tagselect(int handle,int index_no) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - torna il numero dell'indice selezionato - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_tagget(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - si posiziona sul primo record - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_first(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - si posiziona sull'ultimorecord - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_last(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - skip avanti di un record - --------------------------------------------------------------------------*/ -int DB_next(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - skip indietro di un record - --------------------------------------------------------------------------*/ -int DB_prev(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - skip di n records - --------------------------------------------------------------------------*/ -int DB_skip(int handle,long int recno) -{ - return -1; -} - -/*------------------------------------------------------------------------- - locka il record attuale - --------------------------------------------------------------------------*/ -int DB_lock(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - slocka il record attuale - --------------------------------------------------------------------------*/ -int DB_unlock(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - cerca la chiave, torna r4after se not found ma si e' posizionato sul record - successivo, se torna r4eof e' su eof - --------------------------------------------------------------------------*/ -int DB_seek(int handle,char *key) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna 1 se eof, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_eof(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna 1 se tof, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_bof(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - legge un record per numero record - --------------------------------------------------------------------------*/ -int DB_go(int handle,long recno) -{ - return -1; -} - -/*------------------------------------------------------------------------- - cancella il record attuale. Non cancella le chiavi. - --------------------------------------------------------------------------*/ -int DB_delete(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - ripristina il record attuale - --------------------------------------------------------------------------*/ -int DB_recall(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - - --------------------------------------------------------------------------*/ -int DB_flush(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - riscrive il record attuale - --------------------------------------------------------------------------*/ -int DB_rewrite(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - appende il record attuale - --------------------------------------------------------------------------*/ -int DB_add(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Blocca in modo esclusivo il file dati ed indice - --------------------------------------------------------------------------*/ -int DB_lockfile(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Compatta il file dati - --------------------------------------------------------------------------*/ -int DB_packfile(short vis, const char * filename, long eod) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Compatta il file memo - --------------------------------------------------------------------------*/ -int DB_packmemo(short vis, const char * filename) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Elimina i record duplicati - --------------------------------------------------------------------------*/ -int DB_clean_file(int handle, char * filename, char * ff, RecDes * r, short vis) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Compatta gli indici - --------------------------------------------------------------------------*/ -int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask) -{ - return 0; -} - - -/*------------------------------------------------------------------------- - costruisce il file filename - --------------------------------------------------------------------------*/ - -int DB_build(const char * filename, RecDes *r) -{ - return -1; -} - -/*------------------------------------------------------------------------- - reperisce il tracciato record e la stringa di definizione delle chiavi - Stringa di definizione chiavi: - expression1|unique1$expression2|unique2$expression3|unique3 - --------------------------------------------------------------------------*/ - -int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys) -{ - return -1; -} - -/*------------------------------------------------------------------------- - ritorna l'ultimo errore - --------------------------------------------------------------------------*/ -int DB_get_error(void) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Azzera la viarabile globale d'errore - --------------------------------------------------------------------------*/ - -void DB_zero_error(void) -{ -} - -/*------------------------------------------------------------------------- - Si posiziona sull'indice attivo alla chiave indicata, restituisce - la prima chiave che trova >= a from. (TCursor) - --------------------------------------------------------------------------*/ - -int DB_index_seek(int handle, char* from) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna il numero di record corrispondente alla chiave corrente - --------------------------------------------------------------------------*/ - -long DB_index_recno(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Si posiziona sulla chiave successiva dell'indice corrente - --------------------------------------------------------------------------*/ -long DB_index_next(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Restituisce la chiave corrente - --------------------------------------------------------------------------*/ - -char* DB_index_getkey(int handle) -{ - return NULL; -} - -/*------------------------------------------------------------------------- - Restituisce vero se l'indice e' alla fine - --------------------------------------------------------------------------*/ - -int DB_index_eof(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Blocca il record indicato - --------------------------------------------------------------------------*/ - -int DB_lock_rec(int handle,long nrec) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna vero(non zero) se il file dati od indice sono stati bloccati - in modo esclusivo dalla presente applicazione, non da altri programmi!!! - --------------------------------------------------------------------------*/ - -int DB_file_locked(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna vero se il record nrec e' bloccato dalla presente applicazione, - non da altri programmi!!! - --------------------------------------------------------------------------*/ - -int DB_rec_locked(int handle,long nrec) -{ - return 0; -} - -/*------------------------------------------------------------------------- - restituisce la configurazione della libreria - --------------------------------------------------------------------------*/ - -long DB_getconf() -{ - return 0; -} - -/*------------------------------------------------------------------------- - Restituisce il numero di versione scritto sull'header dell'indice - --------------------------------------------------------------------------*/ - -long DB_changed(int handle) -{ - return 0; -} - -char* DB_memoptr( const int handle, const char * fieldname ) -{ - return NULL; -} - -int DB_memowrite( const int handle, const char * fieldname, const char * data ) -{ - return NULL; -} - diff --git a/include/odbc_nul.cpp b/include/odbc_nul.cpp deleted file mode 100755 index a3c4c43e5..000000000 --- a/include/odbc_nul.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include - -#define MAXLEN 137 /* Lunghezza massima chiave */ - - -/*-------------------------------------------------------------------------- - inizializzazione di CodeBase e delle variabili necessarie - questa funzione deve essere chiamata SOLO una volta all'interno - di ciascun eseguibile - --------------------------------------------------------------------------*/ -void DB_init(void) -{ -} - -/*-------------------------------------------------------------------------- - reset di CodeBase - questa funzione dovrebbe essere chiamata prima di uscire da un eseguibile - per una questione di correttezza formale. Non usandola comunque non acca- - de niente di drammatico - --------------------------------------------------------------------------*/ -void DB_exit(void) -{ -} - -/*------------------------------------------------------------------------- - apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura - esclusiva. Il parametro index consente se == 0 l'apertura senza indici. - Ritorna l'handle del file aperto oppure -1 in caso di errore - --------------------------------------------------------------------------*/ -int DB_open(const char *filename,int mode,int index) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - chiusura del database inviduato da handle - torna -1 se il database non puo essere chiuso, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_close(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - torna il puntatore al buffer del record del database individuato da - handle. In caso di errore torna (char *) 0 - --------------------------------------------------------------------------*/ -char *DB_getrecord(int handle) -{ - return NULL; -} - -/*------------------------------------------------------------------------- - torna la lunghezza del record - --------------------------------------------------------------------------*/ -int DB_reclen(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna la lunghezza della chiave corrente - --------------------------------------------------------------------------*/ - -int DB_keylen(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - torna il numero del record attuale - --------------------------------------------------------------------------*/ -long int DB_recno(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna il numero complessivo dei records presenti nell'archivio - --------------------------------------------------------------------------*/ -long int DB_reccount(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - seleziona un indice sul database specificato - torna -1 se errore, altrimenti 0 - --------------------------------------------------------------------------*/ -int DB_tagselect(int handle,int index_no) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - torna il numero dell'indice selezionato - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_tagget(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - si posiziona sul primo record - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_first(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - si posiziona sull'ultimorecord - torna -1 se errore - --------------------------------------------------------------------------*/ -int DB_last(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - skip avanti di un record - --------------------------------------------------------------------------*/ -int DB_next(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - skip indietro di un record - --------------------------------------------------------------------------*/ -int DB_prev(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - skip di n records - --------------------------------------------------------------------------*/ -int DB_skip(int handle,long int recno) -{ - return -1; -} - -/*------------------------------------------------------------------------- - locka il record attuale - --------------------------------------------------------------------------*/ -int DB_lock(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - slocka il record attuale - --------------------------------------------------------------------------*/ -int DB_unlock(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - cerca la chiave, torna r4after se not found ma si e' posizionato sul record - successivo, se torna r4eof e' su eof - --------------------------------------------------------------------------*/ -int DB_seek(int handle,char *key) -{ - return r4eof; -} - -/*------------------------------------------------------------------------- - torna 1 se eof, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_eof(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - torna 1 se tof, 0 altrimenti - --------------------------------------------------------------------------*/ -int DB_bof(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - legge un record per numero record - --------------------------------------------------------------------------*/ -int DB_go(int handle,long recno) -{ - return -1; -} - -/*------------------------------------------------------------------------- - cancella il record attuale. Non cancella le chiavi. - --------------------------------------------------------------------------*/ -int DB_delete(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - ripristina il record attuale - --------------------------------------------------------------------------*/ -int DB_recall(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - - --------------------------------------------------------------------------*/ -int DB_flush(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - riscrive il record attuale - --------------------------------------------------------------------------*/ -int DB_rewrite(int handle) -{ - return -1; -} - - -/*------------------------------------------------------------------------- - appende il record attuale - --------------------------------------------------------------------------*/ -int DB_add(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Blocca in modo esclusivo il file dati ed indice - --------------------------------------------------------------------------*/ -int DB_lockfile(int handle) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Compatta il file dati - --------------------------------------------------------------------------*/ -int DB_packfile(short vis, const char * filename, long eod) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Compatta il file memo - --------------------------------------------------------------------------*/ -int DB_packmemo(short vis, const char * filename) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Elimina i record duplicati - --------------------------------------------------------------------------*/ -int DB_clean_file(int handle, char * filename, char * ff, RecDes * r, short vis) -{ - return -1; -} - -/*------------------------------------------------------------------------- - Compatta gli indici - --------------------------------------------------------------------------*/ -int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask) -{ - return 0; -} - - -/*------------------------------------------------------------------------- - costruisce il file filename - --------------------------------------------------------------------------*/ - -int DB_build(const char * filename, RecDes *r) -{ - return -1; -} - -/*------------------------------------------------------------------------- - reperisce il tracciato record e la stringa di definizione delle chiavi - Stringa di definizione chiavi: - expression1|unique1$expression2|unique2$expression3|unique3 - --------------------------------------------------------------------------*/ - -int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys) -{ - return -1 -} - -/*------------------------------------------------------------------------- - ritorna l'ultimo errore - --------------------------------------------------------------------------*/ -int DB_get_error(void) -{ - return 0 -} - -/*------------------------------------------------------------------------- - Azzera la viarabile globale d'errore - --------------------------------------------------------------------------*/ - -void DB_zero_error(void) -{ -} - -/*------------------------------------------------------------------------- - Si posiziona sull'indice attivo alla chiave indicata, restituisce - la prima chiave che trova >= a from. (TCursor) - --------------------------------------------------------------------------*/ - -int DB_index_seek(int handle, char* from) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna il numero di record corrispondente alla chiave corrente - --------------------------------------------------------------------------*/ - -long DB_index_recno(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Si posiziona sulla chiave successiva dell'indice corrente - --------------------------------------------------------------------------*/ -long DB_index_next(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Restituisce la chiave corrente - --------------------------------------------------------------------------*/ - -char* DB_index_getkey(int handle) -{ - return NULL; -} - -/*------------------------------------------------------------------------- - Restituisce vero se l'indice e' alla fine - --------------------------------------------------------------------------*/ - -int DB_index_eof(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Blocca il record indicato - --------------------------------------------------------------------------*/ - -int DB_lock_rec(int handle,long nrec) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna vero(non zero) se il file dati od indice sono stati bloccati - in modo esclusivo dalla presente applicazione, non da altri programmi!!! - --------------------------------------------------------------------------*/ - -int DB_file_locked(int handle) -{ - return 0; -} - -/*------------------------------------------------------------------------- - Ritorna vero se il record nrec e' bloccato dalla presente applicazione, - non da altri programmi!!! - --------------------------------------------------------------------------*/ - -int DB_rec_locked(int handle,long nrec) -{ - return 0; -} - -/*------------------------------------------------------------------------- - restituisce la configurazione della libreria - --------------------------------------------------------------------------*/ - -long DB_getconf() -{ - return 0; -} - -/*------------------------------------------------------------------------- - Restituisce il numero di versione scritto sull'header dell'indice - --------------------------------------------------------------------------*/ - -long DB_changed(int handle) -{ - return 0; -} - -char* DB_memoptr( const int handle, const char * fieldname ) -{ - return NULL; -} - -int DB_memowrite( const int handle, const char * fieldname, const char * data ) -{ - return NULL; -} - diff --git a/include/relation.cpp b/include/relation.cpp index 3f451d83e..e69410d2a 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -1022,7 +1022,7 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) if (DB_reccount(fhnd) == 0) return 0; - TRecnotype oldrecno=0,ap = 0; + TRecnotype oldrecno= RECORD_NON_FISICO,ap = 0; int pagecnt = 0; FILE* indf = NULL; @@ -1031,7 +1031,7 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) if (junk < 0) junk=get_error(junk); if (junk == _iseof) return 0; - DB_index_recno(fhnd); + // DB_index_recno(fhnd); // A cosa cavolo serve? _pos=-1; const bool filtered = has_filter(); diff --git a/include/xml.cpp b/include/xml.cpp new file mode 100755 index 000000000..a97fdbd9d --- /dev/null +++ b/include/xml.cpp @@ -0,0 +1,498 @@ +#include "real.h" +#include "xml.h" + +#include +#include + +/////////////////////////////////////////////////////////// +// Utilities +/////////////////////////////////////////////////////////// + +void Spaces(ostream& outf, int nSpaces) +{ + outf << '\n'; + if (nSpaces > 0) + { + TString str(nSpaces, ' '); + str.print_on(outf); + } +} + +int hex2int(const char* str) +{ + int n = 0; + for (int i = 0; str[i]; i++) + { + if (str[i] >= '0' && str[i] <= '9') + { + n *= 16; + n += str[i]-'0'; + } else + if (str[i] >= 'A' && str[i] <= 'F') + { + n *= 16; + n += str[i]-'A'+10; + } + else + break; + } + return n; +} + +const TString& EscapeSequence(char cStart, istream& inf) +{ + TString& str = get_tmp_string(); + + if (cStart == '&') + { + for (char c = inf.get(); c != ';'; c = inf.get()) + str << c; + if (str == "lt") return str ="<"; + if (str == "gt") return str =">"; + if (str == "nbsp") return str =" "; + if (str == "Agrave") return str ="À"; + if (str == "Egrave") return str ="È"; + if (str == "Eacuto") return str ="É"; + if (str == "Igrave") return str ="Ì"; + if (str == "Ograve") return str ="Ò"; + if (str == "Ugrave") return str ="Ù"; + if (str == "agrave") return str ="à"; + if (str == "egrave") return str ="è"; + if (str == "eacuto") return str ="é"; + if (str == "igrave") return str ="ì"; + if (str == "ograve") return str ="ò"; + if (str == "ugrave") return str ="ù"; + + const char tmp[2] = { cStart, '\0' }; + str.insert(tmp); + } else + if (cStart == '%') + { + for (int i = 0; i < 2; i++) + str << inf.get(); + char c = hex2int(str); + str = c; + } + + return str; +} + +void WriteXmlString(ostream& outf, const char* str) +{ + for (int i = 0; str[i]; i++) + { + char c = str[i]; + if (c < 0 || strchr("<>/&", c) != NULL) + { + unsigned int n = (unsigned char)c; + TString8 tmp; tmp.format("%%%02X", n); + tmp.print_on(outf); + } + else + outf << c; + } +} + +/////////////////////////////////////////////////////////// +// TXmlAttr +/////////////////////////////////////////////////////////// + +class TXmlAttr : public TString +{ +public: + void Write(ostream& outf) const; + TXmlAttr(const char* str) : TString(str) { } +}; + +void TXmlAttr::Write(ostream& outf) const +{ + if (empty()) + { + outf << '"' << '"'; + } + else + { + if (real::is_real(*this)) + { + print_on(outf); + } + else + { + outf << '"'; + print_on(outf); + outf << '"'; + } + } +} + +/////////////////////////////////////////////////////////// +// TXmlItem +/////////////////////////////////////////////////////////// + +TXmlItem& TXmlItem::SetAttr(const char* strAttr, const char* strVal) +{ + if (m_Attributes == NULL) + m_Attributes = new TAssoc_array; + m_Attributes->remove(strAttr); + m_Attributes->add(strAttr, new TXmlAttr(strVal)); + return *this; +} + +const TString& TXmlItem::GetAttr(const char* strAttr) const +{ + if (m_Attributes != NULL) + { + const TXmlAttr* str = (const TXmlAttr*)m_Attributes->objptr(strAttr); + if (str != NULL) + return *str; + } + return EMPTY_STRING; +} + +int TXmlItem::GetChildren() const +{ + int n = 0; + if (m_Children != NULL) + n = m_Children->items(); + return n; +} + +TXmlItem* TXmlItem::GetChild(size_t n) const +{ + TXmlItem* i = NULL; + if (m_Children != NULL) + i = (TXmlItem*)m_Children->objptr(n); + return i; +} + + +bool TXmlItem::GetWord(istream& inf, TString& str) const +{ + str.cut(0); + + int cFirstChar = EOF; + while (!inf.eof()) + { + cFirstChar = inf.get(); + if (cFirstChar <= 0 || cFirstChar > ' ') + break; + } + if (cFirstChar == EOF) + return false; + + const bool bIsString = cFirstChar == '"' || cFirstChar == '\''; + if (!bIsString) + { + str << char(cFirstChar); + if (strchr("<=/>", cFirstChar) != NULL) + return true; // Simboli terminali + } + + while (!inf.eof()) + { + int c = inf.get(); + if (bIsString) + { + if (c == cFirstChar) + break; + if (c >= '\0' && c <= ' ') + c = ' '; + str << char(c); + } + else + { + if (c >= '\0' && c <= ' ') + break; + if (strchr("<=/>", c)) + { + inf.putback(char(c)); + break; + } + str << char(c); + } + } + return str.not_empty(); +} + +int TXmlItem::ReadTag(istream& inf) +{ + TString str; + if (!GetWord(inf, str)) + return -1; + + if (str[0] != '<') // No tag = sequence of words + { + bool bFirstChar = true; + while (!inf.eof()) + { + char c = inf.get(); + if (c == '<') + { + inf.putback(c); + break; + } + if (bFirstChar) + { + str << ' '; + bFirstChar = false; + } + if (c == '&' || c == '#' || c == '%') + str << EscapeSequence(c, inf); + else + str << c; + } + SetTag(""); + SetText(str); + return 0; + } + + TString name, tmp; + + bool bChildrenFollow = true; + GetWord(inf, m_strTag); + if (m_strTag == "/") // Sto leggendo un tag di chiusura del tipo + { + bChildrenFollow = false; + GetWord(inf, tmp); + m_strTag << tmp; + } + + while (GetWord(inf, name)) + { + if (name[0] == '>') + return bChildrenFollow ? +1 : 0; + + if (name[0] == '/') + { + bChildrenFollow = false; + continue; + } + + // Ho letto un nome di attributo + GetWord(inf, tmp); + if (tmp.empty() || tmp[0] != '=') + break; + // Leggo il valore dell'attributo + GetWord(inf, tmp); + SetAttr(name, tmp); + } + return -1; +} + +TXmlItem& TXmlItem::AddChild(TXmlItem* pItem) +{ + if (m_Children == NULL) + m_Children = new TArray; + if (pItem == NULL) + pItem = new TXmlItem; + m_Children->add(pItem); + return *pItem; +} + +TXmlItem& TXmlItem::AddChild(const char* strTagName) +{ + TXmlItem& i = AddChild((TXmlItem*)NULL); + i.SetTag(strTagName); + return i; +} + +TXmlItem& TXmlItem::AddSoapString(const char* name, const char* value, bool typized) +{ + TXmlItem& xmlVar = AddChild(name); + if (typized) + xmlVar.SetAttr("xsi:type", "xsd:string"); + xmlVar.AddChild("").SetText(value); + return xmlVar; +} + +TXmlItem& TXmlItem::AddSoapInt(const char* name, int value, bool typized) +{ + TXmlItem& xmlVar = AddChild(name); + if (typized) + xmlVar.SetAttr("xsi:type", "xsd:int"); + TString16 str; str << value; + xmlVar.AddChild("").SetText(str); + return xmlVar; +} + +void TXmlItem::RemoveLastChild() +{ + if (m_Children != NULL) + m_Children->destroy(m_Children->last()); +} + +bool TXmlItem::Read(istream& inf) +{ + Destroy(); + const int res = ReadTag(inf); + if (res > 0) // There are children ahead + { + while (!inf.eof()) + { + TXmlItem& item = AddChild("/"); // Add dummy child + if (item.Read(inf)) + { + if (item.m_strTag[0] == '/') + break; + } + else + break; + } + RemoveLastChild(); // Remove dummy child + } + return res >= 0; +} + +TXmlItem* TXmlItem::ForEach(XmlItemCallback cb, long jolly) +{ + if (cb(*this, jolly)) + return this; + + for (int n = 0; ; n++) + { + TXmlItem* c = GetChild(n); + if (c == NULL) + break; + c = c->ForEach(cb, jolly); + if (c) + return c; + } + + return NULL; +} + +static bool GetEnclosedTextCallback(TXmlItem& item, long jolly) +{ + TString* strText = (TString*)jolly; + const TString& str = item.GetText(); + if (!str.empty()) + { + if (!strText->empty()) + *strText << " "; + *strText << str; + } + return false; +} + +bool TXmlItem::GetEnclosedText(TString& text) const +{ + text.cut(0); + ((TXmlItem*)this)->ForEach(GetEnclosedTextCallback, (long)&text); + return text.not_empty(); +} + +TXmlItem& TXmlItem::AddEnclosedText(const char* str) +{ + TXmlItem* item = FindFirst(""); + if (item == NULL) + item = &AddChild(""); + if (item->m_strText == NULL) + item->SetText(str); + else + *item->m_strText << str; + return *item; +} + +TXmlItem& operator<<(TXmlItem& item, const char* str) +{ + item.AddEnclosedText(str); + return item; +} + +void TXmlItem::Write(ostream& outf, int tab) const +{ + if (!GetTag().empty()) + { + Spaces(outf, tab); + outf << '<'; + GetTag().print_on(outf); + if (m_Attributes != NULL) + { + TAssoc_array& ass = *m_Attributes; + FOR_EACH_ASSOC_OBJECT(ass, h, k, a) + { + outf << ' '; + outf.write(k, strlen(k)); + outf << '='; + const TXmlAttr* attr = (const TXmlAttr*)a; + attr->Write(outf); + } + } + if (GetChildren() > 0) + { + outf << '>'; + for (int n = 0; ; n++) + { + TXmlItem* c = GetChild(n); + if (c == NULL) + break; + c->Write(outf, tab+1); + } + if (GetChild(n-1)->GetText().empty()) + Spaces(outf, tab); + outf << '<' << '/'; + GetTag().print_on(outf); + outf << '>'; + } + else + outf << ' ' << '/' << '>'; + } + else + GetText().print_on(outf); +} + +void TXmlItem::AsString(TString& str) const +{ + for (size_t nSize = 8192; ; nSize *= 2) + { + char* buf = str.get_buffer(nSize); + memset(buf, 0, nSize); + ostrstream outf(buf, nSize); + Write(outf, 0); + if (buf[nSize-1] == '\0') + break; + } +} + +void TXmlItem::Save(const char* strFilename) const +{ + ofstream outf(strFilename); + Write(outf, 0); +} + +static bool FindFirstCallback(TXmlItem& item, long jolly) +{ + const char* strTag = (const char*)jolly; + return item.GetTag() == strTag; +} + +void TXmlItem::Destroy() +{ + m_strTag.cut(0); + if (m_strText) + m_strText->cut(0); + if (m_Attributes) + m_Attributes->destroy(); + if (m_Children) + m_Children->destroy(); +} + +TXmlItem* TXmlItem::FindFirst(const char* strTag) const +{ + return ((TXmlItem*)this)->ForEach(FindFirstCallback, (long)strTag); +} + +TXmlItem::TXmlItem() + : m_strTag(15), m_Attributes(NULL), m_Children(NULL), m_strText(NULL) +{ } + +TXmlItem::~TXmlItem() +{ + if (m_strText) + delete m_strText; + if (m_Attributes) + delete m_Attributes; + if (m_Children) + delete m_Children; +} + diff --git a/include/xml.h b/include/xml.h new file mode 100755 index 000000000..6e8b78948 --- /dev/null +++ b/include/xml.h @@ -0,0 +1,85 @@ +#ifndef __XML_H +#define __XML_H + +#ifndef __ASSOC_H +#include +#endif + +class TXmlItem; + +typedef bool (*XmlItemCallback)(TXmlItem& item, long jolly); + +class TXmlItem : public TObject +{ + DECLARE_DYNAMIC_CLASS(TXmlItem); + + TString m_strTag; + TString* m_strText; + TAssoc_array* m_Attributes; + TArray* m_Children; + +protected: + bool GetWord(istream& input, TString& str) const; + int ReadTag(istream& input); + + TXmlItem& AddChild(TXmlItem* pItem); + +public: + const TString& GetTag() const { return m_strTag; } + void SetTag(const char* strTag) { m_strTag = strTag; } + + const TString& GetText() const + { + if (m_strText != NULL) + return *m_strText; + return EMPTY_STRING; + } + void SetText(const char* str) + { + if (m_strText == NULL) + m_strText = new TString(str); + else + *m_strText = str; + } + + TXmlItem& AddEnclosedText(const char* str); + bool GetEnclosedText(TString& str) const; + + TXmlItem& SetAttr(const char* strAttr, const char* strVal); + const TString& GetAttr(const char* strAttr) const; + + TXmlItem& AddChild(const char* strTag); + TXmlItem& AddSoapString(const char* name, const char* value, bool typized = false); + TXmlItem& AddSoapInt(const char* name, int value, bool typized = false); + + int GetChildren() const; + TXmlItem* GetChild(size_t n) const; + void RemoveLastChild(); + + void Destroy(); + bool Read(istream& input); + void Write(ostream& output, int nTab) const; + void AsString(TString& str) const; + + void Save(const char* strFilename) const; + + TXmlItem* ForEach(XmlItemCallback cb, long jolly = 0); + TXmlItem* FindFirst(const char* strTag) const; + + TXmlItem(); + ~TXmlItem(); +}; + +TXmlItem& operator<<(TXmlItem& item, const char* str); + +ostream& operator<<(ostream& outf, const char* str); +ostream& operator<<(ostream& outf, TString str); +istream& operator>>(istream& inf, TString& str); +void Spaces(ostream& outf, int nSpaces); +void WriteXmlString(ostream& outf, const char* str); +int hex2int(const char* str); + +#define endl "\r\n"; + +#endif +