// gestione livelli di giacenza e articoli // oggetto movimento di magazzino // funzione di ricostruzione saldi #include "mglib.h" #ifndef __TABUTIL_H #include #endif // ******************************* // ******************************* #define MAXSIMBOLS 256 #define MAXSTATES 25 class TStateset { unsigned char _container[MAXSTATES]; int _current; public: TStateset & empty(); TStateset & enclose(int e); TStateset & singleton(int e); TStateset & cap(TStateset & s); int get_first() ; int get_next() ; bool is_empty() const; bool is_member(int e) const; TStateset(); ~TStateset() {}; }; struct TAutoma_state { short _transaction[MAXSIMBOLS]; TString16 * _label; bool _final; }; // ******************************* // ******************************* // automa per il riconoscimento di metacaratteri #define EPSILON 0 #define FIRST_STATE 1 #define FIRST_NEMPTY_SYMBOL 1 // ******************************* // ******************************* // automa per il riconoscimento di metacaratteri class TR_automa { TAutoma_state st[MAXSTATES]; short _maxstate; protected: TStateset union_of_closures(TStateset &s); bool is_final(int statenum) const; bool is_final(TStateset states) const; TR_automa & set_label(int statenum, const char *label); bool is_state(int statenum); const char *label(int statenum); int label2state(const char * label); void del_trans(int statenum,unsigned char symbol); int trans_to(int statenum,unsigned char symbol); bool _isdeterministic; public: TR_automa & reset_state(int statenum=-1); void add_tran(int statenum,unsigned char symbol,int next);// aggiunge una transizione int add_state(const char * label);// aggiunge uno stato TR_automa & set_final(int statenum,bool v=TRUE); // pone lo stato come finale bool is_deterministic() {return _isdeterministic;}; // bool recognized(const char * s); // tenta di riconoscere la stringa passata TR_automa(TR_automa *a=NULL,bool makedet=FALSE); // duplica un automa (e lo rende deterministico) ~TR_automa(); static void set2label(const TStateset ss,TString16 & label); static void label2set(const TString16 & label,TStateset & ss); }; // ******************************* TStateset::TStateset() { empty(); } TStateset & TStateset::empty() { _current=0; for (int i= 0; i< MAXSTATES; _container[i++]=0); return *this; } TStateset & TStateset::enclose(int el) { if (el< MAXSTATES && el>=0) _container[el]=1; return *this; } TStateset & TStateset::singleton(int el) { empty(); _container[el]=1; return *this; } TStateset & TStateset::cap(TStateset & s) { for (int i= 0; i< MAXSTATES; i++) _container[i]|=s._container[i]; return *this; } bool TStateset::is_empty() const { for (int i= 0; i< MAXSTATES; i++) { if (_container[i]) return FALSE; } return TRUE; } bool TStateset::is_member(int e) const { return ((e< MAXSTATES && e>=0)? _container[e] : FALSE ); } int TStateset::get_first() { _current=-1; return(get_next()); } int TStateset::get_next() { while (_current+1 < MAXSTATES) { if (_container[++_current]) return _current; } return (-1); } // labels and states bool TR_automa::is_state(int statenum) { return(statenum<=_maxstate && statenum>0); } // restituisce il numero dello stato con quella etichetta int TR_automa::label2state(const char *label) { for (int s=0; s<_maxstate;s++) { if (*(st[s]._label)==label) return(s+1); } return(0); } // resetta uno stato dell'automa (senza eliminarlo) TR_automa & TR_automa::reset_state(int statenum) { int _from,_to; if (statenum>0 && statenum<=_maxstate) { _from=statenum; _to=statenum; } else { _maxstate=0; _isdeterministic=TRUE; _from=1; _to=MAXSTATES; } { for (int i=_from; i<=_to;i++) { set_label(i,""); set_final(i,FALSE); for (int j=0; j0); return retv; } TR_automa & TR_automa::set_final(int statenum,bool v) { st[statenum-1]._final=v; return *this; } //******************* // bows void TR_automa::add_tran(int statenum, unsigned char symbol,int next) { st[statenum-1]._transaction[symbol]=next; if (symbol==EPSILON) _isdeterministic=FALSE; } void TR_automa::del_trans(int statenum, unsigned char symbol) { st[statenum-1]._transaction[symbol]=0; } int TR_automa::trans_to(int statenum, unsigned char symbol) { return (st[statenum-1]._transaction[symbol]); } // costruttore "di copi": crea un automa non deterministico // (transazioni Epsilon ma nessuna transazione multipla) // o ne crea l'equivalente automa deterministico TR_automa::TR_automa(TR_automa * aa,bool makedet) { TStateset arrival; TStateset newstateset; TString16 tmplabel; int curr_new_state; for (int i=0; iunion_of_closures(newstateset.singleton(FIRST_STATE)),tmplabel); add_state(tmplabel); curr_new_state=FIRST_STATE; while (is_state(curr_new_state)) { // determina l'insieme degli stati dell'automa non deterministico // che corrispondono a questo stato dell'automa deterministico label2set(label(curr_new_state),newstateset); // lo stato è finale se include stati finali dell'automa non det. set_final(curr_new_state,aa->is_final(newstateset)); // determina tutte le transazioni for (short symbol=FIRST_NEMPTY_SYMBOL; symboltrans_to(old_state,(unsigned char)symbol)) arrival.enclose(old_next); } while ((old_state=newstateset.get_next())>0); if (!arrival.is_empty()) { // crea il nuovo arco nell'automa deterministico set2label(aa->union_of_closures(arrival),tmplabel); if (!(new_next=label2state(tmplabel))) { new_next=add_state(tmplabel); } add_tran(curr_new_state,(unsigned char)symbol,new_next); } } // loop symbol curr_new_state++; } _isdeterministic=TRUE; } // fine conversione else { *this=*aa; for (int i=0; ist[i]._label; } } } TR_automa::~TR_automa() { for (int i=0; i0); } while (toadd) ; u_of_clo.cap(clo); } while ((_state=start_set.get_next())>0); return u_of_clo; } // tenta di riconoscere la stringa passata bool TR_automa::recognized(const char * t_str) { if (_isdeterministic) { // ricoNosce la stringa di token int curr_state=FIRST_STATE; for (int i=0; t_str[i]; i++) { if (!(curr_state=trans_to(curr_state,t_str[i]))) // fine per mancanza di trasizioni return FALSE; } // fine per mancanza di caratteri di input della stringa return (is_final(curr_state)); } else { // return FALSE; } } // ******************************* // gestione di stringhe di metacaratteri // ******************************* #define C_ESCAPEMETA '\\' #define S_BLANK 1 #define S_DIGIT 2 #define S_LETTER 3 #define S_ANY 4 // ******************************* // ******************************* // riconoscimento di metacaratteri class TR_automa; bool TMetachar::recognized(const char * s) { return(_au->recognized(s)); } void TMetachar::add_tran(int s,unsigned char metasymbol, int nextstate) { unsigned char c; switch (metasymbol) { case EPSILON:// blank _au->add_tran(s,EPSILON,nextstate); break; case S_BLANK:// blank _au->add_tran(s,' ',nextstate); break; case S_DIGIT:// cifra for (c='0';c<='9';c++) _au->add_tran(s,c,nextstate); break; case S_LETTER: // lettera for (c='a';c<='z';c++) _au->add_tran(s,c,nextstate); for (c='A';c<='Z';c++) _au->add_tran(s,c,nextstate); break; case S_ANY: // qualsiasi carattere for (c=MAXSIMBOLS-1;c>=FIRST_NEMPTY_SYMBOL;c--) _au->add_tran(s,c,nextstate); break; default: _au->add_tran(s,metasymbol,nextstate); break; } } // restituisce la stringa di metacaratteri del linguaggio riconosciuto const char * TMetachar::language() const { return(_language); } void TMetachar::set_language(const char * language) { int s; bool escaped_char=FALSE; TString16 label("-"),nextlabel("-"); // crea gli insiemi di metacaratteri standard strcpy(_metach_mand,"0LA&"); strcpy(_metach_opz,"#9?ac"); _language=language; // crea l'automa _au->reset_state(); for (int i=0; language[i]; i++) { label[0]='a'+i; nextlabel[0]='a'+i+1; if (language[i]!=C_ESCAPEMETA) { if (!escaped_char) { // meta-caratteri e literal fuori set s=_au->add_state(label); switch (language[i]) { case '#':// cifra o blank opzionale add_tran(s,S_BLANK,s+1); add_tran(s,'-',s+1); add_tran(s,'+',s+1); case '9':// cifra opzionale add_tran(s,EPSILON,s+1); case '0':// cifra obbligatoria add_tran(s,S_DIGIT,s+1); break; case '?': // lettera opzionale add_tran(s,EPSILON,s+1); case 'L': // lettera obbligatoria add_tran(s,S_LETTER,s+1); break; case 'a': // lettera o numero opzionale add_tran(s,EPSILON,s+1); case 'A': // lettera o numero obbligatorio add_tran(s,S_LETTER,s+1); add_tran(s,S_DIGIT,s+1); break; case 'c': // qualsiasi carattere opzionale add_tran(s,EPSILON,s+1); case '&': // qualsiasi carattere obbligatorio add_tran(s,S_ANY,s+1); break; default: _au->add_tran(s,language[i],s+1); break; } } else { // escaped char s=_au->add_state(label); _au->add_tran(s,language[i],s+1); } } escaped_char=(language[i]==C_ESCAPEMETA); } // end of loop // aggiunge lo stato finale s=_au->add_state(nextlabel); _au->set_final(s); } // ricerca caratteri del set opzionale bool TMetachar::has_opzchars(const char * pattern) { int i=0; bool next_literal=FALSE; while (pattern[i]) { if (!next_literal && strchr(_metach_opz,pattern[i])) return(TRUE); next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(FALSE); } // ricerca caratteri del set opzionale bool TMetachar::has_mandchars(const char * pattern) { int i=0; bool next_literal=FALSE; while (pattern[i]) { if (next_literal || strchr(_metach_mand,pattern[i])) return(TRUE); next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(FALSE); } // stabilisce la lunghezza della stringa di metacaratteri int TMetachar::maxstrlen(const char * pattern) { int i=0,l=0; bool next_literal=FALSE; while (pattern[i]) { if (!next_literal) l++; next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(l); } // costruttore e distruttore TMetachar::TMetachar () { _au = new TR_automa; set_language(""); } TMetachar::TMetachar (const char * metastr) { // crea l'automa e lo trasforma in deterministico // TR_automa auxau; // set_language(&auxau,metastr); _au=new TR_automa; set_language(metastr); if (!_au->is_deterministic()) { TR_automa * auxau = new TR_automa(_au,TRUE); delete _au; _au=auxau; } } TMetachar::~TMetachar () { delete _au; } // ************************** // classe codice a livelli TCodice_livelli:: TCodice_livelli(const char *tabname,const char *tabgrp) { TTable _tabformato(tabname); int e; _last_level=0; e=_tabformato.first(); for (int i=0; i< MANY_MAG_LEV; i++) { _enabled[i]=(e==NOERR); if (_enabled[i]) { _name[i]=_tabformato.get("S0"); _picture[i]=_tabformato.get("S1"); _code_lenght[i]=TMetachar::maxstrlen(_picture[i]); _last_level=i+1; } else { _name[i]=""; _code_lenght[i]=0; _picture[i]=""; } e=_tabformato.next(); } _gruppi = new TDecoder(tabgrp); } const char *TCodice_livelli::code_format(int levnum) const { if (levnum<0) { levnum=max(last_level(),1); } ((TCodice_livelli *)this)->add_metachar(levnum); return ((TMetachar*)_metachars.objptr(levnum-1))->language(); } bool TCodice_livelli::fit_to_format(const char *codepart,int levnum) const { if (levnum<0) { levnum=max(last_level(),1); } ((TCodice_livelli *)this)->add_metachar(levnum); return ((TMetachar*)_metachars.objptr(levnum-1))->recognized(codepart); } void TCodice_livelli::add_metachar(int levnum) { if (_metachars.objptr(levnum-1)==NULL) _metachars.add(new TMetachar(picture(levnum)),levnum-1); } const bool TCodice_livelli::enabled() const { return _lev_enabled && enabled(1); } const bool TCodice_livelli::enabled(int levnum) const { if (levnum<=MANY_MAG_LEV && levnum>0) return(_enabled[levnum-1] && _lev_enabled); else return(FALSE) ; } const int TCodice_livelli::code_lenght(int levnum) const { if (levnum<=MANY_MAG_LEV && levnum>0) return(_code_lenght[levnum-1]); else return(0) ; } const int TCodice_livelli::packed_lenght(int levnum) const { int start=0; for (int i=1; i<=levnum && levnum<=MANY_MAG_LEV; i++) start+= _code_lenght[i-1]; return start; } const TString & TCodice_livelli::name(int levnum) const { if (levnum<=MANY_MAG_LEV && levnum>0) return(_name[levnum-1]); else return(""); } const TString & TCodice_livelli::picture(int levnum) const { if (levnum<=MANY_MAG_LEV && levnum>0) return(_picture[levnum-1]); else return(""); } void TCodice_livelli::pack_grpcode(TString & pc, const TString &codlev, const int levnum) { pc.overwrite(codlev.left(_code_lenght[levnum-1]),packed_lenght(levnum-1)); } TString TCodice_livelli::unpack_grpcode(const TString & pc, const int levnum) const { int start=0; for (int i=1; i=pc.len()) return(""); else { if (levnum != _last_level && !_enabled[levnum-1]) return(""); return(pc.mid(start,levnum == _last_level ? -1 : _code_lenght[levnum-1])); } } TString TCodice_livelli::build_tabcode(const TString & pc, const int levnum) const { TString valore; valore << levnum; valore << unpack_grpcode(pc,levnum); if (valore.len()>1) return valore; else return ""; } const TString & TCodice_livelli::group_descr(const char * code, int levnum) const { return _gruppi->decode(build_tabcode(code,levnum)); } void TCodice_livelli::set_sheetcolumn(TSheet_field &fld_righe,int field, int lev) const { if (enabled(lev)) { fld_righe.sheet_mask().field(field).show(); fld_righe.set_column_header(fld_righe.cid2index(field),name(lev)); fld_righe.sheet_mask().field(field).set_prompt(name(lev)); } else { fld_righe.sheet_mask().field(field).hide(); fld_righe.delete_column(fld_righe.cid2index(field)); } } TCodart_livelli ::TCodart_livelli() : TCodice_livelli("FCA","GCA") { TConfig mgconfig(CONFIG_DITTA, "mg"); _lev_enabled=mgconfig.get_bool("GESLIVART"); // imposta il riconoscimento dei caratteri del formato dell'ultima parte dell'articolo TString80 format(""); TTable _tabfca("FCA"); if (_tabfca.last()==NOERR) { format = _tabfca.get("S1"); } _metachars.add(new TMetachar(format),max(last_level()-1,0)); } TCodart_livelli ::~TCodart_livelli() { } TCodgiac_livelli ::TCodgiac_livelli() : TCodice_livelli("FCG","GCG") { TConfig mgconfig(CONFIG_DITTA, "mg"); _lev_enabled=mgconfig.get_bool("GESLIVGIAC"); }