Change SkStream.
https://codereview.chromium.org/15298009/ git-svn-id: http://skia.googlecode.com/svn/trunk@9312 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
6320e8f393
commit
6cab1a4b6a
@ -78,7 +78,6 @@
|
|||||||
'<(skia_src_path)/core/SkEdge.h',
|
'<(skia_src_path)/core/SkEdge.h',
|
||||||
'<(skia_src_path)/core/SkError.cpp',
|
'<(skia_src_path)/core/SkError.cpp',
|
||||||
'<(skia_src_path)/core/SkErrorInternals.h',
|
'<(skia_src_path)/core/SkErrorInternals.h',
|
||||||
'<(skia_src_path)/core/SkFDStream.cpp',
|
|
||||||
'<(skia_src_path)/core/SkFP.h',
|
'<(skia_src_path)/core/SkFP.h',
|
||||||
'<(skia_src_path)/core/SkFilterProc.cpp',
|
'<(skia_src_path)/core/SkFilterProc.cpp',
|
||||||
'<(skia_src_path)/core/SkFilterProc.h',
|
'<(skia_src_path)/core/SkFilterProc.h',
|
||||||
|
@ -31,7 +31,9 @@
|
|||||||
'../src/ports/SkThread_win.cpp',
|
'../src/ports/SkThread_win.cpp',
|
||||||
|
|
||||||
'../src/ports/SkMemory_malloc.cpp',
|
'../src/ports/SkMemory_malloc.cpp',
|
||||||
|
'../src/ports/SkOSFile_posix.cpp',
|
||||||
'../src/ports/SkOSFile_stdio.cpp',
|
'../src/ports/SkOSFile_stdio.cpp',
|
||||||
|
'../src/ports/SkOSFile_win.cpp',
|
||||||
'../src/ports/SkTime_Unix.cpp',
|
'../src/ports/SkTime_Unix.cpp',
|
||||||
'../src/ports/SkTime_win.cpp',
|
'../src/ports/SkTime_win.cpp',
|
||||||
'../src/ports/SkXMLParser_empty.cpp',
|
'../src/ports/SkXMLParser_empty.cpp',
|
||||||
@ -140,12 +142,14 @@
|
|||||||
'sources!': [ # these are used everywhere but windows
|
'sources!': [ # these are used everywhere but windows
|
||||||
'../src/ports/SkDebug_stdio.cpp',
|
'../src/ports/SkDebug_stdio.cpp',
|
||||||
'../src/ports/SkTime_Unix.cpp',
|
'../src/ports/SkTime_Unix.cpp',
|
||||||
|
'../src/ports/SkOSFile_posix.cpp',
|
||||||
],
|
],
|
||||||
}, { # else !win
|
}, { # else !win
|
||||||
'sources!': [
|
'sources!': [
|
||||||
'../src/ports/SkDebug_win.cpp',
|
'../src/ports/SkDebug_win.cpp',
|
||||||
'../src/ports/SkFontHost_win.cpp',
|
'../src/ports/SkFontHost_win.cpp',
|
||||||
'../src/ports/SkFontHost_win_dw.cpp',
|
'../src/ports/SkFontHost_win_dw.cpp',
|
||||||
|
'../src/ports/SkOSFile_win.cpp',
|
||||||
'../src/ports/SkThread_win.cpp',
|
'../src/ports/SkThread_win.cpp',
|
||||||
'../src/ports/SkTime_win.cpp',
|
'../src/ports/SkTime_win.cpp',
|
||||||
],
|
],
|
||||||
|
@ -48,9 +48,23 @@ char* sk_fgets(char* str, int size, SkFILE* f);
|
|||||||
|
|
||||||
void sk_fflush(SkFILE*);
|
void sk_fflush(SkFILE*);
|
||||||
|
|
||||||
int sk_fseek(SkFILE*, size_t, int);
|
bool sk_fseek(SkFILE*, size_t);
|
||||||
|
bool sk_fmove(SkFILE*, long);
|
||||||
size_t sk_ftell(SkFILE*);
|
size_t sk_ftell(SkFILE*);
|
||||||
|
|
||||||
|
/** Maps a file into memory. Returns the address and length on success, NULL otherwise.
|
||||||
|
* The mapping is read only.
|
||||||
|
*/
|
||||||
|
void* sk_fmmap(SkFILE* f, size_t* length);
|
||||||
|
|
||||||
|
/** Unmaps a file previously mapped by sk_fmmap.
|
||||||
|
* The length parameter must be the same as returned from sk_fmmap.
|
||||||
|
*/
|
||||||
|
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 true if something (file, directory, ???) exists at this path.
|
// Returns true if something (file, directory, ???) exists at this path.
|
||||||
bool sk_exists(const char *path);
|
bool sk_exists(const char *path);
|
||||||
|
|
||||||
|
@ -13,6 +13,12 @@
|
|||||||
|
|
||||||
class SkData;
|
class SkData;
|
||||||
|
|
||||||
|
class SkStream;
|
||||||
|
class SkStreamRewindable;
|
||||||
|
class SkStreamSeekable;
|
||||||
|
class SkStreamAsset;
|
||||||
|
class SkStreamMemory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SkStream -- abstraction for a source of bytes. Subclasses can be backed by
|
* SkStream -- abstraction for a source of bytes. Subclasses can be backed by
|
||||||
* memory, or a file, or something else.
|
* memory, or a file, or something else.
|
||||||
@ -30,50 +36,43 @@ class SkData;
|
|||||||
* no more data (at EOF or hit an error). The caller should *not* call again
|
* no more data (at EOF or hit an error). The caller should *not* call again
|
||||||
* in hopes of fulfilling more of the request.
|
* in hopes of fulfilling more of the request.
|
||||||
*/
|
*/
|
||||||
class SK_API SkStream : public SkRefCnt {
|
class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Attempts to open the specified file, and return a stream to it (using
|
* Attempts to open the specified file, and return a stream to it (using
|
||||||
* mmap if available). On success, the caller must call unref() on the
|
* mmap if available). On success, the caller must call unref() on the
|
||||||
* returned object. On failure, returns NULL.
|
* returned object. On failure, returns NULL.
|
||||||
*/
|
*/
|
||||||
static SkStream* NewFromFile(const char path[]);
|
static SkStreamAsset* NewFromFile(const char path[]);
|
||||||
|
|
||||||
SK_DECLARE_INST_COUNT(SkStream)
|
SK_DECLARE_INST_COUNT(SkStream)
|
||||||
|
|
||||||
/** Called to rewind to the beginning of the stream. If this cannot be
|
/** Reads or skips size number of bytes.
|
||||||
done, return false.
|
* If buffer == NULL, skip size bytes, return how many were skipped.
|
||||||
*/
|
* If buffer != NULL, copy size bytes into buffer, return how many were copied.
|
||||||
virtual bool rewind() = 0;
|
* @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
|
||||||
/** If this stream represents a file, this method returns the file's name.
|
* @param size the number of bytes to skip or copy
|
||||||
If it does not, it returns NULL (the default behavior).
|
* @return bytes read on success
|
||||||
*/
|
*/
|
||||||
virtual const char* getFileName();
|
|
||||||
/** Called to read or skip size number of bytes.
|
|
||||||
If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
|
|
||||||
If buffer is NULL and size == 0, return the total length of the stream.
|
|
||||||
If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
|
|
||||||
@param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
|
|
||||||
@param size The number of bytes to skip or copy
|
|
||||||
@return bytes read on success
|
|
||||||
*/
|
|
||||||
virtual size_t read(void* buffer, size_t size) = 0;
|
virtual size_t read(void* buffer, size_t size) = 0;
|
||||||
|
|
||||||
/** Return the total length of the stream.
|
/** Skip size number of bytes.
|
||||||
*/
|
* @return the actual number bytes that could be skipped.
|
||||||
size_t getLength() { return this->read(NULL, 0); }
|
*/
|
||||||
|
size_t skip(size_t size) {
|
||||||
|
//return this->read(NULL, size);
|
||||||
|
//TODO: remove this old logic after updating existing implementations
|
||||||
|
return 0 == size ? 0 : this->read(NULL, size);
|
||||||
|
}
|
||||||
|
|
||||||
/** Skip the specified number of bytes, returning the actual number
|
/** Returns true if there are no more bytes to be read.
|
||||||
of bytes that could be skipped.
|
* In Progress: do not use until all implementations are updated.
|
||||||
*/
|
* TODO: after this is implemented everywhere, make pure virtual.
|
||||||
size_t skip(size_t bytes);
|
*/
|
||||||
|
virtual bool isAtEnd() const {
|
||||||
/** If the stream is backed by RAM, this method returns the starting
|
SkASSERT(false);
|
||||||
address for the data. If not (i.e. it is backed by a file or other
|
return true;
|
||||||
structure), this method returns NULL.
|
}
|
||||||
The default implementation returns NULL.
|
|
||||||
*/
|
|
||||||
virtual const void* getMemoryBase();
|
|
||||||
|
|
||||||
int8_t readS8();
|
int8_t readS8();
|
||||||
int16_t readS16();
|
int16_t readS16();
|
||||||
@ -93,10 +92,100 @@ public:
|
|||||||
*/
|
*/
|
||||||
SkData* readData();
|
SkData* readData();
|
||||||
|
|
||||||
|
//SkStreamRewindable
|
||||||
|
/** Rewinds to the beginning of the stream. If this cannot be done, return false. */
|
||||||
|
virtual bool rewind() { return false; }
|
||||||
|
|
||||||
|
/** Duplicates this stream. If this cannot be done, returns NULL.
|
||||||
|
* The returned stream will be positioned at the beginning of its data.
|
||||||
|
*/
|
||||||
|
virtual SkStreamRewindable* duplicate() const { return NULL; }
|
||||||
|
|
||||||
|
//SkStreamSeekable
|
||||||
|
/** Returns true if this stream can report it's current position. */
|
||||||
|
virtual bool hasPosition() const { return false; }
|
||||||
|
/** Returns the current position in the stream. If this cannot be done, returns 0. */
|
||||||
|
virtual size_t getPosition() const { return 0; }
|
||||||
|
|
||||||
|
/** Seeks to an absolute position in the stream. If this cannot be done, returns false.
|
||||||
|
* If an attempt is made to seek past the end of the stream, the position will be set
|
||||||
|
* to the end of the stream.
|
||||||
|
*/
|
||||||
|
virtual bool seek(size_t position) { return false; }
|
||||||
|
|
||||||
|
/** Seeks to an relative offset in the stream. If this cannot be done, returns false.
|
||||||
|
* If an attempt is made to move to a position outside the stream, the position will be set
|
||||||
|
* to the closest point within the stream (beginning or end).
|
||||||
|
*/
|
||||||
|
virtual bool move(long offset) { return false; }
|
||||||
|
|
||||||
|
/** Duplicates this stream. If this cannot be done, returns NULL.
|
||||||
|
* The returned stream will be positioned the same as this stream.
|
||||||
|
*/
|
||||||
|
virtual SkStreamSeekable* fork() const { return NULL; }
|
||||||
|
|
||||||
|
//SkStreamAsset
|
||||||
|
/** Returns true if this stream can report it's total length. */
|
||||||
|
virtual bool hasLength() const { return false; }
|
||||||
|
/** Returns the total length of the stream. If this cannot be done, returns 0. */
|
||||||
|
virtual size_t getLength() const {
|
||||||
|
//return 0;
|
||||||
|
//TODO: remove the following after everyone is updated.
|
||||||
|
return ((SkStream*)this)->read(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SkStreamMemory
|
||||||
|
/** Returns the starting address for the data. If this cannot be done, returns NULL. */
|
||||||
|
//TODO: replace with virtual const SkData* getData()
|
||||||
|
virtual const void* getMemoryBase() { return NULL; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef SkRefCnt INHERITED;
|
typedef SkRefCnt INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
|
||||||
|
class SK_API SkStreamRewindable : public SkStream {
|
||||||
|
public:
|
||||||
|
//TODO: remove the following after everyone is updated (ensures new behavior on new classes).
|
||||||
|
virtual bool isAtEnd() const SK_OVERRIDE = 0;
|
||||||
|
//TODO: remove the following after everyone is updated (ensures new behavior on new classes).
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE { return 0; }
|
||||||
|
|
||||||
|
virtual bool rewind() SK_OVERRIDE = 0;
|
||||||
|
virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
|
||||||
|
class SK_API SkStreamSeekable : public SkStreamRewindable {
|
||||||
|
public:
|
||||||
|
virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0;
|
||||||
|
|
||||||
|
virtual bool hasPosition() const SK_OVERRIDE { return true; }
|
||||||
|
virtual size_t getPosition() const SK_OVERRIDE = 0;
|
||||||
|
virtual bool seek(size_t position) SK_OVERRIDE = 0;
|
||||||
|
virtual bool move(long offset) SK_OVERRIDE = 0;
|
||||||
|
virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
|
||||||
|
class SK_API SkStreamAsset : public SkStreamSeekable {
|
||||||
|
public:
|
||||||
|
virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0;
|
||||||
|
virtual SkStreamAsset* fork() const SK_OVERRIDE = 0;
|
||||||
|
|
||||||
|
virtual bool hasLength() const SK_OVERRIDE { return true; }
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
|
||||||
|
class SK_API SkStreamMemory : public SkStreamAsset {
|
||||||
|
public:
|
||||||
|
virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0;
|
||||||
|
virtual SkStreamMemory* fork() const SK_OVERRIDE = 0;
|
||||||
|
|
||||||
|
virtual const void* getMemoryBase() SK_OVERRIDE = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class SK_API SkWStream : SkNoncopyable {
|
class SK_API SkWStream : SkNoncopyable {
|
||||||
public:
|
public:
|
||||||
SK_DECLARE_INST_COUNT_ROOT(SkWStream)
|
SK_DECLARE_INST_COUNT_ROOT(SkWStream)
|
||||||
@ -147,81 +236,76 @@ public:
|
|||||||
|
|
||||||
struct SkFILE;
|
struct SkFILE;
|
||||||
|
|
||||||
/** A stream that reads from a FILE*, which is opened in the constructor and
|
/** A stream that wraps a C FILE* file stream. */
|
||||||
closed in the destructor
|
class SK_API SkFILEStream : public SkStreamAsset {
|
||||||
*/
|
|
||||||
class SK_API SkFILEStream : public SkStream {
|
|
||||||
public:
|
public:
|
||||||
SK_DECLARE_INST_COUNT(SkFILEStream)
|
SK_DECLARE_INST_COUNT(SkFILEStream)
|
||||||
|
|
||||||
/** Initialize the stream by calling fopen on the specified path. Will be
|
/** Initialize the stream by calling sk_fopen on the specified path.
|
||||||
closed in the destructor.
|
* This internal stream will be closed in the destructor.
|
||||||
*/
|
*/
|
||||||
explicit SkFILEStream(const char path[] = NULL);
|
explicit SkFILEStream(const char path[] = NULL);
|
||||||
|
|
||||||
|
enum Ownership {
|
||||||
|
kCallerPasses_Ownership,
|
||||||
|
kCallerRetains_Ownership
|
||||||
|
};
|
||||||
|
/** Initialize the stream with an existing C file stream.
|
||||||
|
* While this stream exists, it assumes exclusive access to the C file stream.
|
||||||
|
* The C file stream will be closed in the destructor unless the caller specifies
|
||||||
|
* kCallerRetains_Ownership.
|
||||||
|
*/
|
||||||
|
explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership);
|
||||||
|
|
||||||
virtual ~SkFILEStream();
|
virtual ~SkFILEStream();
|
||||||
|
|
||||||
/** Returns true if the current path could be opened.
|
/** Returns true if the current path could be opened. */
|
||||||
*/
|
|
||||||
bool isValid() const { return fFILE != NULL; }
|
bool isValid() const { return fFILE != NULL; }
|
||||||
/** Close the current file, and open a new file with the specified
|
|
||||||
path. If path is NULL, just close the current file.
|
/** Close the current file, and open a new file with the specified path.
|
||||||
*/
|
* If path is NULL, just close the current file.
|
||||||
|
*/
|
||||||
void setPath(const char path[]);
|
void setPath(const char path[]);
|
||||||
|
|
||||||
virtual bool rewind() SK_OVERRIDE;
|
|
||||||
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
||||||
virtual const char* getFileName() SK_OVERRIDE;
|
virtual bool isAtEnd() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool rewind() SK_OVERRIDE;
|
||||||
|
virtual SkStreamAsset* duplicate() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual size_t getPosition() const SK_OVERRIDE;
|
||||||
|
virtual bool seek(size_t position) SK_OVERRIDE;
|
||||||
|
virtual bool move(long offset) SK_OVERRIDE;
|
||||||
|
virtual SkStreamAsset* fork() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
const void* getMemoryBase() SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkFILE* fFILE;
|
SkFILE* fFILE;
|
||||||
SkString fName;
|
SkString fName;
|
||||||
|
Ownership fOwnership;
|
||||||
|
// fData is lazilly initialized when needed.
|
||||||
|
mutable SkAutoTUnref<SkData> fData;
|
||||||
|
|
||||||
typedef SkStream INHERITED;
|
typedef SkStreamAsset INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A stream that reads from a file descriptor
|
class SK_API SkMemoryStream : public SkStreamMemory {
|
||||||
*/
|
|
||||||
class SK_API SkFDStream : public SkStream {
|
|
||||||
public:
|
|
||||||
SK_DECLARE_INST_COUNT(SkFDStream)
|
|
||||||
|
|
||||||
/** Initialize the stream with a dup() of the specified file descriptor.
|
|
||||||
If closeWhenDone is true, then the descriptor will be closed in the
|
|
||||||
destructor.
|
|
||||||
*/
|
|
||||||
SkFDStream(int fileDesc, bool closeWhenDone);
|
|
||||||
virtual ~SkFDStream();
|
|
||||||
|
|
||||||
/** Returns true if the current path could be opened.
|
|
||||||
*/
|
|
||||||
bool isValid() const { return fFD >= 0; }
|
|
||||||
|
|
||||||
virtual bool rewind() SK_OVERRIDE;
|
|
||||||
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
|
||||||
virtual const char* getFileName() SK_OVERRIDE { return NULL; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int fFD;
|
|
||||||
bool fCloseWhenDone;
|
|
||||||
|
|
||||||
typedef SkStream INHERITED;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SK_API SkMemoryStream : public SkStream {
|
|
||||||
public:
|
public:
|
||||||
SK_DECLARE_INST_COUNT(SkMemoryStream)
|
SK_DECLARE_INST_COUNT(SkMemoryStream)
|
||||||
|
|
||||||
SkMemoryStream();
|
SkMemoryStream();
|
||||||
/** We allocate (and free) the memory. Write to it via getMemoryBase()
|
|
||||||
*/
|
/** We allocate (and free) the memory. Write to it via getMemoryBase() */
|
||||||
SkMemoryStream(size_t length);
|
SkMemoryStream(size_t length);
|
||||||
/** if copyData is true, the stream makes a private copy of the data
|
|
||||||
*/
|
/** If copyData is true, the stream makes a private copy of the data. */
|
||||||
SkMemoryStream(const void* data, size_t length, bool copyData = false);
|
SkMemoryStream(const void* data, size_t length, bool copyData = false);
|
||||||
|
|
||||||
/**
|
/** Use the specified data as the memory for this stream.
|
||||||
* Use the specified data as the memory for this stream. The stream will
|
* The stream will call ref() on the data (assuming it is not NULL).
|
||||||
* call ref() on the data (assuming it is not null).
|
|
||||||
*/
|
*/
|
||||||
SkMemoryStream(SkData*);
|
SkMemoryStream(SkData*);
|
||||||
|
|
||||||
@ -239,81 +323,42 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setMemoryOwned(const void* data, size_t length);
|
void setMemoryOwned(const void* data, size_t length);
|
||||||
|
|
||||||
/**
|
/** Return the stream's data in a SkData.
|
||||||
* Return the stream's data in a SkData. The caller must call unref() when
|
* The caller must call unref() when it is finished using the data.
|
||||||
* it is finished using the data.
|
|
||||||
*/
|
*/
|
||||||
SkData* copyToData() const;
|
SkData* copyToData() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the specified data as the memory for this stream. The stream will
|
* Use the specified data as the memory for this stream.
|
||||||
* call ref() on the data (assuming it is not null). The function returns
|
* The stream will call ref() on the data (assuming it is not NULL).
|
||||||
* the data parameter as a convenience.
|
* The function returns the data parameter as a convenience.
|
||||||
*/
|
*/
|
||||||
SkData* setData(SkData*);
|
SkData* setData(SkData*);
|
||||||
|
|
||||||
void skipToAlign4();
|
void skipToAlign4();
|
||||||
virtual bool rewind() SK_OVERRIDE;
|
|
||||||
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
|
||||||
virtual const void* getMemoryBase() SK_OVERRIDE;
|
|
||||||
const void* getAtPos();
|
const void* getAtPos();
|
||||||
size_t seek(size_t offset);
|
|
||||||
size_t peek() const { return fOffset; }
|
size_t peek() const { return fOffset; }
|
||||||
|
|
||||||
|
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
||||||
|
virtual bool isAtEnd() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool rewind() SK_OVERRIDE;
|
||||||
|
virtual SkMemoryStream* duplicate() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual size_t getPosition() const SK_OVERRIDE;
|
||||||
|
virtual bool seek(size_t position) SK_OVERRIDE;
|
||||||
|
virtual bool move(long offset) SK_OVERRIDE;
|
||||||
|
virtual SkMemoryStream* fork() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual const void* getMemoryBase() SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkData* fData;
|
SkData* fData;
|
||||||
size_t fOffset;
|
size_t fOffset;
|
||||||
|
|
||||||
typedef SkStream INHERITED;
|
typedef SkStreamMemory INHERITED;
|
||||||
};
|
|
||||||
|
|
||||||
/** \class SkBufferStream
|
|
||||||
This is a wrapper class that adds buffering to another stream.
|
|
||||||
The caller can provide the buffer, or ask SkBufferStream to allocated/free
|
|
||||||
it automatically.
|
|
||||||
*/
|
|
||||||
class SK_API SkBufferStream : public SkStream {
|
|
||||||
public:
|
|
||||||
SK_DECLARE_INST_COUNT(SkBufferStream)
|
|
||||||
|
|
||||||
/** Provide the stream to be buffered (proxy), and the size of the buffer that
|
|
||||||
should be used. This will be allocated and freed automatically. If bufferSize is 0,
|
|
||||||
a default buffer size will be used.
|
|
||||||
The proxy stream is referenced, and will be unreferenced in when the
|
|
||||||
bufferstream is destroyed.
|
|
||||||
*/
|
|
||||||
SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
|
|
||||||
/** Provide the stream to be buffered (proxy), and a buffer and size to be used.
|
|
||||||
This buffer is owned by the caller, and must be at least bufferSize bytes big.
|
|
||||||
Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
|
|
||||||
If buffer is not NULL, it is an error for bufferSize to be 0.
|
|
||||||
The proxy stream is referenced, and will be unreferenced in when the
|
|
||||||
bufferstream is destroyed.
|
|
||||||
*/
|
|
||||||
SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
|
|
||||||
virtual ~SkBufferStream();
|
|
||||||
|
|
||||||
virtual bool rewind() SK_OVERRIDE;
|
|
||||||
virtual const char* getFileName() SK_OVERRIDE;
|
|
||||||
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
|
||||||
virtual const void* getMemoryBase() SK_OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
kDefaultBufferSize = 128
|
|
||||||
};
|
|
||||||
// illegal
|
|
||||||
SkBufferStream(const SkBufferStream&);
|
|
||||||
SkBufferStream& operator=(const SkBufferStream&);
|
|
||||||
|
|
||||||
SkStream* fProxy;
|
|
||||||
char* fBuffer;
|
|
||||||
size_t fOrigBufferSize, fBufferSize, fBufferOffset;
|
|
||||||
bool fWeOwnTheBuffer;
|
|
||||||
|
|
||||||
void init(void*, size_t);
|
|
||||||
|
|
||||||
typedef SkStream INHERITED;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -9,16 +9,6 @@
|
|||||||
#include "SkFlattenableBuffers.h"
|
#include "SkFlattenableBuffers.h"
|
||||||
#include "SkOSFile.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)
|
SK_DEFINE_INST_COUNT(SkData)
|
||||||
|
|
||||||
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
|
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
|
||||||
@ -92,96 +82,27 @@ SkData* SkData::NewWithProc(const void* data, size_t length,
|
|||||||
return new SkData(data, length, proc, context);
|
return new SkData(data, length, proc, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assumes fPtr was allocated with sk_fmmap
|
||||||
|
static void sk_mmap_releaseproc(const void* addr, size_t length, void*) {
|
||||||
|
sk_fmunmap(addr, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkData* SkData::NewFromFILE(SkFILE* f) {
|
||||||
|
size_t size;
|
||||||
|
void* addr = sk_fmmap(f, &size);
|
||||||
|
if (NULL == addr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// assumes context is a SkData
|
// assumes context is a SkData
|
||||||
static void sk_dataref_releaseproc(const void*, size_t, void* context) {
|
static void sk_dataref_releaseproc(const void*, size_t, void* context) {
|
||||||
SkData* src = reinterpret_cast<SkData*>(context);
|
SkData* src = reinterpret_cast<SkData*>(context);
|
||||||
src->unref();
|
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 defined(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) {
|
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,
|
We could, if we wanted/need to, just make a deep copy of src's data,
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
#include "SkStream.h"
|
|
||||||
|
|
||||||
#ifdef SK_BUILD_FOR_WIN
|
|
||||||
|
|
||||||
// -1 means isValid() will return false
|
|
||||||
SkFDStream::SkFDStream(int, bool) : fFD(-1), fCloseWhenDone(false) {}
|
|
||||||
SkFDStream::~SkFDStream() {}
|
|
||||||
bool SkFDStream::rewind() { return false; }
|
|
||||||
size_t SkFDStream::read(void*, size_t) { return 0; }
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
//#define TRACE_FDSTREAM
|
|
||||||
|
|
||||||
SkFDStream::SkFDStream(int fileDesc, bool closeWhenDone)
|
|
||||||
: fFD(fileDesc), fCloseWhenDone(closeWhenDone) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SkFDStream::~SkFDStream() {
|
|
||||||
if (fFD >= 0 && fCloseWhenDone) {
|
|
||||||
::close(fFD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkFDStream::rewind() {
|
|
||||||
if (fFD >= 0) {
|
|
||||||
off_t value = ::lseek(fFD, 0, SEEK_SET);
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
if (value) {
|
|
||||||
SkDebugf("xxxxxxxxxxxxxx rewind failed %d\n", value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return value == 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SkFDStream::read(void* buffer, size_t size) {
|
|
||||||
if (fFD >= 0) {
|
|
||||||
if (buffer == NULL && size == 0) { // request total size
|
|
||||||
off_t curr = ::lseek(fFD, 0, SEEK_CUR);
|
|
||||||
if (curr < 0) {
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx lseek failed 0 CURR\n");
|
|
||||||
#endif
|
|
||||||
return 0; // error
|
|
||||||
}
|
|
||||||
off_t size = ::lseek(fFD, 0, SEEK_END);
|
|
||||||
if (size < 0) {
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx lseek failed 0 END\n");
|
|
||||||
#endif
|
|
||||||
size = 0; // error
|
|
||||||
}
|
|
||||||
if (::lseek(fFD, curr, SEEK_SET) != curr) {
|
|
||||||
// can't restore, error
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx lseek failed %d SET\n", curr);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (size_t) size;
|
|
||||||
} else if (NULL == buffer) { // skip
|
|
||||||
off_t oldCurr = ::lseek(fFD, 0, SEEK_CUR);
|
|
||||||
if (oldCurr < 0) {
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx lseek1 failed %d CUR\n", oldCurr);
|
|
||||||
#endif
|
|
||||||
return 0; // error;
|
|
||||||
}
|
|
||||||
off_t newCurr = ::lseek(fFD, size, SEEK_CUR);
|
|
||||||
if (newCurr < 0) {
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx lseek2 failed %d CUR\n", newCurr);
|
|
||||||
#endif
|
|
||||||
return 0; // error;
|
|
||||||
}
|
|
||||||
// return the actual amount we skipped
|
|
||||||
return (size_t) (newCurr - oldCurr);
|
|
||||||
} else { // read
|
|
||||||
ssize_t actual = ::read(fFD, buffer, size);
|
|
||||||
// our API can't return an error, so we return 0
|
|
||||||
if (actual < 0) {
|
|
||||||
#ifdef TRACE_FDSTREAM
|
|
||||||
SkDebugf("xxxxxxxxxxxxx read failed %d actual %d\n", size, actual);
|
|
||||||
#endif
|
|
||||||
actual = 0;
|
|
||||||
}
|
|
||||||
return actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -16,9 +16,7 @@
|
|||||||
SK_DEFINE_INST_COUNT(SkStream)
|
SK_DEFINE_INST_COUNT(SkStream)
|
||||||
SK_DEFINE_INST_COUNT(SkWStream)
|
SK_DEFINE_INST_COUNT(SkWStream)
|
||||||
SK_DEFINE_INST_COUNT(SkFILEStream)
|
SK_DEFINE_INST_COUNT(SkFILEStream)
|
||||||
SK_DEFINE_INST_COUNT(SkFDStream)
|
|
||||||
SK_DEFINE_INST_COUNT(SkMemoryStream)
|
SK_DEFINE_INST_COUNT(SkMemoryStream)
|
||||||
SK_DEFINE_INST_COUNT(SkBufferStream)
|
|
||||||
SK_DEFINE_INST_COUNT(SkFILEWStream)
|
SK_DEFINE_INST_COUNT(SkFILEWStream)
|
||||||
SK_DEFINE_INST_COUNT(SkMemoryWStream)
|
SK_DEFINE_INST_COUNT(SkMemoryWStream)
|
||||||
SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream)
|
SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream)
|
||||||
@ -26,26 +24,6 @@ SK_DEFINE_INST_COUNT(SkDebugWStream)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const char* SkStream::getFileName()
|
|
||||||
{
|
|
||||||
// override in subclass if you represent a file
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* SkStream::getMemoryBase()
|
|
||||||
{
|
|
||||||
// override in subclass if you represent a memory block
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SkStream::skip(size_t size)
|
|
||||||
{
|
|
||||||
/* Check for size == 0, and just return 0. If we passed that
|
|
||||||
to read(), it would interpret it as a request for the entire
|
|
||||||
size of the stream.
|
|
||||||
*/
|
|
||||||
return size ? this->read(NULL, size) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t SkStream::readS8() {
|
int8_t SkStream::readS8() {
|
||||||
int8_t value;
|
int8_t value;
|
||||||
@ -221,12 +199,17 @@ bool SkWStream::writeData(const SkData* data) {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkFILEStream::SkFILEStream(const char file[]) : fName(file) {
|
SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
|
||||||
fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
|
fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
|
||||||
|
: fFILE((SkFILE*)file)
|
||||||
|
, fOwnership(ownership) {
|
||||||
|
}
|
||||||
|
|
||||||
SkFILEStream::~SkFILEStream() {
|
SkFILEStream::~SkFILEStream() {
|
||||||
if (fFILE) {
|
if (fFILE && fOwnership != kCallerRetains_Ownership) {
|
||||||
sk_fclose(fFILE);
|
sk_fclose(fFILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,8 +225,15 @@ void SkFILEStream::setPath(const char path[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SkFILEStream::getFileName() {
|
size_t SkFILEStream::read(void* buffer, size_t size) {
|
||||||
return fName.c_str();
|
if (fFILE) {
|
||||||
|
return sk_fread(buffer, size, fFILE);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkFILEStream::isAtEnd() const {
|
||||||
|
return sk_feof(fFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkFILEStream::rewind() {
|
bool SkFILEStream::rewind() {
|
||||||
@ -258,15 +248,56 @@ bool SkFILEStream::rewind() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SkFILEStream::read(void* buffer, size_t size) {
|
SkStreamAsset* SkFILEStream::duplicate() const {
|
||||||
if (fFILE) {
|
if (NULL == fFILE) {
|
||||||
if (buffer == NULL && size == 0) { // special signature, they want the total size
|
return new SkMemoryStream();
|
||||||
return sk_fgetsize(fFILE);
|
}
|
||||||
} else {
|
|
||||||
return sk_fread(buffer, size, fFILE);
|
if (NULL != fData.get()) {
|
||||||
|
return new SkMemoryStream(fData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fName.isEmpty()) {
|
||||||
|
SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
|
||||||
|
if (sk_fidentical(that->fFILE, this->fFILE)) {
|
||||||
|
return that.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
fData.reset(SkData::NewFromFILE(fFILE));
|
||||||
|
if (NULL == fData.get()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new SkMemoryStream(fData);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkFILEStream::getPosition() const {
|
||||||
|
return sk_ftell(fFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkFILEStream::seek(size_t position) {
|
||||||
|
return sk_fseek(fFILE, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkFILEStream::move(long offset) {
|
||||||
|
return sk_fmove(fFILE, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkStreamAsset* SkFILEStream::fork() const {
|
||||||
|
SkAutoTUnref<SkStreamAsset> that(this->duplicate());
|
||||||
|
that->seek(this->getPosition());
|
||||||
|
return that.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkFILEStream::getLength() const {
|
||||||
|
return sk_fgetsize(fFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* SkFILEStream::getMemoryBase() {
|
||||||
|
if (NULL == fData.get()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return fData->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -341,22 +372,9 @@ void SkMemoryStream::skipToAlign4() {
|
|||||||
fOffset += -(int)fOffset & 0x03;
|
fOffset += -(int)fOffset & 0x03;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkMemoryStream::rewind() {
|
|
||||||
fOffset = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SkMemoryStream::read(void* buffer, size_t size) {
|
size_t SkMemoryStream::read(void* buffer, size_t size) {
|
||||||
size_t dataSize = fData->size();
|
size_t dataSize = fData->size();
|
||||||
|
|
||||||
if (buffer == NULL && size == 0) // special signature, they want the total size
|
|
||||||
return dataSize;
|
|
||||||
|
|
||||||
// if buffer is NULL, seek ahead by size
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (size > dataSize - fOffset) {
|
if (size > dataSize - fOffset) {
|
||||||
size = dataSize - fOffset;
|
size = dataSize - fOffset;
|
||||||
}
|
}
|
||||||
@ -367,6 +385,44 @@ size_t SkMemoryStream::read(void* buffer, size_t size) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkMemoryStream::isAtEnd() const {
|
||||||
|
return fOffset == fData->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkMemoryStream::rewind() {
|
||||||
|
fOffset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkMemoryStream* SkMemoryStream::duplicate() const {
|
||||||
|
return SkNEW_ARGS(SkMemoryStream, (fData));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkMemoryStream::getPosition() const {
|
||||||
|
return fOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkMemoryStream::seek(size_t position) {
|
||||||
|
fOffset = position > fData->size()
|
||||||
|
? fData->size()
|
||||||
|
: position;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkMemoryStream::move(long offset) {
|
||||||
|
return this->seek(fOffset + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkMemoryStream* SkMemoryStream::fork() const {
|
||||||
|
SkAutoTUnref<SkMemoryStream> that(this->duplicate());
|
||||||
|
that->seek(fOffset);
|
||||||
|
return that.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkMemoryStream::getLength() const {
|
||||||
|
return fData->size();
|
||||||
|
}
|
||||||
|
|
||||||
const void* SkMemoryStream::getMemoryBase() {
|
const void* SkMemoryStream::getMemoryBase() {
|
||||||
return fData->data();
|
return fData->data();
|
||||||
}
|
}
|
||||||
@ -375,165 +431,6 @@ const void* SkMemoryStream::getAtPos() {
|
|||||||
return fData->bytes() + fOffset;
|
return fData->bytes() + fOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SkMemoryStream::seek(size_t offset) {
|
|
||||||
if (offset > fData->size()) {
|
|
||||||
offset = fData->size();
|
|
||||||
}
|
|
||||||
fOffset = offset;
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
|
|
||||||
: fProxy(proxy)
|
|
||||||
{
|
|
||||||
SkASSERT(proxy != NULL);
|
|
||||||
proxy->ref();
|
|
||||||
this->init(NULL, bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
|
|
||||||
: fProxy(proxy)
|
|
||||||
{
|
|
||||||
SkASSERT(proxy != NULL);
|
|
||||||
SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no sense, we must know how big their buffer is
|
|
||||||
proxy->ref();
|
|
||||||
this->init(buffer, bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBufferStream::init(void* buffer, size_t bufferSize)
|
|
||||||
{
|
|
||||||
if (bufferSize == 0)
|
|
||||||
bufferSize = kDefaultBufferSize;
|
|
||||||
|
|
||||||
fOrigBufferSize = bufferSize;
|
|
||||||
fBufferSize = bufferSize;
|
|
||||||
fBufferOffset = bufferSize; // to trigger a reload on the first read()
|
|
||||||
|
|
||||||
if (buffer == NULL)
|
|
||||||
{
|
|
||||||
fBuffer = (char*)sk_malloc_throw(fBufferSize);
|
|
||||||
fWeOwnTheBuffer = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fBuffer = (char*)buffer;
|
|
||||||
fWeOwnTheBuffer = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SkBufferStream::~SkBufferStream()
|
|
||||||
{
|
|
||||||
fProxy->unref();
|
|
||||||
if (fWeOwnTheBuffer)
|
|
||||||
sk_free(fBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkBufferStream::rewind()
|
|
||||||
{
|
|
||||||
fBufferOffset = fBufferSize = fOrigBufferSize;
|
|
||||||
return fProxy->rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* SkBufferStream::getFileName()
|
|
||||||
{
|
|
||||||
return fProxy->getFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
// #define SK_TRACE_BUFFERSTREAM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t SkBufferStream::read(void* buffer, size_t size) {
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf("Request %d", size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (buffer == NULL && size == 0) {
|
|
||||||
return fProxy->read(buffer, size); // requesting total size
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip size bytes
|
|
||||||
if (NULL == buffer) {
|
|
||||||
size_t remaining = fBufferSize - fBufferOffset;
|
|
||||||
if (remaining >= size) {
|
|
||||||
fBufferOffset += size;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
// if we get here, we are being asked to skip beyond our current buffer
|
|
||||||
// so reset our offset to force a read next time, and skip the diff
|
|
||||||
// in our proxy
|
|
||||||
fBufferOffset = fOrigBufferSize;
|
|
||||||
return remaining + fProxy->read(NULL, size - remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t s = size;
|
|
||||||
size_t actuallyRead = 0;
|
|
||||||
|
|
||||||
// flush what we can from our fBuffer
|
|
||||||
if (fBufferOffset < fBufferSize)
|
|
||||||
{
|
|
||||||
if (s > fBufferSize - fBufferOffset)
|
|
||||||
s = fBufferSize - fBufferOffset;
|
|
||||||
memcpy(buffer, fBuffer + fBufferOffset, s);
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf(" flush %d", s);
|
|
||||||
#endif
|
|
||||||
size -= s;
|
|
||||||
fBufferOffset += s;
|
|
||||||
buffer = (char*)buffer + s;
|
|
||||||
actuallyRead = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if there is more to read
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
|
|
||||||
|
|
||||||
if (size < fBufferSize) // lets try to read more than the request
|
|
||||||
{
|
|
||||||
s = fProxy->read(fBuffer, fBufferSize);
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf(" read %d into fBuffer", s);
|
|
||||||
#endif
|
|
||||||
if (size > s) // they asked for too much
|
|
||||||
size = s;
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
memcpy(buffer, fBuffer, size);
|
|
||||||
actuallyRead += size;
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf(" memcpy %d into dst", size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fBufferOffset = size;
|
|
||||||
fBufferSize = s; // record the (possibly smaller) size for the buffer
|
|
||||||
}
|
|
||||||
else // just do a direct read
|
|
||||||
{
|
|
||||||
actuallyRead += fProxy->read(buffer, size);
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf(" direct read %d", size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef SK_TRACE_BUFFERSTREAM
|
|
||||||
SkDebugf("\n");
|
|
||||||
#endif
|
|
||||||
return actuallyRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* SkBufferStream::getMemoryBase()
|
|
||||||
{
|
|
||||||
return fProxy->getMemoryBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -800,7 +697,7 @@ static SkData* mmap_filename(const char path[]) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkStream* SkStream::NewFromFile(const char path[]) {
|
SkStreamAsset* SkStream::NewFromFile(const char path[]) {
|
||||||
SkAutoTUnref<SkData> data(mmap_filename(path));
|
SkAutoTUnref<SkData> data(mmap_filename(path));
|
||||||
if (data.get()) {
|
if (data.get()) {
|
||||||
return SkNEW_ARGS(SkMemoryStream, (data.get()));
|
return SkNEW_ARGS(SkMemoryStream, (data.get()));
|
||||||
|
@ -136,16 +136,30 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
|||||||
SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
|
SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
|
||||||
SkStream* stream = this->getLocalStream();
|
SkStream* stream = this->getLocalStream();
|
||||||
if (stream) {
|
if (stream) {
|
||||||
// TODO: fix issue 1176.
|
|
||||||
// As of now open_stream will return a stream and unwind it, but the
|
|
||||||
// SkStream is not thread safe, and if two threads use the stream they
|
|
||||||
// may collide and print preview for example could still fail,
|
|
||||||
// or there could be some failures in rendering if this stream is used
|
|
||||||
// there.
|
|
||||||
stream->rewind();
|
|
||||||
stream->ref();
|
|
||||||
// should have been provided by CreateFromStream()
|
// should have been provided by CreateFromStream()
|
||||||
*ttcIndex = 0;
|
*ttcIndex = 0;
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStream> dupStream(stream->duplicate());
|
||||||
|
if (dupStream) {
|
||||||
|
return dupStream.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: update interface use, remove the following code in this block.
|
||||||
|
size_t length = stream->getLength();
|
||||||
|
|
||||||
|
const void* memory = stream->getMemoryBase();
|
||||||
|
if (NULL != memory) {
|
||||||
|
return new SkMemoryStream(memory, length, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkAutoTMalloc<uint8_t> allocMemory(length);
|
||||||
|
stream->rewind();
|
||||||
|
if (length == stream->read(allocMemory.get(), length)) {
|
||||||
|
return new SkMemoryStream(allocMemory.detach(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->rewind();
|
||||||
|
stream->ref();
|
||||||
} else {
|
} else {
|
||||||
SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
|
SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
|
||||||
if (NULL == fci.get()) {
|
if (NULL == fci.get()) {
|
||||||
|
18
src/ports/SkOSFile_none.cpp
Normal file
18
src/ports/SkOSFile_none.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkOSFile.h"
|
||||||
|
|
||||||
|
bool sk_fidentical(SkFILE* a, SkFILE* b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_fmunmap(const void* addr, size_t length) { }
|
||||||
|
|
||||||
|
void* sk_fmmap(SkFILE* f, size_t* size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
63
src/ports/SkOSFile_posix.cpp
Normal file
63
src/ports/SkOSFile_posix.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkOSFile.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
dev_t dev;
|
||||||
|
ino_t ino;
|
||||||
|
} SkFILEID;
|
||||||
|
|
||||||
|
static bool sk_ino(SkFILE* a, SkFILEID* id) {
|
||||||
|
int fd = fileno((FILE*)a);
|
||||||
|
if (fd < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct stat status;
|
||||||
|
if (0 != fstat(fd, &status)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
id->dev = status.st_dev;
|
||||||
|
id->ino = status.st_ino;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sk_fidentical(SkFILE* a, SkFILE* b) {
|
||||||
|
SkFILEID aID, bID;
|
||||||
|
return sk_ino(a, &aID) && sk_ino(b, &bID)
|
||||||
|
&& aID.ino == bID.ino
|
||||||
|
&& aID.dev == bID.dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = fileno((FILE*)f);
|
||||||
|
if (fd < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* addr = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (MAP_FAILED == addr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = fileSize;
|
||||||
|
return addr;
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2006 The Android Open Source Project
|
* Copyright 2006 The Android Open Source Project
|
||||||
*
|
*
|
||||||
@ -6,7 +5,6 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "SkOSFile.h"
|
#include "SkOSFile.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -21,74 +19,65 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkFILE* sk_fopen(const char path[], SkFILE_Flags flags)
|
SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) {
|
||||||
{
|
|
||||||
char perm[4];
|
char perm[4];
|
||||||
char* p = perm;
|
char* p = perm;
|
||||||
|
|
||||||
if (flags & kRead_SkFILE_Flag)
|
if (flags & kRead_SkFILE_Flag) {
|
||||||
*p++ = 'r';
|
*p++ = 'r';
|
||||||
if (flags & kWrite_SkFILE_Flag)
|
}
|
||||||
|
if (flags & kWrite_SkFILE_Flag) {
|
||||||
*p++ = 'w';
|
*p++ = 'w';
|
||||||
|
}
|
||||||
*p++ = 'b';
|
*p++ = 'b';
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
//TODO: on Windows fopen is just ASCII or the current code page,
|
//TODO: on Windows fopen is just ASCII or the current code page,
|
||||||
//convert to utf16 and use _wfopen
|
//convert to utf16 and use _wfopen
|
||||||
SkFILE* f = (SkFILE*)::fopen(path, perm);
|
return (SkFILE*)::fopen(path, perm);
|
||||||
#if 0
|
|
||||||
if (NULL == f)
|
|
||||||
SkDebugf("sk_fopen failed for %s (%s), errno=%s\n", path, perm, strerror(errno));
|
|
||||||
#endif
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* sk_fgets(char* str, int size, SkFILE* f) {
|
char* sk_fgets(char* str, int size, SkFILE* f) {
|
||||||
return ::fgets(str, size, (FILE *)f);
|
return ::fgets(str, size, (FILE *)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sk_feof(SkFILE *f) {
|
int sk_feof(SkFILE *f) {
|
||||||
// no :: namespace qualifier because it breaks android
|
// no :: namespace qualifier because it breaks android
|
||||||
return feof((FILE *)f);
|
return feof((FILE *)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sk_fgetsize(SkFILE* f)
|
size_t sk_fgetsize(SkFILE* f) {
|
||||||
{
|
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
|
|
||||||
long curr = ::ftell((FILE*)f); // remember where we are
|
long curr = ::ftell((FILE*)f); // remember where we are
|
||||||
if (curr < 0) {
|
if (curr < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
::fseek((FILE*)f, 0, SEEK_END); // go to the end
|
|
||||||
long size = ::ftell((FILE*)f); // record the size
|
::fseek((FILE*)f, 0, SEEK_END); // go to the end
|
||||||
|
long size = ::ftell((FILE*)f); // record the size
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
::fseek((FILE*)f, curr, SEEK_SET); // go back to our prev loc
|
|
||||||
|
::fseek((FILE*)f, curr, SEEK_SET); // go back to our prev location
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sk_frewind(SkFILE* f)
|
bool sk_frewind(SkFILE* f) {
|
||||||
{
|
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
::rewind((FILE*)f);
|
::rewind((FILE*)f);
|
||||||
// ::fseek((FILE*)f, 0, SEEK_SET);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f)
|
size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f) {
|
||||||
{
|
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL) {
|
||||||
{
|
|
||||||
size_t curr = ::ftell((FILE*)f);
|
size_t curr = ::ftell((FILE*)f);
|
||||||
if ((long)curr == -1) {
|
if ((long)curr == -1) {
|
||||||
SkDEBUGF(("sk_fread: ftell(%p) returned -1 feof:%d ferror:%d\n", f, feof((FILE*)f), ferror((FILE*)f)));
|
SkDEBUGF(("sk_fread: ftell(%p) returned -1 feof:%d ferror:%d\n", f, feof((FILE*)f), ferror((FILE*)f)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// ::fseek((FILE*)f, (long)(curr + byteCount), SEEK_SET);
|
|
||||||
int err = ::fseek((FILE*)f, (long)byteCount, SEEK_CUR);
|
int err = ::fseek((FILE*)f, (long)byteCount, SEEK_CUR);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
SkDEBUGF(("sk_fread: fseek(%d) tell:%d failed with feof:%d ferror:%d returned:%d\n",
|
SkDEBUGF(("sk_fread: fseek(%d) tell:%d failed with feof:%d ferror:%d returned:%d\n",
|
||||||
@ -101,26 +90,40 @@ size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f)
|
|||||||
return ::fread(buffer, 1, byteCount, (FILE*)f);
|
return ::fread(buffer, 1, byteCount, (FILE*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f)
|
size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f) {
|
||||||
{
|
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
return ::fwrite(buffer, 1, byteCount, (FILE*)f);
|
return ::fwrite(buffer, 1, byteCount, (FILE*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_fflush(SkFILE* f)
|
void sk_fflush(SkFILE* f) {
|
||||||
{
|
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
::fflush((FILE*)f);
|
::fflush((FILE*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_fclose(SkFILE* f)
|
bool sk_fseek(SkFILE* f, size_t byteCount) {
|
||||||
{
|
int err = ::fseek((FILE*)f, (long)byteCount, SEEK_SET);
|
||||||
|
return err == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sk_fmove(SkFILE* f, long byteCount) {
|
||||||
|
int err = ::fseek((FILE*)f, byteCount, SEEK_CUR);
|
||||||
|
return err == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sk_ftell(SkFILE* f) {
|
||||||
|
long curr = ::ftell((FILE*)f);
|
||||||
|
if (curr < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_fclose(SkFILE* f) {
|
||||||
SkASSERT(f);
|
SkASSERT(f);
|
||||||
::fclose((FILE*)f);
|
::fclose((FILE*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sk_exists(const char *path)
|
bool sk_exists(const char *path) {
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return (0 == _access(path, 0));
|
return (0 == _access(path, 0));
|
||||||
#else
|
#else
|
||||||
@ -128,8 +131,7 @@ bool sk_exists(const char *path)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sk_isdir(const char *path)
|
bool sk_isdir(const char *path) {
|
||||||
{
|
|
||||||
struct stat status;
|
struct stat status;
|
||||||
if (0 != stat(path, &status)) {
|
if (0 != stat(path, &status)) {
|
||||||
return false;
|
return false;
|
||||||
@ -137,8 +139,7 @@ bool sk_isdir(const char *path)
|
|||||||
return SkToBool(status.st_mode & S_IFDIR);
|
return SkToBool(status.st_mode & S_IFDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sk_mkdir(const char* path)
|
bool sk_mkdir(const char* path) {
|
||||||
{
|
|
||||||
if (sk_isdir(path)) {
|
if (sk_isdir(path)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
99
src/ports/SkOSFile_win.cpp
Normal file
99
src/ports/SkOSFile_win.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkOSFile.h"
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ULONGLONG fVolume;
|
||||||
|
ULONGLONG fLsbSize;
|
||||||
|
ULONGLONG fMsbSize;
|
||||||
|
} SkFILEID;
|
||||||
|
|
||||||
|
static bool sk_ino(SkFILE* f, SkFILEID* id) {
|
||||||
|
int fileno = _fileno((FILE*)f);
|
||||||
|
if (fileno < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE file = (HANDLE)_get_osfhandle(fileno);
|
||||||
|
if (INVALID_HANDLE_VALUE == file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo.
|
||||||
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
|
if (0 == GetFileInformationByHandle(file, &info)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
id->fVolume = info.dwVolumeSerialNumber;
|
||||||
|
id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32);
|
||||||
|
id->fMsbSize = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sk_fidentical(SkFILE* a, SkFILE* b) {
|
||||||
|
SkFILEID aID, bID;
|
||||||
|
return sk_ino(a, &aID) && sk_ino(b, &bID)
|
||||||
|
&& aID.fLsbSize == bID.fLsbSize
|
||||||
|
&& aID.fMsbSize == bID.fMsbSize
|
||||||
|
&& aID.fVolume == bID.fVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = fileSize;
|
||||||
|
return addr;
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#include "SkTypes.h"
|
#include "SkTypes.h"
|
||||||
#include "SkDWriteFontFileStream.h"
|
#include "SkDWriteFontFileStream.h"
|
||||||
#include "SkHRESULT.h"
|
#include "SkHRESULT.h"
|
||||||
|
#include "SkTScopedComPtr.h"
|
||||||
|
|
||||||
#include <dwrite.h>
|
#include <dwrite.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -16,11 +17,10 @@
|
|||||||
// SkIDWriteFontFileStream
|
// SkIDWriteFontFileStream
|
||||||
|
|
||||||
SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
|
SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
|
||||||
: fFontFileStream(fontFileStream)
|
: fFontFileStream(SkRefComPtr(fontFileStream))
|
||||||
, fPos(0)
|
, fPos(0)
|
||||||
, fLockedMemory(NULL)
|
, fLockedMemory(NULL)
|
||||||
, fFragmentLock(NULL) {
|
, fFragmentLock(NULL) {
|
||||||
fontFileStream->AddRef();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkDWriteFontFileStream::~SkDWriteFontFileStream() {
|
SkDWriteFontFileStream::~SkDWriteFontFileStream() {
|
||||||
@ -29,44 +29,19 @@ SkDWriteFontFileStream::~SkDWriteFontFileStream() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* SkDWriteFontFileStream::getMemoryBase() {
|
|
||||||
if (fLockedMemory) {
|
|
||||||
return fLockedMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT64 fileSize;
|
|
||||||
HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
|
|
||||||
HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
|
|
||||||
"Could not lock file fragment.");
|
|
||||||
return fLockedMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkDWriteFontFileStream::rewind() {
|
|
||||||
fPos = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
|
size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
if (NULL == buffer) {
|
if (NULL == buffer) {
|
||||||
UINT64 realFileSize = 0;
|
size_t fileSize = this->getLength();
|
||||||
hr = fFontFileStream->GetFileSize(&realFileSize);
|
|
||||||
if (realFileSize > (std::numeric_limits<size_t>::max)()) {
|
if (fPos + size > fileSize) {
|
||||||
return 0;
|
size_t skipped = fileSize - fPos;
|
||||||
}
|
fPos = fileSize;
|
||||||
size_t fileSize = static_cast<size_t>(realFileSize);
|
return skipped;
|
||||||
if (size == 0) {
|
|
||||||
return fileSize;
|
|
||||||
} else {
|
} else {
|
||||||
if (fPos + size > fileSize) {
|
fPos += size;
|
||||||
size_t skipped = fileSize - fPos;
|
return size;
|
||||||
fPos = fileSize;
|
|
||||||
return skipped;
|
|
||||||
} else {
|
|
||||||
fPos += size;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,28 +56,78 @@ size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//The read may have failed because we asked for too much data.
|
//The read may have failed because we asked for too much data.
|
||||||
|
size_t fileSize = this->getLength();
|
||||||
|
if (fPos + size <= fileSize) {
|
||||||
|
//This means we were within bounds, but failed for some other reason.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read = fileSize - fPos;
|
||||||
|
hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
memcpy(buffer, start, read);
|
||||||
|
fFontFileStream->ReleaseFileFragment(fragmentLock);
|
||||||
|
fPos = fileSize;
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkDWriteFontFileStream::isAtEnd() const {
|
||||||
|
return fPos == this->getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkDWriteFontFileStream::rewind() {
|
||||||
|
fPos = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const {
|
||||||
|
return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkDWriteFontFileStream::getPosition() const {
|
||||||
|
return fPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkDWriteFontFileStream::seek(size_t position) {
|
||||||
|
size_t length = this->getLength();
|
||||||
|
fPos = (position > length) ? length : position;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkDWriteFontFileStream::move(long offset) {
|
||||||
|
return seek(fPos + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkDWriteFontFileStream* SkDWriteFontFileStream::fork() const {
|
||||||
|
SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate());
|
||||||
|
that->seek(fPos);
|
||||||
|
return that.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SkDWriteFontFileStream::getLength() const {
|
||||||
|
HRESULT hr = S_OK;
|
||||||
UINT64 realFileSize = 0;
|
UINT64 realFileSize = 0;
|
||||||
hr = fFontFileStream->GetFileSize(&realFileSize);
|
hr = fFontFileStream->GetFileSize(&realFileSize);
|
||||||
if (realFileSize > (std::numeric_limits<size_t>::max)()) {
|
if (realFileSize > (std::numeric_limits<size_t>::max)()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t fileSize = static_cast<size_t>(realFileSize);
|
return static_cast<size_t>(realFileSize);
|
||||||
if (fPos + size > fileSize) {
|
|
||||||
size_t read = fileSize - fPos;
|
|
||||||
hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
memcpy(buffer, start, read);
|
|
||||||
fFontFileStream->ReleaseFileFragment(fragmentLock);
|
|
||||||
fPos = fileSize;
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
//This means we were within bounds, but failed for some other reason.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* SkDWriteFontFileStream::getMemoryBase() {
|
||||||
|
if (fLockedMemory) {
|
||||||
|
return fLockedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64 fileSize;
|
||||||
|
HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
|
||||||
|
HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
|
||||||
|
"Could not lock file fragment.");
|
||||||
|
return fLockedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SkIDWriteFontFileStreamWrapper
|
// SkIDWriteFontFileStreamWrapper
|
||||||
@ -116,8 +141,7 @@ HRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
|
SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
|
||||||
: fRefCount(1), fStream(stream) {
|
: fRefCount(1), fStream(SkRef(stream)) {
|
||||||
stream->ref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
|
HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
|
||||||
@ -180,7 +204,7 @@ HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
|
|||||||
if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
|
if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
SkAutoTDeleteArray<uint8_t> streamData(new uint8_t[static_cast<size_t>(fragmentSize)]);
|
SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
|
||||||
if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
|
if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
@ -192,10 +216,7 @@ HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
|
void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
|
||||||
if (NULL == fragmentContext) {
|
sk_free(fragmentContext);
|
||||||
return;
|
|
||||||
}
|
|
||||||
delete [] fragmentContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
|
HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
|
||||||
|
@ -19,13 +19,20 @@
|
|||||||
* An SkStream backed by an IDWriteFontFileStream.
|
* An SkStream backed by an IDWriteFontFileStream.
|
||||||
* This allows Skia code to read an IDWriteFontFileStream.
|
* This allows Skia code to read an IDWriteFontFileStream.
|
||||||
*/
|
*/
|
||||||
class SkDWriteFontFileStream : public SkStream {
|
class SkDWriteFontFileStream : public SkStreamMemory {
|
||||||
public:
|
public:
|
||||||
explicit SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream);
|
explicit SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream);
|
||||||
virtual ~SkDWriteFontFileStream();
|
virtual ~SkDWriteFontFileStream();
|
||||||
|
|
||||||
virtual bool rewind() SK_OVERRIDE;
|
|
||||||
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
|
||||||
|
virtual bool isAtEnd() const SK_OVERRIDE;
|
||||||
|
virtual bool rewind() SK_OVERRIDE;
|
||||||
|
virtual SkDWriteFontFileStream* duplicate() const SK_OVERRIDE;
|
||||||
|
virtual size_t getPosition() const SK_OVERRIDE;
|
||||||
|
virtual bool seek(size_t position) SK_OVERRIDE;
|
||||||
|
virtual bool move(long offset) SK_OVERRIDE;
|
||||||
|
virtual SkDWriteFontFileStream* fork() const SK_OVERRIDE;
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE;
|
||||||
virtual const void* getMemoryBase() SK_OVERRIDE;
|
virtual const void* getMemoryBase() SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
#include "SkRandom.h"
|
#include "SkRandom.h"
|
||||||
|
#include "SkOSFile.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
|
|
||||||
@ -17,67 +18,6 @@
|
|||||||
|
|
||||||
#define MAX_SIZE (256 * 1024)
|
#define MAX_SIZE (256 * 1024)
|
||||||
|
|
||||||
static void random_fill(SkMWCRandom& rand, void* buffer, size_t size) {
|
|
||||||
char* p = (char*)buffer;
|
|
||||||
char* stop = p + size;
|
|
||||||
while (p < stop) {
|
|
||||||
*p++ = (char)(rand.nextU() >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_buffer(skiatest::Reporter* reporter) {
|
|
||||||
SkMWCRandom rand;
|
|
||||||
SkAutoMalloc am(MAX_SIZE * 2);
|
|
||||||
char* storage = (char*)am.get();
|
|
||||||
char* storage2 = storage + MAX_SIZE;
|
|
||||||
|
|
||||||
random_fill(rand, storage, MAX_SIZE);
|
|
||||||
|
|
||||||
for (int sizeTimes = 0; sizeTimes < 100; sizeTimes++) {
|
|
||||||
int size = rand.nextU() % MAX_SIZE;
|
|
||||||
if (size == 0) {
|
|
||||||
size = MAX_SIZE;
|
|
||||||
}
|
|
||||||
for (int times = 0; times < 100; times++) {
|
|
||||||
int bufferSize = 1 + (rand.nextU() & 0xFFFF);
|
|
||||||
SkMemoryStream mstream(storage, size);
|
|
||||||
SkBufferStream bstream(&mstream, bufferSize);
|
|
||||||
|
|
||||||
int bytesRead = 0;
|
|
||||||
while (bytesRead < size) {
|
|
||||||
int s = 17 + (rand.nextU() & 0xFFFF);
|
|
||||||
int ss = bstream.read(storage2, s);
|
|
||||||
REPORTER_ASSERT(reporter, ss > 0 && ss <= s);
|
|
||||||
REPORTER_ASSERT(reporter, bytesRead + ss <= size);
|
|
||||||
REPORTER_ASSERT(reporter,
|
|
||||||
memcmp(storage + bytesRead, storage2, ss) == 0);
|
|
||||||
bytesRead += ss;
|
|
||||||
}
|
|
||||||
REPORTER_ASSERT(reporter, bytesRead == size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestRStream(skiatest::Reporter* reporter) {
|
|
||||||
static const char s[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
||||||
char copy[sizeof(s)];
|
|
||||||
SkMWCRandom rand;
|
|
||||||
|
|
||||||
for (int i = 0; i < 65; i++) {
|
|
||||||
char* copyPtr = copy;
|
|
||||||
SkMemoryStream mem(s, sizeof(s));
|
|
||||||
SkBufferStream buff(&mem, i);
|
|
||||||
|
|
||||||
do {
|
|
||||||
copyPtr += buff.read(copyPtr, rand.nextU() & 15);
|
|
||||||
} while (copyPtr < copy + sizeof(s));
|
|
||||||
REPORTER_ASSERT(reporter, copyPtr == copy + sizeof(s));
|
|
||||||
REPORTER_ASSERT(reporter, memcmp(s, copy, sizeof(s)) == 0);
|
|
||||||
}
|
|
||||||
test_buffer(reporter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
|
static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
|
||||||
const void* src, size_t len, int repeat) {
|
const void* src, size_t len, int repeat) {
|
||||||
SkAutoSMalloc<256> storage(len);
|
SkAutoSMalloc<256> storage(len);
|
||||||
@ -118,16 +58,20 @@ static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
|
|||||||
SkFILEStream stream(path.c_str());
|
SkFILEStream stream(path.c_str());
|
||||||
REPORTER_ASSERT(reporter, stream.isValid());
|
REPORTER_ASSERT(reporter, stream.isValid());
|
||||||
test_loop_stream(reporter, &stream, s, 26, 100);
|
test_loop_stream(reporter, &stream, s, 26, 100);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
|
||||||
|
test_loop_stream(reporter, stream2.get(), s, 26, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SK_BUILD_FOR_WIN
|
|
||||||
{
|
{
|
||||||
int fd = ::open(path.c_str(), O_RDONLY);
|
FILE* file = ::fopen(path.c_str(), "rb");
|
||||||
SkFDStream stream(fd, true);
|
SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
|
||||||
REPORTER_ASSERT(reporter, stream.isValid());
|
REPORTER_ASSERT(reporter, stream.isValid());
|
||||||
test_loop_stream(reporter, &stream, s, 26, 100);
|
test_loop_stream(reporter, &stream, s, 26, 100);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
|
||||||
|
test_loop_stream(reporter, stream2.get(), s, 26, 100);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TestWStream(skiatest::Reporter* reporter) {
|
static void TestWStream(skiatest::Reporter* reporter) {
|
||||||
@ -142,7 +86,6 @@ static void TestWStream(skiatest::Reporter* reporter) {
|
|||||||
dst[100*26] = '*';
|
dst[100*26] = '*';
|
||||||
ds.copyTo(dst);
|
ds.copyTo(dst);
|
||||||
REPORTER_ASSERT(reporter, dst[100*26] == '*');
|
REPORTER_ASSERT(reporter, dst[100*26] == '*');
|
||||||
// char* p = dst;
|
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
|
REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
|
||||||
}
|
}
|
||||||
@ -210,7 +153,6 @@ static void TestNullData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void TestStreams(skiatest::Reporter* reporter) {
|
static void TestStreams(skiatest::Reporter* reporter) {
|
||||||
TestRStream(reporter);
|
|
||||||
TestWStream(reporter);
|
TestWStream(reporter);
|
||||||
TestPackedUInt(reporter);
|
TestPackedUInt(reporter);
|
||||||
TestNullData();
|
TestNullData();
|
||||||
|
Loading…
Reference in New Issue
Block a user