00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef FILERESOURCE_H
00011 #define FILERESOURCE_H
00012
00013 #include "AppConfig.h"
00014 #include "Resource.h"
00015 #include <string>
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <errno.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <vector>
00023
00024 #if defined(WIN_API)
00025 #include <io.h>
00026 #include <fcntl.h>
00027 #include <limits>
00028 #define WIN32_LEAN_AND_MEAN
00029 #include <windows.h>
00030 #else
00031 #include <fcntl.h>
00032 #include <sys/fcntl.h>
00033 #include <sys/statvfs.h>
00034 #include <unistd.h>
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043
00044 class FileObject
00045 {
00046 public:
00047
00048
00049
00050
00051
00052 class Args
00053 {
00054 public:
00055 Args(std::string filename, std::string access = "r", bool deleteOnClose = false) :
00056 mFilename(filename),
00057 mAccess(access),
00058 mDeleteOnClose(deleteOnClose)
00059 {}
00060
00061 std::string mFilename;
00062 std::string mAccess;
00063 bool mDeleteOnClose;
00064 };
00065
00066 FILE* obtainResource(const Args& args) const
00067 {
00068 FILE* pFile = fopen(args.mFilename.c_str(), args.mAccess.c_str());
00069 if (args.mAccess.find("r") >= 0 && pFile == NULL)
00070 {
00071 std::string fname = args.mFilename.c_str();
00072 for (size_t i = 0; i < fname.size(); ++i)
00073 {
00074 fname[i] = (char) toupper(fname[i]);
00075 }
00076 pFile = fopen(fname.c_str(), args.mAccess.c_str());
00077 if (pFile == NULL)
00078 {
00079 for (size_t i = 0; i < fname.size(); ++i)
00080 {
00081 fname[i] = (char) tolower(fname[i]);
00082 }
00083 pFile = fopen(fname.c_str(), args.mAccess.c_str());
00084 }
00085 }
00086 return pFile;
00087 }
00088 void releaseResource(const Args& args, FILE* pStream) const
00089 {
00090 if (pStream != NULL)
00091 {
00092 fclose(pStream);
00093 }
00094
00095 if ((args.mDeleteOnClose) && (args.mFilename.empty() == false))
00096 {
00097 remove(args.mFilename.c_str());
00098 }
00099 }
00100 };
00101
00102
00103
00104
00105
00106
00107
00108
00109 class FileResource : public Resource<FILE, FileObject>
00110 {
00111 public:
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 FileResource(const char* pFilename, const char* pAccess, bool deleteOnClose = false) :
00127 Resource<FILE, FileObject>(FileObject::Args(pFilename, pAccess, deleteOnClose))
00128 {}
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 operator FILE*()
00139 {
00140 return get();
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 bool getDeleteOnClose() const
00150 {
00151 const FileObject::Args& args = getArgs();
00152 return args.mDeleteOnClose;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void setDeleteOnClose(bool deleteOnClose)
00164 {
00165 FileObject::Args& args = getArgs();
00166 args.mDeleteOnClose = deleteOnClose;
00167 }
00168 };
00169
00170 class LargeFileResource
00171 {
00172 public:
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 LargeFileResource(bool bResource = true)
00184 {
00185 mbOwned = bResource;
00186 mHandle = -1;
00187 }
00188
00189
00190
00191
00192
00193 ~LargeFileResource()
00194 {
00195 if (mbOwned)
00196 {
00197 LargeFileResource::close();
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 LargeFileResource(LargeFileResource& source)
00210 {
00211 mHandle = source.mHandle;
00212 mbOwned = source.mbOwned;
00213
00214 source.release();
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 LargeFileResource& operator=(LargeFileResource& source)
00226 {
00227 if (mbOwned)
00228 {
00229 LargeFileResource::close();
00230 }
00231 mHandle = source.mHandle;
00232 mbOwned = source.mbOwned;
00233
00234 source.release();
00235 return *this;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 bool open(std::string filename, int openType, int permissionFlag)
00258 {
00259 if (mbOwned)
00260 {
00261
00262 LargeFileResource::close();
00263 }
00264
00265 #if defined(WIN_API)
00266
00267 if (openType & O_TEXT)
00268 {
00269 return false;
00270 }
00271
00272
00273 openType |= O_BINARY;
00274
00275 mHandle = _open(filename.c_str(), openType, permissionFlag );
00276 #else
00277 mHandle = open64(filename.c_str(), openType, permissionFlag | O_LARGEFILE );
00278 #endif
00279
00280 return validHandle();
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 bool reserve(std::string filename, int64_t reserveSize)
00300 {
00301 if (!open(filename, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE | S_IEXEC))
00302 {
00303 return false;
00304 }
00305
00306 #if defined(UNIX_API)
00307 struct statvfs sbuf;
00308 if (statvfs(filename.c_str(), &sbuf) ==0)
00309 {
00310
00311 if ((reserveSize + sbuf.f_bsize - 1) / sbuf.f_bsize < sbuf.f_bfree)
00312 {
00313
00314 if (seek(reserveSize - 1, SEEK_SET) != (reserveSize - 1) ||
00315 write(filename.c_str(), 1) != 1)
00316 {
00317 return false;
00318 }
00319 }
00320 }
00321 #elif defined(WIN_API)
00322 if (seek(reserveSize, SEEK_SET) != (reserveSize))
00323 {
00324 return false;
00325 }
00326 HANDLE winHandle = reinterpret_cast<HANDLE>(_get_osfhandle(mHandle));
00327 if (!::SetEndOfFile(winHandle))
00328 {
00329 return false;
00330 }
00331 #endif
00332 return true;
00333 }
00334
00335
00336
00337
00338
00339
00340 int close()
00341 {
00342 int retVal = -1;
00343 if (validHandle())
00344 {
00345 #if defined(WIN_API)
00346 retVal = _close(mHandle);
00347 #else
00348 retVal = ::close(mHandle);
00349 #endif
00350 mHandle = -1;
00351 }
00352
00353 return retVal;
00354 }
00355
00356
00357
00358
00359
00360 void release()
00361 {
00362 mbOwned = false;
00363 }
00364
00365
00366
00367
00368
00369 void lock()
00370 {
00371 mbOwned = true;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 int creat(std::string filename, int perm)
00387 {
00388 if (mbOwned)
00389 {
00390
00391 LargeFileResource::close();
00392 }
00393 #if defined(WIN_API)
00394 mHandle = _creat(filename.c_str(), perm);
00395 #else
00396 mHandle = ::creat(filename.c_str(), perm);
00397 #endif
00398
00399 return mHandle;
00400 }
00401
00402
00403
00404
00405
00406
00407 int eof()
00408 {
00409 if (!validHandle())
00410 {
00411 return -1;
00412 }
00413 #if defined(WIN_API)
00414 return _eof(mHandle);
00415 #else
00416 return (tell() >= fileLength() ? 1 : 0);
00417 #endif
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 int64_t fileLength()
00427 {
00428 if (!validHandle())
00429 {
00430 return -1;
00431 }
00432 #if defined(WIN_API)
00433 return _filelengthi64(mHandle);
00434 #else
00435 int64_t curPos = tell();
00436 seek(0, SEEK_END);
00437 int64_t fileSize = tell();
00438 seek(curPos, SEEK_SET);
00439 return fileSize;
00440 #endif
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 int64_t seek(int64_t offset, int direction)
00459 {
00460 if (!validHandle())
00461 {
00462 return -1;
00463 }
00464 #if defined(WIN_API)
00465 return _lseeki64(mHandle, offset, direction);
00466 #else
00467 return lseek64(mHandle, offset, direction);
00468 #endif
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 int64_t read(void* pMem, int64_t bytesToRead)
00488 {
00489 if ((pMem == NULL) || (bytesToRead == 0) || !validHandle())
00490 {
00491 return -1;
00492 }
00493 #if defined(WIN_API)
00494 int64_t bytesRead = 0;
00495 while (bytesToRead >= std::numeric_limits<unsigned int>::max())
00496 {
00497 int64_t r = _read(mHandle, pMem, std::numeric_limits<unsigned int>::max()) ;
00498 bytesRead += r;
00499 if (r < std::numeric_limits<unsigned int>::max())
00500 {
00501 return bytesRead;
00502 }
00503 pMem = reinterpret_cast<char*>(pMem) + std::numeric_limits<unsigned int>::max();
00504 bytesToRead -= std::numeric_limits<unsigned int>::max();
00505 }
00506 bytesRead += _read(mHandle, pMem, static_cast<unsigned int>(bytesToRead));
00507 return bytesRead;
00508 #else
00509 return ::read(mHandle, pMem, bytesToRead);
00510 #endif
00511 }
00512
00513
00514
00515
00516
00517
00518 int64_t tell()
00519 {
00520 if (!validHandle())
00521 {
00522 return -1;
00523 }
00524 #if defined(WIN_API)
00525 return _telli64(mHandle);
00526 #else
00527 return lseek64(mHandle, 0, SEEK_CUR);
00528 #endif
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 int64_t write(const void* pMem, int64_t bytesToWrite)
00544 {
00545 if ((pMem == NULL) || (bytesToWrite == 0) || !validHandle())
00546 {
00547 return -1;
00548 }
00549 #if defined(WIN_API)
00550 int64_t bytesWritten = 0;
00551 while (bytesToWrite >= std::numeric_limits<unsigned int>::max())
00552 {
00553 int64_t wrote = _write(mHandle, pMem, std::numeric_limits<unsigned int>::max()) ;
00554 bytesWritten += wrote;
00555 if (wrote < std::numeric_limits<unsigned int>::max())
00556 {
00557 return bytesWritten;
00558 }
00559 pMem = reinterpret_cast<const char*>(pMem) + std::numeric_limits<unsigned int>::max();
00560 bytesToWrite -= std::numeric_limits<unsigned int>::max();
00561 }
00562 bytesWritten += _write(mHandle, pMem, static_cast<unsigned int>(bytesToWrite));
00563 return bytesWritten;
00564 #else
00565 return ::write(mHandle, pMem, bytesToWrite);
00566 #endif
00567 }
00568
00569
00570
00571
00572
00573
00574 bool validHandle()
00575 {
00576 return (mHandle >= 0);
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 std::string readLine(bool* pError = NULL)
00592 {
00593 std::string line;
00594 int64_t pos = tell();
00595 std::vector<char> buffer(4096, 0);
00596 int64_t bytesRead = read(&buffer.front(), buffer.size());
00597 if (bytesRead <= 0)
00598 {
00599 if (pError != NULL)
00600 {
00601 *pError = true;
00602 }
00603 return line;
00604 }
00605 std::string tmp(&buffer.front(), static_cast<std::string::size_type>(bytesRead));
00606 std::string::size_type eolLoc = tmp.find('\n');
00607 if (eolLoc == std::string::npos)
00608 {
00609 if (pError != NULL)
00610 {
00611 *pError = false;
00612 }
00613 return tmp;
00614 }
00615 seek(pos + eolLoc + 1, SEEK_SET);
00616 if (eolLoc != 0 && tmp[eolLoc-1] == '\r')
00617 {
00618 --eolLoc;
00619 }
00620 line = tmp.substr(0, eolLoc);
00621 if (pError != NULL)
00622 {
00623 *pError = false;
00624 }
00625 return line;
00626 }
00627
00628 private:
00629 int mHandle;
00630 bool mbOwned;
00631 };
00632
00633 #endif