PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // AsciiVMatrix.cc 00004 // 00005 // Copyright (C) 2003 Rejean Ducharme, Pascal Vincent 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 /* ******************************************************* 00036 * $Id: AsciiVMatrix.cc 8617 2008-03-03 17:45:54Z nouiz $ 00037 ******************************************************* */ 00038 00041 #include "AsciiVMatrix.h" 00042 #include <plearn/base/stringutils.h> 00043 #include <plearn/io/fileutils.h> 00044 #include <plearn/io/openFile.h> 00045 00046 namespace PLearn { 00047 using namespace std; 00048 00049 00050 PLEARN_IMPLEMENT_OBJECT(AsciiVMatrix, 00051 "AsciiVMatrix implements a file in ASCII format", 00052 "" 00053 ); 00054 00055 AsciiVMatrix::AsciiVMatrix() 00056 :readwritemode(false), newfile(true), 00057 rewrite_length(true) 00058 {} 00059 00060 AsciiVMatrix::AsciiVMatrix(const string& fname, bool readwrite) 00061 :filename(fname), readwritemode(readwrite), newfile(false), 00062 rewrite_length(true) 00063 { 00064 build(); 00065 } 00066 00067 AsciiVMatrix::AsciiVMatrix(const string& fname, int the_width, 00068 const TVec<string>& the_fieldnames, 00069 const string& comment) 00070 :inherited(0,the_width), filename(fname), 00071 readwritemode(true), newfile(true), rewrite_length(true) 00072 { 00073 inherited::build(); 00074 00075 if (isfile(filename)) 00076 PLERROR("In AsciiVMatrix constructor: filename %s already exists",filename.c_str()); 00077 file = openFile(filename, PStream::raw_ascii, "w"); 00078 // TODO Is this really the same as old code ? 00079 // file->open(filename.c_str(), fstream::in | fstream::out | fstream::trunc); 00080 00081 file << "#size: "; 00082 PLERROR("In AsciiVMatrix::AsciiVMatrix - Code is not yet PStram compatible"); 00083 // vmatlength_pos = file.tellp(); // TODO See how to do this with PStreams. 00084 length_max = 9999999; // = 10 000 000 - 1 00085 file << "0 " << width() << " " << endl; 00086 00087 00088 if(the_fieldnames.length()>0) 00089 { 00090 if(the_fieldnames.length()!=the_width) 00091 PLERROR("In AsciiVMatrix constructor: number of given fieldnames (%d) differs from given width (%d)", 00092 the_fieldnames.length(), the_width); 00093 file << "#: "; 00094 for(int k=0; k<the_width; k++) 00095 { 00096 string field_k = space_to_underscore(the_fieldnames[k]); 00097 declareField(k, field_k); 00098 file << field_k << ' '; 00099 } 00100 file << endl; 00101 } 00102 00103 if(comment!="") 00104 { 00105 if(comment[0]!='#') 00106 PLERROR("In AsciiVMatrix constructor: comment must start with a #"); 00107 file << comment; 00108 if(comment[comment.length()-1]!='\n') 00109 file << endl; 00110 } 00111 00112 } 00113 00114 void AsciiVMatrix::build() 00115 { 00116 inherited::build(); 00117 build_(); 00118 } 00119 00120 void AsciiVMatrix::build_() 00121 { 00122 updateMtime(filename); 00123 00124 if(!newfile) // open old file 00125 { 00126 if (!isfile(filename)) 00127 PLERROR("In AsciiVMatrix constructor (with specified width), filename %s does not exists",filename.c_str()); 00128 file = openFile(filename, PStream::raw_ascii, "w"); 00129 // TODO Is this really the same as the old code ? 00130 // file->open(filename.c_str(), fstream::in | fstream::out); 00131 00132 // read the matrix in old or new format 00133 int length = -1; 00134 int width = -1; 00135 bool could_be_old_amat = true; 00136 // file->seekg(0,fstream::beg); // TODO Will it work without this ? 00137 file >> ws; 00138 string line; 00139 while (file.peek()=='#') 00140 { 00141 PLERROR("In AsciiVMatrix::build_ - Code is not PStream-compatible yet"); 00142 // streampos old_pos = file.tellg(); // TODO See how to do this with PStreams. 00143 file.getline(line); 00144 could_be_old_amat = false; 00145 size_t pos=line.find(":"); 00146 if (pos!=string::npos) 00147 { 00148 string sub=line.substr(0,pos); 00149 if (sub=="#size") // we've found the dimension specification line 00150 { 00151 string siz=removeblanks((line.substr(pos)).substr(1)); 00152 vector<string> dim = split(siz," "); 00153 if (dim.size()!=2) PLERROR("I need exactly 2 dimensions for matrix"); 00154 length = toint(dim[0]); 00155 width = toint(dim[1]); 00156 00157 // we set vmatlength_pos 00158 // streampos current_pos = file.tellg(); // TODO See how to do this with PStreams. 00159 PLERROR("In AsciiVMatrix::build_ - Code is not PStream-compatible yet"); 00160 // file->seekg(old_pos); // TODO How to do this with PStreams ? 00161 char c = file.get(); 00162 while (c != ':') 00163 { 00164 c = file.get(); 00165 } 00166 c = file.get(); 00167 // vmatlength_pos = file.tellp(); // TODO See how to do this with PStreams. 00168 //file.seekg(current_pos); // TODO How to do this with PStreams ? 00169 00170 // we set length_max 00171 int width_ndigits = (int)pl_log(real(width)) + 1; 00172 string remain = removenewline(line.substr(pos+1)); 00173 int length_ndigits = (int)remain.length() - width_ndigits - 1; 00174 length_max = (int)pow(10.0,double(length_ndigits)) - 1; 00175 } 00176 } 00177 file >> ws; 00178 } 00179 00180 if (length==-1) // still looking for size info... 00181 { 00182 getNextNonBlankLine(file,line); 00183 int nfields1 = (int)split(line).size(); 00184 getNextNonBlankLine(file,line); 00185 if (line=="") // only one line, no length nor width info 00186 { 00187 length=1; 00188 width=nfields1; 00189 rewrite_length = false; 00190 could_be_old_amat = false; 00191 } 00192 int nfields2 = (int)split(line).size(); 00193 int guesslength = countNonBlankLinesOfFile(filename); 00194 real a, b; 00195 if (could_be_old_amat && nfields1==2) // could be an old .amat with first 2 numbers being length width 00196 { 00197 PLERROR("In AsciiVMatrix::build_ - Code is not PStream-compatible yet"); 00198 // file.seekg(0,fstream::beg); // TODO How to do this with PStreams ? 00199 // file.clear(); // TODO Same question 00200 // vmatlength_pos = file.tellp(); // TODO See how to do this with PStreams. 00201 file >> a >> b; 00202 if (guesslength == int(a)+1 && 00203 fast_exact_is_equal(real(int(a)), a) && 00204 fast_exact_is_equal(real(int(b)), b) && 00205 a>0 && b>0 && int(b)==nfields2) // it's clearly an old .amat 00206 { 00207 length = int(a); 00208 width = int(b); 00209 00210 // file.seekg(vmatlength_pos); // TODO How to do this with PStreams ? 00211 file.getline(line); 00212 int width_ndigits = (int)pl_log(real(width)) + 1; 00213 int max_length_ndigits = (int)line.length() - width_ndigits - 1; 00214 length_max = (int)pow(10.0,double(max_length_ndigits)) - 1; 00215 } 00216 } 00217 00218 if (length==-1) // still don't know size info... 00219 { 00220 if (nfields1==nfields2) // looks like a plain ascii file 00221 { 00222 rewrite_length = false; 00223 length=guesslength; 00224 if (width!=-1 && width!=nfields1) 00225 { 00226 PLWARNING("In AsciiVMatrix: Number of fieldnames and width mismatch in file %s.", filename.c_str()); 00227 } 00228 width = nfields1; 00229 } 00230 else 00231 PLERROR("In AsciiVMatrix: trying to load but couldn't determine file format automatically for %s",filename.c_str()); 00232 } 00233 } 00234 00235 length_ = length; 00236 width_ = width; 00237 00238 // build the vector of position of the begining of the lines 00239 PLERROR("In AsciiVMatrix::build_ - Code is not PStream-compatible yet"); 00240 // file.seekg(0,fstream::beg); // TODO How to do this with PStreams ? 00241 // file.clear(); 00242 if (could_be_old_amat && rewrite_length) 00243 { 00244 file.getline(line); 00245 } 00246 pos_rows.clear(); 00247 while (!file.eof()) 00248 { 00249 file >> ws; 00250 // if (file.peek()!='#' && file.peek()!=EOF) pos_rows.push_back(file.tellg()); // TODO See how to do this with PStreams. 00251 file.getline(line); 00252 } 00253 // file.clear(); // TODO See how to do this with PStreams. 00254 if ((int)pos_rows.size() != length) 00255 PLERROR("In AsciiVMatrix: the matrix has not the rigth size"); 00256 } 00257 } 00258 00259 void AsciiVMatrix::getNewRow(int i, const Vec& v) const 00260 { 00261 #ifdef BOUNDCHECK 00262 if(i<0 || i>length()) 00263 PLERROR("In AsciiVMatrix::getNewRow, bad row number %d",i); 00264 if(v.length() != width()) 00265 PLERROR("In AsciiVMatrix::getNewRow, length of v (%d) does not match matrix width (%d)",v.length(),width()); 00266 #endif 00267 00268 // file.seekg(pos_rows[i]); // TODO How to do this with PStreams ? 00269 for (int j=0; j<width(); j++) 00270 file >> v[j]; 00271 } 00272 00273 void AsciiVMatrix::appendRow(Vec v) 00274 { 00275 if(v.length()!=width()) 00276 PLERROR("In AsciiVMatrix::appendRow, length of Vec to append (%d) differs from width of matrix (%d)",v.length(), width()); 00277 00278 if (length() == length_max) 00279 PLERROR("AsciiVMatrix::appendRow aborted: the matrix has reach its maximum length."); 00280 00281 if(!readwritemode) 00282 PLERROR("AsciiVMatrix::appendRow aborted: the vmat was opened in read only format."); 00283 00284 // write the Vec at the end of the file 00285 // file.seekp(0,fstream::end); // TODO How to do this with PStreams ? 00286 // pos_rows.push_back(file.tellg()); // TODO How to do this with PStreams ? 00287 00288 // file.precision(15); // TODO See what it means to remove it. 00289 for (int i=0; i<v.length(); i++) 00290 file << v[i] << ' '; 00291 file << endl; 00292 00293 // update the length 00294 length_++; 00295 if (rewrite_length) 00296 { 00297 // file->seekp(vmatlength_pos); // TODO How to do this with PStreams ? 00298 file << length() << " " << width(); 00299 } 00300 } 00301 00302 void AsciiVMatrix::put(int i, int j, real value) 00303 { PLERROR("In AsciiVMatrix::put not permitted."); } 00304 void AsciiVMatrix::putSubRow(int i, int j, Vec v) 00305 { PLERROR("In AsciiVMatrix::putSubRow not permitted."); } 00306 void AsciiVMatrix::putRow(int i, Vec v) 00307 { PLERROR("In AsciiVMatrix::putRow not permitted."); } 00308 00309 void AsciiVMatrix::declareOptions(OptionList& ol) 00310 { 00311 declareOption(ol, "filename", &AsciiVMatrix::filename, OptionBase::buildoption, "Filename of the matrix"); 00312 declareOption(ol, "readwritemode", &AsciiVMatrix::readwritemode, OptionBase::buildoption, "Is the file to be opened in read/write mode"); 00313 inherited::declareOptions(ol); 00314 } 00315 00316 AsciiVMatrix::~AsciiVMatrix() 00317 {} 00318 00319 } // end of namespace PLearn 00320 00321 00322 /* 00323 Local Variables: 00324 mode:c++ 00325 c-basic-offset:4 00326 c-file-style:"stroustrup" 00327 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00328 indent-tabs-mode:nil 00329 fill-column:79 00330 End: 00331 */ 00332 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :