Home | History | Annotate | Download | only in xmllite
      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 
     21 XmlBuilder::XmlBuilder() :
     22   pelCurrent_(NULL),
     23   pelRoot_(),
     24   pvParents_(new std::vector<XmlElement *>()) {
     25 }
     26 
     27 void
     28 XmlBuilder::Reset() {
     29   pelRoot_.reset();
     30   pelCurrent_ = NULL;
     31   pvParents_->clear();
     32 }
     33 
     34 XmlElement *
     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
     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
     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
    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
    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 *
    118 XmlBuilder::CreateElement() {
    119   return pelRoot_.release();
    120 }
    121 
    122 XmlElement *
    123 XmlBuilder::BuiltElement() {
    124   return pelRoot_.get();
    125 }
    126 
    127 XmlBuilder::~XmlBuilder() {
    128 }
    129 
    130 }  // namespace buzz
    131