modules_s/dbtext/dbt_file.c

00001 /*
00002  * $Id$
00003  *
00004  * DBText library
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License 
00026  * along with this program; if not, write to the Free Software 
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  */
00029 
00037 #include <stdio.h>
00038 #include <string.h>
00039 #include <time.h>
00040 #include <sys/types.h>
00041 #include <dirent.h>
00042 
00043 #include "../../mem/shm_mem.h"
00044 #include "../../mem/mem.h"
00045 #include "../../dprint.h"
00046 
00047 #include "dbt_util.h"
00048 #include "dbt_lib.h"
00049 
00050 
00054 dbt_table_p dbt_load_file(str *tbn, str *dbn)
00055 {
00056         FILE *fin=NULL;
00057         char path[512], buf[4096];
00058         int c, crow, ccol, bp, sign, max_auto;
00059         dbt_val_t dtval;
00060         dbt_table_p dtp = NULL;
00061         dbt_column_p colp, colp0 = NULL;
00062         dbt_row_p rowp, rowp0 = NULL;
00063                 
00064         enum {DBT_FLINE_ST, DBT_NLINE_ST, DBT_DATA_ST} state;
00065         
00066         DBG("DBT:dbt_load_file: request for table [%.*s]\n", tbn->len, tbn->s);
00067         
00068         if(!tbn || !tbn->s || tbn->len<=0 || tbn->len>=255)
00069                 return NULL;
00070         path[0] = 0;
00071         if(dbn && dbn->s && dbn->len>0)
00072         {
00073                 DBG("DBT:dbt_load_file: db is [%.*s]\n", dbn->len, dbn->s);
00074                 if(dbn->len+tbn->len<511)
00075                 {
00076                         strncpy(path, dbn->s, dbn->len);
00077                         path[dbn->len] = '/';
00078                         strncpy(path+dbn->len+1, tbn->s, tbn->len);
00079                         path[dbn->len+tbn->len+1] = 0;
00080                 }
00081         }
00082         if(path[0] == 0)
00083         {
00084                 strncpy(path, tbn->s, tbn->len);
00085                 path[tbn->len] = 0;
00086         }
00087         
00088         DBG("DBT:dbt_load_file: loading file [%s]\n", path);
00089         fin = fopen(path, "rt");
00090         if(!fin)
00091                 return NULL;    
00092         
00093         dtp = dbt_table_new(tbn->s, tbn->len);
00094         if(!dtp)
00095                 goto done;
00096         
00097         state = DBT_FLINE_ST;
00098         crow = ccol = -1;
00099         colp = colp0 = NULL;
00100         rowp = rowp0 = NULL;
00101         c = fgetc(fin);
00102         max_auto = 0;
00103         while(c!=EOF)
00104         {
00105                 switch(state)
00106                 {
00107                         case DBT_FLINE_ST:
00108                                 //DBG("DBT:dbt_load_file: state FLINE!\n");
00109                                 bp = 0;
00110                                 while(c==DBT_DELIM_C)
00111                                         c = fgetc(fin);
00112                                 if(c==DBT_DELIM_R && !colp0)
00113                                         goto clean;
00114                                 if(c==DBT_DELIM_R)
00115                                 {
00116                                         if(dtp->nrcols <= 0)
00117                                                 goto clean;
00118                                         dtp->colv = (dbt_column_p*)
00119                                                         shm_malloc(dtp->nrcols*sizeof(dbt_column_p));
00120                                         if(!dtp->colv)
00121                                                 goto clean;
00122                                         colp0 = dtp->cols;
00123                                         for(ccol=0; ccol<dtp->nrcols && colp0; ccol++)
00124                                         {
00125                                                 dtp->colv[ccol] = colp0;
00126                                                 colp0 = colp0->next;
00127                                         }
00128                                         state = DBT_NLINE_ST;
00129                                         break;
00130                                 }
00131                                 while(c!=DBT_DELIM_C && c!='(' && c!=DBT_DELIM_R)
00132                                 {
00133                                         if(c==EOF)
00134                                                 goto clean;
00135                                         buf[bp++] = c;
00136                                         c = fgetc(fin);
00137                                 }
00138                                 colp = dbt_column_new(buf, bp);
00139                                 if(!colp)
00140                                         goto clean;
00141                                 //DBG("DBT:dbt_load_file: new col [%.*s]\n", bp, buf);
00142                                 while(c==DBT_DELIM_C)
00143                                         c = fgetc(fin);
00144                                 if(c!='(')
00145                                         goto clean;
00146                                 c = fgetc(fin);
00147                                 while(c==DBT_DELIM_C)
00148                                         c = fgetc(fin);
00149                                 
00150                                 switch(c)
00151                                 {
00152                                         case 's':
00153                                         case 'S':
00154                                                 colp->type = DB_STR;
00155                                                 DBG("DBT: column[%d] is STR!\n", ccol+1);
00156                                         break;
00157                                         case 'i':
00158                                         case 'I':
00159                                                 colp->type = DB_INT;
00160                                                 DBG("DBT: column[%d] is INT!\n", ccol+1);
00161                                         break;
00162                                         case 'f':
00163                                         case 'F':
00164                                                 colp->type = DB_FLOAT;
00165                                                 DBG("DBT: column[%d] is FLOAT!\n", ccol+1);
00166                                         break;
00167                                         case 'd':
00168                                         case 'D':
00169                                                 colp->type = DB_DOUBLE;
00170                                                 DBG("DBT: column[%d] is DOUBLE!\n", ccol+1);
00171                                         break;
00172                                         default:
00173                                                 DBG("DBT: wrong column type!\n");
00174                                                 goto clean;
00175                                 }
00176 
00177                                 while(c!=')' && c!= ',')
00178                                         c = fgetc(fin);
00179                                 if(c==',')
00180                                 {
00181                                         //DBG("DBT: c=%c!\n", c);
00182                                         c = fgetc(fin);
00183                                         while(c==DBT_DELIM_C)
00184                                                 c = fgetc(fin);
00185                                         if(c=='N' || c=='n')
00186                                         {
00187                                                 //DBG("DBT:dbt_load_file: NULL flag set!\n");
00188                                                 colp->flag |= DBT_FLAG_NULL;
00189                                         }
00190                                         else if(colp->type==DB_INT && dtp->auto_col<0
00191                                                         && (c=='A' || c=='a'))
00192                                         {
00193                                                 //DBG("DBT:dbt_load_file: AUTO flag set!\n");
00194                                                 colp->flag |= DBT_FLAG_AUTO;
00195                                                 dtp->auto_col = ccol+1;
00196                                         }
00197                                         else
00198                                                 goto clean;
00199                                         while(c!=')' && c!=DBT_DELIM_R && c!=EOF)
00200                                                 c = fgetc(fin);
00201                                 }
00202                                 if(c == ')')
00203                                 {
00204                                         //DBG("DBT: c=%c!\n", c);
00205                                         if(colp0)
00206                                         {
00207                                                 colp->prev = colp0;
00208                                                 colp0->next = colp;
00209                                         }
00210                                         else
00211                                                 dtp->cols = colp;
00212                                         colp0 = colp;
00213                                         dtp->nrcols++;
00214                                         c = fgetc(fin);
00215                                 }
00216                                 else
00217                                         goto clean;
00218                                 ccol++;
00219                         break;
00220 
00221                         case DBT_NLINE_ST:
00222                                 //DBG("DBT:dbt_load_file: state NLINE!\n");
00223                                 while(c==DBT_DELIM_R)
00224                                         c = fgetc(fin);
00225                                 if(rowp)
00226                                 {
00227                                         if(dbt_table_check_row(dtp, rowp))
00228                                                 goto clean;
00229 
00230                                         if(!rowp0)
00231                                                 dtp->rows = rowp;
00232                                         else
00233                                         {
00234                                                 rowp0->next = rowp;
00235                                                 rowp->prev = rowp0;
00236                                         }
00237                                         rowp0 = rowp;
00238                                         dtp->nrrows++;
00239                                 }
00240                                 if(c==EOF)
00241                                         break;
00242                                 crow++;
00243                                 ccol = 0;
00244                                 rowp = dbt_row_new(dtp->nrcols);
00245                                 if(!rowp)
00246                                         goto clean;
00247                                 state = DBT_DATA_ST;
00248                                 
00249                         break;
00250                         
00251                         case DBT_DATA_ST:
00252                                 //DBG("DBT:dbt_load_file: state DATA!\n");
00253                                 //while(c==DBT_DELIM)
00254                                 //      c = fgetc(fin);
00255                                 if(ccol == dtp->nrcols && (c==DBT_DELIM_R || c==EOF))
00256                                 {
00257                                         state = DBT_NLINE_ST;
00258                                         break;
00259                                 }
00260                                 if(ccol>= dtp->nrcols)
00261                                         goto clean;
00262                                 
00263                                 switch(dtp->colv[ccol]->type)
00264                                 {
00265                                         case DB_INT:
00266                                                 //DBG("DBT:dbt_load_file: INT value!\n");
00267                                                 dtval.val.int_val = 0;
00268                                                 dtval.type = DB_INT;
00269 
00270                                                 if(c==DBT_DELIM || 
00271                                                                 (ccol==dtp->nrcols-1
00272                                                                  && (c==DBT_DELIM_R || c==EOF)))
00273                                                         dtval.nul = 1;
00274                                                 else
00275                                                 {
00276                                                         dtval.nul = 0;
00277                                                         sign = 1;
00278                                                         if(c=='-')
00279                                                         {
00280                                                                 sign = -1;
00281                                                                 c = fgetc(fin);
00282                                                         }
00283                                                         if(c<'0' || c>'9')
00284                                                                 goto clean;
00285                                                         while(c>='0' && c<='9')
00286                                                         {
00287                                                                 dtval.val.int_val=dtval.val.int_val*10+c-'0';
00288                                                                 c = fgetc(fin);
00289                                                         }
00290                                                         dtval.val.int_val *= sign;
00291                                                         //DBG("DBT:dbt_load_file: data[%d,%d]=%d\n", crow,
00292                                                         //      ccol, dtval.val.int_val);
00293                                                 }
00294                                                 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00295                                                         goto clean;
00296                                                 if(dbt_row_set_val(rowp,&dtval,DB_INT,ccol))
00297                                                         goto clean;
00298                                                 if(ccol == dtp->auto_col)
00299                                                         max_auto = (max_auto<dtval.val.int_val)?
00300                                                                         dtval.val.int_val:max_auto;
00301                                         break;
00302                                         
00303                                         case DB_FLOAT:
00304                                                 //DBG("DBT:dbt_load_file: FLOAT value!\n");
00305                                                 dtval.val.float_val = 0.0;
00306                                                 dtval.type = DB_FLOAT;
00307 
00308                                                 if(c==DBT_DELIM || 
00309                                                                 (ccol==dtp->nrcols-1
00310                                                                  && (c==DBT_DELIM_R || c==EOF)))
00311                                                         dtval.nul = 1;
00312                                                 else
00313                                                 {
00314                                                         dtval.nul = 0;
00315                                                         sign = 1;
00316                                                         if(c=='-')
00317                                                         {
00318                                                                 sign = -1;
00319                                                                 c = fgetc(fin);
00320                                                         }
00321                                                         if(c<'0' || c>'9')
00322                                                                 goto clean;
00323                                                         while(c>='0' && c<='9')
00324                                                         {
00325                                                                 dtval.val.float_val = dtval.val.float_val*10
00326                                                                                 + c - '0';
00327                                                                 c = fgetc(fin);
00328                                                         }
00329                                                         if(c=='.')
00330                                                         {
00331                                                                 c = fgetc(fin);
00332                                                                 bp = 1;
00333                                                                 while(c>='0' && c<='9')
00334                                                                 {
00335                                                                         bp *= 10;
00336                                                                         dtval.val.float_val+=((float)(c-'0'))/bp;
00337                                                                         c = fgetc(fin);
00338                                                                 }
00339                                                         }
00340                                                         dtval.val.float_val *= sign;
00341                                                         //DBG("DBT:dbt_load_file: data[%d,%d]=%10.2f\n",
00342                                                         //      crow, ccol, dtval.val.float_val);
00343                                                 }
00344                                                 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00345                                                         goto clean;
00346                                                 if(dbt_row_set_val(rowp,&dtval,DB_FLOAT,ccol))
00347                                                         goto clean;
00348                                         break;
00349 
00350                                         case DB_DOUBLE:
00351                                                 //DBG("DBT:dbt_load_file: DOUBLE value!\n");
00352                                                 dtval.val.double_val = 0.0;
00353                                                 dtval.type = DB_DOUBLE;
00354 
00355                                                 if(c==DBT_DELIM || 
00356                                                                 (ccol==dtp->nrcols-1
00357                                                                  && (c==DBT_DELIM_R || c==EOF)))
00358                                                         dtval.nul = 1;
00359                                                 else
00360                                                 {
00361                                                         dtval.nul = 0;
00362                                                         sign = 1;
00363                                                         if(c=='-')
00364                                                         {
00365                                                                 sign = -1;
00366                                                                 c = fgetc(fin);
00367                                                         }
00368                                                         if(c<'0' || c>'9')
00369                                                                 goto clean;
00370                                                         while(c>='0' && c<='9')
00371                                                         {
00372                                                                 dtval.val.double_val = dtval.val.double_val*10
00373                                                                                 + c - '0';
00374                                                                 c = fgetc(fin);
00375                                                         }
00376                                                         if(c=='.')
00377                                                         {
00378                                                                 c = fgetc(fin);
00379                                                                 bp = 1;
00380                                                                 while(c>='0' && c<='9')
00381                                                                 {
00382                                                                         bp *= 10;
00383                                                                         dtval.val.double_val+=((double)(c-'0'))/bp;
00384                                                                         c = fgetc(fin);
00385                                                                 }
00386                                                         }
00387                                                         dtval.val.double_val *= sign;
00388                                                         //DBG("DBT:dbt_load_file: data[%d,%d]=%10.2f\n",
00389                                                         //      crow, ccol, dtval.val.double_val);
00390                                                 }
00391                                                 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00392                                                         goto clean;
00393                                                 if(dbt_row_set_val(rowp,&dtval,DB_DOUBLE,ccol))
00394                                                         goto clean;
00395                                         break;
00396                                         
00397                                         case DB_STR:
00398                                                 //DBG("DBT:dbt_load_file: STR value!\n");
00399                                                 
00400                                                 dtval.val.str_val.s = NULL;
00401                                                 dtval.val.str_val.len = 0;
00402                                                 dtval.type = DB_STR;
00403                                                 
00404                                                 bp = 0;
00405                                                 if(c==DBT_DELIM || 
00406                                                                 (ccol == dtp->nrcols-1
00407                                                                  && (c == DBT_DELIM_R || c==EOF)))
00408                                                         dtval.nul = 1;
00409                                                 else
00410                                                 {
00411                                                         dtval.nul = 0;
00412                                                         while(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00413                                                         {
00414                                                                 if(c=='\\')
00415                                                                 {
00416                                                                         c = fgetc(fin);
00417                                                                         switch(c)
00418                                                                         {
00419                                                                                 case 'n':
00420                                                                                         c = '\n';       
00421                                                                                 break;
00422                                                                                 case 'r':
00423                                                                                         c = '\r';
00424                                                                                 break;
00425                                                                                 case 't':
00426                                                                                         c = '\t';
00427                                                                                 break;
00428                                                                                 case '\\':
00429                                                                                         c = '\\';
00430                                                                                 break;
00431                                                                                 case DBT_DELIM:
00432                                                                                         c = DBT_DELIM;
00433                                                                                 break;
00434                                                                                 case '0':
00435                                                                                         c = 0;
00436                                                                                 break;
00437                                                                                 default:
00438                                                                                         goto clean;
00439                                                                         }
00440                                                                 }
00441                                                                 buf[bp++] = c;
00442                                                                 c = fgetc(fin);
00443                                                         }
00444                                                         dtval.val.str_val.s = buf;
00445                                                         dtval.val.str_val.len = bp;
00446                                                         //DBG("DBT:dbt_load_file: data[%d,%d]=%.*s\n",
00448                                                 }
00449                                                 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00450                                                         goto clean;
00451                                                 if(dbt_row_set_val(rowp,&dtval,DB_STR,ccol))
00452                                                         goto clean;
00453                                         break;
00454                                         default:
00455                                                 goto clean;
00456                                 }
00457                                 if(c==DBT_DELIM)
00458                                         c = fgetc(fin);
00459                                 ccol++;
00460                         break; // state DBT_DATA_ST
00461                 }
00462         }
00463 
00464         if(max_auto)
00465                 dtp->auto_val = max_auto;
00466 
00467 done:
00468         if(fin)
00469                 fclose(fin);
00470         return dtp;
00471 clean:
00473         // memory leak?!?! with last incomplete row
00474         DBG("DBT:dbt_load_file: error at row=%d col=%d c=%c\n", crow+1, ccol+1, c);
00475         if(dtp)
00476                 dbt_table_free(dtp);
00477         return NULL;
00478 }
00479 
00480 
00484 int dbt_print_table(dbt_table_p _dtp, str *_dbn)
00485 {
00486         dbt_column_p colp = NULL;
00487         dbt_row_p rowp = NULL;
00488         FILE *fout = NULL;
00489         int ccol;
00490         char *p, path[512];
00491         
00492         if(!_dtp || !_dtp->name.s || _dtp->name.len <= 0)
00493                 return -1;
00494 
00495         if(!_dbn || !_dbn->s || _dbn->len <= 0)
00496         {
00497                 fout = stdout;
00498                 fprintf(fout, "\n Content of [%.*s]\n", _dtp->name.len, _dtp->name.s);
00499         }
00500         else
00501         {
00502                 if(_dtp->name.len+_dbn->len > 510)
00503                         return -1;
00504                 strncpy(path, _dbn->s, _dbn->len);
00505                 path[_dbn->len] = '/';
00506                 strncpy(path+_dbn->len+1, _dtp->name.s, _dtp->name.len);
00507                 path[_dbn->len+_dtp->name.len+1] = 0;
00508                 fout = fopen(path, "wt");
00509                 if(!fout)
00510                         return -1;      
00511         }
00512         
00513         colp = _dtp->cols;
00514         while(colp)
00515         {
00516                 switch(colp->type)
00517                 {
00518                         case DB_INT:
00519                                 fprintf(fout, "%.*s(int", colp->name.len, colp->name.s);
00520                         break;
00521                         case DB_FLOAT:
00522                                 fprintf(fout, "%.*s(float", colp->name.len, colp->name.s);
00523                         break;
00524                         case DB_DOUBLE:
00525                                 fprintf(fout, "%.*s(double", colp->name.len, colp->name.s);
00526                         break;
00527                         case DB_STR:
00528                                 fprintf(fout, "%.*s(str", colp->name.len, colp->name.s);
00529                         break;
00530                         default:
00531                                 if(fout!=stdout)
00532                                         fclose(fout);
00533                                 return -1;
00534                 }
00535                 
00536                 if(colp->flag & DBT_FLAG_NULL)
00537                                 fprintf(fout,",null");
00538                 else if(colp->type==DB_INT && colp->flag & DBT_FLAG_AUTO)
00539                                         fprintf(fout,",auto");
00540                 fprintf(fout,")");
00541                 
00542                 colp = colp->next;
00543                 if(colp)
00544                         fprintf(fout,"%c", DBT_DELIM_C);
00545         }
00546         fprintf(fout, "%c", DBT_DELIM_R);
00547         rowp = _dtp->rows;
00548         while(rowp)
00549         {
00550                 for(ccol=0; ccol<_dtp->nrcols; ccol++)
00551                 {
00552                         switch(_dtp->colv[ccol]->type)
00553                         {
00554                                 case DB_INT:
00555                                         if(!rowp->fields[ccol].nul)
00556                                                 fprintf(fout,"%d",
00557                                                                 rowp->fields[ccol].val.int_val);
00558                                 break;
00559                                 case DB_FLOAT:
00560                                         if(!rowp->fields[ccol].nul)
00561                                                 fprintf(fout, "%.2f",
00562                                                                 rowp->fields[ccol].val.float_val);
00563                                 break;
00564                                 case DB_DOUBLE:
00565                                         if(!rowp->fields[ccol].nul)
00566                                                 fprintf(fout, "%.2f",
00567                                                                 rowp->fields[ccol].val.double_val);
00568                                 break;
00569                                 case DB_STR:
00570                                         if(!rowp->fields[ccol].nul)
00571                                         {
00572                                                 p = rowp->fields[ccol].val.str_val.s;
00573                                                 while(p < rowp->fields[ccol].val.str_val.s
00574                                                                 + rowp->fields[ccol].val.str_val.len)
00575                                                 {
00576                                                         switch(*p)
00577                                                         {
00578                                                                 case '\n':
00579                                                                         fprintf(fout, "\\n");
00580                                                                 break;
00581                                                                 case '\r':
00582                                                                         fprintf(fout, "\\r");
00583                                                                 break;
00584                                                                 case '\t':
00585                                                                         fprintf(fout, "\\t");
00586                                                                 break;
00587                                                                 case '\\':
00588                                                                         fprintf(fout, "\\\\");
00589                                                                 break;
00590                                                                 case DBT_DELIM:
00591                                                                         fprintf(fout, "\\%c", DBT_DELIM);
00592                                                                 break;
00593                                                                 case '\0':
00594                                                                         fprintf(fout, "\\0");
00595                                                                 break;
00596                                                                 default:
00597                                                                         fprintf(fout, "%c", *p);
00598                                                         }
00599                                                         p++;
00600                                                 }
00601                                         }
00602                                 break;
00603                                 default:
00604                                         if(fout!=stdout)
00605                                                 fclose(fout);
00606                                         return -1;
00607                         }
00608                         if(ccol<_dtp->nrcols-1)
00609                                 fprintf(fout, "%c",DBT_DELIM);
00610                 }
00611                 fprintf(fout, "%c", DBT_DELIM_R);
00612                 rowp = rowp->next;
00613         }
00614         
00615         if(fout!=stdout)
00616                 fclose(fout);
00617         
00618         return 0;
00619 }
00620