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
This commit is contained in:
parent
135ece137b
commit
11c9a55afd
@ -93,11 +93,21 @@ 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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "SkOSFile.h"
|
||||
|
||||
#include "SkTemplates.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
@ -65,22 +67,21 @@ 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) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fileno = _fileno((FILE*)f);
|
||||
if (fileno < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* sk_fdmmap(int fileno, size_t* length) {
|
||||
HANDLE file = (HANDLE)_get_osfhandle(fileno);
|
||||
if (INVALID_HANDLE_VALUE == file) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (0 == GetFileSizeEx(file, &fileSize)) {
|
||||
//TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
|
||||
return NULL;
|
||||
}
|
||||
if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
|
||||
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.
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user