• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/libjingle/xmllite/xmlbuilder.h"
12 
13 #include <set>
14 #include <vector>
15 #include "webrtc/libjingle/xmllite/xmlconstants.h"
16 #include "webrtc/libjingle/xmllite/xmlelement.h"
17 #include "webrtc/base/common.h"
18 
19 namespace buzz {
20 
XmlBuilder()21 XmlBuilder::XmlBuilder() :
22   pelCurrent_(NULL),
23   pelRoot_(),
24   pvParents_(new std::vector<XmlElement *>()) {
25 }
26 
27 void
Reset()28 XmlBuilder::Reset() {
29   pelRoot_.reset();
30   pelCurrent_ = NULL;
31   pvParents_->clear();
32 }
33 
34 XmlElement *
BuildElement(XmlParseContext * pctx,const char * name,const char ** atts)35 XmlBuilder::BuildElement(XmlParseContext * pctx,
36                               const char * name, const char ** atts) {
37   QName tagName(pctx->ResolveQName(name, false));
38   if (tagName.IsEmpty())
39     return NULL;
40 
41   XmlElement * pelNew = new XmlElement(tagName);
42 
43   if (!*atts)
44     return pelNew;
45 
46   std::set<QName> seenNonlocalAtts;
47 
48   while (*atts) {
49     QName attName(pctx->ResolveQName(*atts, true));
50     if (attName.IsEmpty()) {
51       delete pelNew;
52       return NULL;
53     }
54 
55     // verify that namespaced names are unique
56     if (!attName.Namespace().empty()) {
57       if (seenNonlocalAtts.count(attName)) {
58         delete pelNew;
59         return NULL;
60       }
61       seenNonlocalAtts.insert(attName);
62     }
63 
64     pelNew->AddAttr(attName, std::string(*(atts + 1)));
65     atts += 2;
66   }
67 
68   return pelNew;
69 }
70 
71 void
StartElement(XmlParseContext * pctx,const char * name,const char ** atts)72 XmlBuilder::StartElement(XmlParseContext * pctx,
73                               const char * name, const char ** atts) {
74   XmlElement * pelNew = BuildElement(pctx, name, atts);
75   if (pelNew == NULL) {
76     pctx->RaiseError(XML_ERROR_SYNTAX);
77     return;
78   }
79 
80   if (!pelCurrent_) {
81     pelCurrent_ = pelNew;
82     pelRoot_.reset(pelNew);
83     pvParents_->push_back(NULL);
84   } else {
85     pelCurrent_->AddElement(pelNew);
86     pvParents_->push_back(pelCurrent_);
87     pelCurrent_ = pelNew;
88   }
89 }
90 
91 void
EndElement(XmlParseContext * pctx,const char * name)92 XmlBuilder::EndElement(XmlParseContext * pctx, const char * name) {
93   RTC_UNUSED(pctx);
94   RTC_UNUSED(name);
95   pelCurrent_ = pvParents_->back();
96   pvParents_->pop_back();
97 }
98 
99 void
CharacterData(XmlParseContext * pctx,const char * text,int len)100 XmlBuilder::CharacterData(XmlParseContext * pctx,
101                                const char * text, int len) {
102   RTC_UNUSED(pctx);
103   if (pelCurrent_) {
104     pelCurrent_->AddParsedText(text, len);
105   }
106 }
107 
108 void
Error(XmlParseContext * pctx,XML_Error err)109 XmlBuilder::Error(XmlParseContext * pctx, XML_Error err) {
110   RTC_UNUSED(pctx);
111   RTC_UNUSED(err);
112   pelRoot_.reset(NULL);
113   pelCurrent_ = NULL;
114   pvParents_->clear();
115 }
116 
117 XmlElement *
CreateElement()118 XmlBuilder::CreateElement() {
119   return pelRoot_.release();
120 }
121 
122 XmlElement *
BuiltElement()123 XmlBuilder::BuiltElement() {
124   return pelRoot_.get();
125 }
126 
~XmlBuilder()127 XmlBuilder::~XmlBuilder() {
128 }
129 
130 }  // namespace buzz
131