00001 #ifndef Impala_Util_IOBufferFile_h
00002 #define Impala_Util_IOBufferFile_h
00003
00004 #include "Basis/NativeTypeFormats.h"
00005 #include "Basis/String.h"
00006 #include "Util/IOBuffer.h"
00007
00008 namespace Impala
00009 {
00010 namespace Util
00011 {
00012
00013
00014 class IOBufferFile : public IOBuffer
00015 {
00016 public:
00017
00018 static bool
00019 FileExists(CString path)
00020 {
00021 FILE* fp = Open(path, "r");
00022 if (fp)
00023 {
00024 fclose(fp);
00025 return true;
00026 }
00027 return false;
00028 }
00029
00030 IOBufferFile(CString filename, bool readMode, bool useMemory)
00031 {
00032 mReadMode = readMode;
00033 mUseMemory = useMemory;
00034
00035 mFile = Open(filename, (mReadMode ? "rb" : "w+b"));
00036 if (!mFile)
00037 {
00038 ILOG_ERROR("Failed to open " << filename);
00039 return;
00040 }
00041
00042 if (mReadMode)
00043 {
00044 FSeek(mFile, 0, SEEK_END);
00045 PositionType size = FTell(mFile);
00046 FSeek(mFile, 0, SEEK_SET);
00047 if (mUseMemory)
00048 {
00049 unsigned char* buf = new unsigned char[size];
00050 fread(buf, 1, size, mFile);
00051 SetBuffer(buf, size);
00052 fclose(mFile);
00053 mFile = 0;
00054 }
00055 else
00056 {
00057 SetSize(size);
00058 }
00059 }
00060 }
00061
00062 virtual
00063 ~IOBufferFile()
00064 {
00065 CheckDataChannelWrite();
00066 if (mFile)
00067 {
00068 if (mUseMemory && !mReadMode)
00069 fwrite(GetBuffer(), 1, GetPosition(), mFile);
00070 fclose(mFile);
00071 }
00072 }
00073
00074 virtual bool
00075 Valid()
00076 {
00077 if (mReadMode && mUseMemory)
00078 return (GetBuffer() != 0);
00079 return (mFile != 0);
00080 }
00081
00082 virtual void
00083 SetPosition(PositionType position)
00084 {
00085 if (GetPosition() == position)
00086 return;
00087 if (!mUseMemory)
00088 FSeek(mFile, position, SEEK_SET);
00089 IOBuffer::SetPosition(position);
00090 }
00091
00092 virtual Int64
00093 Read(void* buf, Int64 bytesToRead)
00094 {
00095 Int64 available = Available();
00096 if (available < bytesToRead)
00097 bytesToRead = available;
00098 if (mUseMemory)
00099 {
00100 memcpy(buf, GetBuffer() + GetPosition(), bytesToRead);
00101 }
00102 else
00103 {
00104 FSeek(mFile, GetPosition(), SEEK_SET);
00105 Int64 nRead = fread(buf, 1, bytesToRead, mFile);
00106 }
00107 SetPosition(GetPosition() + bytesToRead);
00108 return bytesToRead;
00109 }
00110
00111 virtual String
00112 ReadLine()
00113 {
00114 if (mUseMemory)
00115 return IOBuffer::ReadLine();
00116
00117
00118 Int64 available = Available();
00119 Int64 maxLineSize = 1048576;
00120 if (available < maxLineSize)
00121 maxLineSize = available + 1;
00122
00123
00124 static char buf[1024 * 1024];
00125 FSeek(mFile, GetPosition(), SEEK_SET);
00126 fgets(buf, maxLineSize, mFile);
00127 SetPosition(FTell(mFile));
00128 for (int i=0 ; i<maxLineSize ; i++)
00129 {
00130 if ((buf[i] == '\r') || (buf[i] == '\n'))
00131 {
00132 buf[i] = '\0';
00133 break;
00134 }
00135 }
00136 String res(buf);
00137
00138 return res;
00139 }
00140
00141 virtual Int64
00142 Gets(char* buf, Int64 bytesToRead)
00143 {
00144 if (mUseMemory)
00145 return IOBuffer::Gets(buf, bytesToRead);
00146
00147 Int64 available = Available();
00148 if (available < bytesToRead)
00149 bytesToRead = available;
00150 FSeek(mFile, GetPosition(), SEEK_SET);
00151 fgets(buf, bytesToRead, mFile);
00152 SetPosition(FTell(mFile));
00153 return bytesToRead;
00154 }
00155
00156 virtual void
00157 NativeTypeRead(Int8* ptr)
00158 {
00159 DoNativeTypeRead(ptr);
00160 }
00161
00162 virtual void
00163 NativeTypeRead(UInt8* ptr)
00164 {
00165 DoNativeTypeRead(ptr);
00166 }
00167
00168 virtual void
00169 NativeTypeRead(Int16* ptr)
00170 {
00171 DoNativeTypeRead(ptr);
00172 }
00173
00174 virtual void
00175 NativeTypeRead(UInt16* ptr)
00176 {
00177 DoNativeTypeRead(ptr);
00178 }
00179
00180 virtual void
00181 NativeTypeRead(Int32* ptr)
00182 {
00183 DoNativeTypeRead(ptr);
00184 }
00185
00186 virtual void
00187 NativeTypeRead(UInt32* ptr)
00188 {
00189 DoNativeTypeRead(ptr);
00190 }
00191
00192 virtual void
00193 NativeTypeRead(Int64* ptr)
00194 {
00195 DoNativeTypeRead(ptr);
00196 }
00197
00198 virtual void
00199 NativeTypeRead(UInt64* ptr)
00200 {
00201 DoNativeTypeRead(ptr);
00202 }
00203
00204 virtual void
00205 NativeTypeRead(Real32* ptr)
00206 {
00207 DoNativeTypeRead(ptr);
00208 }
00209
00210 virtual void
00211 NativeTypeRead(Real64* ptr)
00212 {
00213 DoNativeTypeRead(ptr);
00214 }
00215
00216 virtual void
00217 Write(const void* buf, Int64 bytesToWrite)
00218 {
00219 if (mUseMemory)
00220 return IOBuffer::Write(buf, bytesToWrite);
00221
00222 fwrite(buf, 1, bytesToWrite, mFile);
00223 SetPositionAndSize(FTell(mFile));
00224 }
00225
00226 virtual Int64
00227 Puts(const char* buf)
00228 {
00229 if (mUseMemory)
00230 return IOBuffer::Puts(buf);
00231
00232 fprintf(mFile, "%s\n", buf);
00233 SetPositionAndSize(FTell(mFile));
00234 return 1;
00235 }
00236
00237 virtual void
00238 NativeTypeWrite(Int8 val)
00239 {
00240 DoNativeTypeWrite(val);
00241 }
00242
00243 virtual void
00244 NativeTypeWrite(UInt8 val)
00245 {
00246 DoNativeTypeWrite(val);
00247 }
00248
00249 virtual void
00250 NativeTypeWrite(Int16 val)
00251 {
00252 DoNativeTypeWrite(val);
00253 }
00254
00255 virtual void
00256 NativeTypeWrite(UInt16 val)
00257 {
00258 DoNativeTypeWrite(val);
00259 }
00260
00261 virtual void
00262 NativeTypeWrite(Int32 val)
00263 {
00264 DoNativeTypeWrite(val);
00265 }
00266
00267 virtual void
00268 NativeTypeWrite(UInt32 val)
00269 {
00270 DoNativeTypeWrite(val);
00271 }
00272
00273 virtual void
00274 NativeTypeWrite(Int64 val)
00275 {
00276 DoNativeTypeWrite(val);
00277 }
00278
00279 virtual void
00280 NativeTypeWrite(UInt64 val)
00281 {
00282 DoNativeTypeWrite(val);
00283 }
00284
00285 virtual void
00286 NativeTypeWrite(Real32 val)
00287 {
00288 DoNativeTypeWrite(val);
00289 }
00290
00291 virtual void
00292 NativeTypeWrite(Real64 val)
00293 {
00294 DoNativeTypeWrite(val);
00295 }
00296
00297 private:
00298
00299 static FILE*
00300 Open(CString path, CString mode)
00301 {
00302 #ifdef WIN32
00303 if (path.size() >= _MAX_PATH)
00304 {
00305 static const String longPathPrefix = "\\\\?\\";
00306 const String longPathSpec = longPathPrefix + StringReplaceAll(path, "/", "\\");
00307 wchar_t longPathSpecWC[32768+1];
00308 for (int i = 0; i < longPathSpec.size(); i++)
00309 longPathSpecWC[i] = (wchar_t) longPathSpec.at(i);
00310 longPathSpecWC[longPathSpec.size()] = L'\0';
00311 wchar_t modeWC[10];
00312 for (int i = 0; i < mode.size(); i++)
00313 modeWC[i] = (wchar_t) mode.at(i);
00314 modeWC[mode.size()] = L'\0';
00315 FILE* fp = _wfopen(longPathSpecWC, modeWC);
00316 return fp;
00317 }
00318 #endif
00319 return fopen(path.c_str(), mode.c_str());
00320 }
00321
00322 template <class NativeType>
00323 void
00324 DoNativeTypeRead(NativeType* ptr)
00325 {
00326 if (mUseMemory)
00327 return IOBuffer::DoNativeTypeRead(ptr);
00328
00329 String fs = NativeTypeFormat<NativeType>(0);
00330 FSeek(mFile, GetPosition(), SEEK_SET);
00331 fscanf(mFile, fs.c_str(), ptr);
00332 SetPosition(FTell(mFile));
00333 }
00334
00335 template <class NativeType>
00336 void
00337 DoNativeTypeWrite(NativeType val)
00338 {
00339 String fs = NativeTypeFormat<NativeType>(0) + " ";
00340 if (mUseMemory)
00341 {
00342 char* start = (char*) (GetBuffer() + GetPosition());
00343 sprintf(start, fs.c_str(), val);
00344 Int64 i = 0;
00345 while (start[i] != ' ')
00346 i++;
00347 SetPosition(GetPosition() + i + 1);
00348 }
00349 else
00350 {
00351 fprintf(mFile, fs.c_str(), val);
00352 SetPositionAndSize(FTell(mFile));
00353 }
00354 }
00355
00356 PositionType
00357 FTell(FILE* fp)
00358 {
00359 #ifdef WIN32
00360 #if _MSC_VER <= 1310
00361 return ftell(fp);
00362 #else
00363 return _ftelli64(fp);
00364 #endif
00365 #else
00366 return ftello(fp);
00367 #endif
00368 }
00369
00370 int
00371 FSeek(FILE* fp, PositionType offset, int origin)
00372 {
00373 #ifdef WIN32
00374 #if _MSC_VER <= 1310
00375 return fseek(fp, offset, origin);
00376 #else
00377 return _fseeki64(fp, offset, origin);
00378 #endif
00379 #else
00380 return fseeko(fp, offset, origin);
00381 #endif
00382 }
00383
00384 bool mReadMode;
00385 bool mUseMemory;
00386 FILE* mFile;
00387
00388 ILOG_VAR_DEC;
00389 };
00390
00391 ILOG_VAR_INIT(IOBufferFile, Impala.Util);
00392
00393 }
00394 }
00395
00396 #endif