gfx/skia/trunk/src/xml/SkDOM.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial