c65328720a789051e49be9d41d4a0a6866a022fc
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkData.cpp
1 /*
2  * 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.
6  */
7
8 #include "SkData.h"
9 #include "SkLazyPtr.h"
10 #include "SkOSFile.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
13
14 SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
15     fPtr = ptr;
16     fSize = size;
17     fReleaseProc = proc;
18     fReleaseProcContext = context;
19 }
20
21 SkData::~SkData() {
22     if (fReleaseProc) {
23         fReleaseProc(fPtr, fSize, fReleaseProcContext);
24     }
25 }
26
27 bool SkData::equals(const SkData* other) const {
28     if (NULL == other) {
29         return false;
30     }
31
32     return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
33 }
34
35 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
36     size_t available = fSize;
37     if (offset >= available || 0 == length) {
38         return 0;
39     }
40     available -= offset;
41     if (length > available) {
42         length = available;
43     }
44     SkASSERT(length > 0);
45
46     memcpy(buffer, this->bytes() + offset, length);
47     return length;
48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51
52 SkData* SkData::NewEmptyImpl() {
53     return new SkData(NULL, 0, NULL, NULL);
54 }
55 void SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); }
56
57 SkData* SkData::NewEmpty() {
58     SK_DECLARE_STATIC_LAZY_PTR(SkData, empty, NewEmptyImpl, DeleteEmpty);
59     return SkRef(empty.get());
60 }
61
62 // assumes fPtr was allocated via sk_malloc
63 static void sk_free_releaseproc(const void* ptr, size_t, void*) {
64     sk_free((void*)ptr);
65 }
66
67 SkData* SkData::NewFromMalloc(const void* data, size_t length) {
68     return new SkData(data, length, sk_free_releaseproc, NULL);
69 }
70
71 SkData* SkData::NewWithCopy(const void* data, size_t length) {
72     if (0 == length) {
73         return SkData::NewEmpty();
74     }
75
76     void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
77     memcpy(copy, data, length);
78     return new SkData(copy, length, sk_free_releaseproc, NULL);
79 }
80
81 SkData* SkData::NewWithProc(const void* data, size_t length,
82                             ReleaseProc proc, void* context) {
83     return new SkData(data, length, proc, context);
84 }
85
86 // assumes fPtr was allocated with sk_fmmap
87 static void sk_mmap_releaseproc(const void* addr, size_t length, void*) {
88     sk_fmunmap(addr, length);
89 }
90
91 SkData* SkData::NewFromFILE(SkFILE* f) {
92     size_t size;
93     void* addr = sk_fmmap(f, &size);
94     if (NULL == addr) {
95         return NULL;
96     }
97
98     return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
99 }
100
101 SkData* SkData::NewFromFileName(const char path[]) {
102     SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL;
103     if (NULL == f) {
104         return NULL;
105     }
106     SkData* data = NewFromFILE(f);
107     sk_fclose(f);
108     return data;
109 }
110
111 SkData* SkData::NewFromFD(int fd) {
112     size_t size;
113     void* addr = sk_fdmmap(fd, &size);
114     if (NULL == addr) {
115         return NULL;
116     }
117
118     return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
119 }
120
121 // assumes context is a SkData
122 static void sk_dataref_releaseproc(const void*, size_t, void* context) {
123     SkData* src = reinterpret_cast<SkData*>(context);
124     src->unref();
125 }
126
127 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
128     /*
129         We could, if we wanted/need to, just make a deep copy of src's data,
130         rather than referencing it. This would duplicate the storage (of the
131         subset amount) but would possibly allow src to go out of scope sooner.
132      */
133
134     size_t available = src->size();
135     if (offset >= available || 0 == length) {
136         return SkData::NewEmpty();
137     }
138     available -= offset;
139     if (length > available) {
140         length = available;
141     }
142     SkASSERT(length > 0);
143
144     src->ref(); // this will be balanced in sk_dataref_releaseproc
145     return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
146                          const_cast<SkData*>(src));
147 }
148
149 SkData* SkData::NewWithCString(const char cstr[]) {
150     size_t size;
151     if (NULL == cstr) {
152         cstr = "";
153         size = 1;
154     } else {
155         size = strlen(cstr) + 1;
156     }
157     return NewWithCopy(cstr, size);
158 }