gfx/skia/trunk/src/xml/SkDOM.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 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkDOM.h"
michael@0 11
michael@0 12 /////////////////////////////////////////////////////////////////////////
michael@0 13
michael@0 14 #include "SkXMLParser.h"
michael@0 15
michael@0 16 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node)
michael@0 17 {
michael@0 18 const char* elemName = dom.getName(node);
michael@0 19
michael@0 20 if (this->startElement(elemName))
michael@0 21 return false;
michael@0 22
michael@0 23 SkDOM::AttrIter iter(dom, node);
michael@0 24 const char* name, *value;
michael@0 25
michael@0 26 while ((name = iter.next(&value)) != NULL)
michael@0 27 if (this->addAttribute(name, value))
michael@0 28 return false;
michael@0 29
michael@0 30 if ((node = dom.getFirstChild(node)) != NULL)
michael@0 31 do {
michael@0 32 if (!this->parse(dom, node))
michael@0 33 return false;
michael@0 34 } while ((node = dom.getNextSibling(node)) != NULL);
michael@0 35
michael@0 36 return !this->endElement(elemName);
michael@0 37 }
michael@0 38
michael@0 39 /////////////////////////////////////////////////////////////////////////
michael@0 40
michael@0 41 struct SkDOMAttr {
michael@0 42 const char* fName;
michael@0 43 const char* fValue;
michael@0 44 };
michael@0 45
michael@0 46 struct SkDOMNode {
michael@0 47 const char* fName;
michael@0 48 SkDOMNode* fFirstChild;
michael@0 49 SkDOMNode* fNextSibling;
michael@0 50 uint16_t fAttrCount;
michael@0 51 uint8_t fType;
michael@0 52 uint8_t fPad;
michael@0 53
michael@0 54 const SkDOMAttr* attrs() const
michael@0 55 {
michael@0 56 return (const SkDOMAttr*)(this + 1);
michael@0 57 }
michael@0 58 SkDOMAttr* attrs()
michael@0 59 {
michael@0 60 return (SkDOMAttr*)(this + 1);
michael@0 61 }
michael@0 62 };
michael@0 63
michael@0 64 /////////////////////////////////////////////////////////////////////////
michael@0 65
michael@0 66 #define kMinChunkSize 512
michael@0 67
michael@0 68 SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(NULL)
michael@0 69 {
michael@0 70 }
michael@0 71
michael@0 72 SkDOM::~SkDOM()
michael@0 73 {
michael@0 74 }
michael@0 75
michael@0 76 const SkDOM::Node* SkDOM::getRootNode() const
michael@0 77 {
michael@0 78 return fRoot;
michael@0 79 }
michael@0 80
michael@0 81 const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const
michael@0 82 {
michael@0 83 SkASSERT(node);
michael@0 84 const Node* child = node->fFirstChild;
michael@0 85
michael@0 86 if (name)
michael@0 87 {
michael@0 88 for (; child != NULL; child = child->fNextSibling)
michael@0 89 if (!strcmp(name, child->fName))
michael@0 90 break;
michael@0 91 }
michael@0 92 return child;
michael@0 93 }
michael@0 94
michael@0 95 const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const
michael@0 96 {
michael@0 97 SkASSERT(node);
michael@0 98 const Node* sibling = node->fNextSibling;
michael@0 99 if (name)
michael@0 100 {
michael@0 101 for (; sibling != NULL; sibling = sibling->fNextSibling)
michael@0 102 if (!strcmp(name, sibling->fName))
michael@0 103 break;
michael@0 104 }
michael@0 105 return sibling;
michael@0 106 }
michael@0 107
michael@0 108 SkDOM::Type SkDOM::getType(const Node* node) const
michael@0 109 {
michael@0 110 SkASSERT(node);
michael@0 111 return (Type)node->fType;
michael@0 112 }
michael@0 113
michael@0 114 const char* SkDOM::getName(const Node* node) const
michael@0 115 {
michael@0 116 SkASSERT(node);
michael@0 117 return node->fName;
michael@0 118 }
michael@0 119
michael@0 120 const char* SkDOM::findAttr(const Node* node, const char name[]) const
michael@0 121 {
michael@0 122 SkASSERT(node);
michael@0 123 const Attr* attr = node->attrs();
michael@0 124 const Attr* stop = attr + node->fAttrCount;
michael@0 125
michael@0 126 while (attr < stop)
michael@0 127 {
michael@0 128 if (!strcmp(attr->fName, name))
michael@0 129 return attr->fValue;
michael@0 130 attr += 1;
michael@0 131 }
michael@0 132 return NULL;
michael@0 133 }
michael@0 134
michael@0 135 /////////////////////////////////////////////////////////////////////////////////////
michael@0 136
michael@0 137 const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const
michael@0 138 {
michael@0 139 return node->fAttrCount ? node->attrs() : NULL;
michael@0 140 }
michael@0 141
michael@0 142 const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const
michael@0 143 {
michael@0 144 SkASSERT(node);
michael@0 145 if (attr == NULL)
michael@0 146 return NULL;
michael@0 147 return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : NULL;
michael@0 148 }
michael@0 149
michael@0 150 const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const
michael@0 151 {
michael@0 152 SkASSERT(node);
michael@0 153 SkASSERT(attr);
michael@0 154 return attr->fName;
michael@0 155 }
michael@0 156
michael@0 157 const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const
michael@0 158 {
michael@0 159 SkASSERT(node);
michael@0 160 SkASSERT(attr);
michael@0 161 return attr->fValue;
michael@0 162 }
michael@0 163
michael@0 164 /////////////////////////////////////////////////////////////////////////////////////
michael@0 165
michael@0 166 SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node)
michael@0 167 {
michael@0 168 SkASSERT(node);
michael@0 169 fAttr = node->attrs();
michael@0 170 fStop = fAttr + node->fAttrCount;
michael@0 171 }
michael@0 172
michael@0 173 const char* SkDOM::AttrIter::next(const char** value)
michael@0 174 {
michael@0 175 const char* name = NULL;
michael@0 176
michael@0 177 if (fAttr < fStop)
michael@0 178 {
michael@0 179 name = fAttr->fName;
michael@0 180 if (value)
michael@0 181 *value = fAttr->fValue;
michael@0 182 fAttr += 1;
michael@0 183 }
michael@0 184 return name;
michael@0 185 }
michael@0 186
michael@0 187 //////////////////////////////////////////////////////////////////////////////
michael@0 188
michael@0 189 #include "SkXMLParser.h"
michael@0 190 #include "SkTDArray.h"
michael@0 191
michael@0 192 static char* dupstr(SkChunkAlloc* chunk, const char src[])
michael@0 193 {
michael@0 194 SkASSERT(chunk && src);
michael@0 195 size_t len = strlen(src);
michael@0 196 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
michael@0 197 memcpy(dst, src, len + 1);
michael@0 198 return dst;
michael@0 199 }
michael@0 200
michael@0 201 class SkDOMParser : public SkXMLParser {
michael@0 202 bool fNeedToFlush;
michael@0 203 public:
michael@0 204 SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk)
michael@0 205 {
michael@0 206 fRoot = NULL;
michael@0 207 fLevel = 0;
michael@0 208 fNeedToFlush = true;
michael@0 209 }
michael@0 210 SkDOM::Node* getRoot() const { return fRoot; }
michael@0 211 SkXMLParserError fParserError;
michael@0 212 protected:
michael@0 213 void flushAttributes()
michael@0 214 {
michael@0 215 int attrCount = fAttrs.count();
michael@0 216
michael@0 217 SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr),
michael@0 218 SkChunkAlloc::kThrow_AllocFailType);
michael@0 219
michael@0 220 node->fName = fElemName;
michael@0 221 node->fFirstChild = NULL;
michael@0 222 node->fAttrCount = SkToU16(attrCount);
michael@0 223 node->fType = SkDOM::kElement_Type;
michael@0 224
michael@0 225 if (fRoot == NULL)
michael@0 226 {
michael@0 227 node->fNextSibling = NULL;
michael@0 228 fRoot = node;
michael@0 229 }
michael@0 230 else // this adds siblings in reverse order. gets corrected in onEndElement()
michael@0 231 {
michael@0 232 SkDOM::Node* parent = fParentStack.top();
michael@0 233 SkASSERT(fRoot && parent);
michael@0 234 node->fNextSibling = parent->fFirstChild;
michael@0 235 parent->fFirstChild = node;
michael@0 236 }
michael@0 237 *fParentStack.push() = node;
michael@0 238
michael@0 239 memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr));
michael@0 240 fAttrs.reset();
michael@0 241
michael@0 242 }
michael@0 243 virtual bool onStartElement(const char elem[])
michael@0 244 {
michael@0 245 if (fLevel > 0 && fNeedToFlush)
michael@0 246 this->flushAttributes();
michael@0 247 fNeedToFlush = true;
michael@0 248 fElemName = dupstr(fAlloc, elem);
michael@0 249 ++fLevel;
michael@0 250 return false;
michael@0 251 }
michael@0 252 virtual bool onAddAttribute(const char name[], const char value[])
michael@0 253 {
michael@0 254 SkDOM::Attr* attr = fAttrs.append();
michael@0 255 attr->fName = dupstr(fAlloc, name);
michael@0 256 attr->fValue = dupstr(fAlloc, value);
michael@0 257 return false;
michael@0 258 }
michael@0 259 virtual bool onEndElement(const char elem[])
michael@0 260 {
michael@0 261 --fLevel;
michael@0 262 if (fNeedToFlush)
michael@0 263 this->flushAttributes();
michael@0 264 fNeedToFlush = false;
michael@0 265
michael@0 266 SkDOM::Node* parent;
michael@0 267
michael@0 268 fParentStack.pop(&parent);
michael@0 269
michael@0 270 SkDOM::Node* child = parent->fFirstChild;
michael@0 271 SkDOM::Node* prev = NULL;
michael@0 272 while (child)
michael@0 273 {
michael@0 274 SkDOM::Node* next = child->fNextSibling;
michael@0 275 child->fNextSibling = prev;
michael@0 276 prev = child;
michael@0 277 child = next;
michael@0 278 }
michael@0 279 parent->fFirstChild = prev;
michael@0 280 return false;
michael@0 281 }
michael@0 282 private:
michael@0 283 SkTDArray<SkDOM::Node*> fParentStack;
michael@0 284 SkChunkAlloc* fAlloc;
michael@0 285 SkDOM::Node* fRoot;
michael@0 286
michael@0 287 // state needed for flushAttributes()
michael@0 288 SkTDArray<SkDOM::Attr> fAttrs;
michael@0 289 char* fElemName;
michael@0 290 int fLevel;
michael@0 291 };
michael@0 292
michael@0 293 const SkDOM::Node* SkDOM::build(const char doc[], size_t len)
michael@0 294 {
michael@0 295 fAlloc.reset();
michael@0 296 SkDOMParser parser(&fAlloc);
michael@0 297 if (!parser.parse(doc, len))
michael@0 298 {
michael@0 299 SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
michael@0 300 fRoot = NULL;
michael@0 301 fAlloc.reset();
michael@0 302 return NULL;
michael@0 303 }
michael@0 304 fRoot = parser.getRoot();
michael@0 305 return fRoot;
michael@0 306 }
michael@0 307
michael@0 308 ///////////////////////////////////////////////////////////////////////////
michael@0 309
michael@0 310 static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser)
michael@0 311 {
michael@0 312 const char* elem = dom.getName(node);
michael@0 313
michael@0 314 parser->startElement(elem);
michael@0 315
michael@0 316 SkDOM::AttrIter iter(dom, node);
michael@0 317 const char* name;
michael@0 318 const char* value;
michael@0 319 while ((name = iter.next(&value)) != NULL)
michael@0 320 parser->addAttribute(name, value);
michael@0 321
michael@0 322 node = dom.getFirstChild(node, NULL);
michael@0 323 while (node)
michael@0 324 {
michael@0 325 walk_dom(dom, node, parser);
michael@0 326 node = dom.getNextSibling(node, NULL);
michael@0 327 }
michael@0 328
michael@0 329 parser->endElement(elem);
michael@0 330 }
michael@0 331
michael@0 332 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node)
michael@0 333 {
michael@0 334 fAlloc.reset();
michael@0 335 SkDOMParser parser(&fAlloc);
michael@0 336
michael@0 337 walk_dom(dom, node, &parser);
michael@0 338
michael@0 339 fRoot = parser.getRoot();
michael@0 340 return fRoot;
michael@0 341 }
michael@0 342
michael@0 343 //////////////////////////////////////////////////////////////////////////
michael@0 344
michael@0 345 int SkDOM::countChildren(const Node* node, const char elem[]) const
michael@0 346 {
michael@0 347 int count = 0;
michael@0 348
michael@0 349 node = this->getFirstChild(node, elem);
michael@0 350 while (node)
michael@0 351 {
michael@0 352 count += 1;
michael@0 353 node = this->getNextSibling(node, elem);
michael@0 354 }
michael@0 355 return count;
michael@0 356 }
michael@0 357
michael@0 358 //////////////////////////////////////////////////////////////////////////
michael@0 359
michael@0 360 #include "SkParse.h"
michael@0 361
michael@0 362 bool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const
michael@0 363 {
michael@0 364 const char* vstr = this->findAttr(node, name);
michael@0 365 return vstr && SkParse::FindS32(vstr, value);
michael@0 366 }
michael@0 367
michael@0 368 bool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const
michael@0 369 {
michael@0 370 const char* vstr = this->findAttr(node, name);
michael@0 371 return vstr && SkParse::FindScalars(vstr, value, count);
michael@0 372 }
michael@0 373
michael@0 374 bool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const
michael@0 375 {
michael@0 376 const char* vstr = this->findAttr(node, name);
michael@0 377 return vstr && SkParse::FindHex(vstr, value);
michael@0 378 }
michael@0 379
michael@0 380 bool SkDOM::findBool(const Node* node, const char name[], bool* value) const
michael@0 381 {
michael@0 382 const char* vstr = this->findAttr(node, name);
michael@0 383 return vstr && SkParse::FindBool(vstr, value);
michael@0 384 }
michael@0 385
michael@0 386 int SkDOM::findList(const Node* node, const char name[], const char list[]) const
michael@0 387 {
michael@0 388 const char* vstr = this->findAttr(node, name);
michael@0 389 return vstr ? SkParse::FindList(vstr, list) : -1;
michael@0 390 }
michael@0 391
michael@0 392 bool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const
michael@0 393 {
michael@0 394 const char* vstr = this->findAttr(node, name);
michael@0 395 return vstr && !strcmp(vstr, value);
michael@0 396 }
michael@0 397
michael@0 398 bool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const
michael@0 399 {
michael@0 400 const char* vstr = this->findAttr(node, name);
michael@0 401 int32_t value;
michael@0 402 return vstr && SkParse::FindS32(vstr, &value) && value == target;
michael@0 403 }
michael@0 404
michael@0 405 bool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const
michael@0 406 {
michael@0 407 const char* vstr = this->findAttr(node, name);
michael@0 408 SkScalar value;
michael@0 409 return vstr && SkParse::FindScalar(vstr, &value) && value == target;
michael@0 410 }
michael@0 411
michael@0 412 bool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const
michael@0 413 {
michael@0 414 const char* vstr = this->findAttr(node, name);
michael@0 415 uint32_t value;
michael@0 416 return vstr && SkParse::FindHex(vstr, &value) && value == target;
michael@0 417 }
michael@0 418
michael@0 419 bool SkDOM::hasBool(const Node* node, const char name[], bool target) const
michael@0 420 {
michael@0 421 const char* vstr = this->findAttr(node, name);
michael@0 422 bool value;
michael@0 423 return vstr && SkParse::FindBool(vstr, &value) && value == target;
michael@0 424 }
michael@0 425
michael@0 426 //////////////////////////////////////////////////////////////////////////
michael@0 427
michael@0 428 #ifdef SK_DEBUG
michael@0 429
michael@0 430 static void tab(int level)
michael@0 431 {
michael@0 432 while (--level >= 0)
michael@0 433 SkDebugf("\t");
michael@0 434 }
michael@0 435
michael@0 436 void SkDOM::dump(const Node* node, int level) const
michael@0 437 {
michael@0 438 if (node == NULL)
michael@0 439 node = this->getRootNode();
michael@0 440 if (node)
michael@0 441 {
michael@0 442 tab(level);
michael@0 443 SkDebugf("<%s", this->getName(node));
michael@0 444
michael@0 445 const Attr* attr = node->attrs();
michael@0 446 const Attr* stop = attr + node->fAttrCount;
michael@0 447 for (; attr < stop; attr++)
michael@0 448 SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue);
michael@0 449
michael@0 450 const Node* child = this->getFirstChild(node);
michael@0 451 if (child)
michael@0 452 {
michael@0 453 SkDebugf(">\n");
michael@0 454 while (child)
michael@0 455 {
michael@0 456 this->dump(child, level+1);
michael@0 457 child = this->getNextSibling(child);
michael@0 458 }
michael@0 459 tab(level);
michael@0 460 SkDebugf("</%s>\n", node->fName);
michael@0 461 }
michael@0 462 else
michael@0 463 SkDebugf("/>\n");
michael@0 464 }
michael@0 465 }
michael@0 466
michael@0 467 void SkDOM::UnitTest()
michael@0 468 {
michael@0 469 #ifdef SK_SUPPORT_UNITTEST
michael@0 470 static const char gDoc[] =
michael@0 471 "<root a='1' b='2'>"
michael@0 472 "<elem1 c='3' />"
michael@0 473 "<elem2 d='4' />"
michael@0 474 "<elem3 e='5'>"
michael@0 475 "<subelem1/>"
michael@0 476 "<subelem2 f='6' g='7'/>"
michael@0 477 "</elem3>"
michael@0 478 "<elem4 h='8'/>"
michael@0 479 "</root>"
michael@0 480 ;
michael@0 481
michael@0 482 SkDOM dom;
michael@0 483
michael@0 484 SkASSERT(dom.getRootNode() == NULL);
michael@0 485
michael@0 486 const Node* root = dom.build(gDoc, sizeof(gDoc) - 1);
michael@0 487 SkASSERT(root && dom.getRootNode() == root);
michael@0 488
michael@0 489 const char* v = dom.findAttr(root, "a");
michael@0 490 SkASSERT(v && !strcmp(v, "1"));
michael@0 491 v = dom.findAttr(root, "b");
michael@0 492 SkASSERT(v && !strcmp(v, "2"));
michael@0 493 v = dom.findAttr(root, "c");
michael@0 494 SkASSERT(v == NULL);
michael@0 495
michael@0 496 SkASSERT(dom.getFirstChild(root, "elem1"));
michael@0 497 SkASSERT(!dom.getFirstChild(root, "subelem1"));
michael@0 498
michael@0 499 dom.dump();
michael@0 500 #endif
michael@0 501 }
michael@0 502
michael@0 503 #endif

mercurial