home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////
- // Implementation file of database class: NAC.
- //
- // Source generated by: CSDBGEN version 1.2.b.
- // Date of generation: Thursday, 2 March 1995.
- // Time of generation: 12:02:10.
- //
- //
- // The next lines represent the database definition
- // file used as input for CSDBGEN.
- //
- //
- ////////////// Start of the .def file //////////////////
- /*
- class: NAC
- record: nac_record
- file: dbfile
- field: name s 40 T
- field: address s 30 Y
- field: city s 20 Y
- field: birthday d Y4MD Y
- field: salary f
- */
- /////////////// End of .def file //////////////////////////////////////////////
- /*
-
-
-
- █████ █ █
- ██ ██ ██ ██
- ███ ████ ███ ██ ███ ████
- ███ ██ ██ ███ ██ ██
- ███ ██ █████ ██ ██
- ██ ██ ██ █ ██ ██ ██ ██ █
- █████ ██ ███ ██ ██ ██
-
-
- ████ ████ ██ ██ ██ ███ █████ ████
- ██ ██ ██ ██ ██ ███ ██ ██ █ ██ ██
- ████ ██ ██ ██ ██ ██ ██ ██████
- ██ ██ ██ ██ ██ ██ ██ █ ██
- ████ ████ ███ ██ ██ █████ █████
-
-
-
- */
- //////////////////////////////////////////////////////////////////////////////
-
- #include "demo.h"
-
- extern unsigned _stklen=7000; //A large stack is needed
-
-
- ///////////////////////////////// Constructor ////////////////////////////////
- NAC::NAC(void)
- {
- is_open=FALSE;
- current=1;
- _birthday.format(Y4MD);
- }
-
- ///////////////////////////////// reindex ////////////////////////////////////
- void NAC::reindex(void)
- {
- U32 l=current;
- nac_record *rp;
- in1.empty();
- in2.empty();
- in3.empty();
- in4.empty();
- for(current=numrec(); current>0; current--)
- {
- rp=(nac_record *)db.locate_rec(current);
- tokenize(rp->_name,&NAC::in1_ins_tok);
- in2.insert(rp->_address,¤t);
- in3.insert(rp->_city,¤t);
- in4.insert(&rp->__birthday,¤t);
- }
- current=l;
- }
-
- /////////////// go_to ////////////////////////////////////////////
- void NAC::go_to(long n)
- {
- if(order()!=UNSORTED)
- {
- csmess_p(7110,"NAC");
- return;
- }
- write_rec();
- current=max(min(n,db.numrec()),1);
- read_rec();
- }
-
- /////////////// append blank//////////////////////////////////////
- void NAC::append_blank(void)
- {
- append();
- tokenize(recp->_name,&NAC::in1_ins_tok);
- in2.insert(rec._address,¤t);
- in3.insert(rec._city,¤t);
- in4.insert(&rec.__birthday,¤t);
- }
-
- ///////////////////////////////// append /////////////////////////////////////
- // This function doesn't update the indexes, which can save some
- // disk I/O because you are likely to alter the fields
- // immediately after you have appended the record.
- // However, if you have an index on a field you don't update, this
- // record will NOT appear in that particular index!
- // The 'append_blank' function does update all indexes, which
- // makes it a safer, but slower option.
- //
- void NAC::append(void)
- {
- write_rec();
- memset(&rec,0,sizeof(nac_record));
- current=db.append_rec(&rec);
- recp=(nac_record *)db.locate_rec(current);
- dirty=TRUE;
- _birthday.sem_jul(0L);
- }
-
- ///////////////////////////////// open ///////////////////////////////////////
- void NAC::open(void)
- {
- if(is_open) return;
- int needs_reindex=FALSE;
- dirty=FALSE;
-
- #ifdef _Windows
- int fre=300/9; //Use 300 Kb for buffers. You may increase this.
- #else
- int fre=(int)(coreleft()-100000L)/9/1024;
- fre=max(fre,0);
- #endif
-
- if(!db.open("dbfile.dbf",fre))
- {
- csmess_disp("FATAL: Can't open database dbfile.dbf.");
- exit(1);
- }
- if(db.lengthrec()!=sizeof(nac_record))
- {
- csmess_disp("FATAL: wrong record size.\n\rProbably wrong or old database file.");
- db.close();
- exit(1);
- }
- if(!file_exist("dbfile01.idx"))
- {
- in1.multiple_keys(TRUE);
- in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
- needs_reindex=TRUE;
- }
- in1.open("dbfile01.idx",fre*2);
-
- if(!file_exist("dbfile02.idx"))
- {
- in2.multiple_keys(TRUE);
- in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
- needs_reindex=TRUE;
- }
- in2.open("dbfile02.idx",fre*2);
-
- if(!file_exist("dbfile03.idx"))
- {
- in3.multiple_keys(TRUE);
- in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
- needs_reindex=TRUE;
- }
- in3.open("dbfile03.idx",fre*2);
-
- if(!file_exist("dbfile04.idx"))
- {
- in4.multiple_keys(TRUE);
- in4.define("dbfile04.idx",sizeof(long),sizeof(long));
- needs_reindex=TRUE;
- }
- in4.open("dbfile04.idx",fre*2);
-
- if(needs_reindex) reindex();
- is_open=TRUE;
- if(numrec()==0) append_blank();
- else read_rec();
-
- order(UNSORTED);
- }
-
- ///////////////////////////////// close //////////////////////////////////////
- void NAC::close(void)
- {
- if(!is_open) return;
- write_rec();
- db.close();
- in1.close();
- in2.close();
- in3.close();
- in4.close();
- is_open=FALSE;
- }
-
- ///////////////////////////////// define /////////////////////////////////////
- void NAC::define(void)
- {
- db.define("dbfile.dbf",sizeof(nac_record));
- in1.multiple_keys(TRUE);
- in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
- in2.multiple_keys(TRUE);
- in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
- in3.multiple_keys(TRUE);
- in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
- in4.multiple_keys(TRUE);
- in4.define("dbfile04.idx",sizeof(long),sizeof(long));
- }
-
- ///////////////////////////////// pack ///////////////////////////////////////
- void NAC::pack(void)
- {
- write_rec();
- db.pack();
- reindex();
- if(numrec()==0) append_blank();
- top();
- }
-
- ///////////////////////////////// skip ///////////////////////////////////////
- int NAC::skip0(int delta)
- {
- long old_current=current;
- current=max(min(current+delta,db.numrec()),1);
- return current-old_current;
- }
-
- int NAC::skip(int delta)
- {
- int rc;
- write_rec();
- rc=(this->*skip_fun)(delta);
- read_rec();
- return rc;
- }
-
- ///////////////////////////////// order //////////////////////////////////////
- void NAC::order(int nr)
- {
- switch(nr)
- {
- case 0: //Unsorted
- bof_fun =&NAC::bof0;
- eof_fun =&NAC::eof0;
- skip_fun =&NAC::skip0;
- top_fun =&NAC::top0;
- bottom_fun=&NAC::bottom0;
- search_fun=&NAC::search0;
- break;
- case 1: //Index on field name
- bof_fun =&NAC::bof1;
- eof_fun =&NAC::eof1;
- skip_fun =&NAC::skip1;
- top_fun =&NAC::top1;
- bottom_fun=&NAC::bottom1;
- search_fun=&NAC::search1;
- break;
- case 2: //Index on field address
- bof_fun =&NAC::bof2;
- eof_fun =&NAC::eof2;
- skip_fun =&NAC::skip2;
- top_fun =&NAC::top2;
- bottom_fun=&NAC::bottom2;
- search_fun=&NAC::search2;
- break;
- case 3: //Index on field city
- bof_fun =&NAC::bof3;
- eof_fun =&NAC::eof3;
- skip_fun =&NAC::skip3;
- top_fun =&NAC::top3;
- bottom_fun=&NAC::bottom3;
- search_fun=&NAC::search3;
- break;
- case 4: //Index on field birthday
- bof_fun =&NAC::bof4;
- eof_fun =&NAC::eof4;
- skip_fun =&NAC::skip4;
- top_fun =&NAC::top4;
- bottom_fun=&NAC::bottom4;
- search_fun=&NAC::search4;
- break;
- default: return; // Function called with wrong parameter.
- }
- iOrder=nr;
- top();
- }
- /////////////////////////////writing record ///////////////////////////////
- void NAC::write_rec2(void)
- {
- if(strcmp(recp->_name,rec._name))
- {
- tokenize(recp->_name,&NAC::in1_del_tok);
- tokenize(rec._name,&NAC::in1_ins_tok);
- }
- if(strcmp(recp->_address,rec._address))
- {
- in2.delet(recp->_address,¤t);
- in2.insert(rec._address,¤t);
- }
- if(strcmp(recp->_city,rec._city))
- {
- in3.delet(recp->_city,¤t);
- in3.insert(rec._city,¤t);
- }
- rec.__birthday=_birthday.sem_jul();
- if(recp->__birthday!=rec.__birthday)
- {
- in4.delet(&recp->__birthday,¤t);
- in4.insert(&rec.__birthday,¤t);
- }
- db.write_rec(current,&rec);
- dirty=FALSE;
- }
-
- ///////////////////////////////// export /////////////////////////////////////
- int NAC::export(char *s)
- {
- FILE *fo=fopen(s,"w");
- if(fo==NULL) return FALSE;
-
- write_rec();
- fprintf(fo,"class: NAC");
- fprintf(fo,"\nrecord: nac_record");
- fprintf(fo,"\nfile: dbfile");
- fprintf(fo,"\nfield: name s 40 Y");
- fprintf(fo,"\nfield: address s 30 Y");
- fprintf(fo,"\nfield: city s 20 Y");
- fprintf(fo,"\nfield: birthday d Y");
- fprintf(fo,"\nfield: salary f ");
-
- if(ferror(fo)) { fclose(fo); return FALSE; }
-
- nac_record *recp;
- DATE conv;
- conv.format(Y4MD);
- for(long l=numrec();l>0;l--)
- {
- recp=( nac_record * )db.locate_rec(l);
- fprintf(fo,"\n%c",12);
- fprintf(fo,"\n%s",recp->_name);
- fprintf(fo,"\n%s",recp->_address);
- fprintf(fo,"\n%s",recp->_city);
- conv.sem_jul(recp->__birthday);
- fprintf(fo,"\n%s",(char *)conv);
- fprintf(fo,"\n%g",recp->_salary);
- fprintf(fo,"\n"); //Additional linefeed, to avoid trouble!
-
- if(ferror(fo)) { fclose(fo); return FALSE; }
- }
- return !fclose(fo);
- }
-
- ///////////////////////////////// import /////////////////////////////////////
- int NAC::import(char *s)
- {
-
- FILE *fr=fopen(s,"r");
- if(fr==NULL) return FALSE;
-
-
- #define MAX_NUM_FIELDS 100 //Increase this to allow more fields
- #define MAX_FIELD_LEN 500 //Increase this to allow longer fields
-
- int *finu;
- finu=(int *)malloc(MAX_NUM_FIELDS*sizeof(int));
- if(finu==NULL) { fclose(fr); return FALSE; }
-
- char *fibu;
- fibu=(char *)malloc(MAX_FIELD_LEN);
- if(fibu==NULL) { fclose(fr); free(finu); return FALSE; }
- *fibu=0;
-
- char *fipo=fibu+strlen("field:");
- char *cp;
- int ifieldnr=0;
- int ofieldnr;
- DATE conv;
- conv.format(Y4MD);
-
- memset(finu,0,MAX_NUM_FIELDS*sizeof(int));
-
- fgets(fibu,MAX_FIELD_LEN,fr);
- while(!strchr(fibu,12))
- {
- strlwr(fibu);
- notabs(fibu);
- trim_string(fibu);
- if(strstr(fibu,"field:"))
- {
- ifieldnr++;
- trim_string(fipo);
- if((cp=strchr(fipo,' '))!=NULL) *cp=0;
- if (!strcmp(fipo,"name")) ofieldnr=1;
- else if(!strcmp(fipo,"address")) ofieldnr=2;
- else if(!strcmp(fipo,"city")) ofieldnr=3;
- else if(!strcmp(fipo,"birthday")) ofieldnr=4;
- else if(!strcmp(fipo,"salary")) ofieldnr=5;
- else ofieldnr=0;
- finu[ifieldnr]=ofieldnr;
- }
- fgets(fibu,MAX_FIELD_LEN,fr);
- }
-
-
-
- for(;;)
- {
- if(!strchr(fibu,12))
- {
- ifieldnr++;
- if(ifieldnr<MAX_NUM_FIELDS)
- switch(finu[ifieldnr])
- {
- case 0: break;
- case 1:
- fibu[NAME_LENGTH]=0;
- name(fibu);
- break;
- case 2:
- fibu[ADDRESS_LENGTH]=0;
- address(fibu);
- break;
- case 3:
- fibu[CITY_LENGTH]=0;
- city(fibu);
- break;
- case 4:
- conv=fibu;
- _birthday.sem_jul(conv.sem_jul());
- break;
- case 5:
- salary(atof(fibu));
- break;
- }
- }
- else
- {
- ifieldnr=0;
- append_blank();
- }
- if(feof(fr)) break;
- fgets(fibu,MAX_FIELD_LEN,fr);
- cp=fibu+(max(1,strlen(fibu))-1);
- if(*cp=='\n') *cp=0; //removing the line feed
- }
-
-
- fclose(fr);
- free(fibu);
- free(finu);
-
- #undef MAX_NUM_FIELDS
- #undef MAX_FIELD_LEN
-
- return TRUE;
- }
-
- ///////////////////////////////// export to dBASE compatible file. ///////////
- int NAC::to_DBASE(char *s)
- {
-
- char bufje[12];
- if(!is_open) return FALSE;
-
- write_rec();
- FILE *fo=fopen(s,"wb");
- if(fo==NULL) return FALSE;
-
- int i;
-
- DATE d_upda;
- d_upda.sem_jul(db.sj_updated());
- fputc(03,fo);
-
- fputc(d_upda.year()%100,fo);
- fputc(d_upda.month(),fo);
- fputc(d_upda.day(),fo);
-
- long nr_record=numrec();
- fwrite(&nr_record,sizeof(long),1,fo);
- putw(194,fo); //Header length
- putw(113,fo); //Length of data record
- for(i=0;i<20;i++) fputc(0,fo); // 20 dummy bytes
-
-
- // Writing definition of field name to dbase file header.
- memset(bufje,0,11);
- strcpy(bufje,"NAME");
- fwrite(bufje,11,1,fo);
- fputc('C',fo);
- for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
- fputc(40,fo);
- fputc(0,fo);
- for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
-
- // Writing definition of field address to dbase file header.
- memset(bufje,0,11);
- strcpy(bufje,"ADDRESS");
- fwrite(bufje,11,1,fo);
- fputc('C',fo);
- for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
- fputc(30,fo);
- fputc(0,fo);
- for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
-
- // Writing definition of field city to dbase file header.
- memset(bufje,0,11);
- strcpy(bufje,"CITY");
- fwrite(bufje,11,1,fo);
- fputc('C',fo);
- for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
- fputc(20,fo);
- fputc(0,fo);
- for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
-
- // Writing definition of field birthday to dbase file header.
- memset(bufje,0,11);
- strcpy(bufje,"BIRTHDAY");
- fwrite(bufje,11,1,fo);
- fputc('D',fo);
- for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
- fputc(8,fo);
- fputc(0,fo);
- for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
-
- // Writing definition of field salary to dbase file header.
- memset(bufje,0,11);
- strcpy(bufje,"SALARY");
- fwrite(bufje,11,1,fo);
- fputc('N',fo);
- for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
- fputc(14,fo);
- fputc(7,fo);
- for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
-
-
- fputc(13,fo); //Field terminator
- fputc(0,fo);
-
- // By now we have written the definition of the
- // record structure to the file header.
- // From here on we will export the records.
-
- nac_record *recp;
- for(long l=numrec();l>0;l--)
- {
-
- if(ferror(fo)) { fclose(fo); return FALSE; }
- recp=(nac_record *)db.locate_rec(l);
-
- if(db.is_delet(l)) fputc(42,fo);
- else fputc(32,fo);
-
- /////////////////////// writing field name /////////////
- fprintf(fo,"%-40s",recp->_name);
- /////////////////////// writing field address /////////////
- fprintf(fo,"%-30s",recp->_address);
- /////////////////////// writing field city /////////////
- fprintf(fo,"%-20s",recp->_city);
- /////////////////////// writing field birthday /////////////
- if(recp->__birthday)
- {
- d_upda.sem_jul(recp->__birthday);
- fprintf(fo,"%4d",d_upda.year4());
- fprintf(fo,"%02d",d_upda.month());
- fprintf(fo,"%02d",d_upda.day());
- }
- else
- {
- fprintf(fo," ");
- }
- /////////////////////// writing field salary /////////////
- fprintf(fo,"%14.7f",recp->_salary);
- }
- fputc(26,fo); //End of File
- fclose(fo);
-
- return TRUE;
- }
-
- ///////////////////////////////// tokenize field ///////////////////////
- void NAC::tokenize(char *s,void(NAC::*fun)(void *))
- {
-
- char delim[]="\t,()- "; //Token delimiters
- const min_len=4; //Minimum length for a token to be indexed.
- char *p,*q=s;
- char c;
- int insert=FALSE;
-
- p=strpbrk(q,delim);
- while(p)
- {
- c=*p; *p=0;
- if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
- *p=c;
- do{ p=strpbrk(q=p+1,delim); }while(q==p);
- }
-
- if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
- if(!insert) (this->*fun)(s);
-
- }