#include #ifdef WIN32 #include #include #endif #include #include #include #ifndef INCSTR_H #include #endif #include #include #include #include #include #include // @doc EXTERNAL // @func Ritorna il nome dell'utente attuale // // @rdesc Ritorno il nome dell'utente attuale TString& user() { static TString8 _user; return _user; } const TToken_string& empty_string() { static TToken_string _ts(1); return _ts; } // Most descriptions will fit in fifty characters const int DEFAULT_SIZE = 50; const int MAX_SIZE = 32000; inline bool is_space(char c) { return c >= '\t' && c <= ' '; } // Certified 99% // @doc EXTERNAL // // @mfunc Cambia la dimensione della stringa eventualmente preservandone il contenuto iniziale void TString::resize( int size, // @parm Nuova dimensione della stringa bool cpy) // @parm Se TRUE mantiene il contenuto della stringa e alloca // nuovo spazio // @comm Non funziona con le stringhe static e per valori negativi di

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

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

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

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

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

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

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

caratteri a partire // da

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

cartteri da

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

a

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

a

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

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

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

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

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

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

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

la stringa viene // riempita col carattere

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

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

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

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

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

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

permette di stabilire la // corretta sintassi della stringa

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

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

dalla posizione

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

fino alla lunghezza di

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

la stringa

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

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

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

ritorna il prossimo Token // (come se

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

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

bool TToken_string::get( int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) TString& tok) const // @parm Stringa da ritornare // @syntax const char* get(TString& str, int n); // // @xref { CHECK(_separator, "Corrupted TToken_string: NULL separator"); if (n < 0) { const char* sep = strrchr(_str, _separator); tok = sep ? sep+1 : _str; return tok.not_empty(); } int sep = 0; const char* s; for (s = _str; *s && sep < n; s++) if (*s == _separator) sep++; bool found = sep == n; if (found) { char* p = strchr(s, _separator); if (p == NULL) { tok = s; found = tok.not_empty(); } else { *p = '\0'; tok = s; *p = _separator; } } else tok.cut(0); return found; } bool TToken_string::get( int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) char& tok) const // @parm char da ritornare { TString16 str; bool found = get(n, str); tok = found ? str[0] : '\0'; return found; } bool TToken_string::get( int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) int& tok) const // @parm int da ritornare { TString16 str; bool found = get(n, str); tok = found ? atoi(str) : 0; return found; } bool TToken_string::get( int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) long& tok) const // @parm long da ritornare { TString16 str; bool found = get(n, str); tok = found ? atol(str) : 0L; return found; } bool TToken_string::get( int n, // @parm Posizione del token da ritornare (0 = primo, -1 = prossimo, -2 = ultimo, n = n-simo) real& tok) const // @parm real da ritornare { TString80 str; bool found = get(n, str); if (found) tok = real(str); else tok = ZERO; return found; } // Certified 90% bool TToken_string::set_item(const char* v, int n) { CHECK(_separator, "Corrupted TToken_string: NULL separator"); TString& spark = get_tmp_string(); int sep = 0, i; for (i = 0; sep < n && _str[i]; i++) if (_str[i] == _separator) sep++; if (sep < n) // Aggiunge items mancanti prima della posizione n { for (;sep < n; sep++) *this << _separator; *this << v; return FALSE; } int e = find(_separator, i); if (e < 0) e = len(); spark = _str+e; // Salva items seguenti cut(i); // Considera solo items precedenti *this << v << spark; // Aggiunge item desiderato e seguenti return TRUE; } // Certified 80% int TToken_string::get_pos(const char* s) { const char* item; restart(); for (int i = 0; (item = get()) != NULL; i++) if (strcmp(item, s) == 0) return i; return -1; } // Certified 80% int TToken_string::get_pos(long n) { char s[16]; sprintf(s, "%ld", n); return get_pos(s); } // Certified 90% bool TToken_string::empty_items() const { for (const char* c = _str; *c; c++) if (!is_space(*c) && *c != _separator) return FALSE; return TRUE; } // Certified 80% int TToken_string::items() const { int t = 0; if (not_empty()) { t++; for (const char* s = _str; *s; s++) if (*s == _separator) t++; } return t; } // Certified 99% // @doc EXTERNAL // @mfunc Aggiunge un elemento alla token string void TToken_string::add( const char* s, // @parm Stringa da aggiungere int pos) // @parm Posizione nella quale aggiungere l'elemento // (default aggiunge come ultimo elemento) // @parm char | c | Caratter da aggiungere // @parm long | n | Long da aggiungere // @parm int | n | Intero da aggiungere // @syntax void add(const char* s, int n = -1); // @syntax void add(char c, int pos = -1); // @syntax void add(long n, int pos = -1); // @syntax void add(int n, int pos = -1); // // @comm Permette, a seconda del parametro passato, di aggiungere alla Token // string un nuovo elemnto gia' completo del carattere di separazione { if (s == NULL || *s == '\0') s = " "; if (pos < 0) { if (not_empty()) *this << _separator; *this << s; } else set_item(s, pos); if (_last < 0) _last = 0; } // Certified 100% void TToken_string::add(char c, int pos) { const char s[2] = { c, '\0' }; add(s, pos); } // Adds an integer value to the token string // Certified 100% void TToken_string::add(long n, int pos) { char s[16]; sprintf(s, "%ld", n); add(s, pos); } // Adds an integer value to the token string // Certified 100% void TToken_string::add(int n, int pos) { char s[16]; sprintf(s, "%d", n); add(s, pos); } // Certified 50% void TToken_string::destroy(int n) { if (_last == -2) return ; if (n < 0) { char* s = strrchr(_str, _separator); if (s != NULL) *s = '\0'; } else { int sep = 0; char * s; for (s = _str; sep < n && *s; s++) if (*s == _separator) sep++; if (sep >= n) { const char* p = strchr(s, _separator); *s = '\0'; if (p != NULL) strcat(s, p+1); } } restart(); } /////////////////////////////////////////////////////////// // TAuto_token_string /////////////////////////////////////////////////////////// TAuto_token_string& TAuto_token_string::create(const char* ts) { // Copia la stringa set(ts); // Calcola il separatore for (const char* s = ts; s && *s; s++) { if (strchr("|?\t\n^;,!&+", *s) != NULL) { separator(*s); break; } } return *this; } /////////////////////////////////////////////////////////// // Paragraph string /////////////////////////////////////////////////////////// TParagraph_string::TParagraph_string(const char* s, int width) : TToken_string(s, '|'), _width(width) { tokenize(); } const TString& TParagraph_string::operator =(const char* s) { TToken_string::operator=(s); tokenize(); return *this; } /* void TParagraph_string::tokenize() { int last_space = -1, last_start = 0; int num_chars = 0; const int l = len(); TString stmp,swork; // stringhe di lavoro for (int start = 0; start < l;) { switch (_str[start]) { case '\r': case '\n': last_space = start; num_chars = _width; break; case ' ' : last_space = start; num_chars++; break; default : num_chars++; break; } if (num_chars == _width && (start < l-1)) { int num_of_chars_in_row = (last_space+1) - last_start; if (num_of_chars_in_row <= 0) num_of_chars_in_row = _width; // Se non ci sono spazi tronca la stringa a 25 swork = mid(last_start,num_of_chars_in_row); stmp << swork.trim(); stmp << '|'; last_space = num_chars = 0; // start = start - (_width - num_of_chars_in_row); // riporta indietro (toglie il numero di caratteri effettivi della riga) start = last_start + num_of_chars_in_row; last_start = start; } else start++; } swork=mid(last_start,l-last_start); swork.trim(); stmp << swork; if (stmp.empty()) stmp = _str; TToken_string::operator=(stmp); } */ void TParagraph_string::tokenize() { if (not_empty()) { TToken_string tmp; int start = 0; int last_space = -1; const int length = len(); for (int i = start; i <= length; i++) { int add_now = -1; switch(_str[i]) { case ' ': case '\t': last_space = i; break; case '\r': case '\n': case '\0': add_now = i; break; default: if (i - start >= _width) { if (last_space > start) add_now = last_space; else add_now = i; } break; } if (add_now >= start) { TString256 tok = sub(start, add_now); tok.rtrim(); // Preserva gli spazi iniziali dopo un a capo forzato da \n tmp.add(tok); start = add_now + (_str[add_now] <= ' '); last_space = start; } } tmp.rtrim(); TToken_string::operator=(tmp); } } /////////////////////////////////////////////////////////// // TString_array /////////////////////////////////////////////////////////// int TString_array::add(const char* s, int n) { if (objptr(n) == NULL) n = TArray::add(new TToken_string(s), n); else row(n) = s; return n; } int TString_array::add(const TToken_string& s, int n) { if (objptr(n) == NULL) n = TArray::add(s, n); else row(n) = s; return n; } const TString_array& TString_array::operator=(const TString_array& a) { destroy(); for (int i = a.last(); i >= 0; i = a.pred(i)) { const TToken_string& s = a.row(i); add(s, i); } return a; } // @doc EXTERNAL // @mfunc Cerca una stringa nell'array // // @rdesc Ritorna la posizione nell'array in cui si trova la stringa (-1 se non // e' stata trovata) int TString_array::find( const char* s, // @parm Stringa da cercare int from) const // @parm Posizione dalla quale cercare la stringa { int found = -1; for (int i = from; i < items(); i++) if (row(i).compare(s, -1, TRUE) == 0) { found = i; break; } return found; } HIDDEN int ascending_string(const TObject** o1, const TObject** o2) { const TString* s1 = (const TString*)*o1; const TString* s2 = (const TString*)*o2; return strcmp(*s1, *s2); } HIDDEN int descending_string(const TObject** o1, const TObject** o2) { return -ascending_string(o1, o2); } void TString_array::sort(bool ascending) { TArray::sort(ascending ? ascending_string : descending_string); } // Temporary strings generator: a little step for a man, a big step for campo! TToken_string& get_tmp_string(int len) { static TString_array ararar(128); static int next = 0; TToken_string* str = (TToken_string*)ararar.objptr(next); if (str == NULL) { str = new TToken_string(len); ararar.add(str, next); } if (str->size() < len) str->spaces(len); str->cut(0); if (++next >= ararar.size()) next = 0; return *str; }