| Index: webrtc/libjingle/xmllite/xmlelement.cc
|
| diff --git a/webrtc/libjingle/xmllite/xmlelement.cc b/webrtc/libjingle/xmllite/xmlelement.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2d90836ec1d51099e1f42de8ae2210cfd043536f
|
| --- /dev/null
|
| +++ b/webrtc/libjingle/xmllite/xmlelement.cc
|
| @@ -0,0 +1,496 @@
|
| +/*
|
| + * Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/libjingle/xmllite/xmlelement.h"
|
| +
|
| +#include <ostream>
|
| +#include <sstream>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "webrtc/libjingle/xmllite/qname.h"
|
| +#include "webrtc/libjingle/xmllite/xmlbuilder.h"
|
| +#include "webrtc/libjingle/xmllite/xmlconstants.h"
|
| +#include "webrtc/libjingle/xmllite/xmlparser.h"
|
| +#include "webrtc/libjingle/xmllite/xmlprinter.h"
|
| +#include "webrtc/base/common.h"
|
| +
|
| +namespace buzz {
|
| +
|
| +XmlChild::~XmlChild() {
|
| +}
|
| +
|
| +bool XmlText::IsTextImpl() const {
|
| + return true;
|
| +}
|
| +
|
| +XmlElement* XmlText::AsElementImpl() const {
|
| + return NULL;
|
| +}
|
| +
|
| +XmlText* XmlText::AsTextImpl() const {
|
| + return const_cast<XmlText *>(this);
|
| +}
|
| +
|
| +void XmlText::SetText(const std::string& text) {
|
| + text_ = text;
|
| +}
|
| +
|
| +void XmlText::AddParsedText(const char* buf, int len) {
|
| + text_.append(buf, len);
|
| +}
|
| +
|
| +void XmlText::AddText(const std::string& text) {
|
| + text_ += text;
|
| +}
|
| +
|
| +XmlText::~XmlText() {
|
| +}
|
| +
|
| +XmlElement::XmlElement(const QName& name) :
|
| + name_(name),
|
| + first_attr_(NULL),
|
| + last_attr_(NULL),
|
| + first_child_(NULL),
|
| + last_child_(NULL),
|
| + cdata_(false) {
|
| +}
|
| +
|
| +XmlElement::XmlElement(const XmlElement& elt) :
|
| + XmlChild(),
|
| + name_(elt.name_),
|
| + first_attr_(NULL),
|
| + last_attr_(NULL),
|
| + first_child_(NULL),
|
| + last_child_(NULL),
|
| + cdata_(false) {
|
| +
|
| + // copy attributes
|
| + XmlAttr* attr;
|
| + XmlAttr ** plast_attr = &first_attr_;
|
| + XmlAttr* newAttr = NULL;
|
| + for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
|
| + newAttr = new XmlAttr(*attr);
|
| + *plast_attr = newAttr;
|
| + plast_attr = &(newAttr->next_attr_);
|
| + }
|
| + last_attr_ = newAttr;
|
| +
|
| + // copy children
|
| + XmlChild* pChild;
|
| + XmlChild ** ppLast = &first_child_;
|
| + XmlChild* newChild = NULL;
|
| +
|
| + for (pChild = elt.first_child_; pChild; pChild = pChild->NextChild()) {
|
| + if (pChild->IsText()) {
|
| + newChild = new XmlText(*(pChild->AsText()));
|
| + } else {
|
| + newChild = new XmlElement(*(pChild->AsElement()));
|
| + }
|
| + *ppLast = newChild;
|
| + ppLast = &(newChild->next_child_);
|
| + }
|
| + last_child_ = newChild;
|
| +
|
| + cdata_ = elt.cdata_;
|
| +}
|
| +
|
| +XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
|
| + name_(name),
|
| + first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
|
| + last_attr_(first_attr_),
|
| + first_child_(NULL),
|
| + last_child_(NULL),
|
| + cdata_(false) {
|
| +}
|
| +
|
| +bool XmlElement::IsTextImpl() const {
|
| + return false;
|
| +}
|
| +
|
| +XmlElement* XmlElement::AsElementImpl() const {
|
| + return const_cast<XmlElement *>(this);
|
| +}
|
| +
|
| +XmlText* XmlElement::AsTextImpl() const {
|
| + return NULL;
|
| +}
|
| +
|
| +const std::string XmlElement::BodyText() const {
|
| + if (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
|
| + return first_child_->AsText()->Text();
|
| + }
|
| +
|
| + return std::string();
|
| +}
|
| +
|
| +void XmlElement::SetBodyText(const std::string& text) {
|
| + if (text.empty()) {
|
| + ClearChildren();
|
| + } else if (first_child_ == NULL) {
|
| + AddText(text);
|
| + } else if (first_child_->IsText() && last_child_ == first_child_) {
|
| + first_child_->AsText()->SetText(text);
|
| + } else {
|
| + ClearChildren();
|
| + AddText(text);
|
| + }
|
| +}
|
| +
|
| +const QName XmlElement::FirstElementName() const {
|
| + const XmlElement* element = FirstElement();
|
| + if (element == NULL)
|
| + return QName();
|
| + return element->Name();
|
| +}
|
| +
|
| +XmlAttr* XmlElement::FirstAttr() {
|
| + return first_attr_;
|
| +}
|
| +
|
| +const std::string XmlElement::Attr(const StaticQName& name) const {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + return attr->value_;
|
| + }
|
| + return std::string();
|
| +}
|
| +
|
| +const std::string XmlElement::Attr(const QName& name) const {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + return attr->value_;
|
| + }
|
| + return std::string();
|
| +}
|
| +
|
| +bool XmlElement::HasAttr(const StaticQName& name) const {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool XmlElement::HasAttr(const QName& name) const {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void XmlElement::SetAttr(const QName& name, const std::string& value) {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + break;
|
| + }
|
| + if (!attr) {
|
| + attr = new XmlAttr(name, value);
|
| + if (last_attr_)
|
| + last_attr_->next_attr_ = attr;
|
| + else
|
| + first_attr_ = attr;
|
| + last_attr_ = attr;
|
| + return;
|
| + }
|
| + attr->value_ = value;
|
| +}
|
| +
|
| +void XmlElement::ClearAttr(const QName& name) {
|
| + XmlAttr* attr;
|
| + XmlAttr* last_attr = NULL;
|
| + for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
| + if (attr->name_ == name)
|
| + break;
|
| + last_attr = attr;
|
| + }
|
| + if (!attr)
|
| + return;
|
| + if (!last_attr)
|
| + first_attr_ = attr->next_attr_;
|
| + else
|
| + last_attr->next_attr_ = attr->next_attr_;
|
| + if (last_attr_ == attr)
|
| + last_attr_ = last_attr;
|
| + delete attr;
|
| +}
|
| +
|
| +XmlChild* XmlElement::FirstChild() {
|
| + return first_child_;
|
| +}
|
| +
|
| +XmlElement* XmlElement::FirstElement() {
|
| + XmlChild* pChild;
|
| + for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText())
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement* XmlElement::NextElement() {
|
| + XmlChild* pChild;
|
| + for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText())
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement* XmlElement::FirstWithNamespace(const std::string& ns) {
|
| + XmlChild* pChild;
|
| + for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement *
|
| +XmlElement::NextWithNamespace(const std::string& ns) {
|
| + XmlChild* pChild;
|
| + for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement *
|
| +XmlElement::FirstNamed(const QName& name) {
|
| + XmlChild* pChild;
|
| + for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement *
|
| +XmlElement::FirstNamed(const StaticQName& name) {
|
| + XmlChild* pChild;
|
| + for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement *
|
| +XmlElement::NextNamed(const QName& name) {
|
| + XmlChild* pChild;
|
| + for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement *
|
| +XmlElement::NextNamed(const StaticQName& name) {
|
| + XmlChild* pChild;
|
| + for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
| + return pChild->AsElement();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
|
| + XmlElement* child = FirstNamed(name);
|
| + if (!child) {
|
| + child = new XmlElement(name);
|
| + AddElement(child);
|
| + }
|
| +
|
| + return child;
|
| +}
|
| +
|
| +const std::string XmlElement::TextNamed(const QName& name) const {
|
| + XmlChild* pChild;
|
| + for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
| + if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
| + return pChild->AsElement()->BodyText();
|
| + }
|
| + return std::string();
|
| +}
|
| +
|
| +void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
|
| + if (predecessor == NULL) {
|
| + next->next_child_ = first_child_;
|
| + first_child_ = next;
|
| + }
|
| + else {
|
| + next->next_child_ = predecessor->next_child_;
|
| + predecessor->next_child_ = next;
|
| + }
|
| +}
|
| +
|
| +void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
|
| + XmlChild* next;
|
| +
|
| + if (predecessor == NULL) {
|
| + next = first_child_;
|
| + first_child_ = next->next_child_;
|
| + }
|
| + else {
|
| + next = predecessor->next_child_;
|
| + predecessor->next_child_ = next->next_child_;
|
| + }
|
| +
|
| + if (last_child_ == next)
|
| + last_child_ = predecessor;
|
| +
|
| + delete next;
|
| +}
|
| +
|
| +void XmlElement::AddAttr(const QName& name, const std::string& value) {
|
| + ASSERT(!HasAttr(name));
|
| +
|
| + XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
|
| + last_attr_ = (*pprev = new XmlAttr(name, value));
|
| +}
|
| +
|
| +void XmlElement::AddAttr(const QName& name, const std::string& value,
|
| + int depth) {
|
| + XmlElement* element = this;
|
| + while (depth--) {
|
| + element = element->last_child_->AsElement();
|
| + }
|
| + element->AddAttr(name, value);
|
| +}
|
| +
|
| +void XmlElement::AddParsedText(const char* cstr, int len) {
|
| + if (len == 0)
|
| + return;
|
| +
|
| + if (last_child_ && last_child_->IsText()) {
|
| + last_child_->AsText()->AddParsedText(cstr, len);
|
| + return;
|
| + }
|
| + XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
| + last_child_ = *pprev = new XmlText(cstr, len);
|
| +}
|
| +
|
| +void XmlElement::AddCDATAText(const char* buf, int len) {
|
| + cdata_ = true;
|
| + AddParsedText(buf, len);
|
| +}
|
| +
|
| +void XmlElement::AddText(const std::string& text) {
|
| + if (text == STR_EMPTY)
|
| + return;
|
| +
|
| + if (last_child_ && last_child_->IsText()) {
|
| + last_child_->AsText()->AddText(text);
|
| + return;
|
| + }
|
| + XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
| + last_child_ = *pprev = new XmlText(text);
|
| +}
|
| +
|
| +void XmlElement::AddText(const std::string& text, int depth) {
|
| + // note: the first syntax is ambigious for msvc 6
|
| + // XmlElement* pel(this);
|
| + XmlElement* element = this;
|
| + while (depth--) {
|
| + element = element->last_child_->AsElement();
|
| + }
|
| + element->AddText(text);
|
| +}
|
| +
|
| +void XmlElement::AddElement(XmlElement *child) {
|
| + if (child == NULL)
|
| + return;
|
| +
|
| + XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
| + *pprev = child;
|
| + last_child_ = child;
|
| + child->next_child_ = NULL;
|
| +}
|
| +
|
| +void XmlElement::AddElement(XmlElement *child, int depth) {
|
| + XmlElement* element = this;
|
| + while (depth--) {
|
| + element = element->last_child_->AsElement();
|
| + }
|
| + element->AddElement(child);
|
| +}
|
| +
|
| +void XmlElement::ClearNamedChildren(const QName& name) {
|
| + XmlChild* prev_child = NULL;
|
| + XmlChild* next_child;
|
| + XmlChild* child;
|
| + for (child = FirstChild(); child; child = next_child) {
|
| + next_child = child->NextChild();
|
| + if (!child->IsText() && child->AsElement()->Name() == name)
|
| + {
|
| + RemoveChildAfter(prev_child);
|
| + continue;
|
| + }
|
| + prev_child = child;
|
| + }
|
| +}
|
| +
|
| +void XmlElement::ClearAttributes() {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; ) {
|
| + XmlAttr* to_delete = attr;
|
| + attr = attr->next_attr_;
|
| + delete to_delete;
|
| + }
|
| + first_attr_ = last_attr_ = NULL;
|
| +}
|
| +
|
| +void XmlElement::ClearChildren() {
|
| + XmlChild* pchild;
|
| + for (pchild = first_child_; pchild; ) {
|
| + XmlChild* to_delete = pchild;
|
| + pchild = pchild->next_child_;
|
| + delete to_delete;
|
| + }
|
| + first_child_ = last_child_ = NULL;
|
| +}
|
| +
|
| +std::string XmlElement::Str() const {
|
| + std::stringstream ss;
|
| + XmlPrinter::PrintXml(&ss, this);
|
| + return ss.str();
|
| +}
|
| +
|
| +XmlElement* XmlElement::ForStr(const std::string& str) {
|
| + XmlBuilder builder;
|
| + XmlParser::ParseXml(&builder, str);
|
| + return builder.CreateElement();
|
| +}
|
| +
|
| +XmlElement::~XmlElement() {
|
| + XmlAttr* attr;
|
| + for (attr = first_attr_; attr; ) {
|
| + XmlAttr* to_delete = attr;
|
| + attr = attr->next_attr_;
|
| + delete to_delete;
|
| + }
|
| +
|
| + XmlChild* pchild;
|
| + for (pchild = first_child_; pchild; ) {
|
| + XmlChild* to_delete = pchild;
|
| + pchild = pchild->next_child_;
|
| + delete to_delete;
|
| + }
|
| +}
|
| +
|
| +} // namespace buzz
|
|
|