blob: acdc9a71f0f136b78790198b4d916c5c8b1fc77a [file] [log] [blame]
mike@reedtribe.org0f175a62012-01-02 00:34:50 +00001/*
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 "SkJSON.h"
9#include "SkString.h"
10
11struct SkJSON::Object::Slot {
12 Slot(const char name[], Type type) {
13 fNext = NULL;
14
15 size_t len = strlen(name);
16 char* str = new char[len + 2];
17 str[0] = (char)type;
18 memcpy(str + 1, name, len + 1);
19 fName = str;
20
21 // fValue is uninitialized
22 }
23 ~Slot();
24
25 const char* name() const {
26 return fName ? &fName[1] : "";
27 }
28
29 Type type() const {
30 return (Type)fName[0];
31 }
32
33 Slot* fNext;
34 char* fName; // fName[0] is the type
35 union {
36 SkJSON::Object* fObject;
37 SkJSON::Array* fArray;
38 char* fString;
39 int32_t fInt;
40 float fFloat;
41 bool fBool;
42 intptr_t fIntPtr; // for generic getter
43 } fValue;
44};
45
46SkJSON::Object::Slot::~Slot() {
47 switch (this->type()) {
48 case kObject:
49 delete fValue.fObject;
50 break;
51 case kArray:
52 case kString:
53 delete[] fValue.fString;
54 break;
55 default:
56 break;
57 }
58 delete[] fName;
59}
60
61///////////////////////////////////////////////////////////////////////////////
62
63SkJSON::Object::~Object() {
64 Slot* slot = fHead;
65 while (slot) {
66 Slot* next = slot->fNext;
67 delete slot;
68 slot = next;
69 }
70}
71
72SkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) {
73 SkASSERT(NULL == slot->fNext);
74 if (NULL == fHead) {
75 SkASSERT(NULL == fTail);
76 fHead = fTail = slot;
77 } else {
78 SkASSERT(fTail);
79 SkASSERT(NULL == fTail->fNext);
80 fTail->fNext = slot;
81 fTail = slot;
82 }
83}
84
85void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) {
86 Slot* slot = addSlot(new Slot(name, kObject));
87 fTail->fValue.fObject = value;
88}
89
90void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) {
91 Slot* slot = addSlot(new Slot(name, kArray));
92 fTail->fValue.fArray = value;
93}
94
95void SkJSON::Object::addString(const char name[], const char value[]) {
96 Slot* slot = addSlot(new Slot(name, kString));
97 size_t len = strlen(value);
98 char* str = new char[len + 1];
99 memcpy(str, value, len + 1);
100 slot->fValue.fString = str;
101}
102
103void SkJSON::Object::addInt(const char name[], int32_t value) {
104 Slot* slot = addSlot(new Slot(name, kInt));
105 fTail->fValue.fInt = value;
106}
107
108void SkJSON::Object::addFloat(const char name[], float value) {
109 Slot* slot = addSlot(new Slot(name, kFloat));
110 fTail->fValue.fFloat = value;
111}
112
113void SkJSON::Object::addBool(const char name[], bool value) {
114 Slot* slot = addSlot(new Slot(name, kBool));
115 fTail->fValue.fBool = value;
116}
117
118///////////////////////////////////////////////////////////////////////////////
119
120const SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[]) const {
121 for (const Slot* slot = fHead; slot; slot = slot->fNext) {
122 if (!strcmp(slot->name(), name)) {
123 return slot;
124 }
125 }
126 return NULL;
127}
128
129const SkJSON::Object::Slot* SkJSON::Object::findSlotAndType(const char name[],
130 Type t) const {
131 const Slot* slot = this->findSlot(name);
132 if (slot && (slot->type() != t)) {
133 slot = NULL;
134 }
135 return slot;
136}
137
138bool SkJSON::Object::findString(const char name[], SkString* value) const {
139 const Slot* slot = this->findSlotAndType(name, kString);
140 if (slot) {
141 if (value) {
142 value->set(slot->fValue.fString);
143 }
144 return true;
145 }
146 return false;
147}
148
149bool SkJSON::Object::findInt(const char name[], int32_t* value) const {
150 const Slot* slot = this->findSlotAndType(name, kInt);
151 if (slot) {
152 if (value) {
153 *value = slot->fValue.fInt;
154 }
155 return true;
156 }
157 return false;
158}
159
160bool SkJSON::Object::findFloat(const char name[], float* value) const {
161 const Slot* slot = this->findSlotAndType(name, kFloat);
162 if (slot) {
163 if (value) {
164 *value = slot->fValue.fFloat;
165 }
166 return true;
167 }
168 return false;
169}
170
171bool SkJSON::Object::findBool(const char name[], bool* value) const {
172 const Slot* slot = this->findSlotAndType(name, kBool);
173 if (slot) {
174 if (value) {
175 *value = slot->fValue.fBool;
176 }
177 return true;
178 }
179 return false;
180}
181
182bool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const {
183 const Slot* slot = this->findSlotAndType(name, kObject);
184 if (slot) {
185 if (value) {
186 *value = slot->fValue.fObject;
187 }
188 return true;
189 }
190 return false;
191}
192
193///////////////////////////////////////////////////////////////////////////////
194
195static void tabForLevel(int level) {
196 for (int i = 0; i < level; ++i) {
197 SkDebugf(" ");
198 }
199}
200
201void SkJSON::Object::dump() const {
202 SkDebugf("{\n");
203 this->dumpLevel(0);
204 SkDebugf("}\n");
205}
206
207void SkJSON::Object::dumpLevel(int level) const {
208 for (Slot* slot = fHead; slot; slot = slot->fNext) {
209 Type t = slot->type();
210 tabForLevel(level + 1);
211 SkDebugf("\"%s\" : ", slot->name());
212 switch (slot->type()) {
213 case kObject:
214 if (slot->fValue.fObject) {
215 SkDebugf("{\n");
216 slot->fValue.fObject->dumpLevel(level + 1);
217 tabForLevel(level + 1);
218 SkDebugf("}");
219 } else {
220 SkDebugf("null");
221 }
222 break;
223 case kArray:
224 if (slot->fValue.fArray) {
225 SkDebugf("[");
226 slot->fValue.fArray->dumpLevel(level + 1);
227 SkDebugf("]");
228 } else {
229 SkDebugf("null");
230 }
231 break;
232 case kString:
233 SkDebugf("\"%s\"", slot->fValue.fString);
234 break;
235 case kInt:
236 SkDebugf("%d", slot->fValue.fInt);
237 break;
238 case kFloat:
239 SkDebugf("%g", slot->fValue.fFloat);
240 break;
241 case kBool:
242 SkDebugf("%s", slot->fValue.fBool ? "true" : "false");
243 break;
244 default:
245 SkASSERT(!"how did I get here");
246 break;
247 }
248 if (slot->fNext) {
249 SkDebugf(",");
250 }
251 SkDebugf("\n");
252 }
253}
254
255void SkJSON::Array::dumpLevel(int level) const {
256 if (0 == fCount) {
257 return;
258 }
259 int last = fCount - 1;
260
261 switch (this->type()) {
262 case kInt: {
263 for (int i = 0; i < last; ++i) {
264 SkDebugf(" %d,", fArray.fInts[i]);
265 }
266 SkDebugf(" %d ", fArray.fInts[last]);
267 } break;
268 case kFloat: {
269 for (int i = 0; i < last; ++i) {
270 SkDebugf(" %g,", fArray.fFloats[i]);
271 }
272 SkDebugf(" %g ", fArray.fFloats[last]);
273 } break;
274 case kBool: {
275 for (int i = 0; i < last; ++i) {
276 SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false");
277 }
278 SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false");
279 } break;
280 default:
281 SkASSERT(!"unsupported array type");
282 break;
283 }
284}
285
286///////////////////////////////////////////////////////////////////////////////
287
288static const uint8_t gBytesPerType[] = {
289 sizeof(SkJSON::Object*),
290 sizeof(SkJSON::Array*),
291 sizeof(char*),
292 sizeof(int32_t),
293 sizeof(float),
294 sizeof(bool)
295};
296
297void SkJSON::Array::init(Type type, int count, const void* src) {
298 if (count < 0) {
299 count = 0;
300 }
301 size_t size = count * gBytesPerType[type];
302
303 fCount = count;
304 fType = type;
305 fArray.fVoids = sk_malloc_throw(size);
306 if (src) {
307 memcpy(fArray.fVoids, src, size);
308 }
309}
310
311SkJSON::Array::Array(Type type, int count) {
312 this->init(type, count, NULL);
313}
314
315SkJSON::Array::Array(const int32_t values[], int count) {
316 this->init(kInt, count, values);
317}
318
319SkJSON::Array::Array(const float values[], int count) {
320 this->init(kFloat, count, values);
321}
322
323SkJSON::Array::Array(const bool values[], int count) {
324 this->init(kBool, count, values);
325}
326
327SkJSON::Array::Array(const Array& src) {
328 this->init(src.type(), src.count(), src.fArray.fVoids);
329}
330
331SkJSON::Array::~Array() {
332 sk_free(fArray.fVoids);
333}
334