2
* libSpiff - XSPF playlist handling library
4
* Copyright (C) 2007, Sebastian Pipping / Xiph.Org Foundation
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
11
* * Redistributions of source code must retain the above
12
* copyright notice, this list of conditions and the following
15
* * Redistributions in binary form must reproduce the above
16
* copyright notice, this list of conditions and the following
17
* disclaimer in the documentation and/or other materials
18
* provided with the distribution.
20
* * Neither the name of the Xiph.Org Foundation nor the names of
21
* its contributors may be used to endorse or promote products
22
* derived from this software without specific prior written
25
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
36
* OF THE POSSIBILITY OF SUCH DAMAGE.
38
* Sebastian Pipping, sping@xiph.org
43
* Implementation of SpiffData.
46
#include <spiff/SpiffData.h>
47
#include <spiff/SpiffExtension.h>
48
#include <spiff/SpiffToolbox.h>
49
using namespace Spiff::Toolbox;
56
/// @cond DOXYGEN_NON_API
59
* D object for SpiffData.
61
class SpiffDataPrivate {
63
friend class SpiffData;
65
const XML_Char * image; ///< Image URI
66
const XML_Char * info; ///< Info URI
67
const XML_Char * annotation; ///< Annotation
68
const XML_Char * creator; ///< Creator/artist
69
const XML_Char * title; ///< Title
70
bool ownImage; ///< Image memory ownership flag
71
bool ownInfo; ///< Info memory ownership flag
72
bool ownAnnotation; ///< Annotation memory ownership flag
73
bool ownCreator; ///< Creator memory ownership flag
74
bool ownTitle; ///< Title memory ownership flag
75
std::deque<std::pair<std::pair<const XML_Char *, bool> *, std::pair<const XML_Char *, bool> *> *> * links; ///< List of link pairs
76
std::deque<std::pair<std::pair<const XML_Char *, bool> *, std::pair<const XML_Char *, bool> *> *> * metas; ///< List of meta pairs
77
std::deque<std::pair<const SpiffExtension *, bool> *> * extensions; ///< List of extensions
80
* Creates a new D object.
102
* @param source Source to copy from
104
SpiffDataPrivate(const SpiffDataPrivate & source)
105
: image(source.ownImage
106
? newAndCopy(source.image)
109
? newAndCopy(source.info)
111
annotation(source.ownAnnotation
112
? newAndCopy(source.annotation)
113
: source.annotation),
114
creator(source.ownCreator
115
? newAndCopy(source.creator)
117
title(source.ownTitle
118
? newAndCopy(source.title)
120
ownImage(source.ownImage),
121
ownInfo(source.ownInfo),
122
ownAnnotation(source.ownAnnotation),
123
ownCreator(source.ownCreator),
124
ownTitle(source.ownTitle),
128
copyMetasOrLinks(this->links, source.links);
129
copyMetasOrLinks(this->metas, source.metas);
130
copyExtensions(this->extensions, source.extensions);
134
* Assignment operator.
136
* @param source Source to copy from
138
SpiffDataPrivate & operator=(const SpiffDataPrivate & source) {
139
if (this != &source) {
141
copyIfOwned(this->title, this->ownTitle, source.title, source.ownTitle);
142
copyIfOwned(this->creator, this->ownCreator, source.creator, source.ownCreator);
143
copyIfOwned(this->annotation, this->ownAnnotation, source.annotation, source.ownAnnotation);
144
copyIfOwned(this->image, this->ownImage, source.image, source.ownImage);
145
copyIfOwned(this->info, this->ownInfo, source.info, source.ownInfo);
146
copyMetasOrLinks(this->links, source.links);
147
copyMetasOrLinks(this->metas, source.metas);
148
copyExtensions(this->extensions, source.extensions);
154
* Destroys this D object.
156
~SpiffDataPrivate() {
161
freeIfOwned(this->title, this->ownTitle);
162
freeIfOwned(this->creator, this->ownCreator);
163
freeIfOwned(this->annotation, this->ownAnnotation);
164
freeIfOwned(this->image, this->ownImage);
165
freeIfOwned(this->info, this->ownInfo);
166
freeMetasOrLinks(this->links);
167
freeMetasOrLinks(this->metas);
168
freeExtensions(this->extensions);
171
static inline void freeMetasOrLinks(std::deque<std::pair<std::pair<
172
const XML_Char *, bool> *, std::pair<const XML_Char *,
173
bool> *> *> * & container) {
174
if (container != NULL) {
175
deque<pair<pair<const XML_Char *, bool> *,
176
pair<const XML_Char *, bool> *> *>
177
::const_iterator iter = container->begin();
178
while (iter != container->end()) {
179
pair<pair<const XML_Char *, bool> *,
180
pair<const XML_Char *, bool> *>
181
* const entry = *iter;
182
if (entry->first->second) {
183
delete [] entry->first->first;
186
if (entry->second->second) {
187
delete [] entry->second->first;
189
delete entry->second;
199
static inline void copyMetasOrLinks(std::deque<std::pair<
200
std::pair<const XML_Char *, bool> *,
201
std::pair<const XML_Char *, bool> *> *> * & dest,
202
std::deque<std::pair<
203
std::pair<const XML_Char *, bool> *,
204
std::pair<const XML_Char *, bool> *> *> * const & source) {
205
dest = new deque<pair<
206
pair<const XML_Char *, bool> *,
207
pair<const XML_Char *, bool> *> *>();
209
if (source != NULL) {
210
deque<pair<pair<const XML_Char *, bool> *,
211
pair<const XML_Char *, bool> *> *>::const_iterator
212
iter = source->begin();
213
while (iter != source->end()) {
214
const pair<pair<const XML_Char *, bool> *,
215
pair<const XML_Char *, bool> *>
216
* const entry = *iter;
218
const bool ownRel = entry->first->second;
219
const bool ownContent = entry->second->second;
220
const XML_Char * const rel = ownRel
221
? entry->first->first
222
: Toolbox::newAndCopy(entry->first->first);
223
const XML_Char * const content = ownContent
224
? entry->second->first
225
: Toolbox::newAndCopy(entry->second->first);
227
SpiffData::appendHelper(dest, rel, ownRel,
228
content, ownContent);
234
static inline void freeExtensions(std::deque<std::pair<
235
const SpiffExtension *, bool> *> * & container) {
236
if (container != NULL) {
237
deque<pair<const SpiffExtension *, bool> *>::const_iterator
238
iter = container->begin();
239
while (iter != container->end()) {
240
pair<const SpiffExtension *, bool>
241
* const entry = *iter;
254
static inline void copyExtensions(std::deque<
255
std::pair<const SpiffExtension *, bool> *> * & dest,
257
std::pair<const SpiffExtension *, bool> *> * const & source) {
258
dest = new deque<pair<const SpiffExtension *, bool> *>();
260
if (source != NULL) {
261
deque<pair<const SpiffExtension *, bool> *>::const_iterator
262
iter = source->begin();
263
while (iter != source->end()) {
264
const pair<const SpiffExtension *, bool>
265
* const entry = *iter;
267
const bool own = entry->second;
268
const SpiffExtension * const extension = own
269
? entry->first->clone()
271
SpiffData::appendHelper(dest, extension, own);
284
SpiffData::SpiffData() : d(new SpiffDataPrivate()) {
290
SpiffData::SpiffData(const SpiffData & source)
291
: d(new SpiffDataPrivate(*(source.d))) {
297
SpiffData & SpiffData::operator=(const SpiffData & source) {
298
if (this != &source) {
299
*(this->d) = *(source.d);
306
SpiffData::~SpiffData() {
312
void SpiffData::giveAnnotation(const XML_Char * annotation, bool copy) {
313
Toolbox::deleteNewAndCopy(this->d->annotation, this->d->ownAnnotation,
319
void SpiffData::giveCreator(const XML_Char * creator, bool copy) {
320
Toolbox::deleteNewAndCopy(this->d->creator, this->d->ownCreator,
326
void SpiffData::giveInfo(const XML_Char * info, bool copy) {
327
Toolbox::deleteNewAndCopy(this->d->info, this->d->ownInfo, info, copy);
332
void SpiffData::giveImage(const XML_Char * image, bool copy) {
333
Toolbox::deleteNewAndCopy(this->d->image, this->d->ownImage, image, copy);
338
void SpiffData::giveTitle(const XML_Char * title, bool copy) {
339
Toolbox::deleteNewAndCopy(this->d->title, this->d->ownTitle, title, copy);
344
void SpiffData::giveAppendLink(const XML_Char * rel, bool copyRel, const XML_Char * content, bool copyContent) {
345
appendHelper(this->d->links, copyRel ? Toolbox::newAndCopy(rel) : rel, true,
346
copyContent ? Toolbox::newAndCopy(content) : content, true);
351
void SpiffData::giveAppendMeta(const XML_Char * rel, bool copyRel, const XML_Char * content, bool copyContent) {
352
appendHelper(this->d->metas, copyRel ? Toolbox::newAndCopy(rel) : rel, true,
353
copyContent ? Toolbox::newAndCopy(content) : content, true);
358
void SpiffData::giveAppendExtension(const SpiffExtension * extension, bool copy) {
359
appendHelper(this->d->extensions,
368
void SpiffData::lendAnnotation(const XML_Char * annotation) {
369
Toolbox::deleteNewAndCopy(this->d->annotation, this->d->ownAnnotation,
375
void SpiffData::lendCreator(const XML_Char * creator) {
376
Toolbox::deleteNewAndCopy(this->d->creator, this->d->ownCreator,
382
void SpiffData::lendInfo(const XML_Char * info) {
383
Toolbox::deleteNewAndCopy(this->d->info, this->d->ownInfo, info, false);
388
void SpiffData::lendImage(const XML_Char * image) {
389
Toolbox::deleteNewAndCopy(this->d->image, this->d->ownImage, image, false);
394
void SpiffData::lendTitle(const XML_Char * title) {
395
Toolbox::deleteNewAndCopy(this->d->title, this->d->ownTitle, title, false);
400
void SpiffData::lendAppendLink(const XML_Char * rel, const XML_Char * content) {
401
appendHelper(this->d->links, rel, false, content, false);
406
void SpiffData::lendAppendMeta(const XML_Char * rel, const XML_Char * content) {
407
appendHelper(this->d->metas, rel, false, content, false);
412
void SpiffData::lendAppendExtension(SpiffExtension * extension) {
413
appendHelper(this->d->extensions, extension, false);
418
XML_Char * SpiffData::stealTitle() {
419
return stealHelper(this->d->title, this->d->ownTitle);
424
XML_Char * SpiffData::stealAnnotation() {
425
return stealHelper(this->d->annotation, this->d->ownAnnotation);
430
XML_Char * SpiffData::stealCreator() {
431
return stealHelper(this->d->creator, this->d->ownCreator);
436
XML_Char * SpiffData::stealInfo() {
437
return stealHelper(this->d->info, this->d->ownInfo);
442
XML_Char * SpiffData::stealImage() {
443
return stealHelper(this->d->image, this->d->ownImage);
448
pair<XML_Char *, XML_Char *> * SpiffData::stealFirstMeta() {
449
return stealFirstHelper(this->d->metas);
454
pair<XML_Char *, XML_Char *> * SpiffData::stealFirstLink() {
455
return stealFirstHelper(this->d->links);
460
SpiffExtension * SpiffData::stealFirstExtension() {
461
return stealFirstHelper(this->d->extensions);
466
const XML_Char * SpiffData::getImage() const {
467
return this->d->image;
472
const XML_Char * SpiffData::getInfo() const {
473
return this->d->info;
478
const XML_Char * SpiffData::getAnnotation() const {
479
return this->d->annotation;
484
const XML_Char * SpiffData::getCreator() const {
485
return this->d->creator;
490
const XML_Char * SpiffData::getTitle() const {
491
return this->d->title;
496
pair<const XML_Char *, const XML_Char *> * SpiffData::getLink(int index) const {
497
return getHelper(this->d->links, index);
502
pair<const XML_Char *, const XML_Char *> * SpiffData::getMeta(int index) const {
503
return getHelper(this->d->metas, index);
507
const SpiffExtension * SpiffData::getExtension(int index) const {
508
return getHelper(this->d->extensions, index);
513
int SpiffData::getLinkCount() const {
514
return (this->d->links == NULL) ? 0 : static_cast<int>(this->d->links->size());
519
int SpiffData::getMetaCount() const {
520
return (this->d->metas == NULL) ? 0 : static_cast<int>(this->d->metas->size());
525
int SpiffData::getExtensionCount() const {
526
return (this->d->extensions == NULL) ? 0 : static_cast<int>(this->d->extensions->size());
531
/*static*/ void SpiffData::appendHelper(
532
std::deque<std::pair<std::pair<const XML_Char *, bool> *,
533
std::pair<const XML_Char *, bool> *> *> * & container,
534
const XML_Char * rel, bool ownRel,
535
const XML_Char * content, bool ownContent) {
536
if (container == NULL) {
537
container = new deque<pair<pair<const XML_Char *, bool> *, pair<const XML_Char *, bool> *> *>;
539
pair<const XML_Char *, bool> * const first = new pair<const XML_Char *, bool>(rel, ownRel);
540
pair<const XML_Char *, bool> * const second = new pair<const XML_Char *, bool>(content, ownContent);
541
pair<pair<const XML_Char *, bool> *, pair<const XML_Char *, bool> *> * const entry =
542
new pair<pair<const XML_Char *, bool> *, pair<const XML_Char *, bool> *>(first, second);
543
container->push_back(entry);
548
/*static*/ void SpiffData::appendHelper(
549
std::deque<std::pair<const SpiffExtension *, bool> *> * & container,
550
const SpiffExtension * extension, bool own) {
551
if (container == NULL) {
552
container = new deque<pair<const SpiffExtension *, bool> *>;
554
pair<const SpiffExtension *, bool> * const entry =
555
new pair<const SpiffExtension *, bool>(extension, own);
556
container->push_back(entry);
561
/*static*/ XML_Char * SpiffData::stealHelper(const XML_Char * & property,
563
const XML_Char * const res = Toolbox::getSetNull<XML_Char>(property);
565
return const_cast<XML_Char *>(res);
566
} else if (res == NULL) {
569
return Toolbox::newAndCopy(res);
575
/*static*/ pair<XML_Char *, XML_Char *> * SpiffData::stealFirstHelper(
576
std::deque<std::pair<std::pair<const XML_Char *, bool> *,
577
std::pair<const XML_Char *, bool> *> *> * & container) {
578
if ((container == NULL) || container->empty()) {
581
pair<pair<const XML_Char *, bool> *, pair<const XML_Char *, bool> *> * const entry =
583
container->pop_front();
584
pair<XML_Char *, XML_Char *> * const res = new pair<XML_Char *, XML_Char *>(
586
? const_cast<XML_Char *>(entry->first->first)
587
: Toolbox::newAndCopy(entry->first->first), entry->second->second
588
? const_cast<XML_Char *>(entry->second->first)
589
: Toolbox::newAndCopy(entry->second->first));
591
delete entry->second;
598
/*static*/ SpiffExtension * SpiffData::stealFirstHelper(
599
std::deque<std::pair<const SpiffExtension *, bool> *> * & container) {
600
if ((container == NULL) || container->empty()) {
603
pair<const SpiffExtension *, bool> * const entry = container->front();
604
container->pop_front();
605
SpiffExtension * res = entry->second
606
? const_cast<SpiffExtension *>(entry->first)
607
: entry->first->clone();
614
/*static*/ pair<const XML_Char *, const XML_Char *> * SpiffData::getHelper(
615
std::deque<std::pair<std::pair<const XML_Char *, bool> *,
616
std::pair<const XML_Char *, bool> *> *> * & container, int index) {
617
if ((container == NULL) || container->empty() || (index < 0)
618
|| (index >= static_cast<int>(container->size()))) {
621
pair<pair<const XML_Char *, bool> *, pair<const XML_Char *, bool> *> * const entry =
622
container->at(index);
624
// NOTE: getX() just peeps at data so don't clone anything
625
pair<const XML_Char *, const XML_Char *> * const res =
626
new pair<const XML_Char *, const XML_Char *>(
627
entry->first->first, entry->second->first);
633
/*static*/ const SpiffExtension * SpiffData::getHelper(
634
std::deque<std::pair<const SpiffExtension *, bool> *> * & container,
636
if ((container == NULL) || container->empty() || (index < 0)
637
|| (index >= static_cast<int>(container->size()))) {
641
// NOTE: getX() just peeps at data so don't clone anything
642
pair<const SpiffExtension *, bool> * const entry
643
= container->at(index);