diff --git a/omnia/Omnia0.cpp b/omnia/Omnia0.cpp index 01c1414ca..0a4ffbdb5 100755 --- a/omnia/Omnia0.cpp +++ b/omnia/Omnia0.cpp @@ -1,26 +1,311 @@ #include #include +#include "expr.h" #include "utility.h" #include "xml.h" +/////////////////////////////////////////////////////////// +// TTextRecord +/////////////////////////////////////////////////////////// + +class TTextRecord : public TString_array +{ + const TXmlItem* m_trc; + const TXmlItem* m_inrec; + int m_nLines, m_nColumns; + +protected: + char* GetLineBuffer(int i, int size); + const TString& GetFieldValue(const TXmlItem& field) const; + const TXmlItem* FindField(const TString& name) const; + +public: + void SetTrc(const TXmlItem& trc); + bool Read(istream& input); + + const TString& GetValue(const TString& name) const; + const TString& Evaluate(TExpression& exp) const; + + TTextRecord() : m_trc(NULL), m_nLines(0), m_nColumns(0) { } + TTextRecord(const TXmlItem& trc) : m_trc(&trc) { } +}; + +void TTextRecord::SetTrc(const TXmlItem& trc) +{ + m_trc = &trc; + + m_nLines = trc.GetIntAttr("Lines"); + if (m_nLines <= 0) + m_nLines = 1; + + m_nColumns = trc.GetIntAttr("Columns"); + + m_inrec = trc.FindFirst("Record"); + CHECK(m_inrec, "Null input record"); +} + +char* TTextRecord::GetLineBuffer(int i, int size) +{ + CHECKD(i >= 0 && i < m_nLines, "Line out of range ", i); + CHECKD(size > 0, "Bad record size ", size); + + TToken_string* str = (TToken_string*)objptr(i); + if (str == NULL) + { + str = new TToken_string(size); + add(str, i); + } + char* buff = str->get_buffer(size); + *buff = '\0'; + return buff; +} + +bool TTextRecord::Read(istream& input) +{ + bool ok = true; + if (m_nLines <= 1 && m_nColumns > 0) // Record a lunghezza fissa + { + char* buff = GetLineBuffer(0, m_nColumns); + input.read(buff, m_nColumns); + buff[m_nColumns] = '\0'; + } + else + { + int size = m_nColumns; + if (size <= 0) + size = 1024*16; + for (int i = 0; i < m_nLines; i++) + { + char* buff = GetLineBuffer(i, size); + input.getline(buff, size); + buff[size] = '\0'; + } + } + return ok; +} + +const TString& TTextRecord::GetFieldValue(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 = row(y).mid(x, l); + return str; +} + +const TXmlItem* TTextRecord::FindField(const TString& name) const +{ + for (int i = 0; i < m_inrec->GetChildren(); i++) + { + const TXmlItem* field = m_inrec->GetChild(i); + if (field->GetAttr("Name") == name) + return field; + } + return NULL; +} + +const TString& TTextRecord::GetValue(const TString& name) const +{ + const TXmlItem* f = FindField(name); + if (f != NULL) + return GetFieldValue(*f); + return EMPTY_STRING; +} + +const TString& TTextRecord::Evaluate(TExpression& exp) const +{ + for (int i = exp.numvar()-1; i >= 0; i--) + { + const TString& name = exp.varname(i); + const TString& value = GetValue(name); + exp.setvar(i, value); + } + return exp.as_string(); +} + +/////////////////////////////////////////////////////////// +// TScrittore +/////////////////////////////////////////////////////////// + +class TScrittore : public TObject +{ +private: + ofstream* _out; + +public: + ofstream& OutStream() { return *_out; } + + TScrittore(const char* name) { _out = new ofstream(name); } + virtual~ TScrittore() { delete _out; } +}; + + +/////////////////////////////////////////////////////////// +// TCasaEditrice +/////////////////////////////////////////////////////////// + +class TCasaEditrice : public TAssoc_array +{ + const TXmlItem& m_trc; + TString m_strPrefix, m_strExt; + + TExpression* m_exprSuffix; + + TString m_strRecHead, m_strRecFoot, m_strFldHead, m_strFldFoot; + +protected: + ofstream& OutStream(const char* suffix); + void WriteHeader(ostream& output) const; + void WriteFooter(ostream& output) const; + +public: + const TString& RecHead() const { return m_strRecHead; } + const TString& RecFoot() const { return m_strRecFoot; } + const TString& FldHead() const { return m_strFldHead; } + const TString& FldFoot() const { return m_strFldFoot; } + + ofstream& ChooseOutput(const TTextRecord& rec); + TCasaEditrice(const TXmlItem& trc, const char* name); + virtual ~TCasaEditrice(); +}; + + +void TCasaEditrice::WriteHeader(ostream& output) const +{ + TXmlItem* pOutput = m_trc.FindFirst("Output"); + CHECK(pOutput, "NULL output file"); + + TXmlItem* pHeader = pOutput->FindFirst("Header"); + + if (pHeader != NULL) + { + TString strHeader; pHeader->GetEnclosedText(strHeader); + if (strHeader[0] == '"') + { + strHeader.rtrim(1); + strHeader.ltrim(1); + } + strHeader = esc(strHeader); + output << strHeader; + + if (pHeader->GetAttr("Auto") == "1") + { + TXmlItem* pRecOut = pOutput->FindFirst("Record"); + CHECK(pRecOut, "NULL output record"); + + output << m_strRecHead; + for (int i = 0; i < pRecOut->GetChildren(); i++) + { + const TXmlItem* outfield = pRecOut->GetChild(i); + output << m_strFldHead; + output << outfield->GetAttr("Name"); + output << m_strFldFoot; + } + output << m_strRecFoot; + } + } +} + +void TCasaEditrice::WriteFooter(ostream& output) const +{ + TXmlItem* pOutput = m_trc.FindFirst("Output"); + CHECK(pOutput, "NULL output file"); + TXmlItem* pFooter = pOutput->FindFirst("Footer"); + if (pFooter != NULL) + { + TString strFooter; pFooter->GetEnclosedText(strFooter); + if (strFooter[0] == '"') + { + strFooter.rtrim(1); + strFooter.ltrim(1); + } + strFooter = esc(strFooter); + output << strFooter; + } +} + +ofstream& TCasaEditrice::OutStream(const char* suffix) +{ + TScrittore* s = (TScrittore*)objptr(suffix); + if (s == NULL) + { + TFilename n; + n << m_strPrefix << suffix; + if (m_strExt.not_empty()) + n << '.' << m_strExt; + s = new TScrittore(n); + add(suffix, s); + WriteHeader(s->OutStream()); + } + return s->OutStream(); +} + +ofstream& TCasaEditrice::ChooseOutput(const TTextRecord& rec) +{ + TString16 strSuffix; + if (m_exprSuffix != NULL) + strSuffix = rec.Evaluate(*m_exprSuffix); + return OutStream(strSuffix); +} + +TCasaEditrice::TCasaEditrice(const TXmlItem& trc, const char* name) : m_trc(trc), m_exprSuffix(NULL) +{ + const TFilename path(name); + m_strExt = path.ext(); + m_strPrefix = path.name(); + const int dot = m_strPrefix.find('.'); + if (dot >= 0) + m_strPrefix.cut(dot); + + const TXmlItem* pOutFile = m_trc.FindFirst("Output"); + CHECK(pOutFile, "NULL Output tag"); + + + const TString strSuffix = pOutFile->GetAttr("Suffix"); + if (strSuffix.not_empty()) + m_exprSuffix = new TExpression(strSuffix, _strexpr); + + TXmlItem* pRecOut = pOutFile->FindFirst("Record"); + CHECK(pRecOut, "NULL output record"); + + m_strRecHead = esc(pRecOut->GetAttr("RecHead")); + m_strRecFoot = esc(pRecOut->GetAttr("RecFoot")); + m_strFldHead = esc(pRecOut->GetAttr("FldHead")); + m_strFldFoot = esc(pRecOut->GetAttr("FldFoot")); +} + +TCasaEditrice::~TCasaEditrice() +{ + TAssoc_array& myself = *this; + FOR_EACH_ASSOC_OBJECT(myself, h, k, o) + { + TScrittore* s = (TScrittore*)o; + WriteFooter(s->OutStream()); + } +} + +/////////////////////////////////////////////////////////// +// TLettore +/////////////////////////////////////////////////////////// + class TLettore : public TObject { TXmlItem _trc; - - int _lines, _chars; - TString _rseparator, _fseparator; - TString_array _curr; + TTextRecord _curr; + TArray _expressions; 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; + const TString& evaluate(int index) const; public: int convert(const TFilename& src, const TFilename& trc, const TFilename& dst); @@ -40,112 +325,10 @@ bool TLettore::load_trc(const char* t) return ok; } -char* TLettore::get_line_buffer(int i, int size) +const TString& TLettore::evaluate(int index) const { - 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; - } - } - } + TExpression& exp = (TExpression&)_expressions[index]; + return _curr.Evaluate(exp); } int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilename& dst) @@ -184,38 +367,34 @@ int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilenam return 4; } - _lines = recin->GetIntAttr("Lines"); - if (_lines <= 0) - _lines = 1; + _curr.SetTrc(*infile); - _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); + + TCasaEditrice mondadori(_trc, dst); + + TString expr; + for (int i = 0; i < recout->GetChildren(); i++) + { + const TXmlItem* outfield = recout->GetChild(i); + outfield->GetEnclosedText(expr); + _expressions.add(new TExpression(expr, _strexpr)); + } - 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); + _curr.Read(input); + ofstream& output = mondadori.ChooseOutput(_curr); + output << mondadori.RecHead(); 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; + const TString& val = evaluate(i); + output << mondadori.FldHead() << val << mondadori.FldFoot(); } - output << _rseparator; + output << mondadori.RecFoot(); } return 0; @@ -231,7 +410,6 @@ int TLettore::convert(const char* cmd) return convert(src, trc, dst); } - int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { TLettore app; diff --git a/omnia/date.cpp b/omnia/date.cpp new file mode 100755 index 000000000..00032b780 --- /dev/null +++ b/omnia/date.cpp @@ -0,0 +1,669 @@ +#include +#include +#include + +#define __DATE_CPP +#include "date.h" +#include "real.h" + +#define DAYYEAR 365 +#define DAYBIAS 36525L + +static const byte _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +inline bool is_leap(int year) +{ return (year % 4) == 0; } + +/////////////////////////////////////////////////////////// +// Utility functions +/////////////////////////////////////////////////////////// + +TDate::TDate(const TDate &d) : _val(d._val) +{} + +TDate::TDate(long l) : _val(l) +{ + if (_val == TODAY) + { + _val = NULLDATE; + time_t lt; + if (time(<) != -1) + { + struct tm * timeloc = localtime(<); + if (timeloc != NULL) + _val = makedata(timeloc->tm_mday, timeloc->tm_mon+1, timeloc->tm_year + 1900); + } + } + else + { + if (_val == 0) + _val = NULLDATE; + else + { + if (_val < 1000000L) + { + long wd = _val; + int cnt = 1900; + if (wd > DAYBIAS) + { + wd -= DAYBIAS; + cnt += 100; + } + else + while (wd < 0) + { + cnt -= 100; + wd += DAYBIAS; + } + int m, y, leap; + for(y = 0; wd > DAYYEAR + (leap = is_leap(y)); y++) + wd -= (DAYYEAR + leap); + for(m = 0; wd > (_days_in_month[m] + (leap && (m == 1))); m++) + wd -= (_days_in_month[m] + (leap && (m == 1))); + _val = makedata((int) wd, m+1, y+cnt); + } + } + } +} + + +TDate::TDate(const char* s) +{ + _val = NULLDATE; + + const int len = (s && *s) ? strlen(s) : 0; + if (len != 8 && len != 10) + return; + + int d = 0, m = 0, y = 0; + if (len == 8) + { + for (int i = 0; i < 8; i++) + if (!isdigit(s[i])) break; + if (i == 8) + { + TString16 str(s); + d = atoi(((const char *)str)+6); str.cut(6); + m = atoi(((const char *)str)+4); str.cut(4); + y = atoi(((const char *)str)+0); + } + } + else + if (len == 10) + { + if (s[2] == s[5] && !isdigit(s[2])) + { + d = atoi(s); + m = atoi(&s[3]); + y = atoi(&s[6]); + } + } + +#ifdef DBG + if (d < 1 || d > 31 || m < 1 || m > 12 || y < 0) + yesnofatal_box("Lamentati con Guy se la data %s non viene accettata!", s); +#endif + _val = makedata(d, m, y); +} + +TDate::TDate(int day, int month, int year) +{ + if (day >= 1 && day <= 31 && month >= 1 && month <= 12 && year > 0) + _val = makedata(day, month, year); + else + _val = NULLDATE; +} + +int TDate::last_day(int month, int year) + // parse_filastrok( + // "trenta giorni ha novembre + // con april, giugno e settembre + // son ventotto case uno + // per default ce n'ha trentuno"); +{ + int d = _days_in_month[month-1]; + if (month == 2 && is_leap(year)) + d++; + return d; +} + +void TDate::set_end_month() +{ + _val = makedata(last_day(month(),year()),month(),year()); +} + +bool TDate::is_end_month() +{ + return day() == last_day(month(),year()); +} + +bool TDate::empty() const +{ + return _val == 0; +} + +int TDate::wday() const +{ + // day of week (1=lunedi) + // DDJ algorithm (4/1995) Della serie: "non e' colpa mia se funziona". + int m = month(); + int d = day(); + int y = year(); + + if (m <= 2) // Gennaio e Febbraio sono gli ultimi mesi dell'anno scorso + { + y --; + m += 12; + } + + return ((d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7) + 1; // Pure magic +} + +void TDate::set_day(int n) +{ + CHECK(n > 0 && n < 32, "TDate::set_day: giorno insensato"); + _val = makedata(n, month(), year()); +} +void TDate::set_month(int n) +{ + CHECK(n > 0 && n < 13, "TDate::set_month: mese impossibile"); + _val = makedata(day(), n, year()); +} + +void TDate::set_year(int n) +{ + _val = makedata(day(), month(), n); +} + +TDate::operator const char*() const +{ + return string(); +} + +TDate& TDate::operator =(const char* s) +{ + return *this = TDate(s); +} + +TDate& TDate::operator =(long val) +{ + if (val < 0L) + *this = TDate(val); + else + _val = val; + return *this; +} + +void TDate::print_on(ostream& out) const +{ + out << string(); +} + +void TDate::read_from(istream& in) +{ + char s[256]; + in >> s; + TDate d(s); + _val = d._val; +} + +TObject* TDate::dup() const +{ + TDate * d = new TDate(*this); + return d; +} + +// @doc EXTERNAL + +// @mfunc Ritorna la data in formato di stringa (anche in formato ANSI) +// +// @rdesc Se si tratta di una data valida ritorna la stringa secondo il +// formato scelto (vedi ), altrimenti ritorna "" +char* TDate::string( + TDate_mgafmt yearf, // @parm Formato per l'anno (default def) + char sep, // @parm Carattere separatore (default '-') + TDate_mgafmt dayf, // @parm Formato per il giorno (default def) + TDate_mgafmt monthf, // @parm Formato per il mese (default def) + TDate_order ord) const // @parm Ordine con la quale visualizzare la data + // (vedi ; default gma_date) +{ + if (!ok() || *this == botime) + return ""; + + if (yearf == ANSI) + { + yearf = full; + ord = amg_date; + sep='\0'; + } + + TString80 df, yf, mf; + bool letterflag = FALSE; + + // format day + if (dayf == letters) + { + const real ddd(day()); + df = ddd.string("LETTERE"); + letterflag = TRUE; + } + else if (dayf == weekday) + { + df.format("%s %d", itow(wday()), day()); + letterflag = TRUE; + } + else + df.format(dayf == brief ? "%d" : "%02d", day()); + + // format year + if (yearf == letters) + { + const real ddd(year()); + yf = ddd.string("LETTERE"); + letterflag = TRUE; + } + else + if (yearf == brief) + yf.format("%02d", year() % 100); + else + yf.format("%04d", year()); + + // format month + if (monthf == letters) + { + letterflag = TRUE; + mf = itom(month()); + } + else if (monthf == quarter) + { + if (ord < m_date) ord = ma_date; + mf.format("trimestre %d", (month()/3)+1); + } + else + mf.format(monthf == brief ? "%d" : "%02d", month()); + + if ((letterflag && sep == '-') || sep == 'S') + sep = ' '; + + // build date string + + TString& dfm = get_tmp_string(80); + + switch (ord) + { + case mga_date: + dfm << mf << sep << df << sep << yf; + break; + case amg_date: + dfm << yf << sep << mf << sep << df; + break; + case a_date: + dfm << yf; + break; + case m_date: + dfm << mf; + break; + case g_date: + dfm << df; + break; + case ma_date: + dfm << mf << sep << yf; + break; + default: + dfm << df << sep << mf << sep << yf; + break; + } + + return dfm.get_buffer(); +} + +long TDate::date2julian() const +{ + const int d = day(), m = month(), y = year(); + + return (long)(d - 32076) + + 1461L * (y + 4800L + (m - 14) / 12) / 4 + + 367 * ( m - 2 - (m - 14) / 12 * 12) / 12 + - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4 + + 1; + +} + +long TDate::julian2date(long julian) const +{ + long x, z, m, d, y; + const long daysPer400Years = 146097L; + const long fudgedDaysPer4000Years = 1460970L + 31; + + x = julian + 68569L; + z = 4 * x / daysPer400Years; + x = x - (daysPer400Years * z + 3) / 4; + y = 4000 * (x + 1) / fudgedDaysPer4000Years; + x = x - 1461 * y / 4 + 31; + m = 80 * x / 2447; + d = x - 2447 * m / 80; + x = m / 11; + m = m + 2 - 12 * x; + y = 100 * (z - 49) + y + x; + return makedata((int) d, (int) m, (int) y); +} + +int TDate::day() const +{ + return int(_val % 100L); +} + +int TDate::month() const +{ + return int((_val % 10000L) / 100L); +} + + +int TDate::year() const +{ + return int(_val / 10000L); +} + + +int TDate::week() const +{ + TDate y(1, 1, year()); + const int w = y.wday(); + if (w > 1) y -= w-1; + return int((*this - y) / 7 + 1); +} + +TDate& TDate::operator +=(long nday) +{ + const long d = day() + nday; + if (d > 0 && d < 29) + _val += nday; + else + _val = julian2date(date2julian() + nday); + return *this; +} + +void TDate::get_week_year(int &weekd, int &yeard, bool complete) +{ + weekd = week(); + yeard = year(); + const int wday = TDate(1,1,yeard).wday(); + if (complete) + { + if (wday != 1) + weekd --; + if (weekd <= 0) + { + weekd = 52; + yeard --; + } + } + else + { + if (weekd > 52) + { + weekd = 1; + yeard ++; + } + } +} + +void TDate::addmonth(int nmonth) +{ + const int wday = day(); + int wyear = year(); + int wmonth = month() + nmonth; + while (wmonth > 12) + { + wmonth -= 12; + wyear++; + } + _val = makedata(wday, wmonth, wyear); +} + +void TDate::addyear(int nyear) +{ + const int wday = day(); + const int wmonth = month(); + const int wyear = year() + nyear; + _val = makedata(wday, wmonth, wyear); +} + +bool TDate::isdate(const char* s) +{ + const int len = strlen(s); + if (len != 8 && len != 10) + return FALSE; + + int d = 0, m = 0, y = 0; + if (len == 8) + { + for (int i = 0; i < 8; i++) + if (!isdigit(s[i])) break; + if (i == 8) + { + TString16 str(s); + d = atoi(((const char *)str)+6); str.cut(6); + m = atoi(((const char *)str)+4); str.cut(4); + y = atoi(((const char *)str)+0); + } + } + else + if (len == 10) + { + if (s[2] == s[5] && !isdigit(s[2])) + { + d = atoi(s); + m = atoi(&s[3]); + y = atoi(&s[6]); + } + } + + if (d < 1 || d > 31 || + m < 1 || m > 12 || + y < 0) + return FALSE; + + return d <= last_day(m,y); +} + + +bool TDate::ok() const +{ + return _val > 0; +} + + +// @doc EXTERNAL + +// @func TDate& | operator + | Incrementa la data di un certo numero di giorni +TDate operator +( + const TDate& a, // @parm Data a cui aggiungere i giorni + long nday) // @parm Numero di giorni da aggiungere + + // @syntax operator + (const TDate& a, long nday) + // @syntax operator + (long nday, const TDate& a) + // + // @comm E' indifferente quale parametro viene passato per primo +{ + TDate tmp(a); + tmp += nday; + return tmp; +} + + +TDate operator +(const long nday, const TDate& b) +{ + TDate tmp(b); + tmp += nday; + return tmp; +} + +// @doc EXTERNAL + +// @func TDate& | operator - | Decrementa la data di un certo numero di giorni +TDate operator -( + const TDate& a, // @parm Data da decrementare + long nday) // @parm Numero di giorni da togliere +{ + TDate tmp(a); + tmp += -nday; + return tmp; +} + +// @doc EXTERNAL + +// @func TDate& | operator - | Calcola la differenza tra due date +long operator -( + const TDate& a, // @parm Data da decrementare + const TDate& b) // @parm Data da sottrarre +{ + const long diff = a.date2julian() - b.date2julian(); + return diff; +} + +// @doc EXTERNAL + +// @func Scambia la data

con la data

+void swap( + TDate& a, // @parm Prima data da scambiare + TDate& b) // @parm Seconda data da scambiare + +{ + const TDate tmp = b; + b = a; + a = tmp; +} + +// @doc EXTERNAL + +// @func Ritorna la data piu' piccola tra

e

+const TDate& fnc_min( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare + +{ + if (a < b) return a; + else return b; +} + +// @doc EXTERNAL + +// @func Ritorna la data piu' grande tra

e

+const TDate& fnc_max( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare + +{ + if (a > b) return a; + else return b; +} + +/////////////////////////////////////////////////////////// +// TFormatted_date +/////////////////////////////////////////////////////////// + +TFormatted_date::TFormatted_date(int day, int month, int year, const char* form) +: TDate(day, month, year) +{ + set_format(form); +} + +TFormatted_date::TFormatted_date(const TDate& d, const char* form) +: TDate(d) +{ + set_format(form); +} + +TFormatted_date::TFormatted_date(const TFormatted_date& d) +: TDate(d) +{ + set_format(d._format); +} + +// @doc EXTERNAL + +// @mfunc Permette di stabilire il criterio di formattazione delle date +void TFormatted_date::set_format( + const char* f) // @parm Stringa di 5 caratteri che indica il formato della data + + // @comm Ogni carattere del parametro

permette di settare un tipo di formattazione + // della data: + // 1° carattere - FORMATO. Puo' assumere i seguenti valori: + // 1 = giorno-mese-anno + // 2 = mese-anno-giorno + // 3 = anno-giorno-mese + // 4 = solo anno + // 5 = solo mese + // 6 = solo giorno + // 7 = mese-anno + // 2° carattere - Formato GIORNO. Puo assumere i seguenti valori: + // 2 = formato normale (es. 4) + // 4 = formato con 0 (es. 04) + // 5 = lettere (es. quattro) + // 6 = giorno della settimana + // 3° carattere - Formato MESE. Puo assumere i seguenti valori: + // 2 = formato normale (es. 4) + // 4 = formato con 0 (es. 04) + // 5 = lettere (es. quattro) + // 7 = trimestre + // 4° carattere - Formato ANNO. Puo' assumere i seguenti valori: + // 2 = breve (es. 95) + // 4 = lungo (es. 1995) + // 5° carattere - Carattere SEPARATORE. Puo' essere un carattere o lo spazio o essere omesso (sep= char nullo) + +{ + CHECKS(memchr(f, 0, 4) == NULL, "Bad date format (you must define all the first 4 chars) :", f); + memcpy(_format, f, 5); +} + +const char* TFormatted_date::string() const +{ + TDate_mgafmt yearf = (TDate_mgafmt)(_format[3] - '0'); + char sep = _format[4]; + TDate_mgafmt dayf = (TDate_mgafmt)(_format[1] - '0'); + TDate_mgafmt monthf = (TDate_mgafmt)(_format[2] - '0'); + TDate_order ord = (TDate_order)(_format[0] - '0'); + + return TDate::string(yearf, sep, dayf, monthf, ord); +} + + +/////////////////////////////////////////////////////////// +// Utility functions +/////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @func Converte un numero da 1 a 12 nel corrispondente mese +const char* itom( + int m) // @parm Numero del mese da convertire in parole (da 1 a 12) + + // @comm Se il parametro

e' maggiore di 12 viene calcolato il nome del + // mese corrispondente a tale cifra (es. 15 = "Marzo") +{ + CHECK(m>=1, "Il mese indicato deve essere un numero da 1 a 12 "); + const char* const nomi[12] = + { + "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", + "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" + }; + return nomi[(m-1) % 12]; +} + +// @doc EXTERNAL + +// @func Ritorna il nome del giorno (1-7) +const char* itow( + int d) // @parm Numero del giorna da convertire in parole (da 1 a 7) + + // @comm Come primo giorno della setimana e' preso il Lunedi. + // Se il parametro

e' maggiore di 7 viene calcolato il nome del + // giorno corrispondente a tale cifra (es. 15 = "Lunedi") +{ + CHECKD(d >= 1 && d <= 7, "Bad week day ", d); + const char* const nomi[7] = + { "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato", "Domenica" }; + return nomi[(d-1) % 7]; +} + diff --git a/omnia/date.h b/omnia/date.h new file mode 100755 index 000000000..1a898ac69 --- /dev/null +++ b/omnia/date.h @@ -0,0 +1,291 @@ +#ifndef __DATE_H +#define __DATE_H + +#ifndef __OBJECT_H +#include "object.h" +#endif + +#define NULLDATE 0L +#define TODAY -1L + +// @doc EXTERNAL + +// @enum TDate_order | Criterio col quale ordinare gli elementi della data +enum TDate_order { + gma_date = 1, // @emem Giorno-Mese-Anno (default 1) + mga_date, // @emem Mese-Giorno-Anno + amg_date, // @emem Anno-Mese-Giorno + a_date, // @emem Solo anno + m_date, // @emem Solo Mese + g_date, // @emem Solo Giorno + ma_date }; // @emem Mese-Anno + +// @doc EXTERNAL + +// @enum TDate_mgafmt | Criterio col quale visualizzare le date +enum TDate_mgafmt { + ANSI = -1, // @emem Formato ANSI + brief = 2, // @emem Formato breve + full = 4, // @emem Formato completo + letters = 5, // @emem Lettere + weekday = 6, // @emem Giorno della settimana + quarter = 7, // @emem Formato trimestrale + def = 99 }; // @emem Formato standard + +// @doc EXTERNAL + +// @class TDate | Classe per la gestione delle date +// +// @base public | TObject +class TDate : public TObject + +// @author:(INTERNAL) Guido + +// @access:(INTERNAL) Private Member +{ + + // @cmember:(INTERNAL) Valore data in formato ANSI + long _val; + + // @access Protected Member +protected: + + // @cmember Controlla se una data e' minore di un'altra + friend bool operator <(const TDate& a, const TDate& b); + // @cmember Controlla se una data e' maggiore di un'altra + friend bool operator >(const TDate& a, const TDate& b); + // @cmember Controlla se una data e' minore o ugaule ad un'altra + friend bool operator <=(const TDate& a, const TDate& b); + // @cmember Controlla se una data e' maggiore o uguale ad un'altra + friend bool operator >=(const TDate& a, const TDate& b); + // @cmember Controlla se 2 date sono uguali + friend bool operator ==(const TDate& a, const TDate& b); + // @cmember Controlla se una 2 date sono diverse + friend bool operator !=(const TDate& a, const TDate& b); + // @cmember Costruisce la data in formato packed + long makedata(int day, int month, int year) const + { return (10000L * year) + ( 100L * month) + day; } + + // @access Public Member +public: + // @cmember Duplica un TDate. + virtual TObject* dup() const; + // @cmember Ritorna la data in formato di stringa (anche in formato ANSI) + char* string(TDate_mgafmt year = full, char sep = '-', TDate_mgafmt day = full, TDate_mgafmt month = full, TDate_order ord = gma_date) const ; + // @cmember Ritorna la data come numero giuliano + long date2julian() const; + // @cmember Trasforma un numero giuliano in data ANSI + long julian2date(long julian) const; + // @cmember Ritorna la data come numero ANSI + long date2ansi() const { return _val; } + + // @cmember Ritorna il giorno + int day() const ; + // @cmember Ritorna il mese + int month() const ; + // @cmember Ritorna l'anno + int year() const ; + // @cmember Ritorna il giorno della settimana (1 = Lunedi, 7 = domenica) + int wday() const ; + // @cmember Ritorna la settimana dell'anno + int week() const ; + // @cmember Ritorna la settimana e l'anno considerando le settimane complete

o no + void get_week_year(int &weekd, int &yeard, bool complete); + // @cmember Aggiunge dei mesi + void addmonth(int nmonth = 1); + // @cmember Aggiunge degli anni + void addyear(int nyear = 1); + // @cmember Controlla se si tratta di una data corretta + bool ok() const; + // @cmember Controlla se la stringa passata e' una data corretta + static bool isdate(const char*); + + // @cmember Ritorna l'ultimo giorno possibile del mese + static int last_day(int month, int year); + // @cmember Controlla se il giorno e' l'ultimo del mese + bool is_end_month(); + // @cmember Setta il giorno del mese all'ultimo possibile + void set_end_month(); + // @cmember Controlla se la data è nulla + bool empty() const ; + + // @cmember Setta la il giorno + void set_day(int n); + // @cmember Setta il mese + void set_month(int n); + // @cmember Setta l'anno + void set_year(int n); + // @cmember Permette di stabilire il criterio di formattazione delle date + void set_format(const char* f); + + // @cmember Incrementa la data di un certo numero di giorni + TDate& operator +=(long nday); + // @cmember Decrementa la data di un certo numero di giorni + TDate& operator -=(long nday) + { return operator+=(-nday); } + // @cmember Incrementa la data di un giorno + TDate& operator ++() + { return operator +=(1L); } + // @cmember Decrementa la data di un giorno + TDate& operator --() + { return operator +=(-1L); } + + // @cmember Stampa sull'output passato la data + void print_on(ostream& out) const ; + // @cmember Legge dall'input passato la data + void read_from(istream& in) ; + + // @cmember void | operator const char*() const | | Ritorna la data in formato stringa (chiama ) + operator const char*() const ; + // @cmember Assegna la data passata come stringa + TDate& operator =(const char* s); + // @cmember Assegna la data passato come valore numerico ANSI + TDate& operator =(long val); + // @cmember Assegna la data passata come oggetto data + TDate& operator =(const TDate& d) + { _val = d._val; return *this;} + + // @cmember Costruttore + TDate(const TDate& d); + // @cmember Costruttore + TDate(long l = NULLDATE); + // @cmember Costruttore + TDate(const char* s); + // @cmember Costruttore + TDate(int day, int month, int year); +}; + + +// @doc EXTERNAL + +// @class TFormatted_date | Classe per la definizione di date con un formato +// +// @base public | TDate +class TFormatted_date : public TDate + +// @author:(INTERNAL) Guido + +// @access:(INTERNAL) Private Member +{ + + // @cmember:(INTERNAL) Formato per tutti i pezzettini + char _format[5]; + + // @access Public Member +public: + // @cmember Permette di stabilire il criterio di formattazione delle date + void set_format(const char* f); + // @cmember Ritorna la data in formato di stringa (vedi ) + const char* string() const; + + // @cmember Controlla se due stringhe contenenti date coincidono (TRUE se uguali) + TFormatted_date& operator =(const char* s) + { TDate::operator =(s); return *this; } + // @cmember Controlla se due oggetti TDate coincidono (TRUE se uguali) + TFormatted_date& operator =(const TDate& d) + { TDate::operator =(d); return *this; } + // @cmember Controlla se due oggetti TFormatted_date coincidono (TRUE se uguali) + TFormatted_date& operator =(const TFormatted_date& d) + { TDate::operator =(d); set_format(d._format); return *this; } + + // @cmember Costruttore (accetta la definizione di giorno, mese e anno) + TFormatted_date(int day = 0, int month = 0, int year = 0, const char* f = "1444-"); + // @cmember Costruttore (accetta una TDate) + TFormatted_date(const TDate& d, const char* f = "1444-"); + // @cmember Costruttore + TFormatted_date(const TFormatted_date& d); +}; + +TDate operator +(const TDate& a, long nday) ; +TDate operator +(const long nday, const TDate& b) ; +TDate operator -(const TDate& a, long nday) ; +long operator -(const TDate& a, const TDate& b) ; + +// @doc EXTERNAL + +// @func inline bool | operator | Controlla se una data e' minore di un'altra +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' maggiore di

+// @flag FALSE | Se

non e' maggiore di

+inline bool operator <( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val < b._val;} + +// @doc EXTERNAL + +// @func inline bool | operator | Controlla se una data e' maggiore di un'altra +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' minore di

+// @flag FALSE | Se

non e' minore di

+inline bool operator >( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val > b._val;} + +// @doc EXTERNAL + +// @func inline bool | operator = | Controlla se una data e' minore o ugaule ad un'altra +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' minore o uguale a

+// @flag FALSE | Se

e' maggiore di

+inline bool operator <=( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val <= b._val;} + +// @doc EXTERNAL + +// @func inline bool | operator = | Controlla se una data e' maggiore o uguale ad un'altra +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' maggiore o ugaule a

+// @flag FALSE | Se

e' minore di

+inline bool operator >=( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val >= b._val;} + +// @doc EXTERNAL + +// @func inline bool | operator == | Controlla se 2 date sono uguali +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se le due date sono uguali +// @flag FALSE | Se le due date non sono uguali +inline bool operator ==( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val == b._val;} + +// @doc EXTERNAL + +// @func inline bool | operator != | Controlla se 2 date sono diverse +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se le due date sono diverse +// @flag FALSE | Se le due date non sono diverse +inline bool operator !=( + const TDate& a, // @parm Prima data da confrontare + const TDate& b) // @parm Secondo data da confrontare +{ return a._val != b._val;} + +void swap(TDate& a, TDate& b) ; +const TDate& fnc_min(const TDate& a, const TDate& b) ; +const TDate& fnc_max(const TDate& a, const TDate& b) ; + +const char* itom(int month); +const char* itow(int dayofweek); + +const TDate botime(0,0,0), eotime(31,12,2050); + +#endif // __DATE_H diff --git a/omnia/expr.cpp b/omnia/expr.cpp new file mode 100755 index 000000000..63f86a189 --- /dev/null +++ b/omnia/expr.cpp @@ -0,0 +1,1224 @@ +#include +#include +#include + +#define __EXPR_CPP +#include "expr.h" +#include "date.h" + +void TCodearray::clear() +{ + destroy(); + TArray::add(new TCode(_endsym)); +} + +void TCodearray::add(TCodesym sym, const TValue& val) +{ + TArray::insert(new TCode(sym, val), last()); +} + +TObject * TCode::dup() const +{ + TCode * o = new TCode(*this); + return o; +} + +TCode& TCode::operator =(const TCode& b) +{ + _sym = b._sym; + _val = b._val; + return *this; +} + +TObject * TVar::dup() const +{ + TVar * o = new TVar(*this); + return o; +} + +void TVararray::add(const char* name, const TValue& val) +{ + TArray::add(new TVar(name, val)); +} + +void TVararray::set(const char* name, const real& val) +{ + for (int i = last(); i >= 0; i--) + { + TVar* var = (TVar*)objptr(i); + if (var->getname() == name) + { + *var = val; + return; + } + } + NFCHECK("Variabile non trovata: %s", name); +} + + +void TVararray::set(const char* name, const char* val) +{ + for (int i = last(); i >= 0; i--) + { + TVar* var = (TVar*)objptr(i); + if (var->getname() == name) + { + *var = val; + return; + } + } + NFCHECK("Variabile non trovata: %s", name); +} + +const real& TVararray::getnum(const char* name) +{ + for (int i = items()-1; i >= 0; i--) + { + TVar* var = (TVar*)objptr(i); + if (var->getname() == name) + return var->number(); + } + NFCHECK("Unknown variable: %s", name); + return ZERO; +} + + +const real& TVararray::getnum(int varnum) +{ + if (varnum < 0 || varnum >= items()) + { + NFCHECK("Invalid variable number : %d", varnum); + return ZERO; + } + return ((TVar*)objptr(varnum))->number(); +} + + +const TString& TVararray::getstring(const char* name) +{ + for (int i = last(); i >= 0; i--) + { + TVar* var = (TVar*)objptr(i); + if (var->getname() == name) + return var->string(); + } + NFCHECK("Unknown variable : %s", name); + return EMPTY_STRING; +} + + +const TString& TVararray::getstring(int varnum) +{ + TVar* var = (TVar*)objptr(varnum); + if (var == NULL) + { + NFCHECK("Invalid variable number : %d", varnum); + return EMPTY_STRING; + } + return var->string(); +} + +/////////////////////////////////////////////////////////// +// TEval_stack +/////////////////////////////////////////////////////////// + +void TEval_stack::push(bool b) +{ + if (_sp < _data.items()) + { + _sp++; + peek_real() = b ? 1.0 : 0.0; + } + else + TStack::push(new TValue(b ? real(1.0) : ZERO)); +} + +void TEval_stack::push(int n) +{ + if (_sp < _data.items()) + { + _sp++; + peek_real() = n; + } + else + TStack::push(new TValue(real(n))); +} + + +void TEval_stack::push(const real& r) +{ + if (_sp < _data.items()) + { + _sp++; + peek_real() = r; + } + else + TStack::push(new TValue(r)); +} + +void TEval_stack::push(const TString& s) +{ + if (_sp < _data.items()) + { + _sp++; + peek_string() = s; + } + else + TStack::push(new TValue(s)); +} + +void TEval_stack::push(const char* s) +{ + if (_sp < _data.items()) + { + _sp++; + peek_string() = s; + } + else + TStack::push(new TValue(s)); +} + +real& TEval_stack::pop_real() +{ + TValue& o = (TValue&)pop(); + return o.number(); +} + +real& TEval_stack::peek_real() +{ + TValue& o = (TValue&)peek(0); + return o.number(); +} + +TString& TEval_stack::pop_string() +{ + TValue& o = (TValue&)pop(); + return o.string(); +} + +TString& TEval_stack::peek_string() +{ + TValue& o = (TValue&)peek(0); + return o.string(); +} + +/////////////////////////////////////////////////////////// +// TExpression +/////////////////////////////////////////////////////////// + +TExpression::TExpression(const char* expression, TTypeexp type, bool ignore_err) + : _original(expression) +{ + _ignore_error=ignore_err; + _error=0; + _dirty = TRUE; + _type = type; + compile(_original, type); +} + + +TExpression::TExpression(TTypeexp type, bool ignore_err) +{ + _ignore_error=ignore_err; + _error=0; + _dirty = FALSE; + _type = type; + _code.clear(); +} + +TExpression::TExpression(const TExpression & expr) + : _code(expr._code), _var(expr._var), + _val(expr._val), _dirty(expr._dirty), + _type(expr._type), _original(expr._original), + _user_func_defined(expr._user_func_defined), + _ignore_error(expr._ignore_error),_error(expr._error) +{ +} + +TObject* TExpression::dup() const +{ + TExpression* o = new TExpression(*this); + return o; +} + +const real & TExpression::as_real() +{ + if (user_func_dirty() || _dirty) + eval(); + _dirty = FALSE; + return _val.number(); +} + +const TString & TExpression::as_string() +{ + if (user_func_dirty() || _dirty) eval(); + _dirty = FALSE; + return _val.string(); +} + +bool TExpression::as_bool() +{ + return !as_real().is_zero(); +} + +void TExpression::print_on(ostream& out) const +{ out << _original; } + +void TExpression::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp curtype) const +{ + NFCHECK("Unknown function %d.", index); + for (int i = nparms; i > 0; i--) + stack.pop(); + stack.push(ZERO); +} + +void TExpression::setvar(const char* varname, const real& val) +{ + if (_var.getnum(varname) != val) + { + _var.set(varname, val); + _dirty = TRUE; + } +} + +void TExpression::setvar(int varnum, const real& val) +{ + if (_var.getnum(varnum) != val) + { + _var.set(varnum, val); + _dirty = TRUE; + } +} + +void TExpression::setvar(const char* varname, const char* val) +{ + if (_var.getstring(varname) != val) + { + _var.set(varname, val); + _dirty = TRUE; + } +} + + +void TExpression::setvar(int varnum, const char* val) +{ + if (strcmp(_var.getstring(varnum), val) != 0) + { + _var.set(varnum, val); + _dirty = TRUE; + } +} + +bool TExpression::print_error(const char* msg) const +{ + return yesnofatal_box("%s", msg); +} + +void TExpression::eval() +{ + TEval_stack evalstack; + TBit_array types; + int type_pointer = 0; + TCode instr; + + types.set(type_pointer, (_type == _numexpr)); + + TTypeexp type = _type; + + _code.begin(); + while (!_code.end()) + { + instr = _code.step(); + switch (instr.getsym()) + { + case _invalid: + case _endsym: + break; + case _variable: + if (type == _strexpr) + { + const TString & s1 = _var.getstring(instr.string()); + evalstack.push(s1); + } + else + { + const real & r1 = _var.getnum(instr.string()); + evalstack.push(r1); + } + break; + case _number: + { + const real & r1 = instr.number(); + evalstack.push(r1); + } + break; + case _string: + { + const TString & s1 = instr.string(); + evalstack.push(s1); + } + break; + case _plus: + if (type == _strexpr) + { + // Non unire le seguenti righe + const TString& s = evalstack.pop_string(); + evalstack.peek_string() << s; + } + else + { + // Non unire le seguenti righe + const real& r = evalstack.pop_real(); + evalstack.peek_real() += r; + } + break; + case _minus: + { + const real& r = evalstack.pop_real(); + evalstack.peek_real() -= r; + } + break; + case _multiply: + { + const real& r = evalstack.pop_real(); + evalstack.peek_real() *= r; + } + break; + case _divide: + { + const real& r = evalstack.pop_real(); + if (r.is_zero()) + { + if (!evalstack.peek_real().is_zero()) + if (_ignore_error) + _error=1; + else + print_error("Divisione per zero!"); + } else + evalstack.peek_real() /= r; + } + break; + case _chgs: + { + real & r = evalstack.peek_real(); + r = -r; + } + break; + case _and: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (!r1.is_zero() && !r2.is_zero()) ? UNO : ZERO; + } + break; + case _or: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 != ZERO || r2 != ZERO) ? UNO : ZERO; + } + break; + case _not: + { + real & r1 = evalstack.peek_real(); + r1 = (r1 == ZERO) ? 1.0 : 0.0; + } + break; + case _equal: + if (type == _strexpr) + { + const TString & s2 = evalstack.pop_string(); + const TString & s1 = evalstack.pop_string(); + evalstack.push(s1 == s2); + } + else + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 == r2) ? 1.0 : 0.0; + } + break; + case _match: + { + const TString & s2 = evalstack.pop_string(); + const TString & s1 = evalstack.pop_string(); + // evalstack.push(s1.match(s2)); // TBI + evalstack.push(ZERO); + } + break; + case _noteq: + if (type == _strexpr) + { + const TString & s2 = evalstack.pop_string(); + TString & s1 = evalstack.pop_string(); + evalstack.push(s1 != s2); + } + else + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 != r2) ? 1.0 : 0.0; + } + break; + case _lt: + if (type == _strexpr) + { + const TString & s2 = evalstack.pop_string(); + const TString & s1 = evalstack.pop_string(); + evalstack.push(s1 < s2); + } + else + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 < r2) ? 1.0 : 0.0; + } + break; + case _gt: + if (type == _strexpr) + { + const TString & s2 = evalstack.pop_string(); + const TString & s1 = evalstack.pop_string(); + evalstack.push(s1 > s2); + } + else + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 > r2) ? 1.0 : 0.0; + } + break; + case _lteq: + if (type == _strexpr) + { + const TString& s2 = evalstack.pop_string(); + const TString& s1 = evalstack.pop_string(); + evalstack.push(s1 <= s2); + } + else + { + const real& r2 = evalstack.pop_real(); + real& r1 = evalstack.peek_real(); + r1 = (r1 <= r2) ? 1.0 : 0.0; + } + break; + case _gteq: + if (type == _strexpr) + { + const TString& s2 = evalstack.pop_string(); + const TString& s1 = evalstack.pop_string(); + evalstack.push(s1 >= s2); + } + else + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = (r1 >= r2) ? 1.0 : 0.0; + } + break; + case _userfunc: + { + const int nparms = (int) evalstack.pop_real().integer(); + const int index = atoi(instr.string()); + + evaluate_user_func(index, nparms, evalstack, type); + } + break; + case _sqrt: + { + real& r = evalstack.peek_real(); + if (r < ZERO) + { + if (_ignore_error) + _error=1; + else + print_error("Radice negativa!"); + r = -r; + } + r = sqrt(r); + } + break; + case _sqr: + evalstack.peek_real() = sqr(evalstack.peek_real()); + break; + case _exp10: + evalstack.peek_real() = exp10(evalstack.peek_real()); + break; + case _exp: + evalstack.peek_real() = exp(evalstack.peek_real()); + break; + case _log10: + evalstack.peek_real() = log10(evalstack.peek_real()); + break; + case _log: + evalstack.peek_real() = log(evalstack.peek_real()); + break; + case _sin: + evalstack.peek_real() = sin(evalstack.peek_real()); + break; + case _cos: + evalstack.peek_real() = cos(evalstack.peek_real()); + break; + case _tan: + evalstack.peek_real() = tan(evalstack.peek_real()); + break; + case _left: + { + const int len = (int)evalstack.pop_real().integer(); + TString & s1 = evalstack.peek_string(); + s1 = s1.left(len); + } + break; + case _right: + { + const int len = (int)evalstack.pop_real().integer(); + TString & s1 = evalstack.peek_string(); + s1 = s1.right(len); + } + break; + case _mid: + { + int count = (int)evalstack.pop_real().integer(); + if (count == 0) count--; + int from = (int)evalstack.pop_real().integer() - 1; + if (from < 0) from = 0; + TString & s1 = evalstack.peek_string(); + s1 = s1.mid(from, count); + } + break; + case _substr: + { + const int to = (int)evalstack.pop_real().integer(); + int from = (int)evalstack.pop_real().integer() - 1; + if (from < 0) from = 0; + TString & s1 = evalstack.peek_string(); + s1 = s1.sub(from, to); + } + break; + case _len: + { + TString& s1 = evalstack.pop_string(); + evalstack.push(s1.len()); + } + break; + case _pow: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = pow(r1, r2); + } + break; + case _min: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + if (r2 < r1) + r1 = r2; + } + break; + case _max: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + if (r2 > r1) + r1 = r2; + } + break; + case _upper: + evalstack.peek_string().upper(); + break; + case _trim: + evalstack.peek_string().trim(); + break; + case _round: + { + const int ndec = (int)(evalstack.pop_real()).integer(); + real & r = evalstack.peek_real(); + r.round(ndec); + } + break; + case _trunc: + { + const int ndec = (int)(evalstack.pop_real()).integer(); + real & r = evalstack.peek_real(); + r.trunc(ndec); + } + break; + case _ceil: + { + const int ndec = (int)(evalstack.pop_real()).integer(); + real & r = evalstack.peek_real(); + r.ceil(ndec); + } + break; + case _perc: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 = real(r1 * r2 / 100.0); + } + break; + case _scorp: + { + const real & r2 = evalstack.pop_real(); + real & r1 = evalstack.peek_real(); + r1 -= r1 * r2 / (r2 + 100.0); + } + break; + case _if: + { + if (type == _strexpr) + { + const TString & s1 = evalstack.pop_string(); + const TString & s2 = evalstack.pop_string(); + const real & cond = evalstack.pop_real(); + evalstack.push(cond.is_zero() ? s1 : s2); + } + else + { + const real & r1 = evalstack.pop_real(); + const real & r2 = evalstack.pop_real(); + real & cond = evalstack.peek_real(); + cond = cond.is_zero() ? r1 : r2; + } + } + break; + case _ansi: + { + TString& s = evalstack.peek_string(); + const TDate d(s); + s = d.string(ANSI); + } + break; + case _num: + type_pointer++; + types.set(type_pointer, FALSE); + type = _strexpr; + break; + case _endnum: + type_pointer--; + type = types[type_pointer] ? _numexpr : _strexpr; + if (type == _numexpr) + evalstack.peek_real(); + break; + case _str: + type_pointer++; + types.set(type_pointer, TRUE); + type = _numexpr; + break; + case _endstr: + type_pointer--; + type = types[type_pointer] ? _numexpr : _strexpr; + if (type == _strexpr) + evalstack.peek_string(); + break; + case _after: + { + const TString& s1 = evalstack.pop_string(); + TString& s2 = evalstack.peek_string(); + const int pos = s2.find(s1); + if (pos > 0) + s2 = s2.mid(pos+s1.len()); + else + s2.cut(0); + } + break; + case _before: + { + const TString& s1 = evalstack.pop_string(); + TString& s2 = evalstack.peek_string(); + const int pos = s2.find(s1); + if (pos >= 0) + s2.cut(pos); + } + break; + case _rfind: + { + const TString& s1 = evalstack.pop_string(); + const TString& s2 = evalstack.pop_string(); + const int pos = s2.rfind(s1[0]) + 1; + evalstack.push(pos); + } + break; + default: + NFCHECK("operazione non valida %d", (int) instr.getsym()); + break; + } + } + + // Lo stack non e' vuoto + if (_code.items() > 1) + _val = (const TValue&)evalstack.pop(); + else + _val = ZERO; +} + + +HIDDEN const char* _s; +HIDDEN char _tok[81]; + +TCodesym TExpression::tok2fun(const char* tok) const +{ + const int MAX_TOK = 31; + HIDDEN const char* fnstr[MAX_TOK] = { "AFTER", "ANSI", "BEFORE", "CEIL", + "COS", "EXP", "EXP10", "IF", "LEFT", + "LEN", "LOG", "LOG10", "MAX", "MID", + "MIN", "NUM", "PERC", "POW", "RFIND", + "RIGHT", "ROUND", "SCORP", "SIN", "SQR", + "SQRT", "STR", "SUBSTR", "TAN", "TRIM", + "TRUNC", "UPPER" }; + + HIDDEN TCodesym fntok[MAX_TOK] = { _after, _ansi, _before, _ceil, + _cos, _exp, _exp10, _if, _left, + _len, _log, _log10, _max, _mid, + _min, _num, _perc, _pow, _rfind, + _right, _round, _scorp, _sin, _sqr, + _sqrt, _str, _substr, _tan, _trim, + _trunc, _upper }; + + int f = 0, l = MAX_TOK-1, i = MAX_TOK/2; + while (TRUE) + { +// i = (f+l)>>1; + i = f + (toupper(*tok) - *fnstr[f]) * (l - f + 1) / (*fnstr[l] - *fnstr[f] + 1); + + if (i < f || i > l) + return _invalid; + + const int cmp = stricmp(tok, fnstr[i]); + + if (cmp == 0) + break; + if (cmp > 0) f = i+1; + else l = i-1; + + if (f > l) + return _invalid; + } + CHECKD(i >= 0 && i < MAX_TOK, "Invalid function index ", i); + return fntok[i]; +} + + + +TCodesym TExpression::__gettoken(bool /* reduct */) +{ + TCodesym sym = _invalid; + int i = 0; + + _tok[0] = '\0'; + while (isspace(*_s)) _s++; + if (!*_s) return _endsym; + + bool square_bracket = FALSE; + + if (isdigit(*_s) || (*_s == '.')) + { + sym = _number; + while (isalnum(*_s) || (*_s == '_') || (*_s == '.') || + (*_s == ':') || (*_s == '@') || + (sym == _variable && *_s == '[') || + (sym == _number && *_s == '-' ) || + (square_bracket && (*_s == ',' || *_s == ']')) + ) + { + if (*_s == '-') + { + if (_s[1] != '>') break; + _tok[i++] = *(_s++); + _tok[i++] = *(_s++); + sym = _variable; + } + else + { + if (sym == _number) + { + if (isalpha(*_s) || (*_s == '_') || (*_s == ':') + /* || (*_s == '[') || (*_s == ']') || (*_s == ',') */ + ) + sym = _variable; + } + else + { + if (sym == _variable && *_s == '[') + square_bracket = TRUE; + } + _tok[i++] = *(_s++); + } + } + _tok[i] = '\0'; + return sym; + } + if (isalpha(*_s) || (*_s == '#') || (*_s == '_')) + { + if (*_s == '#') + sym = _variable; + + _tok[i++] = *(_s++); + + while (isalnum(*_s) || (*_s == '-') || (*_s == '[') || + (*_s == ':') || (*_s == '_') || + (square_bracket && (*_s == ',' || *_s == ']')) + ) + { + if (*_s == '-') + { + if (_s[1] != '>') + break; // Non e' una -> (freccia) + _tok[i++] = *(_s++); + sym = _variable; + } + else + { + if (*_s == '[') + { + sym = _variable; + square_bracket = TRUE; + } + } + _tok[i++] = *(_s++); + } + _tok[i] = '\0'; + + if (sym != _variable) // So gia' tutto, inutile controllare oltre + { + sym = tok2fun(_tok); + if (sym != _invalid) + return sym; + + for (const char * p = _s; isspace(*p); p++); + if (*p == '(') + return _userfunc; + } + + return _variable; + } + switch (*_s) + { + case '"' : + case '\'' : + { + const char sep = *_s; + _s++; + while ((*_s) && (*_s != sep)) + _tok[i++] = *(_s++); + _tok[i] = '\0'; + if (*_s == sep) _s++; + return _string; + } + case ',' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _comma; + case ';' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _semicolon; + case '(' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _lpar; + case ')' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _rpar; + case '+' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _plus; + case '-' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _minus; + case '*' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _multiply; + case '/' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _divide; + case '&' : + _tok[i++] = *(_s++); + if (*_s != '&') break; + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _and; + case '|' : + _tok[i++] = *(_s++); + if (*_s != '|') break; + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _or; + case '!' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + if (*_s == '=') + { + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _noteq; + } + return _not; + case '=' : + _tok[i++] = *(_s++); + if (*_s == '=') _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _equal; + case '?' : + _tok[i++] = *(_s++); + if (*_s == '=') _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _match; + case '>' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + if (*_s == '=') + { + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _gteq; + } + return _gt; + case '<' : + _tok[i++] = *(_s++); + _tok[i] = '\0'; + if (*_s == '=') + { + _tok[i++] = *(_s++); + _tok[i] = '\0'; + return _lteq; + } + return _lt; + default: + break; + } + return _invalid; +} + +//HIDDEN int __parms_found = -1; + +TCodesym TExpression::__factor(TCodesym startsym) +{ + TCodesym sym = _invalid; + int nparms_found = 0; + + switch (startsym) + { + case _lpar: + sym = __gettoken(); + sym = __expression(sym); + if (sym == _rpar) sym = __gettoken(); + else sym = _invalid; + break; + case _variable: + { + int from = 1, to = 0; + char* quadra = strchr(_tok, '['); + if (quadra) + { + if (sscanf(quadra, "[%d,%d]", &from, &to) == 0) + { + sym = _invalid; + break; + } + *quadra = '\0'; + } + _code.add(_variable, _tok); + if (quadra) + { + _code.add(_number, real(from)); + _code.add(_number, real(to >= from ? to-from+1 : 0)); + _code.add(_mid); + } + for (int i = numvar()-1 ; i >= 0; i--) + if (strcmp(_tok, varname(i)) == 0) break; + if (i < 0) _var.add(_tok); + sym = __gettoken(TRUE); + } + break; + case _number: + case _string: + _code.add(startsym, _tok); + sym = __gettoken(TRUE); + break; + case _userfunc: + { + TValue val (_tok); + int nparms_found = 0; + sym = __function(-1, true, nparms_found); + if (sym != _invalid) + { + const int index = parse_user_func((const char *) val.string(), nparms_found); + + if (index < 0) + { + strcpy(_tok, (const char *) val.string()); + sym = _invalid; + } + else + { + _code.add(_number, real(nparms_found)); + val = real(index); + _code.add(startsym, val); + _user_func_defined = TRUE; + } + } + } + break; + case _sqrt: + case _sqr: + case _exp10: + case _exp: + case _log10: + case _log: + case _sin: + case _cos: + case _tan: + case _ansi: + case _upper: + case _trim: + case _len: + sym = __function(1, true, nparms_found); + _code.add(startsym); + break; + case _left: + case _right: + case _pow: + case _min: + case _max: + case _round: + case _ceil: + case _trunc: + case _perc: + case _scorp: + case _after: + case _before: + case _rfind: + sym = __function(2, true, nparms_found); + _code.add(startsym); + break; + case _mid: + case _substr: + sym = __function(3, true, nparms_found); + _code.add(startsym); + break; + case _if: + sym = __function(3, true, nparms_found); + _code.add(startsym); + break; + case _num: + case _str: + _code.add(startsym); + sym = __function(1, true, nparms_found); + _code.add(startsym == _num ? _endnum : _endstr); + break; + default: + break; + } + return sym; +} + + +TCodesym TExpression::__term(TCodesym startsym) +{ + TCodesym sym = __factor(startsym); + while (sym == _multiply || sym == _divide) + { + const TCodesym savedsym = sym; + sym = __gettoken(); + sym = __factor(sym); + _code.add(savedsym); + } + return sym; +} + + +TCodesym TExpression::__expression(TCodesym startsym) +{ + TCodesym sym; + if ((startsym == _minus) || (startsym == _not) || (startsym == _plus)) + sym =__gettoken(); + else + sym = startsym; + sym = __term(sym); + if ((startsym == _minus) || (startsym == _not)) + _code.add(startsym == _not ? startsym : _chgs); + while ((sym != _endsym) && + ((sym == _minus) || (sym == _plus) || (sym == _equal) || + (sym == _noteq) || (sym == _gt) || (sym == _lt) || + (sym == _gteq) || (sym == _lteq) || (sym == _and) || + (sym == _or) || (sym == _match))) + { + TCodesym savedsym = sym; + sym = __gettoken(); + sym = __term(sym); + _code.add(savedsym); + } + return(sym); +} + +TCodesym TExpression::__function(int nparms, bool fixed_num, int& nparms_found) +{ + TCodesym sym = __gettoken(TRUE); + if (sym != _lpar) + return _invalid; + nparms_found = 0; + sym = __gettoken(TRUE); + if (sym == _rpar) + return nparms <= 0 || !fixed_num ? __gettoken(TRUE) : _invalid; + nparms_found++; + sym = __expression(sym); + while (sym == _comma || sym == _semicolon) + { + sym = __gettoken(TRUE); + nparms_found++; + sym = __expression(sym); + } + if (sym == _rpar) + return nparms < 0 || nparms_found == nparms || (nparms_found < nparms && !fixed_num) ? + __gettoken(TRUE) : + _invalid; + return _invalid; +} + +bool TExpression::set(const char* expression, TTypeexp type) +{ + _original = expression; + _type = type; + _dirty = TRUE; + return compile(_original, type); +} + +bool TExpression::compile(const TString& expression, TTypeexp type) +{ + _user_func_defined = FALSE; + _s = expression; + _type = type; + _val = ZERO; + _code.clear(); + if (expression.blank()) + return TRUE; + + TCodesym currsym = __gettoken(); + bool ok = currsym != _invalid; + if (ok) + ok = __expression(currsym) == _endsym; + if (!ok) + { + _error = 2; + if (!_ignore_error) + { + TString msg; + msg << "Espressione errata : " << _original; + print_error(msg); + } + } + + return ok; +} + +const char* TExpression::last_token() const +{ + return _tok; +} diff --git a/omnia/expr.h b/omnia/expr.h new file mode 100755 index 000000000..5507b2966 --- /dev/null +++ b/omnia/expr.h @@ -0,0 +1,519 @@ +#ifndef __EXPR_H +#define __EXPR_H + +#ifndef __REAL_H +#include "real.h" +#endif + +#ifndef __STACK_H +#include "stack.h" +#endif + + +// @doc INTERNAL + +// @enum TCodesym | Lista di simboli/istruzioni possibili +enum TCodesym { + _invalid, // @emem Simbolo non riconosciuto + _endsym, // @emem Segnaposto per simbolo finale + _comma, // @emem Simbolo virgola "," + _semicolon, // @emem Simbolo punto e virgola ";" + _lpar, // @emem Simbolo aperta parentesi "(" + _rpar, // @emem Simbolo chiusa parentesi ")" + _variable, // @emem Nome di una variabile + _number, // @emem Numero + _string, // @emem Stringa + _plus, // @emem Simbolo piu' "+" + _minus, // @emem Simbolo meno "-" + _multiply, // @emem Simbolo per "*" + _divide, // @emem Simbolo diviso "/" + _chgs, // @emem MENO unario + _and, // @emem AND logico + _or, // @emem OR logico + _not, // @emem NOT logico + _equal, // @emem Simbolo uguale "=" + _match, // @emem Confronto tra stringhe con wildcards + _noteq, // @emem Simbolo diverso "!=" + _lt, // @emem Simbolo minore "" + _gt, // @emem Simbolo maggiore "" + _lteq, // @emem Simbolo minore o uguale "=" + _gteq, // @emem Simbolo maggiore o uguale "=" + _userfunc, // @emem Funzione utente non definita chiamera' la .... in esecuzione + _sqrt, // @emem Radice quadrata + _sqr, // @emem Elevamento al quadrato + _exp10, // @emem Funzione 10 a potenza + _exp, // @emem Funzione e (nepero) elevato a + _log10, // @emem Logaritmo in base 10 + _log, // @emem Logaritmo naturale + _sin, // @emem Funzione seno + _cos, // @emem Funzione coseno + _tan, // @emem Funzione tangente + _left, // @emem Primi caratteri di una stringa + _right, // @emem Ultimi caratteri di una stringa + _pow, // @emem Elevamento a potenza + _min, // @emem Minimo tra piu' elementi + _max, // @emem Massimo tra piu' elementi + _mid, // @emem Media degli elementi + _upper, // @emem Trasformazione in maiuscolo + _round, // @emem Arrotondamento + _ansi, // @emem Data in ansi + _if, // @emem Se(expr, val TRUE, val FALSE) + _num, // @emem Converte una stringa in numero + _endnum, // @emem Termine della funzione num + _str, // @emem Converte un numero in stringa + _endstr, // @emem Termine della funzione str + _ceil, // @emem Arrotonda un numero all'intero successivo + _trunc, // @emem Tronca i decimali + _perc, // @emem Calcola la percentuale + _scorp, // @emem Scorpora una percentuale + _substr, // @emem Estrae una sottostringa + _len, // @emem Lunghezza di una stringa + _trim, // @emem Elimina spazi iniziali e finali di una stringa + _before, // @emem Estrae la parte precedente una stringa fissa data + _after, // @emem Estrae la parte seguente una stringa fissa data + _rfind, // @emem Cerca una stringa all'indietro +}; +// @doc INTERNAL + + // @enum TTypeexp | Tipi di espressioni definiti + enum TTypeexp { + _numexpr, // @emem Espressione numerica + _strexpr } ; // @emem Espressione in lettere + +// @doc INTERNAL + +// @class TValue | Classe per la definizione dei valori che possono essere assunti +// dai termini di una espressione o il valore dell'espressione stessa +// +// @base public | TObject +class TValue : public TObject +// @author:(INTERNAL) Alex +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Valore real + real _r; + // @cmember:(INTERNAL) Valore in formato stringa + TString256 _s; + // @cmember:(INTERNAL) Tipo preferito + TTypeexp _t; + + // @access Public Member +public: + // @cmember Assegnamento tra oggetti TValue + TValue& operator =(const TValue& val) + { _s = val._s; _r = val._r; _t = val._t; return *this; } + // @cmember Assegnamento di una stringa + TValue& operator =(const TString& s) + { _s = s; _t = _strexpr; return *this; } + // @cmember Assegnamento di un numero + TValue& operator =(const real& r) + { _r = r; _t = _numexpr; return *this; } + // @cmember Ritorna il valore numerico + real& number() + { if (_t == _strexpr) { _r = real(_s); _t = _numexpr; } return _r; } + // @cmember Ritorna il valore come stringa + TString& string() + { if (_t == _numexpr) { _s = _r.string(); _t = _strexpr; } return _s; } + // @cmember Setta il valore passato come real + void set(const real& val) + { _r = val; _t = _numexpr; } + // @cmember Setta il valore passato come stringa + void set(const char* val) + { _s = val; _t = _strexpr; } + // @cmember Setta il valore passato come stringa + TTypeexp type() const { return _t; } + + // @cmember Costruttore. Inizializza TValue con un reale + TValue(const real& val) + { _r = val; _t = _numexpr; } + // @cmember Costruttore. Inizializza TValue con una stringa + TValue(const char* val) + { _s = val; _t = _strexpr; } + // @cmember Costruttore. Inizializza TValue con una stringa + TValue(const TString& val) + { _s = val; _t = _strexpr; } + // @cmember Costruttore. Inizializza TValue con un altro TValue + TValue(const TValue& val) + { *this = val; } + // @cmember Costruttore. Inizializza TValue a 0,0 e "" + TValue() + { } + // @cmember Distruttore + virtual ~TValue() + {} +}; + + +#ifdef __EXPR_CPP +#define extern +#endif + +extern TValue nulltvalue; + +#undef extern + +// @doc INTERNAL + +// @class TCode | Classe per la ridefinizione di una espressione in +// notazione polacca inversa (RPN) +// +// @base public | TObject +class TCode : public TObject + +// @author:(INTERNAL) Sandro + +// @access:(INTERNAL) Private Member +{ + + // @cmember:(INTERNAL) Simbolo-istruzione-codice + TCodesym _sym; + // @cmember:(INTERNAL) Valore + TValue _val; + + // @access Public Member +public: + // @cmember Duplica il codice + virtual TObject* dup() const; + // @cmember Assegnamento tra oggetti TCode + TCode& operator =(const TCode& b); + // @cmember Inizializza simbolo e valore + void set(TCodesym sym, const TValue& val = nulltvalue) + { _sym = sym; _val = val; } + // @cmember Ritorna il simbolo + TCodesym getsym() const + { return _sym;} + // @cmember Ritorna il valore come + real& number() + { return _val.number(); } + // @cmember Ritorna il valore come stringa + TString& string() + { return _val.string(); } + + // @cmember Costruttore, inizializza simbolo con "invalid", valore a nullvalue + TCode() + {set(_invalid);} + // @cmember Costruttore + TCode(TCodesym sym, const TValue& val = nulltvalue) + // @cmember Costruttore, inizializza simbolo con

e valore con

+ { set(sym, val);} + // @cmember Costruttore + TCode(const TCode & c) + // @cmember Costruttore, inizializza simbolo con

+ { set(c._sym, c._val);} + // @cmember Distruttore + virtual ~TCode() + {} +}; + +// @doc INTERNAL + +// @class TCodearray | Classe per la definizione di un array di istruzioni da valutare +// passo per passo in una espressione +// +// @base public | TArray +class TCodearray : public TArray + +// @author:(INTERNAL) Sandro + +// @access:(INTERNAL) Private Member +{ + + // @cmember:(INTERNAL) Puntatore all'istruzione corrente (Istruction pointer) + int _ip; + + // @access Public Member +public: + // @cmember Cancella contenuto array + void clear(); + // @cmember Aggiunge un'istruzione all'array + void add(TCodesym sym, const TValue& val = nulltvalue); + // @cmember Posiziona all'inizio il puntatore all'istruzione corrente + void begin() + { _ip = 0;} + // @cmember Incrementa l'istruction pointer + TCode& step() + { return *((TCode *) objptr(end() ? _ip : _ip++));} + // @cmember Ritorna TRUE se l'istruction pointer ha raggiunto il simbolo di fine codice + bool end() const + { return ((TCode *) objptr(_ip))->getsym() == _endsym;} + // @cmember Sposta indietro l'istruction pointer di

passi (si ferma + // quando trova l'inizio del puntatore) + void backtrace(int step = 1) + { if (_ip > step) _ip -= step; else begin(); } + // @cmember Costruttore. Crea un array di 50 elementi + TCodearray(int size = 50) : TArray(size), _ip(0) + {} + // @cmember Distruttore + virtual ~TCodearray() + {} +}; + +// @doc INTERNAL + +// @class TVar | Classe per la definizione delle variabile delle espressioni +// +// @base public | TObject +class TVar : public TObject + +// @author:(INTERNAL) Sandro + +// @access:(INTERNAL) Private Member +{ + + // @cmember:(INTERNAL) Nome della variabile + TString _name; + // @cmember:(INTERNAL) Valore assegnato alla variabile + TValue _val; + + // @access Public Member +public: + // @cmember Duplica la variabile + virtual TObject* dup() const; + + // @cmember Assegnamento di una stringa all'oggetto Tval + const char* operator =(const char* val) + { _val.set(val); return val;} + // @cmember Assegnamento di un numero all'oggetto TVal + const real& operator =(const real& val) + { _val.set(val); return val;} + // @cmember Assegnamento di un oggetto + TVar& operator =(const TValue& val) + { _val = val; return *this;} + // @cmember Assegnamento tra oggetti TVal + TVar& operator =(const TVar& var) + { _name = var._name ; _val = var._val; return *this;} + // @cmember Setta l'oggetto TVal con il nome e il valore passati + void set(const char* name, const TValue& val = nulltvalue) + { _name = name ; _val = val;} + // @cmember Setta a

il nome della variabile + void setname(const char* name) + { _name = name;} + // @cmember Ritorna il nome della variabile + const TString& getname() const + { return _name;} + + // @cmember Ritorna il valore assegnato alla variabile (un ) + operator TValue&() + { return _val;} + // @cmember Ritorna il valore real della variabile + real& number() + { return _val.number(); } + // @cmember Ritorna il valore stringa della variabile + TString& string() + { return _val.string();} + + // @cmember Costruttore (assegna "" al campo

ed il valore nulltvalue al campo

) + TVar() + { _name = ""; _val = nulltvalue;} + // @cmember Costruttore (assegna nome e valore passato) + TVar(const char* name, const TValue& val = nulltvalue) + { _name = name; _val = val;} + // @cmember Costruttore (assegna l'oggetto TVal passato) + TVar(const TVar & v) + { _name = v._name; _val = v._val;} + // @cmember Distruttore + virtual ~TVar() + {} +}; + +// @doc INTERNAL + +// @class TVararray | Classe per la definizione di un array di variabili da +// valutare nell'esspressione +// +// @base public | TArray +class TVararray : public TArray + +// @author:(INTERNAL) Sandro + +// @access:(INTERNAL) Private Member +{ + + // @access Public Member +public: + // @cmember Cancella il contenuto dell'array + void clear() + { destroy();} + // @cmember Aggiunge un oggetto TVar + void add(const TVar& var); + // @cmember Aggiunge un nome di variabile e il suo valore + void add(const char* name, const TValue& val = nulltvalue); + // @cmember Ritorna il nome della variabile di posto varnum + const char* varname(int varnum) const + { return varnum < items() ? ((TVar *) objptr(varnum))->getname() : "";} + + // @cmember Setta l'oggetto TVararray con il nome e il valore della variabile + void set(const char* varname, const real& val); + // @cmember Setta l'oggetto TVararray con il nome e il valore della variabile + // (passato come stringa) + void set(const char* varname, const char* val); + // @cmember Setta l'elemnto dell varaibile

-esima al valore passato + void set(int varnum, const real& val) + { if (varnum < items()) *((TVar *) objptr(varnum)) = val;} + // @cmember Setta l'elemnto dell varaibile

-esima al valore passato + // come stringa + void set(int varnum, const char* val) + { if (varnum < items()) *((TVar *) objptr(varnum)) = val;} + + // @cmember Ritorna il valore della variabile con nome

+ const real& getnum(const char* varname); + // @cmember Ritorna il valore della variabile di posto

-esimo + const real& getnum(int varnum); + // @cmember Ritorna il nome della variabile con nome

+ const TString& getstring(const char* varname); + // @cmember Ritorna il nome della variabile di posto

-esimo + const TString& getstring(int varnum); + + // @cmember Ritorna il numero di variabili utilizzate + int numvar() const + { return items();} + + // @cmember Costruttore + TVararray(int size = 10) : TArray(size) {} + // @cmember Distruttore + virtual ~TVararray() + {} +}; + +class TEval_stack : public TStack +{ +public: + real& pop_real(); + real& peek_real(); + TString& pop_string(); + TString& peek_string(); + + void push(bool b); + void push(int n); + void push(const real& r); + void push(const TString& s); + void push(const char* s); +}; + +// @doc EXTERNAL + +// @class TExpression | Classe per la interpretazione e valutazione di espressioni +// numeriche e di stringhe +// +// @base public | TObject +class TExpression : public TObject + +// @author:(INTERNAL) Sandro + +// @access:(INTERNAL) Private Member +{ + // @access Protected Member +protected: + // @cmember:(INTERNAL) Array di codice + TCodearray _code; + // @cmember:(INTERNAL) Array di variabili + TVararray _var; + // @cmember:(INTERNAL) Valore dell'espressione + TValue _val; + // @cmember:(INTERNAL) Indica se segnalare o no errori di valutazione + bool _ignore_error; + // @cmember:(INTERNAL) Diverso da 0 se la valutazione dell'espressione ha dato errori (ZERO DIV) + int _error; + // @cmember:(INTERNAL) TRUE se l'espressione e' stata modificata + bool _dirty; + // @cmember:(INTERNAL) TRUE se l'espressione ha almeno una funzione utente + bool _user_func_defined; + // @cmember:(INTERNAL) Tipo dell'espressione + TTypeexp _type; + // @cmember:(INTERNAL) Stringa originale + TString _original; + + // @access Protected Member +protected: + // @cmember funzione utente da ricalcolare + virtual bool user_func_dirty() const { return _user_func_defined; } + // @cmember stampa un messaggio d'errore + virtual bool print_error(const char* msg) const; + // @cmember Valuta (calcola) l'espressione + void eval(); + // @cmember Converte una stringa in un nome di funzione o _invalid se non esiste + TCodesym tok2fun(const char* tok) const; + // @cmember Ritorna il prossimo token dell'espressione (se

e' TRUE interpreta + // la virgola come un token) + TCodesym __gettoken(bool reduct = FALSE); + // @cmember Esegue la compilazione di un fattore + TCodesym __factor(TCodesym startsym); + // @cmember Esegue la compilazione di un termine + TCodesym __term(TCodesym startsym); + // @cmember Esegue la compilazione di un'espressione + TCodesym __expression(TCodesym startsym); + // @cmember Esegue la compilazione di un una funzione + TCodesym __function(int nparms, bool fixed_num, int& nparms_found); + // @cmember Compila l'espressione + bool compile(const TString& expression, TTypeexp type); + +protected: // TObject + // @cmember Stampa l'espressione su

(serve per implementare l'insertore) + virtual void print_on(ostream& out) const ; + virtual void evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const; + virtual int parse_user_func(const char * name, int nparms) const { return -1; } + + // @access Public Member +public: + // @cmember Duplica l'espressione + virtual TObject* dup() const; + // @cmember operator const | real& | | Ritorna il valore real dell'espressione + operator const real&() {return as_real();} + // @cmember operator const | char* | | Ritorna il valore dell'espressione come stringa + operator const TString &() {return as_string();} + // @cmember Ritorna il valore dell'espressione come booleano + operator bool() {return as_bool();} + // @cmember operator const | real& | | Ritorna il valore real dell'espressione + const real & as_real(); + // @cmember operator const | char* | | Ritorna il valore dell'espressione come stringa + const TString & as_string(); + // @cmember Ritorna il valore dell'espressione come booleano + bool as_bool(); + // @cmember Ritorna il nome della variabile di posto

+ const char* varname(int varnum) const + { return _var.varname(varnum); } + // @cmember Ritorna il numero di variabili nell'espressione + int numvar() const + { return _var.numvar(); } + // @cmember Ritorna il tipo dell'espressione + const TTypeexp type() const + { return _type; } + // @cmember Ritorna l'array del codice + TCodearray& code() const + { return (TCodearray&)_code; } + // @cmember Ritorna l'array di variabili + const TVararray& vars() const + { return _var; } + + // @cmember Setta la variabile con nome e numero + void setvar(const char* varname, const real& val); + // @cmember Setta la variabile con posizione e numero + void setvar(int varnum, const real& val); + // @cmember Setta la variabile con nome e valore passato come stringa + void setvar(const char* varname, const char* val); + // @cmember Setta la variabile passato con posizione e numero passato come stringa + void setvar(int varnum, const char* val); + // @cmember Setta il tipo dell'espressione + void set_type(const TTypeexp type) + { _type = type; } + // @cmember Setta l'espressione e la compila (ritorna il risultato della compilazione) + bool set(const char* expression, TTypeexp type = _numexpr); + const char* last_token() const; + // @cmember Ritorna l'espressione originale + const char * string() const { return _original; } + // @cmember Ritorna eventuali errori + int error() {return _error;} + + // @cmember Costruttore (assegna l'estressione e il suo tipo) + TExpression(const char* expression, TTypeexp type = _numexpr, bool ignore_err=FALSE); + // @cmember Costruttore (assegna il tipo dell'istruzione) + TExpression(TTypeexp type = _numexpr, bool ignore_err=FALSE); + // @cmember Costruttore di copia + TExpression(const TExpression & expr); + // @cmember Distruttore + virtual ~TExpression() + {} +}; + +#endif // __EXPR_H diff --git a/omnia/real.cpp b/omnia/real.cpp new file mode 100755 index 000000000..bf051eb58 --- /dev/null +++ b/omnia/real.cpp @@ -0,0 +1,1810 @@ +#include +#include + +#include "real.h" + +const real ZERO(0.0); +const real UNO(1.0); +const real CENTO(100.0); + +#ifdef __LONGDOUBLE__ + +#include + +#include +inline long double _atold(const char* str) +{ + long double num = 0.0; + sscanf(str, "%Lf", &num); + return num; +} + +real::real () : _dec(0.0) +{ } + +real::real (const real& b) : _dec(b._dec) +{ } + +real::real (long double a) : _dec(a) +{ } + +void real::set_int64(__int64 b) +{ + _dec = (long double)b; +} + +bool real::is_real (const char *s) +{ + if (s && *s) + { + const long double n = _atold(s); + if (n == 0.0) + { + for(; *s; s++) if (*s != '0' && *s != ' ' && *s != '.') + return FALSE; + } + } + return TRUE; +} + +real::real (const char *s) +{ + _dec = (s && *s) ? _atold(s) : 0.0; +} + +real& real::operator = (const real& b) +{ + _dec = b._dec; + return *this; +} + +real& real::operator = (long double b) +{ + _dec = b; + return *this; +} + +real& real::operator += (long double b) +{ + _dec += b; + return *this; +} + +real& real::operator -= (long double b) +{ + _dec -= b; + return *this; +} + +real& real::operator *= (long double b) +{ + _dec *= b; + return *this; +} + +real& real::operator /= (long double b) +{ + CHECK(b != 0.0, "Division by zero"); + _dec /= b; + return *this; +} + + +// @doc EXTERNAL + +// @mfunc Ritorna il segno del reale +// +// @rdesc Ritorna i seguenti valori: +// +// @flag 0 | Se il numero e' minore di 0 +// @flag = 0 | Se il numero e' uguale a 0 +// @flag 0 | Se il numero e' maggiore di 0 +int real::sign () const +{ + const int s = _dec > 0.0 ? +1 : (_dec < 0.0 ? -1 : 0); + return s; +} + +real real::operator - () const +{ + real n(-_dec); + return n; +} + +long real::integer () const +{ + return (long)floorl(_dec); +} + +// Certified 91% +// @doc EXTERNAL + +// @mfunc Trasforma un reale in stringa +// +// @rdesc Ritorna la stringa nella lunghezza richiesta +const char *real::string ( + int len, // @parm Lunghezza della stringa (compreso decimali) + int dec, // @parm Numero di decimali (default UNDEFINED) + char pad) const // @parm Carattere di riempimento (default ' ') + // @parm char * | picture | Formato della stringa + + // @syntax string (int len, int dec, char pad); + // @syntax string (const char *picture); + // + // @comm Nel primo caso ritorna una stringa lunga

con

decimali e + // inserisce nella stringa stessa il carattere

nel caso la + // lunghezza richiesta sia maggiore di quella che risulterebbe per la + // completa rappresentazione del reale. + // Nel secondo caso ritorna la stringa con il formato stabilito in + //

. + +{ + TString16 fmt("%"); + if (pad != ' ') fmt << '0'; + if (len != 0) fmt << len; + if (dec != UNDEFINED) fmt << '.' << dec; + fmt << "Lf"; + + TString& tmp = get_tmp_string(); + char* __string = tmp.get_buffer(len); + + sprintf(__string, fmt, _dec); + + if (len == 0 && dec == UNDEFINED && strchr(__string, '.') != NULL) + { + int cut = strlen (__string); + for (int i = cut-1; i >= 0; i--) + { + if (__string[i] == '0') + cut--; + else + { + if(__string[i] == '.') + cut--; + break; + } + } + __string[cut] = '\0'; + } + return __string; +} + +// Childish algorithm faster and more accurate than powl(10.0, pow) +HIDDEN void ipow10(int pow, double& m, double& d) +{ + m = d = 1.0; + if (pow > 0) + { + for (int i = pow; i > 0; i--) + { + m *= 10.0; + d *= 0.1; + } + } + else + { + for (int i = pow; i < 0; i++) + { + m *= 0.1; + d *= 10.0; + } + } +} + +int real::precision() const +{ + const TFixed_string s(string()); + const int d = s.find('.'); + const int p = d < 0 ? 0 : (s.len()-d-1); + return p; +} + + +// @doc EXTERNAL + +// @mfunc real& | real | round | Arrotonda al numero di decimali passati +real& real::round ( + int prec) // @parm Numero di decimali a cui arrotondare il numero (default 0) + + // @comm Nel caso

sia: + // + // @flag 0 | Arrotonda al decimale + // @flag = 0 | Arrotonda all'intero + // @flag 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille) +{ + if (abs(prec) < 20) + { + double m, d; + if (prec != 0) + { + ipow10(prec, m, d); + if (prec < 0) + _dec /= d; + else + _dec *= m; + } + + if (_dec >= 0.0) + _dec = floorl(_dec + 0.5); + else + _dec = ceill(_dec - 0.5); + + if (prec != 0) + { + if (prec < 0) + _dec *= d; + else + _dec /= m; + } + } + return *this; +} + +real& real::ceil (int prec) +{ + double m, d; + if (prec != 0) + { + ipow10(prec, m, d); + _dec *= m; + } + _dec = ceill(_dec); + if (prec != 0) +// _dec *= d; Risulta stranamente molto impreciso! + _dec /= m; + + return *this; +} + +real& real::floor (int prec) +{ + double m, d; + if (prec != 0) + { + ipow10(prec, m, d); + _dec *= m; + } + _dec = floorl(_dec); + if (prec != 0) +// _dec *= d; Risulta stranamente molto impreciso! + _dec /= m; + + return *this; +} + +real& real::trunc(int prec) +{ + double m, d; + if (prec != 0) + { + ipow10(prec, m, d); + _dec *= m; + } + _dec = floorl(_dec); + if (prec != 0) +// _dec *= d; Risulta stranamente molto impreciso! + _dec /= m; + return *this; +} + + +// @doc EXTERNAL + +// @func Scambia il numero reale

con il numero real

+void swap ( + real& a, // @parm Primo numero da scambiare + real& b) // @parm Secondo numero da scambiare + +{ + const real n = a; + a = b; + b = n; +} + +long double operator%(const real& a, const real& b) +{ + const long double times = floorl(a / b); + const long double resto = a - b * times; + return resto; +} + +long double sqrt(long double a) +{ + return sqrtl(a); +} + +long double sqr(long double a) +{ + return a*a; +} + +long double exp10(long double a) +{ + return powl(10.0, a); +} + +long double pow(long double a, long double b) +{ + return powl(a, b); +} + +long double exp(long double a) +{ + return expl(a); +} + +long double log10(long double a) +{ + return log10l(a); +} + +long double log(long double a) +{ + return logl(a); +} + +long double sin(long double a) +{ + return sinl(a); +} + +long double cos(long double a) +{ + return cosl(a); +} + +long double tan(long double a) +{ + return tanl(a); +} + +long double abs(long double a) +{ + return fabsl(a); +} + +#else + +#include + +extern "C" +{ + double pow (double, double); +} // Should be #include + + +HIDDEN real __tmp_real; + +real::real () +{ + dzero (ptr ()); + trail(); +} + +real::real (const real & b) +{ + dcpy (ptr (), b.ptr ()); +} + +real::real (double a) +{ + dftodr (ptr (), a, 9); // Round the number (1.0 is NOT 0.999999999) + + trail( ); // Delete Trailing zeroes + +} + +void real::set_int64(__int64 b) +{ + TString80 s; s.format("%I64d", b); + + atod (ptr (), (char *) (const char *) s); + trail(); +} + +void real::trail( ) +{ + deltrz (ptr (), ptr () ); // Delete Trailing zeroes +} + +bool real::is_real (const char *s) +{ + bool ok = TRUE; + if (s) + { + while (*s == ' ') + s++; // Remove leading spaces before atod + if (*s) + ok = atod (__tmp_real.ptr (), (char *) s) != GM_NULL; + } + return ok; +} + +real::real (const char *s) +{ + if (s) + while (*s == ' ') + s++; // Remove leading spaces before atod + + if (s && *s) + atod (ptr (), (char *) s); + else + dzero (ptr ()); + + trail(); +} + +real& real::operator =(const real & b) +{ + dcpy (ptr (), b.ptr ()); + return *this; +} + +real& real::operator =(double a) +{ + const real n (a); + operator = (n); + return *this; +} + +real& real::operator += (const real & b) +{ + dadd (ptr (), ptr (), b.ptr ()); + trail( ); + return *this; +} + +real& real::operator += (double a) +{ + adddfd (ptr (), ptr (), a); + trail( ); + return *this; +} + +real& real::operator -= (const real & b) +{ + dsub (ptr (), ptr (), b.ptr ()); + trail( ); + return *this; +} + +real& real::operator *= (const real & b) +{ + dmul (ptr (), ptr (), b.ptr ()); + trail( ); + return *this; +} + +real& real::operator /= (const real & b) +{ + const DEC *dst = ddiv (ptr (), ptr (), b.ptr ()); + +#ifdef DBG + if (dst == GM_NULL) + { + char * s = get_tmp_string().get_buffer(256); + errname (s, gmec ()); + error_box ("Division error: %s", s); + + } +#endif + trail( ); + return *this; +} + +bool real::is_zero () const +{ + return diszero (ptr ()) != 0; +} + +// @doc EXTERNAL + +// @mfunc Ritorna il segno del reale +// +// @rdesc Ritorna i seguenti valori: +// +// @flag 0 | Se il numero e' minore di 0 +// @flag = 0 | Se il numero e' uguale a 0 +// @flag 0 | Se il numero e' maggiore di 0 +int real::sign () const + +{ + return dsign (ptr ()); +} + +real real::operator - () const +{ + real n; + dchgs (n.ptr (), ptr ()); + // n.trail( ); + return n; +} + +long real::integer () const +{ + return (long)dtodf(ptr ()); +} + +// Certified 91% +// @doc EXTERNAL + +// @mfunc Trasforma un reale in stringa +// +// @rdesc Ritorna la stringa nella lunghezza richiesta +const char *real::string ( + int len, // @parm Lunghezza della stringa (compreso decimali) + int dec, // @parm Numero di decimali (default UNDEFINED) + char pad) const // @parm Carattere di riempimento (default ' ') + // @parm char * | picture | Formato della stringa + + // @syntax string (int len, int dec, char pad); + // @syntax string (const char *picture); + // + // @comm Nel primo caso ritorna una stringa lunga

con

decimali e + // inserisce nella stringa stessa il carattere

nel caso la + // lunghezza richiesta sia maggiore di quella che risulterebbe per la + // completa rappresentazione del reale. + // Nel secondo caso ritorna la stringa con il formato stabilito in + //

. + +{ + __tmp_real = *this; + if (dec != UNDEFINED) + __tmp_real.round (dec); + else + __tmp_real.trail(); + + char * s = get_tmp_string().get_buffer(80); + dtoa (s, __tmp_real.ptr ()); + int lun = strlen (s); + + + if (lun < len) + { + const int delta = len - lun; + for (int i = lun; i >= 0; i--) + s[i + delta] = s[i]; + for (i = 0; i < delta; i++) + s[i] = pad; + } + + return s; +} + +// @doc EXTERNAL + +// @func ostream& | operator | Permette di reindirizzare il numero +// reale per la stampa +// +// @rdesc Ritorna l'utput sul quale e' stata reindirizzata la stampa +ostream & operator << ( + ostream & out, // @parm Indica l'output sul quale stampare il numero + const real & a) // @parm Numero da stampare + +{ + return out << a.string (); +} + +// @doc EXTERNAL + +// @func istream& | operator | Permette di leggere un numero reale +// +// @rdesc Ritorna l'output sul quale e' stato letto il numero +istream & operator >> ( + istream & in, // @parm Input da cui leggere il numero + real & a) // @parm Indirizzo in cui posizionare il numero + +{ + TString80 s; + in >> s; + atod (a.ptr (), s.get_buffer()); + + a.trail(); + return in; +} + + +int real::precision() const +{ + return dprec(ptr()); +} + +// @doc EXTERNAL + +// @mfunc real& | real | round | Arrotonda al numero di decimali passati +real & real ::round ( + int prec) // @parm Numero di decimali a cui arrotondare il numero (default 0) + + // @comm Nel caso

sia: + // + // @flag 0 | Arrotonda al decimale + // @flag = 0 | Arrotonda all'intero + // @flag 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille) +{ + if (abs(prec < 20)) + { + if (prec < 0) + { + const double p = ::pow (10.0, -prec); + divdfd (ptr (), ptr (), p); + dround (ptr (), ptr (), 0); + muldfd (ptr (), ptr (), p); + trail(); + } + else + dround (ptr (), ptr (), prec); + } + return *this; +} + +real & real ::ceil (int prec) +{ + double p = 1.0; + if (prec != 0) + { + p = ::pow (10.0, -prec); + divdfd (ptr (), ptr (), p); + } + + DEC integer; + dint (&integer, ptr ()); // Extract the integer part + + if (disgt (ptr (), &integer)) // If positive ... + addid (ptr (), &integer, 1); // ... add 1 + else + dcpy(ptr(), &integer); // If negative + + if (prec != 0) + muldfd (ptr (), ptr (), p); + + trail(); + return *this; +} + +real & real ::floor (int prec) +{ + double p = 1.0; + if (prec != 0) + { + p = ::pow (10.0, -prec); + divdfd (ptr (), ptr (), p); + } + + DEC integer; + dint (&integer, ptr ()); // Extract the integer part + + if (dislt (ptr (), &integer)) // If negative ... + addid (ptr (), &integer, -1); // ... subtract 1 + else + dcpy(ptr(), &integer); // If positive + + if (prec != 0) + muldfd (ptr (), ptr (), p); + + trail(); + return *this; +} + +real & real ::trunc (int prec) +{ + dtrunc (ptr (), ptr (), prec); + return *this; +} + +// @doc EXTERNAL + +// @func real | operator + | Somma due numeri reali +// +// @rdesc Ritorna il valore della somma +real operator + ( + const real & a, // @parm Primo addendo da sommare + const real & b) // @parm Secondo addendo da sommare + + // @syntax operator +(const real &a, const real &b); + // @syntax operator +(double a, const real &b); + // @syntax operator +(const real &a, double b); + +{ + dadd (__tmp_real.ptr (), a.ptr (), b.ptr ()); + return __tmp_real; +} + +real operator + (double a, const real & b) + +{ + __tmp_real = a; + return __tmp_real += b; +} + +real operator + (const real & a, double b) + +{ + __tmp_real = a; + return __tmp_real += b; +} + +// @doc EXTERNAL + +// @func real | operator - | Sottrae due numeri reali +// +// @rdesc Ritorna il valore della sottrazione +real operator - ( + const real & a, // @parm Primo addendo da sottrarre + const real & b) // @parm Secondo addendo da sottrarre + + // @syntax operator -(const real &a, const real &b); + // @syntax operator -(double a, const real &b); + // @syntax operator -(const real &a, double b); +{ + dsub (__tmp_real.ptr (), a.ptr (), b.ptr ()); + __tmp_real.trail(); + return __tmp_real; +} + +real operator - (double a, const real & b) +{ + __tmp_real = a; + dsub (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +real operator - (const real & a, double b) +{ + __tmp_real = -b; + __tmp_real += a; + __tmp_real.trail(); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func real | operator * | Moltiplica due numeri reali +// +// @rdesc Ritorna il valore della moltiplicazione +real operator *( + const real & a, // @parm Primo numero da moltiplicare + const real & b) // @parm Secondo numero da moltiplicare + + // @syntax operator *(const real &a, const real &b); + // @syntax operator *(double a, const real &b); + // @syntax operator *(const real &a, double b); + +{ + dmul (__tmp_real.ptr (), a.ptr (), b.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +real operator *(double a, const real & b) +{ + __tmp_real = a; + dmul(__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +real operator *(const real & a, double b) +{ + __tmp_real = b; + dmul (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func real | operator / | Divide due numeri reali +// +// @rdesc Ritorna il valore della divisione +real operator / ( + const real & a, // @parm Primo numero da dividere + const real & b) // @parm Secondo numero da dividere + + // @syntax operator /(const real &a, const real &b); + // @syntax operator /(double a, const real &b); + // @syntax operator /(const real &a, double b); +{ + ddiv (__tmp_real.ptr (), a.ptr (), b.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +real operator / (double a, const real & b) +{ + __tmp_real = a; + ddiv (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +real operator / (const real & a, double b) +{ + __tmp_real = b; + ddiv (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ()); + __tmp_real.trail( ); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func bool | operator | Controlla se un reale e' maggiore di un altro +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' maggiore di

+// @flag FALSE | Se

e' non maggiore di

+bool operator > ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator (const real &a, const real &b); + // @syntax operator (double a, const real &b); +{ + return disgt (a.ptr (), b.ptr ()) != 0; +} + +bool operator > (double a, const real & b) +{ + // dftod(__tmp_real.ptr(), a); + // return disgt(__tmp_real.ptr(), b.ptr()); + const double n = dtodf (b.ptr ()); + return a > n; +} + +// @doc EXTERNAL + +// @func bool | operator | Controlla se un reale e' minore di un altro +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' minore di

+// @flag FALSE | Se

e' non minore di

+bool operator < ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator (const real &a, const real &b); + // @syntax operator (double a, const real &b); + +{ + return dislt (a.ptr (), b.ptr ()) != 0; +} + +bool operator < (double a, const real & b) + +{ + // dftod(__tmp_real.ptr(), a); + // return dislt(__tmp_real.ptr(), b.ptr()); + const double n = dtodf (b.ptr ()); + return a < n; +} + +// @doc EXTERNAL + +// @func bool | operator = | Controlla se un reale e' maggiore o uguale ad +// un altro +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' maggiore o uguale a

+// @flag FALSE | Se

e' minore di

+bool operator >= ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator = (const real &a, const real &b); + // @syntax operator = (double a, const real &b); + +{ + return disge (a.ptr (), b.ptr ()) != 0; +} + +bool operator >= (double a, const real & b) + +{ + // dftod(__tmp_real.ptr(), a); + // return disge(__tmp_real.ptr(), b.ptr()); + const double n = dtodf (b.ptr ()); + return a >= n; +} + +// @doc EXTERNAL + +// @func bool | operator = | Controlla se un reale e' minore o uguale ad +// un altro +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' minore o uguale a

+// @flag FALSE | Se

e' maggiore di

+bool operator <= ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator = (const real &a, const real &b); + // @syntax operator = (double a, const real &b); +{ + return disle (a.ptr (), b.ptr ()) != 0; +} + +bool operator <= (double a, const real & b) + +{ + // dftod(__tmp_real.ptr(), a); + // return disle(__tmp_real.ptr(), b.ptr()); + const double n = dtodf (b.ptr ()); + return a <= n; +} + +// @doc EXTERNAL + +// @func bool | operator == | Controlla se un reale e' uguale ad un altro +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' uguale a

+// @flag FALSE | Se

non e' uguale a

+bool operator == ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator == (const real &a, const real &b); + // @syntax operator == (double a, const real &b); +{ + return diseq (a.ptr (), b.ptr ()) != 0; +} + +bool operator == (double a, const real & b) +{ + const double n = dtodf (b.ptr ()); + return a == n; +} + +// @doc EXTERNAL + +// @func bool | operator != | Controlla se 2 reali dono diversi +// +// @rdesc Ritorna i seguenti valori +// +// @flag TRUE | Se

e' diverso da

+// @flag FALSE | Se

e' uguale a

+bool operator != ( + const real & a, // @parm Primo numero da conforntare + const real & b) // @parm Secondo numero da confrontare + + // @syntax operator != (const real &a, const real &b); + // @syntax operator != (double a, const real &b); +{ + return !diseq (a.ptr (), b.ptr ()); +} + +bool operator != (double a, const real & b) + +{ + const double n = dtodf (b.ptr ()); + return a != n; +} + +// @doc EXTERNAL + +// @func real | operator % | Ritorna il modulo di due numeri +// +// @rdesc Ritorna il resto della divisione tra due numeri +real operator % ( + const real& a, // @parm Primo membro della divisione + const real& b) // @parm Secondo membro della divisione + +// @syntax long double operator%(const real& a, const real& b) +// @syntax real operator % (const real& a, const real& b) + +{ + const long l = b.integer(); + dmodl (__tmp_real.ptr (), a.ptr (), l); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Scambia il numero reale

con il numero real

+void swap ( + real & a, // @parm Primo numero da scambiare + real & b) // @parm Secondo numero da scambiare + +{ + SwapDecimal (a.ptr (), b.ptr ()); +} + +// @doc EXTERNAL + +// @func Ritorna il numero reale piu' piccolo tra

e

+const real& fnc_min ( + const real & a, // @parm Primo numero da confrontare + const real & b) // @parm Secondo numero da confrontare + // @parm long double | a | Primo numero da confrontare + // @parm long double | b | Secondo numero da confrontare + +// @syntax const real& fnc_min (const real & a, const real & b) +// @syntax inline long double fnc_min(long double a, long double b) + + +{ + dmin (__tmp_real.ptr (), a.ptr (), b.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Ritorna il numero reale piu' grande tra

e

+const real& fnc_max ( + const real & a, // @parm Primo numero da confrontare + const real & b) // @parm Secondo numero da confrontare + // @parm long double | a | Primo numero da confrontare + // @parm long double | b | Secondo numero da confrontare + +// @syntax const real& fnc_max (const real & a, const real & b) +// @syntax inline long double fnc_max(long double a, long double b) + +{ + dmax (__tmp_real.ptr (), a.ptr (), b.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Ritorna la radice quadrata del numero +real sqrt ( + const real & a) // @parm Numero del quale calcolare la radice + // @parm long double | a | Numero del quale calcolare la radice + +// @syntax real sqrt (const real) +// @syntax long double sqrt(long double) + +{ + dsqrt (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Ritorna il quadarato del numero +real sqr ( + const real & a) // @parm Numero del quale calcolare il quadrato + // @parm long double | a | Numero del quale calcolare il quadrato + +// @syntax real sqr (const real) +// @syntax long double sqr(long double) + +{ + dmul (__tmp_real.ptr (), a.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola 10 a potenza

+real exp10 ( + const real & a) // @parm Esponente al quale elevare + // @parm long double | a | Esponente al quale elevare + +// @syntax real exp10 (const real) +// @syntax long double exp10 (long double) + + +{ + dalog (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola l'elevamento a potenza

del numero

+real pow ( + const real & a, // @parm Numero da elevare a potenza + const real & b) // @parm Esponente + // @parm long double | a | Numero da elevare a potenza + // @parm long double | b | Esponente + +// @syntax real pow (const real & a, const real & b) +// @syntax long double pow(long double a, long double b) + +{ + dpow (__tmp_real.ptr (), a.ptr (), b.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola e (nepero) elevato ad

+real exp ( + const real & a) // @parm Esponente + // @parm long double | a | Esponente + +// @syntax real exp (const real & a) +// @syntax long double exp(long double a) + +{ + dexp (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola il logaritmo in base 10 del numero +real log10 ( + const real & a) // @parm Numero del quale calcolare il logaritmo + // @parm long double | a | Numero del quale calcolare il logaritmo + +// @syntax real log10 (const real & a) +// @syntax long double log10(long double a) + +{ + dlog (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcoa il logaritmo naturale (base e) del numero +real log ( + const real & a) // @parm Numero del quale calcolare il logaritmo + // @parm long double | a | Numero del quale calcolare il logaritmo + +// @syntax real log (const real & a) +// @syntax long double log(long double a) + +{ + dln (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola il seno dell'angolo +real sin ( + const real & a) // @parm Angolo passato in radianti + // @parm long double | a | Angolo passato in radianti + +// @syntax real sin (const real & a) +// @syntax long double sin (long double a) + +{ + dsin (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola il coseno dell'angolo +real cos ( + const real & a) // @parm Angolo passato in radianti + // @parm long double | a | Angolo passato in radianti + +// @syntax real cos (const real & a) +// @syntax long double cos (long double a) + + +{ + dcos (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Calcola la tangente dell'angolo +real tan ( + const real & a) // @parm Angolo passato in radianti + // @parm long double | a | Angolo passato in radianti + +// @syntax real tan (const real & a) +// @syntax long double tan (long double a) + + +{ + dtan (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +// @doc EXTERNAL + +// @func Ritorna il valore assoluto di un numero +real abs ( + const real & a) // @parm Numero del quale si vuole conoscere il valore assoluto + // @parm long double | a | Numero del quale si vuole conoscere il valore assoluto + +// @syntax real abs (const real & a) +// @syntax long double abs(long double a) + +{ + dabs (__tmp_real.ptr (), a.ptr ()); + return __tmp_real; +} + +#endif + +// Funzioni comuni dei due real + +TObject* real::dup () const +{ + return new real(*this); +} + +const char *real::eng2ita (char *s) +{ + if (s) + { + char *dot = strchr (s, '.'); + if (dot) + *dot = ','; + } + return s; +} + +// Elimina gli spazi ed i punti, converte le virgole in punti +const char *real::ita2eng (const char *s) +{ + TString& tmp = get_tmp_string(); + char* __string = tmp.get_buffer(strlen(s)); + + int j = 0; + if (s) + for (int i = 0; s[i]; i++) + { + switch (s[i]) + { + case ' ': + case '.': + break; + case ',': + __string[j++] = '.'; + break; + default: + __string[j++] = s[i]; + break; + } + } + __string[j] = '\0'; + return __string; +} + +bool real::is_null(const char *s) +{ + bool z = TRUE; + if (s != NULL) for (const char* n = s; *n; n++) + { + if (strchr("123456789", *n) != NULL) + { + z = FALSE; + break; + } + if (strchr(" ,-.0", *n) == NULL) + break; + } + return z; +} + +bool real::is_natural (const char *s) +{ + bool ok = s && *s != '\0'; + if (ok) + { + while (*s == ' ') + s++; // Remove leading spaces before + + if (*s) + { + while (isdigit(*s)) + s++; + ok = *s == '\0'; + } + else + ok = FALSE; + } + return ok; +} + +// Certified 75% +const char* real::literals() const +{ + const char *primi20[] = + {"", "uno", "due", "tre", "quattro", + "cinque", "sei", "sette", "otto", + "nove", "dieci", "undici", "dodici", + "tredici", "quattordici", "quindici", "sedici", + "diciassette", "diciotto", "diciannove"}; + const char *decine[] = + {"zero", "dieci", "venti", "trenta", "quaranta", + "cinquanta", "sessanta", "settanta", "ottanta", + "novanta", "cento"}; + const char *uni[] = + {"uno", "mille", "unmilione", "unmiliardo"}; + + const char *potenze[] = + {"", "mila", "milioni", "miliardi"}; + + real tmp_real = *this; + tmp_real.trunc(); + + TString r (tmp_real.string (0, 0)); + const bool negativo = r[0] == '-'; + if (negativo) + r.ltrim (1); + + TString& risultato = get_tmp_string(128); + risultato.cut (0); + + TString centinaia; + + for (int migliaia = 0;; migliaia++) + { + int v = r.len () - 3; + if (v < -2) + break; + + if (v < 0) + v = 0; + const int val = atoi (&r[v]); + r.cut (v); // Elimina ultimi 3 caratteri + + v = val; + if (v >= 100) + { + const int c = v / 100; + if (c > 1) + centinaia = primi20[c]; + else + centinaia.cut(0); + v -= c * 100; + centinaia << "cento"; + } else centinaia.cut(0); + const int d = v / 10; + if (d > 1) + { + if (d == 8 && centinaia.right(1)[0] == 'o') + centinaia.rtrim(1); + centinaia << decine[d]; + v -= d * 10; + } + + if (val > 0) + { + if (v != 1) + { + if (v == 8) + centinaia.rtrim(1); + centinaia << primi20[v] << potenze[migliaia]; + } + else if (val > 1) + { + if (d > 1) + centinaia.rtrim(1); + centinaia << "un" << (migliaia ? potenze[migliaia] : "o"); + } + else + centinaia = uni[migliaia]; + } + + risultato.insert(centinaia, 0); + } + + if (tmp_real != *this) // Ci sono dei decimali! + { + TString80 res = risultato; + const real tmp_dec = abs(*this - tmp_real); + TString80 str = tmp_dec.string(); + str.ltrim(2); str.cut(3); + res << '/' << str; + risultato = res; + } + + if (negativo) + risultato.insert ("meno", 0); + return risultato; +} + +// Certified 75% +const char* real::points (int dec) const +{ + const char *str = stringa (0, dec); + const int neg = (*str == '-') ? 1 : 0; + TFixed_string n ((char *)str, 64); + int i; + + int dot = n.find (','); + if (dot < 0) + dot = n.len (); + + if (dec > 0) + { + if (n[dot] == '\0') + n << ','; + const int d = strlen (str + dot + 1); // Decimals already there + + if (d <= dec) + for (i = d; i < dec; i++) + n << '0'; + else + n.cut (dot + dec + 1); + } + + for (i = dot - 3; i > neg; i -= 3) + n.insert (".", i); + + return str; +} + +HIDDEN int get_picture_decimals (const TString& picture, char& decsep) +{ + int decimali = 0; + int virgola = -1; + + if (decsep == ',') + { + int firstcomma = -1, lastcomma = -1, firstdot = -1, lastdot = -1; + for (int i = 0; picture[i]; i++) + { + if (picture[i] == ',') + { + if (firstcomma < 0) firstcomma = i; + lastcomma = i; + } + else if (picture[i] == '.') + { + if (firstdot < 0) firstdot = i; + lastdot = i; + } + } + if (lastcomma >= 0 && lastdot >= 0) + { + virgola = lastcomma > lastdot ? lastcomma : lastdot; + decsep = picture[virgola]; + } + else + if (lastcomma >= 0) virgola = lastcomma; + } + else virgola = picture.find('.'); + + if (virgola >= 0) + { + const int len = picture.len (); + for (int i = virgola + 1; i < len; i++) + if (strchr ("#@^", picture[i])) + decimali++; + } + return decimali; +} + +const char* real::string(const char *picture) const +{ + if (*picture == '\0') + return string (); + if (*picture == '.') + return points (atoi (picture + 1)); + if (stricmp (picture, "LETTERE") == 0) + return literals (); + + TString v (string()); + TString& f = get_tmp_string(); + f = picture; + + char decsep = ','; // Separatore dei decimali + if (f[f.len() - 1] == 'E') + { + f.rtrim(1); + decsep = '.'; + } + + // Calcola il numero di decimali voluti ed eventualmente + // determina il vero separatore dei decimali + const int voluti = get_picture_decimals (f, decsep); + const char migsep = decsep == '.' ? ',' : '.'; // Separatore delle migliaia + + const int virgola = v.find ('.'); // v e' la nostra cifra, certamente in english format + int decimali = (virgola >= 0) ? v.len () - virgola - 1 : 0; + + for (; voluti > decimali; decimali++) + v << '@'; + if (voluti < decimali) + v.cut (virgola + voluti + (voluti > 0)); + + int j = v.len () - 1; + bool sign(FALSE); + for (int i = f.len () - 1; i >= 0 && j >= 0; i--) + { + char &z = f[i]; + if (strchr ("#@^", z)) + { + char c = v[j--]; + if (j >= 0 && v[j] == '.') + j--; + if (z == '^') + c = ' '; + else + { + if (c == '@') + c = (z == '@') ? '0' : ' '; + else + if (c == '-') + { + if (z == '@') // Altrimenti -10 con picture @@@@@ diventa "00-10" + { + if (f[i+1] == migsep) + f[i+1] = '0'; + sign=TRUE; // posticipa l'append del segno + i++; + c=z; + } else { + if (f[i+1] == migsep ) // Altrimenti -100 diventa -.100 + { + f[i+1] = '-'; + c = ' '; //OK + } + } + } + } + + z = c; + } + } + for (int i2=0; i2 <= i; i2++) + if (f[i2] == '@') + { + if (sign) + { + f[i2] = '-'; // add sign in first pos + sign=FALSE; + } + else + f[i2] = '0'; + } + for (; i >=0 ; i--) + switch (f[i]) + { + case '#': + case '^': + case '.': + case ',': + f[i] = ' '; + break; + default: + break; + } + return f; +} + +// Certified 99% +const char* real::stringa (int len, int dec, char pad) const +{ + char* str = (char*)string(len, dec, pad); + if (dec > 0 || dec == UNDEFINED) + eng2ita (str); + return str; +} + +void real::print_on(ostream& out) const +{ + out << string(); +} + +/////////////////////////////////////////////////////////// +// Distrib +// Oggetto per dividere un real in varie sue percentuali +// in modo che la loro somma dia sempre il real di partenza +// ///////////////////////////////////////////////////////// + +void TDistrib::add(real slice) +{ + if (slice > real (1.0)) + slice /= 100.0; + CHECK (!_ready, "TDistrib: les jeux sont faits"); + _slices.add (slice); +} + +real TDistrib::get () +{ + _ready = TRUE; + CHECK (_current < _slices.items(), "TDistrib: too many gets"); + real r = _tot * ((real &) _slices[_current++]); + r.round (_decs); + if (r > _tot - _prog) + { + r = _tot - _prog; _prog = _tot; + } + else + _prog += r; + return r; +} + +// @doc EXTERNAL + +// @mfunc Inizializza l'oggetto +void TDistrib::init ( + const real & r, // @parm Importo da dividere + bool zap) // @parm Permette di cancellare le percenutali immesse (default FALSE) + + // @comm Se

e' vero cancella tutte le percentuali immesse, altrimenti + // cambia solo il totale +{ + _current = 0; _prog = 0; + _tot = r; _ready = FALSE; + if (zap) _slices.destroy(); +} + +/////////////////////////////////////////////////////////// +// Generic_distrib +// Oggetto per dividere un real in parti prefissate +// in modo che la loro somma dia sempre il real di partenza +// ///////////////////////////////////////////////////////// + + +void TGeneric_distrib::add(real slice) +{ + CHECK (!_ready, "TGeneric_distrib: les jeux sont faits"); + _totslices += slice; + _slices.add (slice); +} + +real TGeneric_distrib::get () +{ + _ready = TRUE; + CHECK (_current < _slices.items(), "TGeneric_distrib: too many gets"); + real & currslice = (real &) _slices[_current++]; + real r = currslice; + if (_tot != _totslices) + { + if (_tot < 1E9 && currslice < 1E9) + r = (_tot * currslice) / _totslices; + else + r *= (_tot / _totslices); + } + r.round (_decs); + _tot -= r; + _totslices -= currslice; + return r; +} + +// @doc EXTERNAL + +// @mfunc Inizializza l'oggetto +void TGeneric_distrib::init ( + const real & r, // @parm Importo da dividere + bool zap) // @parm Permette di cancellare le percenutali immesse + // (default FALSE) + + // @comm Se

e' vero cancella tutte le percentuali immesse, altrimenti + // cambia solo il totale +{ + _current = 0; _totslices = 0; + _tot = r; _ready = FALSE; + if (zap) _slices.destroy(); + else + { + const int items = _slices.items(); + for (int i = 0; i < items; i++) + _totslices += (real &) _slices[i]; + } +} + +/////////////////////////////////////////////////////////// +// Importo +/////////////////////////////////////////////////////////// + +const TImporto& TImporto::add_to(TToken_string& s, int pos) const +{ + const bool dare = sezione() == 'D'; + const char* v = valore().string(); + s.add(dare ? v : "", pos); + s.add(dare ? "" : v, pos+1); + return *this; +} + +// Cerified 99% +const TImporto& TImporto::operator =(TToken_string& sv) +{ + _valore = real(sv.get(0)); + if (_valore.is_zero()) + { + _valore = real(sv.get()); + _sezione = 'A'; + } + else + _sezione = 'D'; + return *this; +} + + +const TImporto& TImporto::set(char s, const real& v) +{ + if (s <= ' ' && v.is_zero()) // Accetta sezioni nulle per importi nulli + s = 'D'; + CHECKD(s == 'D' || s == 'A', "Sezione errata per importo: codice ", (int)s); + _sezione = s; _valore = v; + return *this; +} + + +const TImporto& TImporto::operator += (const TImporto& i) +{ + if (_valore.is_zero()) + _sezione = i._sezione; + + if (_sezione == i._sezione) + _valore += i._valore; + else + _valore -= i._valore; + return *this; +} + + +const TImporto& TImporto::operator -= (const TImporto& i) +{ + if (_valore.is_zero()) + _sezione = i._sezione; + + if (_sezione == i._sezione) + _valore -= i._valore; + else + _valore += i._valore; + return *this; +} + + +const TImporto& TImporto::swap_section() +{ + _sezione = (_sezione == 'D') ? 'A' : 'D'; + return *this; +} + + +// @doc EXTERNAL + +// @mfunc Normalizza il segno o la sezione in base al parametro s +const TImporto& TImporto::normalize( + char s) // @parm Tipo di normalizzazione da effettuare: + // + // @flag A | Forza la sezione Avere + // @flag D | Forza la sezione Dare + // @flag 0 | Forza il segno negativo + // @flag =0 | Forza il segno positivo + +{ + bool ex = FALSE; + switch (s) + { + case 'A': + case 'D': + ex = s != _sezione; + break; + default: + if (s < 0) + ex = _valore.sign() > 0; + else + ex = _valore.sign() < 0; + break; + } + if (ex) + { + _valore = -_valore; + swap_section(); + } + return *this; +} + + +int TImporto::compare(const TSortable& s) const +{ + const TImporto& i = (const TImporto&)s; + const real v = i.sezione() == sezione() ? i.valore() : -i.valore(); + const real d = valore() - v; + const int res = d.sign(); + return res; +} + +bool TImporto::is_zero() const +{ +#ifdef __LONGDOUBLE__ + return fabsl(_valore) < 0.00001; +#else + return _valore.is_zero(); +#endif +} \ No newline at end of file diff --git a/omnia/real.h b/omnia/real.h new file mode 100755 index 000000000..48c28f30f --- /dev/null +++ b/omnia/real.h @@ -0,0 +1,508 @@ +#ifndef __REAL_H +#define __REAL_H + +#ifndef __STRINGS_H +#include "strings.h" +#endif + +#define ALL_DECIMALS 883 +#define AUTO_DECIMALS -883 +#define AUTO_PRICES_DECIMALS -884 + +#ifdef __LONGDOUBLE__ + +// @doc EXTERNAL + +// @class real | Classe per la gestione dei numeri reali +// +// @base public | TObject +class real : public TObject + +// @comm Questa classe utilizza i long double definiti per Visual C++. Esiste un'altra classe +// real: per accedere scegliere il tasto successivo () dalla barra dei bottoni + +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Numero reale + long double _dec; + + // @access Protected Member +protected: + // @cmember Permette di stampare l'oggetto + virtual void print_on(ostream& out) const; + + // @cmember Duplica il numero reale (vedi classe ) + virtual TObject* dup() const; + // @cmember Traduce in lettere il numero reale + const char* literals() const; + // @cmember Inserisce i punti separatori delle migliaia e riempe i decimali + // alla lunghezza passata (es: 3.000,20) + const char* points(int decimals = 0) const; + + // @access Public Member +public: + // @cmember long double | operator long double | | Ritorna il numero reale + operator long double () const + { return _dec; } + + // @cmember Trasforma un numero dal formato inglese (decimali con punto) in + // formato italiano (decimali con virgola) + static const char* eng2ita(char* s); + // @cmember Trasforma un numero dal formato italiano (decimali con virgola) in + // formato inglese (decimali con punto) + static const char* ita2eng(const char* s); + // @cmember Controlla se si tratta di un numero reale (TRUE se vero) + static bool is_real(const char* n); + // @cmember Controlla se si tratta di un numero naturale intero (TRUE se vero) + static bool is_natural(const char* n); + // @cmember Controlla se si tratta di uno zero (TRUE se vero) + static bool is_null(const char* n); + // @cmember Trasforma un reale in stringa + const char* string(int len = 0, int dec = UNDEFINED, char pad = ' ') const; + // @cmember Trasforma un reale in stringa (chiama ), ma + // ritorna il formato italiano + const char* stringa(int len = 0, int dec = UNDEFINED, char pad = ' ') const; + // @cmember Ritorna la stringa con il formato passato + const char* string(const char* picture) const; + + // @cmember Ritorna la precisione del reale (numero di decimali) + int precision() const; + // @cmember Controlla se si tratta di un reale uguale 0 (TRUE se 0) + bool is_zero() const + { return _dec == 0.0; } + // @cmember Ritorna il segno del reale + int sign() const; + // @cmember Trasforma il reale in intero (operator int era troppo pericoloso) + long integer() const; + + // @cmember Arrotonda al numero di decimali passati + real& round(int prec = 0) ; + // @cmember Tronca al numero di decimali passati (default 0) + real& trunc(int prec = 0) ; + // @cmember Arrotonda al numero successivo (della precisione passata) + real& ceil(int prec = 0); + // @cmember Arrotonda al numero precedente (della precisione passata) + real& floor(int prec = 0); + // @cmember Assegna un reale + real& operator = (const real& a); + // @cmember Assegna un reale + real& operator =(long double a); + // @cmember Assegna un __int64 ad un reale + void set_int64(__int64 b); + // @cmember Aggiunge ad un reale il valore passato (passato per indirizzo) + real& operator +=(long double a); + // @cmember Sottrae ad un reale il valore passato (passato per indirizzo) + real& operator -=(long double b); + // @cmember Moltiplica un reale per il valore passato (passato per indirizzo) + real& operator *=(long double b); + // @cmember Divide un reale per il valore passato (passato per indirizzo) + real& operator /=(long double b); + // @cmember Ritorna la negazione di un reale (TRUE se 0, altrimenti FALSE) + bool operator !() const + { return _dec == 0.0; } + // @cmember Ritorna il risultato della differenza tra due reali + real operator -() const; + + // @cmember Costruttore + real(); + // @cmember Costruttore + real(const real& b); + // @cmember Costruttore + real(long double a); + // @cmember Costruttore + real(const char* s); + // @cmember Distruttore + virtual ~real() + {} +}; + +inline long double fnc_min(long double a, long double b){ return a < b ? a : b; } +inline long double fnc_max(long double a, long double b) { return a > b ? a : b; } + +long double operator%(const real& a, const real& b); +void swap(real& a, real& b) ; +long double sqrt(long double) ; +long double sqr(long double) ; +long double exp10(long double) ; +long double pow(long double, long double) ; +long double exp(long double a) ; +long double log10(long double a) ; +long double log(long double a) ; +long double sin(long double a) ; +long double cos(long double a) ; +long double tan(long double a) ; +long double abs(long double a) ; + +#else + +#ifndef __IOSTREAM_H +#include +#endif + +#ifndef GMDOTH +#include "../gfm/gmsys1.h" +#include "../gfm/gfd.h" +#endif + +// @doc EXTERNAL + +// @class real (per GREENLEAF) | Classe per la gestione dei numeri reali +// +// @base public | TObject +class real : public TObject + +// @comm Questa classe utilizza i DEC definiti per GREENLEAF. Esiste un'altra classe +// real: per accedere scegliere il tasto precedente () dalla barra deo bottoni + +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Numero reale + DEC _dec; + + // @access Protected Member +protected: + // @cmember Permette di stampare l'oggetto + virtual void print_on(ostream& out) const; + + // @cmember Duplica il numero reale (vedi classe ) + virtual TObject* dup() const; + // @cmember Traduce in lettere il numero reale + const char* literals() const; + // @cmember Inserisce i punti separatori delle migliaia e riempe i decimali + // alla lunghezza passata (es: 3.000,20) + const char* points(int decimals = 0) const; + + // @access Public Member +public: + + + // @cmember Rimuove gli zeri prima della virgola, aggiustando la precisione + void trail( ); + + // @cmember Trasforma un numero dal formato inglese (decimali con punto) in + // formato italiano (decimali con virgola) + static const char* eng2ita(char* s); + // @cmember Trasforma un numero dal formato italiano (decimali con virgola) in + // formato inglese (decimali con punto) + static const char* ita2eng(const char* s); + // @cmember Controlla se si tratta di un numero reale (TRUE se vero) + static bool is_real(const char* n); + // @cmember Controlla se si tratta di un numero naturale intero (TRUE se vero) + static bool is_natural(const char* n); + // @cmember Controlla se si tratta di uno zero (TRUE se vero) + static bool is_null(const char* n); + + // @cmember Ritorna l'indirizzo del numero reale + DEC* ptr() const + { return (DEC*)&_dec; } + // @cmember Trasforma un reale in stringa + const char* string(int len = 0, int dec = UNDEFINED, char pad = ' ') const; + // @cmember Trasforma un reale in stringa (chiama ), ma + // ritorna il formato italiano + const char* stringa(int len = 0, int dec = UNDEFINED, char pad = ' ') const; + // @cmember Ritorna la stringa con il formato passato + const char* string(const char* picture) const; + + // @cmember Ritorna la precisione del reale (numero di decimali) + int precision() const; + // @cmember Controlla se si tratta di un reale uguale 0 (TRUE se 0) + bool is_zero() const; + // @cmember Ritorna il segno del reale + int sign() const; + // @cmember Trasforma il reale in intero (operator int era troppo pericoloso) + long integer() const; + + // @cmember Arrotonda al numero di decimali passati + real& round(int prec = 0) ; + // @cmember Tronca al numero di decimali passati (default 0) + real& trunc(int prec = 0) ; + // @cmember Arrotonda al numero successivo (della precisione passata) + real& ceil(int prec = 0); + // @cmember Arrotonda al numero precedente (della precisione passata) + real& floor(int prec = 0); + // @cmember Assegna un reale + real& operator =(double a); + // @cmember Assegna un __int64 ad un reale + void set_int64(__int64 b); + // @cmember Assegna un reale (passato per indirizzo) + real& operator =(const real& b); + // @cmember Aggiunge ad un reale il valore passato (passato per indirizzo) + real& operator +=(const real& b); + // @cmember Aggiunge ad un reale il valore passato + real& operator +=(double a); + // @cmember Sottrae ad un reale il valore passato (passato per indirizzo) + real& operator -=(const real& b); + // @cmember Moltiplica un reale per il valore passato (passato per indirizzo) + real& operator *=(const real& b); + // @cmember Divide un reale per il valore passato (passato per indirizzo) + real& operator /=(const real& b); + // @cmember Ritorna la negazione di un reale (TRUE se 0, altrimenti FALSE) + bool operator !() const + { return is_zero(); } + // @cmember Ritorna il risultato della differenza tra due reali + real operator -() const; + + // @cmember Costruttore + real(); + // @cmember Costruttore + real(const real& b); + // @cmember Costruttore + real(double a); + // @cmember Costruttore + real(const char* s); + // @cmember Distruttore + virtual ~real() + {} +}; + +/////////////////////////////////////////////////////////// +// Math operators +/////////////////////////////////////////////////////////// + +ostream& operator <<(ostream& out, const real& a) ; +istream& operator >>(istream& in, real& a) ; + +real operator +(const real& a, const real& b) ; +real operator +(double a, const real& b) ; +real operator +(const real& a, double b) ; +real operator -(const real& a, const real& b) ; +real operator -(double a, const real& b) ; +real operator -(const real& a, double b) ; +real operator *(const real& a, const real& b) ; +real operator *(double a, const real& b) ; +real operator *(const real& a, double b) ; +real operator /(const real& a, const real& b) ; +real operator /(double a, const real& b) ; +real operator /(const real& a, double b) ; + +bool operator <(const real& a, const real& b) ; +bool operator <(double a, const real& b) ; +bool operator >(const real& a, const real& b) ; +bool operator >(double a, const real& b) ; +bool operator <=(const real& a, const real& b) ; +bool operator <=(double a, const real& b) ; +bool operator >=(const real& a, const real& b) ; +bool operator >=(double a, const real& b) ; +bool operator ==(const real& a, const real& b) ; +bool operator ==(double a, const real& b) ; +bool operator !=(const real& a, const real& b) ; +bool operator !=(double a, const real& b) ; + +inline bool operator <(const real& a, double b) { return operator >(b, a); } +inline bool operator >(const real& a, double b) { return operator <(b, a); } +inline bool operator <=(const real& a, double b) { return operator >=(b, a); } +inline bool operator >=(const real& a, double b) { return operator <=(b, a); } +inline bool operator ==(const real& a, double b) { return operator ==(b, a); } +inline bool operator !=(const real& a, double b) { return operator !=(b, a); } + +real operator %(const real& a, const real& b) ; +void swap(real& a, real& b) ; +const real& fnc_min(const real& a, const real& b) ; +const real& fnc_max(const real& a, const real& b) ; +real sqrt(const real& a) ; +real sqr(const real& a) ; +real exp10(const real& a) ; +real pow(const real& a, const real& b) ; +real exp(const real& a) ; +real log10(const real& a) ; +real log(const real& a) ; +real sin(const real& a) ; +real cos(const real& a) ; +real tan(const real& a) ; +real abs(const real& a) ; + +#endif + +// TReal implementato coi maledetti DEC + +extern const real ZERO; +extern const real UNO; +extern const real CENTO; + +// @doc EXTERNAL + +// @class TDistrib | Classe per dividere un in varie sue percentuali +// in modo che la loro somma dia sempre il real di partenza +// +// @base public | TObject +class TDistrib : public TObject + +// @author:(INTERNAL) Guido +{ + + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Totale da ripartire + real _tot; + // @cmember:(INTERNAL) Progressivo gia' distribuito + real _prog; + // @cmember:(INTERNAL) Pronto per essere usato (tutti gli fatti) + bool _ready; + // @cmember:(INTERNAL) Percentuali da distribuire + TArray _slices; + // @cmember:(INTERNAL) Indice delle percentuali aggiunte o estratte + int _current; + // @cmember:(INTERNAL) Precisione + int _decs; + + // @access Public Member +public: + + // @cmember Aggiunge una percentuale per la ripartizione + void add(real slice); + // @cmember Ritorna il successivo degli importi suddivisi + real get(); + + // @cmember Inizializza il numero di decimali + void set_dec(int decs) { _decs = decs;} + + // @cmember Inizializza l'oggetto + void init(const real& r, bool zap = FALSE); + + // @cmember Assegnamento di un importo + void operator =(const real& r) + { init(r); } + // @cmember Ritorna l'ultima percentuale aggiunta + const real& last_slice() const + { + CHECK(_current,"TDistrib: slices not set"); + return (const real&)_slices[_current-1]; + } + + // @cmember Costruttore + TDistrib(const real& r,int round=UNDEFINED) : _prog(0.0),_tot(r),_ready(FALSE),_current(0),_decs(round),_slices(4) + {} + // @cmember Distruttore + virtual ~TDistrib() + {} +}; + +// @doc EXTERNAL + +// @class TGeneric_distrib | Classe per dividere un real in parti fissate +// in modo che la loro somma dia sempre il real di partenza +// +// @base public | TObject + +class TGeneric_distrib : public TObject +{ + + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Totale da ripartire + real _tot; + // @cmember:(INTERNAL) Totale parti da distribuire + real _totslices; + // @cmember:(INTERNAL) Pronto per essere usato (tutti gli add() fatti) + bool _ready; + // @cmember:(INTERNAL) Percentuali da distribuire + TArray _slices; + // @cmember:(INTERNAL) Indice delle percentuali aggiunte o estratte + int _current; + // @cmember:(INTERNAL) Precisione + int _decs; + + // @access Public Member +public: + + // @cmember Aggiunge una percentuale per la ripartizione + virtual void add(real slice); + // @cmember Ritorna il successivo degli importi suddivisi + virtual real get(); + + // @cmember Inizializza il numero di decimali + void set_dec(int decs) + { _decs = decs;} + + // @cmember Inizializza l'oggetto + void init(const real& r, bool zap = FALSE); + + // @cmember Assegnamento di un importo + void operator =(const real& r) + { init(r); } + // @cmember Ritorna l'ultima percentuale aggiunta + const real& last_slice() const + { + CHECK(_current,"TGeneric_distrib: slices not set"); + return (const real&)_slices[_current-1]; + } + + // @cmember Costruttore + TGeneric_distrib(const real& r,int round=0) : _totslices(0.0),_tot(r),_ready(FALSE),_current(0),_decs(round),_slices(4) + {} + // @cmember Distruttore + virtual ~TGeneric_distrib() + {} +}; + +// @doc EXTERNAL + +// @class TImporto | Classe per la definizione di oggetti con sezione e importo +// +// @base public | TSortable +class TImporto : public TSortable +// @author:(INTERNAL) Guido +{ + + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Sezione alla quale apprtiene l'importo + char _sezione; + // @cmember:(INTERNAL) Valore dell'importo + real _valore; + + // @access Protected Member +protected: + // @cmember Permette la comparazione degli importi (0 se uguali in valore + // ed importo) + virtual int compare(const TSortable& s) const; + + // @access Public Member +public: + // @cmember Ritorna la sezione dell'importo + char sezione() const + { return _sezione; } + // @cmember Ritorna il valore dell'importo + const real& valore() const + { return _valore; } + // @cmember Ritorna il valore dell'importo + real& valore() + { return _valore; } + + // @cmember Controlla se l'importo e' 0 (in qualsiasi sezione, TRUE se 0) + bool is_zero() const; + + // @cmember Assegna l'importo passato + const TImporto& operator=(const TImporto& i) + { return set(i.sezione(), i.valore()); } + // @cmember Assegna l'importo da una (sezione ambigua se + // ZERO) + const TImporto& operator=(TToken_string& sv); + // @cmember Aggiunge all'importo l'oggetto passato + const TImporto& operator+=(const TImporto& i); + // @cmember Sottrae all'importo l'oggetto passato + const TImporto& operator-=(const TImporto& i); + // @cmember Normalizza il segno o la sezione in base al parametro s + const TImporto& normalize(char s = '\0'); + // @cmember Inverte la sezione dell'importo + const TImporto& swap_section(); + + // @cmember Assegna sezione ed importo all'oggetto + const TImporto& set(char s, const real& v); + // @cmember Setta i due elementi pos e pos+1 della + // al valore dell'importo, lasciando bianco il dare (pos) o l'avere (pos+1) + const TImporto& add_to(TToken_string& s, int pos) const; + + // @cmember Costruttore + TImporto(char s = 'D', const real& v = ZERO) + { set(s, v); } + // @cmember Costruttore (copia l'oggetto) + TImporto(const TImporto& i) : _sezione(i._sezione), _valore(i._valore) + {} +}; + +#endif // __REAL_H diff --git a/omnia/stack.cpp b/omnia/stack.cpp new file mode 100755 index 000000000..68461f6bc --- /dev/null +++ b/omnia/stack.cpp @@ -0,0 +1,42 @@ +#include "stack.h" + +TStack::TStack(int size) : _data(size), _sp(0) +{ } + +TStack::TStack(const TStack& stack) : _data(stack._data), _sp(0) +{ } + +void TStack::push(const TObject& o) +{ + _data.add(o, _sp++); +} + +void TStack::push(TObject* o) +{ + _data.add(o, _sp++); +} + +TObject& TStack::pop() +{ + CHECK(_sp > 0, "Stack underflow!"); + return _data[--_sp]; +} + +TObject& TStack::peek(int depth) const +{ + CHECKD(depth >= 0 && depth < _sp, "Stack depth error: ", depth); + return _data[_sp-depth-1]; +} + +void TStack::destroy() +{ + _data.destroy(); + _sp = 0; +} + +bool TStack::destroy_base() +{ + if (_sp > 0) _sp--; + return _data.destroy(0, TRUE); +} + diff --git a/omnia/stack.h b/omnia/stack.h new file mode 100755 index 000000000..2a5a0e836 --- /dev/null +++ b/omnia/stack.h @@ -0,0 +1,51 @@ +#ifndef __STACK_H +#define __STACK_H + +#ifndef __ARRAY_H +#include "array.h" +#endif + +// @doc EXTERNAL + +// @class TStack | Classe per la gestione dello stack a basso livello +// +// @base public | TObject +class TStack : public TObject + +// @author:(INTERNAL) Alex + +// @access:(INTERNAL) Private Member +{ +protected: + // @cmember:(INTERNAL) Dati dello stack + TArray _data; + + // @cmember:(INTERNAL) Puntatore alla cima dello stack + int _sp; + +// @access Public Member +public: + // @cmember Ritorna il puntatore allo stack + int count() const + { return _sp; } + // @cmember Aggiunge un oggetto sullo stack + void push(const TObject& o); + // @cmember Aggiunge un oggetto sullo stack + void push(TObject* o); + // @cmember Ritorna il primo oggetto sulla cima dello stack + TObject& pop(); + // @cmember Ritorna l'oggetto ad una data profondita' nello stack + TObject& peek(int depth = 0) const; + // @cmember Distrugge l'intero stack + void destroy(); + // @cmember Distrugge l'oggetto alla base dello stack + bool destroy_base(); + // @cmember Costruttore. Chiama il costruttore di + TStack(int size = 16); + // @cmember Costruttore. Chiama il costruttore di + TStack(const TStack& stack); + // @cmember Distruttore. Chiama il distruttore di + virtual ~TStack() { } +}; + +#endif diff --git a/omnia/xml.cpp b/omnia/xml.cpp index d28203752..82db32e4d 100755 --- a/omnia/xml.cpp +++ b/omnia/xml.cpp @@ -171,8 +171,8 @@ TXmlItem* TXmlItem::GetChild(size_t n) const return i; } - -bool TXmlItem::GetWord(istream& inf, TString& str) const +// 0 = Nulla; 1 = Simbolo terminale; 2 = Stringa tra apici; 3 = parola qualsiasi +int TXmlItem::GetWord(istream& inf, TString& str) const { str.cut(0); @@ -184,14 +184,14 @@ bool TXmlItem::GetWord(istream& inf, TString& str) const break; } if (cFirstChar == EOF) - return false; + return 0; const bool bIsString = cFirstChar == '"' || cFirstChar == '\''; if (!bIsString) { - str << char(cFirstChar); + str << char(cFirstChar); if (strchr("<=/>", cFirstChar) != NULL) - return true; // Simboli terminali + return 1; // Simboli terminali } while (!inf.eof()) @@ -217,17 +217,25 @@ bool TXmlItem::GetWord(istream& inf, TString& str) const str << char(c); } } - return str.not_empty(); + + return bIsString ? 2 : 3; } int TXmlItem::ReadTag(istream& inf) { TString str; - if (!GetWord(inf, str)) + const int tt = GetWord(inf, str); + if (tt == 0) return -1; - if (str[0] != '<') // No tag = sequence of words + if (tt >= 2) // sequence of words (2 or 3) { + if (tt == 2) + { + str.insert("\""); + str << '"'; + } + bool bFirstChar = true; while (!inf.eof()) { diff --git a/omnia/xml.h b/omnia/xml.h index e862686be..d69670fc1 100755 --- a/omnia/xml.h +++ b/omnia/xml.h @@ -19,7 +19,7 @@ class TXmlItem : public TObject TArray* m_Children; protected: - bool GetWord(istream& input, TString& str) const; + int GetWord(istream& input, TString& str) const; int ReadTag(istream& input); TXmlItem& AddChild(TXmlItem* pItem);