Move MMap to SkData.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 24 Apr 2013 20:03:00 +0000 (20:03 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 24 Apr 2013 20:03:00 +0000 (20:03 +0000)
R=reed@google.com

Author: bungeman@google.com

Review URL: https://chromiumcodereview.appspot.com/14336003

git-svn-id: http://skia.googlecode.com/svn/trunk@8848 2bbb7eff-a529-9590-31e7-b0007b416f81

gm/factory.cpp
include/core/SkData.h
src/core/SkData.cpp
src/core/SkStream.cpp
src/ports/SkOSFile_stdio.cpp
src/utils/win/SkHRESULT.cpp

index f4e8ae3..4538cda 100644 (file)
@@ -32,12 +32,12 @@ protected:
         // Copyright-free file from http://openclipart.org/detail/29213/paper-plane-by-ddoo
         filename.append("plane.png");
 
-        SkFILEStream stream(filename.c_str());
-        if (stream.isValid()) {
-            stream.rewind();
-            size_t length = stream.getLength();
+        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
+        if (NULL != stream.get()) {
+            stream->rewind();
+            size_t length = stream->getLength();
             void* buffer = sk_malloc_throw(length);
-            stream.read(buffer, length);
+            stream->read(buffer, length);
             SkAutoDataUnref data(SkData::NewFromMalloc(buffer, length));
             SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget);
             // Create a cache which will boot the pixels out anytime the
index fdd3a57..0e8ee22 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "SkFlattenable.h"
 
+struct SkFILE;
+
 /**
  *  SkData holds an immutable data buffer. Not only is the data immutable,
  *  but the actual ptr that is returned (by data() or bytes()) is guaranteed
@@ -89,10 +91,12 @@ public:
     static SkData* NewFromMalloc(const void* data, size_t length);
 
     /**
-     *  Create a new dataref from a pointer allocated by mmap. The Data object
-     *  will handle calling munmap().
+     *  Create a new dataref from a SkFILE.
+     *  This does not take ownership of the SkFILE, nor close it.
+     *  The SkFILE must be open for reading only.
+     *  Returns NULL on failure.
      */
-    static SkData* NewFromMMap(const void* data, size_t length);
+    static SkData* NewFromFILE(SkFILE* f);
 
     /**
      *  Create a new dataref using a subset of the data in the specified
index 8c22200..53d5f23 100644 (file)
@@ -7,12 +7,16 @@
 
 #include "SkData.h"
 #include "SkFlattenableBuffers.h"
+#include "SkOSFile.h"
 
 #if SK_MMAP_SUPPORT
     #include <unistd.h>
     #include <sys/mman.h>
     #include <fcntl.h>
     #include <errno.h>
+    #include <unistd.h>
+#else
+    #include <io.h>
 #endif
 
 SK_DEFINE_INST_COUNT(SkData)
@@ -94,6 +98,90 @@ static void sk_dataref_releaseproc(const void*, size_t, void* context) {
     src->unref();
 }
 
+#if SK_MMAP_SUPPORT
+
+static void sk_munmap_releaseproc(const void* addr, size_t length, void*) {
+    munmap(const_cast<void*>(addr), length);
+}
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+    size_t size = sk_fgetsize(f);
+    if (0 == size) {
+        return NULL;
+    }
+
+    int fd = fileno((FILE*)f);
+    if (fd < 0) {
+        return NULL;
+    }
+
+    void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+    if (MAP_FAILED == addr) {
+        return NULL;
+    }
+
+    return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL);
+}
+
+#elif SK_BUILD_FOR_WIN32
+
+template <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)>
+class SkAutoTHandle : SkNoncopyable {
+public:
+    SkAutoTHandle(HandleType handle) : fHandle(handle) { }
+    ~SkAutoTHandle() { Close(fHandle); }
+    operator HandleType() { return fHandle; }
+    bool isValid() { return InvalidValue != fHandle; }
+private:
+    HandleType fHandle;
+};
+typedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile;
+typedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap;
+
+static void sk_munmap_releaseproc(const void* addr, size_t, void*) {
+    UnmapViewOfFile(addr);
+}
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+    size_t size = sk_fgetsize(f);
+    if (0 == size) {
+        return NULL;
+    }
+
+    int fileno = _fileno((FILE*)f);
+    if (fileno < 0) {
+        return NULL;
+    }
+
+    HANDLE file = (HANDLE)_get_osfhandle(fileno);
+    if (INVALID_HANDLE_VALUE == file) {
+        return NULL;
+    }
+
+    SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
+    if (!mmap.isValid()) {
+        //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
+        return NULL;
+    }
+
+    // Eventually call UnmapViewOfFile
+    void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
+    if (NULL == addr) {
+        //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
+        return NULL;
+    }
+
+    return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL);
+}
+
+#else
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+    return NULL;
+}
+
+#endif
+
 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
     /*
         We could, if we wanted/need to, just make a deep copy of src's data,
@@ -127,20 +215,6 @@ SkData* SkData::NewWithCString(const char cstr[]) {
     return NewWithCopy(cstr, size);
 }
 
-#if SK_MMAP_SUPPORT
-static void sk_munmap_releaseproc(const void* addr, size_t length, void*) {
-    munmap(const_cast<void*>(addr), length);
-}
-
-SkData* SkData::NewFromMMap(const void* addr, size_t length) {
-    return SkNEW_ARGS(SkData, (addr, length, sk_munmap_releaseproc, NULL));
-}
-#else
-SkData* SkData::NewFromMMap(const void* addr, size_t length) {
-    return NULL;
-}
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
index ed1287e..74734e6 100644 (file)
 #include "SkString.h"
 #include "SkOSFile.h"
 
-#if SK_MMAP_SUPPORT
-    #include <unistd.h>
-    #include <sys/mman.h>
-    #include <fcntl.h>
-    #include <errno.h>
-    #include <unistd.h>
-#endif
-
 SK_DEFINE_INST_COUNT(SkStream)
 SK_DEFINE_INST_COUNT(SkWStream)
 SK_DEFINE_INST_COUNT(SkFILEStream)
@@ -796,46 +788,22 @@ bool SkDebugWStream::write(const void* buffer, size_t size)
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool mmap_filename(const char path[], void** addrPtr, size_t* sizePtr) {
-#if SK_MMAP_SUPPORT
-    int fd = open(path, O_RDONLY);
-    if (fd < 0) {
-        return false;
-    }
 
-    off_t offset = lseek(fd, 0, SEEK_END);    // find the file size
-    if (offset == -1) {
-        close(fd);
-        return false;
+static SkData* mmap_filename(const char path[]) {
+    SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
+    if (NULL == file) {
+        return NULL;
     }
-    (void)lseek(fd, 0, SEEK_SET);   // restore file offset to beginning
-
-    // to avoid a 64bit->32bit warning, I explicitly create a size_t size
-    size_t size = static_cast<size_t>(offset);
 
-    void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-    close(fd);
-
-    if (MAP_FAILED == addr) {
-        return false;
-    }
-
-    *addrPtr = addr;
-    *sizePtr = size;
-    return true;
-#else
-    return false;
-#endif
+    SkData* data = SkData::NewFromFILE(file);
+    sk_fclose(file);
+    return data;
 }
 
 SkStream* SkStream::NewFromFile(const char path[]) {
-    void* addr;
-    size_t size;
-    if (mmap_filename(path, &addr, &size)) {
-        SkAutoTUnref<SkData> data(SkData::NewFromMMap(addr, size));
-        if (data.get()) {
-            return SkNEW_ARGS(SkMemoryStream, (data.get()));
-        }
+    SkAutoTUnref<SkData> data(mmap_filename(path));
+    if (data.get()) {
+        return SkNEW_ARGS(SkMemoryStream, (data.get()));
     }
 
     // If we get here, then our attempt at using mmap failed, so try normal
index 1d27c6b..40c8745 100644 (file)
@@ -33,6 +33,8 @@ SkFILE* sk_fopen(const char path[], SkFILE_Flags flags)
     *p++ = 'b';
     *p = 0;
 
+    //TODO: on Windows fopen is just ASCII or the current code page,
+    //convert to utf16 and use _wfopen
     SkFILE* f = (SkFILE*)::fopen(path, perm);
 #if 0
     if (NULL == f)
index 8b6b79f..32d9d4c 100644 (file)
@@ -29,7 +29,7 @@ void SkTraceHR(const char* file, unsigned long line,
     if (NULL == errorText) {
         SkDEBUGF(("<unknown>\n"));
     } else {
-        SkDEBUGF((errorText));
+        SkDEBUGF(("%s", errorText));
         LocalFree(errorText);
         errorText = NULL;
     }