~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/xmllite/xmlelement.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2004--2005, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without 
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice, 
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products 
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#include "talk/xmllite/xmlelement.h"
 
29
 
 
30
#include <ostream>
 
31
#include <sstream>
 
32
#include <string>
 
33
#include <vector>
 
34
 
 
35
#include "talk/base/common.h"
 
36
#include "talk/xmllite/qname.h"
 
37
#include "talk/xmllite/xmlparser.h"
 
38
#include "talk/xmllite/xmlbuilder.h"
 
39
#include "talk/xmllite/xmlprinter.h"
 
40
#include "talk/xmllite/xmlconstants.h"
 
41
 
 
42
namespace buzz {
 
43
 
 
44
XmlChild::~XmlChild() {
 
45
}
 
46
 
 
47
bool XmlText::IsTextImpl() const {
 
48
  return true;
 
49
}
 
50
 
 
51
XmlElement* XmlText::AsElementImpl() const {
 
52
  return NULL;
 
53
}
 
54
 
 
55
XmlText* XmlText::AsTextImpl() const {
 
56
  return const_cast<XmlText *>(this);
 
57
}
 
58
 
 
59
void XmlText::SetText(const std::string& text) {
 
60
  text_ = text;
 
61
}
 
62
 
 
63
void XmlText::AddParsedText(const char* buf, int len) {
 
64
  text_.append(buf, len);
 
65
}
 
66
 
 
67
void XmlText::AddText(const std::string& text) {
 
68
  text_ += text;
 
69
}
 
70
 
 
71
XmlText::~XmlText() {
 
72
}
 
73
 
 
74
XmlElement::XmlElement(const QName& name) :
 
75
    name_(name),
 
76
    first_attr_(NULL),
 
77
    last_attr_(NULL),
 
78
    first_child_(NULL),
 
79
    last_child_(NULL),
 
80
    cdata_(false) {
 
81
}
 
82
 
 
83
XmlElement::XmlElement(const XmlElement& elt) :
 
84
    XmlChild(),
 
85
    name_(elt.name_),
 
86
    first_attr_(NULL),
 
87
    last_attr_(NULL),
 
88
    first_child_(NULL),
 
89
    last_child_(NULL),
 
90
    cdata_(false) {
 
91
 
 
92
  // copy attributes
 
93
  XmlAttr* attr;
 
94
  XmlAttr ** plast_attr = &first_attr_;
 
95
  XmlAttr* newAttr = NULL;
 
96
  for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
 
97
    newAttr = new XmlAttr(*attr);
 
98
    *plast_attr = newAttr;
 
99
    plast_attr = &(newAttr->next_attr_);
 
100
  }
 
101
  last_attr_ = newAttr;
 
102
 
 
103
  // copy children
 
104
  XmlChild* pChild;
 
105
  XmlChild ** ppLast = &first_child_;
 
106
  XmlChild* newChild = NULL;
 
107
 
 
108
  for (pChild = elt.first_child_; pChild; pChild = pChild->NextChild()) {
 
109
    if (pChild->IsText()) {
 
110
      newChild = new XmlText(*(pChild->AsText()));
 
111
    } else {
 
112
      newChild = new XmlElement(*(pChild->AsElement()));
 
113
    }
 
114
    *ppLast = newChild;
 
115
    ppLast = &(newChild->next_child_);
 
116
  }
 
117
  last_child_ = newChild;
 
118
 
 
119
  cdata_ = elt.cdata_;
 
120
}
 
121
 
 
122
XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
 
123
  name_(name),
 
124
  first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
 
125
  last_attr_(first_attr_),
 
126
  first_child_(NULL),
 
127
  last_child_(NULL),
 
128
  cdata_(false) {
 
129
}
 
130
 
 
131
bool XmlElement::IsTextImpl() const {
 
132
  return false;
 
133
}
 
134
 
 
135
XmlElement* XmlElement::AsElementImpl() const {
 
136
  return const_cast<XmlElement *>(this);
 
137
}
 
138
 
 
139
XmlText* XmlElement::AsTextImpl() const {
 
140
  return NULL;
 
141
}
 
142
 
 
143
const std::string XmlElement::BodyText() const {
 
144
  if (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
 
145
    return first_child_->AsText()->Text();
 
146
  }
 
147
 
 
148
  return std::string();
 
149
}
 
150
 
 
151
void XmlElement::SetBodyText(const std::string& text) {
 
152
  if (text.empty()) {
 
153
    ClearChildren();
 
154
  } else if (first_child_ == NULL) {
 
155
    AddText(text);
 
156
  } else if (first_child_->IsText() && last_child_ == first_child_) {
 
157
    first_child_->AsText()->SetText(text);
 
158
  } else {
 
159
    ClearChildren();
 
160
    AddText(text);
 
161
  }
 
162
}
 
163
 
 
164
const QName XmlElement::FirstElementName() const {
 
165
  const XmlElement* element = FirstElement();
 
166
  if (element == NULL)
 
167
    return QName();
 
168
  return element->Name();
 
169
}
 
170
 
 
171
XmlAttr* XmlElement::FirstAttr() {
 
172
  return first_attr_;
 
173
}
 
174
 
 
175
const std::string XmlElement::Attr(const StaticQName& name) const {
 
176
  XmlAttr* attr;
 
177
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
178
    if (attr->name_ == name)
 
179
      return attr->value_;
 
180
  }
 
181
  return std::string();
 
182
}
 
183
 
 
184
const std::string XmlElement::Attr(const QName& name) const {
 
185
  XmlAttr* attr;
 
186
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
187
    if (attr->name_ == name)
 
188
      return attr->value_;
 
189
  }
 
190
  return std::string();
 
191
}
 
192
 
 
193
bool XmlElement::HasAttr(const StaticQName& name) const {
 
194
  XmlAttr* attr;
 
195
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
196
    if (attr->name_ == name)
 
197
      return true;
 
198
  }
 
199
  return false;
 
200
}
 
201
 
 
202
bool XmlElement::HasAttr(const QName& name) const {
 
203
  XmlAttr* attr;
 
204
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
205
    if (attr->name_ == name)
 
206
      return true;
 
207
  }
 
208
  return false;
 
209
}
 
210
 
 
211
void XmlElement::SetAttr(const QName& name, const std::string& value) {
 
212
  XmlAttr* attr;
 
213
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
214
    if (attr->name_ == name)
 
215
      break;
 
216
  }
 
217
  if (!attr) {
 
218
    attr = new XmlAttr(name, value);
 
219
    if (last_attr_)
 
220
      last_attr_->next_attr_ = attr;
 
221
    else
 
222
      first_attr_ = attr;
 
223
    last_attr_ = attr;
 
224
    return;
 
225
  }
 
226
  attr->value_ = value;
 
227
}
 
228
 
 
229
void XmlElement::ClearAttr(const QName& name) {
 
230
  XmlAttr* attr;
 
231
  XmlAttr* last_attr = NULL;
 
232
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
 
233
    if (attr->name_ == name)
 
234
      break;
 
235
    last_attr = attr;
 
236
  }
 
237
  if (!attr)
 
238
    return;
 
239
  if (!last_attr)
 
240
    first_attr_ = attr->next_attr_;
 
241
  else
 
242
    last_attr->next_attr_ = attr->next_attr_;
 
243
  if (last_attr_ == attr)
 
244
    last_attr_ = last_attr;
 
245
  delete attr;
 
246
}
 
247
 
 
248
XmlChild* XmlElement::FirstChild() {
 
249
  return first_child_;
 
250
}
 
251
 
 
252
XmlElement* XmlElement::FirstElement() {
 
253
  XmlChild* pChild;
 
254
  for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
 
255
    if (!pChild->IsText())
 
256
      return pChild->AsElement();
 
257
  }
 
258
  return NULL;
 
259
}
 
260
 
 
261
XmlElement* XmlElement::NextElement() {
 
262
  XmlChild* pChild;
 
263
  for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
 
264
    if (!pChild->IsText())
 
265
      return pChild->AsElement();
 
266
  }
 
267
  return NULL;
 
268
}
 
269
 
 
270
XmlElement* XmlElement::FirstWithNamespace(const std::string& ns) {
 
271
  XmlChild* pChild;
 
272
  for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
 
273
    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
 
274
      return pChild->AsElement();
 
275
  }
 
276
  return NULL;
 
277
}
 
278
 
 
279
XmlElement *
 
280
XmlElement::NextWithNamespace(const std::string& ns) {
 
281
  XmlChild* pChild;
 
282
  for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
 
283
    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
 
284
      return pChild->AsElement();
 
285
  }
 
286
  return NULL;
 
287
}
 
288
 
 
289
XmlElement *
 
290
XmlElement::FirstNamed(const QName& name) {
 
291
  XmlChild* pChild;
 
292
  for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
 
293
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
 
294
      return pChild->AsElement();
 
295
  }
 
296
  return NULL;
 
297
}
 
298
 
 
299
XmlElement *
 
300
XmlElement::FirstNamed(const StaticQName& name) {
 
301
  XmlChild* pChild;
 
302
  for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
 
303
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
 
304
      return pChild->AsElement();
 
305
  }
 
306
  return NULL;
 
307
}
 
308
 
 
309
XmlElement *
 
310
XmlElement::NextNamed(const QName& name) {
 
311
  XmlChild* pChild;
 
312
  for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
 
313
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
 
314
      return pChild->AsElement();
 
315
  }
 
316
  return NULL;
 
317
}
 
318
 
 
319
XmlElement *
 
320
XmlElement::NextNamed(const StaticQName& name) {
 
321
  XmlChild* pChild;
 
322
  for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
 
323
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
 
324
      return pChild->AsElement();
 
325
  }
 
326
  return NULL;
 
327
}
 
328
 
 
329
XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
 
330
  XmlElement* child = FirstNamed(name);
 
331
  if (!child) {
 
332
    child = new XmlElement(name);
 
333
    AddElement(child);
 
334
  }
 
335
 
 
336
  return child;
 
337
}
 
338
 
 
339
const std::string XmlElement::TextNamed(const QName& name) const {
 
340
  XmlChild* pChild;
 
341
  for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
 
342
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
 
343
      return pChild->AsElement()->BodyText();
 
344
  }
 
345
  return std::string();
 
346
}
 
347
 
 
348
void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
 
349
  if (predecessor == NULL) {
 
350
    next->next_child_ = first_child_;
 
351
    first_child_ = next;
 
352
  }
 
353
  else {
 
354
    next->next_child_ = predecessor->next_child_;
 
355
    predecessor->next_child_ = next;
 
356
  }
 
357
}
 
358
 
 
359
void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
 
360
  XmlChild* next;
 
361
 
 
362
  if (predecessor == NULL) {
 
363
    next = first_child_;
 
364
    first_child_ = next->next_child_;
 
365
  }
 
366
  else {
 
367
    next = predecessor->next_child_;
 
368
    predecessor->next_child_ = next->next_child_;
 
369
  }
 
370
 
 
371
  if (last_child_ == next)
 
372
    last_child_ = predecessor;
 
373
 
 
374
  delete next;
 
375
}
 
376
 
 
377
void XmlElement::AddAttr(const QName& name, const std::string& value) {
 
378
  ASSERT(!HasAttr(name));
 
379
 
 
380
  XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
 
381
  last_attr_ = (*pprev = new XmlAttr(name, value));
 
382
}
 
383
 
 
384
void XmlElement::AddAttr(const QName& name, const std::string& value,
 
385
                         int depth) {
 
386
  XmlElement* element = this;
 
387
  while (depth--) {
 
388
    element = element->last_child_->AsElement();
 
389
  }
 
390
  element->AddAttr(name, value);
 
391
}
 
392
 
 
393
void XmlElement::AddParsedText(const char* cstr, int len) {
 
394
  if (len == 0)
 
395
    return;
 
396
 
 
397
  if (last_child_ && last_child_->IsText()) {
 
398
    last_child_->AsText()->AddParsedText(cstr, len);
 
399
    return;
 
400
  }
 
401
  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
 
402
  last_child_ = *pprev = new XmlText(cstr, len);
 
403
}
 
404
 
 
405
void XmlElement::AddCDATAText(const char* buf, int len) {
 
406
  cdata_ = true;
 
407
  AddParsedText(buf, len);
 
408
}
 
409
 
 
410
void XmlElement::AddText(const std::string& text) {
 
411
  if (text == STR_EMPTY)
 
412
    return;
 
413
 
 
414
  if (last_child_ && last_child_->IsText()) {
 
415
    last_child_->AsText()->AddText(text);
 
416
    return;
 
417
  }
 
418
  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
 
419
  last_child_ = *pprev = new XmlText(text);
 
420
}
 
421
 
 
422
void XmlElement::AddText(const std::string& text, int depth) {
 
423
  // note: the first syntax is ambigious for msvc 6
 
424
  // XmlElement* pel(this);
 
425
  XmlElement* element = this;
 
426
  while (depth--) {
 
427
    element = element->last_child_->AsElement();
 
428
  }
 
429
  element->AddText(text);
 
430
}
 
431
 
 
432
void XmlElement::AddElement(XmlElement *child) {
 
433
  if (child == NULL)
 
434
    return;
 
435
 
 
436
  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
 
437
  *pprev = child;
 
438
  last_child_ = child;
 
439
  child->next_child_ = NULL;
 
440
}
 
441
 
 
442
void XmlElement::AddElement(XmlElement *child, int depth) {
 
443
  XmlElement* element = this;
 
444
  while (depth--) {
 
445
    element = element->last_child_->AsElement();
 
446
  }
 
447
  element->AddElement(child);
 
448
}
 
449
 
 
450
void XmlElement::ClearNamedChildren(const QName& name) {
 
451
  XmlChild* prev_child = NULL;
 
452
  XmlChild* next_child;
 
453
  XmlChild* child;
 
454
  for (child = FirstChild(); child; child = next_child) {
 
455
    next_child = child->NextChild();
 
456
    if (!child->IsText() && child->AsElement()->Name() == name)
 
457
    {
 
458
      RemoveChildAfter(prev_child);
 
459
      continue;
 
460
    }
 
461
    prev_child = child;
 
462
  }
 
463
}
 
464
 
 
465
void XmlElement::ClearAttributes() {
 
466
  XmlAttr* attr;
 
467
  for (attr = first_attr_; attr; ) {
 
468
    XmlAttr* to_delete = attr;
 
469
    attr = attr->next_attr_;
 
470
    delete to_delete;
 
471
  }
 
472
  first_attr_ = last_attr_ = NULL;
 
473
}
 
474
 
 
475
void XmlElement::ClearChildren() {
 
476
  XmlChild* pchild;
 
477
  for (pchild = first_child_; pchild; ) {
 
478
    XmlChild* to_delete = pchild;
 
479
    pchild = pchild->next_child_;
 
480
    delete to_delete;
 
481
  }
 
482
  first_child_ = last_child_ = NULL;
 
483
}
 
484
 
 
485
std::string XmlElement::Str() const {
 
486
  std::stringstream ss;
 
487
  XmlPrinter::PrintXml(&ss, this);
 
488
  return ss.str();
 
489
}
 
490
 
 
491
XmlElement* XmlElement::ForStr(const std::string& str) {
 
492
  XmlBuilder builder;
 
493
  XmlParser::ParseXml(&builder, str);
 
494
  return builder.CreateElement();
 
495
}
 
496
 
 
497
XmlElement::~XmlElement() {
 
498
  XmlAttr* attr;
 
499
  for (attr = first_attr_; attr; ) {
 
500
    XmlAttr* to_delete = attr;
 
501
    attr = attr->next_attr_;
 
502
    delete to_delete;
 
503
  }
 
504
 
 
505
  XmlChild* pchild;
 
506
  for (pchild = first_child_; pchild; ) {
 
507
    XmlChild* to_delete = pchild;
 
508
    pchild = pchild->next_child_;
 
509
    delete to_delete;
 
510
  }
 
511
}
 
512
 
 
513
}  // namespace buzz