SkDOM.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*
  2. * Copyright 2006 The Android Open Source Project
  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. #include "src/xml/SkDOM.h"
  8. #include "include/core/SkStream.h"
  9. #include "include/private/SkTo.h"
  10. #include "src/xml/SkXMLParser.h"
  11. #include "src/xml/SkXMLWriter.h"
  12. bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) {
  13. const char* elemName = dom.getName(node);
  14. if (this->startElement(elemName)) {
  15. return false;
  16. }
  17. SkDOM::AttrIter iter(dom, node);
  18. const char* name, *value;
  19. while ((name = iter.next(&value)) != nullptr) {
  20. if (this->addAttribute(name, value)) {
  21. return false;
  22. }
  23. }
  24. if ((node = dom.getFirstChild(node)) != nullptr) {
  25. do {
  26. if (!this->parse(dom, node)) {
  27. return false;
  28. }
  29. } while ((node = dom.getNextSibling(node)) != nullptr);
  30. }
  31. return !this->endElement(elemName);
  32. }
  33. /////////////////////////////////////////////////////////////////////////
  34. struct SkDOMAttr {
  35. const char* fName;
  36. const char* fValue;
  37. };
  38. struct SkDOMNode {
  39. const char* fName;
  40. SkDOMNode* fFirstChild;
  41. SkDOMNode* fNextSibling;
  42. SkDOMAttr* fAttrs;
  43. uint16_t fAttrCount;
  44. uint8_t fType;
  45. uint8_t fPad;
  46. const SkDOMAttr* attrs() const {
  47. return fAttrs;
  48. }
  49. SkDOMAttr* attrs() {
  50. return fAttrs;
  51. }
  52. };
  53. /////////////////////////////////////////////////////////////////////////
  54. #define kMinChunkSize 4096
  55. SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(nullptr) {}
  56. SkDOM::~SkDOM() {}
  57. const SkDOM::Node* SkDOM::getRootNode() const {
  58. return fRoot;
  59. }
  60. const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const {
  61. SkASSERT(node);
  62. const Node* child = node->fFirstChild;
  63. if (name) {
  64. for (; child != nullptr; child = child->fNextSibling) {
  65. if (!strcmp(name, child->fName)) {
  66. break;
  67. }
  68. }
  69. }
  70. return child;
  71. }
  72. const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const {
  73. SkASSERT(node);
  74. const Node* sibling = node->fNextSibling;
  75. if (name) {
  76. for (; sibling != nullptr; sibling = sibling->fNextSibling) {
  77. if (!strcmp(name, sibling->fName)) {
  78. break;
  79. }
  80. }
  81. }
  82. return sibling;
  83. }
  84. SkDOM::Type SkDOM::getType(const Node* node) const {
  85. SkASSERT(node);
  86. return (Type)node->fType;
  87. }
  88. const char* SkDOM::getName(const Node* node) const {
  89. SkASSERT(node);
  90. return node->fName;
  91. }
  92. const char* SkDOM::findAttr(const Node* node, const char name[]) const {
  93. SkASSERT(node);
  94. const Attr* attr = node->attrs();
  95. const Attr* stop = attr + node->fAttrCount;
  96. while (attr < stop) {
  97. if (!strcmp(attr->fName, name)) {
  98. return attr->fValue;
  99. }
  100. attr += 1;
  101. }
  102. return nullptr;
  103. }
  104. /////////////////////////////////////////////////////////////////////////////////////
  105. const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const {
  106. return node->fAttrCount ? node->attrs() : nullptr;
  107. }
  108. const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const {
  109. SkASSERT(node);
  110. if (attr == nullptr) {
  111. return nullptr;
  112. }
  113. return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : nullptr;
  114. }
  115. const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const {
  116. SkASSERT(node);
  117. SkASSERT(attr);
  118. return attr->fName;
  119. }
  120. const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const {
  121. SkASSERT(node);
  122. SkASSERT(attr);
  123. return attr->fValue;
  124. }
  125. /////////////////////////////////////////////////////////////////////////////////////
  126. SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) {
  127. SkASSERT(node);
  128. fAttr = node->attrs();
  129. fStop = fAttr + node->fAttrCount;
  130. }
  131. const char* SkDOM::AttrIter::next(const char** value) {
  132. const char* name = nullptr;
  133. if (fAttr < fStop) {
  134. name = fAttr->fName;
  135. if (value)
  136. *value = fAttr->fValue;
  137. fAttr += 1;
  138. }
  139. return name;
  140. }
  141. //////////////////////////////////////////////////////////////////////////////
  142. #include "include/private/SkTDArray.h"
  143. #include "src/xml/SkXMLParser.h"
  144. static char* dupstr(SkArenaAlloc* chunk, const char src[]) {
  145. SkASSERT(chunk && src);
  146. size_t len = strlen(src);
  147. char* dst = chunk->makeArrayDefault<char>(len + 1);
  148. memcpy(dst, src, len + 1);
  149. return dst;
  150. }
  151. class SkDOMParser : public SkXMLParser {
  152. public:
  153. SkDOMParser(SkArenaAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) {
  154. fAlloc->reset();
  155. fRoot = nullptr;
  156. fLevel = 0;
  157. fNeedToFlush = true;
  158. }
  159. SkDOM::Node* getRoot() const { return fRoot; }
  160. SkXMLParserError fParserError;
  161. protected:
  162. void flushAttributes() {
  163. SkASSERT(fLevel > 0);
  164. int attrCount = fAttrs.count();
  165. SkDOMAttr* attrs = fAlloc->makeArrayDefault<SkDOMAttr>(attrCount);
  166. SkDOM::Node* node = fAlloc->make<SkDOM::Node>();
  167. node->fName = fElemName;
  168. node->fFirstChild = nullptr;
  169. node->fAttrCount = SkToU16(attrCount);
  170. node->fAttrs = attrs;
  171. node->fType = fElemType;
  172. if (fRoot == nullptr) {
  173. node->fNextSibling = nullptr;
  174. fRoot = node;
  175. } else { // this adds siblings in reverse order. gets corrected in onEndElement()
  176. SkDOM::Node* parent = fParentStack.top();
  177. SkASSERT(fRoot && parent);
  178. node->fNextSibling = parent->fFirstChild;
  179. parent->fFirstChild = node;
  180. }
  181. *fParentStack.push() = node;
  182. sk_careful_memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr));
  183. fAttrs.reset();
  184. }
  185. bool onStartElement(const char elem[]) override {
  186. this->startCommon(elem, SkDOM::kElement_Type);
  187. return false;
  188. }
  189. bool onAddAttribute(const char name[], const char value[]) override {
  190. SkDOM::Attr* attr = fAttrs.append();
  191. attr->fName = dupstr(fAlloc, name);
  192. attr->fValue = dupstr(fAlloc, value);
  193. return false;
  194. }
  195. bool onEndElement(const char elem[]) override {
  196. --fLevel;
  197. if (fNeedToFlush)
  198. this->flushAttributes();
  199. fNeedToFlush = false;
  200. SkDOM::Node* parent;
  201. fParentStack.pop(&parent);
  202. SkDOM::Node* child = parent->fFirstChild;
  203. SkDOM::Node* prev = nullptr;
  204. while (child) {
  205. SkDOM::Node* next = child->fNextSibling;
  206. child->fNextSibling = prev;
  207. prev = child;
  208. child = next;
  209. }
  210. parent->fFirstChild = prev;
  211. return false;
  212. }
  213. bool onText(const char text[], int len) override {
  214. SkString str(text, len);
  215. this->startCommon(str.c_str(), SkDOM::kText_Type);
  216. this->SkDOMParser::onEndElement(str.c_str());
  217. return false;
  218. }
  219. private:
  220. void startCommon(const char elem[], SkDOM::Type type) {
  221. if (fLevel > 0 && fNeedToFlush) {
  222. this->flushAttributes();
  223. }
  224. fNeedToFlush = true;
  225. fElemName = dupstr(fAlloc, elem);
  226. fElemType = type;
  227. ++fLevel;
  228. }
  229. SkTDArray<SkDOM::Node*> fParentStack;
  230. SkArenaAlloc* fAlloc;
  231. SkDOM::Node* fRoot;
  232. bool fNeedToFlush;
  233. // state needed for flushAttributes()
  234. SkTDArray<SkDOM::Attr> fAttrs;
  235. char* fElemName;
  236. SkDOM::Type fElemType;
  237. int fLevel;
  238. };
  239. const SkDOM::Node* SkDOM::build(SkStream& docStream) {
  240. SkDOMParser parser(&fAlloc);
  241. if (!parser.parse(docStream))
  242. {
  243. SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
  244. fRoot = nullptr;
  245. fAlloc.reset();
  246. return nullptr;
  247. }
  248. fRoot = parser.getRoot();
  249. return fRoot;
  250. }
  251. ///////////////////////////////////////////////////////////////////////////
  252. static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) {
  253. const char* elem = dom.getName(node);
  254. if (dom.getType(node) == SkDOM::kText_Type) {
  255. SkASSERT(dom.countChildren(node) == 0);
  256. parser->text(elem, SkToInt(strlen(elem)));
  257. return;
  258. }
  259. parser->startElement(elem);
  260. SkDOM::AttrIter iter(dom, node);
  261. const char* name;
  262. const char* value;
  263. while ((name = iter.next(&value)) != nullptr)
  264. parser->addAttribute(name, value);
  265. node = dom.getFirstChild(node, nullptr);
  266. while (node)
  267. {
  268. walk_dom(dom, node, parser);
  269. node = dom.getNextSibling(node, nullptr);
  270. }
  271. parser->endElement(elem);
  272. }
  273. const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) {
  274. SkDOMParser parser(&fAlloc);
  275. walk_dom(dom, node, &parser);
  276. fRoot = parser.getRoot();
  277. return fRoot;
  278. }
  279. SkXMLParser* SkDOM::beginParsing() {
  280. SkASSERT(!fParser);
  281. fParser.reset(new SkDOMParser(&fAlloc));
  282. return fParser.get();
  283. }
  284. const SkDOM::Node* SkDOM::finishParsing() {
  285. SkASSERT(fParser);
  286. fRoot = fParser->getRoot();
  287. fParser.reset();
  288. return fRoot;
  289. }
  290. //////////////////////////////////////////////////////////////////////////
  291. int SkDOM::countChildren(const Node* node, const char elem[]) const {
  292. int count = 0;
  293. node = this->getFirstChild(node, elem);
  294. while (node) {
  295. count += 1;
  296. node = this->getNextSibling(node, elem);
  297. }
  298. return count;
  299. }
  300. //////////////////////////////////////////////////////////////////////////
  301. #include "include/utils/SkParse.h"
  302. bool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const {
  303. const char* vstr = this->findAttr(node, name);
  304. return vstr && SkParse::FindS32(vstr, value);
  305. }
  306. bool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const {
  307. const char* vstr = this->findAttr(node, name);
  308. return vstr && SkParse::FindScalars(vstr, value, count);
  309. }
  310. bool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const {
  311. const char* vstr = this->findAttr(node, name);
  312. return vstr && SkParse::FindHex(vstr, value);
  313. }
  314. bool SkDOM::findBool(const Node* node, const char name[], bool* value) const {
  315. const char* vstr = this->findAttr(node, name);
  316. return vstr && SkParse::FindBool(vstr, value);
  317. }
  318. int SkDOM::findList(const Node* node, const char name[], const char list[]) const {
  319. const char* vstr = this->findAttr(node, name);
  320. return vstr ? SkParse::FindList(vstr, list) : -1;
  321. }
  322. bool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const {
  323. const char* vstr = this->findAttr(node, name);
  324. return vstr && !strcmp(vstr, value);
  325. }
  326. bool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const {
  327. const char* vstr = this->findAttr(node, name);
  328. int32_t value;
  329. return vstr && SkParse::FindS32(vstr, &value) && value == target;
  330. }
  331. bool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const {
  332. const char* vstr = this->findAttr(node, name);
  333. SkScalar value;
  334. return vstr && SkParse::FindScalar(vstr, &value) && value == target;
  335. }
  336. bool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const {
  337. const char* vstr = this->findAttr(node, name);
  338. uint32_t value;
  339. return vstr && SkParse::FindHex(vstr, &value) && value == target;
  340. }
  341. bool SkDOM::hasBool(const Node* node, const char name[], bool target) const {
  342. const char* vstr = this->findAttr(node, name);
  343. bool value;
  344. return vstr && SkParse::FindBool(vstr, &value) && value == target;
  345. }