aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-03 17:10:35 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-03 17:10:35 +0000
commit11c9a55afd95078d14ab8cd7c1c5c0032af2a498 (patch)
tree3479a58fe5e8e8dfc687f6a76412b049773e3c8f
parent135ece137b471219eea06a652069b86a3b6ec349 (diff)
Add SkData::NewFromFD.
Chromium needs a SkStream backed by a file descriptor. Skia already has the code and can do the work, this change exposes the functionality in Skia in a clean way. https://codereview.chromium.org/15941025/ git-svn-id: http://skia.googlecode.com/svn/trunk@9408 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/SkData.h10
-rw-r--r--include/core/SkOSFile.h14
-rw-r--r--include/core/SkTemplates.h5
-rw-r--r--src/core/SkData.cpp10
-rw-r--r--src/ports/SkDebug_brew.cpp28
-rw-r--r--src/ports/SkMemory_brew.cpp55
-rw-r--r--src/ports/SkOSFile_brew.cpp90
-rw-r--r--src/ports/SkOSFile_none.cpp4
-rw-r--r--src/ports/SkOSFile_posix.cpp29
-rw-r--r--src/ports/SkOSFile_win.cpp32
-rw-r--r--src/utils/win/SkDWriteFontFileStream.cpp3
-rw-r--r--tests/DataRefTest.cpp52
12 files changed, 128 insertions, 204 deletions
diff --git a/include/core/SkData.h b/include/core/SkData.h
index 0e8ee2219e..4600429fea 100644
--- a/include/core/SkData.h
+++ b/include/core/SkData.h
@@ -93,12 +93,22 @@ public:
/**
* Create a new dataref from a SkFILE.
* This does not take ownership of the SkFILE, nor close it.
+ * The caller is free to close the SkFILE at its convenience.
* The SkFILE must be open for reading only.
* Returns NULL on failure.
*/
static SkData* NewFromFILE(SkFILE* f);
/**
+ * Create a new dataref from a file descriptor.
+ * This does not take ownership of the file descriptor, nor close it.
+ * The caller is free to close the file descriptor at its convenience.
+ * The file descriptor must be open for reading only.
+ * Returns NULL on failure.
+ */
+ static SkData* NewFromFD(int fd);
+
+ /**
* Create a new dataref using a subset of the data in the specified
* src dataref.
*/
diff --git a/include/core/SkOSFile.h b/include/core/SkOSFile.h
index 11330a03b1..f8ce06bcaf 100644
--- a/include/core/SkOSFile.h
+++ b/include/core/SkOSFile.h
@@ -54,10 +54,17 @@ size_t sk_ftell(SkFILE*);
/** Maps a file into memory. Returns the address and length on success, NULL otherwise.
* The mapping is read only.
+ * When finished with the mapping, free the returned pointer with sk_fmunmap.
*/
void* sk_fmmap(SkFILE* f, size_t* length);
-/** Unmaps a file previously mapped by sk_fmmap.
+/** Maps a file descriptor into memory. Returns the address and length on success, NULL otherwise.
+ * The mapping is read only.
+ * When finished with the mapping, free the returned pointer with sk_fmunmap.
+ */
+void* sk_fdmmap(int fd, size_t* length);
+
+/** Unmaps a file previously mapped by sk_fmmap or sk_fdmmap.
* The length parameter must be the same as returned from sk_fmmap.
*/
void sk_fmunmap(const void* addr, size_t length);
@@ -65,6 +72,11 @@ void sk_fmunmap(const void* addr, size_t length);
/** Returns true if the two point at the exact same filesystem object. */
bool sk_fidentical(SkFILE* a, SkFILE* b);
+/** Returns the underlying file descriptor for the given file.
+ * The return value will be < 0 on failure.
+ */
+int sk_fileno(SkFILE* f);
+
// Returns true if something (file, directory, ???) exists at this path.
bool sk_exists(const char *path);
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index ce76dbfbba..bbbed48cea 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -64,6 +64,11 @@ template <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffs
);
}
+/** Returns true if the source value 's' will fit in the destination type 'D'. */
+template <typename D, typename S> inline bool SkTFitsIn(S s) {
+ return static_cast<D>(s) == s;
+}
+
/** \class SkAutoTCallVProc
Call a function when this goes out of scope. The template uses two
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp
index 32e029740a..c1a21365ab 100644
--- a/src/core/SkData.cpp
+++ b/src/core/SkData.cpp
@@ -97,6 +97,16 @@ SkData* SkData::NewFromFILE(SkFILE* f) {
return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
}
+SkData* SkData::NewFromFD(int fd) {
+ size_t size;
+ void* addr = sk_fdmmap(fd, &size);
+ if (NULL == addr) {
+ return NULL;
+ }
+
+ return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
+}
+
// assumes context is a SkData
static void sk_dataref_releaseproc(const void*, size_t, void* context) {
SkData* src = reinterpret_cast<SkData*>(context);
diff --git a/src/ports/SkDebug_brew.cpp b/src/ports/SkDebug_brew.cpp
deleted file mode 100644
index b7ad3ef275..0000000000
--- a/src/ports/SkDebug_brew.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* libs/corecg/SkDebug_brew.cpp
- *
- * Copyright 2009, The Android Open Source Project
- * Copyright 2009, Company 100, Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkTypes.h"
-
-#ifdef SK_BUILD_FOR_BREW
-
-static const size_t kBufferSize = 256;
-
-#include <AEEStdLib.h>
-#include <stdarg.h>
-
-void SkDebugf(const char format[], ...) {
- char buffer[kBufferSize + 1];
- va_list args;
- va_start(args, format);
- VSNPRINTF(buffer, kBufferSize, format, args);
- va_end(args);
- DBGPRINTF(buffer);
-}
-
-#endif SK_BUILD_FOR_BREW
diff --git a/src/ports/SkMemory_brew.cpp b/src/ports/SkMemory_brew.cpp
deleted file mode 100644
index 96af7021e6..0000000000
--- a/src/ports/SkMemory_brew.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* libs/graphics/ports/SkMemory_brew.cpp
- *
- * Copyright 2009, The Android Open Source Project
- * Copyright 2009, Company 100, Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkTypes.h"
-
-#ifdef SK_BUILD_FOR_BREW
-
-#include <AEEStdLib.h>
-
-void sk_throw() {
- SkDEBUGFAIL("sk_throw");
- abort();
-}
-
-void sk_out_of_memory(void) {
- SkDEBUGFAIL("sk_out_of_memory");
- abort();
-}
-
-void* sk_malloc_throw(size_t size) {
- return sk_malloc_flags(size, SK_MALLOC_THROW);
-}
-
-void* sk_realloc_throw(void* addr, size_t size) {
- void* p = REALLOC(addr, size | ALLOC_NO_ZMEM);
- if (size == 0) {
- return p;
- }
- if (p == NULL) {
- sk_throw();
- }
- return p;
-}
-
-void sk_free(void* p) {
- FREEIF(p);
-}
-
-void* sk_malloc_flags(size_t size, unsigned flags) {
- void* p = MALLOC(size | ALLOC_NO_ZMEM);
- if (p == NULL) {
- if (flags & SK_MALLOC_THROW) {
- sk_throw();
- }
- }
- return p;
-}
-
-#endif
diff --git a/src/ports/SkOSFile_brew.cpp b/src/ports/SkOSFile_brew.cpp
deleted file mode 100644
index 50e133ff2f..0000000000
--- a/src/ports/SkOSFile_brew.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* libs/graphics/ports/SkOSFile_brew.cpp
- *
- * Copyright 2006, The Android Open Source Project
- * Copyright 2009, Company 100, Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkOSFile.h"
-
-#ifdef SK_BUILD_FOR_BREW
-
-#include <AEEAppGen.h>
-#include <AEEFile.h>
-#include <AEEStdLib.h>
-
-SkFILE* sk_fopen(const char path[], SkFILE_Flags flags)
-{
- int err;
- OpenFileMode mode;
- IFileMgr* fileMgr;
- IFile* file;
- IShell* shell;
-
- shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
- err = ISHELL_CreateInstance(shell, AEECLSID_FILEMGR, (void**)&fileMgr);
- if (err!= SUCCESS)
- return NULL;
-
- if (flags & kWrite_SkFILE_Flag)
- mode = _OFM_READWRITE;
- else /* kRead_SkFILE_Flag */
- mode = _OFM_READ;
-
- file = IFILEMGR_OpenFile(fileMgr, path, mode);
- IFILEMGR_Release(fileMgr);
-
- return (SkFILE*)file;
-}
-
-size_t sk_fgetsize(SkFILE* f)
-{
- FileInfo fileInfo;
-
- IFILE_GetInfo((IFile*)f, &fileInfo);
- return fileInfo.dwSize;
-}
-
-bool sk_frewind(SkFILE* f)
-{
- SkASSERT(f);
- return IFILE_Seek((IFile*)f, _SEEK_START, 0) == SUCCESS;
-}
-
-size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f)
-{
- SkASSERT(f);
- if (buffer == NULL)
- {
- int err = IFILE_Seek((IFile*)f, _SEEK_CURRENT, (int)byteCount);
- if (err == EFAILED) {
- SkDEBUGF(("sk_fread: IFILE_Seek(%d) failed returned:%d\n", byteCount, err));
- return 0;
- }
- return byteCount;
- }
- else
- return IFILE_Read((IFile*)f, buffer, byteCount);
-}
-
-size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f)
-{
- SkASSERT(f);
- return IFILE_Write((IFile*)f, buffer, byteCount);
-}
-
-void sk_fflush(SkFILE* f)
-{
- SkASSERT(f);
-}
-
-void sk_fclose(SkFILE* f)
-{
- SkASSERT(f);
- IFILE_Release((IFile*)f);
-}
-
-#endif
diff --git a/src/ports/SkOSFile_none.cpp b/src/ports/SkOSFile_none.cpp
index e22d22ed4d..f268e13783 100644
--- a/src/ports/SkOSFile_none.cpp
+++ b/src/ports/SkOSFile_none.cpp
@@ -13,6 +13,10 @@ bool sk_fidentical(SkFILE* a, SkFILE* b) {
void sk_fmunmap(const void* addr, size_t length) { }
+void* sk_fdmmap(int fd, size_t* size) {
+ return NULL;
+}
+
void* sk_fmmap(SkFILE* f, size_t* size) {
return NULL;
}
diff --git a/src/ports/SkOSFile_posix.cpp b/src/ports/SkOSFile_posix.cpp
index c9da4db6b8..72a1b59335 100644
--- a/src/ports/SkOSFile_posix.cpp
+++ b/src/ports/SkOSFile_posix.cpp
@@ -7,6 +7,8 @@
#include "SkOSFile.h"
+#include "SkTemplates.h"
+
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -42,16 +44,18 @@ void sk_fmunmap(const void* addr, size_t length) {
munmap(const_cast<void*>(addr), length);
}
-void* sk_fmmap(SkFILE* f, size_t* size) {
- size_t fileSize = sk_fgetsize(f);
- if (0 == fileSize) {
+void* sk_fdmmap(int fd, size_t* size) {
+ struct stat status;
+ if (0 != fstat(fd, &status)) {
return NULL;
}
-
- int fd = fileno((FILE*)f);
- if (fd < 0) {
+ if (!S_ISREG(status.st_mode)) {
+ return NULL;
+ }
+ if (!SkTFitsIn<size_t>(status.st_size)) {
return NULL;
}
+ size_t fileSize = static_cast<size_t>(status.st_size);
void* addr = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fd, 0);
if (MAP_FAILED == addr) {
@@ -61,3 +65,16 @@ void* sk_fmmap(SkFILE* f, size_t* size) {
*size = fileSize;
return addr;
}
+
+int sk_fileno(SkFILE* f) {
+ return fileno((FILE*)f);
+}
+
+void* sk_fmmap(SkFILE* f, size_t* size) {
+ int fd = sk_fileno(f);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ return sk_fdmmap(fd, size);
+}
diff --git a/src/ports/SkOSFile_win.cpp b/src/ports/SkOSFile_win.cpp
index fdf9ca5013..2133f7bf12 100644
--- a/src/ports/SkOSFile_win.cpp
+++ b/src/ports/SkOSFile_win.cpp
@@ -7,6 +7,8 @@
#include "SkOSFile.h"
+#include "SkTemplates.h"
+
#include <io.h>
#include <stdio.h>
#include <sys/stat.h>
@@ -65,19 +67,18 @@ void sk_fmunmap(const void* addr, size_t) {
UnmapViewOfFile(addr);
}
-void* sk_fmmap(SkFILE* f, size_t* length) {
- size_t fileSize = sk_fgetsize(f);
- if (0 == fileSize) {
+void* sk_fdmmap(int fileno, size_t* length) {
+ HANDLE file = (HANDLE)_get_osfhandle(fileno);
+ if (INVALID_HANDLE_VALUE == file) {
return NULL;
}
- int fileno = _fileno((FILE*)f);
- if (fileno < 0) {
+ LARGE_INTEGER fileSize;
+ if (0 == GetFileSizeEx(file, &fileSize)) {
+ //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
return NULL;
}
-
- HANDLE file = (HANDLE)_get_osfhandle(fileno);
- if (INVALID_HANDLE_VALUE == file) {
+ if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
return NULL;
}
@@ -94,6 +95,19 @@ void* sk_fmmap(SkFILE* f, size_t* length) {
return NULL;
}
- *length = fileSize;
+ *length = static_cast<size_t>(fileSize.QuadPart);
return addr;
}
+
+int sk_fileno(SkFILE* f) {
+ return _fileno((FILE*)f);
+}
+
+void* sk_fmmap(SkFILE* f, size_t* length) {
+ int fileno = sk_fileno(f);
+ if (fileno < 0) {
+ return NULL;
+ }
+
+ return sk_fdmmap(fileno, length);
+}
diff --git a/src/utils/win/SkDWriteFontFileStream.cpp b/src/utils/win/SkDWriteFontFileStream.cpp
index 971fdb98b4..eb591138b7 100644
--- a/src/utils/win/SkDWriteFontFileStream.cpp
+++ b/src/utils/win/SkDWriteFontFileStream.cpp
@@ -8,6 +8,7 @@
#include "SkTypes.h"
#include "SkDWriteFontFileStream.h"
#include "SkHRESULT.h"
+#include "SkTemplates.h"
#include "SkTScopedComPtr.h"
#include <dwrite.h>
@@ -111,7 +112,7 @@ size_t SkDWriteFontFileStream::getLength() const {
HRESULT hr = S_OK;
UINT64 realFileSize = 0;
hr = fFontFileStream->GetFileSize(&realFileSize);
- if (realFileSize > (std::numeric_limits<size_t>::max)()) {
+ if (!SkTFitsIn<size_t>(realFileSize)) {
return 0;
}
return static_cast<size_t>(realFileSize);
diff --git a/tests/DataRefTest.cpp b/tests/DataRefTest.cpp
index 0cbce3fcd1..d8bd24b2ba 100644
--- a/tests/DataRefTest.cpp
+++ b/tests/DataRefTest.cpp
@@ -9,21 +9,10 @@
#include "SkData.h"
#include "SkDataSet.h"
#include "SkDataTable.h"
-#include "SkStream.h"
#include "SkOrderedReadBuffer.h"
#include "SkOrderedWriteBuffer.h"
-
-template <typename T> class SkTUnref {
-public:
- SkTUnref(T* ref) : fRef(ref) {}
- ~SkTUnref() { fRef->unref(); }
-
- operator T*() { return fRef; }
- operator const T*() { return fRef; }
-
-private:
- T* fRef;
-};
+#include "SkOSFile.h"
+#include "SkStream.h"
static void test_is_equal(skiatest::Reporter* reporter,
const SkDataTable* a, const SkDataTable* b) {
@@ -223,7 +212,7 @@ static void test_dataset(skiatest::Reporter* reporter, const SkDataSet& ds,
static void test_dataset(skiatest::Reporter* reporter) {
SkDataSet set0(NULL, 0);
- SkDataSet set1("hello", SkTUnref<SkData>(SkData::NewWithCString("world")));
+ SkDataSet set1("hello", SkAutoTUnref<SkData>(SkData::NewWithCString("world")));
const SkDataSet::Pair pairs[] = {
{ "one", SkData::NewWithCString("1") },
@@ -270,6 +259,40 @@ static void test_cstring(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 0 == *r2->bytes());
}
+static void test_files(skiatest::Reporter* reporter) {
+ if (skiatest::Test::GetTmpDir().isEmpty()) {
+ return;
+ }
+
+ const char* tmpDir = skiatest::Test::GetTmpDir().c_str();
+ SkString path;
+ path.printf("%s%s", tmpDir, "data_test");
+
+ const char s[] = "abcdefghijklmnopqrstuvwxyz";
+ {
+ SkFILEWStream writer(path.c_str());
+ if (!writer.isValid()) {
+ SkString msg;
+ msg.printf("Failed to create tmp file %s\n", path.c_str());
+ reporter->reportFailed(msg.c_str());
+ return;
+ }
+ writer.write(s, 26);
+ }
+
+ SkFILE* file = sk_fopen(path.c_str(), kRead_SkFILE_Flag);
+ SkAutoTUnref<SkData> r1(SkData::NewFromFILE(file));
+ REPORTER_ASSERT(reporter, r1.get() != NULL);
+ REPORTER_ASSERT(reporter, r1->size() == 26);
+ REPORTER_ASSERT(reporter, strncmp(static_cast<const char*>(r1->data()), s, 26) == 0);
+
+ int fd = sk_fileno(file);
+ SkAutoTUnref<SkData> r2(SkData::NewFromFD(fd));
+ REPORTER_ASSERT(reporter, r2.get() != NULL);
+ REPORTER_ASSERT(reporter, r2->size() == 26);
+ REPORTER_ASSERT(reporter, strncmp(static_cast<const char*>(r2->data()), s, 26) == 0);
+}
+
static void TestData(skiatest::Reporter* reporter) {
const char* str = "We the people, in order to form a more perfect union.";
const int N = 10;
@@ -297,6 +320,7 @@ static void TestData(skiatest::Reporter* reporter) {
test_cstring(reporter);
test_dataset(reporter);
+ test_files(reporter);
}
#include "TestClassDef.h"