campo-sirio/mg/mglib01.cpp
augusto 7b01cc1b0f - funzione maxstrlen statica per la gestione della lunghezza delle parti del codice
- set_sheetcolum per settare la maschera
- abilitazione/disab globale della gestione codice a livelli


git-svn-id: svn://10.65.10.50/trunk@4903 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-07-24 14:47:52 +00:00

753 lines
18 KiB
C++
Executable File
Raw Blame History

// gestione livelli di giacenza e articoli
// oggetto movimento di magazzino
// funzione di ricostruzione saldi
#include "mglib.h"
#ifndef __TABUTIL_H
#include <tabutil.h>
#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; j<MAXSIMBOLS;j++) {
del_trans(i,j);
}
}
}
return *this;
}
// aggiunge una label
int TR_automa::add_state(const char * label)
{
_maxstate++;
reset_state(_maxstate);
set_label(_maxstate,label);
return _maxstate;
}
TR_automa & TR_automa::set_label(int statenum, const char * name)
{
(*(st[statenum-1]._label))=name;
return *this;
}
const char * TR_automa::label(int statenum)
{
return (*(st[statenum-1]._label));
}
bool TR_automa::is_final(int statenum) const
{
return (st[statenum-1]._final);
}
bool TR_automa::is_final(TStateset ss ) const
{
bool retv=FALSE;
int statenum=ss.get_first();
do {
retv=retv || is_final(statenum);
} while ((statenum=ss.get_next())>0);
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; i<MAXSTATES;i++) {
st[i]._label = new TString16;
}
if (aa==NULL) {
reset_state();
return;
}
if (makedet) {
reset_state();
// crea il primo stato nell'automa deterministico
set2label(aa->union_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 <20> 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; symbol<MAXSIMBOLS; symbol++) {
// determina lo stato di arrivo nell'automa det.:
// esso <20> pari all'insieme degli stati raggiunti col questo simbolo
// dal sottoinsieme degli stati dell'automa non det. che etichetta il nuovo stato nell'automa det.
arrival.empty();
int new_next,old_next;
int old_state=newstateset.get_first() ;
do {
if (old_next=aa->trans_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; i<MAXSTATES;i++) {
st[i]._label= aa->st[i]._label;
}
}
}
TR_automa::~TR_automa()
{
for (int i=0; i<MAXSTATES;i++) {
delete (st[i]._label);
}
}
void TR_automa::set2label(const TStateset ss,TString16 & label)
{
char coded[MAXSTATES];
char c=0;
for (int i= 0; i< MAXSTATES; i++) {
if (ss.is_member(i))
coded[c++]=(char)(i+'0');
}
coded[c]='\0';
label=coded;
}
void TR_automa::label2set(const TString16 & label,TStateset & ss)
{
ss.empty();
for (int i= 0; i<= label.len();i++)
ss.enclose(int(label[i]-'0'));
}
// costruisce l'unione delle epslilon closures
TStateset TR_automa::union_of_closures(TStateset &start_set)
{
TStateset u_of_clo,clo;
int _state,_next;
bool toadd;
u_of_clo.empty();
_state=start_set.get_first() ;
do {
// la chiusura <20> composta dallo stato e tutte le sue transazioni epsilon
clo.singleton(_state);
do {
int _state2=clo.get_first();
do {
toadd=((_next=trans_to(_state2,EPSILON)) && (!clo.is_member(_next)));
if (toadd)
clo.enclose(_next);
} while ((_state2=clo.get_next())>0);
} 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<levnum; i++)
start+= _code_lenght[i-1];
if (start>=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");
}