gfx/skia/trunk/src/utils/SkJSON.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2011 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "SkJSON.h"
michael@0 9 #include "SkString.h"
michael@0 10
michael@0 11 #ifdef SK_DEBUG
michael@0 12 // #define TRACE_SKJSON_LEAKS
michael@0 13 #endif
michael@0 14
michael@0 15 #ifdef TRACE_SKJSON_LEAKS
michael@0 16 static int gStringCount;
michael@0 17 static int gSlotCount;
michael@0 18 static int gObjectCount;
michael@0 19 static int gArrayCount;
michael@0 20 #define LEAK_CODE(code) code
michael@0 21 #else
michael@0 22 #define LEAK_CODE(code)
michael@0 23 #endif
michael@0 24
michael@0 25 ///////////////////////////////////////////////////////////////////////////////
michael@0 26
michael@0 27 static char* alloc_string(size_t len) {
michael@0 28 LEAK_CODE(SkDebugf(" string[%d]\n", gStringCount++);)
michael@0 29 char* str = (char*)sk_malloc_throw(len + 1);
michael@0 30 str[len] = 0;
michael@0 31 return str;
michael@0 32 }
michael@0 33
michael@0 34 static char* dup_string(const char src[]) {
michael@0 35 if (NULL == src) {
michael@0 36 return NULL;
michael@0 37 }
michael@0 38 size_t len = strlen(src);
michael@0 39 char* dst = alloc_string(len);
michael@0 40 memcpy(dst, src, len);
michael@0 41 return dst;
michael@0 42 }
michael@0 43
michael@0 44 static void free_string(char* str) {
michael@0 45 if (str) {
michael@0 46 sk_free(str);
michael@0 47 LEAK_CODE(SkASSERT(gStringCount > 0); SkDebugf("~string[%d]\n", --gStringCount);)
michael@0 48 }
michael@0 49 }
michael@0 50
michael@0 51 ///////////////////////////////////////////////////////////////////////////////
michael@0 52
michael@0 53 struct SkJSON::Object::Slot {
michael@0 54 Slot(const char name[], Type type) {
michael@0 55 LEAK_CODE(SkDebugf(" slot[%d]\n", gSlotCount++);)
michael@0 56 SkASSERT(name);
michael@0 57
michael@0 58 fNext = NULL;
michael@0 59
michael@0 60 size_t len = strlen(name);
michael@0 61 // extra 1 for str[0] which stores the type
michael@0 62 char* str = alloc_string(1 + len);
michael@0 63 str[0] = (char)type;
michael@0 64 // str[1] skips the type, len+1 includes the terminating 0 byte.
michael@0 65 memcpy(&str[1], name, len + 1);
michael@0 66 fName = str;
michael@0 67
michael@0 68 // fValue is uninitialized
michael@0 69 }
michael@0 70 ~Slot();
michael@0 71
michael@0 72 Type type() const { return (Type)fName[0]; }
michael@0 73 const char* name() const { return &fName[1]; }
michael@0 74
michael@0 75 Slot* fNext;
michael@0 76 char* fName; // fName[0] is the type, &fName[1] is the "name"
michael@0 77 union {
michael@0 78 Object* fObject;
michael@0 79 Array* fArray;
michael@0 80 char* fString;
michael@0 81 int32_t fInt;
michael@0 82 float fFloat;
michael@0 83 bool fBool;
michael@0 84 } fValue;
michael@0 85 };
michael@0 86
michael@0 87 SkJSON::Object::Slot::~Slot() {
michael@0 88 free_string(fName);
michael@0 89 switch (this->type()) {
michael@0 90 case kObject:
michael@0 91 delete fValue.fObject;
michael@0 92 break;
michael@0 93 case kArray:
michael@0 94 delete fValue.fArray;
michael@0 95 break;
michael@0 96 case kString:
michael@0 97 free_string(fValue.fString);
michael@0 98 break;
michael@0 99 default:
michael@0 100 break;
michael@0 101 }
michael@0 102 LEAK_CODE(SkASSERT(gSlotCount > 0); SkDebugf("~slot[%d]\n", --gSlotCount);)
michael@0 103 }
michael@0 104
michael@0 105 ///////////////////////////////////////////////////////////////////////////////
michael@0 106
michael@0 107 SkJSON::Object::Iter::Iter(const Object& obj) : fSlot(obj.fHead) {}
michael@0 108
michael@0 109 bool SkJSON::Object::Iter::done() const {
michael@0 110 return NULL == fSlot;
michael@0 111 }
michael@0 112
michael@0 113 void SkJSON::Object::Iter::next() {
michael@0 114 SkASSERT(fSlot);
michael@0 115 fSlot = fSlot->fNext;
michael@0 116 }
michael@0 117
michael@0 118 SkJSON::Type SkJSON::Object::Iter::type() const {
michael@0 119 SkASSERT(fSlot);
michael@0 120 return fSlot->type();
michael@0 121 }
michael@0 122
michael@0 123 const char* SkJSON::Object::Iter::name() const {
michael@0 124 SkASSERT(fSlot);
michael@0 125 return fSlot->name();
michael@0 126 }
michael@0 127
michael@0 128 SkJSON::Object* SkJSON::Object::Iter::objectValue() const {
michael@0 129 SkASSERT(fSlot);
michael@0 130 SkASSERT(kObject == fSlot->type());
michael@0 131 return fSlot->fValue.fObject;
michael@0 132 }
michael@0 133
michael@0 134 SkJSON::Array* SkJSON::Object::Iter::arrayValue() const {
michael@0 135 SkASSERT(fSlot);
michael@0 136 SkASSERT(kArray == fSlot->type());
michael@0 137 return fSlot->fValue.fArray;
michael@0 138 }
michael@0 139
michael@0 140 const char* SkJSON::Object::Iter::stringValue() const {
michael@0 141 SkASSERT(fSlot);
michael@0 142 SkASSERT(kString == fSlot->type());
michael@0 143 return fSlot->fValue.fString;
michael@0 144 }
michael@0 145
michael@0 146 int32_t SkJSON::Object::Iter::intValue() const {
michael@0 147 SkASSERT(fSlot);
michael@0 148 SkASSERT(kInt == fSlot->type());
michael@0 149 return fSlot->fValue.fInt;
michael@0 150 }
michael@0 151
michael@0 152 float SkJSON::Object::Iter::floatValue() const {
michael@0 153 SkASSERT(fSlot);
michael@0 154 SkASSERT(kFloat == fSlot->type());
michael@0 155 return fSlot->fValue.fFloat;
michael@0 156 }
michael@0 157
michael@0 158 bool SkJSON::Object::Iter::boolValue() const {
michael@0 159 SkASSERT(fSlot);
michael@0 160 SkASSERT(kBool == fSlot->type());
michael@0 161 return fSlot->fValue.fBool;
michael@0 162 }
michael@0 163
michael@0 164 ///////////////////////////////////////////////////////////////////////////////
michael@0 165
michael@0 166 SkJSON::Object::Object() : fHead(NULL), fTail(NULL) {
michael@0 167 LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
michael@0 168 }
michael@0 169
michael@0 170 SkJSON::Object::Object(const Object& other) : fHead(NULL), fTail(NULL) {
michael@0 171 LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
michael@0 172
michael@0 173 Iter iter(other);
michael@0 174 while (!iter.done()) {
michael@0 175 switch (iter.type()) {
michael@0 176 case kObject:
michael@0 177 this->addObject(iter.name(), new Object(*iter.objectValue()));
michael@0 178 break;
michael@0 179 case kArray:
michael@0 180 this->addArray(iter.name(), new Array(*iter.arrayValue()));
michael@0 181 break;
michael@0 182 case kString:
michael@0 183 this->addString(iter.name(), dup_string(iter.stringValue()));
michael@0 184 break;
michael@0 185 case kInt:
michael@0 186 this->addInt(iter.name(), iter.intValue());
michael@0 187 break;
michael@0 188 case kFloat:
michael@0 189 this->addFloat(iter.name(), iter.floatValue());
michael@0 190 break;
michael@0 191 case kBool:
michael@0 192 this->addBool(iter.name(), iter.boolValue());
michael@0 193 break;
michael@0 194 }
michael@0 195 iter.next();
michael@0 196 }
michael@0 197 }
michael@0 198
michael@0 199 SkJSON::Object::~Object() {
michael@0 200 Slot* slot = fHead;
michael@0 201 while (slot) {
michael@0 202 Slot* next = slot->fNext;
michael@0 203 delete slot;
michael@0 204 slot = next;
michael@0 205 }
michael@0 206 LEAK_CODE(SkASSERT(gObjectCount > 0); SkDebugf("~object[%d]\n", --gObjectCount);)
michael@0 207 }
michael@0 208
michael@0 209 int SkJSON::Object::count() const {
michael@0 210 int n = 0;
michael@0 211 for (const Slot* slot = fHead; slot; slot = slot->fNext) {
michael@0 212 n += 1;
michael@0 213 }
michael@0 214 return n;
michael@0 215 }
michael@0 216
michael@0 217 SkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) {
michael@0 218 SkASSERT(NULL == slot->fNext);
michael@0 219 if (NULL == fHead) {
michael@0 220 SkASSERT(NULL == fTail);
michael@0 221 fHead = fTail = slot;
michael@0 222 } else {
michael@0 223 SkASSERT(fTail);
michael@0 224 SkASSERT(NULL == fTail->fNext);
michael@0 225 fTail->fNext = slot;
michael@0 226 fTail = slot;
michael@0 227 }
michael@0 228 return slot;
michael@0 229 }
michael@0 230
michael@0 231 void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) {
michael@0 232 this->addSlot(new Slot(name, kObject))->fValue.fObject = value;
michael@0 233 }
michael@0 234
michael@0 235 void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) {
michael@0 236 this->addSlot(new Slot(name, kArray))->fValue.fArray = value;
michael@0 237 }
michael@0 238
michael@0 239 void SkJSON::Object::addString(const char name[], const char value[]) {
michael@0 240 this->addSlot(new Slot(name, kString))->fValue.fString = dup_string(value);
michael@0 241 }
michael@0 242
michael@0 243 void SkJSON::Object::addInt(const char name[], int32_t value) {
michael@0 244 this->addSlot(new Slot(name, kInt))->fValue.fInt = value;
michael@0 245 }
michael@0 246
michael@0 247 void SkJSON::Object::addFloat(const char name[], float value) {
michael@0 248 this->addSlot(new Slot(name, kFloat))->fValue.fFloat = value;
michael@0 249 }
michael@0 250
michael@0 251 void SkJSON::Object::addBool(const char name[], bool value) {
michael@0 252 this->addSlot(new Slot(name, kBool))->fValue.fBool = value;
michael@0 253 }
michael@0 254
michael@0 255 ///////////////////////////////////////////////////////////////////////////////
michael@0 256
michael@0 257 const SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[],
michael@0 258 Type t) const {
michael@0 259 for (const Slot* slot = fHead; slot; slot = slot->fNext) {
michael@0 260 if (t == slot->type() && !strcmp(slot->name(), name)) {
michael@0 261 return slot;
michael@0 262 }
michael@0 263 }
michael@0 264 return NULL;
michael@0 265 }
michael@0 266
michael@0 267 bool SkJSON::Object::find(const char name[], Type t) const {
michael@0 268 return this->findSlot(name, t) != NULL;
michael@0 269 }
michael@0 270
michael@0 271 bool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const {
michael@0 272 const Slot* slot = this->findSlot(name, kObject);
michael@0 273 if (slot) {
michael@0 274 if (value) {
michael@0 275 *value = slot->fValue.fObject;
michael@0 276 }
michael@0 277 return true;
michael@0 278 }
michael@0 279 return false;
michael@0 280 }
michael@0 281
michael@0 282 bool SkJSON::Object::findArray(const char name[], SkJSON::Array** value) const {
michael@0 283 const Slot* slot = this->findSlot(name, kArray);
michael@0 284 if (slot) {
michael@0 285 if (value) {
michael@0 286 *value = slot->fValue.fArray;
michael@0 287 }
michael@0 288 return true;
michael@0 289 }
michael@0 290 return false;
michael@0 291 }
michael@0 292
michael@0 293 bool SkJSON::Object::findString(const char name[], SkString* value) const {
michael@0 294 const Slot* slot = this->findSlot(name, kString);
michael@0 295 if (slot) {
michael@0 296 if (value) {
michael@0 297 value->set(slot->fValue.fString);
michael@0 298 }
michael@0 299 return true;
michael@0 300 }
michael@0 301 return false;
michael@0 302 }
michael@0 303
michael@0 304 bool SkJSON::Object::findInt(const char name[], int32_t* value) const {
michael@0 305 const Slot* slot = this->findSlot(name, kInt);
michael@0 306 if (slot) {
michael@0 307 if (value) {
michael@0 308 *value = slot->fValue.fInt;
michael@0 309 }
michael@0 310 return true;
michael@0 311 }
michael@0 312 return false;
michael@0 313 }
michael@0 314
michael@0 315 bool SkJSON::Object::findFloat(const char name[], float* value) const {
michael@0 316 const Slot* slot = this->findSlot(name, kFloat);
michael@0 317 if (slot) {
michael@0 318 if (value) {
michael@0 319 *value = slot->fValue.fFloat;
michael@0 320 }
michael@0 321 return true;
michael@0 322 }
michael@0 323 return false;
michael@0 324 }
michael@0 325
michael@0 326 bool SkJSON::Object::findBool(const char name[], bool* value) const {
michael@0 327 const Slot* slot = this->findSlot(name, kBool);
michael@0 328 if (slot) {
michael@0 329 if (value) {
michael@0 330 *value = slot->fValue.fBool;
michael@0 331 }
michael@0 332 return true;
michael@0 333 }
michael@0 334 return false;
michael@0 335 }
michael@0 336
michael@0 337 bool SkJSON::Object::remove(const char name[], Type t) {
michael@0 338 SkDEBUGCODE(int count = this->count();)
michael@0 339 Slot* prev = NULL;
michael@0 340 Slot* slot = fHead;
michael@0 341 while (slot) {
michael@0 342 Slot* next = slot->fNext;
michael@0 343 if (t == slot->type() && !strcmp(slot->name(), name)) {
michael@0 344 if (prev) {
michael@0 345 SkASSERT(fHead != slot);
michael@0 346 prev->fNext = next;
michael@0 347 } else {
michael@0 348 SkASSERT(fHead == slot);
michael@0 349 fHead = next;
michael@0 350 }
michael@0 351 if (fTail == slot) {
michael@0 352 fTail = prev;
michael@0 353 }
michael@0 354 delete slot;
michael@0 355 SkASSERT(count - 1 == this->count());
michael@0 356 return true;
michael@0 357 }
michael@0 358 prev = slot;
michael@0 359 slot = next;
michael@0 360 }
michael@0 361 SkASSERT(count == this->count());
michael@0 362 return false;
michael@0 363 }
michael@0 364
michael@0 365 ///////////////////////////////////////////////////////////////////////////////
michael@0 366
michael@0 367 static void tabForLevel(int level) {
michael@0 368 for (int i = 0; i < level; ++i) {
michael@0 369 SkDebugf(" ");
michael@0 370 }
michael@0 371 }
michael@0 372
michael@0 373 void SkJSON::Object::toDebugf() const {
michael@0 374 SkDebugf("{\n");
michael@0 375 this->dumpLevel(0);
michael@0 376 SkDebugf("}\n");
michael@0 377 }
michael@0 378
michael@0 379 void SkJSON::Object::dumpLevel(int level) const {
michael@0 380 for (Slot* slot = fHead; slot; slot = slot->fNext) {
michael@0 381 Type t = slot->type();
michael@0 382 tabForLevel(level + 1);
michael@0 383 SkDebugf("\"%s\" : ", slot->name());
michael@0 384 switch (slot->type()) {
michael@0 385 case kObject:
michael@0 386 if (slot->fValue.fObject) {
michael@0 387 SkDebugf("{\n");
michael@0 388 slot->fValue.fObject->dumpLevel(level + 1);
michael@0 389 tabForLevel(level + 1);
michael@0 390 SkDebugf("}");
michael@0 391 } else {
michael@0 392 SkDebugf("null");
michael@0 393 }
michael@0 394 break;
michael@0 395 case kArray:
michael@0 396 if (slot->fValue.fArray) {
michael@0 397 SkDebugf("[");
michael@0 398 slot->fValue.fArray->dumpLevel(level + 1);
michael@0 399 SkDebugf("]");
michael@0 400 } else {
michael@0 401 SkDebugf("null");
michael@0 402 }
michael@0 403 break;
michael@0 404 case kString:
michael@0 405 SkDebugf("\"%s\"", slot->fValue.fString);
michael@0 406 break;
michael@0 407 case kInt:
michael@0 408 SkDebugf("%d", slot->fValue.fInt);
michael@0 409 break;
michael@0 410 case kFloat:
michael@0 411 SkDebugf("%g", slot->fValue.fFloat);
michael@0 412 break;
michael@0 413 case kBool:
michael@0 414 SkDebugf("%s", slot->fValue.fBool ? "true" : "false");
michael@0 415 break;
michael@0 416 default:
michael@0 417 SkDEBUGFAIL("how did I get here");
michael@0 418 break;
michael@0 419 }
michael@0 420 if (slot->fNext) {
michael@0 421 SkDebugf(",");
michael@0 422 }
michael@0 423 SkDebugf("\n");
michael@0 424 }
michael@0 425 }
michael@0 426
michael@0 427 void SkJSON::Array::dumpLevel(int level) const {
michael@0 428 if (0 == fCount) {
michael@0 429 return;
michael@0 430 }
michael@0 431 int last = fCount - 1;
michael@0 432
michael@0 433 switch (this->type()) {
michael@0 434 case kObject: {
michael@0 435 SkDebugf("\n");
michael@0 436 for (int i = 0; i <= last; ++i) {
michael@0 437 Object* obj = fArray.fObjects[i];
michael@0 438 tabForLevel(level + 1);
michael@0 439 if (obj) {
michael@0 440 SkDebugf("{\n");
michael@0 441 obj->dumpLevel(level + 1);
michael@0 442 tabForLevel(level + 1);
michael@0 443 SkDebugf(i < last ? "}," : "}");
michael@0 444 } else {
michael@0 445 SkDebugf(i < last ? "null," : "null");
michael@0 446 }
michael@0 447 SkDebugf("\n");
michael@0 448 }
michael@0 449 } break;
michael@0 450 case kArray: {
michael@0 451 SkDebugf("\n");
michael@0 452 for (int i = 0; i <= last; ++i) {
michael@0 453 Array* array = fArray.fArrays[i];
michael@0 454 tabForLevel(level + 1);
michael@0 455 if (array) {
michael@0 456 SkDebugf("[");
michael@0 457 array->dumpLevel(level + 1);
michael@0 458 tabForLevel(level + 1);
michael@0 459 SkDebugf(i < last ? "]," : "]");
michael@0 460 } else {
michael@0 461 SkDebugf(i < last ? "null," : "null");
michael@0 462 }
michael@0 463 SkDebugf("\n");
michael@0 464 }
michael@0 465 } break;
michael@0 466 case kString: {
michael@0 467 for (int i = 0; i < last; ++i) {
michael@0 468 const char* str = fArray.fStrings[i];
michael@0 469 SkDebugf(str ? " \"%s\"," : " null,", str);
michael@0 470 }
michael@0 471 const char* str = fArray.fStrings[last];
michael@0 472 SkDebugf(str ? " \"%s\" " : " null ", str);
michael@0 473 } break;
michael@0 474 case kInt: {
michael@0 475 for (int i = 0; i < last; ++i) {
michael@0 476 SkDebugf(" %d,", fArray.fInts[i]);
michael@0 477 }
michael@0 478 SkDebugf(" %d ", fArray.fInts[last]);
michael@0 479 } break;
michael@0 480 case kFloat: {
michael@0 481 for (int i = 0; i < last; ++i) {
michael@0 482 SkDebugf(" %g,", fArray.fFloats[i]);
michael@0 483 }
michael@0 484 SkDebugf(" %g ", fArray.fFloats[last]);
michael@0 485 } break;
michael@0 486 case kBool: {
michael@0 487 for (int i = 0; i < last; ++i) {
michael@0 488 SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false");
michael@0 489 }
michael@0 490 SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false");
michael@0 491 } break;
michael@0 492 default:
michael@0 493 SkDEBUGFAIL("unsupported array type");
michael@0 494 break;
michael@0 495 }
michael@0 496 }
michael@0 497
michael@0 498 ///////////////////////////////////////////////////////////////////////////////
michael@0 499
michael@0 500 static const uint8_t gBytesPerType[] = {
michael@0 501 sizeof(SkJSON::Object*),
michael@0 502 sizeof(SkJSON::Array*),
michael@0 503 sizeof(char*),
michael@0 504 sizeof(int32_t),
michael@0 505 sizeof(float),
michael@0 506 sizeof(bool)
michael@0 507 };
michael@0 508
michael@0 509 typedef void* (*DupProc)(const void*);
michael@0 510
michael@0 511 static void* dup_object(const void* src) {
michael@0 512 return SkNEW_ARGS(SkJSON::Object, (*(SkJSON::Object*)src));
michael@0 513 }
michael@0 514
michael@0 515 static void* dup_array(const void* src) {
michael@0 516 return SkNEW_ARGS(SkJSON::Array, (*(SkJSON::Array*)src));
michael@0 517 }
michael@0 518
michael@0 519 static const DupProc gDupProcs[] = {
michael@0 520 dup_object, // Object
michael@0 521 dup_array, // Array
michael@0 522 (DupProc)dup_string, // String
michael@0 523 NULL, // int
michael@0 524 NULL, // float
michael@0 525 NULL, // bool
michael@0 526 };
michael@0 527
michael@0 528 void SkJSON::Array::init(Type type, int count, const void* src) {
michael@0 529 LEAK_CODE(SkDebugf(" array[%d]\n", gArrayCount++);)
michael@0 530
michael@0 531 SkASSERT((unsigned)type < SK_ARRAY_COUNT(gBytesPerType));
michael@0 532
michael@0 533 if (count < 0) {
michael@0 534 count = 0;
michael@0 535 }
michael@0 536 size_t size = count * gBytesPerType[type];
michael@0 537
michael@0 538 fCount = count;
michael@0 539 fType = type;
michael@0 540 fArray.fVoids = sk_malloc_throw(size);
michael@0 541 if (src) {
michael@0 542 DupProc proc = gDupProcs[fType];
michael@0 543 if (!proc) {
michael@0 544 memcpy(fArray.fVoids, src, size);
michael@0 545 } else {
michael@0 546 void** srcPtr = (void**)src;
michael@0 547 void** dstPtr = (void**)fArray.fVoids;
michael@0 548 for (int i = 0; i < fCount; ++i) {
michael@0 549 dstPtr[i] = proc(srcPtr[i]);
michael@0 550 }
michael@0 551 }
michael@0 552 } else {
michael@0 553 sk_bzero(fArray.fVoids, size);
michael@0 554 }
michael@0 555 }
michael@0 556
michael@0 557 SkJSON::Array::Array(Type type, int count) {
michael@0 558 this->init(type, count, NULL);
michael@0 559 }
michael@0 560
michael@0 561 SkJSON::Array::Array(const int32_t values[], int count) {
michael@0 562 this->init(kInt, count, values);
michael@0 563 }
michael@0 564
michael@0 565 SkJSON::Array::Array(const float values[], int count) {
michael@0 566 this->init(kFloat, count, values);
michael@0 567 }
michael@0 568
michael@0 569 SkJSON::Array::Array(const bool values[], int count) {
michael@0 570 this->init(kBool, count, values);
michael@0 571 }
michael@0 572
michael@0 573 SkJSON::Array::Array(const Array& other) {
michael@0 574 this->init(other.type(), other.count(), other.fArray.fVoids);
michael@0 575 }
michael@0 576
michael@0 577 typedef void (*FreeProc)(void*);
michael@0 578
michael@0 579 static void free_object(void* obj) {
michael@0 580 delete (SkJSON::Object*)obj;
michael@0 581 }
michael@0 582
michael@0 583 static void free_array(void* array) {
michael@0 584 delete (SkJSON::Array*)array;
michael@0 585 }
michael@0 586
michael@0 587 static const FreeProc gFreeProcs[] = {
michael@0 588 free_object, // Object
michael@0 589 free_array, // Array
michael@0 590 (FreeProc)free_string, // String
michael@0 591 NULL, // int
michael@0 592 NULL, // float
michael@0 593 NULL, // bool
michael@0 594 };
michael@0 595
michael@0 596 SkJSON::Array::~Array() {
michael@0 597 FreeProc proc = gFreeProcs[fType];
michael@0 598 if (proc) {
michael@0 599 void** ptr = (void**)fArray.fVoids;
michael@0 600 for (int i = 0; i < fCount; ++i) {
michael@0 601 proc(ptr[i]);
michael@0 602 }
michael@0 603 }
michael@0 604 sk_free(fArray.fVoids);
michael@0 605
michael@0 606 LEAK_CODE(SkASSERT(gArrayCount > 0); SkDebugf("~array[%d]\n", --gArrayCount);)
michael@0 607 }
michael@0 608
michael@0 609 void SkJSON::Array::setObject(int index, Object* object) {
michael@0 610 SkASSERT((unsigned)index < (unsigned)fCount);
michael@0 611 Object*& prev = fArray.fObjects[index];
michael@0 612 if (prev != object) {
michael@0 613 delete prev;
michael@0 614 prev = object;
michael@0 615 }
michael@0 616 }
michael@0 617
michael@0 618 void SkJSON::Array::setArray(int index, Array* array) {
michael@0 619 SkASSERT((unsigned)index < (unsigned)fCount);
michael@0 620 Array*& prev = fArray.fArrays[index];
michael@0 621 if (prev != array) {
michael@0 622 delete prev;
michael@0 623 prev = array;
michael@0 624 }
michael@0 625 }
michael@0 626
michael@0 627 void SkJSON::Array::setString(int index, const char str[]) {
michael@0 628 SkASSERT((unsigned)index < (unsigned)fCount);
michael@0 629 char*& prev = fArray.fStrings[index];
michael@0 630 if (prev != str) {
michael@0 631 free_string(prev);
michael@0 632 prev = dup_string(str);
michael@0 633 }
michael@0 634 }

mercurial