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
This commit is contained in:
guy 2004-01-08 15:08:43 +00:00
parent f577cf2f07
commit c95157e55e
18 changed files with 6500 additions and 0 deletions

240
omnia/Omnia0.cpp Executable file
View File

@ -0,0 +1,240 @@
#include <windows.h>
#include <fstream.h>
#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 <Input> o <Output>");
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 <Record>");
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;
}

877
omnia/array.cpp Executable file
View File

@ -0,0 +1,877 @@
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
#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.
// <nl>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 <mf TArray::pack> 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.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
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.
// <nl>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.
// <nl>Se e' stato passato un indice minore della dimensione dell'array,
// viene aumentata automaticamente la dimensione dell'array stesso tramite
// la chiamata alla funzione <mf TArray::resize>.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::insert>
{
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.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::add>
{
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
// <mf TArray::pack> (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 <gt>0 | se <p this> <gt> <p s>
// @flag 0 | se <p this> == <p s>
// @flag <lt>0 | se <p this> <lt> <p s>
// @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 <mf TArray::sort> 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 <t COMPARE_FUNCTION>
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 <c Tsortable>
{
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 <mf TArray::pack> 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.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
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 <mf TBit_array::last_one> <mf TBit_array::first_one>
{
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 <mf TBit_array::first_one> <mf TBit_array::ones>
{
for (word i = _size; i--;)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 8; j--;)
if ((1<<j) & b) return (long(i)<<3) + j;
}
}
return -1;
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Ritorna la posizione del primo 1 nell'array
//
// @rdesc Ritorna i seguenti valori:
//
// @flag >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 <mf TBit_array::last_one> <mf TBit_array::ones>
{
for (word i = 0; i < _size; i++)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 0; j < 8; j++)
if ((1<<j) & b) return (long(i)<<3)+j;
}
}
return -1;
}
// @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 TBit_array::ok() const
// @comm Controlla se la dimensione dell'array e' maggiore di 0 e se esistono
// degli elementi diversi da NULL
{
return _bit != NULL && _size > 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;
}

324
omnia/array.h Executable file
View File

@ -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 <c TObject> da passare al metodo sort dei <c TArray>
typedef int (*COMPARE_FUNCTION)(const TObject**, const TObject**);
// @doc EXTERNAL
// @type CONDITION_FUNCTION | Prototipo funzione di ricerca/filtro
// per i derivati di <c TObject> da passare ai metodi dei <c TContainer>
typedef bool (*CONDITION_FUNCTION) ( const TObject& );
// @doc EXTERNAL
// @type OPERATION_FUNCTION | Prototipo funzione attuatore
// da passare ai metodi sort dei <c TContainer>
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 <t CONDITION_FUNCTION>)
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 <t OPERATION_FUNCTION>
virtual void for_each( OPERATION_FUNCTION );
// @cmember Cerca il successivo elemento che soddisfa la <t OPERATION_FUNCTION>
// per ogni elemento di <t CONDITION_FUNCTION>
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 <mf TArray::resize>)
TArray(int arraysize);
// @cmember Costruttore. Crea un array (non chiama <mf TArray::resize>)
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 <t COMPARE_FUNCTION>
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 <c TArray> 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 <p n>
word index(long n) const
{ return word(n >> 3); }
// @cmember Ritorna la posizione del bit <p n> 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 <mf TBit_array::resize>)
TBit_array(long size = 0);
// @cmember Costruttore. Crea un array di (chiama <mf TBit_array::copy>)
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

450
omnia/assoc.cpp Executable file
View File

@ -0,0 +1,450 @@
#include <stdlib.h>
#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 <p k>
//
// @rdesc Ritorna l'oggetto corrispondente alla chiave passate come parametro.
// <nl>Il parametro <p isnew> 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 <p k>,
// nel caso non venga trovato <p isnew> ritorna TRUE (si tratta di un
// oggetto nuovo) e viene inserito nella tabella se il parametro <p insert>
// 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 <p force>:
// <nl>se <p force> = TRUE lo sostituisce e ritorna TRUE,
// <nl>se <p force> = FALSE non sostituisce e ritorna TRUE,
// <nl>altrimenti ritorna FALSE.
// <nl><nl>Nel caso l'oggetto da aggiungere venga passato per indirizzo
// la funzione aggiunge una copia dell'oggetto e quindi deve essere
// definita <mf TObject::dup>
{
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 <p k> 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 <p key>. 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 <p key>
// @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 <mf TAssoc_array::get_hashobj>
{
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
// <mf TAssoc_array::objptr>
//
// @xref <mf TAssoc_array::get>
{
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();
}

182
omnia/assoc.h Executable file
View File

@ -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 <mf TAssoc_array::find>)
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 <c TString_array> 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

181
omnia/checks.cpp Executable file
View File

@ -0,0 +1,181 @@
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#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 <p fmt>
// @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 <p fmt>
// @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 <p fmt>
// @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 <p fmt>
// @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 <p fmt>
{
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 <p fmt>
// @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 <p fmt>
// @comm Se si opera in ambiente Windows crea la finestra con i bottoni SI e NO
// e l'icona col punto di domanda.
// <nl>A differenza della <m yesno_box> 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 <m yesno_box> <m yesnofatal_box>
{
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 <p fmt>
// @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 <m yesno_box> <m yesnofatal_box>
{
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 <p fmt>
// @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;
}

95
omnia/checks.h Executable file
View File

@ -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 <m fatal_box> 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 <p p> e' FALSE.
// <nl>Utilizzata in fase di debug (definire il simbolo DBG in compilazione).
//
// @xref <m CHECKS> <m CHECKD>
// @doc EXTERNAL
// @msg CHECKS | Macro che richiama una <m fatal_box> 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 <p p> e' FALSE. Oltre al messaggio passato in <p m>
// stampa anche una strina aggiuntiva passata in <p s0>.
// <nl>Utilizzata in fase di debug (definire il simbolo DBG in compilazione).
//
// @xref <m CHECK> <m CHECKD>
// @doc EXTERNAL
// @msg CHECKD | Macro che richiama una <m fatal_box> 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 <p p> e' FALSE. Oltre al messaggio passato in <p m>
// stampa anche un numero passato in <p d0>.
// <nl>Utilizzata in fase di debug (definire il simbolo DBG in compilazione).
//
// @xref <m CHECKS> <m CHECK>
// @doc EXTERNAL
// @msg CHECKD | Macro che richiama una <m yesnofatal_box> per stampare messaggi d'errore a video
#define NFCHECK yesnofatal_box
// @xref <m CHECKS> <m CHECK>
#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 <m __trace>
#define TRACE __trace
#else
#define TRACE 1 ? 0 : __trace
#endif
#endif // __CHECKS_H

71
omnia/classes.h Executable file
View File

@ -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

89
omnia/object.cpp Executable file
View File

@ -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);
}

268
omnia/object.h Executable file
View File

@ -0,0 +1,268 @@
#ifndef __OBJECT_H
#define __OBJECT_H
#ifndef __IOSTREAM_H
#include <iostream.h>
#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 <p cid>
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 <p cid>
virtual bool is_kind_of(word cid) const;
// @cmember Controlla se si tratta di un oggetto valido (sempre FALSE)
virtual bool ok() const;
// @xref <c TObject>
};
//////////////////////////////////////////////////////////////////////////////
// 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
// <nl>Ritorna: <gt>0 se <p this> <gt> <p s>
// <nl> 0 se <p this> == <p s>
// <nl> <lt>0 se <p this> <lt> <p s>
// <nl> 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 <p cid>
virtual bool is_kind_of(word cid) const;
// @cmember Distruttore
virtual ~TSortable()
{}
};
//////////////////////////////////////////////////////////////////////////////
// inline functions
//////////////////////////////////////////////////////////////////////////////
// @doc EXTERNAL
// @func inline ostream& | operator <lt><lt> | 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 <gt><gt> | 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 <gt> | Controlla se un oggetto e' maggiore dell'altro
//
// @rdesc Ritorna i seguenti valori:
//
// @flag TRUE | Se <p a> e' maggiore di <p b>
// @flag FALSE | Se <p b> e' maggiore o uguale a <p 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 <lt> | Controlla se un oggetto e' minore dell'altro
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore di <p b>
// @flag FALSE | Se <p b> e' minore o uguale a <p 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 <gt>= | Controlla se un oggetto e' maggiore o uguale all'altro
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' maggiore o uguale a <p b>
// @flag FALSE | Se <p b> e' maggiore <p 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 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 <lt>= | Controlla se un oggetto e' minore o uguale all'altro
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore o uguale a <p b>
// @flag FALSE | Se <p b> e' minore <p 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 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

2
omnia/stdtypes.cpp Executable file
View File

@ -0,0 +1,2 @@

59
omnia/stdtypes.h Executable file
View File

@ -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

1841
omnia/strings.cpp Executable file

File diff suppressed because it is too large Load Diff

740
omnia/strings.h Executable file
View File

@ -0,0 +1,740 @@
#ifndef __STRINGS_H
#define __STRINGS_H
#ifndef _INC_STRING
#include <string.h>
#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 <p find_char> col carattere <p replace_char>
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 <mf TString::resize>)
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 <mf TString::ltrim> e <mf TString::rtrim> 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 <c TString16> 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 <c TString16> 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 <c TString80> e <c TString256> 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 <c TString16> 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 <c TString16> 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 <c TString256>
// @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 <mf TToken_string::get>)
char get_char(int n = -1);
// @cmember Ritorna un intero (chiama <mf TToken_string::get>)
int get_int(int n = -1);
// @cmember Ritorna un intero esteso (chiama <mf TToken_string::get>)
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 <mf TArray::add>)
int add(TToken_string* s, int n = -1)
{ return TArray::add(s, n); }
// @cmember Aggiunge un oggetto stringa all'array (chiama <mf TArray::add>)
int add(const TToken_string& s, int n = -1);
// @cmember Aggiunge una stringa all'array (chiama <mf TArray::add>)
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

454
omnia/utility.cpp Executable file
View File

@ -0,0 +1,454 @@
#include <ctype.h>
#include <direct.h>
#include <io.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#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 <p dest> in coda al file <p orig> (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 <p fmt>
// @comm Il funzionamento e' come la <f sprintf> 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 <f decode>
{
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 <f encode>
{
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;
}

37
omnia/utility.h Executable file
View File

@ -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 */

504
omnia/xml.cpp Executable file
View File

@ -0,0 +1,504 @@
#include <ctype.h>
#include <fstream.h>
#include <stdlib.h>
#include <strstrea.h>
#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 </SOAP-ENV>
{
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;
}

86
omnia/xml.h Executable file
View File

@ -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