]> granicus.if.org Git - taglib/commitdiff
FileStream improvement in Win32
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 7 Sep 2012 14:48:06 +0000 (23:48 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 7 Sep 2012 14:48:06 +0000 (23:48 +0900)
taglib/toolkit/tfilestream.cpp

index b1fd9f80aff4eba5318cea63d5b6cf551b48359b..928a2d2de55a363abdedcfb75cafe8631124d221 100644 (file)
 # include <wchar.h>
 # include <windows.h>
 # include <io.h>
-# define ftruncate _chsize
 #else
 # include <unistd.h>
 #endif
 
 #include <stdlib.h>
 
-#ifndef R_OK
-# define R_OK 4
-#endif
-#ifndef W_OK
-# define W_OK 2
-#endif
-
 using namespace TagLib;
 
+namespace {
 #ifdef _WIN32
 
-typedef FileName FileNameHandle;
+  // For Windows 
 
-#else
+  typedef FileName FileNameHandle;
 
-struct FileNameHandle : public std::string
-{
-  FileNameHandle(FileName name) : std::string(name) {}
-  operator FileName () const { return c_str(); }
-};
-
-#endif
+  // Using native file handles instead of file descriptors for reducing the resource consumption.
 
-namespace {
-  FILE *openFile(const FileName &path, bool readOnly)
+  HANDLE openFile(const FileName &path, bool readOnly)
   {
-    // Calls a proper variation of fopen() depending on the compiling environment.
-
-#if defined(_WIN32)
-  
-# if defined(_MSC_VER) && (_MSC_VER >= 1400) 
-
-    // Visual C++ 2005 or later.
-
-    FILE *file;
-    errno_t err;
+    DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
 
     if(wcslen(path) > 0)
-      err = _wfopen_s(&file, path, readOnly ? L"rb" : L"rb+");
+      return CreateFileW(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     else
-      err = fopen_s(&file, path, readOnly ? "rb" : "rb+");
-  
-    if(err == 0)
-      return file;
-    else
-      return NULL;
-  
-# else   // defined(_MSC_VER) && (_MSC_VER >= 1400)
+      return CreateFileA(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+  }
 
-    // Visual C++.NET 2003 or earlier.
+  size_t fread(void *ptr, size_t size, size_t nmemb, HANDLE stream)
+  {
+    DWORD read_len;
+    ReadFile(stream, ptr, size * nmemb, &read_len, NULL);
 
-    if(wcslen(path) > 0)
-      return _wfopen(path, readOnly ? L"rb" : L"rb+");
-    else
-      return fopen(path, readOnly ? "rb" : "rb+");
+    return (read_len / size);
+  }
 
-# endif  // defined(_MSC_VER) && (_MSC_VER >= 1400)
+  size_t fwrite(const void *ptr, size_t size, size_t nmemb, HANDLE stream)
+  {
+    DWORD written_len;
+    WriteFile(stream, ptr, size * nmemb, &written_len, NULL);
 
-#else  // defined(_WIN32)
+    return written_len;
+  }
 
-    // Non-Win32
+#else
 
-    return fopen(path, readOnly ? "rb" : "rb+");
+  // For non-Windows 
+
+  struct FileNameHandle : public std::string
+  {
+    FileNameHandle(FileName name) : std::string(name) {}
+    operator FileName () const { return c_str(); }
+  };
 
-#endif // defined(_WIN32)
+  FILE *openFile(const FileName &path, bool readOnly)
+  {
+    return fopen(path, readOnly ? "rb" : "rb+");
   }
+
+#endif
 }
 
 class FileStream::FileStreamPrivate
@@ -115,8 +101,16 @@ class FileStream::FileStreamPrivate
 public:
   FileStreamPrivate(FileName fileName, bool openReadOnly);
 
+#ifdef _WIN32
+
+  HANDLE file;
+
+#else
+
   FILE *file;
 
+#endif
+
   FileNameHandle name;
 
   bool readOnly;
@@ -156,8 +150,18 @@ FileStream::FileStream(FileName file, bool openReadOnly)
 
 FileStream::~FileStream()
 {
+#ifdef _WIN32
+
+  if(d->file)
+    CloseHandle(d->file);
+
+#else
+
   if(d->file)
     fclose(d->file);
+
+#endif
+
   delete d;
 }
 
@@ -348,27 +352,67 @@ void FileStream::seek(long offset, Position p)
     return;
   }
 
+#ifdef _WIN32
+
+  DWORD whence;
+  switch(p) {
+  case Beginning:
+    whence = FILE_BEGIN;
+    break;
+  case Current:
+    whence = FILE_CURRENT;
+    break;
+  case End:
+    whence = FILE_END;
+    break;
+  }
+
+  SetFilePointer(d->file, offset, NULL, whence);
+
+#else
+
+  int whence;
   switch(p) {
   case Beginning:
-    fseek(d->file, offset, SEEK_SET);
+    whence = SEEK_SET;
     break;
   case Current:
-    fseek(d->file, offset, SEEK_CUR);
+    whence = SEEK_CUR;
     break;
   case End:
-    fseek(d->file, offset, SEEK_END);
+    whence = SEEK_END;
     break;
   }
+
+  fseek(d->file, offset, whence);
+
+#endif
 }
 
 void FileStream::clear()
 {
+#ifdef _WIN32
+
+  // NOP
+
+#else
+
   clearerr(d->file);
+
+#endif
 }
 
 long FileStream::tell() const
 {
+#ifdef _WIN32
+
+  return (long)SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
+
+#else
+
   return ftell(d->file);
+
+#endif
 }
 
 long FileStream::length()
@@ -398,17 +442,20 @@ long FileStream::length()
 
 void FileStream::truncate(long length)
 {
+#ifdef _WIN32
 
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)  // VC++2005 or later
+  long current_pos = tell();
 
-  ftruncate(_fileno(d->file), length);
+  seek(length);
+  SetEndOfFile(d->file);
+
+  seek(current_pos);
 
 #else
 
   ftruncate(fileno(d->file), length);
 
 #endif
-
 }
 
 TagLib::uint FileStream::bufferSize()