From c95157e55e1cbd4c22eee14b4334c89937c11b18 Mon Sep 17 00:00:00 2001 From: guy Date: Thu, 8 Jan 2004 15:08:43 +0000 Subject: [PATCH] Patch level : 2.0 Files correlati : Omnia0.exe Ricompilazione Demo : [ ] Commento : Prima versione del traduttore universale git-svn-id: svn://10.65.10.50/trunk@11690 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- omnia/Omnia0.cpp | 240 ++++++ omnia/array.cpp | 877 +++++++++++++++++++++ omnia/array.h | 324 ++++++++ omnia/assoc.cpp | 450 +++++++++++ omnia/assoc.h | 182 +++++ omnia/checks.cpp | 181 +++++ omnia/checks.h | 95 +++ omnia/classes.h | 71 ++ omnia/object.cpp | 89 +++ omnia/object.h | 268 +++++++ omnia/stdtypes.cpp | 2 + omnia/stdtypes.h | 59 ++ omnia/strings.cpp | 1841 ++++++++++++++++++++++++++++++++++++++++++++ omnia/strings.h | 740 ++++++++++++++++++ omnia/utility.cpp | 454 +++++++++++ omnia/utility.h | 37 + omnia/xml.cpp | 504 ++++++++++++ omnia/xml.h | 86 +++ 18 files changed, 6500 insertions(+) create mode 100755 omnia/Omnia0.cpp create mode 100755 omnia/array.cpp create mode 100755 omnia/array.h create mode 100755 omnia/assoc.cpp create mode 100755 omnia/assoc.h create mode 100755 omnia/checks.cpp create mode 100755 omnia/checks.h create mode 100755 omnia/classes.h create mode 100755 omnia/object.cpp create mode 100755 omnia/object.h create mode 100755 omnia/stdtypes.cpp create mode 100755 omnia/stdtypes.h create mode 100755 omnia/strings.cpp create mode 100755 omnia/strings.h create mode 100755 omnia/utility.cpp create mode 100755 omnia/utility.h create mode 100755 omnia/xml.cpp create mode 100755 omnia/xml.h diff --git a/omnia/Omnia0.cpp b/omnia/Omnia0.cpp new file mode 100755 index 000000000..01c1414ca --- /dev/null +++ b/omnia/Omnia0.cpp @@ -0,0 +1,240 @@ +#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; +} \ No newline at end of file diff --git a/omnia/array.cpp b/omnia/array.cpp new file mode 100755 index 000000000..606863126 --- /dev/null +++ b/omnia/array.cpp @@ -0,0 +1,877 @@ +#include +#include +#include + +#include "strings.h" + +void TContainer::for_each( OPERATION_FUNCTION op ) +{ + TObject* curr = first_item(); + while(curr) + { + op(*curr); + curr = succ_item(); + } +} + +void TContainer::for_each_that( OPERATION_FUNCTION op, CONDITION_FUNCTION match ) +{ + TObject* curr = first_that( match ); + while( curr ) + { + op( *curr ); + curr = succ_that( ); + } +} + +TObject* TContainer::first_that( CONDITION_FUNCTION match ) +{ + _last_condition = match; + if( _last_condition ) + { + TObject* curr = first_item( ); + while( curr && !_last_condition( *curr ) ) + curr = succ_item( ); + return curr; + } + else + return first_item( ); +} + +TObject* TContainer::last_that( CONDITION_FUNCTION match ) +{ + _last_condition = match; + if( _last_condition ) + { + TObject* curr = last_item( ); + while( curr && !_last_condition( *curr ) ) + curr = pred_item( ); + return curr; + } + else + return last_item( ); +} + +TObject* TContainer::succ_that( ) +{ + if( _last_condition ) + { + TObject* curr = succ_item( ); + while( curr && !_last_condition( *curr ) ) + curr = succ_item( ); + return curr; + } + else + return succ_item( ); +} + +TObject* TContainer::pred_that( ) +{ + if( _last_condition ) + { + TObject* curr = pred_item( ); + while( curr && !_last_condition( *curr ) ) + curr = pred_item( ); + return curr; + } + else + return pred_item( ); +} + +long TContainer::count( CONDITION_FUNCTION match ) +{ + long c = 0; + TObject* curr = first_item( ); + while( curr ) + if( match( *curr ) ) + c++; + return c; +} + +TObject* TArray::first_item( ) +{ + _scanindex = first( ); + return ( _scanindex == size( ) )?NULL:_data[ _scanindex ]; +}; + +TObject* TArray::last_item( ) +{ + _scanindex = last( ); + return ( _scanindex == -1 )?NULL:_data[ _scanindex ]; +}; + +TObject* TArray::succ_item( ) +{ + _scanindex = succ( _scanindex ); + return ( _scanindex == size( ))?NULL:_data[ _scanindex ]; +}; + +TObject* TArray::pred_item( ) +{ + _scanindex = pred( _scanindex ); + return ( _scanindex == -1)?NULL:_data[ _scanindex ]; +}; + +// @doc EXTERNAL + +// @mfunc Modifica la dimensione dell'array. +void TArray::resize( + int arraysize) // @parm Indica la nuova dimensione che deve assumere l'array. + + // @comm Alloca la memoria necessaria per contentere i dati della nuova + // dimensione inizializzando a NULL tutti i nuovi elementi aggiunti + // all'array lasciando inalterati, sia in posizione che in + // contenuto gli elementi gia' presenti. + // Nel caso si cerchi di diminuire la dimensione viene dato un + // messaggio di errore. + +{ + CHECK(arraysize > _size, "Can't reduce array size."); + + TObject** newdata = new TObject* [arraysize]; + memset(newdata, 0, arraysize*sizeof(TObject*)); + if (_data != NULL) + { + memcpy(newdata, _data, _size*sizeof(TObject*)); + delete _data; + } + _size = arraysize; + _data = newdata; +} + +// @doc EXTERNAL + +// @mfunc Rimuove uno o tutti (default) gli elementi +// @rdesc Ritorna uno dei seguenti parametri: +// +// @flag TRUE | Se l'operazione e' riuscita con successo +// @flag FALSE | Se il numero di elementi e' rimasto invariato +bool TArray::destroy( + int index, // @parm Numero dell'elemento da eliminare (default -1) + bool pack) // @parm Se true richiama la funzione per compattare gli elementi dell'array (default FALSE) + + // @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli + // elementi dell'array assegnandone il valore NULL. + // Nel caso il parametro pack sia TRUE permette di rendere contigui + // tutti gli elementi diversi da NULL tramite la chiamata alla funzione + // . + +{ + const int old = _items; + + if (index < 0) + { + for (int i = last(); i >= 0; i--) if (_data[i] != NULL) + { + delete _data[i]; + _data[i] = NULL; + } + _items = _next = 0; + } + else + { + TObject* o = remove(index, pack); + if (o) delete o; + } + + return _items < old; +} + + +TArray::TArray(int arraysize) + : _size(0), _items(0), _next(0), _data(NULL) +{ + if (arraysize) + resize(arraysize); +} + +TArray::TArray() + : _size(0), _items(0), _next(0), _data(NULL) +{ +} + +TArray::TArray(const TArray& a) + : _size(0), _items(0), _next(0), _data(NULL) +{ + (*this) = a; +} + +TArray& TArray::operator= (const TArray& a) +{ + destroy(); + if (size() < a.size()) + resize(a.size()); + for (int i = a.size()-1; i >= 0; i--) + { + const TObject* o = a.objptr(i); + if (o != NULL) + { + _data[i] = o->dup(); +#ifdef DBG + const long vir_tab1 = *((long*)o); + const long vir_tab2 = *((long*)_data[i]); + if (vir_tab1 != vir_tab2) + NFCHECK("Duplicazione di elementi di array pericolosa"); +#endif + } + } + _items = ( int )a.items(); + _next = ( int )a._next; + + return *this; +} + +TArray::~TArray() +{ + if (ok()) + { + destroy(); + delete _data; + } +} + +const char* TArray::class_name() const +{ + return "Array"; +} + + +word TArray::class_id() const +{ + return CLASS_ARRAY; +} + +// @doc EXTERNAL + +// @mfunc Stampa un array +void TArray::print_on( + ostream& out) const // @parm indica l'output sul quale reindirizzare la stampa (funzione standard del C++) + + // @comm Permette di stampare sull'output passato come parametro il contenuto + // dell'array, preceduto dal numero dell'elemetno a cui si riferisce. + // Nel caso vi siano degli elementi vuoti (valore = NULL) viene + // stampato il valore (null). + +{ + for (int i = 0; i < size(); i++) + { + out.width(4); + out << i << ' '; + out.width(); + if (_data[i] != NULL) out << *_data[i]; + else out << "(null)"; + out << endl; + } +} + +// @doc EXTERNAL + +// @mfunc Controlla se si tratta di un oggetto valido +// +// @rdesc Ritorna uno dei seguenti parametri: +// @flag TRUE | Se l'array contiene degli elementi +// @flag FALSE | Se l'array e' vuoto +bool TArray::ok() const + +// @comm Controlla se la dimensione dell'array e' uguale a 0 e se esistono +// degli elementi diversi da NULL + +{ + return(size() != 0 && (_data != NULL)); +} + +#ifdef DBG +TObject& TArray::operator[] (int index) const +{ + TObject* o = objptr(index); + if (o == NULL) + { + NFCHECK("Can't access NULL array item %d of %d", index, _size); + const int f = last(); + if (f >= 0) + { + o = objptr(f)->dup(); + ((TArray*)this)->add(o, index); + } + CHECK(o, "Unrecoverable array access error"); + } + return *o; +} +#endif + +// @doc EXTERNAL + +// @mfunc Aggiunge un oggetto ad un array. +// +// @rdesc La funzione ritorna la posizione nella quale e' stato aggiunto +// l'oggetto. +int TArray::add( + TObject *object, // @parm Oggetto da aggiungere nell'array + int index) // @parm Posizione in cui aggiungere l'oggetto + // @parm TObject | &object | Oggetto da aggiungere nell'array. L'oggetto viene duplicato + + // @syntax add(TObject* object,int index); + // @syntax add(TObject& object,int index); + // + // @comm Nel caso venga passata una posizione minore di 0 l'elemento viene aggiunto + // in coda all'array, diversamente viene l'elemento presente viene + // sostitito con l'oggetto passato nei prametri. + // Se e' stato passato un indice minore della dimensione dell'array, + // viene aumentata automaticamente la dimensione dell'array stesso tramite + // la chiamata alla funzione . + // ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve + // essere definita la funzione . + // + // @xref +{ + if (index < 0) + for (index = _next; index < size() && _data[index]; index++); + if (index >= size()) + { + long newsize = 3L * index / 2 + 1; + if (newsize > INT_MAX) + newsize = INT_MAX; + resize((int)newsize); + } + + if (object != _data[index]) // Evita ricopiatura su se stesso + { + if (_data[index] != NULL) + { + delete _data[index]; + _items--; + } + + _data[index] = object; + if (object != NULL) + { + _items++; + _next = index+1; + } + else + { + if (index < _next) + _next = index; + } + } + return index; +} + +// @doc EXTERNAL + +// @mfunc Inserisce un elemento dell'array nella posizione index +// +// @rdesc La funzione ritorna la posizione nella quale e' stato inserito l'oggetto. +int TArray::insert( + TObject *object, // @parm Oggetto da inserire nell'array + int index, // @parm Posizione in cui inserire l'oggetto (puo' essere -1) + bool force) // @parm Forza l'inserimento anche se la posizione e' vuota + // @parm TObject | &object | Oggetto da inserire nell'array. L'oggetto viene duplicato + + // @syntax insert(TObject* object, int index); + // @syntax insert(TObject& object, int index); + // + // @comm Nel caso l'elemento della posizione passata sia diverso da NULL vengono + // spostati di una posizione tutti gli elementi presenti nell'array. + // La dimensione dell'array viene automaticamente aumentata nel caso + // la stessa non sia sufficiente a contenere il nuovo oggetto. + // ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve + // essere definita la funzione . + // + // @xref +{ + const int s = size(); + if ((index >= 0 && index < s) && (force || objptr(index))) + { + if (_data[s - 1]) // Se l'ultimo non e' vuoto ... + add(NULL, s); // ... aggiungi un elemento in fondo + for (int i = size()-1; i > index; i--) // size va aggiornato perche potrebbe essere cambiato + _data[i] = _data[i - 1]; + _data[index] = NULL; + } + return add(object, index); +} + +int TArray::add(const TObject& object, int index) +{ + TObject* objptr = object.dup(); + return add(objptr, index); +} + +int TArray::insert(const TObject& object, int index, bool force) +{ + TObject* objptr = object.dup(); + return insert(objptr, index, force); +} + +// @doc EXTERNAL + +// @mfunc Elimina l'elemento nella posizione index dell'array +// +// @rdesc Ritorna l'elemento dell'array eliminato senza farne la delete +TObject* TArray::remove( + int index, // @parm Indica la posizione dell'elemento da eliminare + bool dopack) // @parm Indica se si vuole richiamare la funzione + // (default FALSE) per spostare gli elementi successivi dell'array +{ + CHECKD(index >= 0, "Can't remove array item ", index); + + TObject* o = objptr(index); + if (o) + { + _data[index] = NULL; + _items--; + if (index < _next) + _next = index; + } + if (dopack && index < size()) + { + const int last = size()-1; + for (int i = index ; i < last; i++) + _data[i] = _data[i+1]; + _data[last] = NULL; + } + return o; +} + +TObject* TArray::remove_item(bool pack ) +{ + return remove(_scanindex,pack); +} + +void TArray::swap(int i1, int i2) +{ + TObject* o1 = remove(i1, FALSE); + TObject* o2 = remove(i2, FALSE); + if (o1) add(o1, i2); + if (o2) add(o2, i1); +} + +// @doc EXTERNAL + +// @mfunc Cerca il prossimo oggetto dell'array +// +// @rdesc Ritorna l'indice del prossimo elemento trovato o size() se non esiste +int TArray::succ(int i) const + +{ + CHECKD(i >= -1, "Bad array index ", i); + for (i++; i < size(); i++) + if (_data[i]) break; + return i; +} + +// @doc EXTERNAL + +// @mfunc Cerca il precedente oggetto dell'array +// +// @rdesc Ritorna l'indice dell'elemento precedente o -1 se non esiste +int TArray::pred(int i) const + +{ + CHECKD(i <= size(), "Bad array index ", i); + for (i--; i >= 0; i--) + if (_data[i]) break; + return i; +} + +// @doc EXTERNAL + +// @mfunc Cerca il primo oggetto dell'array +// +// @rdesc Ritorna l'indice del primo elemento trovato o size() se l'array e' vuoto +int TArray::first() const + +{ + return succ(-1); +} + +// @doc EXTERNAL + +// @mfunc Cerca l'ultimo oggetto dell'array +// +// @rdesc Ritorna l'indice dell'ultimo elemento trovato o -1 se l'array e' vuoto +int TArray::last() const + +{ + return pred(size()); +} + +// @doc EXTERNAL + +// @mfunc Rende contigui tutti gli elementi non nulli +void TArray::pack() + + // @comm Riordina gli elementi dell'array facendo che tra di loro non ve ne + // siano con valore uguale a NULL. +{ + int next = 0; + for (int i = 0; i < size(); i++) + { + if (_data[i] != NULL) + { + if (next < i) + { + _data[next] = _data[i]; + _data[i] = NULL; + } + next++; + } + } + _next = next; +} + +// @doc INTERNAL + +// @func Funzione per permettere il confonto tra 2 oggetti. +// +// @rdesc Ritorna i seguenti valori +// +// @flag 0 | se

+// @flag 0 | se

==

+// @flag 0 | se

+// @flag UNDEFINED | se l'ordine non e' definito +static int sortable_compare( + const TObject** o1, // @parm Primo oggetto da confrontare + const TObject** o2) // @parm Secondo oggetto da confrontare + + // @comm E' utilizzata dalla funzione come default per + // stabilire il criteri di ordinamento degli oggetti passati. +{ + if (o1 == o2) + return 0; // qsort a volte confronta un oggetto con se stesso: per cui ne approfitto! + + const TSortable* s1 = (const TSortable*)*o1; + const TSortable* s2 = (const TSortable*)*o2; + return s1->compare(*s2); +} + +// @doc EXTERNAL + +// @mfunc Ordina i TObject secondo il criterio definito in +void TArray::sort( + COMPARE_FUNCTION compare) // @parm Funzione indicante il criterio di ordinamento (default TSortable) + + // @comm Nel caso non venga passata nessuna funzione che permetta di conforntare + // i due oggetti viene utilizzato il criterio +{ + typedef int (*qsortfunc)(const void*, const void*); + if (compare == NULL) compare = sortable_compare; + + pack(); + qsort(_data, items(), sizeof(TObject*), (qsortfunc)compare); +} + +/////////////////////////////////////////////////////////// +// TPointer_array +/////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @mfunc Rimuove uno o tutti (default) gli elementi +// @rdesc Ritorna uno dei seguenti parametri: +// +// @flag TRUE | Se l'operazione e' riuscita con successo +// @flag FALSE | Se il numero di elementi e' rimasto invariato +bool TPointer_array::destroy( + int index, // @parm Numero dell'elemento da eliminare (default -1) + bool pack) // @parm Se true richiama la funzione per compattare gli elementi dell'array (default FALSE) + + // @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli + // elementi dell'array assegnandone il valore NULL. + // Nel caso il parametro pack sia TRUE permette di rendere contigui + // tutti gli elementi diversi da NULL tramite la chiamata alla funzione + // . + +{ + if (data()) + { + if (index < 0) + memset(data(), 0, size() * sizeof(TObject*)); + else + remove(index); + } + return TArray::destroy(index, pack); +} + +void TPointer_array::copy(const TArray& a) +{ + destroy(); + if (size() < a.size()) + resize(a.size()); + +// for (int i = a.size()-1; i >= 0; i--) +// add(a.objptr(i), i); + memcpy(data(), a.data(), a.size() * sizeof(TObject*)); + _items = a._items; + _next = a._next; +} + +int TPointer_array::add(TObject* object, int index) +{ + if (index >= 0) + remove(index); + return TArray::add(object, index); +} + +int TPointer_array::add(const TObject& object, int index) +{ + return add(&(TObject&)object, index); +} + +int TPointer_array::insert(const TObject& object, int index, bool force) +{ + return TArray::insert(&(TObject&)object, index, force); +} + +/////////////////////////////////////////////////////////// +// TBit_array +/////////////////////////////////////////////////////////// + +TBit_array::TBit_array(long size) + : _bit(NULL), _size(0) +{ + if (size) + resize(index(size)); +} + +// @doc EXTERNAL + +// @mfunc Copia l'array passato come parametro +void TBit_array::copy( + const TBit_array& ba) // @parm Array da copiare + + // @comm Copia il contenuto dell'array passato come parametro. +{ + if (_bit) + { + delete _bit; + _bit = NULL; + _size = 0; + } + resize(ba._size-1); + memcpy(_bit, ba._bit, _size); +} + +TBit_array::TBit_array(const TBit_array& ba) : _bit(NULL), _size(0) +{ copy(ba); } + +TBit_array& TBit_array::operator=(const TBit_array& ba) +{ + copy(ba); + return *this; +} + + +TBit_array::~TBit_array() +{ + if (_bit) + delete _bit; +} + +// Certified 100% +void TBit_array::set() +{ + if (_bit) + memset(_bit, 0xFF, _size); +} + +// Certified 100% +void TBit_array::reset() +{ + if (_bit) + memset(_bit, 0x0, _size); +} + +// Certified 99% +// @doc EXTERNAL +// +// @mfunc Modifica la dimensione dell'array. +void TBit_array::resize( + word size) // @parm Indica la nuova dimensione che deve assumere l'array. + + // @comm Alloca la memoria necessaria per contentere i dati della nuova + // dimensione inizializzando a NULL tutti i nuovi elementi aggiunti + // all'array lasciando inalterati, sia in posizione che in + // contenuto gli elementi gia' presenti. +{ + word oldsize = _size; + byte* oldbit = _bit; + + _size = size+1; + _bit = new byte[_size]; + reset(); + + if (oldsize) + { + memcpy(_bit, oldbit, oldsize); + delete oldbit; + } +} + +bool TBit_array::operator[] (long n) const +{ + const word i = index(n); + if (i >= _size) return FALSE; + return (_bit[i] & mask(n)) != 0; +} + +// Certified 99% +TBit_array& TBit_array::operator|= (const TBit_array& ba) +{ + if (_size < ba._size) + resize(ba._size); + + for (word i = 0; i < _size; i++) + _bit[i] |= ba._bit[i]; + + return *this; +} + +// Certified 99% +void TBit_array::set(long n) +{ + CHECKD(n >= 0, "Can't set a negative bit ", n); + const word i = index(n); + if (i >= _size) + resize(i); + _bit[i] |= mask(n); +} + +// Certified 99% +void TBit_array::reset(long n) +{ + const word i = index(n); + if (i < _size) + _bit[i] &= ~mask(n); +} + +// Certified 99% +void TBit_array::not(long n) +{ + const word i = index(n); + if (i >= _size) resize(i); + _bit[i] ^= mask(n); +} + +// Certified 90% +// @doc EXTERNAL + +// @mfunc Ritorna il numero di 1 presenti nell'array +// +// @rdesc Numero di 1 trovati. +long TBit_array::ones() const + +// @comm Passa tutto l'array di bit e conta quanti degli elementi presenti sono +// settati ad 1. +// +// @xref +{ + long one = 0; + for (word i = 0; i < _size; i++) + { + const byte b = _bit[i]; + if (b) + { + for (byte m = 1; m; m <<= 1) + if (b & m) one++; + } + } + return one; +} + +// Certified 90% +// @doc EXTERNAL + +// @mfunc Ritorna la posizione dell'ultimo 1 nell'array +// +// @rdesc Ritorna i seguenti valori: +// @flag >0 | Posizione nella quale si trova l'ultimo 1 +// @flag -1 | Se non sono presenti bit settati ad 1 + +long TBit_array::last_one() const + +// @comm Cerca all'interno dell'array di bit la posizione dell'ultimo bit +// settato ad 1 +// +// @xref +{ + for (word i = _size; i--;) + { + const byte b = _bit[i]; + if (b) + { + for (byte j = 8; j--;) + if ((1<0 | Posizione nella quale si trova il primo 1 +// @flag -1 | Se non sono presenti bit settati ad 1 + +long TBit_array::first_one() const + +// @comm Cerca all'interno dell'array di bit la posizione del primo bit +// settato ad 1 +// +// @xref +{ + for (word i = 0; i < _size; i++) + { + const byte b = _bit[i]; + if (b) + { + for (byte j = 0; j < 8; j++) + if ((1< 0; +} + + +void TBit_array::set(const char* numbers) +{ + TToken_string s(numbers, ' '); + for (const char* n = s.get(0); n; n = s.get()) + if (isdigit(*n)) set(atol(n)); +} + +// @doc EXTERNAL +// +// @mfunc Stampa un array +void TBit_array::print_on( + ostream& out) const // @parm Indica l'output sul quale reindirizzare la stampa (funzione standard del C++) + + // @comm Stampa tutti gli indici degli elementi diversi da 0 +{ + const long last = _size<<3; + for (long i = 1; i < last; i++) + if (operator[](i)) out << ' ' << i; +} + + diff --git a/omnia/array.h b/omnia/array.h new file mode 100755 index 000000000..75edacfc8 --- /dev/null +++ b/omnia/array.h @@ -0,0 +1,324 @@ +#ifndef __ARRAY_H +#define __ARRAY_H + +#ifndef __OBJECT_H +#include "object.h" +#endif + +#ifndef NULL +#define NULL 0L +#endif + +// @doc EXTERNAL +// +// @type COMPARE_FUNCTION | Prototipo funzione di confronto tra elementi della +// classe da passare al metodo sort dei +typedef int (*COMPARE_FUNCTION)(const TObject**, const TObject**); + +// @doc EXTERNAL + +// @type CONDITION_FUNCTION | Prototipo funzione di ricerca/filtro +// per i derivati di da passare ai metodi dei +typedef bool (*CONDITION_FUNCTION) ( const TObject& ); + +// @doc EXTERNAL + +// @type OPERATION_FUNCTION | Prototipo funzione attuatore +// da passare ai metodi sort dei +typedef void (*OPERATION_FUNCTION) ( const TObject& ); + + +// @doc EXTERNAL + +// @class TContainer | Generico contenitore ad accesso casuale (con indice) +// @base public | TObject +class TContainer : public TObject +{ + +// @author:(INTERNAL) Matteo + +// @access:(INTERNAL) Private Member +private: + // @cmember:(INTERNAL) Ultima condizione di ricerca/filtro (vedi ) + CONDITION_FUNCTION _last_condition; + + // @access Public Member +public: + + // @cmember Ritorna un puntatore al primo oggetto del contenitore + virtual TObject* first_item( ) pure; + // @cmember Ritorna un puntatore all'ultimo oggetto del contenitore + virtual TObject* last_item( ) pure; + // @cmember Ritorna un puntatore all'oggetto successivo all'oggetto corrente + virtual TObject* succ_item( ) pure; + // @cmember Ritorna un puntatore all'oggetto che precede l'oggetto corrente + virtual TObject* pred_item( ) pure; + // @cmember Ritorna il numero di oggetti nel contenitore + virtual long objects( ) pure; + + // @cmember Cerca il successivo elemento che soddisfa la + virtual void for_each( OPERATION_FUNCTION ); + // @cmember Cerca il successivo elemento che soddisfa la + // per ogni elemento di + virtual void for_each_that( OPERATION_FUNCTION, CONDITION_FUNCTION = NULL ); + + // @cmember Ritorna il puntatore al primo oggetto che soddisfa la condizione + virtual TObject* first_that( CONDITION_FUNCTION = NULL ); + // @cmember Ritorna il puntatore all'ultimo oggetto che soddisfa la condizione + virtual TObject* last_that( CONDITION_FUNCTION = NULL ); + // @cmember Ritorna il prossimo oggetto che soddisfa la condizione. Va usata con first_that per scandire il container + virtual TObject* succ_that( ); + // @cmember Ritorna il precedente oggetto che soddisfa la condizione. Va usata con last_that per scandire il container all'indietro + virtual TObject* pred_that( ); + // @cmember Ritorna il numero di elementi che soddisfano la condizione + virtual long count( CONDITION_FUNCTION = NULL ); + // @cmember Ritorna l'oggetto successivo a quello corrente + TObject* operator++ () + { return succ_item( ); }; + // @cmember Ritorna l'oggetto che precede quello corrente + TObject* operator-- () + { return pred_item( ); }; + +}; + +// @doc EXTERNAL + +// @class TArray | Classe per la definizione degli array +// +// @base public | TContainer +class TArray : public TContainer + +// @author:(INTERNAL) Guido + +// @access:(INTERNAL) Private Member +{ + friend class TPointer_array; + + // @cmember:(INTERNAL) Array di puntatori ad oggetti + TObject** _data; + // @cmember:(INTERNAL) Dimensione dell'array + int _size; + // @cmember:(INTERNAL) Numero di elementi presenti nell'array + int _items; + // @cmember:(INTERNAL) Prossimo elemento libero nell'array + int _next; + + // @cmember:(INTERNAL) Indice per la scansione sequenziale + int _scanindex; + + // @access Protected Member +protected: + TObject** data() const { return _data; } + + // @cmember Modifica la dimensione dell'array. + void resize(int newdim); + + // @access Public Member +public: + // @cmember Costruttore. Crea un array (chiama ) + TArray(int arraysize); + // @cmember Costruttore. Crea un array (non chiama ) + TArray(); + // @cmember Costruttore. Copia tutto l'array e ne duplica gli elementi + TArray(const TArray&); + + // @cmember Distruttore + virtual ~TArray() ; + // @cmember Ritorna il nome della classe + virtual const char* class_name() const ; + // @cmember Ritorna l'id della class + virtual word class_id() const ; + // @cmember Stampa un array + virtual void print_on(ostream& out) const ; + // @cmember Controlla se si tratta di un oggetto valido + virtual bool ok() const ; + + // @cmember Ritorna la grandezza dell'array + int size() const + { return _size; } + // @cmember Ritorna numero di oggetti nell'array + virtual long objects( ) + { return _items; } + + // @cmember Ritorna numero di oggetti nell'array + virtual int items( ) const + { return _items; } + + + // @cmember Ritorna il primo elemento dell'array + virtual TObject* first_item( ); + // @cmember Ritorna l'ultimo elemento dell'array + virtual TObject* last_item( ); + // @cmember Ritorna il successivo elemento dell'array rispetto all'elemento corrente + virtual TObject* succ_item( ); + // @cmember Ritorna il precedente elemento dell'array rispetto all'elemento corrente + virtual TObject* pred_item( ); + + // @cmember Ritorna l'indice del primo oggetto + int first() const; + // @cmember Ritorna l'indice dell'ultimo oggetto + int last() const; + // @cmember Ritorna l'indice del primo oggetto dopo l'i-esimo + int succ(int i) const; + // @cmember Ritorna l'indice del primo oggetto che precede l'i-esimo + int pred(int i) const; + + // @cmember Ritorna l'oggetto nella posizione index + TObject& operator[] (int index) const ; + // @cmember Ritorna l'oggetto nella posizione index + TObject* objptr(int index) const ; + // @cmember Assegna all'array l'oggetto passato + TArray& operator= (const TArray& a); + + // @cmember Rimuove uno o tutti (default) gli elementi + virtual bool destroy(int index = -1, bool pack = FALSE); + // @cmember Aggiunge un oggetto ad un array. + virtual int add(TObject* obj, int index = -1) ; + // @cmember Inserisce un elemento dell'array nella posizione index + virtual int insert(TObject* obj, int index = 0, bool force = FALSE); + + // @cmember Aggiunge un oggetto all'array. L'oggetto viene duplicato + virtual int add(const TObject& object, int index = -1) ; + // @cmember Inserisce un oggetto alla posizione index + virtual int insert(const TObject& object, int index = 0, bool force = FALSE); + // @cmember Elimina l'elemento nella posizione index dell'array + TObject* remove(int index, bool pack = FALSE); + // @cmember Elimina l'elemento nella posizione index dell'array + TObject* remove_item(bool pack = FALSE) ; + // @cmember Scambia di posto due elementi dell'array + void swap(int i1, int i2); + // @cmember Rende contigui tutti gli elementi non nulli + virtual void pack(); + // @cmember Ordina i TObject secondo il criterio definito in + void sort(COMPARE_FUNCTION = NULL); +}; + +inline TObject* TArray::objptr(int index) const +{ + return (index < _size && index >= 0) ? _data[index] : NULL; +} + +#ifndef DBG +inline TObject& TArray::operator[] (int index) const +{ + return *objptr(index); +} +#endif + +#define FOR_EACH_ARRAY_ITEM(__arr, __r, __obj) \ + TObject* __obj; \ + for (int __r = __arr.first(); \ + __obj = __arr.objptr(__r); \ + __r = __arr.succ(__r)) + +#define FOR_EACH_ARRAY_ITEM_BACK(__arr, __r, __obj) \ + TObject* __obj; \ + for (int __r = __arr.last(); \ + __obj = __arr.objptr(__r); \ + __r = __arr.pred(__r)) + + +class TPointer_array : public TArray +{ +protected: + void copy(const TArray& a); + +public: + virtual bool destroy(int index = -1, bool pack = FALSE); + virtual int add(TObject* object, int index = -1); + virtual int add(const TObject& object, int index = -1); + virtual int insert(const TObject& object, int index = 0, bool force = FALSE); + virtual TPointer_array& operator= (const TArray& a) { copy(a); return *this; } + virtual TPointer_array& operator= (const TPointer_array& a) { copy(a); return *this; } + + long get_long(int index) const { return (long)objptr(index); } + int get_int(int index) const { return (int)get_long(index); } + int add_long(long value, int index = -1) { return add((TObject*)value, index); } + int insert_long(long value, int index = -1) { return TArray::insert((TObject*)value, index, TRUE); } + + TPointer_array() { } + TPointer_array(int size) : TArray(size) { } + TPointer_array(const TArray& a) { copy(a); } + TPointer_array(const TPointer_array& a) { copy(a); } + virtual ~TPointer_array() { destroy(); } +}; + +// @doc EXTERNAL + +// @class TBit_array | Come la classe ma i suoi elementi sono bit; +// questo permette di costruire array piu' piccoli rispetto +// alla classe TArray. +// +// @base public | TObject +class TBit_array : public TObject + +// @author:(INTERNAL) Guido + +// @access:(INTERNAL) Private Member +{ + // @cmember:(INTERNAL) dimensione dell'array + word _size; + // @cmember:(INTERNAL) bit in cui sono contenuti i dati + byte* _bit; + + // @access Protected Member +protected: + // @cmember Controlla se si tratta di un oggetto valido + virtual bool ok() const; + // @cmember Stampa un array + virtual void print_on(ostream& out) const; + + // @cmember Modifica la dimensione dell'array. + void resize(word size); + // @cmember Copia nell'array l'elemento passato come parametro + void copy(const TBit_array& ba); + // @cmember Ritorna il numero del byte contenente il bit

+ word index(long n) const + { return word(n >> 3); } + // @cmember Ritorna la posizione del bit

all'interno del byte + byte mask(long n) const + { return byte(1 << (n & 0x7)); } + + // @access Public Member +public: + // @cmember Costruttore. Crea un array di (chiama ) + TBit_array(long size = 0); + // @cmember Costruttore. Crea un array di (chiama ) + TBit_array(const TBit_array& ba); + // @cmember Distruttore + virtual ~TBit_array(); + + // @cmember Assegna all'array l'oggetto passato + TBit_array& operator=(const TBit_array& ba); + // @cmember Ritorna l'oggetto puntato da n + bool operator[] (long n) const; + // @cmember Ritorna l'or logico tra due Bit_array modificando l'oggetto corrente + TBit_array& operator |=(const TBit_array& b); + + // @cmember Ritorna il numero di bit nell'array + long items() const { return 8L * _size; } + // @cmember Ritorna la posizione del primo 1 nell'array (-1 se non lo trova) + long first_one() const; + // @cmember Ritorna la posizione dell'ultimo 1 nell'array (-1 se non lo trova) + long last_one() const; + // @cmember Ritorna il numero di 1 presenti nell'array + long ones() const; + + // @cmember Setta ad 1 il bit n-esimo dell'array + void set(long n); + // @cmember Setta a 0 il bit n-esimo dell'array + void reset(long n); + // @cmember Not logico del bit n-esimo dell'array + void not(long n); + + // @cmember Setta il bit n-esimo a seconda del valore passato come secondo elemento + void set(long n, bool on) { on ? set(n) : reset(n); } + // @cmember Setta ad 1 tutti i bit dell'array + void set(); + // @cmember Setta a 0 tutti i bit dell'array + void reset(); + // @cmember Data una stringa setta ad 1 gli elementi indicati della stringa + void set(const char* numbers); +}; + +#endif diff --git a/omnia/assoc.cpp b/omnia/assoc.cpp new file mode 100755 index 000000000..ceb8833d2 --- /dev/null +++ b/omnia/assoc.cpp @@ -0,0 +1,450 @@ +#include +#include "assoc.h" + +// @ccost:(INTERNAL) HASH_SIZE | 883 | Dimensione della tabella hash +const int HASH_SIZE = 883; + +THash_object::~THash_object() +{ + if (_obj != NULL) + delete _obj; +} + +TArray& TAssoc_array::bucket(int index) +{ + TArray* arr = (TArray*)_bucket.objptr(index); + if (arr == NULL) + { + arr = new TArray; + _bucket.add(arr, index); + } + return *arr; +} + +// @doc EXTERNAL + +// @mfunc Cerca l'oggetto con chiave

+// +// @rdesc Ritorna l'oggetto corrispondente alla chiave passate come parametro. +// Il parametro

assume il valore TRUE se si tratta di un +// nuovo oggetto. +THash_object* TAssoc_array::_lookup( + const char* k, // @parm Chiave da cercare + bool& isnew, // @parm Viene assegnato TRUE se si tratta di una nuova chiave + bool insert) // @parm Permette di inserire la chiave + + // @comm Ricerca all'interno della tabella hash l'oggetto con la chiave

, + // nel caso non venga trovato

ritorna TRUE (si tratta di un + // oggetto nuovo) e viene inserito nella tabella se il parametro

+ // e' settato a TRUE. +{ + const TFixed_string key(k); + const word hv = key.hash() % HASH_SIZE; + TArray& arr = bucket(hv); + THash_object* o = NULL; + isnew = FALSE; + + for (int i = 0; i < arr.items(); i++) + { + THash_object* ob = (THash_object*)arr.objptr(i); + if (ob->_key == key) + { o = ob; break; } + if (ob->_key > key) + break; + } + + if (o == NULL) + { + if (insert) + { + o = new THash_object(key); + arr.insert(o,i); + _cnt++; + } + isnew = TRUE; + } + + return o; +} + +void TAssoc_array::destroy() +{ + _bucket.destroy(); + _cnt = _row = _col = 0; + _rowitem = _colitem = 0; +} + +TObject* TAssoc_array::first_item() +{ + _rowitem = _colitem = 0; + return succ_item(); +} + +TObject* TAssoc_array::last_item() +{ + _rowitem = _bucket.last(); + if( _rowitem < 0 ) + return NULL; + _colitem = bucket(_rowitem).items() - 1; + return pred_item( ); +} + +TObject* TAssoc_array::succ_item() +{ + const TArray* arr = (const TArray*)_bucket.objptr(_rowitem); + while (_rowitem < HASH_SIZE) + { + if (arr && (int)_colitem < arr->items()) + break; + _rowitem = _bucket.succ(_rowitem); + if (_rowitem < HASH_SIZE) + { + arr = (TArray*)_bucket.objptr(_rowitem); + _colitem = 0; + } + } + if (_rowitem >= HASH_SIZE) + return NULL; + THash_object* o = (THash_object*)arr->objptr(_colitem++); + return (o == NULL || o->_obj == NULL) ? NULL : o->_obj; +} + +TObject* TAssoc_array::pred_item() +{ + const TArray* arr = (const TArray*)_bucket.objptr(_rowitem); + while (_rowitem >= 0) + { + if (arr && (int)_colitem >= 0) + break; + _rowitem = _bucket.pred(_rowitem); + if (_rowitem >= 0) + { + arr = (TArray*)_bucket.objptr(_rowitem); + _colitem = arr->items()-1; + } + } + if (_rowitem < 0 ) + return NULL; + + THash_object* o = (THash_object*)arr->objptr(_colitem--); + return (o == NULL || o->_obj == NULL) ? NULL : o->_obj; +} + +THash_object* TAssoc_array::random_hash_object() +{ + THash_object* o = NULL; + if (items() > 0) + { + int bucket = rand() % _bucket.size(); + if (_bucket.objptr(bucket) == NULL) + bucket = _bucket.succ(bucket); + if (_bucket.objptr(bucket) == NULL) + bucket = _bucket.pred(bucket); + const TArray* arr = (const TArray*)_bucket.objptr(bucket); + if (arr != NULL) + { + const int item = rand() % arr->size(); + o = (THash_object*)arr->objptr(item); + if (o != NULL) + { + _rowitem = bucket; + _colitem = item; + } + } + } + return o; +} + +// @doc EXTERNAL + +// @mfunc Aggiunge un oggetto all'array. +// @rdesc Ritorna TRUE se esisteva gia' un elemento con la stessa chiave +bool TAssoc_array::add( + const char* key, // @parm Chiave d'ordinamento + TObject* obj, // @parm Oggetto da inserire (default=NULL) + bool force) // @parm Permette di forzare l'inserimento se esiste gia' + // un oggetto con la stessa chiave + + // @parm const TObject | &obj | Indirizzo dell'oggetto da aggiungere + // + // @syntax add(const char* key, TObject* obj, bool force) + // @syntax add(const char* key, const TObject& obj, bool force) + // + // @comm Se l'oggetto da aggiungere esite gia' la chiave guarda il parametro

: + // se

= TRUE lo sostituisce e ritorna TRUE, + // se

= FALSE non sostituisce e ritorna TRUE, + // altrimenti ritorna FALSE. + // Nel caso l'oggetto da aggiungere venga passato per indirizzo + // la funzione aggiunge una copia dell'oggetto e quindi deve essere + // definita +{ + bool isnew = FALSE; + THash_object* o = _lookup(key,isnew,TRUE); + if (!isnew) + { + if (force) + { + if (o->_obj != NULL) + delete o->_obj; + o->_obj = obj; + } + return TRUE; + } + o->_obj = obj; + return FALSE; +} + +bool TAssoc_array::add(const char* key, const TObject& obj, bool force) +{ + // Non inserire l'Hash_object se non lo trovi (ci pensa la add sotto) + bool isnew = FALSE; + THash_object* o = _lookup(key,isnew,FALSE); + if (!isnew && !force) + return TRUE; + return add(key,obj.dup(),force); +} + +// @doc EXTERNAL + +// @mfunc Elimina un oggetto. +// @rdesc Ritorna il risultato dell'operazione +// +// @flag TRUE | Eliminazione avvenuta +// @flag FALSE | L'oggetto non e' stato trovato +bool TAssoc_array::remove( + const char* k) // @parm Chiave dell'oggetto da eliminare + +// @comm Cerca nella tabella hash l'oggetto con chiave

e lo elimina. + +{ + const TFixed_string key(k); + const word hv = key.hash() % HASH_SIZE; + TArray& arr = bucket(hv); + THash_object* o = NULL; + for (int i = 0; i < arr.items(); i++) + { + THash_object* ob = (THash_object*)&arr[i]; + if (ob->_key == key) + { o = ob; break; } + if (ob->_key > key) + break; + } + if (o != NULL) + { + arr.destroy(i,TRUE); + _cnt--; + return TRUE; + } + return FALSE; +} + +// @doc EXTERNAL + +// @mfunc Trova l'oggetto indicizzato +// +// @rdesc Ritorna l'oggetto cercato. Se l'oggetto non viene trovato +// ritorna un errore +TObject& TAssoc_array::find( + const char* key) const // @parm Chiave dell'oggetto da trovare + + + // @comm Cerca l'oggetto indicizzato con chiave

. Viene controllato se + // non c'e' (normalmente si usa operator[key]) +{ + TObject* o = objptr(key); + CHECKS(o, "Can't find hash object with key ", key); + return *o; +} + +// @doc EXTERNAL + +// @mfunc Ritorna l'oggetto con chiave

+// @rdesc Se l'oggetto esiste ne ritorna il puntatore, altrimenti ritorna NULL +TObject* TAssoc_array::objptr( + const char* key) const // @parm Chiave dell'oggetto da ritornare +{ + bool isnew = FALSE; + THash_object* o = ((TAssoc_array*)this)->_lookup(key,isnew); + return o ? o->_obj : NULL; +} + +// @doc EXTERNAL + +// @mfunc Controlla l'esistenza di una chiave +// +// @rdesc Ritorna il risultato della ricerca +// +// @flag TRUE | Se la chiave esiste +// @flag FALSE | Se la chiave non esiste +bool TAssoc_array::is_key( + const char* key) const // @parm Chiave di cui cercare l'esistenza +{ + bool isnew = FALSE; + THash_object* o = ((TAssoc_array *)this)->_lookup(key,isnew); + return o != NULL; +} + +// @doc EXTERNAL + +// @mfunc Ritorna solo l'oggetto +// +// @rdesc Ritorna il puntatore all'oggetto (se diverso da NULL), altrimenti +// ritorna error object +TObject* TAssoc_array::get() +// @xref +{ + const TArray* arr = (const TArray*)_bucket.objptr(_row); + while(_row < HASH_SIZE) + { + if (arr && (int)_col < arr->items()) + break; + _row = _bucket.succ(_row); + arr = (const TArray*)_bucket.objptr(_row); + _col = 0; + } + if (_row >= HASH_SIZE) + { + _row = 0; + return NULL; + } + THash_object* o = (THash_object*)arr->objptr(_col++); + return (o == NULL || o->_obj == NULL) ? &error_object : o->_obj; +} + +// @doc EXTERNAL + +// @mfunc Ritorna l'oggetto e la relativa chiave +// +// @rdesc Se l'oggetto esiste ne ritorna il puntatore, altrimenti ritorna NULL +THash_object* TAssoc_array::get_hashobj() + + // @comm Se l'oggetto viene trovato viene richiamata la funzione + // + // + // @xref +{ + const TArray* arr = (const TArray*)_bucket.objptr(_row); + while(_row < HASH_SIZE) + { + if (arr && (int)_col < arr->items()) + break; + _row = _bucket.succ(_row); + arr = (const TArray*)_bucket.objptr(_row); + _col = 0; + } + if (_row >= HASH_SIZE) + { + _row = 0; + return NULL; + } + return (THash_object*)arr->objptr(_col++); +} + + +// mette chiavi e opzionalmente valori (come stringa) nel +// TString_array passato +int TAssoc_array::get_keys(TString_array& kl, bool add_values) +{ + kl.destroy(); + restart(); + THash_object* o = NULL; + TString tmp(80); + while (o = get_hashobj()) + { + TToken_string* tt = new TToken_string(o->key()); + if (add_values) + { + tmp = ""; + tmp << o->obj(); + tt->add(tmp); + } + kl.add(tt); + } + restart(); + return kl.items(); +} + +// @doc INTERNAL + +// @mfunc Copia tutto l'array e ne duplica gli elementi +// +TAssoc_array & TAssoc_array::copy(const TAssoc_array & a) // @parm Array associativo sorgente +{ + destroy(); + TAssoc_array& from = (TAssoc_array&)a; + from.restart(); + for (THash_object* obj = from.get_hashobj(); obj; obj = from.get_hashobj()) + add(obj->key(), obj->obj(), TRUE); + return * this; +} + + +/////////////////////////////////////////////////////////// +// TCache +// Un simpatico contenitore che può dimenticare i contenuti +// a patto che riusciate a fornire un metodo per ricrearli! +/////////////////////////////////////////////////////////// + +TObject* TCache::key2obj(const char* key) +{ + NFCHECK("Pure key2obj function not implemented"); + return new TString(key); // Place holder +} + +void TCache::discarding(const THash_object* obj) +{ + // Nothing to do normally +} + +TObject* TCache::objptr(const TString& key) +{ + const int hv = key.hash() % _data.size(); + THash_object* ho = (THash_object*)_data.objptr(hv); + TObject* obj = NULL; + if (ho != NULL && ho->key() == key) + { + obj = &ho->obj(); + } + else + { + obj = key2obj(key); + if (obj != NULL) + { + if (ho != NULL) + { + discarding(ho); + _data.destroy(hv); + } + ho = new THash_object(key, obj); + _data.add(ho, hv); + } + } + return obj; +} + +TObject* TCache::objptr(size_t s) +{ + TString16 key; key.format("%10lu", s); + return objptr(key); +} + +void TCache::destroy() +{ + for (int i = _data.last(); i >= 0; i--) + { + THash_object* ho = (THash_object*)_data.objptr(i); + if (ho != NULL) + { + discarding(ho); + _data.destroy(i); + } + } +} + +TCache::TCache(size_t size) : _data(size > 0 ? size : HASH_SIZE) +{ } + +TCache::~TCache() +{ + destroy(); +} diff --git a/omnia/assoc.h b/omnia/assoc.h new file mode 100755 index 000000000..b56c3df21 --- /dev/null +++ b/omnia/assoc.h @@ -0,0 +1,182 @@ +#ifndef __ASSOC_H +#define __ASSOC_H + +#ifndef __STRINGS_H +#include "strings.h" +#endif + +// @doc INTERNAL + +// @class THash_object | Classe per la definizione degli elementi di una tabella hash. +// +// @base public | TObject +class THash_object : public TObject + +// @author:(INTERNAL) Guido + +{ + // @cfriend TAssoc_array + friend class TAssoc_array; + + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Chiave d'ordinamento + TString _key; + // @cmember:(INTERNAL) Oggetto della tabella da ordinare + TObject* _obj; + + // @access Public Member +public: + + // @cmember Ritorna la chiave di ordinamento + const TString& key() const + { return _key; } + // @cmember Ritorna l'oggetto + TObject& obj() const + { return *_obj; } + + // @cmember Costruttore (inizializza la chiave ed opzionalmente l'oggetto) + THash_object(const char* k, TObject* o = NULL) : _key(k), _obj(o) + {} + // @cmember Distruttore + virtual ~THash_object(); +}; + +// @doc EXTERNAL + +// @class TAssoc_array | Tabella hash di oggetti generici +// +// @base public |TObject +class TAssoc_array : public TContainer + +// @author:(INTERNAL) Guido + +//@access:(INTERNAL) Private Member +{ + // @cmember:(INTERNAL) Numero di oggetti contenuti nella tabella + word _cnt; + // @cmember:(INTERNAL) Numero di righe della tabella hash + word _row; + // @cmember:(INTERNAL) Numero di colonne della tabella hash + word _col; + // @cmember:(INTERNAL) Numero di righe della tabella hash per i metodi _item + int _rowitem; + // @cmember:(INTERNAL) Numero di colonne della tabella hash per i metodi _item + int _colitem; + // @cmember:(INTERNAL) Array contenente i dati veri e propri + TArray _bucket; + + // @access Protected member +protected: + TArray& bucket(int index); + + // @cmember Cerca l'oggetto con chiave k + THash_object* _lookup(const char* k, bool& isnew, bool insert = FALSE); + // @cmember Copia tutto l'array associativo e ne duplica gli elementi + TAssoc_array & copy(const TAssoc_array & a); + + // @access Public Member +public: + // @cmember Duplica l'array associativo copiandone gli elementi. + virtual TObject* dup () const { return new TAssoc_array(*this);} + + // @cmember Ritorna un puntatore al primo oggetto + virtual TObject* first_item( ); + // @cmember Ritorna un puntatore all'ultimo oggetto + virtual TObject* last_item( ); + // @cmember Ritorna un puntatore all'oggetto successivo al quello corrente + virtual TObject* succ_item( ); + // @cmember Ritorna un puntatore all'oggetto che precede quello corrente + virtual TObject* pred_item( ); + // @cmember Ritorna un puntatore ad un THash_object casuale (anche NULL) + THash_object* random_hash_object(); + + // @cmember Ritorna il numero di elementi presenti come long + virtual long objects() { return _cnt; } + + // @cmember Ritorna il numero di elementi presenti + int items() const { return _cnt; } + // @cmember Cancella tutti gli elementi + virtual void destroy(); + + // @cmember Aggiunge un oggetto. Se era gia' presente guarda il parametro force + bool add(const char* key, TObject* obj = NULL, bool force = FALSE); + + // @cmember Aggiunge una copia dell'oggetto + bool add(const char* key, const TObject& obj, bool force = FALSE); + + // @cmember Elimina un oggetto + bool remove(const char* key); + + // @cmember Controlla l'esistenza di una chiave + bool is_key(const char* key) const ; + + // @cmember Ritorna l'oggetto con chiave key + TObject* objptr(const char* key) const ; + + // @cmember Trova l'oggetto indicizzato + TObject& find(const char* key) const ; + + // @cmember Ritorna l'indice del oggetto con chiave key (piu' intuitivo di ) + TObject& operator[] (const char* key) const + { return find(key); } + + // iterazione come TToken_string + // si puo' adoperare get() e get_hashobj() intercambiabilmente ma + // non sono indipendenti (entrambe avanzano gli stessi contatori) + + // @cmember Azzera il numero di riga e colonna corrente della tabella hash + void restart() + { _row = 0; _col = 0; } + // @cmember Ritorna solo l'oggetto + TObject* get(); + // @cmember Ritorna l'oggetto e la relativa chiave + THash_object* get_hashobj(); + + // @cmember Mette chiavi e opzionalmente valori (come stringa) nel passato + int get_keys(TString_array& kl, bool add_values = FALSE); + // @cmember Operatore di assegnamento tra array associativi + TAssoc_array& operator= (const TAssoc_array & a) + { return copy(a); } + + // @cmember Costruttore + TAssoc_array() : _cnt(0), _row(0), _col(0) + {} + // @cmember Costruttore. Copia tutto l'array associativo e ne duplica gli elementi + TAssoc_array(const TAssoc_array& a) : _cnt(0), _row(0), _col(0) + { copy(a); } + // @cmember Distruttore + virtual ~TAssoc_array() + { destroy(); } +}; + +class TCache : public TObject +{ + TArray _data; + +protected: + virtual void discarding(const THash_object* obj); + virtual TObject* key2obj(const char* key) pure; + +public: + TObject* objptr(const TString& key); + TObject* objptr(size_t nkey); + + void destroy(); // Not very useful, but who knows? + TCache(size_t size = 0); // 883 assigned by default + virtual ~TCache(); +}; + +#define FOR_EACH_ASSOC_STRING(__ass, __obj, __key, __str) \ + const char *__key, *__str; __ass.restart(); \ + for (THash_object* __obj = __ass.get_hashobj(); \ + __obj && ((__str = (const TString&)__obj->obj()) != NULL, __obj && (__key = __obj->key()) != NULL); \ + __obj = __ass.get_hashobj()) + +#define FOR_EACH_ASSOC_OBJECT(__ass, __obj, __key, __itm) \ + const char *__key; TObject* __itm; __ass.restart(); \ + for (THash_object* __obj = __ass.get_hashobj(); \ + __obj && (__itm = &__obj->obj()) != NULL, __obj && (__key = __obj->key()) != NULL; \ + __obj = __ass.get_hashobj()) + +#endif diff --git a/omnia/checks.cpp b/omnia/checks.cpp new file mode 100755 index 000000000..48878ff34 --- /dev/null +++ b/omnia/checks.cpp @@ -0,0 +1,181 @@ +#include + +#include +#include + +#include "checks.h" + +const char* const AppTitle = "Omnia"; + +#define buildmsg() char msg[256];va_list argptr;va_start(argptr,fmt);vsprintf(msg,fmt,argptr);va_end(argptr) + +// @doc EXTERNAL + +// @msg fatal_box | Crea una finestra di ERRORE FATALE con il relativo messaggio +bool fatal_box( + const char* fmt, ...) // @parm Messaggio da stampare nella finestra + // (il formato e' come nella printf del C) + // @comm Il programma viene interrotto al momento in cui si e' verificato l'errore. +{ + buildmsg(); + MessageBox(NULL, msg, AppTitle, MB_OK | MB_ICONSTOP); + exit(0); + return false; +} + +// @doc EXTERNAL + +// @msg error_box | Crea una finestra di ERRORE con il relativo messaggio +bool error_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con il bottone OK + // e l'icona punto esclamativo. +{ + buildmsg(); + MessageBox(NULL, msg, AppTitle, MB_OK | MB_ICONERROR); + return false; +} + +// @doc EXTERNAL +// @msg warning_box | Crea una finestra di ATTENZIONE con il relativo messaggio +bool warning_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con il bottone OK + // e l'icona punto di domanda. +{ + buildmsg(); + MessageBox(NULL, msg, AppTitle, MB_OK | MB_ICONEXCLAMATION); + return 0; +} + +// @doc EXTERNAL +// @msg message_box | Crea una finestra di INFORMAZIONE con relativo il messaggio +bool message_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con il bottone OK + // e l'icona informazioni. +{ + buildmsg(); + MessageBox(NULL, msg, AppTitle, MB_OK | MB_ICONINFORMATION); + return false; +} + +// @doc EXTERNAL +// @msg sorry_box | Crea una finestra di SCUSE con il relativo messaggio +bool sorry_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con il bottone OK + // e l'icona informazioni. +{ + buildmsg(); + MessageBox(NULL, msg, AppTitle, MB_OK | MB_ICONINFORMATION); + return false; +} + +// @msg yesno_box | Crea una finestra di RICHIESTA con il relativo messaggio +bool noyes_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+{ + buildmsg(); + int ret = MessageBox(NULL, msg, AppTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); + return ret == IDYES; +} + +// @doc EXTERNAL +// @msg yesno_box | Crea una finestra di RICHIESTA con il relativo messaggio +bool yesno_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con i bottni SI e NO + // e l'icona col punto di domanda. + // + // @rdesc Ritorna il risultato della richiesta: + // + // @flag 1 | Se viene premuto il taso SI + // @flag 0 | Se viene premuto il taso NO +{ + buildmsg(); + int ret = MessageBox(NULL, msg, AppTitle, MB_ICONQUESTION | MB_YESNO); + return ret == IDYES; +} + +// @doc EXTERNAL +// @msg yesnofatal_box | Crea una finestra di RICHIESTA con il relativo +// messaggio, ma permette di terminare il programma +bool yesnofatal_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Se si opera in ambiente Windows crea la finestra con i bottoni SI e NO + // e l'icona col punto di domanda. + // A differenza della permette di terminare il programma + // se viene premuto il tasto SI + // + // @rdesc Ritorna il risultato della richiesta: + // + // @flag 1 | Se viene premuto il tasto SI + // @flag 0 | Se viene premuto il tasto NO + // + // @xref +{ + buildmsg(); + +#ifdef DBG + char s[256]; sprintf(s, "%s\nContinuare ugualmente?", msg); + const bool ret = yesno_box("%s", s); + if (!ret) +#endif + fatal_box(msg); + + return FALSE; +} + +// @doc EXTERNAL +// @msg yesnocancel_box | Crea una finestra di RICHIESTA con il relativo messaggio +int yesnocancel_box( + const char* fmt, // @parm Messaggio da stampare nella finestra + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Se si opera in ambiente Windows crea la finestra con i bottoni SI e NO + // e l'icona col punto di domanda. + // + // @rdesc Ritorna il risultato della richiesta: + // + // @flag K_YES | Se viene premuto il tasto SI + // @flag K_NO | Se viene premuto il tasto NO + // @flag K_ESC | Se viene premuto il tosto ESC + // + // @xref +{ + buildmsg(); + int ret = MessageBox(NULL, msg, AppTitle, MB_ICONQUESTION | MB_YESNOCANCEL); + return ret; +} + +// @doc EXTERNAL +// @msg __trace | Permette di mandare dei messaggi nel file trace.log +bool __trace( + const char* fmt, // @parm Messaggio da stampare + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ // @comm Usato in fase di debug, permette di vedere se il programma ha + // fatto certe operazioni (deve essere definito il simbolo TRC in + // fase di compilazione). + // + // @rdesc Ritorna non 0 se riesca ad aprire il file trace.log +{ + static FILE* f = NULL; + if (f == NULL) + f = fopen("trace.log", "w"); + if (f != NULL) + { + buildmsg(); + fprintf(f, "%s\n", msg); + fflush(f); + } + return f != NULL; +} + diff --git a/omnia/checks.h b/omnia/checks.h new file mode 100755 index 000000000..1735a9caa --- /dev/null +++ b/omnia/checks.h @@ -0,0 +1,95 @@ +#ifndef __CHECKS_H +#define __CHECKS_H + +#ifndef __STDTYPES_H +#include "stdtypes.h" +#endif + +bool message_box(const char* fmt, ...); +bool warning_box(const char* fmt, ...); +bool sorry_box(const char* fmt, ...); +bool error_box(const char* fmt, ...); +bool fatal_box(const char* fmt, ...); +bool noyes_box(const char* fmt, ...); +bool yesno_box(const char* fmt, ...); +int yesnocancel_box(const char* fmt, ...); +bool yesnofatal_box(const char* fmt, ...); +bool __trace(const char* fmt, ...); + +// Utilizzate in fase di debug (definire il simbolo DBG in compilazione) + +// @doc EXTERNAL + +#ifdef DBG +// @msg CHECK | Macro che richiama una per stampare messaggi a video +#define CHECK(p, m) ( (p) ? (void)0 : (void) fatal_box( \ + "Check failed in %s, line %d:\n\r%s", \ + __FILE__, __LINE__, m) ) + // @parm | p | Condizione per la stampa del messaggio (stampa se FALSE) + // @parm | m | Messaggio da stampare + // + // @comm Viene richiamata se

e' FALSE. + // Utilizzata in fase di debug (definire il simbolo DBG in compilazione). + // + // @xref + +// @doc EXTERNAL + +// @msg CHECKS | Macro che richiama una per stampare messaggi a video +#define CHECKS(p, m, s0) ( (p) ? (void)0 : (void) fatal_box( \ + "Check failed in %s, line %d:\n\r%s%s", \ + __FILE__, __LINE__, m, s0) ) + // @parm | p | Condizione per la stampa del messaggio (stampa se FALSE) + // @parm | m | Messaggio da stampare + // @parm | s0 | Stringa aggiuntiva da stampare + // + // @comm Viene richiamata se

e' FALSE. Oltre al messaggio passato in

+ // stampa anche una strina aggiuntiva passata in

. + // Utilizzata in fase di debug (definire il simbolo DBG in compilazione). + // + // @xref + +// @doc EXTERNAL + +// @msg CHECKD | Macro che richiama una per stampare messaggi a video +#define CHECKD(p, m, d0) ( (p) ? (void)0 : (void) fatal_box( \ + "Check failed in %s, line %d:\n%s%d", \ + __FILE__, __LINE__, m, d0) ) + // @parm | p | Condizione per la stampa del messaggio (stampa se FALSE) + // @parm | m | Messaggio da stampare + // @parm | d0 | Stringa aggiuntiva da stampare + // + // @comm Viene richiamata se

e' FALSE. Oltre al messaggio passato in

+ // stampa anche un numero passato in

. + // Utilizzata in fase di debug (definire il simbolo DBG in compilazione). + // + // @xref + +// @doc EXTERNAL + +// @msg CHECKD | Macro che richiama una per stampare messaggi d'errore a video +#define NFCHECK yesnofatal_box + + // @xref + +#else + +#define CHECK(p, m) +#define CHECKS(p, m, s) +#define CHECKD(p, m, d) +#define NFCHECK 1 ? 0 : yesnofatal_box + +#endif + +// Utilizzata in fase di debug (definire il simbolo TRC in compilazione) + +#ifdef TRC +// @doc EXTERNAL + +// @msg TRACE | Macro che richiama la funzione +#define TRACE __trace +#else +#define TRACE 1 ? 0 : __trace +#endif + +#endif // __CHECKS_H diff --git a/omnia/classes.h b/omnia/classes.h new file mode 100755 index 000000000..488530453 --- /dev/null +++ b/omnia/classes.h @@ -0,0 +1,71 @@ +#ifndef __CLASSES_H +#define __CLASSES_H + +// @N +// Codici identificativi delle classi +// @END + +// @M +#define CLASS_ERROR 0 +#define CLASS_OBJECT 1 +#define CLASS_SORTABLE 2 + +#define CLASS_STRING 10 +#define CLASS_FIXED_STRING 11 +#define CLASS_FILENAME 12 +#define CLASS_TOKEN_STRING 13 + +#define CLASS_APPLICATION 20 +#define CLASS_RELATION_APPLICATION 21 +#define CLASS_PRINT_APPLICATION 22 + +#define CLASS_PRINTER 50 +#define CLASS_PRINTROW 51 + +#define CLASS_CONTAINER 100 +#define CLASS_ARRAY 101 +#define CLASS_STACK 102 + +#define CLASS_WINDOW 200 +#define CLASS_SHEET 201 +#define CLASS_MASK 210 +#define CLASS_FIELD 220 +#define CLASS_TEXT_FIELD 221 +#define CLASS_LINE_FIELD 222 +#define CLASS_RECTANGLE_FIELD 223 +#define CLASS_GROUPBOX_FIELD 224 +#define CLASS_OPERABLE_FIELD 230 +#define CLASS_BUTTON_FIELD 231 +#define CLASS_SHEET_FIELD 232 +#define CLASS_BROWSEFILE_FIELD 233 +#define CLASS_MEMO_FIELD 234 +#define CLASS_ZOOM_FIELD 235 +#define CLASS_EDITABLE_FIELD 240 +#define CLASS_BOOLEAN_FIELD 241 +#define CLASS_LIST_FIELD 242 +#define CLASS_RADIO_FIELD 243 +#define CLASS_EDIT_FIELD 244 +#define CLASS_REAL_FIELD 245 +#define CLASS_DATE_FIELD 246 +#define CLASS_GRID_FIELD 247 +#define CLASS_TREE_FIELD 248 +#define CLASS_CURRENCY_FIELD 249 +#define CLASS_GOLEM_CLIENT_FIELD 250 + +#define CLASS_BASEISAMFILE 300 +#define CLASS_ISAMFILE 301 +#define CLASS_SYSTEMISAMFILE 302 +#define CLASS_LOCALISAMFILE 303 +#define CLASS_ISAMTEMPFILE 304 +#define CLASS_EXTERNISAMFILE 304 +#define CLASS_SORTEDFILE 310 + +#define CLASS_RECTYPE 350 +#define CLASS_VARIABLE_RECTYPE 351 +#define CLASS_AUTO_VARIABLE_RECTYPE 352 +#define CLASS_EXT_RECTYPE 353 + +#define CLASS_GOLEM 900 + +// @END +#endif // __CLASSES_H diff --git a/omnia/object.cpp b/omnia/object.cpp new file mode 100755 index 000000000..3b82eabc4 --- /dev/null +++ b/omnia/object.cpp @@ -0,0 +1,89 @@ +#define __OBJECT_CPP + +#include "object.h" + +/////////////////////////////////////////////////////////// +// Object +/////////////////////////////////////////////////////////// + +const char* TObject::class_name() const +{ + return "Object"; +} + +word TObject::class_id() const +{ + return CLASS_OBJECT; +} + +bool TObject::is_kind_of(word cid) const +{ + return cid == CLASS_OBJECT; +} + + +bool TObject::ok() const +{ + return TRUE; +} + + +TObject* TObject::dup() const + +{ + CHECK(FALSE, "Can't duplicate an Object"); + return 0L; +} + + +void TObject::print_on(ostream& out) const + +{ + out << class_name(); +} + + +/////////////////////////////////////////////////////////// +// Error Object +/////////////////////////////////////////////////////////// + +const char* TError_Object::class_name() const +{ + return "Error_Object"; +} + + +word TError_Object::class_id() const +{ + return CLASS_ERROR; +} + +bool TError_Object::is_kind_of(word cid) const +{ + return cid == CLASS_ERROR || TObject::is_kind_of(cid); +} + +bool TError_Object::ok() const + +{ + return FALSE; +} + +/////////////////////////////////////////////////////////// +// Sortable +/////////////////////////////////////////////////////////// + +const char* TSortable::class_name() const +{ + return "Sortable"; +} + +word TSortable::class_id() const +{ + return CLASS_SORTABLE; +} + +bool TSortable::is_kind_of(word cid) const +{ + return cid == CLASS_SORTABLE || TObject::is_kind_of(cid); +} diff --git a/omnia/object.h b/omnia/object.h new file mode 100755 index 000000000..9a21215cc --- /dev/null +++ b/omnia/object.h @@ -0,0 +1,268 @@ +#ifndef __OBJECT_H +#define __OBJECT_H + +#ifndef __IOSTREAM_H +#include +#endif + +#ifndef __CLASSES_H +#include "classes.h" +#endif + +#ifndef __STDTYPES_H +#include "stdtypes.h" +#endif + +#ifndef __CHECKS_H +#include "checks.h" +#endif + +////////////////////////////////////////////////////////////////////////////// +// Object +////////////////////////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @class TObject | Classe base per la definizione della gerarchia degli oggetti +class TObject +// @author:(INTERNAL) Guido +{ + // @access Public Member +public: + // @cmember Distruttore + virtual ~TObject() + {} + // @cmember Ritorna il nome della classe + virtual const char* class_name() const; + // @cmember Ritorna l'id della classe + virtual word class_id() const; + // @cmember Controlla se si tratta di un oggetto derivato dalla classe

+ virtual bool is_kind_of(word cid) const; + // @cmember Controlla se si tratta di un oggetto valido (sempre TRUE) + virtual bool ok() const; + // @cmember Duplica un'oggetto + virtual TObject* dup() const; + // @cmember Permette di stampare l'oggetto + virtual void print_on(ostream& out) const; + // @cmember Permette di leggere l'oggetto da istream + virtual void read_from(istream&) + {} + // @cmember Ritorna il codice hash dell'oggetto + virtual word hash() const + { return 0; } +}; + + +////////////////////////////////////////////////////////////////////////////// +// Error Object +////////////////////////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @class TError_Object | Classe per poter ritornare un oggetto sempre errato (ok() == false) +// +// @base public | TObject +class TError_Object : public TObject +// @author:(INTERNAL) Guido +{ + // @access Public Member +public: + // @cmember Ritorna il nome dell'oggetto + virtual const char* class_name() const; + // @cmember Ritorna l'id della classe + virtual word class_id() const; + // @cmember Controlla se si tratta di un oggetto derivato dalla classe

+ virtual bool is_kind_of(word cid) const; + // @cmember Controlla se si tratta di un oggetto valido (sempre FALSE) + virtual bool ok() const; + + // @xref +}; + + +////////////////////////////////////////////////////////////////////////////// +// Error Object +////////////////////////////////////////////////////////////////////////////// + + +// @class TSortable | Classe per la comparazione degli oggetti +// +// @base public | TObject +class TSortable : public TObject +// @author:(INTERNAL) Guido +{ + // @access Public Memebr +public: + // @cmember Permette la comparazione degli oggetti + // Ritorna: 0 se

+ // 0 se

==

+ // 0 se

+ // UNDEFINED se l'ordine non e' definito + virtual int compare(const TSortable& s) const pure; + // @cmember Ritorna il nome della classe + virtual const char* class_name() const; + // @cmember Ritorna l'id della classe + virtual word class_id() const; + // @cmember Controlla se si tratta di un oggetto derivato dalla classe

+ virtual bool is_kind_of(word cid) const; + // @cmember Distruttore + virtual ~TSortable() + {} +}; + + +////////////////////////////////////////////////////////////////////////////// +// inline functions +////////////////////////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @func inline ostream& | operator | Permette di reindirizzare l'oggeto per la stampa + +// @rdesc Ritorna l'output sul quale e' stata reindirizzata la stampa +inline ostream& operator <<( + ostream& out, // @parm Indica l'output sul quale stampare l'oggetto + const TObject& obj) // @parm Oggetto da stampare +{ + obj.print_on(out); + return out; +} + + +// @doc EXTERNAL + +// @func inline istream& | operator | Permette di leggere l'oggetto +// +// @rdesc Ritorna l'input dal quale e' stato letto l'oggetto +inline istream& operator >>( + istream& in, // @parm Input da cui leggere l'oggetto + TObject& obj) // @parm Indirizzo in cui posizionare l'oggetto letto + + // @comm Legge dall'input passato come parametro l'oggetto, nel caso si tratti + // di un oggetto on valido viene dato un messaggio di errore. +{ + obj.read_from(in); + CHECK(obj.ok(), "Can't read an Object from a stream"); + return in; +} + +// @doc EXTERNAL + +// @func inline bool | operator == | Controlla se 2 oggetti sono uguali +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se i due oggetti sono uguali +// @flag FALSE | Se i due oggetti sono diversi +inline bool operator ==( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + // @comm Controlla se i due oggetti passati come parametro sono uguali + // utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res == 0 || res == UNDEFINED; +} + +// @doc EXTERNAL + +// @func inline bool | operator | Controlla se un oggetto e' maggiore dell'altro +// +// @rdesc Ritorna i seguenti valori: +// +// @flag TRUE | Se

e' maggiore di

+// @flag FALSE | Se

e' maggiore o uguale a

+inline bool operator >( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + + // @comm Controlla se l'oggetti passato come primo parametro e' maggiore del + // secondo utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res > 0 || res == UNDEFINED; +} + +// @doc EXTERNAL + +// @func inline bool | operator | Controlla se un oggetto e' minore dell'altro + // @rdesc Ritorna i seguenti valori + // + // @flag TRUE | Se

e' minore di

+ // @flag FALSE | Se

e' minore o uguale a

+inline bool operator <( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + + // @comm Controlla se l'oggetti passato come primo parametro e' minore del + // secondo utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res < 0 || res == UNDEFINED; +} + +// @doc EXTERNAL + +// @func inline bool | operator = | Controlla se un oggetto e' maggiore o uguale all'altro +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' maggiore o uguale a

+// @flag FALSE | Se

e' maggiore

+inline bool operator >=( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + + // + // @comm Controlla se l'oggetti passato come primo parametro e' maggiore o uguale al + // secondo utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res >= 0 || res == UNDEFINED; +} + +// @doc EXTERNAL + +// @func inline bool | operator = | Controlla se un oggetto e' minore o uguale all'altro + // @rdesc Ritorna i seguenti valori + // + // @flag TRUE | Se

e' minore o uguale a

+ // @flag FALSE | Se

e' minore

+inline bool operator <=( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + + // @comm Controlla se l'oggetti passato come primo parametro e' minore o uguale al + // secondo utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res <= 0 || res == UNDEFINED; +} + +// @doc EXTERNAL + +// @func inline bool | operator != | Controlla se 2 oggetti sono diversi +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se i due oggetti sono diversi +// @flag FALSE | Se i due oggetti sono uguali +inline bool operator !=( + const TSortable& a, // @parm Primo oggetto da confrontare + const TSortable& b) // @parm Secondo oggetto da confrontare + + // @comm Controlla se i due oggetti passati come parametro sono diversi + // utilizzando il criterio di comparazione previsto per l'oggetto. +{ + int res = a.compare(b); + return res != 0 && res != UNDEFINED; +} + +#ifdef __OBJECT_CPP +#define extern +#endif + +extern TError_Object error_object; + +#undef extern + +#endif // __OBJECT_H diff --git a/omnia/stdtypes.cpp b/omnia/stdtypes.cpp new file mode 100755 index 000000000..139597f9c --- /dev/null +++ b/omnia/stdtypes.cpp @@ -0,0 +1,2 @@ + + diff --git a/omnia/stdtypes.h b/omnia/stdtypes.h new file mode 100755 index 000000000..24e9c7351 --- /dev/null +++ b/omnia/stdtypes.h @@ -0,0 +1,59 @@ +#ifndef __STDTYPES_H +#define __STDTYPES_H + +#ifndef DBG +#ifndef NDEBUG +#define DBG +#endif +#endif + +#define pure =0 + +#define HIDDEN static + +#define EOL -1 +#define NOERR 0 + + +// @doc EXTERNAL + +// @type bool | Tipo booleano che puo' assumere i valori TRUE (definito come 1) +// e FALSE (definito come 0). + +#ifdef __cplusplus + #ifndef FALSE + #define FALSE false + #define TRUE true + #endif +#else + typedef unsigned short bool; + #ifndef FALSE + #define FALSE 0 + #define TRUE 1 + #endif +#endif + +// @doc EXTERNAL + +// @type word | Tipo per la definizione di tipi di lunghezza pari a due byte +typedef unsigned short word; +// @doc EXTERNAL + +// @type dword | Tipo per la definizione di tipi di lunghezza pari a quattro byte +typedef unsigned int dword; +// @doc EXTERNAL + +// @type byte | Tipo per la definizione di tipi di lunghezza pari ad un byte +typedef unsigned char byte; +// @doc EXTERNAL + +// @type KEY | Tipo per la definizione di variabili destinati a contenere i caratteri +// immessi da tastiera +typedef unsigned short KEY; + +#define UNDEFINED -32767 + + +#endif // __STDTYPES_H + + diff --git a/omnia/strings.cpp b/omnia/strings.cpp new file mode 100755 index 000000000..d9e2162ec --- /dev/null +++ b/omnia/strings.cpp @@ -0,0 +1,1841 @@ +#include +#include +#include +#include +#include +#include + +#include "strings.h" +#include "utility.h" + +// @doc EXTERNAL + +// @func Ritorna il nome dell'utente attuale +// +// @rdesc Ritorno il nome dell'utente attuale +TString& user() +{ + static TString16 _user; + return _user; +} + +const TToken_string& empty_string() +{ + static TToken_string _ts(1); + return _ts; +} + +// Most descriptions will fit in fifty characters +const int DEFAULT_SIZE = 50; +const int MAX_SIZE = 32000; + +inline bool is_space(char c) +{ return c >= '\t' && c <= ' '; } + +// Certified 99% +// @doc EXTERNAL +// +// @mfunc Cambia la dimensione della stringa eventualmente preservandone il contenuto iniziale +void TString::resize( + int size, // @parm Nuova dimensione della stringa + bool cpy) // @parm Se TRUE mantiene il contenuto della stringa e alloca + // nuovo spazio + + // @comm Non funziona con le stringhe static e per valori negativi di

+{ + CHECKD(size >= 0, "Invalid string resize ", size); + char* s = new char[size+1]; + if (cpy && _str) strcpy(s, _str); + else *s = '\0'; + + if (_str) + delete _str; + + _str = s; + _size = size; +} + +// Certified 99% (uses resize) +// @doc EXTERNAL +// +// @mfunc Inizializza con la stringa puntata da char* di lunghezza size +// (usa ) +TString& TString::set( + const char* s) // @parm Stringa da inizializzare + + // @rdesc Ritorna l'indirizzo della stringa inizializzata +{ + if (s && *s) + { + const int sz = strlen(s); + if (sz > size()) resize(sz, FALSE); + strcpy(_str, s); + } + else + { + if (size() == 0) + resize(DEFAULT_SIZE, FALSE); + *_str = '\0'; + } + + return *this; +} +// @doc EXTERNAL + +// @mfunc Espande la stringa per altri caratteri +int TString::make_room( + int s) // @parm Numero di caratteri di cui si vuole aspandere la stringa + + // @comm La stringa viene espansa di un numero di caratteri maggiore (per efficienza) di + // quello passato per parametro + // + // @rdesc Ritorna il numero di caratteri della stringa prima della chiamata +{ + const int lun = len(); + const int spare = size() - lun; + if (spare < s) + { + long new_size = long(lun) + long(s); + if (new_size > MAX_SIZE) + fatal_box("Stringa di lunghezza eccessiva (> %ld)", MAX_SIZE); + new_size = 3L * new_size / 2L; + if (new_size > MAX_SIZE) + new_size = MAX_SIZE; + + resize(int(new_size), TRUE); + } + return lun; +} + +TString::TString(const char* s) : _str(NULL), _size(0) +{ set(s); } + +TString::TString(const TString& s) : _str(NULL), _size(0) +{ set(s); } + +TString::TString(int size, char c) : _str(NULL), _size(0) +{ + if (size > 0) + fill(c, size); // Guy: Much simpler and faster (uses memset) + else + resize(DEFAULT_SIZE, FALSE); +} + +TString::TString() : _str(NULL), _size(0) +{ resize(DEFAULT_SIZE, FALSE); } + +TString::~TString() +{ + if (_str) + delete _str; +} + +char TString::shift(int n) +{ + CHECK(n>0,"Scorrimento a destra delle stringhe non ancora supportato"); + CHECK(n<_size,"Errore di scorrimento"); + char r=*(_str+n-1); + if (n) + { + char *c=_str; + while (*c) + { + *(c)=*(c+n); + c++; + } + } + return r; +} + + +TString& TString::operator <<(const char* s) +{ + if (s && *s) + { + const int pos = make_room(strlen(s)); + strcpy(&_str[pos], s); + } + return *this; +} + +TString& TString::operator <<(char c) +{ + int pos = make_room(1); + _str[pos++] = c; + _str[pos] = '\0'; + return *this; +} + + +TString& TString::operator <<(int n) +{ + char s[16]; + sprintf(s, "%d", n); + return operator <<(s); +} + + +TString& TString::operator <<(long n) +{ + char s[16]; + sprintf(s, "%ld", n); + return operator <<(s); +} + +TString& TString::operator <<(double n) +{ + char s[32]; + sprintf(s, "%lg", n); + return operator <<(s); +} + +// Appends an object to the string +// Certified 50% +// The object should be completely storable in spark +TString& TString::operator <<(const TObject& obj) +{ + TString256 spark; + ostrstream out(spark.get_buffer(), spark.size()); + obj.print_on(out); + out << ends; + return operator <<(spark); +} + + +TString& TString::operator <<(const TString& str) +{ return operator <<(str._str); } + + +// @doc EXTERNAL + +// @mfunc Elimina tutti i caratteri contenuti in

+TString& TString::strip( + const char* k) // @parm Stringa dei caratteri da eliminare + +{ + int j = 0; + for (int i = 0; _str[i]; i++) + { + char c = _str[i]; + if (strchr(k, c) == NULL) + _str[j++] = c; + } + return cut(j); +} + + +bool TString::blank() const +{ + for (int i = 0; _str[i]; i++) + if (!is_space(_str[i])) + return FALSE; + return TRUE; +} + +TString& TString::strip_spaces() +{ + char instring = '\0'; + int j = 0; + for (int i = 0; _str[i]; i++) + { + char c = _str[i]; + if (is_space(c) && !instring) continue; + if (c == '"' || c == '\'') + { + if (instring == c) instring = '\0'; + else + if (instring == '\0') instring = c; + } + _str[j++] = c; + } + _str[j] = '\0'; + return *this; +} + +TString& TString::strip_d_spaces() +{ + int j = 0; + bool spc = FALSE; + for (int i = 0; _str[i]; i++) + { + char c = _str[i]; + if (is_space(c)) + if (spc) + continue; + else + spc = TRUE; + else + if (spc) spc = FALSE; + _str[j++] = c; + } + _str[j] = '\0'; + return *this; +} + +// Certified 100% +const char* TString::class_name() const +{ return "String"; } + +// Certified 100% +word TString::class_id() const +{ return CLASS_STRING; } + +// @doc EXTERNAL + +// @mfunc Duplica una stringa +TObject* TString::dup() const + +// @comm Alloca nuovo spazio per duplicare la stringa +// +// @rdesc Ritorna il puntatore alla stringa duplicata +{ + TString* s = new TString(_str); + return s; +} + +void TString::read_from(istream& in) +{ + if (size() < 256) + { + char tmp[256] = ""; + in >> tmp; + set(tmp); + } + else + { + cut(0); + in >> _str; + } +} + +// Certified 100% +void TString::print_on(ostream& out) const +{ out << _str; } + + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Ritorna la posizione del carattere o della stringa nell'oggetto TString +// +// @rdesc Ritorna i seguneti parametri: +// +// @flag = 0 | Posizione dell'elemento nella stringa +// @flag -1 | L'elemento non e' stato trovato +int TString::find( + char c, // @parm Carattere da cercare + int from) const // @parm Posizione da cui iniziare la ricerca + // @parm const char* | s | Stringa da cercare + + // @syntax find(char c, int from); + // @syntax find(const char* s, int from); + // + // @comm Cerca nella stringa, dalla posizione indicata, l'elemento passato. + // Nel caso

sia maggiore della lunghezza della stringa manda + // un messaggio di errore +{ + int pos = -1; + if (from < len()) + { + const char* p = strchr(_str + from, c); + if (p) + pos = int(p - _str); + } + return pos; +} + +int TString::rfind( + char c) const // @parm Carattere da cercare + + // @syntax rfind(char c); + // +{ + const char* p = strrchr(_str, c); + return p ? int(p - _str) : -1; +} + + +// Certified 100% +int TString::find(const char* s, int from) const +{ + int pos = -1; + if (from < len()) + { + const char* p = strstr(_str + from, s); + if (p) + pos = int(p - _str); + } + return pos; +} + +int TString::replace(char find_char, char replace_char) +{ + int n = 0; + for (int i = 0; _str[i]; i++) + if (_str[i] == find_char) + { + _str[i] = replace_char; + n++; + } + return n; +} + + +// Certified 99% +// @doc EXTERNAL + +// @mfunc Ritorna l'oggetto TString composto dai

caratteri da sinistra +const TString& TString::left( + int count) const // @parm Indica fino quale carattere restituire la stringa + + // @rdesc Ritorna l'indirizzo della stringa contenente i

caratteri da sinistra +{ + TString& spark = get_tmp_string(); + spark = _str; + spark.cut(count); + return spark; +} + +// Certified 99% +// @doc EXTERNAL + +// @mfunc Ritorna l'oggetto TString composto dai

caratteri da destra +const TString& TString::right( + int count) const // @parm Indica da quale carattere restituire la stringa + + // @rdesc Ritorna l'indirizzo della stringa contenente i

caratteri da destra +{ + TString& spark = get_tmp_string(); + int from = len()-count; + if (from < 0) from = 0; + spark = _str + from; + return spark; +} + + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Ritorna l'oggetto TString composto dai

caratteri a partire +// da

+const TString& TString::mid( + int from, // @parm Posizione dalla quale partire per l'estrazione + int count) const // @parm Numero di caratteri da estrarre + + // @rdesc Ritorna l'indirizzo della stringa contenente i

cartteri da

+{ + TString& spark = get_tmp_string(); + const int l = len(); + +#ifdef DBG + if (from < 0) + { + NFCHECK("Invalid MID parameter: from = %d", from); + from = 0; + } +#endif + if (from > l) from = l; + if (count < 0 || from+count>l) + count = l-from; + spark.strncpy(&_str[from], count); + return spark; +} + + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Ritorna la stringa da

a

(escluso) +const TString& TString::sub( + int from, // @parm Posizione dalla quale estrarre la stringa + int to) const // @parm Posizione fin alla quale estrarre la stringa + + // @rdesc Ritorna l'indirizzo della stringa da i

a

+{ + const int count = to-from; + return mid(from, count); +} + +// Certified 100% +TString& TString::cut(int n) +{ + CHECKD(n >= 0, "Invalid TString::cut position ", n); + if (n <= _size) + _str[n] = '\0'; + return *this; +} + +// @doc EXTERNAL +// @mfunc Espande la stringa fino alla lunghezza indicata, eventualmente aggiungendo spazi a destra +TString& TString::rpad(const int n,const char c) +{ + const int l = len(); + if (n > l) + { + if (n > size()) resize(n, TRUE); + memset(_str+l, c, n-l); + _str[n] = '\0'; + } + return *this; +} + +// @doc EXTERNAL +// @mfunc Espande la stringa fino alla lunghezza indicata, eventualmente aggiungendo spazi a sinistra +TString& TString::lpad(const int n,const char c) +{ + int l=len(); + const int nsp=n-l; + if (n>l) + { + if (n > size()) resize(n, TRUE); + for (l--; l>=0; l--) + *(_str+l+nsp)=*(_str+l); + memset(_str, c, nsp); + _str[n] = '\0'; + } + return *this; +} + +// @doc EXTERNAL + +// @mfunc Elimina gli spazi da sinistra o i primi n caratteri (da sinistra). +TString& TString::ltrim( + int count) // @parm Indica il numero di caratteri da eliminare. + // Se uguale a 0 elimina tutti gli spazi da sinistra + + // @comm Controlla se

e' 0. Se non lo Š ritorna l'indirizzo della + // stringa a partire dal

-esimo carattere; altrimenti controlla + // se i primi caratteri sono spazi e li elimina fino a che non trova + // un carattere diverso da ' ' + // + // @xref +{ + const char* s; + + if (count > 0) + { + if (count >= len()) return cut(0); + s = &_str[count]; + } + else for (s = _str; *s && is_space(*s); s++); + + if (s != _str) strcpy(_str, s); + return *this; +} + +// @doc EXTERNAL + +// @mfunc Elimina gli spazi da destra o i primi n caratteri (da destra). +TString& TString::rtrim( + int count) // @parm Indica il numero di caratteri da eliminare. + // Se uguale a 0 elimina tutti gli spazi da destra + + // @comm Controlla se

e' 0. Se non lo e' pone il fine stringa alla + // posizione

; altrimenti controlla se gli ultimi caratteri + // sono spazi e li elimina fino a che non trova un carattere diverso da ' ' + // + // @xref +{ + if (count > 0) + { + int i = len() - count; + if (i < 0) i = 0; + cut(i); + } + else + { + char* good = _str-1; + for (char* s = _str; *s; s++) + if (!is_space(*s)) good = s; + *(good+1) = '\0'; + } + return *this; +} + +TString& TString::trim() +{ + char* last = _str; + + // Salta spazi iniziali + for (const char* s = _str; *s && is_space(*s); s++); + + // Copia stringa + if (s > _str) + { + for(char* c = _str; *s; s++) + { + *c++ = *s; + if (!is_space(*s)) last = c; + } + // Elimina spazi finali + *last = '\0'; + } + else rtrim(); + + return *this; +} + +// Certified 50% +// @doc EXTERNAL + +// @mfunc Compara due stringhe (o i primi

caratteri) +// +// @rdesc Ritrna i seguenti valori: +// +// @flag 0 | Se le stringhe sono uguali +// @flag 0 | Se le stringhe sono diverse +int TString::compare( + const char* s, // @parm Stringa da comparare + int max, // @parm Numero di caratteri da conforntare (default tutta la stringa) + bool ignorecase) const // @parm Ignorare la differenza maiuscolo/minuscolo (default FALSE) +{ + int res; + + if (s == NULL) s = ""; + if (ignorecase) + { + if (max < 0) + res = stricmp(_str, s); + else + { + for (int i = 0; i < max; i++) + { + res = toupper(_str[i]) - toupper(s[i]); + if (res) break; + } + } + } + else + res = max < 0 ? strcmp(_str, s) : strncmp(_str, s, max); + + return res; +} + +bool TString::starts_with(const char* s, bool ignorecase) const +{ + return compare(s, strlen(s), ignorecase) == 0; +} + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Riempe la stringa con n caratteri c +// +// @rdesc Ritorna l'indirizzo dell stringa +TString& TString::fill( + char c, // @parm Caratteri con cui riempire la stringa + int n) // @parm Numero di caratteri da inserire nella stringa + // (default per tutta la lungehzza) + + // @comm Se il paramatro

e' maggiore della dimensione della stringa, la + // stessa viene ridimensionata (chaimata alla ). + // Nel caso non venga passato il parametro

la stringa viene + // riempita col carattere

per tutta la lunghezza. + +{ + if (n < 0) + n = size(); + else + if (n > size()) + resize(n, FALSE); + memset(_str, c, n); + _str[n] = '\0'; + return *this; +} + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Giustifica l'oggetto stringa a destra +TString& TString::right_just( + int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa) + char c) // @parm Carattere di riempimento (default ' ') + + // @comm Nel caso venga passato un carattere in

, questo viene inserito + // nel resto della stringa (a sinistra della stringa stessa) + // + // @xref +{ + if (n < 0) + n = size(); + trim(); + if (len() < n) + { + TString& spark = get_tmp_string(); + spark = _str; + fill(c, n); + overwrite(spark, n-spark.len()); + } + + return *this; +} + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Centra l'oggetto stringa +TString& TString::center_just( + int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa) + char c) // @parm Carattere di riempimento (default ' ') + + // @comm Nel caso venga passato un carattere in

, questo viene inserito + // nel resto della stringa (a destra e a sinistra della stringa stessa) + // + // @xref +{ + if (n < 0) + n = size(); + trim(); + if (len() < n) + { + TString& spark = get_tmp_string(); + spark = _str; + fill(c, n); + const int p = (n-spark.len()) >> 1; + overwrite(spark, p); + } + + return *this; +} + +// Certified 100% +// @doc EXTERNAL + +// @mfunc Giustifica l'oggetto stringa a sinistra +TString& TString::left_just( + int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa) + char c) // @parm Carattere di riempimento (default ' ') + + // @comm Nel caso venga passato un carattere in

, questo viene inserito + // nel resto della stringa (a destra della stringa stessa) + // + // @xref +{ + if (n < 0) + n = size(); + trim(); + if (len() < n) + { + TString& spark = get_tmp_string(); + spark = _str; + fill(c, n); + overwrite(spark, 0); + } + return *this; +} + +// @doc EXTERNAL + +// @mfunc Formatta una stringa usando il formato dato da

+TString& TString::picture( + const char* pic, // @parm Formato della stringa + const char* s) // @parm Stringa da formattare +{ + if (pic == NULL || *pic == '\0') + return set(s); + + set(pic); + + int l = strlen(s)-1; // Prossimo carattere da sostituire a # o @ + + for (int i = len()-1; i >= 0; i--) + { + const char k = pic[i]; + if (k == '#') _str[i] = (l >= 0) ? s[l--] : ' '; + else if (k == '@') _str[i] = (l >= 0) ? s[l--] : '0'; + else if (k == '^') { _str[i] = ' '; l--; } + } + + return *this; +} + +// Certified 99% (s != NULL) +int TString::strncpy(const char* s, int n) +{ + if (n > size()) + resize(n, FALSE); + int i = 0; + if (s && *s) + { + for (; *s && i < n; i++) + _str[i] = *s++; + } + _str[i] = '\0'; + return i; +} + +// Certified 90% (spark size limited) +// @doc EXTERNAL + +// @mfunc Manda un output formattato alla stringa oggetto +TString& TString::format( + const char* fmt, // @parm Stringa da formattare + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Funziona come la funzione "sprintf" standard del C e ritorna la + // stringa formattata con i parametri passati. +{ + char spark[512]; + va_list pars; + va_start(pars, fmt); + const int tot = vsprintf(spark, fmt, pars); + va_end(pars); + + CHECK(tot < sizeof(spark), "Ue'! Quanto scrivi?"); + return set(spark); +} + +// Certified 99% +char* TString::get_buffer(int min_size) +{ + if (min_size > size()) + resize(min_size, TRUE); + return _str; +} + +// Certified 99% +TString& TString::upper(int from, int to) +{ + for (int c=0; *(_str+c) && (to<0 || c<=to); c++) + if (c>=from) + *(_str+c) = toupper(*(_str+c)); + return *this; +} + +// Certified 99% +TString& TString::lower(int from, int to) +{ + for (int c=0; *(_str+c) && (to<0 || c<=to); c++) + if (c>=from) + *(_str+c) = tolower(*(_str+c)); + return *this; +} + +// Certified 50% +// @doc EXTERNAL + +// @mfunc Permette di ttrovare il plurale di una stringa +TString& TString::add_plural( + long num, // @parm Numero di elementi per sapere la desineneza + const char* name) // @parm Stringa da modificare + + // @comm A seconda del numero passato in

permette di stabilire la + // corretta sintassi della stringa

da scrivere nei messaggi + // dati all'utente. Nel caso

sia 0 allora ritorna "nessuno". +{ + const TFixed_string n(name); + const char last = n[n.len()-1]; + + if (num < 1) + { + *this << "nessun"; + if (toupper(last) == 'A' || toupper(n[0]) == 'Z' || + toupper(n[0]) == 'S' && strchr("aeiouAEIOU", n[1]) == NULL) + *this << tolower(last); + *this << ' ' << name; + } + else + { + *this << num << ' ' << name; + if (num > 1) + _str[len()-1] = (last == 'a') ? 'e' : 'i'; + } + + return *this; +} + +// Certified 90% +// @doc EXTERNAL + +// @mfunc Sovrascrive la stringa

dalla posizione

+TString& TString::overwrite( + const char* s, // @parm Stringa da inserire + int pos, // @parm Posizione dalla quale iniziare a sovrascrivere + int lung) // @parm Lunghezza + + // @comm Sovrascrive dalla posizione

fino alla lunghezza di

l'oggetto + // stringa. Nel caso la dimensione sia maggiore l'oggetto viene riallocato + // dinamicamente + // + // @xref +{ + if (lung == 0) lung=strlen(s); + if (s || lung) + { + const int l = len(); + if (pos < 0) pos = l; + const int max = pos+lung; + if (max > size()) resize(max, TRUE); // resize needed? + + const bool over = max > l; // beyond end of string? + for (int i = l; i < pos; i++) _str[i] = ' '; // space padding per inserimenti dopo la fine della stringa + for (; *s; s++) _str[pos++] = *s; // write + for (; pos < max ; pos++) _str[pos] = ' '; // space padding per inserimenti con stringhe minori della lunghezza prevista + if (over) _str[pos] = '\0'; // end of string + } + return *this; +} + + +// Certified 90% +// @doc EXTERNAL + +// @mfunc Inserisce la stringa s dalla posizione pos +TString& TString::insert( + const char* s, // @parm Stringa da inserire + int pos) // @parm Posizione dalla quale iniziare a inserire + + // @comm Inserisce dalla posizione

la stringa

nell'oggetto + // stringa. Nel caso la dimensione sia maggiore l'oggetto viene riallocato + // dinamicamente + // + // @xref +{ + if (s && *s) + { + const int l = strlen(s); + make_room(l); + const TString& spark = mid(pos); // Scrivi in spark la stringa da pos in poi + overwrite(s, pos); // Aggiungi s + strcpy(&_str[pos+l], spark); // Aggiungi spark + } + return *this; +} + +// Certified 90% +word TString::hash() const +{ +/* +// Villa's megasmart hash function + word h = 0x0000; + for (int i = 0; _str[i]; i++) + h ^= (i & 0x1) ? (_str[i] << 8) : _str[i]; +*/ + // Peter Weinberger's (PJW) generic hashing + word h = 0; + for (const char* s = _str; *s; s++) + { + h = (h << 2) + *s; + const word i = h & 0xC000; + if (i) h = (h ^ (i >> 12)) & 0x3FFF; + } + return h; +} + +/////////////////////////////////////////////////////////// +// TFixed_string +/////////////////////////////////////////////////////////// + +// Certified 100% +TFixed_string::TFixed_string(const char* str, int size) +: TString((char*)str, (size <= 0) ? strlen(str) : size-1) +{ + CHECK(str, "NULL buffer for fixed string"); + if (size > 0 && memchr(str, '\0', size) == NULL) + cut(0); +} + + +// Certified 100% +TFixed_string::~TFixed_string() +{ _str = NULL; } // Impedisce la deallocazione + +// Certified 100% +void TFixed_string::resize(int size, bool) +{ + fatal_box("Impossibile ridimensionare una stringa fissa da %d a %d caratteri:\n'%s'", + _size, size, _str); +} + +// Certified 99% +// @doc EXTERNAL + +// @mfunc Manda un output formattato alla stringa oggetto +TString& TFixed_string::format( + const char* fmt, // @parm Formato della stringa + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Funziona come la funzione "sprintf" standard del C e ritorna la + // stringa formattata con i parametri passati. + // E' piu' efficiente di poiche' non usa spark +{ + va_list pars; + va_start(pars, fmt); + const int tot = vsprintf(_str, fmt, pars); + va_end(pars); + CHECK(tot >= 0 && tot <= size(), "Ue'! Quanto scrivi con 'sta format?"); + return *this; +} + +/////////////////////////////////////////////////////////// +// Filename +/////////////////////////////////////////////////////////// + +// Certified 90% +const char* TFilename::ext() const +{ + const char* d = strrchr(name(), '.'); + if (d && !is_slash(*(++d))) return d; + return ""; +} + +// Certified 90% +void TFilename::ext(const char* e) +{ + int start = find(' ')-1; + if (start < 0) + start = len()-1; + + bool can_cut = TRUE; + for (int i = start; i > 0 && _str[i] != '.'; i--) + if (is_slash(_str[i]) || _str[i] == ':') + { + can_cut = FALSE; + i = start; + break; + } + + if (i > 0 && can_cut && !is_slash(_str[i+1])) + cut(i); + if (*e) + { + if (*e != '.') + *this << "."; + *this << e; + } +} + + +// Certified 95% +const char* TFilename::name() const +{ + int start = find(' ')-1; + if (start < 0) + start = len()-1; + for (int i = start; i >= 0; i--) + if (is_slash(_str[i]) || _str[i] == ':') + break; + + TString& spark = get_tmp_string(); + spark = &_str[i+1]; + spark.cut(start-i); + return spark; +} + +// Certified 95% +const char* TFilename::path() const +{ + int start = find(' ')-1; + if (start < 0) + start = len()-1; + for (int i = start; i >= 0; i--) + if (is_slash(_str[i]) || _str[i] == ':') + break; + TString& spark = get_tmp_string(); + spark = _str; + spark.cut(i+1); + return spark; +} + + +TFilename& TFilename::add(const char* n) +{ + if (not_empty() && !is_slash(_str[len()-1]) && !is_slash(*n)) + *this << SLASH; + *this << n; + return *this; +} + + +// @doc EXTERNAL + +// @mfunc Controlla il formato del nome del file +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se il nome del file e' sintatticamente corretto +// @flag FALSE | Se il nome del file non e' sintatticamente corretto +bool TFilename::ok() const + +// @comm Controlla tutti i casi per cui un nome di file puo' non essere valido. +// Nel caso si lavori in Windows controlla anche che il nome del +// disco sia corretto. +{ + const int l = len(); + + int len = 0; // lunghezza ultima sottostringa + bool ext = FALSE; // trovata estensione + + for (int c = 0; c < l; c++) + { + switch(_str[c]) + { + case ':': + if (c != 1 || !isalpha(_str[0])) return FALSE; // Nome disco errato + len = 0; + break; + case '\\': + case '/': + if (ext) return FALSE; // Slash dopo estensione + if (len > _MAX_FNAME) return FALSE; // Nome troppo lungo + if (!isalnum(_str[++c])) return FALSE; + len = 1; + break; + case '.': + if (len == 0 || ext) return FALSE; // Nome nullo o Doppia estensione + ext = TRUE; + len = 0; + c++; + default: + if (isalnum(_str[c])) len++; + else return FALSE; + break; + } + } + + if (ext && len > _MAX_EXT) + return FALSE; + + return len > 0 && len <= _MAX_FNAME; +} + +// Certified 70% +const TFilename& TFilename::tempdir() +{ + static TFilename _tempdir; + const bool create = _tempdir.empty() || user().compare(_tempdir.right(user().len()), -1, TRUE); + + if (create) + { + _tempdir = getenv("TEMP"); + if (_tempdir.empty()) + _tempdir = getenv("TMP"); + if (_tempdir.empty()) + _tempdir << SLASH << "temp"; + + const int last = len()-1; + if (is_slash(_str[last])) + _tempdir.cut(last); + + bool ok = TRUE; + + _tempdir.lower(); + if (!_tempdir.exist()) + ok = mkdir(_tempdir) == 0; + + if (!ok) + fatal_box("Impossibile creare la directory '%s' per i file temporanei", (const char*)_tempdir); + + TString tmp = _tempdir; + tmp.insert("TMP=", 0); + putenv(tmp); + } + + set(_tempdir); + return *this; +} + +const TFilename& TFilename::currdir() +{ + getcwd(_str, size()); + return *this; +} +// Certified 50% +// @doc EXTERNAL + +// @mfunc Genera il nome di un file temporaneo +const TFilename& TFilename::temp( + const char* prefix, // @parm Eventuale prefisso da assegnare al file temporaneo + const char* extension) // @parm Eventuale estensione da assegnare al file temporaneo + + // @comm Nel generare il nome del file controlla se esistone dei caratteri jolly + // e li elimina. +{ + tempdir(); + if (prefix && *prefix) + { + set(prefix); // Copia prefisso e ... + strip("$#*?."); // ... toglie caratteri jolly + } + else + cut(0); + + char* t = tempnam(NULL, (char*)_str); + CHECK(t != NULL, "Can't execute tempnam"); + set(t); + free(t); + + CHECKS(!fexist(_str), "Il file temporaneo esiste gia': ", _str); + return *this; +} + + +bool TFilename::is_absolute_path() const +{ + const char* s = _str; + if (isalpha(*s) && s[1] == ':') + s += 2; + return is_slash(*s); +} + +const TFilename& TFilename::make_absolute_path() +{ + if (is_relative_path()) + { + const TString saved(_str); + currdir(); + add(saved); + } + return *this; +} + +bool TFilename::exist() const +{ + return ::fexist(_str); +} + +bool TFilename::search_in_path(TFilename& path) const +{ + _searchenv(_str, "PATH", path.get_buffer()); + if (path.empty()) + _searchenv(_str, "path", path.get_buffer()); + return path.not_empty(); +} + +bool TFilename::custom_path(const char* path_list) +{ + bool ok = false; + if (!is_absolute_path()) + { + TToken_string pl = path_list; + if (pl.empty()) + pl.add("custom"); // c:/campo32/custom + const TString fname = name(); + FOR_EACH_TOKEN(pl, path) + { + TFilename cust = path; + cust.add(fname); + if (cust.exist()) + { + set(cust); + ok = true; + break; + } + } + } + else + ok = exist(); + return ok; +} + +/////////////////////////////////////////////////////////// +// Token string +/////////////////////////////////////////////////////////// + +// Certified 100% +TToken_string::~TToken_string() +{ +} + +// Certified 100% +TToken_string::TToken_string(const char* s, char separator) +: TString(s), _separator(separator) +{ + CHECK(_separator, "NULL TToken_string separator"); + restart(); +} + +// Certified 100% +TToken_string::TToken_string(int n, char separator) +: TString(n), _separator(separator), _last(-1) +{ + CHECK(_separator, "NULL TToken_string separator"); +} + +// Certified 100% +TToken_string::TToken_string(const TToken_string& s) +: TString(s), _separator(s._separator), _last(s._last) +{ + CHECK(_separator, "NULL TToken_string separator"); +} + +const TToken_string& TToken_string::operator =(const TToken_string& s) +{ + set(s); + restart(); + separator(s.separator()); + return *this; +} + +void TToken_string::separator(char s) +{ + CHECK(s, "NULL TToken_string separator"); + _separator = s; +} + + +// Certified 100% +TObject* TToken_string::dup() const +{ + return new TToken_string(_str, _separator); +} + +// Certified 90% +const char* TToken_string::get() +{ + CHECK(_separator, "Corrupted TToken_string: NULL separator"); + + if (_last < 0) return NULL; + + const int start = _last; + + if (_str[start] == '\0') + { + _last = -1; + return NULL; + } + else + if (_str[start] == _separator) + { + _last = start+1; + } + else + { + const int k = find(_separator, start); + _last = (k >= 0) ? k+1 : -1; + return sub(start, k); + } + return ""; +} + +// Certified 50% +// @doc EXTERNAL + +// @mfunc Ritorna un Token +// +// @rdesc Ritorna la stringa alla posizione

+const char* TToken_string::get( + int n) // @parm Token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) + + // @syntax const char* get(int n); + // @syntax const char* get(); + // + // @comm Se non viene passato il parametro

ritorna il prossimo Token + // (come se

== -1) + // + // @xref +{ + CHECK(_separator, "Corrupted TToken_string: NULL separator"); + TString& spark = get_tmp_string(); + + if (n < 0) + { + if (n == -2) + { + const char* sep = strrchr(_str, _separator); + _last = -1; + return sep ? sep+1 : _str; + } + else return get(); + } + int sep = 0; + for (const char* s = _str; sep < n && *s; s++) + if (*s == _separator) sep++; + + if (sep >= n) + { + char* p = strchr(s, _separator); + if (p == NULL) + { + spark = s; + _last = -1; + } + else + { + *p = '\0'; + spark = s; + *p = _separator; + _last = (int)((const char*)p - _str) + 1; + } + } + else + { + _last = -1; + return NULL; + } + + return spark; +} + +// Certified 99% +// @doc EXTERNAL + +// @mfunc Ritorna un carattere +// +// @rdesc Ritorna il primo carattere del Token richiesto +char TToken_string::get_char( + int n) // @parm Token da ritornare + + // @comm Chiama la con tutti i relativi significati per + // il parametro

+{ + const char* const car = get(n); + return car ? *car : '\0'; +} + +// Certified 99% +int TToken_string::get_int(int n) +{ + const char* const num = get(n); + return num ? atoi(num) : 0; +} + + +// Certified 99% +long TToken_string::get_long(int n) +{ + const char* const num = get(n); + return num ? atol(num) : 0L; +} + + +// const TToken_string new age! + +// @rdesc Ritorna TRUE se e' stata trovata una stringa alla posizione

+bool TToken_string::get( + int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) + TString& tok) const // @parm Stringa da ritornare + // @syntax const char* get(TString& str, int n); + // + // @xref +{ + CHECK(_separator, "Corrupted TToken_string: NULL separator"); + + if (n < 0) + { + const char* sep = strrchr(_str, _separator); + tok = sep ? sep+1 : _str; + return tok.not_empty(); + } + + int sep = 0; + for (const char* s = _str; *s && sep < n; s++) + if (*s == _separator) sep++; + + bool found = sep == n; + if (found) + { + char* p = strchr(s, _separator); + if (p == NULL) + { + tok = s; + found = tok.not_empty(); + } + else + { + *p = '\0'; + tok = s; + *p = _separator; + } + } + else + tok.cut(0); + + return found; +} + +bool TToken_string::get( + int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) + char& tok) const // @parm char da ritornare +{ + TString16 str; + bool found = get(n, str); + tok = found ? str[0] : '\0'; + return found; +} + +bool TToken_string::get( + int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) + int& tok) const // @parm int da ritornare +{ + TString16 str; + bool found = get(n, str); + tok = found ? atoi(str) : 0; + return found; +} + +bool TToken_string::get( + int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) + long& tok) const // @parm long da ritornare +{ + TString16 str; + bool found = get(n, str); + tok = found ? atol(str) : 0L; + return found; +} + +// Certified 90% +bool TToken_string::set_item(const char* v, int n) +{ + CHECK(_separator, "Corrupted TToken_string: NULL separator"); + TString& spark = get_tmp_string(); + + int sep = 0; + for (int i = 0; sep < n && _str[i]; i++) + if (_str[i] == _separator) sep++; + + if (sep < n) // Aggiunge items mancanti prima della posizione n + { + for (;sep < n; sep++) + *this << _separator; + *this << v; + return FALSE; + } + + int e = find(_separator, i); + if (e < 0) e = len(); + + spark = _str+e; // Salva items seguenti + cut(i); // Considera solo items precedenti + *this << v << spark; // Aggiunge item desiderato e seguenti + return TRUE; +} + + +// Certified 80% +int TToken_string::get_pos(const char* s) +{ + const char* item; + + restart(); + for (int i = 0; (item = get()) != NULL; i++) + if (strcmp(item, s) == 0) return i; + + return -1; +} + +// Certified 80% +int TToken_string::get_pos(long n) +{ + char s[16]; sprintf(s, "%ld", n); + return get_pos(s); +} + +// Certified 90% +bool TToken_string::empty_items() const +{ + for (const char* c = _str; *c; c++) + if (!is_space(*c) && *c != _separator) + return FALSE; + return TRUE; +} + +// Certified 80% +int TToken_string::items() const +{ + int t = 0; + if (not_empty()) + { + t++; + for (const char* s = _str; *s; s++) + if (*s == _separator) t++; + } + return t; +} + +// Certified 99% +// @doc EXTERNAL + +// @mfunc Aggiunge un elemento alla token string +void TToken_string::add( + const char* s, // @parm Stringa da aggiungere + int pos) // @parm Posizione nella quale aggiungere l'elemento + // (default aggiunge come ultimo elemento) + // @parm char | c | Caratter da aggiungere + // @parm long | n | Long da aggiungere + // @parm int | n | Intero da aggiungere + + // @syntax void add(const char* s, int n = -1); + // @syntax void add(char c, int pos = -1); + // @syntax void add(long n, int pos = -1); + // @syntax void add(int n, int pos = -1); + // + // @comm Permette, a seconda del parametro passato, di aggiungere alla Token + // string un nuovo elemnto gia' completo del carattere di separazione +{ + if (s == NULL || *s == '\0') s = " "; + if (pos < 0) + { + if (not_empty()) *this << _separator; + *this << s; + } + else + set_item(s, pos); + if (_last < 0) _last = 0; +} + +// Certified 100% +void TToken_string::add(char c, int pos) +{ + const char s[2] = { c, '\0' }; + add(s, pos); +} + +// Adds an integer value to the token string +// Certified 100% +void TToken_string::add(long n, int pos) +{ + char s[16]; + sprintf(s, "%ld", n); + add(s, pos); +} + +// Adds an integer value to the token string +// Certified 100% +void TToken_string::add(int n, int pos) +{ + char s[16]; + sprintf(s, "%d", n); + add(s, pos); +} + +// Certified 50% +void TToken_string::destroy(int n) +{ + if (_last == -2) return ; + + if (n < 0) + { + char* s = strrchr(_str, _separator); + if (s != NULL) *s = '\0'; + } + else + { + int sep = 0; + for (char* s = _str; sep < n && *s; s++) + if (*s == _separator) sep++; + + if (sep >= n) + { + const char* p = strchr(s, _separator); + *s = '\0'; + if (p != NULL) strcat(s, p+1); + } + } + restart(); +} + +/////////////////////////////////////////////////////////// +// TAuto_token_string +/////////////////////////////////////////////////////////// + +TAuto_token_string& TAuto_token_string::create(const char* ts) +{ + // Copia la stringa + set(ts); + + // Calcola il separatore + for (const char* s = ts; s && *s; s++) + { + if (strchr("|¦\t\n^;,!&+", *s) != NULL) + { + separator(*s); + break; + } + } + + return *this; +} + +/////////////////////////////////////////////////////////// +// Paragraph string +/////////////////////////////////////////////////////////// + +TParagraph_string::TParagraph_string(const char* s, int width) +: TToken_string(s, '|'), _width(width) +{ tokenize(); } + +const TString& TParagraph_string::operator =(const char* s) +{ + TToken_string::operator=(s); + tokenize(); + return *this; +} + +/* +void TParagraph_string::tokenize() +{ + int last_space = -1, last_start = 0; + int num_chars = 0; + const int l = len(); + TString stmp,swork; // stringhe di lavoro + for (int start = 0; start < l;) + { + + switch (_str[start]) + { + case '\r': + case '\n': last_space = start; num_chars = _width; break; + case ' ' : last_space = start; num_chars++; break; + default : num_chars++; break; + } + + if (num_chars == _width && (start < l-1)) + { + int num_of_chars_in_row = (last_space+1) - last_start; + if (num_of_chars_in_row <= 0) num_of_chars_in_row = _width; // Se non ci sono spazi tronca la stringa a 25 + swork = mid(last_start,num_of_chars_in_row); + stmp << swork.trim(); stmp << '|'; + last_space = num_chars = 0; +// start = start - (_width - num_of_chars_in_row); // riporta indietro (toglie il numero di caratteri effettivi della riga) + start = last_start + num_of_chars_in_row; + last_start = start; + } + else + start++; + } + swork=mid(last_start,l-last_start); + swork.trim(); + stmp << swork; + if (stmp.empty()) stmp = _str; + TToken_string::operator=(stmp); +} +*/ + +void TParagraph_string::tokenize() +{ + if (not_empty()) + { + TToken_string tmp; + int start = 0; + int last_space = -1; + + const int length = len(); + for (int i = start; i <= length; i++) + { + int add_now = -1; + switch(_str[i]) + { + case ' ': + case '\t': + last_space = i; + break; + case '\r': + case '\n': + case '\0': + add_now = i; + break; + default: + if (i - start >= _width) + { + if (last_space > start) + add_now = last_space; + else + add_now = i; + } + break; + } + if (add_now >= start) + { + TString256 tok = sub(start, add_now); + tok.rtrim(); // Preserva gli spazi iniziali dopo un a capo forzato da \n + tmp.add(tok); + start = add_now + (_str[add_now] <= ' '); + last_space = start; + } + } + tmp.rtrim(); + TToken_string::operator=(tmp); + } +} + +/////////////////////////////////////////////////////////// +// TString_array +/////////////////////////////////////////////////////////// + +int TString_array::add(const char* s, int n) +{ + if (objptr(n) == NULL) + n = TArray::add(new TToken_string(s), n); + else row(n) = s; + return n; +} + +int TString_array::add(const TToken_string& s, int n) +{ + if (objptr(n) == NULL) + n = TArray::add(s, n); + else + row(n) = s; + return n; +} + +const TString_array& TString_array::operator=(const TString_array& a) +{ + destroy(); + for (int i = a.last(); i >= 0; i = a.pred(i)) + { + const TToken_string& s = a.row(i); + add(s, i); + } + return a; +} + +// @doc EXTERNAL + +// @mfunc Cerca una stringa nell'array +// +// @rdesc Ritorna la posizione nell'array in cui si trova la stringa (-1 se non +// e' stata trovata) +int TString_array::find( + const char* s, // @parm Stringa da cercare + int from) const // @parm Posizione dalla quale cercare la stringa +{ + int found = -1; + for (int i = from; i < items(); i++) + if (row(i).compare(s, -1, TRUE) == 0) + { + found = i; + break; + } + return found; +} + +HIDDEN int ascending_string(const TObject** o1, const TObject** o2) +{ + const TString* s1 = (const TString*)*o1; + const TString* s2 = (const TString*)*o2; + return strcmp(*s1, *s2); +} + +HIDDEN int descending_string(const TObject** o1, const TObject** o2) +{ + return -ascending_string(o1, o2); +} + +void TString_array::sort(bool ascending) +{ + TArray::sort(ascending ? ascending_string : descending_string); +} + +// Temporary strings generator: a little step for a man, a big step for campo! + +TToken_string& get_tmp_string(int len) +{ + static TString_array ararar(128); + static int next = 0; + + TToken_string* str = (TToken_string*)ararar.objptr(next); + if (str == NULL) + { + str = new TToken_string(len); + ararar.add(str, next); + } + if (str->size() < len) + str->spaces(len); + str->cut(0); + + if (++next >= ararar.size()) + next = 0; + return *str; +} diff --git a/omnia/strings.h b/omnia/strings.h new file mode 100755 index 000000000..ec9dc4158 --- /dev/null +++ b/omnia/strings.h @@ -0,0 +1,740 @@ +#ifndef __STRINGS_H +#define __STRINGS_H + +#ifndef _INC_STRING +#include +#endif + +#ifndef __ARRAY_H +#include "array.h" +#endif + +#define SAFE_PIPE_CHR '¦' + +// @doc EXTERNAL + +// @class Classe per la definizione della stringhe +// +// @base public | TObject +class TString : public TObject +// @author:(INTERNAL) Guido +{ + // @access Protected Member +protected: + // @cmember Puntatore alla stringa + char* _str; + // @cmember Lunghezza della stringa + int _size; + + // @cmember Espande la stringa per altri caratteri + int make_room(int size); + // @cmember Inizializza con la stringa puntata da char* di lunghezza size + TString& set(const char*); + + // @cmember Costruttore per consentire la derivazione delle TFixed_string + TString(char* str, int size) : _str(str), _size(size) + {} + + // @access Public member +public: + // @cmember Cambia la dimensione della stringa eventualmente preservandone il contenuto iniziale + virtual void resize(int size, bool cpy); + + // @cmember Costruttore + TString(); + // @cmember Costruttore di default per una stringa data + TString(int size, char c='\0'); + // @cmember Costruttore a partire da una stringa s + TString(const char* s); + // @cmember Costruttore da un oggetto TString s + TString(const TString& s); + // @cmember Distruttore + virtual ~TString(); + + // @cmember Ritorna il nome della classe + virtual const char* class_name() const; + // @cmember Ritorna l'identificatore della classe + virtual word class_id() const; + // @cmember Controlla se si tratta di una stringa valida (diversa da NULL) + virtual bool ok() const + { return _str != NULL; } + // @cmember Duplica una stringa + virtual TObject* dup() const; + // @cmember Stampa una stringa + virtual void print_on(ostream& out) const; + // @cmember Legge una stringa + virtual void read_from(istream& in); + // @cmember Ritorna il valore hash della stringa + virtual word hash() const; + + // @cmember const char * | operator const char*() | | Trasforma una stringa + // in puntatore a carattere + operator const char*() const + { return (const char*)_str; } + // @cmember Ritorna un riferimento al carattere i-esimo della stringa + char& operator[](int i) + { + CHECKD(i >= 0 && i <= _size, "Bad string subscript: ", i); + return _str[i]; + } + // @cmember Ritorna il carattere i-esimo della stringa + char operator[](int i) const + { + CHECKD(i >= 0 && i <= _size, "Bad string subscript: ", i); + return _str[i]; + } + + // @cmember Ritorna la dimensione allocata della stringa + int size() const + { return _size; } + // @cmember Ritorna la lunghezza della stringa (numero di caratteri) + int len() const + { return _str ? strlen(_str) : 0; } + // @cmember Controlla se la stringa e' vuota (TRUE se non contiene caratteri) + bool empty() const + { return *_str == '\0'; } + // @cmember Controlla se la stringa non e' vuota (TRUE se contiene caratteri) + bool not_empty() const + { return *_str != '\0'; } + // @cmember Controlla se la stringa e' vuota o contiene solo whitespace (TRUE se vuota) + bool blank() const; + + // @cmember Ritorna la posizione della prima occorrenza carattere char nell'oggetto TString + int find(char, int from = 0) const; + // @cmember Ritorna la posizione dell'ultima occorrenza carattere char nell'oggetto TString + int rfind(char) const; + // @cmember Ritorna la posizione della stringa s nell'oggetto TString + int find(const char* s, int from = 0) const; + // @cmember Sostituisce le occorrenze di

col carattere

+ int replace(char find_char, char replace_char); + + // @cmember Ritorna l'oggetto TString composto dai count caratteri da sinistra + const TString& left(int count) const; + // @cmember Ritorna l'oggetto TString composto dai count caratteri a partire da from + const TString& mid(int from, int count = -1) const; + // @cmember Ritorna la stringa da from a to (escluso) + const TString& sub(int from, int to = -1) const; + // @cmember Ritorna l'oggetto TString composto dai count caratteri da destra + const TString& right(int count) const; + + // @cmember Ritorna un oggetto TString temporaneo composto dai count caratteri da sinistra + TString sleft(int count) const + { return ((TString)left(count)); } + // @cmember Ritorna un oggetto TString temporaneo composto dai count caratteri a partire da from + TString smid(int from, int count = -1) const + { return ((TString)mid(from, count)); } + // @cmember Ritorna un oggetto TString temporaneo composto dai caratteri da from a to (escluso) + TString ssub(int from, int to = -1) const + { return ((TString)sub(from, to)); } + // @cmember Ritorna un oggetto TString temporaneo composto dai count caratteri da destra + TString sright(int count) const + { return ((TString)right(count)); } + + // @cmember Riempe la stringa con n caratteri c + TString& fill(char c, int n = -1); + // @cmember Riempe la stringa con n caratteri spazio (chiama ) + TString& spaces(int n = -1) + { return fill(' ', n); } + // @cmember Sovrascrive la stringa s dalla posizione pos + TString& overwrite(const char* s, int pos = 0, int len = 0); + // @cmember Inserisce la stringa s dalla posizione pos + TString& insert(const char* s, int pos = 0); + + // @cmember Elimina tutti i caratteri contenuti in k + TString& strip(const char* k); + // @cmember Elimina tutti gli spazi non contenuti tra apici singoli o doppi + TString& strip_spaces(); + // @cmember Elimina tutti gli spazi doppi + TString& strip_d_spaces(); + // @cmember Elimina gli spazi da sinistra o i primi n caratteri (da sinistra). + TString& ltrim(int n = 0); + // @cmember Elimina gli spazi da destra o i primi n caratteri (da destra). + TString& rtrim(int n = 0); + // @cmember Composizione di e per eliminare + // gli spazi iniziali e finali + TString& trim(); + // @cmember Aggiunge spazi a destra fino alla dimensione indicata + TString& rpad(const int n,const char c=' '); + // @cmember Aggiunge spazi a destra fino alla dimensione indicata + TString& lpad(const int n,const char c=' '); + + // @cmember Giustifica l'oggetto stringa a destra + TString& right_just(int n = -1, char c = ' '); + // @cmember Centra l'oggetto stringa + TString& center_just(int n = -1, char c = ' '); + // @cmember Giustifica l'oggetto stringa a sinistra + TString& left_just(int n = -1, char c = ' '); + + // @cmember Formatta una stringa usando il formato dato da pic + TString& picture(const char* pic, const char* s); + + // @cmember Copia n caratteri nella stringa oggetto + int strncpy(const char* s, int n); + + // @cmember Manda un output formattato alla stringa oggetto + virtual TString& format(const char* fmt, ...); + + // @cmember Tronca la stringa alla posizione n-esima. + TString& cut(int n); + + // @cmember Ritorna il buffer interno della stringa (usare con attenzione!) + char* get_buffer(int min_size = -1); + + // @cmember Converte la stringa in maiuscolo + TString& upper(int from =0, int to=-1); + // @cmember Converte la stringa in minuscolo + TString& lower(int from =0, int to=-1); + // @cmember Permette di trovare il plurale di una stringa + TString& add_plural(long num, const char * name); + + // @cmember Assegna la stringa passata con indirizzo + const TString& operator =(const TString& s) + { return set(s._str); } + // @cmember Assegna la stringa passata + const TString& operator =(const char* s) + { return set(s); } + + // @cmember Fa scorrere a sinistra la stringa e restituisce l'ultimo carattere scartato + char shift(int n=1); + // @cmember Fa scorrere a destra la stringa e restituisce l'ultimo carattere scartato + char rshift(int n=1) + {return shift(-n);} + // @cmember Concatena una stringa all'oggetto stringa + TString& operator <<(const char*); + // @cmember Concatena un carattere all'oggetto stringa + TString& operator <<(char); + // @cmember Concatena un intero all'oggetto stringa + TString& operator <<(int); + // @cmember Concatena un long all'oggetto stringa + TString& operator <<(long); + // @cmember Concatena un double all'oggetto stringa + TString& operator <<(double); + // @cmember Concatena un oggetto all'oggetto stringa + TString& operator <<(const TObject& obj); + // @cmember Concatena una stringa all'oggetto stringa (usato per aumentare l'efficienza) + TString& operator <<(const TString& str); + + + // @cmember Controlla se due stringhe sono uguali + bool operator ==(const char* s) const + { return s ? strcmp(_str, s) == 0 : empty();} + // @cmember Controlla se due stringhe sono uguali + bool operator ==(char* s) const + { return s ? strcmp(_str, s) == 0 : empty();} + // @cmember Controlla se due stringe sono uguali + bool operator ==(const TString& s) const + { return strcmp(_str, s._str) == 0; } + // @cmember Controlla se due stringhe sono diverse + bool operator !=(const char* s) const + { return s ? strcmp(_str, s) != 0 : not_empty();} + // @cmember Controlla se due stringhe sono diverse + bool operator !=(char* s) const + { return s ? strcmp(_str, s) != 0 : not_empty();} + // @cmember Controlla se due stringhe sono diverse + bool operator !=(const TString& s) const + { return strcmp(_str, s._str) != 0; } + // @cmember Controlla se una stringa e' minore di un'altra + bool operator <(const char* s) const + { return s ? strcmp(_str, s) < 0 : FALSE;} + // @cmember Controlla se una stringa e' maggiore di un'altra + bool operator >(const char* s) const + { return s ? strcmp(_str, s) > 0 : not_empty();} + // @cmember Controlla se una stringa e' maggiore o uguale ad un'altra + bool operator >=(const char* s) const + { return s ? strcmp(_str, s) >= 0 : TRUE;} + // @cmember Controlla se una stringa e' minore o uguale ad un'altra + bool operator <=(const char* s) const + { return s ? strcmp(_str, s) <= 0 : empty();} + // @cmember Controlla se una stringa e' minore di un'altra + bool operator <(const TString & s) const + { return strcmp(_str, s._str) < 0; } + // @cmember Controlla se una stringa e' maggiore di un'altra + bool operator >(const TString & s) const + { return strcmp(_str, s._str) > 0; } + // @cmember Controlla se una stringa e' maggiore o uguale ad un'altra + bool operator >=(const TString & s) const + { return strcmp(_str, s._str) >= 0; } + // @cmember Controlla se una stringa e' minore o uguale ad un'altra + bool operator <=(const TString & s) const + { return strcmp(_str, s._str) <= 0; } + // @cmember Compara due stringhe (o i primi max caratteri) + int compare(const char* s, int max = -1, bool ignorecase = FALSE) const; + // @cmember Controlla se la strinvga comincia per s + bool starts_with(const char* s, bool ignorecase = FALSE) const; +}; + +// @doc EXTERNAL + +// @class TFixed_string | Classe per la definizione di stringhe di lunghezza +// fissa e non rilocabili dinamicamente +// +// @base public | TString +class TFixed_string : public TString +// @author:(INTERNAL) Guido +{ + + // @access Protected Member +protected: + // @cmember Causa un erroe fatale + virtual void resize(int size, bool cpy); + + // @access Public Member +public: + // @cmember Costruttore + TFixed_string(const char* str, int size = -1); + // @cmember Distruttore + virtual ~TFixed_string(); + + // @cmember Manda un output formattato alla stringa oggetto + virtual TString& format(const char* fmt, ...); + + // @cmember Assegna la stringa passata con indirizzo + const TString& operator =(const TString& s) + { return set((const char*)s); } + // @cmember Assegna la stringa passata + const TString& operator =(const char* str) + { return set(str); } +}; + + +// @doc EXTERNAL + +// @class TString4 | Definisce le stringhe di 4 caratteri +// +// @base public | TFixed_string +// +// @author:(INTERNAL) Augusto +// +// @comm Questa classe e' identica alla per quanto riguarda i public member e quindi +// si rimanda a tale classe per ulteriori spiegazioni. +class TString4 : public TFixed_string +{ + char _str4[5]; + +public: + TString4(const char* s = "") : TFixed_string(_str4, 5) { set(s); } + TString4(const TString& s) : TFixed_string(_str4, 5) { set(s); } + TString4(const TString4& s) : TFixed_string(_str4, 5) { set(s); } + const TString& operator =(const char* s) { return set(s); } + const TString& operator =(const TString& s) { return set((const char*)s); } + const TString& operator =(const TString4& s) { return set((const char*)s); } +}; + + +// @doc EXTERNAL + +// @class TString8 | Definisce le stringhe di 8 caratteri +// +// @base public | TFixed_string +// +// @author:(INTERNAL) Augusto +// +// @comm Questa classe e' identica alla per quanto riguarda i public member e quindi +// si rimanda a tale classe per ulteriori spiegazioni. +class TString8 : public TFixed_string +{ + char _str8[9]; + +public: + TString8(const char* s = "") : TFixed_string(_str8, 9) { set(s); } + TString8(const TString& s) : TFixed_string(_str8, 9) { set(s); } + TString8(const TString8& s) : TFixed_string(_str8, 9) { set(s); } + const TString& operator =(const char* s) { return set(s); } + const TString& operator =(const TString& s) { return set((const char*)s); } + const TString& operator =(const TString8& s) { return set((const char*)s); } +}; + + +// @doc EXTERNAL + +// @class TString16 | Definisce le stringhe di 16 caratteri +// +// @base public | TFixed_string +class TString16 : public TFixed_string +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private member + + // @cmember:(INTERNAL) Stringa di 16 caratteri + char _str16[17]; + + // @access Public Member +public: + // @cmember Duplica una stringa di 16 caratteri + virtual TObject* dup() const { return new TString16(_str16); } + + // @cmember Costruttore + TString16(const char* s = "") : TFixed_string(_str16, 17) + { set(s); } + // @cmember Costruttore + TString16(const TString& s) : TFixed_string(_str16, 17) + { set(s); } + // @cmember Costruttore + TString16(const TString16& s) : TFixed_string(_str16, 17) + { set(s); } + // @cmember Assegna una stringa + const TString& operator =(const char* s) + { return set(s); } + // @cmember Assegna una stringa + const TString& operator =(const TString& s) + { return set((const char*)s); } + // @cmember Assegna una stringa + const TString& operator =(const TString16& s) + { return set((const char*)s); } + + // @comm Sono definite anche le classi e per le + // stringhe rispettivamente di 80 e 256 caratteri. I class member sono + // gli stessi, la differenza e' solo nel numero di caratteri della stringa. +}; + +// @doc EXTERNAL + +// @class TString80 | Definisce le stringhe di 80 caratteri +// +// @base public | TFixed_string +// +// @author:(INTERNAL) Guido +// +// @comm Questa classe e' identica alla per quanto riguarda i public member e quindi +// si rimanda a tale classe per ulteriori spiegazioni. +class TString80 : public TFixed_string +{ + char _str80[81]; + +public: + // @cmember Duplica una stringa di 80 caratteri + virtual TObject* dup() const { return new TString80(_str80); } + + TString80(const char* s = "") : TFixed_string(_str80, 81) { set(s); } + TString80(const TString& s) : TFixed_string(_str80, 81) { set(s); } + TString80(const TString80& s) : TFixed_string(_str80, 81) { set(s); } + const TString& operator =(const char* s) { return set(s); } + const TString& operator =(const TString& s) { return set((const char*)s); } + const TString& operator =(const TString80& s) { return set((const char*)s); } +}; + +// @doc EXTERNAL + +// @class TString256 | Definisce le stringhe di 256 caratteri +// +// @base public | TFixed_string +// +// @author:(INTERNAL) Guido +// +// @comm Questa classe e' identica alla per quanto riguarda i public member e quindi +// si rimanda a tale classe per ulteriori spiegazioni. +class TString256 : public TFixed_string +{ + char _str256[257]; + +public: + // @cmember Duplica una stringa di 256 caratteri + virtual TObject* dup() const { return new TString256(_str256); } + + TString256(const char* s = "") : TFixed_string(_str256, 257) { set(s); } + TString256(const TString& s) : TFixed_string(_str256, 257) { set(s); } + TString256(const TString256& s) : TFixed_string(_str256, 257) { set(s); } + const TString& operator =(const char* s) { return set(s); } + const TString& operator =(const TString& s) { return set((const char*)s); } + const TString& operator =(const TString256& s) { return set((const char*)s); } +}; + +// @doc EXTERNAL + +// @class TFilename | Classe per la gestione dei nome dei file +// +// @base public | TString +class TFilename : public TString +// @author:(INTERNAL) Guido + +{ + // @comm Nel caso di utilizzo di Windows 95 occorre cambiare le classe base in + + // @access Public Member +public: + // @cmember Costruttore + TFilename(const char* n = "") : TString(256) + { set(n); } + // @cmember Costruttore + TFilename(const TString& n) : TString(256) + { set(n); } + // @cmember Costruttore + TFilename(const TFilename& n) : TString(256) + { set(n); } + + // @cmember Assegnazione tra TFilename e stringa + const TString& operator =(const char* s) + { return set(s); } + // @cmember Assegnazione tra TFilename e TString + const TString& operator =(const TString& s) + { return set((const char*)s); } + // @cmember Assegnazione tra TFilename e TFilename + const TString& operator =(const TFilename& s) + { return set((const char*)s); } + + // @cmember Controlla il formato del nome del file + virtual bool ok() const; + + // @cmember Ritorna l'estensione del file + const char* ext() const; + // @cmember Imposta come estensione la stringa puntata da char* + void ext(const char*); + + // @cmember Concatena un nome di file ad una directory + TFilename& add(const char* n); + + // @cmember Controlla se si tratta di un path assoluto + bool is_absolute_path() const; + // @cmember Controlla se si tratta di un path relativo + bool is_relative_path() const { return !is_absolute_path(); } + // @cmember Trasforma un path da relativo ad assoluto + const TFilename& make_absolute_path(); + // @cmember Testa se il file esiste + bool exist() const; + // @cmember Cerca nel path il nome del file corrente e scrive il path assoluto in path + bool search_in_path(TFilename& path) const; + // @cmember Ritorna il nome del file + const char* name() const; + // @cmember Ritorna il nome del direttorio + const char* path() const; + // @cmember Genera il nome di un file temporaneo + const TFilename& temp(const char* prefix = NULL, const char* extension = NULL); + // @cmember Genera il nome della directory temporanea + const TFilename& tempdir(); + // @cmember Genera il nome della directory corrente + const TFilename& currdir(); + // @cmember Prepone il nome della dir custom + bool custom_path(const char* path_list = NULL); +}; + +// @doc EXTERNAL + +// @class TToken_string | Contiene una stringa formata da piu' stringhe +// separate da un carattere (di solito il pipe) +// +// @base public | TString +class TToken_string : public TString +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Carattere separatore + char _separator; + // @cmember:(INTERNAL) Puntatore all'ultimo + int _last; + + // @access Protected Member +protected: + // @cmember Inserisce l'n-esima stringa + bool set_item(const char* v, int n); + + // @access Public Member +public: + // @cmember Costruttore + TToken_string(const char* = "", char separator = '|'); + // @cmember Costruttore + TToken_string(int n, char separator = '|'); + // @cmember Costruttore + TToken_string(const TToken_string& s); + // @cmember Distruttore + ~TToken_string(); + + // @cmember Crea un duplicato della token string + virtual TObject* dup() const; + // @cmember Setta il carattere separatore a s + void separator(char s); + // @cmember Ritorna il carattere separatore + char separator() const { return _separator; } + + // @cmember Rimette all'inizio il puntatore + void restart() + { _last = empty() ? -1 : 0; } + // @cmember Assegna una stringa + const TString& operator =(const char* s) + { set(s);restart();return *this; } + // @cmember Assegna una stringa + const TString& operator =(const TString& s) + { set(s);restart();return *this; } + // @cmember Assegna una stringa + const TToken_string& operator =(const TToken_string& s); + + // @cmember Aggiunge una stringa + void add(const char* s, int n = -1); + // @cmember Aggiunge un carattere + void add(char c, int pos = -1); + // @cmember Aggiunge un long + void add(long n, int pos = -1); + // @cmember Aggiunge un intero + void add(int n, int pos = -1); + // @cmember Toglie la stringa di posizione pos + void destroy(int pos); + + // @cmember Ritorna il prossimo token + const char* get(); + // @cmember Ritorna un token + const char* get(int n); + // @cmember Ritorna un carattere (chiama ) + char get_char(int n = -1); + // @cmember Ritorna un intero (chiama ) + int get_int(int n = -1); + // @cmember Ritorna un intero esteso (chiama ) + long get_long(int n = -1); + + // TToken_string new age: const methods; + // @cmember Ritorna l'ennesimo token + bool get(int n, TString& tok) const; + // @cmember Ritorna l'ennesimo char + bool get(int n, char& tok) const; + // @cmember Ritorna l'ennesimo int + bool get(int n, int& tok) const; + // @cmember Ritorna l'ennesimo long + bool get(int n, long& tok) const; + + // @cmember Ritorna la posizione dell'item s + int get_pos(const char* s); + // @cmember Ritorna la posizione dell'item s + int get_pos(long s); + // @cmember Ritorna il numero di token presenti + int items() const; + // @cmember Controlla se tutti i token sono nulli + bool empty_items() const; +}; + +#define FOR_EACH_TOKEN(__tok, __str) \ + for (const char* __str = __tok.get(0); __str; __str = __tok.get()) +#define FOR_EACH_STR_TOKEN(__tok, __str) \ + TString __str;for (int __t=0;__tok.get(__t,__str);__t++) + +/////////////////////////////////////////////////////////// +// Mitica token string che sceglie da sola il separatore +/////////////////////////////////////////////////////////// + +class TAuto_token_string : public TToken_string +{ +protected: + TAuto_token_string& create(const char* ts); + +public: + TAuto_token_string& operator=(const char* ts) { return create(ts); } + TAuto_token_string& operator=(const TString& ts) { return create(ts); } + TAuto_token_string& operator=(const TToken_string& ts) { return create(ts); } + TAuto_token_string& operator=(const TAuto_token_string& ts) { return create(ts); } + TAuto_token_string(int sz = 50) : TToken_string(sz) { } + TAuto_token_string(const char* ts) { create(ts); } + virtual ~TAuto_token_string() { } +}; + +/////////////////////////////////////////////////////////// +// TParagraph_string +/////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @class TParagraph_string | Classe che serve per spezzare le stringhe in paragrafi +// lunghi al massimo la lunghezza fissata +// +// @base public | TToken_string +class TParagraph_string : public TToken_string +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Lunghezza massima del paragrafo + int _width; + + // @access Protected Member +protected: + // @cmember Spezza la stringa in paragrafi di lunghezza massima fissata + void tokenize(); + + // @access Public Member +public: + // @cmember Costruttore + TParagraph_string(const char* s, int width); + + // @cmember Distruttore + virtual ~TParagraph_string() { } + + // @cmember Assegna una stringa + const TString& operator =(const char* s); + // @cmember Assegna un oggetto stringa + const TString& operator =(const TString & s) + { return operator=((const char *) s);} + // @cmember Permette di assegnare la lunghezza massima del paragrafo + void set_width(int width) + { _width = width; } +}; + +/////////////////////////////////////////////////////////// +// DES TString_array +/////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @class TString_array | Array di stringhe +// +// @base public | TArray +class TString_array : public TArray +// @author:(INTERNAL) Guido +{ + // @access Public Member +public: + // @cmember Ritorna la stringa n dell'array (se non c'e' ritorna errore) + TToken_string& row(int n) + { return (TToken_string&)operator[](n); } + // @cmember Ritorna la stringa n dell'array (se non c'e' ritorna errore) + const TToken_string& row(int n) const + { return (TToken_string&)operator[](n); } + // @cmember Restituisce il puntatore alla stringa n dell'array (NULL se non esiste) + TToken_string* rowptr(int n) + { return (TToken_string*)objptr(n); } + // @cmember assegnamento di un array + const TString_array& operator=(const TString_array& a); + // @cmember Aggiunge una Token string all'array (chiama ) + int add(TToken_string* s, int n = -1) + { return TArray::add(s, n); } + // @cmember Aggiunge un oggetto stringa all'array (chiama ) + int add(const TToken_string& s, int n = -1); + // @cmember Aggiunge una stringa all'array (chiama ) + int add(const char* s, int n = -1); + // @cmember Cerca una stringa nell'array + int find(const char* s, int from = 0) const; + // @cmember Ordina alfabeticamente l'array + void sort(bool ascendig = TRUE); + + // @cmember Costruttore + TString_array(int size = 8) : TArray(size) + {} + // @cmember Distruttore + virtual ~TString_array() + {} +}; + +TString& user(); + +TToken_string& get_tmp_string(int len = -1); + +const TToken_string& empty_string(); +#define EMPTY_STRING empty_string() + +#define FOR_EACH_ARRAY_ROW(__arr, __r, __riga) \ + TToken_string* __riga; \ + for (int __r = (__arr).first(); \ + __riga = (TToken_string*)(__arr).objptr(__r); \ + __r = (__arr).succ(__r)) + +#define FOR_EACH_ARRAY_ROW_BACK(__arr, __r, __riga) \ + TToken_string* __riga; \ + for (int __r = (__arr).last(); \ + __riga = (TToken_string*)(__arr).objptr(__r); \ + __r = (__arr).pred(__r)) + +const char SLASH = +#if XVT_OS == XVT_OS_WIN32 +'\\'; +#else +'/'; +#endif + +#endif + diff --git a/omnia/utility.cpp b/omnia/utility.cpp new file mode 100755 index 000000000..b8d51bfb0 --- /dev/null +++ b/omnia/utility.cpp @@ -0,0 +1,454 @@ +#include +#include +#include +#include +#include +#include + +#include "strings.h" +#include "utility.h" + +// @doc EXTERNAL + +// @func Permette di copiare un file +// +// @rdesc Ritorna il risultato dell'operazione: +// +// @flag TRUE | Se l'operazione e' stata effettuata con successo +// @flag FALSE | Se l'operazione non e' stata effettuata con successo +bool fcopy( + const char* orig, // @parm Nome del file di origine + const char* dest, // @parm Nome del file di destinazione + bool append) // @parm Controllo per aggiungere il contenuto del + // file

in coda al file

(default FALSE) + + // @comm Nel caso vengano ravvisati degli errori durante l'operazione vengono + // creati dei box di comunicazione che indicano la causa del problema +{ + CHECK(orig && *orig && dest && *dest, "fcopy: Invalid file name"); + + const char* const rflag = "rb"; + const char* wflag = append ? "ab" : "wb"; + + // Copia il file su se stesso? + if (stricmp(orig, dest) == 0) + return TRUE; // Or FALSE? + + FILE* i = fopen(orig, rflag); + if (i == NULL) + return error_box("Impossibile leggere il file %s\nda copiare in %s", orig, dest); + + FILE* o = fopen(dest, wflag); + if (o == NULL) + { + fclose(i); + return error_box("Impossibile creare il file %s\nper copiare il file %s", dest, orig); + } + + const int size = 16*1024; + TString buffer(size); + + bool ok = TRUE; + while (ok) + { + const word letti = fread(buffer.get_buffer(), 1, size, i); + ok = fwrite(buffer.get_buffer(), 1, letti, o) == letti; + if (letti < size) break; + } + + if (!ok) + error_box("Errore di scrittura: controllare lo spazio libero sul disco!"); + + fclose(o); + fclose(i); + + return ok; +} + +// @doc EXTERNAL + +// @func Controlla l'esistenza di un file +// +// @rdesc Ritrona i seguenti valori: +// +// @flag TRUE | Se il file esiste +// @flag FALSE | Se il file non esiste +bool fexist( + const char* file) // @parm Nome del file di cui contrallare l'esistenza +{ + int err = access(file, 0x00); + return err == 0; +} + +long fsize(const char* name) +{ + long s = 0; + if (name && *name) + { + FILE* f = fopen(name, "r"); + if (f != NULL) + { + fseek(f, 0, SEEK_END); + s = ftell(f); + fclose(f); + } + } + return s; +} + + +// @doc EXTERNAL + +// @func Permette di creare una directory +// +// @rdesc Ritorna il risultato dell'operazione +// +// @flag TRUE | Se l'operazione e' avvenuta con successo +// @flag FALSE | Se l'operazione non e' riuscita +bool make_dir( + const char* dir) // @parm Nome della directory da creare +{ + int res = mkdir(dir); + return res == 0; +} + +// @doc EXTERNAL + +// @func Ritorna la lista dei file il cui nome corrisponde alla stringa (con caratteri +// jolly) passata. +// +// @rdesc Ritorna il numero di file che soddisfano la condizione passata (numero di elementi +// di result) +int list_files( + const char* filelist, // @parm Stringa contenente la maschera di estrazione + TString_array& result) // @parm Array da riempire con la lista dei file + +{ +/* + TFilename dir(filelist); + for (int i = dir.len()-1; i >= 0; i--) + if (dir[i] == '/' || dir[i] == '\\' || dir[i] == ':') break; + + TFilename mask(dir.mid(i+1)); + dir.cut(i > 0 ? i+1 : 0); + + xvt_fsys_save_dir(); + + if (dir.not_empty()) + { + DIRECTORY directory; xvt_fsys_convert_str_to_dir(dir.get_buffer(), &directory); + BOOLEAN ok = xvt_fsys_set_dir(&directory); + if (!ok) + { + error_box("Impossibile entrare in %s", (const char*)dir); + return 0; + } + } + + SLIST files = xvt_fsys_list_files("", mask.get_buffer(), FALSE); + const int count = xvt_slist_count(files); + + for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e)) + { + char* f = xvt_slist_get(files, e, NULL); + if (dir.not_empty()) + { + mask = dir; + mask.add(f); + result.add(mask); + } + else + result.add(f); + } + + xvt_slist_destroy(files); + xvt_fsys_restore_dir(); + + return count; +*/ + return 0; +} + +// Certified 99% +// @doc EXTERNAL + +// @func Permette di ritornare una stringa formattata +// +// @rdesc Ritorna la stringa desiderata +char* format( + const char* fmt, // @parm Formato che deve essere dato alla stringa + ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Il funzionamento e' come la del C, solo che non e' necessario passare la + // stringa di destinazione alla funzione. +{ + va_list pars; + + char buf[512]; + va_start(pars, fmt); + const int tot = vsprintf(buf, fmt, pars); + va_end(pars); + + CHECK(tot < 512, "Ue'! Ma quanto scrivi?"); + TString& tmp = get_tmp_string(); + tmp = buf; + + return tmp.get_buffer(); +} + +// @doc EXTERNAL + +// @func Converte la coppia nome-parametro in una stringa che identifica il programma +// +// @rdesc Ritorna la stringa identificante il programma +const char* cmd2name( + const char* argv0, // @parm Nome del programma + const char* argv1) // @parm Nome del parametro (default "") +{ + TFilename app(argv0); + app = app.name(); + if (argv1 && *argv1) + app << ' ' << argv1; + else + { + const char* space = strchr(argv0, ' '); + if (space != NULL) + app << space; + } + + app.lower(); + + const int par = app.find(" -"); + const int num = par > 0 ? atoi(app.mid(par+2))+1 : 1; + + const char c = (num > 9) ? ('a'+num-10) : ('0'+num); + app.cut(3); + app << c << "00"; + + TString& tmp = get_tmp_string(); + tmp = app; + return tmp; +} + + +/////////////////////////////////////////////////////////// +// Conversione in cifre romane +/////////////////////////////////////////////////////////// + +HIDDEN const char * cifre_romane = "IVXLCDM@"; +HIDDEN const int valori_cifre [] = { 1, 5, 10, 50, 100, 500, 1000, -1 }; + +HIDDEN int ctoi(char c) +{ + if (c == '\0') return 0; + + c = toupper(c); + for (int i = 0; cifre_romane[i]; i++) + if (cifre_romane[i] == c) return valori_cifre[i]; + + return -1; +} + +// @doc EXTERNAL + +// @func Converte una cifra romana in intero normale +// +// @rdesc Ritorna l'equivalente in numeri della cifra romane +int rtoi( + const char * val) // @parm Stringa contenente la cifra scritta in numeri romani +{ + if (val == NULL) return 0; + + int tot = 0; + int value = ctoi (val[0]); + for (int i = 1; value > 0; i++) + { + const int next_val = ctoi(val[i]); + if (value < next_val) tot -= value; + else tot += value; + value = next_val; + } + + return (value == 0) ? tot : -1; +} + +// @doc EXTERNAL + +// @func Converte un numero intero nell'equivalente cifra romana +// +// @rdesc Ritorna una stringa contenente la cifra romana +const char* itor( + int num) // @parm Intero da convertire in cifra romana +{ + HIDDEN char roman_string[16]; + int cifra = 0; + + for (int pos = 7; pos--;) + { + int val = valori_cifre[pos]; + int quanti = num / val; + if (quanti < 4) + { + if ((pos & 1) && quanti == 1 && (num/valori_cifre[pos-1]) == 9) + { + roman_string[cifra++] = cifre_romane[pos-1]; + roman_string[cifra++] = cifre_romane[pos+1]; + val = valori_cifre[pos-1]; + quanti = 9; + } + else for (int i = 0; i < quanti; i++) + roman_string[cifra++] = cifre_romane[pos]; + } + else + { + roman_string[cifra++] = cifre_romane[pos]; + roman_string[cifra++] = cifre_romane[pos+1]; + } + + num -= quanti * val; + } + + roman_string[cifra] = '\0'; + return roman_string; +} + +// @doc EXTERNAL + +// @func Permette di codificare i caratteri di escape +// +// @rdesc Ritorna il carattere codificato +const char* esc( + const char* s) // @parm Stringa da codificare +{ + const char *s1 = s == NULL ? "" : s; + char* encoded = get_tmp_string().get_buffer(strlen(s)); + char* s2 = encoded; + while (*s1) + { + if (*s1 == '\\') + { + s1++; + switch (tolower(*s1)) + { + case 'b' : *s2++ = '\b'; break; + case 'e' : *s2++ = '\033'; break; + case 'f' : *s2++ = '\f'; break; + case 'n' : *s2++ = '\n'; break; + case 'r' : *s2++ = '\r'; break; + case 't' : *s2++ = '\t'; break; + default : + { + if (isdigit(*s1)) + { + int base = 10; + if (*s1 == '0') + { + s1++; + if (tolower(*s1) == 'x') + { + s1++; + base = 16; + } + else + base = 8; + } + *s2 = 0; + char c = tolower(*s1); + while (isdigit(c) || (base == 16 && c >= 'a' && c <= 'f')) + { + *s2 *= base; + if (isdigit(*s1)) *s2 += (*s1 - 48); + else *s2 += (*s1 - 'a' + 10) & 0x0F; + s1++; + c = tolower(*s1); + } + s2++; s1--; + } + else *s2++ = *s1; + } + } + } + else + if (*s1 == '^') + { + s1++; + *s2++ = (tolower(*s1) - 'a' + 1); + } + else *s2++ = *s1 ; + s1++; + } + *s2 = '\0'; + return encoded; +} + +const char* unesc( + const char* s) // @parm Stringa da decodificare +{ + char *decoded = get_tmp_string().get_buffer(strlen(s)*4); + char* s2 = decoded; + for (const char *s1 = s; *s1; s1++) + { + const char& c = *s1; + if (c >= '\0' && c < ' ') + { + switch(c) + { + case '\n': + *s2++ = '\\'; *s2++ = 'n'; + break; + case '\r': + *s2++ = '\\'; *s2++ = 'r'; + break; + case '\t': + *s2++ = '\\'; *s2++ = 't'; + break; + default: + *s2++ = '\\'; *s2++ = '0'; *s2++ = 'x'; + sprintf(s2, "%02x", int(c)); s2 += 2; + break; + } + } + else + *s2++ = c; + } + *s2 = '\0'; + return decoded; +} + + +HIDDEN const char * const encryption_key = "QSECOFR-"; + +// @doc EXTERNAL + +// @func Permette di criptare una parola +// +// @rdesc Ritorna la stringa criptata +const char * encode( + const char * data) // @parm Stringa da criptare + + // @xref +{ + char* tmp = get_tmp_string(50).get_buffer(); + for (int i = 0; data[i]; i++) + tmp[i] = data[i] + (i < 8 ? encryption_key[i] : data[i - 8]); + tmp[i] = '\0'; + return tmp; +} + +// @doc EXTERNAL + +// @func Permette di decodificare una stringa criptata +// +// @rdesc Ritorna la stringa in chiaro +const char * decode( + const char * data) // @parm Stringa criptata da tradurre + + // @xref +{ + char* tmp = get_tmp_string(50).get_buffer(); + for (int i = 0; data[i]; i++) + tmp[i] = data[i] - (i < 8 ? encryption_key[i] : tmp[i - 8]); + tmp[i] = '\0'; + return tmp; +} + diff --git a/omnia/utility.h b/omnia/utility.h new file mode 100755 index 000000000..ad0cd178d --- /dev/null +++ b/omnia/utility.h @@ -0,0 +1,37 @@ +#ifndef __UTILITY_H +#define __UTILITY_H + +#ifndef __STDTYPES_H +#include "stdtypes.h" +#endif + +class TString_array; +class TFilename; + +char* format (const char* fmt, ...); +const char* cmd2name(const char* argv0, const char* argv1 = ""); +int rtoi(const char * roman); +const char* itor(int i); +bool fcopy(const char* orig, const char* dest, bool append=FALSE); +bool fexist(const char* file); +long fsize(const char* file); + +bool make_dir(const char* file); +int list_files(const char* mask, TString_array& result); + +const char* encode(const char* data); +const char* decode(const char* data); + +inline bool is_slash(char s) // @parm Carattere da confrontare +{ return s == '\\' || s == '/'; } + +inline bool is_not_slash(char s) // @parm Carattere da confrontare +{ return s != '\\' && s != '/'; } + +const char* esc(const char* str); // Trasforma le sequenze "\n" nel carattere '\n' +const char* unesc(const char* str); // Trasforma i caratteri '\n' nella sequenza "\n" + +#define ODD(x) (x & 1) +#define EVEN(x) !(x & 1) + +#endif /* __UTILITY_H */ diff --git a/omnia/xml.cpp b/omnia/xml.cpp new file mode 100755 index 000000000..d28203752 --- /dev/null +++ b/omnia/xml.cpp @@ -0,0 +1,504 @@ +#include +#include +#include +#include + +#include "xml.h" + +/////////////////////////////////////////////////////////// +// 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 (isdigit((*this)[0])) + { + 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::GetIntAttr(const char* strAttr) const +{ + return atoi(GetAttr(strAttr)); +} + +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(7), 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/omnia/xml.h b/omnia/xml.h new file mode 100755 index 000000000..e862686be --- /dev/null +++ b/omnia/xml.h @@ -0,0 +1,86 @@ +#ifndef __XML_H +#define __XML_H + +#ifndef __ASSOC_H +#include "assoc.h" +#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; + int GetIntAttr(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 +