Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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 // DiskFile 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 // encode to utf8 for linux 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 // see the ifs above 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 // opens the file 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 // http://linux.die.net/man/2/stat 00158 struct stat mybuf; 00159 memset(&mybuf, 0, sizeof(struct stat)); 00160 // encode to utf8 for linux 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 /*VL_CHECK( sizeof(wchar_t) == sizeof(unsigned short) )*/ 00178 // opens the file 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 // avoid win xp problem: read fails if request to read much more bytes than the file size 00225 // but makes the reading way too slow. 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 // reads blocks of 20 megs due to possible problems under win xp 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 //-----------------------------------------------------------------------------