PLearn 0.1
|
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 :