PLearn 0.1
IntVecFile.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 1998 Pascal Vincent
00005 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of Montreal
00006 //
00007 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 
00037  
00038 
00039 /* *******************************************************      
00040  * $Id: IntVecFile.cc 8837 2008-04-19 01:25:41Z lamblin $
00041  * AUTHORS: Pascal Vincent
00042  * This file is part of the PLearn library.
00043  ******************************************************* */
00044 
00045 #include "IntVecFile.h"
00046 //#include "fileutils.h"
00047 #include <plearn/base/byte_order.h>
00048 
00049 namespace PLearn {
00050 using namespace std;
00051 
00052 const char IntVecFile::signature[] = {
00053     '\xDE', '\xAD', '\xBE', '\xEF', '\x00'     
00054 };
00055 
00056 const int IntVecFile::header_size[] = {      
00057     0,                                         
00058     2                                          
00059 };
00060 
00061 
00062 IntVecFile::IntVecFile(const IntVecFile& other)
00063     : filename(other.filename), f(0), length_(other.length_),
00064       version_number_(other.version_number_), endianness_(other.endianness_)
00065 {
00066     open(filename, false /* readonly */);
00067 }
00068 
00069 void IntVecFile::open(const string& the_filename, bool readwrite)
00070 {
00071     if(f)
00072         close();
00073 
00074     filename = the_filename;
00075     bool file_exists = isfile(filename);
00076     if(readwrite)
00077     {
00078         f = fopen(filename.c_str(),"a+b");
00079         if(!f)
00080             PLERROR("Couldn't open file %s for read/write",filename.c_str());
00081     }
00082     else
00083     {
00084         f = fopen(filename.c_str(),"rb");
00085         if(!f)
00086             PLERROR("Couldn't open file %s for reading",filename.c_str());
00087     }
00088     if (file_exists)
00089         getVersionAndSize();
00090     else
00091         writeFileSignature();
00092 }
00093 
00094 int IntVecFile::get(int i) const
00095 {
00096 #ifdef BOUNDCHECK
00097     if(i<0 || i>=length())
00098         PLERROR("Out Of Bounds in IntVecFile::get");
00099 #endif
00100     seek_to_index(i);
00101     return fread_int(f, endianness_ == BIG_ENDIAN_ORDER);
00102 }
00103 
00104 void IntVecFile::put(int i, int value)
00105 {
00106     seek_to_index(i);
00107     fwrite_int(f, value, endianness_ == BIG_ENDIAN_ORDER);
00108     if(i>=length_)
00109         length_ = i+1;
00110 }
00111 
00112 void IntVecFile::close()
00113 {
00114     if(f)
00115         fclose(f);
00116     f=0;
00117 }
00118 
00119 IntVecFile::~IntVecFile()
00120 {
00121     close();
00122 }
00123 
00124 #ifdef __INTEL_COMPILER
00125 #pragma warning(disable:593)  // Get rid of compiler warning.
00126 #endif
00127 TVec<int> IntVecFile::getVec() const
00128 {
00129     size_t tt;
00130     TVec<int> res(length());
00131     seek_to_index(0);
00132     if((tt=fread(res.data(), sizeof(int), length(), f)) != size_t(length()))
00133         PLERROR("fread error in IntVecFile::getVec()");
00134     // Switch byte order if necessary
00135     if (byte_order() != endianness_)
00136         endianswap(res.data(), length());
00137 
00138     return res;
00139 }
00140 #ifdef __INTEL_COMPILER
00141 #pragma warning(default:593)
00142 #endif
00143 
00144 void IntVecFile::append(const TVec<int>& vec)
00145 {
00146     seek_to_index(length());
00147 
00148     if (byte_order() != endianness_) {
00149         TVec<int> new_vec(vec.length());
00150         new_vec << vec;
00151         endianswap(new_vec.data(), new_vec.length());
00152         fwrite(new_vec.data(), sizeof(int), new_vec.length(), f);
00153     }
00154     else {
00155         fwrite(vec.data(), sizeof(int), vec.length(), f);
00156     }
00157 
00158     length_ += vec.length();
00159 }
00160 
00161 void IntVecFile::writeFileSignature()
00162 {
00163     // This is for a new file.  Assume length 0, version number 1,
00164     // file endianness is current-platform endianness
00165     length_ = 0;
00166     version_number_ = 1;
00167     endianness_ = byte_order();
00168 
00169     fseek(f, 0, SEEK_SET);
00170     fputs(signature, f);                       
00171     fputc(endianness_, f);
00172     fputc(0x00, f);
00173     fputc(0x00, f);
00174     fputc(char(version_number_), f);
00175 }
00176 
00177 void IntVecFile::getVersionAndSize()
00178 {
00179     if (sizeof(int) != 4)
00180         PLERROR("IntVecFile::getVersionAndSize: "
00181                 "IntVecFile not yet designed to handle sizeof(int) != 4");
00182   
00183     long the_filesize = filesize(filename);
00184     if (the_filesize < long(2*sizeof(int)) /* assume 4 */)
00185         goto version0;                           // unbelievable but true!
00186 
00187     fseek(f, 0, SEEK_SET);
00188     for (int i=0; i<4; ++i)
00189         if (char(fgetc(f)) != signature[i])
00190             goto version0;                         
00191 
00192     // Assume new-world file format
00193     endianness_ = char(fgetc(f));
00194     if (endianness_ != LITTLE_ENDIAN_ORDER &&
00195         endianness_ != BIG_ENDIAN_ORDER)
00196         PLERROR("IntVecFile::getVersionAndSize: "
00197                 "File format error in file %s Only supported endianness is 'L' or 'B'\n"
00198                 "Read %c", filename.c_str(),endianness_);
00199 
00200     if(fgetc(f) != 0x00 || fgetc(f) != 0x00)
00201         PLERROR("IntVecFile::getVersionAndSize: "
00202                 "File format error in file %s", filename.c_str());
00203 
00204     version_number_ = (unsigned char)fgetc(f);
00205 
00206     if (version_number_ > 1)
00207         PLERROR("IntVecFile::getVersionAndSize: "
00208                 "File version (%d) is not supported", version_number_);
00209 
00210     length_ = int(the_filesize / sizeof(int) - header_size[version_number_]);
00211     return;
00212 
00213  version0:
00214     length_ = int(the_filesize / sizeof(int));
00215     version_number_ = 0;
00216     endianness_ = 'L';
00217 }
00218 
00219 void IntVecFile::seek_to_index(int i) const
00220 {
00221     fseek(f, (i+header_size[version_number_]) * sizeof(int), SEEK_SET);
00222 }
00223 
00224 } // end of namespace PLearn
00225 
00226 
00227 /*
00228   Local Variables:
00229   mode:c++
00230   c-basic-offset:4
00231   c-file-style:"stroustrup"
00232   c-file-offsets:((innamespace . 0)(inline-open . 0))
00233   indent-tabs-mode:nil
00234   fill-column:79
00235   End:
00236 */
00237 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines