Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(971)

Side by Side Diff: src/xml/SkDOM.cpp

Issue 940283002: [SVGDevice] Text whitespace unittest (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: more win warnings Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/svg/SkSVGDevice.cpp ('k') | src/xml/SkXMLWriter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkDOM.h" 10 #include "SkDOM.h"
11 #include "SkStream.h"
12 #include "SkXMLWriter.h"
11 13
12 ///////////////////////////////////////////////////////////////////////// 14 /////////////////////////////////////////////////////////////////////////
13 15
14 #include "SkXMLParser.h" 16 #include "SkXMLParser.h"
15
16 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) 17 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node)
17 { 18 {
18 const char* elemName = dom.getName(node); 19 const char* elemName = dom.getName(node);
19 20
20 if (this->startElement(elemName)) 21 if (this->startElement(elemName))
21 return false; 22 return false;
22 23
23 SkDOM::AttrIter iter(dom, node); 24 SkDOM::AttrIter iter(dom, node);
24 const char* name, *value; 25 const char* name, *value;
25 26
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 static char* dupstr(SkChunkAlloc* chunk, const char src[]) 193 static char* dupstr(SkChunkAlloc* chunk, const char src[])
193 { 194 {
194 SkASSERT(chunk && src); 195 SkASSERT(chunk && src);
195 size_t len = strlen(src); 196 size_t len = strlen(src);
196 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp e); 197 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp e);
197 memcpy(dst, src, len + 1); 198 memcpy(dst, src, len + 1);
198 return dst; 199 return dst;
199 } 200 }
200 201
201 class SkDOMParser : public SkXMLParser { 202 class SkDOMParser : public SkXMLParser {
202 bool fNeedToFlush;
203 public: 203 public:
204 SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) 204 SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk)
205 { 205 {
206 fAlloc->reset();
206 fRoot = NULL; 207 fRoot = NULL;
207 fLevel = 0; 208 fLevel = 0;
208 fNeedToFlush = true; 209 fNeedToFlush = true;
209 } 210 }
210 SkDOM::Node* getRoot() const { return fRoot; } 211 SkDOM::Node* getRoot() const { return fRoot; }
211 SkXMLParserError fParserError; 212 SkXMLParserError fParserError;
213
212 protected: 214 protected:
213 void flushAttributes() 215 void flushAttributes()
214 { 216 {
217 SkASSERT(fLevel > 0);
218
215 int attrCount = fAttrs.count(); 219 int attrCount = fAttrs.count();
216 220
217 SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + at trCount * sizeof(SkDOM::Attr), 221 SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + at trCount * sizeof(SkDOM::Attr),
218 SkChunkAlloc::kThrow_All ocFailType); 222 SkChunkAlloc::kThrow_All ocFailType);
219 223
220 node->fName = fElemName; 224 node->fName = fElemName;
221 node->fFirstChild = NULL; 225 node->fFirstChild = NULL;
222 node->fAttrCount = SkToU16(attrCount); 226 node->fAttrCount = SkToU16(attrCount);
223 node->fType = SkDOM::kElement_Type; 227 node->fType = fElemType;
224 228
225 if (fRoot == NULL) 229 if (fRoot == NULL)
226 { 230 {
227 node->fNextSibling = NULL; 231 node->fNextSibling = NULL;
228 fRoot = node; 232 fRoot = node;
229 } 233 }
230 else // this adds siblings in reverse order. gets corrected in onEndE lement() 234 else // this adds siblings in reverse order. gets corrected in onEndE lement()
231 { 235 {
232 SkDOM::Node* parent = fParentStack.top(); 236 SkDOM::Node* parent = fParentStack.top();
233 SkASSERT(fRoot && parent); 237 SkASSERT(fRoot && parent);
234 node->fNextSibling = parent->fFirstChild; 238 node->fNextSibling = parent->fFirstChild;
235 parent->fFirstChild = node; 239 parent->fFirstChild = node;
236 } 240 }
237 *fParentStack.push() = node; 241 *fParentStack.push() = node;
238 242
239 memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); 243 memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr));
240 fAttrs.reset(); 244 fAttrs.reset();
241 245
242 } 246 }
243 virtual bool onStartElement(const char elem[]) 247
244 { 248 bool onStartElement(const char elem[]) override {
245 if (fLevel > 0 && fNeedToFlush) 249 this->startCommon(elem, SkDOM::kElement_Type);
246 this->flushAttributes();
247 fNeedToFlush = true;
248 fElemName = dupstr(fAlloc, elem);
249 ++fLevel;
250 return false; 250 return false;
251 } 251 }
252 virtual bool onAddAttribute(const char name[], const char value[]) 252
253 { 253 bool onAddAttribute(const char name[], const char value[]) override {
254 SkDOM::Attr* attr = fAttrs.append(); 254 SkDOM::Attr* attr = fAttrs.append();
255 attr->fName = dupstr(fAlloc, name); 255 attr->fName = dupstr(fAlloc, name);
256 attr->fValue = dupstr(fAlloc, value); 256 attr->fValue = dupstr(fAlloc, value);
257 return false; 257 return false;
258 } 258 }
259 virtual bool onEndElement(const char elem[]) 259
260 { 260 bool onEndElement(const char elem[]) override {
261 --fLevel; 261 --fLevel;
262 if (fNeedToFlush) 262 if (fNeedToFlush)
263 this->flushAttributes(); 263 this->flushAttributes();
264 fNeedToFlush = false; 264 fNeedToFlush = false;
265 265
266 SkDOM::Node* parent; 266 SkDOM::Node* parent;
267 267
268 fParentStack.pop(&parent); 268 fParentStack.pop(&parent);
269 269
270 SkDOM::Node* child = parent->fFirstChild; 270 SkDOM::Node* child = parent->fFirstChild;
271 SkDOM::Node* prev = NULL; 271 SkDOM::Node* prev = NULL;
272 while (child) 272 while (child)
273 { 273 {
274 SkDOM::Node* next = child->fNextSibling; 274 SkDOM::Node* next = child->fNextSibling;
275 child->fNextSibling = prev; 275 child->fNextSibling = prev;
276 prev = child; 276 prev = child;
277 child = next; 277 child = next;
278 } 278 }
279 parent->fFirstChild = prev; 279 parent->fFirstChild = prev;
280 return false; 280 return false;
281 } 281 }
282
283 bool onText(const char text[], int len) override {
284 SkString str(text, len);
285 this->startCommon(str.c_str(), SkDOM::kText_Type);
286 this->SkDOMParser::onEndElement(str.c_str());
287
288 return false;
289 }
290
282 private: 291 private:
292 void startCommon(const char elem[], SkDOM::Type type) {
293 if (fLevel > 0 && fNeedToFlush)
294 this->flushAttributes();
295
296 fNeedToFlush = true;
297 fElemName = dupstr(fAlloc, elem);
298 fElemType = type;
299 ++fLevel;
300 }
301
283 SkTDArray<SkDOM::Node*> fParentStack; 302 SkTDArray<SkDOM::Node*> fParentStack;
284 SkChunkAlloc* fAlloc; 303 SkChunkAlloc* fAlloc;
285 SkDOM::Node* fRoot; 304 SkDOM::Node* fRoot;
305 bool fNeedToFlush;
286 306
287 // state needed for flushAttributes() 307 // state needed for flushAttributes()
288 SkTDArray<SkDOM::Attr> fAttrs; 308 SkTDArray<SkDOM::Attr> fAttrs;
289 char* fElemName; 309 char* fElemName;
310 SkDOM::Type fElemType;
290 int fLevel; 311 int fLevel;
291 }; 312 };
292 313
293 const SkDOM::Node* SkDOM::build(const char doc[], size_t len) 314 const SkDOM::Node* SkDOM::build(const char doc[], size_t len)
294 { 315 {
295 fAlloc.reset();
296 SkDOMParser parser(&fAlloc); 316 SkDOMParser parser(&fAlloc);
297 if (!parser.parse(doc, len)) 317 if (!parser.parse(doc, len))
298 { 318 {
299 SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.g etLineNumber());) 319 SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.g etLineNumber());)
300 fRoot = NULL; 320 fRoot = NULL;
301 fAlloc.reset(); 321 fAlloc.reset();
302 return NULL; 322 return NULL;
303 } 323 }
304 fRoot = parser.getRoot(); 324 fRoot = parser.getRoot();
305 return fRoot; 325 return fRoot;
306 } 326 }
307 327
308 /////////////////////////////////////////////////////////////////////////// 328 ///////////////////////////////////////////////////////////////////////////
309 329
310 static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par ser) 330 static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par ser)
311 { 331 {
312 const char* elem = dom.getName(node); 332 const char* elem = dom.getName(node);
333 if (dom.getType(node) == SkDOM::kText_Type) {
334 SkASSERT(dom.countChildren(node) == 0);
335 parser->text(elem, SkToInt(strlen(elem)));
336 return;
337 }
313 338
314 parser->startElement(elem); 339 parser->startElement(elem);
315 340
316 SkDOM::AttrIter iter(dom, node); 341 SkDOM::AttrIter iter(dom, node);
317 const char* name; 342 const char* name;
318 const char* value; 343 const char* value;
319 while ((name = iter.next(&value)) != NULL) 344 while ((name = iter.next(&value)) != NULL)
320 parser->addAttribute(name, value); 345 parser->addAttribute(name, value);
321 346
322 node = dom.getFirstChild(node, NULL); 347 node = dom.getFirstChild(node, NULL);
323 while (node) 348 while (node)
324 { 349 {
325 walk_dom(dom, node, parser); 350 walk_dom(dom, node, parser);
326 node = dom.getNextSibling(node, NULL); 351 node = dom.getNextSibling(node, NULL);
327 } 352 }
328 353
329 parser->endElement(elem); 354 parser->endElement(elem);
330 } 355 }
331 356
332 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) 357 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node)
333 { 358 {
334 fAlloc.reset();
335 SkDOMParser parser(&fAlloc); 359 SkDOMParser parser(&fAlloc);
336 360
337 walk_dom(dom, node, &parser); 361 walk_dom(dom, node, &parser);
338 362
339 fRoot = parser.getRoot(); 363 fRoot = parser.getRoot();
340 return fRoot; 364 return fRoot;
341 } 365 }
342 366
367 SkXMLParser* SkDOM::beginParsing() {
368 SkASSERT(!fParser);
369 fParser.reset(SkNEW_ARGS(SkDOMParser, (&fAlloc)));
370
371 return fParser.get();
372 }
373
374 const SkDOM::Node* SkDOM::finishParsing() {
375 SkASSERT(fParser);
376 fRoot = fParser->getRoot();
377 fParser.free();
378
379 return fRoot;
380 }
381
343 ////////////////////////////////////////////////////////////////////////// 382 //////////////////////////////////////////////////////////////////////////
344 383
345 int SkDOM::countChildren(const Node* node, const char elem[]) const 384 int SkDOM::countChildren(const Node* node, const char elem[]) const
346 { 385 {
347 int count = 0; 386 int count = 0;
348 387
349 node = this->getFirstChild(node, elem); 388 node = this->getFirstChild(node, elem);
350 while (node) 389 while (node)
351 { 390 {
352 count += 1; 391 count += 1;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 { 459 {
421 const char* vstr = this->findAttr(node, name); 460 const char* vstr = this->findAttr(node, name);
422 bool value; 461 bool value;
423 return vstr && SkParse::FindBool(vstr, &value) && value == target; 462 return vstr && SkParse::FindBool(vstr, &value) && value == target;
424 } 463 }
425 464
426 ////////////////////////////////////////////////////////////////////////// 465 //////////////////////////////////////////////////////////////////////////
427 466
428 #ifdef SK_DEBUG 467 #ifdef SK_DEBUG
429 468
430 static void tab(int level)
431 {
432 while (--level >= 0)
433 SkDebugf("\t");
434 }
435
436 void SkDOM::dump(const Node* node, int level) const 469 void SkDOM::dump(const Node* node, int level) const
437 { 470 {
438 if (node == NULL) 471 if (node == NULL)
439 node = this->getRootNode(); 472 node = this->getRootNode();
440 if (node)
441 {
442 tab(level);
443 SkDebugf("<%s", this->getName(node));
444 473
445 const Attr* attr = node->attrs(); 474 SkDebugWStream debugStream;
446 const Attr* stop = attr + node->fAttrCount; 475 SkXMLStreamWriter xmlWriter(&debugStream);
447 for (; attr < stop; attr++) 476 xmlWriter.writeDOM(*this, node, false);
448 SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue);
449
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 } 477 }
466 478
467 void SkDOM::UnitTest() 479 void SkDOM::UnitTest()
468 { 480 {
469 #ifdef SK_SUPPORT_UNITTEST 481 #ifdef SK_SUPPORT_UNITTEST
470 static const char gDoc[] = 482 static const char gDoc[] =
471 "<root a='1' b='2'>" 483 "<root a='1' b='2'>"
472 "<elem1 c='3' />" 484 "<elem1 c='3' />"
473 "<elem2 d='4' />" 485 "<elem2 d='4' />"
474 "<elem3 e='5'>" 486 "<elem3 e='5'>"
(...skipping 19 matching lines...) Expand all
494 SkASSERT(v == NULL); 506 SkASSERT(v == NULL);
495 507
496 SkASSERT(dom.getFirstChild(root, "elem1")); 508 SkASSERT(dom.getFirstChild(root, "elem1"));
497 SkASSERT(!dom.getFirstChild(root, "subelem1")); 509 SkASSERT(!dom.getFirstChild(root, "subelem1"));
498 510
499 dom.dump(); 511 dom.dump();
500 #endif 512 #endif
501 } 513 }
502 514
503 #endif 515 #endif
OLDNEW
« no previous file with comments | « src/svg/SkSVGDevice.cpp ('k') | src/xml/SkXMLWriter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698