00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlCore/DiskFile.hpp>
00033 #include <stdio.h>
00034
00035 #if defined(__APPLE__) || (__FreeBSD__)
00036 #define fseeko64 fseeko
00037 #endif
00038
00039 using namespace vl;
00040
00041
00042
00043
00044 DiskFile::DiskFile(const String& path)
00045 {
00046 mHandle = NULL;
00047 setPath(path);
00048 }
00049
00050 DiskFile::~DiskFile()
00051 {
00052 close();
00053 }
00054
00055 bool DiskFile::open(const String& path, EOpenMode mode)
00056 {
00057 setPath(path);
00058 return open(mode);
00059 }
00060
00061 bool DiskFile::open(EOpenMode mode)
00062 {
00063 if ( isOpen() )
00064 {
00065 Log::error("DiskFile::open(): file already open.\n");
00066 return false;
00067 }
00068
00069 #if defined(VL_PLATFORM_WINDOWS)
00070 mHandle = INVALID_HANDLE_VALUE;
00071 switch(mode)
00072 {
00073 case OM_ReadOnly:
00074 mHandle = CreateFile( (const wchar_t*)path().ptr(),
00075 GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); break;
00076 case OM_WriteOnly:
00077 mHandle = CreateFile( (const wchar_t*)path().ptr(),
00078 GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); break;
00079 default:
00080 break;
00081 }
00082 if (mHandle == INVALID_HANDLE_VALUE)
00083 #elif defined(__GNUG__)
00084
00085 std::vector<unsigned char> utf8;
00086 path().toUTF8( utf8, false );
00087 switch(mode)
00088 {
00089 case OM_ReadOnly: mHandle = fopen( (char*)&utf8[0], "rb"); break;
00090 case OM_WriteOnly: mHandle = fopen( (char*)&utf8[0], "wb"); break;
00091 default:
00092 break;
00093 }
00094 if (mHandle == NULL)
00095 #endif
00096
00097 {
00098 Log::error( Say("DiskFile::open(): error opening input file '%s'\n") << path() );
00099 return false;
00100 }
00101
00102 return true;
00103 }
00104
00105 bool DiskFile::isOpen() const
00106 {
00107 return mHandle != NULL;
00108 }
00109
00110 void DiskFile::close()
00111 {
00112 if (mHandle)
00113 {
00114 #if defined(VL_PLATFORM_WINDOWS)
00115 CloseHandle(mHandle);
00116 #elif defined(__GNUG__)
00117 fclose(mHandle);
00118 #endif
00119 }
00120 mHandle = NULL;
00121 }
00122
00123 long long DiskFile::size() const
00124 {
00125 #if defined(VL_PLATFORM_WINDOWS)
00126
00127 HANDLE hdl = CreateFile(
00128 (const wchar_t*)path().ptr(),
00129 FILE_READ_ATTRIBUTES,
00130 FILE_SHARE_READ,
00131 NULL,
00132 OPEN_EXISTING,
00133 FILE_ATTRIBUTE_NORMAL,
00134 NULL
00135 );
00136
00137 if (mHandle == INVALID_HANDLE_VALUE)
00138 {
00139 Log::error( Say("DiskFile::size(): file '%s' does not seem to exist.\n") << path() );
00140 return 0;
00141 }
00142
00143 #if defined(__MINGW32_VERSION)
00144 DWORD size = GetFileSize(hdl, NULL);
00145 CloseHandle(hdl);
00146 if (size != INVALID_FILE_SIZE )
00147 return size;
00148 else
00149 return -1;
00150 #else
00151 LARGE_INTEGER file_size;
00152 BOOL ok = GetFileSizeEx( hdl, &file_size );
00153 CloseHandle(hdl);
00154 return ok ? file_size.QuadPart : -1;
00155 #endif
00156 #elif defined(__GNUG__)
00157
00158 struct stat mybuf;
00159 memset(&mybuf, 0, sizeof(struct stat));
00160
00161 std::vector<unsigned char> utf8;
00162 path().toUTF8( utf8, false );
00163 if (utf8.empty())
00164 return 0;
00165 if (stat((char*)&utf8[0], &mybuf) == -1)
00166 return 0;
00167 else
00168 return (long long)mybuf.st_size;
00169 #endif
00170 }
00171
00172 bool DiskFile::exists() const
00173 {
00174 if (path().empty())
00175 return false;
00176 #if defined(VL_PLATFORM_WINDOWS)
00177
00178
00179 HANDLE hdl = CreateFile(
00180 (const wchar_t*)path().ptr(),
00181 FILE_READ_ATTRIBUTES,
00182 FILE_SHARE_READ,
00183 NULL,
00184 OPEN_EXISTING,
00185 FILE_ATTRIBUTE_NORMAL,
00186 NULL
00187 );
00188
00189 if (hdl != INVALID_HANDLE_VALUE)
00190 {
00191 CloseHandle(hdl);
00192 return true;
00193 }
00194 else
00195 return false;
00196 #elif defined(__GNUG__)
00197 std::vector<unsigned char> utf8;
00198 path().toUTF8( utf8, false );
00199 if (utf8.empty())
00200 return false;
00201 FILE* fin = fopen( (char*)&utf8[0], "rb");
00202 if (fin != NULL)
00203 {
00204 fclose(fin);
00205 return true;
00206 }
00207 else
00208 return false;
00209 #endif
00210 }
00211
00212 long long DiskFile::read_Implementation(void* buffer, long long byte_count)
00213 {
00214 if (!mHandle)
00215 {
00216 Log::error("DiskFile::read_Implementation() called on closed file!\n");
00217 return 0;
00218 }
00219
00220 long long count = 0;
00221 #if defined(VL_PLATFORM_WINDOWS)
00222
00223 #if 0
00224
00225
00226 long long file_size = size();
00227 byte_count = byte_count < file_size ? byte_count : (long long)file_size;
00228 #endif
00229
00230 char* ptr = (char*)buffer;
00231 DWORD NumberOfBytesRead = 0;
00232
00233 long long bytes = byte_count < 20*1024*1024 ? byte_count : 20*1024*1024;
00234 while( ReadFile( mHandle, ptr, (DWORD)bytes, &NumberOfBytesRead, NULL ) && NumberOfBytesRead )
00235 {
00236 byte_count -= NumberOfBytesRead;
00237 bytes = byte_count < 20*1024*1024 ? byte_count : 20*1024*1024;
00238 ptr += NumberOfBytesRead;
00239 count += NumberOfBytesRead;
00240 }
00241 #elif defined(__GNUG__)
00242 char* ptr = (char*)buffer;
00243 long long bytes_read = 0;
00244 while( (bytes_read = fread(ptr, 1, byte_count, mHandle)) )
00245 {
00246 byte_count -= bytes_read;
00247 ptr += bytes_read;
00248 count += bytes_read;
00249 }
00250 if (ferror(mHandle))
00251 perror("Error reading file: ");
00252 #endif
00253 return count;
00254 }
00255
00256 long long DiskFile::write_Implementation(const void* buffer, long long byte_count)
00257 {
00258 if (!mHandle)
00259 {
00260 Log::error("DiskFile::write_Implementation() called on closed file!\n");
00261 return 0;
00262 }
00263
00264 long long count = 0;
00265 #if defined(VL_PLATFORM_WINDOWS)
00266 DWORD NumberOfBytesWritten = 0;
00267 WriteFile( mHandle, buffer, (DWORD)byte_count, &NumberOfBytesWritten, NULL );
00268 count = NumberOfBytesWritten;
00269 #elif defined(__GNUG__)
00270 count = fwrite( buffer, 1, byte_count, mHandle );
00271 if (ferror(mHandle))
00272 perror("Error reading file: ");
00273 #endif
00274 return count;
00275 }
00276
00277 long long DiskFile::position_Implementation() const
00278 {
00279 if (!mHandle)
00280 {
00281 Log::error("DiskFile::position_Implementation() called on closed file!\n");
00282 return -1;
00283 }
00284
00285 #if defined(VL_PLATFORM_WINDOWS)
00286 LARGE_INTEGER position;
00287 position.QuadPart = 0;
00288 SetFilePointerEx(
00289 mHandle,
00290 position,
00291 &position,
00292 FILE_CURRENT );
00293 return position.QuadPart;
00294 #elif defined(__GNUG__)
00295 return ftell(mHandle);
00296 #endif
00297 }
00298
00299 bool DiskFile::seekSet_Implementation(long long offset)
00300 {
00301 if (!mHandle)
00302 {
00303 Log::error("DiskFile::seekSet_Implementation() called on closed file!\n");
00304 return false;
00305 }
00306
00307 #if defined(VL_PLATFORM_WINDOWS)
00308 LARGE_INTEGER position;
00309 position.QuadPart = offset;
00310 if (mHandle)
00311 {
00312 SetFilePointerEx(
00313 mHandle,
00314 position,
00315 &position,
00316 FILE_BEGIN );
00317 }
00318 #elif defined(__GNUG__)
00319 fseeko64(mHandle, offset, SEEK_SET);
00320 #endif
00321 return true;
00322 }
00323
00324 ref<VirtualFile> DiskFile::clone() const
00325 {
00326 ref<DiskFile> file = new DiskFile;
00327 file->operator=(*this);
00328 return file;
00329 }
00330