COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_full/CsvTextBook.cpp
Go to the documentation of this file.
00001 
00002 #include <coopy/CsvTextBook.h>
00003 #include <coopy/CsvFile.h>
00004 #include <coopy/FormatSniffer.h>
00005 
00006 #include <algorithm>
00007 
00008 using namespace coopy::store;
00009 using namespace coopy::format;
00010 using namespace std;
00011 
00012 static string getRoot(const char *fname) {
00013   string root = fname;
00014   if (root.rfind("/")!=string::npos) {
00015     root = root.substr(0,root.rfind("/")+1);
00016   } else if (root.rfind("\\")!=string::npos) {
00017     root = root.substr(0,root.rfind("\\")+1);
00018   } else {
00019     root = "";
00020   }
00021   return root;
00022 }
00023 
00024 bool CsvTextBook::readCsvsData(const char *data, int len) {
00025   if (!compact) return false;
00026   clear();
00027   Property p;
00028   if (CsvFile::read(data,len,*this,p)!=0) {
00029     fprintf(stderr,"Failed to read CSVS data\n");
00030     return false;
00031   }
00032   for (int i=0; i<(int)sheets.size(); i++) {
00033     sheets[i].setRowOffset();
00034   }
00035   return true;
00036 }
00037 
00038 
00039 std::string CsvTextBook::writeCsvsData() {
00040   string result;
00041   write(NULL,this,true,&result);
00042   return result;
00043 }
00044 
00045 bool CsvTextBook::readCsvs(const char *fname) {
00046   if (compact) {
00047     clear();
00048     Property p;
00049     if (CsvFile::read(fname,*this,p)!=0) {
00050       fprintf(stderr,"Failed to read %s\n", fname);
00051       return false;
00052     }
00053     for (int i=0; i<(int)sheets.size(); i++) {
00054       sheets[i].setRowOffset();
00055     }
00056     dbg_printf("Read CSVS file %s\n", fname);
00057     return true;
00058   }
00059 
00060   CsvSheet index;
00061   if (CsvFile::read(fname,index)!=0) {
00062     fprintf(stderr,"Failed to read %s\n", fname);
00063     return false;
00064   }
00065   string root = getRoot(fname);
00066   for (int y=0; y<index.height(); y++) {
00067     string cmd = index.cell(0,y);
00068     if (cmd=="table") {
00069       string key = index.cell(1,y);
00070       //printf("key %s\n", key.c_str());
00071       string f = root + key + ".csv";
00072       dbg_printf("Adding %s [%s]\n", key.c_str(), f.c_str());
00073       name2index[key] = (int)sheets.size();
00074       CsvSheet *data = new CsvSheet;
00075       if (data==NULL) {
00076         fprintf(stderr,"Failed to allocated data sheet\n");
00077         return false;
00078       }
00079       if (CsvFile::read(f.c_str(),*data)!=0) {
00080         fprintf(stderr,"Failed to read %s referenced from %s\n", f.c_str(),
00081                 fname);
00082         delete data;
00083         return false;
00084       }
00085       PolySheet sheet(data,true);
00086       sheets.push_back(sheet);
00087       names.push_back(key);
00088     }
00089   }
00090   return true;
00091 }
00092 
00093 bool CsvTextBook::write(const char *fname, TextBook *book, bool compact,
00094                         std::string *output) {
00095   if (fname==NULL && output==NULL) return false;
00096   vector<string> names = book->getNames();
00097   if (compact) {
00098     Property p;
00099     if (fname) {
00100       p.put("file",fname);
00101     }
00102     int len = (int)names.size();
00103     for (int i=0; i<len; i++) {
00104       if (book->namedSheets() || len>1) {
00105         FILE *fp = NULL;
00106         if (fname) {
00107           if (string(fname)=="-") {
00108             fp = stdout;
00109           } else {
00110             fp = fopen(fname,(i>0)?"ab":"wb");
00111             if (!fp) {
00112               fprintf(stderr,"CsvTextBook: could not open %s\n", fname);
00113               return false;
00114             }
00115           }
00116         }
00117         if (i>0) {
00118           // use Windows encoding, since UNIX is more forgiving
00119           string eol = " \r\n";
00120           if (fp) {
00121             fprintf(fp,"%s",eol.c_str());
00122           } else {
00123             *output += eol;
00124           }
00125         }
00126         // use Windows encoding, since UNIX is more forgiving
00127         if (fp) {
00128           fprintf(fp,"== %s ==\r\n", names[i].c_str());
00129         } else {
00130           *output += "== ";
00131           *output += names[i];
00132           *output += " ==\r\n";
00133         }
00134         if (fp) {
00135           if (fp!=stdout) {
00136             fclose(fp);
00137             fp = NULL;
00138           }
00139         }
00140         p.put("append",true);
00141         p.put("mark_header",true);
00142       }
00143       PolySheet sheet = book->readSheetByIndex(i);
00144       dbg_printf("  writing CSVS sheet %s\n", names[i].c_str());
00145       if (!output) {
00146         CsvFile::write(sheet,p);
00147       } else {
00148         *output += CsvFile::writeString(sheet,p);
00149       }
00150     }
00151     return true;
00152   }
00153 
00154   string root = getRoot(fname);
00155   CsvSheet idx;
00156   bool ok = true;
00157   for (int i=0; i<(int)names.size(); i++) {
00158     idx.addField("table",false);
00159     idx.addField(names[i].c_str(),false);
00160     idx.addField("",false);
00161     idx.addRecord();
00162     string f = root + names[i] + ".csv";
00163     //printf("%s\n", f.c_str());
00164     CsvFile::write(book->readSheetByIndex(i),f.c_str());
00165   }
00166   ok = ok && (CsvFile::write(idx,fname)==0);
00167   return ok;
00168 }
00169 
00170 //bool CsvTextBook::open(const Property& config) {
00171 //  if (!config.check("file")) return false;
00172 //  return readCsvs(config.get("file").asString().c_str());
00173 //}
00174 
00175 bool CsvTextBook::addSheet(const SheetSchema& schema) {
00176   dbg_printf("csvtextbook::addsheet %s\n", schema.getSheetName().c_str());
00177   string name = schema.getSheetName();
00178   if (!schema.hasSheetName()) {
00179     named = false;
00180   }
00181   if (find(names.begin(),names.end(),name)!=names.end()) {
00182     return false;
00183   }
00184   CsvSheet *data = new CsvSheet;
00185   if (data==NULL) {
00186     fprintf(stderr,"Failed to allocated data sheet\n");
00187     return false;
00188   }
00189   if (schema.hasSheetName()) {
00190     data->setSheetName(name.c_str());
00191   }
00192   PolySheet sheet(data,true);
00193   name2index[name] = (int)sheets.size();
00194   sheets.push_back(sheet);
00195   names.push_back(name);
00196   data->setWidth(schema.getColumnCount());
00197 
00198   SimpleSheetSchema *rec = new SimpleSheetSchema;
00199   COOPY_ASSERT(rec);
00200   rec->copy(schema);
00201   sheets.back().setSchema(rec,true);
00202 
00203   //COOPY_ASSERT(rec);
00204   //rec->copy(schema);
00205   //data->setSchema(Poly<SheetSchema>(rec,true));
00206 
00207   /*
00208   CsvSheetSchema *rec = new CsvSheetSchema(data,name,0);
00209   COOPY_ASSERT(rec);
00210   data->setSchema(Poly<SheetSchema>(rec,true));
00211   */
00212   return true;
00213 }
00214 
00215 
00216 CsvSheet *CsvTextBook::nextSheet(const char *name, bool named) {
00217   CsvSheet *data = new CsvSheet;
00218   if (data==NULL) {
00219     fprintf(stderr,"Failed to allocated data sheet\n");
00220     return NULL;
00221   }
00222   PolySheet sheet(data,true);
00223   name2index[name] = (int)sheets.size();
00224   sheets.push_back(sheet);
00225   names.push_back(name);
00226   this->named = named;
00227   dbg_printf("Adding CSV sheet %s (named? %d)\n", name, named);
00228   return data;
00229 }
00230 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines