COOPY » Guide
version 0.6.5
|
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