Files correlati : Ricompilazione Demo : [ ] Commento :correzioni dovute al passaggio al nuovo compilatore git-svn-id: svn://10.65.10.50/trunk@14698 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1076 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1076 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <stdlib.h>
 | |
| 
 | |
| #include <filetext.h>
 | |
| #include <tabutil.h>  
 | |
| 
 | |
| 
 | |
| // Ritorna TRUE se la stringa e' piena di zero
 | |
| static bool zero_only(const TString& v)
 | |
| {
 | |
| 	int i;
 | |
|   for (i = v.len()-1; i>=0 && v[i]=='0'; i--);
 | |
|   return i<0;
 | |
| }
 | |
| 
 | |
| //////////////////////////////////////// TTracciato_Campo ////////////////////////////////////////
 | |
| TTracciato_campo::TTracciato_campo(int position, int length, int decimal, const char align, const char filler)
 | |
|  : _datatype('S'), _position(position), _length(length),
 | |
|    _decimal(decimal), _align(align), _filler(filler) 
 | |
| {}
 | |
| 
 | |
| TObject* TTracciato_campo::dup() const
 | |
| {            
 | |
|   TTracciato_campo* t = new TTracciato_campo(*this);
 | |
|   return t;
 | |
| }
 | |
| 
 | |
| const TTracciato_campo& TTracciato_campo::operator =(const TTracciato_campo& tc)
 | |
| {
 | |
|   copy(tc);
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| void TTracciato_campo::copy(const TTracciato_campo& tc)
 | |
| {                                         
 | |
|   set_name(tc._name);
 | |
|   set_datatype(tc._datatype);    
 | |
|   set_type(tc._type);    
 | |
|   set_field(tc._field);
 | |
|   set_ftype(tc._ftype);    
 | |
|   set_position(tc._position);
 | |
|   set_length(tc._length);
 | |
|   set_decimal(tc._decimal); 
 | |
|   set_align(tc._align);
 | |
|   set_filler(tc._filler); 
 | |
|   set_picture(tc._picture); 
 | |
|   set_message(tc._message);
 | |
| }                                     
 | |
| 
 | |
| // determina la lunghezza del campo da scrivere su file isam
 | |
| const int TFile_text::flength(const TTracciato_campo &tc , const TRectype & record ) const
 | |
| {
 | |
|   if (tc.ftype().empty())
 | |
|     return tc.field().len(record); // il default è la lunghezza del campo isam
 | |
|   else
 | |
|     return ((TTracciato_campo &)_tipi[tc.ftype()]).length(); // altrimenti è quella definita nel FTYPE
 | |
| }
 | |
| const int TFile_text::fdecimal(const TTracciato_campo &tc ) const
 | |
| {
 | |
|   if (tc.ftype().empty())
 | |
|     return tc.decimal();
 | |
|   else
 | |
|     return ((TTracciato_campo &)_tipi[tc.ftype()]).decimal();
 | |
| }
 | |
| const char TFile_text::falign(const TTracciato_campo &tc ) const
 | |
| {
 | |
|   if (tc.ftype().empty())
 | |
|     return tc.align();
 | |
|   else
 | |
|     return ((TTracciato_campo &)_tipi[tc.ftype()]).align();
 | |
| }
 | |
| const char TFile_text::ffiller(const TTracciato_campo &tc ) const 
 | |
| {
 | |
|   if (tc.ftype().empty())
 | |
|     return tc.filler();
 | |
|   else
 | |
|     return ((TTracciato_campo &)_tipi[tc.ftype()]).filler();
 | |
| }
 | |
| const TString& TFile_text::fpicture(const TTracciato_campo &tc ) const
 | |
| {
 | |
|   if (tc.ftype().empty())
 | |
|     return tc.picture();
 | |
|   else
 | |
|     return ((TTracciato_campo &)_tipi[tc.ftype()]).picture();
 | |
| }
 | |
| 
 | |
| //////////////////////////////////////// TTracciato_record ////////////////////////////////////////
 | |
| 
 | |
| void TTracciato_record::set_relation(TRelation* rel)
 | |
| {
 | |
|   if (_rel) delete _rel;
 | |
|   _rel = rel;
 | |
| }
 | |
| 
 | |
| TObject* TTracciato_record::dup() const
 | |
| { 
 | |
|   TTracciato_record* t = new TTracciato_record(*this);
 | |
|    return t; 
 | |
| } 
 | |
| 
 | |
| TTracciato_record::TTracciato_record(const TTracciato_record& tr) : _rel(NULL)
 | |
| {
 | |
|   set_relation(tr.relation());
 | |
|   set_type(tr.type());
 | |
|   _tracciati_campo = tr._tracciati_campo;
 | |
| }                       
 | |
| 
 | |
| TTracciato_record::~TTracciato_record()
 | |
| {
 | |
|   if (_rel) delete _rel;
 | |
| }
 | |
| 
 | |
| void TTracciato_record::add(const TTracciato_campo& tc, int pos)
 | |
| {
 | |
|   _tracciati_campo.add(tc,pos);
 | |
| }
 | |
| 
 | |
| void TTracciato_record::add(TTracciato_campo* tc, int pos)
 | |
| {
 | |
|   _tracciati_campo.add(tc,pos);
 | |
| }
 | |
| 
 | |
| int TTracciato_record::get_pos(const char* name) const
 | |
| {
 | |
| 	int i;
 | |
| 	
 | |
|   for (i = _tracciati_campo.last(); i >= 0; i = _tracciati_campo.pred(i))
 | |
|   {
 | |
|     const TTracciato_campo& tc = get(i);
 | |
|     if (tc.name() == name)
 | |
|       break;
 | |
|   }
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| TTracciato_campo& TTracciato_record::get(int n)
 | |
| {
 | |
|   if (TTracciato_record::ptr(n) == NULL)//se non esiste lo creo
 | |
|   {
 | |
|     TTracciato_campo* t = new TTracciato_campo();
 | |
|     add(t, n);
 | |
|   }  
 | |
|   return (TTracciato_campo&)_tracciati_campo[n];  
 | |
| }
 | |
| //////////////////////////////////////// TRecord_text ////////////////////////////////////////
 | |
| const TString& TRecord_text::row(int pos) const         
 | |
| {                               
 | |
| 	const TString* str = (const TString*)_array.objptr(pos);
 | |
| 	if (str != NULL)
 | |
| 		return *str;
 | |
|   return EMPTY_STRING;
 | |
| }
 | |
| 
 | |
| TString& TRecord_text::row(int pos)
 | |
| {                                                              
 | |
|   return _array.row(pos);
 | |
| }
 | |
| 
 | |
| void TRecord_text::add(const TString& c, int pos)
 | |
| {
 | |
|   _array.add(c, pos);
 | |
| }                                                               
 | |
| //////////////////////////////////////// TFile_text ////////////////////////////////////////
 | |
| TTracciato_record* TFile_text::t_rec(const char* type) const
 | |
| {
 | |
|   return (TTracciato_record*)_tracciati_record.objptr(type);
 | |
| } 
 | |
| 
 | |
| TTracciato_record* TFile_text::t_rec(int mainfile, const char * tabname) const
 | |
| {
 | |
|   if (tabname)
 | |
|     mainfile=(tabname[0] != '%') ? LF_TAB: LF_TABCOM;
 | |
|   TTracciato_record *trrd;
 | |
|   TAssoc_array &tr = (((TFile_text *)this)->_tracciati_record);
 | |
|   tr.restart();
 | |
|   while ((trrd=(TTracciato_record *)tr.get()))
 | |
|   {
 | |
|     if (trrd->relation() && trrd->relation()->lfile().num()==mainfile)
 | |
|       if (tabname)
 | |
|       {
 | |
|         TTable & tab=(TTable & )trrd->relation()->lfile();
 | |
|         if (tabname == tab.name() )
 | |
|           break;
 | |
|       } else 
 | |
|         break;
 | |
|   }
 | |
|   return trrd;
 | |
| } 
 | |
| 
 | |
| 
 | |
| void TFile_text::set_gen_parm(TConfig& config, const TString& section)
 | |
| {
 | |
|   _decsep = config.get_char("DECSEP",section);
 | |
|   _recordsize = config.get_int("RECORDSIZE",section); // solo se a lung. fissa
 | |
| 	TString tmpstring = config.get("FIELDSEP",section);    // solo se a lung. variabile
 | |
|   
 | |
| 	if (tmpstring[0] == '\\')  
 | |
|   {
 | |
|     if (tmpstring = "\t")
 | |
|       _fieldsep = '\t';
 | |
| 	}
 | |
| 	else
 | |
| 		_fieldsep = tmpstring[0];    // solo se a lung. variabile
 | |
| 
 | |
|   _recordsep = config.get("RECORDSEP",section);       // solo se a lung. variabile
 | |
|   if (_recordsize <= 0 && _recordsep.empty())         // separatore di record standard
 | |
|     _recordsep = "\r\n";                  
 | |
|   if (_recordsep[0] == '\\')  
 | |
|   {
 | |
|     if (_recordsep == "\\r")
 | |
|       _recordsep = "\r"; else
 | |
|     if (_recordsep == "\\n")
 | |
|       _recordsep = "\n"; else
 | |
|     if (_recordsep == "\\n\\r")
 | |
|       _recordsep = "\n\r";
 | |
|   }
 | |
|   _skiplines = config.get_int("SKIPLINES",section);   // righe iniziali da ignorare
 | |
|     
 | |
|   _typefield = config.get_int("TYPEFIELD",section);  // Numero del campo tipo (puo' essere -1)
 | |
|   _fixedlen = _fieldsep <= ' '; // && _recordsep.blank();
 | |
|   _typepos = config.get_int("TYPEPOS", section, -1, -1); 
 | |
|   _typelen = config.get_int("TYPELEN", section, -1, 0); 
 | |
|   if (_typelen > 16)
 | |
|     NFCHECK("Tipo record di lunghezza spropositata: %d", _typelen);
 | |
| }        
 | |
| 
 | |
| void TFile_text::set_type_parm(TConfig& config, TString& section)
 | |
| {
 | |
|   TString lavoro = section;
 | |
|   lavoro.ltrim(4);//elimino la parola 'TYPE' e gli spazi vuoti
 | |
|   lavoro.trim();//per avere solo il nome del tipo predefinito
 | |
|   TTracciato_campo tipo;  
 | |
|   tipo.set_type(lavoro);
 | |
|   tipo.set_length(config.get_int("LENGTH", section));
 | |
|   tipo.set_decimal(config.get_int("DECIMAL", section));
 | |
|   tipo.set_align(config.get_char("ALIGN", section));
 | |
|   const char datatype=config.get_char("DATA", section);
 | |
|   if (datatype>' ')
 | |
|     tipo.set_datatype(datatype);
 | |
|   else
 | |
|     tipo.set_datatype('S');
 | |
|   TString s  = config.get("FILLER", section); 
 | |
|   if (s.len() > 1)
 | |
|     tipo.set_filler(s[1]);
 | |
|   else
 | |
|     tipo.set_filler(s[0]);
 | |
|   tipo.set_picture(config.get("PICTURE", section));
 | |
|   _tipi.add(lavoro, tipo);// aggiungo il tracciato campo all'assoc_array dei tipi predefiniti
 | |
| }
 | |
|         
 | |
| void TFile_text::set_rec_parm(TConfig& config, const char* section)
 | |
| {
 | |
|   TString sectkey = section;
 | |
|   sectkey.ltrim(6);//elimino la parola 'RECORD' o 'HEADER' o 'FOOTER' e gli spazi vuoti
 | |
|   sectkey.trim();//per avere solo il nome del tipo del record
 | |
|   TTracciato_record *tr=new TTracciato_record(sectkey);//istanzio un tracciato_record del tipo corrente
 | |
|   //setto tutti i dati relatvi ai tipi predefini nei tracciati campo per i diversi campi del record 
 | |
|   TRelation *tmprel=NULL; // relazione associata al tracciato record
 | |
|   config.set_paragraph(section);
 | |
|   TString lavoro;
 | |
|   TString_array variables;
 | |
|   const int numvar = config.list_variables(variables, TRUE);//scarico tutte le variabili della sezione 
 | |
|   variables.sort(FALSE);
 | |
|   TBit_array indici(numvar);
 | |
|   indici.reset();
 | |
|   for (int j = 0; j < numvar; j++)//scandisco tutte le variabili della sezione                                       
 | |
|   {
 | |
|     const TString key = variables.row(j).get(0);//estraggo nome 
 | |
|     const TString& obj = variables.row(j).get(1);//estraggo valore 
 | |
|     lavoro = key.left(3);    
 | |
|     int pos = key.find('(');
 | |
|     int n  = atoi(key.mid(pos+1, -1));//estraggo l'indice              
 | |
|     if (!indici[n])    
 | |
|     {
 | |
|       if (config.exist("TYPE",  n))
 | |
|       {
 | |
|         TString tipo = config.get("TYPE", section, n);
 | |
|         if (!tipo.empty())
 | |
|         {
 | |
|           TTracciato_campo& tc = (TTracciato_campo&)_tipi[tipo];
 | |
|           tr->add(tc, n);   
 | |
|         }
 | |
|       }  
 | |
|       indici.set(n);
 | |
|     }
 | |
|     if (lavoro == "USE")  // setta la relazione
 | |
|     {                            
 | |
|         CHECKS(tmprel == NULL,"Relazione già definita per il tracciato: %s", (const char *) sectkey);
 | |
|         if (atoi((const char *)obj)!=0)
 | |
|           tmprel= new TRelation(atoi((const char *)obj));
 | |
|         else
 | |
|           tmprel= new TRelation((const char *)obj);
 | |
|     }
 | |
|     if (lavoro == "JOI")  // setta i join
 | |
|     {
 | |
|       CHECKS(tmprel, "Can't join to NULL relation %s", (const char*)j);
 | |
|       
 | |
|       TToken_string join_expr((const char *)obj,' ');             // Join expression
 | |
|       int token=0;
 | |
|       TString16 j(join_expr.get(token++)); // file or table
 | |
|       int to=0;     // 'to' default: _relation->lfile()->num();
 | |
|       if (strcmp(join_expr.get(token++),"TO")==0)         // TO keyword
 | |
|       {
 | |
|         const char* t = join_expr.get(token++);
 | |
|         to = name2log(t);
 | |
|       } else 
 | |
|         token --;
 | |
|       int nkey = 1;
 | |
|       if (strcmp(join_expr.get(token++),"KEY")==0)
 | |
|         nkey = join_expr.get_int(token++);
 | |
|       else 
 | |
|         token--;
 | |
|       int alias = 0;
 | |
|       if (strcmp(join_expr.get(token++),"ALIAS")==0)
 | |
|         alias = join_expr.get_int(token++);
 | |
|       else 
 | |
|         token--;
 | |
|       TToken_string exp(80);
 | |
|       if (strcmp(join_expr.get(token++),"INTO")==0)
 | |
|       {
 | |
|         const char* r = join_expr.get(token++);
 | |
|         while (r && strchr(r, '=') != NULL)
 | |
|         {
 | |
|           exp.add(r);
 | |
|           r = join_expr.get(token++);
 | |
|         }
 | |
|       }
 | |
|                 
 | |
|       #ifdef DBG      
 | |
|       if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
 | |
|       #endif  
 | |
|                                
 | |
|       if (j[0] >= '0' && j[0] <= '9')
 | |
|       {
 | |
|         tmprel->add(atoi(j), exp, nkey, to, alias);   // join file
 | |
|         tmprel->write_enable(atoi(j),key.left(6)!="JOINRO");
 | |
|       } else
 | |
|       {
 | |
|       #ifdef DBG      
 | |
|         if (j.len() > 4)
 | |
|           yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j);
 | |
|         else  
 | |
|       #endif
 | |
|         {
 | |
|           tmprel->add(j, exp, nkey, to, alias);      // join table
 | |
|           tmprel->write_enable(j,key.left(6)!="JOINRO");
 | |
|         }               
 | |
|       }               
 | |
|       continue;
 | |
|     }
 | |
|     TTracciato_campo& tc = tr->get(n);//prendo il tracciato campo con indice <n>
 | |
|     if (lavoro == "NAM")
 | |
|     {                            
 | |
|        tc.set_name(obj);
 | |
|        continue;
 | |
|     }
 | |
|     if (lavoro == "FIE")
 | |
|     {                 
 | |
|       TFieldref field;
 | |
|       field = obj;
 | |
|       tc.set_field(field);
 | |
|       continue;
 | |
|     }          
 | |
|     if (lavoro == "FTY") // field type
 | |
|     {                 
 | |
|        CHECKS(_tipi.objptr(obj)!=NULL,"Riferimento a campo inesistente:%s", (const char *) obj);
 | |
|        tc.set_ftype(obj);
 | |
|        continue;
 | |
|     }          
 | |
|     if (lavoro == "POS")
 | |
|     {             
 | |
|        const int pos = atoi(obj);
 | |
|        if (pos >= 0)
 | |
|        {
 | |
|          tc.set_position(pos);
 | |
|          if (_typepos < 0 && n == _typefield)
 | |
|             _typepos = pos;
 | |
|        }
 | |
|        continue;
 | |
|     }
 | |
|     if (lavoro == "LEN")
 | |
|     {             
 | |
|        const int len = atoi(obj);                  
 | |
|        if (tc.length() <= 0 && len > 0)
 | |
|        {
 | |
|          tc.set_length(len);
 | |
|          if (_typelen < 0 && n == _typefield)
 | |
|             _typelen = len;
 | |
|        }
 | |
|        continue;
 | |
|     }                  
 | |
|     if (lavoro == "DEC")
 | |
|     {             
 | |
|         int dec = atoi(obj);  
 | |
|         if (tc.decimal() <= 0 && dec >= 0 && tc.decimal() != dec)
 | |
|           tc.set_decimal(dec);
 | |
|         continue;
 | |
|      }                          
 | |
|      if (lavoro == "ALI")
 | |
|     {                  
 | |
|        bool condition = tc.align() != obj[0];
 | |
|        if (condition)
 | |
|          tc.set_align(obj[0]);
 | |
|        continue;
 | |
|     } 
 | |
|     if (lavoro == "FIL")
 | |
|     {             
 | |
|       if (!obj.blank())
 | |
|       {
 | |
|         bool condition = tc.filler() != obj[1];
 | |
|         if (condition)      
 | |
|         {
 | |
|           if (obj.len() > 1)
 | |
|             tc.set_filler(obj[1]);
 | |
|           else
 | |
|             tc.set_filler(obj[0]);
 | |
|         }
 | |
|       } 
 | |
|       continue;
 | |
|     }
 | |
|     if (lavoro == "PIC")
 | |
|     {             
 | |
|        if (tc.picture().blank() && (!obj.blank()))
 | |
|         tc.set_picture(obj);
 | |
|        continue;
 | |
|     }
 | |
|     if (lavoro == "MES")
 | |
|     {                      
 | |
|        tc.set_message(obj);
 | |
|        continue;
 | |
|     } 
 | |
|     if (_fixedlen && _typelen < 0 && n == _typefield)
 | |
|      _typelen = tc.length();
 | |
|     
 | |
|   }
 | |
|   tr->set_relation(tmprel);
 | |
|   //aggiungo il tracciato record all'assoc_array dei tracciati record
 | |
|   _tracciati_record.add(sectkey, tr);
 | |
| }
 | |
| 
 | |
| TFile_text::TFile_text(const char* file_name, const char* config_name) 
 | |
|           : _name(file_name), _skiplines(0), _kill_zeroes(FALSE), _force_record_separator(FALSE)
 | |
| {
 | |
|   _read_file = NULL;
 | |
|   _write_file = NULL;
 | |
|   TConfig config(config_name);
 | |
|   TString_array paragraphs;
 | |
|   config.list_paragraphs(paragraphs);//scarico la lista dei paragrafi
 | |
|   int items = paragraphs.items();//quanti paragrafi ho scaricato
 | |
|   TString section, sec;
 | |
|   for (int i = 0; i < items; i++)//scandisco tutti i paragrafi
 | |
|   {                                             
 | |
|     section = paragraphs.row(i) ;//prendo il nome del paragrafo
 | |
|     sec = section.left(3);//prendo le prime tre lettere del nome
 | |
|     if (sec == "MAI") //inizializzo i parametri generali del file
 | |
|     {
 | |
|        set_gen_parm(config,section);
 | |
|        continue;
 | |
|     }        
 | |
|     if (sec == "TYP")
 | |
|     {          
 | |
|        set_type_parm(config, section);
 | |
|        continue;
 | |
|     }
 | |
|     if (sec == "FTY") // field type
 | |
|     {          
 | |
|        set_type_parm(config, section);
 | |
|        continue;
 | |
|     }
 | |
|     if ((sec == "REC")||(sec == "HEA")||(sec == "FOO"))
 | |
|     {   
 | |
|       set_rec_parm(config, section);
 | |
|       continue;
 | |
|     }  
 | |
|   }  
 | |
| }                                                    
 | |
| 
 | |
| TFile_text::~TFile_text() 
 | |
| {
 | |
|   if (_read_file) 
 | |
|     delete _read_file;
 | |
|   if (_write_file)
 | |
|     delete _write_file;
 | |
|   _tipi.destroy();
 | |
|   _tracciati_record.destroy();
 | |
| 
 | |
| }
 | |
|                           
 | |
| //Legge da file il record text
 | |
| int TFile_text::read(TRecord_text& rec)
 | |
| {
 | |
|   if (_read_file == NULL)
 | |
|     open('r');
 | |
| 
 | |
|   TToken_string buffer; 
 | |
|   
 | |
|   if (_recordsize > 0)
 | |
|   {        
 | |
|     if (buffer.size() < _recordsize)
 | |
|       buffer.spaces(_recordsize);
 | |
|     
 | |
|     _read_file->read(buffer.get_buffer(), _recordsize); 
 | |
|     if (!ok_r()) return 1; //non ritorna errore se fine file ed il record e' completo!
 | |
|   }
 | |
|   else
 | |
|   {                     
 | |
|     if (_recordsep == "\r\n" || _recordsep == "\n\r")
 | |
|     {                                        
 | |
|       const int maxsize = 1024*16;
 | |
|       char* buf = buffer.get_buffer(maxsize);
 | |
|       _read_file->get(buf, maxsize, _recordsep[0]);
 | |
|       if (buffer.empty())
 | |
|         return EOF;
 | |
|       char c = _read_file->get();
 | |
|       c = _read_file->get();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       //legge carattere per carattere fino a quando non si trova il separatore di record 
 | |
|       char c = _read_file->get();
 | |
|       if (c == EOF)
 | |
|         return EOF;
 | |
|       while (c != _recordsep[0])
 | |
|       { 
 | |
|         buffer << c;
 | |
|         c = _read_file->get();
 | |
|         if (!ok_r()) 
 | |
|           return EOF; //non ritorna errore se fine file ed il record e' completo! 
 | |
|       }     
 | |
|       for (int j = _recordsep.len()-1; j > 0; j--)
 | |
|         c = _read_file->get();
 | |
|     }
 | |
|   }                                   
 | |
|   
 | |
|   if (_fieldsep != '\0')
 | |
|   {
 | |
|     buffer.separator(_fieldsep);
 | |
|     
 | |
|     const char* tipo = _typefield >= 0 ? buffer.get(_typefield) : ""; 
 | |
|     TTracciato_record& tr = *t_rec(tipo); 
 | |
|     rec.set_type(tipo);//istanzio il tipo del record text
 | |
|     
 | |
|     TArray& a_tc = tr.tracciati_campo();
 | |
|     const int items =  a_tc.items();
 | |
|     buffer.restart();
 | |
|     TString lavoro;
 | |
|     for (int i = 0; i < items; i++)
 | |
|     {
 | |
|       buffer.get(i, lavoro);
 | |
|       rec.add(lavoro, i);
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     TString16 tipo;
 | |
|     if (_typepos >= 0 && _typelen > 0) 
 | |
|     {
 | |
|       tipo = buffer.mid(_typepos, _typelen);
 | |
|       tipo.trim();
 | |
|     }  
 | |
|     rec.set_type(tipo);//istanzio il tipo del record text
 | |
|     TTracciato_record* tr = t_rec(tipo); 
 | |
|     if (tr != NULL)
 | |
|     {
 | |
|       //ora che ho il tracciato record devo scandire i tracciati campo e caricare il record text
 | |
|       const TArray& a_tc = tr->tracciati_campo();
 | |
|       const int items = a_tc.items();
 | |
|       for (int i = 0; i < items; i++)
 | |
|       {
 | |
|         TTracciato_campo& tc = tr->get(i);
 | |
|         const int pos = tc.position();
 | |
|         const int len = tc.length();
 | |
|         const TString& lavoro = buffer.mid(pos, len); 
 | |
|         rec.add(lavoro, i);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return 0;          
 | |
| }  
 | |
| 
 | |
| //Scrive su file il  record_text  (valido anche per header e footer)
 | |
| int TFile_text::write(TRecord_text& rec)
 | |
| {
 | |
|   TString campo;
 | |
|   TToken_string buffer; 
 | |
| 
 | |
|   const TString& type = rec.type();
 | |
|   TTracciato_record& tr = *t_rec(type);
 | |
| 
 | |
|   const int items = rec.items();
 | |
|   if (_typepos>=0)
 | |
|     rec.add(type,_typepos);
 | |
| 
 | |
| 	const TArray& tac = tr.tracciati_campo();
 | |
| 
 | |
|   if (_fixedlen) // campi a lunghezza fissa
 | |
|   {                        
 | |
| 		FOR_EACH_ARRAY_ITEM(tac, i, obj)
 | |
|     {
 | |
|       const TTracciato_campo& tc = tr.get(i); 
 | |
|       campo = rec.get(i);
 | |
|       format_textfield(tc, campo);
 | |
|       buffer.overwrite(campo, tc.position());                        
 | |
|     }
 | |
|     CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
 | |
|     if (_recordsize<=0) 
 | |
|     {
 | |
|       // Record a lunghezza var
 | |
|       *_write_file <<  buffer;                                  
 | |
|       *_write_file << _recordsep;
 | |
|     } 
 | |
|     else 
 | |
|     {
 | |
|       // Record a lunghezza fissa
 | |
|       buffer.rpad(_recordsize);
 | |
|       buffer.cut(_recordsize);
 | |
|       *_write_file <<  buffer;
 | |
|       if (_force_record_separator)
 | |
|         *_write_file << _recordsep;
 | |
|     }
 | |
|     if (!ok_w()) return 1;
 | |
|   }    
 | |
|   else
 | |
|   {
 | |
|     buffer.separator(_fieldsep);
 | |
| 		FOR_EACH_ARRAY_ITEM(tac, i, obj)
 | |
|     {
 | |
|       const TTracciato_campo& tc = tr.get(i); 
 | |
|       campo = rec.get(i);
 | |
| 		  format_textfield(tc, campo);
 | |
|       buffer.add(campo);
 | |
|     }
 | |
|     CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
 | |
|     *_write_file << buffer;
 | |
|     *_write_file << _recordsep;
 | |
|     if (!ok_w()) return 1;   
 | |
|   }  
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| // Carica tutti i dati del tracciato record (anche header o footer) 
 | |
| // nel record_text
 | |
| bool TFile_text::autoload(TRecord_text& rec, int mainfile)
 | |
| {                             
 | |
|   TTracciato_record* tr = t_rec(mainfile);
 | |
|   if (tr)
 | |
|   {
 | |
|     // esiste il tracciato e posso fare l'autoload
 | |
|     TCursor cur(tr->relation());
 | |
|     rec.set_type(tr->type());
 | |
|     return _autoload(rec,cur,*tr);
 | |
|   }    
 | |
|   //CHECK (FALSE,"Il tracciato record non esiste");
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| // Carica tutti i dati del tracciato record (anche header o footer) 
 | |
| // nel record_text
 | |
| bool TFile_text::autoload(TRecord_text& rec, const char * tabname)
 | |
| {                             
 | |
|   TTracciato_record* tr = t_rec(tabname);
 | |
|   if (tr)
 | |
|   {
 | |
|     // esiste il tracciato e posso fare l'autoload
 | |
|     TCursor cur(tr->relation());
 | |
|     rec.set_type(tr->type());
 | |
|     return _autoload(rec,cur,*tr);
 | |
|   }    
 | |
|   //CHECK (FALSE,"Il tracciato record non esiste");
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| //Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text
 | |
| bool TFile_text::autoload(TRecord_text& rec, TCursor& cur , const TString* tipo)
 | |
| {                             
 | |
|   const TString& type = rec.type();
 | |
|   if (tipo == NULL) tipo = &type;
 | |
|   TTracciato_record* tr = t_rec(*tipo);
 | |
|   CHECKS(tr!=NULL,"Tracciato record file di testo non trovato ",(const char *)*tipo);
 | |
|   return _autoload(rec,cur,*tr);
 | |
| }
 | |
| 
 | |
| bool TFile_text::autoload(TCursor& cur,  const TString* tipo) 
 | |
| {
 | |
|   CHECK(_current,"Record corrente non settato");
 | |
|   return autoload(*_current, cur, tipo); 
 | |
| }
 | |
| 
 | |
| //Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text
 | |
| bool TFile_text::_autoload(TRecord_text& rec, TCursor& cur , TTracciato_record& tr )
 | |
| {                             
 | |
|   TString campo; 
 | |
|   TRelation& rel = *cur.relation();
 | |
|   TArray& a_tc = tr.tracciati_campo();
 | |
|   int items =  a_tc.items();
 | |
|   for (int i = 0; i < items; i++)
 | |
|   {
 | |
|     TTracciato_campo& tc = tr.get(i);
 | |
|     const TFieldref& field = tc.field(); 
 | |
|     if (field.name().not_empty())
 | |
|       campo = field.read(rel);
 | |
|     
 | |
|     const TString& message = tc.message(); 
 | |
|     if (!message.empty())
 | |
|     {
 | |
|       TToken_string msg (message, ',');                               
 | |
|       if (!msg.blank())
 | |
|         validate(cur, rec, msg, campo); 
 | |
|     }   
 | |
| 
 | |
|     rec.add(campo, i);       
 | |
|     campo.cut(0);
 | |
|   }
 | |
|   return can_write(rec,rel);
 | |
| } 
 | |
| 
 | |
| int TFile_text::autosave(const TRecord_text& rec, int mainfile )
 | |
| {
 | |
|   const TString& type = rec.type();//prendo il tracciato record del tipo del record_text 
 | |
|   TTracciato_record* tr = t_rec(type);
 | |
|   if (tr)
 | |
|   {
 | |
|     TRelation* rel = tr->relation();
 | |
|     if (rel && (mainfile==0 || rel->lfile().num()==mainfile))
 | |
|       return _autosave(*rel,rec, *tr);
 | |
|   }      
 | |
|   return NOERR; // l'assenza del tracciato non significa un errore
 | |
| }
 | |
| 
 | |
| int TFile_text::autosave(TRelation& rel, const TRecord_text& rec)
 | |
| {           
 | |
|   const TString& type = rec.type();//prendo il tracciato record del tipo del record_text 
 | |
|   TTracciato_record& tr = *t_rec(type); 
 | |
|   return _autosave(rel,rec, tr);
 | |
| }
 | |
| 
 | |
| int TFile_text::autosave(int mainfile) 
 | |
| {
 | |
|   CHECK(_current,"Record corrente non settato");
 | |
|   return autosave(*_current,mainfile);
 | |
| }
 | |
| 
 | |
| //Carico la relazione con i dati del record text
 | |
| int TFile_text::_autosave(TRelation& rel, const TRecord_text& rec, TTracciato_record& tr )
 | |
| {           
 | |
|   TArray& a_tc = tr.tracciati_campo();
 | |
|   int items =  a_tc.items();                 
 | |
|   TString valore;
 | |
|   for (int i = 0; i < items; i++)
 | |
|   {
 | |
|     const TTracciato_campo& tc = tr.get(i);
 | |
|     if (tc.field().name().not_empty())
 | |
|     {
 | |
|       const TFieldref& field = tc.field(); 
 | |
|       valore = rec.row(i);                     
 | |
|       // formatta il campo del file di testo secondo le specifiche del campo su file isam
 | |
|       preformat_field(field,valore,rel,tr.type());
 | |
|       const TRectype& rel_rec = rel.curr(field.file());
 | |
|       TFieldtypes tipo_campo = rel_rec.type(field.name());
 | |
|       switch(tipo_campo)
 | |
|       {
 | |
|       case _datefld:
 | |
|         {                  
 | |
|           if (real::is_null(valore))
 | |
|             valore.cut(0);
 | |
|           TDate data(valore);  
 | |
|           format_date(data, fpicture(tc), valore);//formatta la data secondo le specifiche del tracciato    
 | |
|         }                
 | |
|         break;
 | |
|       case _realfld:  
 | |
|       case _intfld:  
 | |
|       case _longfld:  
 | |
|         {
 | |
|            real numero(valore);
 | |
|            valore = numero.string(fpicture(tc));//formatta il numero secondo le specifiche del tracciato
 | |
|            
 | |
|            int length = flength(tc,rel_rec);
 | |
|            if (falign(tc) == 'L')
 | |
|              valore.left_just(length, ffiller(tc));
 | |
|            else
 | |
|              valore.right_just(length, ffiller(tc));
 | |
|            int j = valore.replace('.', _decsep); //!?!?! consento decsep diversi per isam e text ?
 | |
|            CHECK(j >= 0 && j <= 1 , "Impossibile scrivere più separatori decimali.");
 | |
|         }              
 | |
|         break;
 | |
|       default:  
 | |
|         if (_kill_zeroes && zero_only(valore))
 | |
|           valore = "";
 | |
|         valore = format_field(tc, rel.lfile().num(), valore);//formatta il campo secondo le specifiche del record
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (rel.exist(field.file()))
 | |
|         field.write(valore, rel);//faccio una write sulla relazione del fieldref
 | |
|     }  
 | |
|   }
 | |
|   if (pre_writerel(rel,rec))
 | |
|   {
 | |
|     int err= rel.write();
 | |
|     if (err == _isdupkey || err ==_isreinsert)
 | |
|       err = rel.rewrite();     
 | |
|     return err;       
 | |
|   }
 | |
| 
 | |
|   return NOERR;
 | |
| } 
 | |
| 
 | |
| //Scarica dal record_text il campo alla posizione <ncampo>
 | |
| const TString& TFile_text::get_field(const TRecord_text& rec, int ncampo) 
 | |
| {                                         
 | |
| /* Guy was here
 | |
|   const TString& type = rec.type();//prendo il tracciato record del tipo del record_text 
 | |
|   TTracciato_record tr(type);
 | |
|   TTracciato_campo& tc = tr.get(ncampo);
 | |
| */  
 | |
|   return rec.row(ncampo);
 | |
| }
 | |
| 
 | |
| //Scarica dal record_text il campo <name>
 | |
| const TString& TFile_text::get_field(const TRecord_text& rec, const char* name) 
 | |
| {                                         
 | |
|   TTracciato_record* tr = t_rec(rec.type());
 | |
|   if (tr != NULL)
 | |
|   {
 | |
|     const int ncampo = tr->get_pos(name);
 | |
|     if (ncampo >= 0)
 | |
|       return rec.row(ncampo);
 | |
|   }
 | |
|   
 | |
|   NFCHECK("Campo inesistente %s", name);
 | |
|   return EMPTY_STRING;
 | |
| }
 | |
| 
 | |
| //Carica nel record_text il campo alla posizione <ncampo> con il valore <val> già formattato  
 | |
| void TFile_text::add_field(TRecord_text& rec, const int ncampo, const char* val)
 | |
| {
 | |
|   TTracciato_record* tr = t_rec(rec.type());
 | |
|   CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type());
 | |
|   tr->get(ncampo);
 | |
|   rec.add(val, ncampo);    
 | |
| }    
 | |
| 
 | |
| //Carica nel record_text il campo <name> con il valore <val> già formattato  
 | |
| void TFile_text::add_field(TRecord_text& rec, const char* name, const char* val)
 | |
| {
 | |
|   TTracciato_record* tr = t_rec(rec.type());
 | |
|   CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type());
 | |
|   int ncampo = tr->get_pos(name);
 | |
|   CHECKS(ncampo >= 0, "Campo inesistente ", name);
 | |
|   rec.add(val, ncampo);
 | |
| }    
 | |
| 
 | |
| 
 | |
| //Formatta la data in base al tracciato 
 | |
| void TFile_text::format_date(const TDate& data, const TString& form, TString& data_str)
 | |
| {                                                             
 | |
|   int i = 1, cnt = 0;
 | |
|   char x = form[0];
 | |
|   do
 | |
|   {  
 | |
|       char k = x;
 | |
|       if (k != 'a' && k != 'm'&& k != 'g')
 | |
|           data_str << k;
 | |
|       else
 | |
|           cnt++;
 | |
|       x = form[i];
 | |
|       i++;  
 | |
|       if (k != x)
 | |
|           switch (k)
 | |
|           {
 | |
|             case 'g':  CHECKD(cnt >= 1 && cnt <= 4, "Formato per giorno non valido ", cnt);
 | |
|                           if (cnt == 1) 
 | |
|                             data_str << data.day();
 | |
|                           if (cnt == 2) 
 | |
|                           {
 | |
|                             TString16 s; 
 | |
|                             s.format("%02d", data.day());
 | |
|                             data_str << s;
 | |
|                           }  
 | |
|                           if (cnt == 3) 
 | |
|                           {
 | |
|                             TString16 s = itow(data.wday());
 | |
|                             s.cut(3);
 | |
|                             data_str << s;
 | |
|                           }
 | |
|                           if (cnt == 4) 
 | |
|                             data_str << itow(data.wday());  
 | |
|                           cnt = 0;
 | |
|                           break;
 | |
|             case 'm': CHECKD(cnt >= 1 && cnt <= 4, "Formato per mese non valido ", cnt);
 | |
|                           if (cnt == 1) 
 | |
|                             data_str << data.month();
 | |
|                           if (cnt == 2) 
 | |
|                           {            
 | |
|                             TString16 s; 
 | |
|                             s.format("%02d", data.month());
 | |
|                             data_str << s;
 | |
|                           }  
 | |
|                           if (cnt == 3) 
 | |
|                           {
 | |
|                             TString16 s = itom(data.month());
 | |
|                             s.cut(3);
 | |
|                             data_str << s;
 | |
|                           }
 | |
|                           if (cnt == 4) data_str << itom(data.month());
 | |
|                           cnt = 0;
 | |
|                           break;
 | |
|             case 'a':  CHECKD(cnt >= 2 && cnt <= 4, "Formato per anno non valido ", cnt);
 | |
|                           if (cnt == 2)  {TString s;s << data.year();s.ltrim(2);data_str << s;}
 | |
|                           if (cnt == 3)  {TString s;s << data.year();s.ltrim(1);data_str << s;}                      
 | |
|                           if (cnt == 4)  data_str << data.year();
 | |
|                           cnt = 0;
 | |
|                           break;
 | |
|           }
 | |
|   }        
 | |
|   while (i <= form.len());  
 | |
| }
 | |
| 
 | |
| // Formatta la stringa in base alle definizioni del tracciato 
 | |
| // La stringa ritornata rappresenta il valore del campo nel filetext e i parametri di fomattazione
 | |
| // sono quelli associati al campo nel filetext
 | |
| TString& TFile_text::format_textfield(const TTracciato_campo& tc, TString& campo)
 | |
| {
 | |
|   //int pos = tc.position();
 | |
|   int length = tc.length();
 | |
|   char fillch=tc.filler();
 | |
|   if (!tc.picture().blank())
 | |
|   { 
 | |
|     switch (tc.datatype())
 | |
|     {
 | |
|       case 'N': // number
 | |
|       {
 | |
|         real tmp(campo);
 | |
|         campo=tmp.string(tc.picture());
 | |
|       }
 | |
|       break;
 | |
|       case 'D': //data
 | |
|       {
 | |
|       	TDate d(campo);
 | |
|         TFormatted_date tmp(d, tc.picture());
 | |
|         campo=tmp.string();
 | |
|       }
 | |
|       break;
 | |
|       default:
 | |
|       {
 | |
|         TString tmp;
 | |
|         tmp.picture(tc.picture(), campo);     
 | |
|         campo=tmp;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   if (length > campo.len())
 | |
|   {
 | |
|     if (fillch == '\0' && _fixedlen)
 | |
|       fillch=' ';
 | |
|     if (tc.align() == 'R')
 | |
|       campo.right_just(length,fillch);
 | |
|     else
 | |
|       campo.left_just(length, fillch);            
 | |
|   } 
 | |
|   else              
 | |
|   {
 | |
|     if (length > 0)
 | |
|     {
 | |
|       if (tc.align() == 'R')
 | |
|         campo=campo.right(length); 
 | |
|       else
 | |
|         campo.cut(length); 
 | |
|     }    
 | |
|   }      
 | |
|   return campo;    
 | |
| }    
 | |
| 
 | |
| // Formatta la stringa passata in base al field del file isam
 | |
| // La stringa ritornata rappresenta il valore del campo nel file isam e i parametri di fomattazione
 | |
| // sono quelli associati al campo nel file isam (metodi fpicture, falign ecc.)
 | |
| TString& TFile_text::format_field(const TTracciato_campo& tc, short lfile, TString& campo)
 | |
| {
 | |
|     const TRectype record(tc.field().file() ? tc.field().file() : lfile);
 | |
| 
 | |
|     int length = flength(tc,record);
 | |
|     const bool is_memo = record.type(tc.field().name()) == _memofld;
 | |
|     
 | |
|     if (!fpicture(tc).blank())
 | |
|     { 
 | |
|       TString tmp;
 | |
|       tmp.picture(fpicture(tc), campo);     
 | |
|       campo=tmp;
 | |
|     }
 | |
|     if (length > campo.len() || is_memo) // Se il field di destinazione e' un memo... si scrive tutto!
 | |
|     {
 | |
|       if (falign(tc) == 'R')
 | |
|         campo.right_just(length, ffiller(tc));
 | |
|       else
 | |
|         campo.left_just(length, ffiller(tc));            
 | |
|     } 
 | |
|     else              
 | |
|     {
 | |
|       if (length > 0)
 | |
|       {
 | |
|         if (falign(tc) == 'R')
 | |
|           campo=campo.right(length); 
 | |
|         else
 | |
|           campo.cut(length);
 | |
|       }    
 | |
|     }       
 | |
|     return campo;    
 | |
| }    
 | |
| 
 | |
| int TFile_text::open(char mode)
 | |
| {
 | |
|   if (mode == 'r')//apertura in lettura
 | |
|   {          
 | |
|     if (_read_file)
 | |
|       delete _read_file;
 | |
| 
 | |
|     _read_file = new ifstream(_name, ios::binary);
 | |
| 
 | |
|     if (!ok_r())
 | |
|     {
 | |
|       error_box("Impossibile aprire il file %s in lettura", (const char *)_name);
 | |
|       return _read_file->rdstate() != ios::goodbit;
 | |
|     }
 | |
|     
 | |
|     if (_skiplines > 0)
 | |
|     {            
 | |
|       if (_recordsize > 0)
 | |
|       {        
 | |
|         streamoff bytestoskip = streamoff(_recordsize) * _skiplines;
 | |
|         _read_file->seekg(bytestoskip, ios::beg);
 | |
|       } else
 | |
|       if (_recordsep.not_empty())
 | |
|       {
 | |
|         int s = _skiplines;
 | |
|         int c;            
 | |
|         for (c = _read_file->get(); c != EOF; c = _read_file->get())
 | |
|         {
 | |
|           if (c == _recordsep[0]) 
 | |
|           {
 | |
|             for (int k = _recordsep.len()-1; k > 0; k--)
 | |
|               c = _read_file->get();
 | |
|             if (--s == 0)
 | |
|               break;
 | |
|           }  
 | |
|         }  
 | |
|         if (c == EOF)
 | |
|           return 1;
 | |
|       }    
 | |
|     }
 | |
|   }
 | |
|   if (mode == 'w')//apertura in scrittura
 | |
|   {
 | |
|     if (_write_file)
 | |
|       delete _write_file;
 | |
|     _write_file = new ofstream(_name, ios::binary|ios::app);  
 | |
|   }  
 | |
| 
 | |
|   return 0;  
 | |
| }
 | |
| 
 | |
| int TFile_text::open(const char* name, char mode)
 | |
| {                               
 | |
|   set_name(name);
 | |
|   return open(mode);
 | |
| }                 
 | |
| 
 | |
| 
 | |
| int TFile_text::close()
 | |
| {
 | |
|   _name = "";
 | |
|   _current = NULL;
 | |
|   if (_read_file) _read_file->close();
 | |
|   if (_write_file) _write_file->close();
 | |
|   return 0;
 | |
| }
 |