blob: fd963a9ff50b22aedf2d18f30ee6880e08afd598 [file] [log] [blame]
reed@google.com3a31ac12011-06-24 13:11:05 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@google.com3a31ac12011-06-24 13:11:05 +00006 */
7
reed@google.com3a31ac12011-06-24 13:11:05 +00008#include "SkData.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00009#include "SkFlattenableBuffers.h"
commit-bot@chromium.org9711e442013-04-24 20:03:00 +000010#include "SkOSFile.h"
commit-bot@chromium.org1f81fd62013-10-23 14:44:08 +000011#include "SkOnce.h"
reed@google.com3a31ac12011-06-24 13:11:05 +000012
13SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
14 fPtr = ptr;
15 fSize = size;
16 fReleaseProc = proc;
17 fReleaseProcContext = context;
18}
19
20SkData::~SkData() {
21 if (fReleaseProc) {
22 fReleaseProc(fPtr, fSize, fReleaseProcContext);
23 }
24}
25
reed@google.comdbc936d2012-06-28 15:40:09 +000026bool SkData::equals(const SkData* other) const {
27 if (NULL == other) {
28 return false;
29 }
30
31 return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
32}
33
reed@google.com3a31ac12011-06-24 13:11:05 +000034size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
35 size_t available = fSize;
36 if (offset >= available || 0 == length) {
37 return 0;
38 }
39 available -= offset;
40 if (length > available) {
41 length = available;
42 }
43 SkASSERT(length > 0);
44
45 memcpy(buffer, this->bytes() + offset, length);
46 return length;
47}
48
49///////////////////////////////////////////////////////////////////////////////
50
commit-bot@chromium.org1f81fd62013-10-23 14:44:08 +000051void SkData::NewEmptyImpl(SkData** empty) {
52 *empty = new SkData(NULL, 0, NULL, NULL);
53}
54
reed@google.com3a31ac12011-06-24 13:11:05 +000055SkData* SkData::NewEmpty() {
56 static SkData* gEmptyRef;
commit-bot@chromium.org1f81fd62013-10-23 14:44:08 +000057 SK_DECLARE_STATIC_ONCE(once);
58 SkOnce(&once, SkData::NewEmptyImpl, &gEmptyRef);
reed@google.com3a31ac12011-06-24 13:11:05 +000059 gEmptyRef->ref();
60 return gEmptyRef;
61}
62
63// assumes fPtr was allocated via sk_malloc
reed@google.com8a85d0c2011-06-24 19:12:12 +000064static void sk_free_releaseproc(const void* ptr, size_t, void*) {
reed@google.com3a31ac12011-06-24 13:11:05 +000065 sk_free((void*)ptr);
66}
67
reed@google.com8a85d0c2011-06-24 19:12:12 +000068SkData* SkData::NewFromMalloc(const void* data, size_t length) {
69 return new SkData(data, length, sk_free_releaseproc, NULL);
70}
71
reed@google.com3a31ac12011-06-24 13:11:05 +000072SkData* SkData::NewWithCopy(const void* data, size_t length) {
73 if (0 == length) {
74 return SkData::NewEmpty();
75 }
76
reed@google.com8a85d0c2011-06-24 19:12:12 +000077 void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
reed@google.com3a31ac12011-06-24 13:11:05 +000078 memcpy(copy, data, length);
reed@google.com8a85d0c2011-06-24 19:12:12 +000079 return new SkData(copy, length, sk_free_releaseproc, NULL);
reed@google.com3a31ac12011-06-24 13:11:05 +000080}
81
82SkData* SkData::NewWithProc(const void* data, size_t length,
reed@google.com8a85d0c2011-06-24 19:12:12 +000083 ReleaseProc proc, void* context) {
reed@google.com3a31ac12011-06-24 13:11:05 +000084 return new SkData(data, length, proc, context);
85}
86
bungeman@google.com6cab1a42013-05-29 13:43:31 +000087// assumes fPtr was allocated with sk_fmmap
88static void sk_mmap_releaseproc(const void* addr, size_t length, void*) {
89 sk_fmunmap(addr, length);
90}
91
92SkData* SkData::NewFromFILE(SkFILE* f) {
93 size_t size;
94 void* addr = sk_fmmap(f, &size);
95 if (NULL == addr) {
96 return NULL;
97 }
98
99 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
100}
101
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000102SkData* SkData::NewFromFileName(const char path[]) {
103 SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL;
104 if (NULL == f) {
105 return NULL;
106 }
107 SkData* data = NewFromFILE(f);
108 sk_fclose(f);
109 return data;
110}
111
bungeman@google.com11c9a552013-06-03 17:10:35 +0000112SkData* SkData::NewFromFD(int fd) {
113 size_t size;
114 void* addr = sk_fdmmap(fd, &size);
115 if (NULL == addr) {
116 return NULL;
117 }
118
119 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
120}
121
reed@google.com3a31ac12011-06-24 13:11:05 +0000122// assumes context is a SkData
123static void sk_dataref_releaseproc(const void*, size_t, void* context) {
124 SkData* src = reinterpret_cast<SkData*>(context);
125 src->unref();
126}
127
128SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
129 /*
130 We could, if we wanted/need to, just make a deep copy of src's data,
131 rather than referencing it. This would duplicate the storage (of the
132 subset amount) but would possibly allow src to go out of scope sooner.
133 */
134
135 size_t available = src->size();
136 if (offset >= available || 0 == length) {
137 return SkData::NewEmpty();
138 }
139 available -= offset;
140 if (length > available) {
141 length = available;
142 }
143 SkASSERT(length > 0);
144
145 src->ref(); // this will be balanced in sk_dataref_releaseproc
146 return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
147 const_cast<SkData*>(src));
148}
149
reed@google.comdbc936d2012-06-28 15:40:09 +0000150SkData* SkData::NewWithCString(const char cstr[]) {
reed@google.comfd59d122012-07-02 20:28:31 +0000151 size_t size;
152 if (NULL == cstr) {
153 cstr = "";
154 size = 1;
reed@google.comdbc936d2012-06-28 15:40:09 +0000155 } else {
reed@google.comfd59d122012-07-02 20:28:31 +0000156 size = strlen(cstr) + 1;
reed@google.comdbc936d2012-06-28 15:40:09 +0000157 }
reed@google.comfd59d122012-07-02 20:28:31 +0000158 return NewWithCopy(cstr, size);
reed@google.comdbc936d2012-06-28 15:40:09 +0000159}