00001
00002 #ifndef INCLUDED_plistCollections_h_
00003 #define INCLUDED_plistCollections_h_
00004
00005 #include "plistPrimitives.h"
00006 #include <map>
00007 #include <vector>
00008 #include <set>
00009 #include <regex.h>
00010
00011 namespace plist {
00012 ObjectBase* loadXML(xmlNode* node);
00013
00014
00015 template<class T> T* allocate() { return new T; }
00016
00017 template<class T> void assign(T& a, const T& b) { a=b; }
00018
00019
00020 template<> inline ObjectBase* allocate() { throw std::runtime_error("cannot plist::allocate generic instances (ObjectBase)"); }
00021 template<> inline PrimitiveBase* allocate() { throw std::runtime_error("cannot plist::allocate generic instances (PrimitiveBase)"); }
00022 template<> inline Collection* allocate() { throw std::runtime_error("cannot plist::allocate generic instances (Collection)"); }
00023 template<> inline void assign(ObjectBase& a, const ObjectBase& b) { a.set(b); }
00024
00025
00026
00027 template<class T> T* loadXML(xmlNode* node) {
00028 T* cobj = plist::allocate<T>();
00029 try {
00030 cobj->loadXML(node);
00031 } catch(...) {
00032 delete cobj;
00033 throw;
00034 }
00035 return cobj;
00036 }
00037
00038
00039 template<> ObjectBase* loadXML(xmlNode* node);
00040 template<> PrimitiveBase* loadXML(xmlNode* node);
00041 template<> Collection* loadXML(xmlNode* node);
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 class Collection : public ObjectBase {
00070 public:
00071
00072 template<typename U, typename V> struct conversion_policy { typedef typename U::DeniedValueConversions value_conversion; };
00073
00074
00075 enum LoadSaveActionBitMask {
00076 ADDITIONS=1,
00077 REMOVALS=2
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 enum LoadSavePolicy {
00096 FIXED = 0,
00097 UNION = ADDITIONS,
00098 INTERSECT = REMOVALS,
00099 SYNC = ADDITIONS|REMOVALS
00100 };
00101
00102
00103 Collection& operator=(const Collection& d) { if(&d==this) return *this; ObjectBase::operator=(d); return *this; }
00104
00105
00106 ~Collection();
00107
00108
00109 virtual ObjectBase* resolveEntry(const std::string& path) const=0;
00110
00111
00112 bool resolveAssignment(const std::string& arg);
00113
00114
00115 bool resolveAssignment(const std::string& arg, std::ostream& errstream);
00116
00117 virtual void clear()=0;
00118
00119 virtual size_t size() const=0;
00120
00121
00122 virtual void addCollectionListener(CollectionListener* l) const;
00123
00124 virtual void removeCollectionListener(CollectionListener* l) const;
00125
00126 virtual bool isCollectionListener(CollectionListener* l) const;
00127
00128 void setSaveCondensed(bool b) { saveCondensed=b; }
00129 bool getSaveCondensed() const { return saveCondensed; }
00130
00131 void setUnusedWarning(bool b) { warnUnused=b; }
00132 bool getUnusedWarning() const { return warnUnused; }
00133
00134 virtual LoadSavePolicy getLoadPolicy() const { return loadPolicy; }
00135 virtual LoadSavePolicy getSavePolicy() const { return savePolicy; }
00136 virtual void setLoadPolicy(LoadSavePolicy lp) { loadPolicy=lp; }
00137 virtual void setSavePolicy(LoadSavePolicy sp) { savePolicy=sp; }
00138 virtual void setLoadSavePolicy(LoadSavePolicy lp, LoadSavePolicy sp) { setLoadPolicy(lp); setSavePolicy(sp); }
00139
00140
00141
00142 static const std::string& subCollectionSep() {
00143 static std::string sep(1,'.');
00144 return sep;
00145 }
00146
00147
00148 virtual unsigned int getLongestKeyLen(const regex_t* reg=NULL, unsigned int depth=-1) const=0;
00149
00150
00151 virtual bool canContain(const ObjectBase& obj)=0;
00152
00153 virtual long toLong() const;
00154 virtual double toDouble() const;
00155
00156 protected:
00157
00158 Collection() : ObjectBase(), collectionListeners(), saveCondensed(false), warnUnused(true), loadPolicy(SYNC), savePolicy(SYNC) {autoFormat=false;}
00159
00160 Collection(LoadSavePolicy lp, LoadSavePolicy sp) : ObjectBase(), collectionListeners(), saveCondensed(false), warnUnused(true), loadPolicy(lp), savePolicy(sp) {autoFormat=false;}
00161
00162 Collection(const Collection& d) : ObjectBase(d), collectionListeners(), saveCondensed(d.saveCondensed), warnUnused(d.warnUnused), loadPolicy(d.loadPolicy), savePolicy(d.savePolicy) {autoFormat=false;}
00163
00164
00165 virtual void fireEntryAdded(ObjectBase& val);
00166
00167 virtual void fireEntryRemoved(ObjectBase& val);
00168
00169 virtual void fireEntriesChanged();
00170
00171 mutable std::set<CollectionListener*>* collectionListeners;
00172
00173
00174 static size_t getIndex(const std::string& name);
00175
00176
00177 static std::string getIndentationPrefix(xmlNode* node);
00178
00179
00180
00181 static const std::string& emptyStr() {
00182 static std::string mt;
00183 return mt;
00184 }
00185
00186
00187 static const std::string& perIndent() {
00188 static std::string pi(1,'\t');
00189 return pi;
00190 }
00191
00192 static const unsigned int KEY_IN_COMMENT_MAX_POS=10;
00193
00194
00195 bool saveCondensed;
00196
00197 bool warnUnused;
00198
00199 LoadSavePolicy loadPolicy;
00200
00201 LoadSavePolicy savePolicy;
00202 };
00203
00204
00205
00206 struct AutoCollectionListener : public plist::PrimitiveListener, public plist::CollectionListener {
00207
00208 AutoCollectionListener(const plist::Collection& source, bool updateOnNewEntry)
00209 : plist::PrimitiveListener(), src(source), updateOnNew(updateOnNewEntry)
00210 {
00211 activate();
00212 }
00213
00214 ~AutoCollectionListener() {
00215 deactivate();
00216 }
00217
00218 AutoCollectionListener& operator=(const AutoCollectionListener&) { return *this; }
00219
00220 virtual void plistCollectionEntryAdded(plist::Collection& col, ObjectBase& primitive);
00221 virtual void plistCollectionEntryRemoved(plist::Collection& col, ObjectBase& primitive);
00222 virtual void plistCollectionEntriesChanged(plist::Collection& col);
00223 virtual void plistSubCollectionAdded(plist::Collection& ) {}
00224 virtual void plistSubCollectionRemoved(plist::Collection& ) {}
00225
00226
00227 virtual void activate(bool callNow=true) {
00228 src.addCollectionListener(this);
00229 if(callNow)
00230 plistCollectionEntriesChanged(const_cast<plist::Collection&>(src));
00231 }
00232
00233 virtual void deactivate();
00234
00235 const plist::Collection& src;
00236 bool updateOnNew;
00237 private:
00238
00239 AutoCollectionListener(const AutoCollectionListener&);
00240 };
00241
00242 template<typename O>
00243 struct CollectionCallbackMember : public plist::AutoCollectionListener {
00244
00245 CollectionCallbackMember(const plist::Collection& source, O& component, void(O::*func)(), bool callOnAdd=true)
00246 : plist::AutoCollectionListener(source,callOnAdd), comp(component), callback(func) { if(updateOnNew) (comp.*callback)(); }
00247 virtual void plistValueChanged(const plist::PrimitiveBase& ) { (comp.*callback)(); }
00248 virtual void activate(bool callNow=true) { if(updateOnNew && callNow) (comp.*callback)(); }
00249 O& comp;
00250 void(O::*callback)();
00251
00252 CollectionCallbackMember& operator=(const CollectionCallbackMember&) { return *this; }
00253 private:
00254 CollectionCallbackMember(CollectionCallbackMember&);
00255 };
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 class DictionaryBase : virtual public Collection {
00270 friend std::ostream& operator<<(std::ostream& os, const DictionaryBase& d);
00271 public:
00272
00273 typedef std::map<std::string,ObjectBase*> storage_t;
00274
00275 typedef storage_t::iterator iterator;
00276
00277 typedef storage_t::const_iterator const_iterator;
00278
00279
00280
00281
00282
00283
00284 struct DeniedValueConversions {
00285 virtual ~DeniedValueConversions() {}
00286 };
00287
00288
00289
00290
00291
00292
00293 template<typename PO>
00294 struct EntryConstraint {
00295 virtual ~EntryConstraint() {}
00296
00297 virtual void setEntry(const std::string& name, PO& val, bool warnExists=false)=0;
00298
00299 virtual void addEntry(const std::string& name, PO& val, const std::string& comment="", bool warnExists=true)=0;
00300
00301 virtual void setEntry(const std::string& name, PO* val, bool warnExists=false)=0;
00302
00303 virtual void addEntry(const std::string& name, PO* val, const std::string& comment="", bool warnExists=true)=0;
00304 };
00305
00306
00307
00308
00309
00310
00311 struct StringConversion {
00312 virtual ~StringConversion() {}
00313
00314 virtual void addValue(const std::string& name, const std::string& val, const std::string& comment="", bool warnExists=true)=0;
00315 };
00316
00317
00318
00319
00320
00321
00322 struct IntegerConversion {
00323 virtual ~IntegerConversion() {}
00324
00325 virtual void addValue(const std::string& name, long val, const std::string& comment="", bool warnExists=true)=0;
00326
00327 virtual void addValue(const std::string& name, unsigned long val, const std::string& comment="", bool warnExists=true)=0;
00328 };
00329
00330
00331
00332
00333
00334
00335 struct RealConversion {
00336 virtual ~RealConversion() {}
00337
00338 virtual void addValue(const std::string& name, double val, const std::string& comment="", bool warnExists=true)=0;
00339 };
00340
00341
00342
00343
00344 template<typename PO>
00345 struct ConversionTo : public StringConversion, public IntegerConversion, public EntryConstraint<PO> {
00346
00347 template<typename T>
00348 void addValue(const std::string& name, const T& val, const std::string& comment="", bool warnExists=true) { addEntry(name,new PO(val),comment,warnExists); }
00349 virtual void addValue(const std::string& name, const std::string& val, const std::string& comment="", bool warnExists=true) { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(name,po,comment,warnExists); }
00350
00351 virtual void addValue(const std::string& name, char val[], const std::string& comment="", bool warnExists=true) { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(name,po,comment,warnExists); }
00352
00353 virtual void addValue(const std::string& name, const char val[], const std::string& comment="", bool warnExists=true) { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(name,po,comment,warnExists); }
00354 virtual void addValue(const std::string& name, long val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new PO(val),comment,warnExists); }
00355 virtual void addValue(const std::string& name, unsigned long val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new PO(val),comment,warnExists); }
00356 };
00357
00358
00359
00360 template<typename PO>
00361 struct WrapValueConversion : public StringConversion, public IntegerConversion, public RealConversion, public EntryConstraint<PO> {
00362
00363 template<typename T>
00364 void addValue(const std::string& name, const T& val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<T>(val),comment,warnExists); }
00365 virtual void addValue(const std::string& name, const std::string& val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<std::string>(val),comment,warnExists); }
00366
00367 virtual void addValue(const std::string& name, char val[], const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<std::string>(val),comment,warnExists); }
00368
00369 virtual void addValue(const std::string& name, const char val[], const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<std::string>(val),comment,warnExists); }
00370 virtual void addValue(const std::string& name, long val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<long>(val),comment,warnExists); }
00371 virtual void addValue(const std::string& name, unsigned long val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<unsigned long>(val),comment,warnExists); }
00372 virtual void addValue(const std::string& name, double val, const std::string& comment="", bool warnExists=true) { this->addEntry(name,new Primitive<double>(val),comment,warnExists); }
00373 };
00374
00375
00376 virtual bool removeEntry(const std::string& name);
00377
00378
00379
00380
00381 virtual bool renameEntry(const std::string& oldname, const std::string& newname);
00382
00383
00384 virtual bool swapEntry(const std::string& a, const std::string& b);
00385
00386
00387 virtual ObjectBase& getEntry(const std::string& name)=0;
00388
00389 virtual ObjectBase& operator[](const std::string& name)=0;
00390
00391 virtual ObjectBase* resolveEntry(const std::string& path) const;
00392
00393
00394 const_iterator findEntry(const std::string& name) const { return dict.find(name); }
00395
00396 virtual void clear();
00397
00398
00399 const_iterator begin() const { return dict.begin(); }
00400
00401 const_iterator end() const { return dict.end(); }
00402
00403 virtual size_t size() const { return dict.size(); }
00404
00405
00406 void setComment(const std::string& name, const std::string& comment);
00407
00408 const std::string& getComment(const std::string& name) const;
00409
00410 virtual void loadXML(xmlNode* node);
00411 virtual void saveXML(xmlNode* node) const { std::set<std::string> seen; saveXML(node,!(savePolicy&ADDITIONS),seen); }
00412
00413
00414
00415
00416
00417
00418 virtual void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00419
00420 virtual std::string toString() const;
00421
00422
00423 virtual unsigned int getLongestKeyLen(const regex_t* reg=NULL, unsigned int depth=-1) const;
00424
00425
00426 bool ownsReference(ObjectBase * val) const { return myRef.find(val)==myRef.end(); }
00427
00428 protected:
00429
00430 explicit DictionaryBase(bool growable) : Collection(growable?UNION:FIXED,SYNC), dict(), myRef(), comments() { setLoadSavePolicy(growable?UNION:FIXED,SYNC); }
00431
00432 DictionaryBase(const DictionaryBase& d) : Collection(d), dict(d.dict), myRef(d.myRef), comments(d.comments) { cloneMyRef(); setLoadSavePolicy(d.getLoadPolicy(),d.getSavePolicy()); }
00433
00434 DictionaryBase& operator=(const DictionaryBase& d) { Collection::operator=(d); return *this; }
00435
00436
00437 ~DictionaryBase() { clear(); }
00438
00439
00440 virtual void takeObject(const std::string& name, ObjectBase* obj);
00441
00442 virtual void fireEntryRemoved(ObjectBase& val);
00443
00444
00445
00446
00447
00448 iterator getSubEntry(const std::string& name, std::string::size_type& seppos);
00449
00450
00451
00452
00453 const_iterator getSubEntry(const std::string& name, std::string::size_type& seppos) const;
00454
00455
00456 virtual void cloneMyRef();
00457
00458
00459 virtual bool loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment)=0;
00460
00461
00462 virtual bool saveOverXMLNode(xmlNode* k, xmlNode* val, const std::string& key, std::string comment, const std::string& indentStr, std::set<std::string>& seen) const;
00463
00464
00465 virtual void saveXMLNode(xmlNode* node, const std::string& key, const ObjectBase* val, const std::string& indentStr, size_t longestKeyLen) const;
00466
00467
00468 storage_t dict;
00469
00470
00471 std::set<ObjectBase*> myRef;
00472
00473
00474 typedef std::map<std::string,std::string> comments_t;
00475
00476
00477 comments_t comments;
00478 };
00479
00480
00481 template<>
00482 struct DictionaryBase::ConversionTo<plist::Primitive<float> > : public DictionaryBase::StringConversion, public IntegerConversion, public DictionaryBase::RealConversion, public DictionaryBase::EntryConstraint<plist::Primitive<float> > {
00483
00484 template<typename T>
00485 void addValue(const std::string& name, const T& val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<float>(val),comment,warnExists); }
00486 virtual void addValue(const std::string& name, const std::string& val, const std::string& comment="", bool warnExists=true) { plist::Primitive<float>* po=new plist::Primitive<float>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00487
00488 virtual void addValue(const std::string& name, char val[], const std::string& comment="", bool warnExists=true) { plist::Primitive<float> * po=new plist::Primitive<float>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00489
00490 virtual void addValue(const std::string& name, const char val[], const std::string& comment="", bool warnExists=true) { plist::Primitive<float> * po=new plist::Primitive<float>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00491 virtual void addValue(const std::string& name, long val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<float>(val),comment,warnExists); }
00492 virtual void addValue(const std::string& name, unsigned long val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<float>(val),comment,warnExists); }
00493 virtual void addValue(const std::string& name, double val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<float>((float)val),comment,warnExists); }
00494 };
00495
00496
00497 template<>
00498 struct DictionaryBase::ConversionTo<plist::Primitive<double> > : public DictionaryBase::StringConversion, public IntegerConversion, public DictionaryBase::RealConversion, public DictionaryBase::EntryConstraint<plist::Primitive<double> > {
00499
00500 template<typename T>
00501 void addValue(const std::string& name, const T& val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<double>(val),comment,warnExists); }
00502 virtual void addValue(const std::string& name, const std::string& val, const std::string& comment="", bool warnExists=true) { plist::Primitive<double>* po=new plist::Primitive<double>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00503
00504 virtual void addValue(const std::string& name, char val[], const std::string& comment="", bool warnExists=true) { plist::Primitive<double> * po=new plist::Primitive<double>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00505
00506 virtual void addValue(const std::string& name, const char val[], const std::string& comment="", bool warnExists=true) { plist::Primitive<double> * po=new plist::Primitive<double>; try { po->set(val); } catch(...) { delete po; throw; } addEntry(name,po,comment,warnExists); }
00507 virtual void addValue(const std::string& name, long val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<double>(val),comment,warnExists); }
00508 virtual void addValue(const std::string& name, unsigned long val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<double>(val),comment,warnExists); }
00509 virtual void addValue(const std::string& name, double val, const std::string& comment="", bool warnExists=true) { addEntry(name,new plist::Primitive<double>(val),comment,warnExists); }
00510 };
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 template<typename PO, typename Alloc=typename PO::template conversion_policy<DictionaryBase,PO>::value_conversion >
00538 class DictionaryOf : public DictionaryBase, public Alloc {
00539
00540 typedef typename storage_t::const_iterator::iterator_category const_iterator_category;
00541 typedef typename std::pair<storage_t::key_type,PO*> const_iterator_value;
00542 typedef typename storage_t::const_iterator::difference_type const_iterator_difference;
00543
00544 public:
00545
00546 typedef typename DictionaryBase::storage_t storage_t;
00547
00548
00549
00550
00551 class const_iterator : public std::iterator<const_iterator_category, const_iterator_value, const_iterator_difference> {
00552 public:
00553 const_iterator(const storage_t::const_iterator& sit) : it(sit), tmp() {}
00554 const const_iterator_value& operator*() const { tmp.first=it->first; tmp.second=dynamic_cast<PO*>(it->second); return tmp; }
00555 const const_iterator_value* operator->() const { tmp.first=it->first; tmp.second=dynamic_cast<PO*>(it->second); return &tmp; }
00556 const_iterator& operator++() { ++it; return *this; }
00557 const_iterator operator++(int) { return const_iterator(it++); }
00558 const_iterator& operator--() { --it; return *this; }
00559 const_iterator operator--(int) { return const_iterator(it--); }
00560 bool operator==(const const_iterator& rhs) const { return it==rhs.it; }
00561 bool operator!=(const const_iterator& rhs) const { return it!=rhs.it; }
00562
00563 protected:
00564 storage_t::const_iterator it;
00565 mutable const_iterator_value tmp;
00566 };
00567
00568
00569
00570 DictionaryOf() : DictionaryBase(true), Alloc() {}
00571
00572 explicit DictionaryOf(bool growable) : DictionaryBase(growable), Alloc() {}
00573
00574 DictionaryOf(const DictionaryOf& d) : DictionaryBase(d), Alloc(d) {}
00575
00576 DictionaryOf& operator=(const DictionaryOf& a);
00577
00578 virtual void set(const ObjectBase& ob) { const DictionaryBase& d=dynamic_cast<const DictionaryBase&>(ob); set(d); }
00579
00580 virtual void set(const DictionaryBase& a);
00581
00582
00583 ~DictionaryOf() { }
00584
00585
00586
00587 virtual void setEntry(const std::string& name, PO& val, bool warnExists=false);
00588
00589
00590 virtual void addEntry(const std::string& name, PO& val, const std::string& comment="", bool warnExists=true);
00591
00592
00593 virtual void setEntry(const std::string& name, PO* val, bool warnExists=false);
00594
00595
00596 virtual void addEntry(const std::string& name, PO* val, const std::string& comment="", bool warnExists=true);
00597
00598
00599 #if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ > 3))
00600 typedef PO entryRet_t;
00601 #else
00602 typedef ObjectBase entryRet_t;
00603 # define PLIST_NO_COVRET
00604 #endif
00605
00606
00607 entryRet_t& getEntry(const std::string& name) {
00608 DictionaryBase::const_iterator it=dict.find(name);
00609 if(it!=dict.end())
00610 return dynamic_cast<PO&>(*it->second);
00611 else {
00612 PO* p = plist::allocate<PO>();
00613 dict[name]=p;
00614 fireEntryAdded(*p);
00615 return *p;
00616 }
00617 }
00618
00619 entryRet_t& operator[](const std::string& name) { return getEntry(name); }
00620
00621 const_iterator findEntry(const std::string& name) const { return dict.find(name); }
00622
00623
00624 const_iterator begin() const { return dict.begin(); }
00625
00626 const_iterator end() const { return dict.end(); }
00627
00628 virtual bool canContain(const ObjectBase& obj) { return (dynamic_cast<const PO*>(&obj)!=NULL); }
00629
00630
00631 PLIST_CLONE_DEF(DictionaryOf,(new DictionaryOf<PO,Alloc>(*this)));
00632
00633 protected:
00634
00635 virtual bool loadXMLNode(const std::string& name, xmlNode* val, const std::string& comment);
00636 };
00637
00638
00639
00640
00641 typedef DictionaryOf<ObjectBase> Dictionary;
00642 extern template class DictionaryOf<ObjectBase>;
00643
00644
00645 template<typename PO, typename Alloc>
00646 void DictionaryOf<PO,Alloc>::setEntry(const std::string& name, PO& val, bool warnExists) {
00647 DictionaryBase::iterator it=dict.find(name);
00648 if(it!=dict.end()) {
00649
00650 if(&val==it->second) {
00651 if(warnExists)
00652 std::cerr << "Warning: entry ("<<name<<","<<val<<") was already added, ignoring duplication..." << std::endl;
00653 myRef.erase(&val);
00654 return;
00655 }
00656 if(warnExists) {
00657 std::cerr << "Warning: new entry ("<<name<<","<<val<<") conflicted with previous entry ("<<name<<","<<(*it->second)<<")" << std::endl;
00658 std::cerr << " (use setEntry(...,false) if you expect you might need to overwrite)" << std::endl;
00659 }
00660 removeEntry(name);
00661
00662 }
00663 dict[name]=&val;
00664 fireEntryAdded(val);
00665 }
00666 template<typename PO, typename Alloc>
00667 void DictionaryOf<PO,Alloc>::addEntry(const std::string& name, PO& val, const std::string& comment, bool warnExists) {
00668 DictionaryBase::storage_t::iterator it=dict.find(name);
00669 if(it!=dict.end()) {
00670
00671 if(&val==it->second) {
00672 if(warnExists)
00673 std::cerr << "Warning: entry ("<<name<<","<<val<<") was already added, ignoring duplication..." << std::endl;
00674 myRef.erase(&val);
00675 return;
00676 }
00677 if(warnExists) {
00678 std::cerr << "Warning: new entry ("<<name<<","<<val<<") conflicted with previous entry ("<<name<<","<<(*it->second)<<")" << std::endl;
00679 std::cerr << " (use setEntry() if you expect you might need to overwrite)" << std::endl;
00680 }
00681 removeEntry(name);
00682
00683 }
00684 if(comment.size()>0)
00685 comments[name]=comment;
00686 dict[name]=&val;
00687 fireEntryAdded(val);
00688 }
00689 template<typename PO, typename Alloc>
00690 void DictionaryOf<PO,Alloc>::setEntry(const std::string& name, PO* val, bool warnExists) {
00691 DictionaryBase::iterator it=dict.find(name);
00692 if(it!=dict.end()) {
00693
00694 if(val==it->second) {
00695 if(warnExists)
00696 std::cerr << "Warning: entry ("<<name<<","<<(*val)<<") was already added, ignoring duplication..." << std::endl;
00697 myRef.insert(val);
00698 return;
00699 }
00700 if(warnExists) {
00701 std::cerr << "Warning: new entry ("<<name<<","<<(*val)<<") conflicted with previous entry ("<<name<<","<<(*it->second)<<")" << std::endl;
00702 std::cerr << " (use setEntry(...,false) if you expect you might need to overwrite)" << std::endl;
00703 }
00704 removeEntry(name);
00705
00706 }
00707 dict[name]=val;
00708 takeObject(name,val);
00709 fireEntryAdded(*val);
00710 }
00711 template<typename PO, typename Alloc>
00712 void DictionaryOf<PO,Alloc>::addEntry(const std::string& name, PO* val, const std::string& comment, bool warnExists) {
00713 DictionaryBase::iterator it=dict.find(name);
00714 if(it!=dict.end()) {
00715
00716 if(val==it->second) {
00717 if(warnExists)
00718 std::cerr << "Warning: entry ("<<name<<","<<(*val)<<") was already added, ignoring duplication..." << std::endl;
00719 myRef.insert(val);
00720 return;
00721 }
00722 if(warnExists) {
00723 std::cerr << "Warning: new entry ("<<name<<","<<(*val)<<") conflicted with previous entry ("<<name<<","<<(*it->second)<<")" << std::endl;
00724 std::cerr << " (use setEntry() if you expect you might need to overwrite)" << std::endl;
00725 }
00726 removeEntry(name);
00727
00728 }
00729 dict[name]=val;
00730 if(comment.size()>0)
00731 comments[name]=comment;
00732 takeObject(name,val);
00733 fireEntryAdded(*val);
00734 }
00735
00736
00737 PLIST_CLONE_IMPT2(PO,Alloc,DictionaryOf,(new DictionaryOf<PO,Alloc>(*this)));
00738
00739 template<typename PO, typename Alloc>
00740 bool DictionaryOf<PO,Alloc>::loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment) {
00741 DictionaryBase::const_iterator it=dict.find(key);
00742 if(it!=dict.end()) {
00743
00744 try {
00745
00746
00747 it->second->loadXML(val);
00748 if(dynamic_cast<Collection*>(it->second)!=NULL) {
00749 const std::string headline=("======== "+key+" ========");
00750 if(comment.compare(0,headline.size(),headline)!=0)
00751 setComment(key,comment);
00752 else if(comment.size()>headline.size())
00753 setComment(key,comment.substr(headline.size()));
00754 } else if(comment.size()>0)
00755 setComment(key,comment);
00756 return true;
00757 } catch(...) {
00758
00759 if(loadPolicy!=SYNC)
00760 throw;
00761
00762 removeEntry(key);
00763 }
00764 } else if(!(loadPolicy&ADDITIONS)) {
00765 if(warnUnused)
00766 std::cerr << "Warning: reading plist dictionary, key '" << key << "' does not match a registered variable. Ignoring..." << std::endl;
00767 return false;
00768 }
00769 PO * cobj = plist::loadXML<PO>(val);
00770 if(dynamic_cast<Collection*>(cobj)!=NULL) {
00771 const std::string headline=("======== "+key+" ========");
00772 if(comment.compare(0,headline.size(),headline)!=0)
00773 addEntry(key,cobj,comment);
00774 else
00775 addEntry(key,cobj,comment.substr(headline.size()));
00776 } else
00777 addEntry(key,cobj,comment);
00778 return true;
00779 }
00780
00781 template<typename PO, typename Alloc>
00782 void DictionaryOf<PO,Alloc>::set(const DictionaryBase& d) {
00783 if(&d == this)
00784 return;
00785
00786 if(const DictionaryOf* od = dynamic_cast<const DictionaryOf*>(&d)) {
00787 operator=(*od);
00788 return;
00789 }
00790 DictionaryBase::operator=(d);
00791
00792 std::set<std::string> seen;
00793 for(DictionaryBase::const_iterator dit=d.begin(); dit!=d.end(); ++dit) {
00794 const std::string key=dit->first;
00795 ObjectBase* val=dit->second;
00796 const std::string comment=d.getComment(key);
00797 seen.insert(key);
00798 DictionaryBase::storage_t::const_iterator it=dict.find(key);
00799 if(it!=dict.end()) {
00800
00801 try {
00802
00803
00804 it->second->set(*val);
00805 if(comment.size()>0)
00806 setComment(key,comment);
00807 continue;
00808 } catch(...) {
00809
00810 if(loadPolicy!=SYNC)
00811 throw;
00812
00813 removeEntry(key);
00814 }
00815 } else if(!(loadPolicy&ADDITIONS)) {
00816 if(warnUnused)
00817 std::cerr << "Warning: reading plist dictionary, key '" << key << "' does not match a registered variable. Ignoring..." << std::endl;
00818 continue;
00819 }
00820 PO* obj=dynamic_cast<PO*>(val);
00821 if(obj==NULL) {
00822 obj = plist::allocate<PO>();
00823 try {
00824 obj->set(*val);
00825 } catch(...) {
00826 delete obj;
00827 throw;
00828 }
00829 myRef.insert(obj);
00830 } else {
00831 obj = dynamic_cast<PO*>(obj->clone());
00832 if(obj==NULL) {
00833
00834 throw std::runtime_error("plist::Dictionary could not assign clone of object due to impossible type conflict (bad clone?)");
00835 }
00836 myRef.insert(obj);
00837 }
00838 if(dynamic_cast<Collection*>(obj)!=NULL) {
00839 const std::string headline=("======== "+key+" ========");
00840 if(comment.compare(0,headline.size(),headline)!=0)
00841 addEntry(key,*obj,comment);
00842 else
00843 addEntry(key,*obj,comment.substr(headline.size()));
00844 } else
00845 addEntry(key,*obj,comment);
00846 }
00847 if((loadPolicy&REMOVALS) && seen.size()!=size()) {
00848 std::set<std::string> rem;
00849 for(const_iterator it=begin(); it!=end(); ++it) {
00850 if(seen.find(it->first)==seen.end())
00851 rem.insert(it->first);
00852 }
00853 for(std::set<std::string>::const_iterator it=rem.begin(); it!=rem.end(); ++it)
00854 removeEntry(*it);
00855 }
00856 }
00857
00858 template<typename PO, typename Alloc>
00859 DictionaryOf<PO,Alloc>& DictionaryOf<PO,Alloc>::operator=(const DictionaryOf& d) {
00860 if(&d==this)
00861 return *this;
00862 DictionaryBase::operator=(d);
00863
00864 std::set<std::string> seen;
00865 for(const_iterator dit=d.begin(); dit!=d.end(); ++dit) {
00866 const std::string key=dit->first;
00867 PO* val=dit->second;
00868 const std::string comment=d.getComment(key);
00869 seen.insert(key);
00870 DictionaryBase::const_iterator it=dict.find(key);
00871 if(it!=dict.end()) {
00872
00873 try {
00874
00875
00876 plist::assign(*dynamic_cast<PO*>(it->second),*val);
00877 if(comment.size()>0)
00878 setComment(key,comment);
00879 continue;
00880 } catch(...) {
00881
00882 if(loadPolicy!=SYNC)
00883 throw;
00884
00885 removeEntry(key);
00886 }
00887 } else if(!(loadPolicy&ADDITIONS)) {
00888 if(warnUnused)
00889 std::cerr << "Warning: reading plist dictionary, key '" << key << "' does not match a registered variable. Ignoring..." << std::endl;
00890 continue;
00891 }
00892 PO* obj = dynamic_cast<PO*>(val->clone());
00893 if(obj==NULL) {
00894
00895 throw std::runtime_error("plist::Dictionary could not assign clone of object due to impossible type conflict (bad clone?)");
00896 }
00897 myRef.insert(obj);
00898 if(dynamic_cast<Collection*>(obj)!=NULL) {
00899 const std::string headline=("======== "+key+" ========");
00900 if(comment.compare(0,headline.size(),headline)!=0)
00901 addEntry(key,*obj,comment);
00902 else
00903 addEntry(key,*obj,comment.substr(headline.size()));
00904 } else
00905 addEntry(key,*obj,comment);
00906 }
00907 if((loadPolicy&REMOVALS) && seen.size()!=size()) {
00908 std::set<std::string> rem;
00909 for(const_iterator it=begin(); it!=end(); ++it) {
00910 if(seen.find(it->first)==seen.end())
00911 rem.insert(it->first);
00912 }
00913 for(std::set<std::string>::const_iterator it=rem.begin(); it!=rem.end(); ++it)
00914 removeEntry(*it);
00915 }
00916 return *this;
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 class ArrayBase : virtual public Collection {
00930 friend std::ostream& operator<<(std::ostream& os, const ArrayBase& d);
00931 public:
00932
00933 typedef std::vector<ObjectBase*> storage_t;
00934
00935 typedef storage_t::iterator iterator;
00936
00937 typedef storage_t::const_iterator const_iterator;
00938
00939
00940
00941
00942
00943
00944 struct DeniedValueConversions {
00945 virtual ~DeniedValueConversions() {}
00946 };
00947
00948 template<typename PO>
00949 struct EntryConstraint {
00950 virtual ~EntryConstraint() {}
00951
00952 virtual void addEntry(PO& val, const std::string& comment="")=0;
00953
00954 virtual void addEntry(PO* val, const std::string& comment="")=0;
00955
00956
00957 virtual void setEntry(size_t index, PO& val, bool warnExists=false)=0;
00958
00959 virtual void addEntry(size_t index, PO& val, const std::string& comment="")=0;
00960
00961 virtual void setEntry(size_t index, PO* val, bool warnExists=false)=0;
00962
00963 virtual void addEntry(size_t index, PO* val, const std::string& comment="")=0;
00964 };
00965
00966
00967
00968
00969
00970
00971 struct StringConversion {
00972 virtual ~StringConversion() {}
00973
00974 virtual void addValue(const std::string& val, const std::string& comment="")=0;
00975
00976 virtual void addValue(size_t index, const std::string&, const std::string& comment="")=0;
00977 };
00978
00979
00980
00981
00982
00983
00984 struct IntegerConversion {
00985 virtual ~IntegerConversion() {}
00986
00987 virtual void addValue(long val, const std::string& comment="", bool warnExists=true)=0;
00988
00989 virtual void addValue(unsigned long val, const std::string& comment="", bool warnExists=true)=0;
00990
00991 virtual void addValue(size_t index, long val, const std::string& comment="", bool warnExists=true)=0;
00992
00993 virtual void addValue(size_t index, unsigned long val, const std::string& comment="", bool warnExists=true)=0;
00994 };
00995
00996
00997
00998
00999
01000
01001 struct RealConversion {
01002 virtual ~RealConversion() {}
01003
01004 virtual void addValue(double val, const std::string& comment="", bool warnExists=true)=0;
01005
01006 virtual void addValue(size_t index, double val, const std::string& comment="", bool warnExists=true)=0;
01007 };
01008
01009
01010
01011
01012
01013 template<typename PO>
01014 struct ConversionTo : public StringConversion, public EntryConstraint<PO> {
01015
01016 template<typename T>
01017 void addValue(const T& val, const std::string& comment="") { addEntry(new PO(val),comment); }
01018 virtual void addValue(const std::string& val, const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(po,comment); }
01019
01020 virtual void addValue(char val[], const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(po,comment); }
01021
01022 virtual void addValue(const char val[], const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(po,comment); }
01023
01024 void addValue(long val, const std::string& comment="") { this->addEntry(new PO(val),comment); }
01025
01026 void addValue(unsigned long val, const std::string& comment="") { this->addEntry(new PO(val),comment); }
01027
01028 void addValue(double val, const std::string& comment="") { this->addEntry(new PO(val),comment); }
01029
01030
01031 template<typename T>
01032 void addValue(size_t index, const T& val, const std::string& comment="") { addEntry(index,new PO(val),comment); }
01033 virtual void addValue(size_t index, const std::string& val, const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(index,po,comment); }
01034
01035 virtual void addValue(size_t index, char val[], const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(index,po,comment); }
01036
01037 virtual void addValue(size_t index, const char val[], const std::string& comment="") { PO * po=new PO; try { po->set(val); } catch(...) { delete po; throw; } this->addEntry(index,po,comment); }
01038
01039 void addValue(size_t index, long val, const std::string& comment="") { this->addEntry(index,new PO(val),comment); }
01040
01041 void addValue(size_t index, unsigned long val, const std::string& comment="") { this->addEntry(index,new PO(val),comment); }
01042
01043 void addValue(size_t index, double val, const std::string& comment="") { this->addEntry(index,new PO(val),comment); }
01044 };
01045
01046
01047
01048 template<typename PO>
01049 struct WrapValueConversion : public StringConversion, public EntryConstraint<PO> {
01050
01051 template<typename T>
01052 void addValue(const T& val, const std::string& comment="") { this->addEntry(new Primitive<T>(val),comment); }
01053 virtual void addValue(const std::string& val, const std::string& comment="") { this->addEntry(new Primitive<std::string>(val),comment); }
01054
01055 virtual void addValue(char val[], const std::string& comment="") { this->addEntry(new Primitive<std::string>(val),comment); }
01056
01057 virtual void addValue(const char val[], const std::string& comment="") { this->addEntry(new Primitive<std::string>(val),comment); }
01058
01059 void addValue(long val, const std::string& comment="") { this->addEntry(new Primitive<long>(val),comment); }
01060
01061 void addValue(unsigned long val, const std::string& comment="") { this->addEntry(new Primitive<unsigned long>(val),comment); }
01062
01063 void addValue(double val, const std::string& comment="") { this->addEntry(new Primitive<double>(val),comment); }
01064
01065
01066 template<typename T>
01067 void addValue(size_t index, const T& val, const std::string& comment="") { this->addEntry(index,new Primitive<T>(val),comment); }
01068 virtual void addValue(size_t index, const std::string& val, const std::string& comment="") { this->addEntry(index,new Primitive<std::string>(val),comment); }
01069
01070 virtual void addValue(size_t index, char val[], const std::string& comment="") { this->addEntry(index,new Primitive<std::string>(val),comment); }
01071
01072 virtual void addValue(size_t index, const char val[], const std::string& comment="") { this->addEntry(index,new Primitive<std::string>(val),comment); }
01073
01074 void addValue(size_t index, long val, const std::string& comment="") { this->addEntry(index,new Primitive<long>(val),comment); }
01075
01076 void addValue(size_t index, unsigned long val, const std::string& comment="") { this->addEntry(index,new Primitive<unsigned long>(val),comment); }
01077
01078 void addValue(size_t index, double val, const std::string& comment="") { this->addEntry(index,new Primitive<double>(val),comment); }
01079 };
01080
01081
01082 virtual void forceEntry(ObjectBase& val, const std::string& comment="")=0;
01083
01084 virtual void forceEntry(ObjectBase* val, const std::string& comment="")=0;
01085
01086 virtual void forceEntry(size_t index, ObjectBase& val, const std::string& comment="")=0;
01087
01088 virtual void forceEntry(size_t index, ObjectBase* val, const std::string& comment="")=0;
01089
01090
01091 virtual bool removeEntry(size_t index);
01092
01093 ObjectBase& getEntry(size_t index) const { return *arr[index]; }
01094
01095 ObjectBase& operator[](size_t index) const { return *arr[index]; }
01096 virtual ObjectBase* resolveEntry(const std::string& path) const;
01097
01098 virtual void clear();
01099
01100
01101 const_iterator begin() const { return arr.begin(); }
01102
01103 const_iterator end() const { return arr.end(); }
01104
01105 virtual size_t size() const { return arr.size(); }
01106
01107 ObjectBase& front() const { return *arr.front(); }
01108
01109 ObjectBase& back() const { return *arr.back(); }
01110
01111
01112 virtual void setComment(size_t index, const std::string& comment);
01113
01114 virtual const std::string& getComment(size_t index) const;
01115
01116 virtual void loadXML(xmlNode* node);
01117 virtual void saveXML(xmlNode* node) const;
01118
01119 virtual std::string toString() const;
01120
01121 virtual unsigned int getLongestKeyLen(const regex_t* reg=NULL, unsigned int depth=-1) const;
01122
01123
01124 bool ownsReference(ObjectBase * val) const { return myRef.find(val)==myRef.end(); }
01125
01126 virtual void setSaveInlineStyle(bool b) { saveInlineStyle=b; }
01127 virtual bool getSaveInlineStyle() const { return saveInlineStyle; }
01128
01129 protected:
01130
01131 ArrayBase(bool growable) : Collection(growable?SYNC:FIXED,SYNC), arr(), myRef(), comments(), saveInlineStyle(false) { setLoadSavePolicy(growable?SYNC:FIXED,SYNC); }
01132
01133 ArrayBase(const ArrayBase& d) : Collection(d), arr(d.arr), myRef(d.myRef), comments(d.comments), saveInlineStyle(false) { cloneMyRef(); setLoadSavePolicy(d.getLoadPolicy(),d.getSavePolicy()); }
01134
01135 ArrayBase& operator=(const ArrayBase& d) { Collection::operator=(d); return *this; }
01136
01137
01138 ~ArrayBase() { clear(); }
01139
01140
01141 virtual void takeObject(size_t index, ObjectBase* obj);
01142
01143 virtual void fireEntryRemoved(ObjectBase& val);
01144
01145
01146
01147
01148
01149 iterator getSubEntry(const std::string& name, std::string::size_type& seppos);
01150
01151
01152
01153
01154 const_iterator getSubEntry(const std::string& name, std::string::size_type& seppos) const;
01155
01156
01157 virtual void cloneMyRef();
01158
01159
01160 virtual bool loadXMLNode(size_t index, xmlNode* val, const std::string& comment)=0;
01161
01162
01163 storage_t arr;
01164
01165
01166 std::set<ObjectBase*> myRef;
01167
01168
01169 typedef std::map<size_t,std::string> comments_t;
01170
01171
01172 comments_t comments;
01173
01174
01175
01176 bool saveInlineStyle;
01177 };
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 template<typename PO, typename Alloc=typename PO::template conversion_policy<ArrayBase,PO>::value_conversion >
01205 class ArrayOf : public ArrayBase, public Alloc {
01206
01207 typedef typename storage_t::const_iterator::iterator_category const_iterator_category;
01208 typedef typename storage_t::const_iterator::difference_type const_iterator_difference;
01209
01210 public:
01211
01212 typedef typename ArrayBase::storage_t storage_t;
01213
01214
01215
01216
01217 class const_iterator : public std::iterator<const_iterator_category, const PO*, const_iterator_difference> {
01218 public:
01219 typedef PO* value_type;
01220 typedef const_iterator_difference difference_type;
01221
01222 const_iterator(const storage_t::const_iterator& sit) : it(sit), tmp(NULL) {}
01223 const_iterator(const const_iterator& oit) : it(oit.it), tmp(NULL) {}
01224 const_iterator& operator=(const const_iterator& oit) { it=oit.it; return *this; }
01225
01226 value_type operator*() const { return dynamic_cast<PO*>(*it); }
01227 value_type const* operator->() const { tmp=dynamic_cast<PO*>(*it); return &tmp; }
01228 const_iterator& operator++() { ++it; return *this; }
01229 const_iterator operator++(int) { return const_iterator(it++); }
01230 const_iterator& operator--() { --it; return *this; }
01231 const_iterator operator--(int) { return const_iterator(it--); }
01232
01233 bool operator==(const const_iterator& rhs) const { return it==rhs.it; }
01234 bool operator!=(const const_iterator& rhs) const { return it!=rhs.it; }
01235
01236
01237 value_type operator[](const difference_type& __n) const { return dynamic_cast<PO*>(it[__n]); }
01238 const_iterator& operator+=(const difference_type& __n) { it += __n; return *this; }
01239 const_iterator operator+(const difference_type& __n) const { return const_iterator(it + __n); }
01240 const_iterator& operator-=(const difference_type& __n) { it -= __n; return *this; }
01241 const_iterator operator-(const difference_type& __n) const { return const_iterator(it - __n); }
01242 bool operator<(const const_iterator& __rhs) const { return it < __rhs.it; }
01243 bool operator>(const const_iterator& __rhs) const { return it > __rhs.it; }
01244 bool operator<=(const const_iterator& __rhs) const { return it <= __rhs.it; }
01245 bool operator>=(const const_iterator& __rhs) const { return it >= __rhs.it; }
01246 difference_type operator-(const const_iterator& __rhs) const { return it - __rhs.it; }
01247
01248 protected:
01249 storage_t::const_iterator it;
01250 mutable PO* tmp;
01251 };
01252
01253
01254
01255 ArrayOf() : ArrayBase(true), Alloc() {}
01256
01257 explicit ArrayOf(typename storage_t::size_type n) : ArrayBase(false), Alloc() {
01258 arr.resize(n);
01259 for(ArrayBase::iterator it=arr.begin(); it!=arr.end(); ++it)
01260 *it=new PO;
01261 myRef.insert(arr.begin(),arr.end());
01262 }
01263
01264 ArrayOf(typename storage_t::size_type n, const PO& t, bool growable=false) : ArrayBase(growable), Alloc() {
01265 arr.resize(n);
01266 #ifdef PLATFORM_APERIOS
01267 for(ArrayBase::iterator it=arr.begin(); it!=arr.end(); ++it) {
01268 *it=dynamic_cast<PO*>(t.clone());
01269 # ifdef DEBUG
01270 if(*it==NULL)
01271 std::cerr << "plist::Array construction from replicated value given NULL via clone" << std::endl;
01272 # endif
01273 }
01274 #else
01275 for(ArrayBase::iterator it=arr.begin(); it!=arr.end(); ++it)
01276 *it=t.clone();
01277 #endif
01278 myRef.insert(arr.begin(),arr.end());
01279 }
01280
01281 ArrayOf(const ArrayOf& d) : ArrayBase(d), Alloc(d) {}
01282
01283 ArrayOf& operator=(const ArrayOf& a);
01284
01285 virtual void set(const ObjectBase& ob) { const ArrayBase& a=dynamic_cast<const ArrayBase&>(ob); set(a); }
01286 virtual void set(const ArrayBase& a);
01287
01288
01289 ~ArrayOf() { }
01290
01291
01292 virtual void addEntry(PO& val, const std::string& comment="") { if(comment.size()>0) setComment(size(),comment); arr.push_back(&val); fireEntryAdded(*arr.back()); }
01293
01294 virtual void addEntry(PO* val, const std::string& comment="") { if(comment.size()>0) setComment(size(),comment); arr.push_back(val); takeObject(size()-1,val); fireEntryAdded(*arr.back()); }
01295
01296
01297 virtual void setEntry(size_t index, PO& val, bool warnExists=false);
01298
01299 virtual void addEntry(size_t index, PO& val, const std::string& comment="");
01300
01301 virtual void setEntry(size_t index, PO* val, bool warnExists=false);
01302
01303 virtual void addEntry(size_t index, PO* val, const std::string& comment="");
01304
01305
01306 virtual void forceEntry(ObjectBase& val, const std::string& comment="") { if(PO* po=dynamic_cast<PO*>(&val)) addEntry(*po,comment); else throw bad_format(NULL,"plist::ArrayBase::forceEntry() of wrong type"); }
01307
01308 virtual void forceEntry(ObjectBase* val, const std::string& comment="") { if(PO* po=dynamic_cast<PO*>(val)) addEntry(po,comment); else throw bad_format(NULL,"plist::ArrayBase::forceEntry() of wrong type"); }
01309
01310 virtual void forceEntry(size_t index, ObjectBase& val, const std::string& comment="") { if(PO* po=dynamic_cast<PO*>(&val)) addEntry(index,*po,comment); else throw bad_format(NULL,"plist::ArrayBase::forceEntry() of wrong type"); }
01311
01312 virtual void forceEntry(size_t index, ObjectBase* val, const std::string& comment="") { if(PO* po=dynamic_cast<PO*>(val)) addEntry(index,po,comment); else throw bad_format(NULL,"plist::ArrayBase::forceEntry() of wrong type"); }
01313
01314
01315 PO& getEntry(size_t index) const { return dynamic_cast<PO&>(*arr[index]); }
01316
01317 PO& operator[](size_t index) const { return dynamic_cast<PO&>(*arr[index]); }
01318
01319
01320 const_iterator begin() const { return arr.begin(); }
01321
01322 const_iterator end() const { return arr.end(); }
01323
01324 PO& front() const { return dynamic_cast<PO&>(*arr.front()); }
01325
01326 PO& back() const { return dynamic_cast<PO&>(*arr.back()); }
01327
01328
01329 virtual bool canContain(const ObjectBase& obj) { return (dynamic_cast<const PO*>(&obj)!=NULL); }
01330
01331
01332 PLIST_CLONE_DEF(ArrayOf,(new ArrayOf<PO,Alloc>(*this)));
01333
01334 protected:
01335
01336 virtual bool loadXMLNode(size_t index, xmlNode* val, const std::string& comment);
01337 };
01338
01339
01340 template<> ArrayOf<ObjectBase, ObjectBase::conversion_policy<ArrayBase,ObjectBase>::value_conversion>::ArrayOf(storage_t::size_type n) ATTR_deprecated;
01341
01342
01343
01344
01345 typedef ArrayOf<ObjectBase> Array;
01346 extern template class ArrayOf<ObjectBase>;
01347 extern template class ArrayOf<Dictionary>;
01348 extern template class ArrayOf<Primitive<float> >;
01349 extern template class ArrayOf<Primitive<double> >;
01350
01351
01352 template<typename PO, typename Alloc>
01353 void ArrayOf<PO,Alloc>::setEntry(size_t index, PO& val, bool warnExists) {
01354 if(index==size()) {
01355 arr.push_back(&val);
01356 fireEntryAdded(val);
01357 } else {
01358 if(arr[index]==&val)
01359 return;
01360 if(warnExists) {
01361 std::cerr << "Warning: new entry "<<index<<" ("<<val<<") conflicted with previous entry "<<index<<" ("<<(*arr[index])<<")"<<std::endl;
01362 std::cerr << " (use setEntry(...,false) if you expect you might need to overwrite)" << std::endl;
01363 }
01364 arr[index]=&val;
01365 fireEntriesChanged();
01366 }
01367 }
01368 template<typename PO, typename Alloc>
01369 void ArrayOf<PO,Alloc>::addEntry(size_t index, PO& val, const std::string& comment) {
01370 if(index==size()) {
01371 arr.push_back(&val);
01372 } else {
01373 ArrayBase::storage_t::iterator it=arr.begin();
01374 advance(it,index);
01375 arr.insert(it,&val);
01376 }
01377 if(comment.size()>0)
01378 setComment(index,comment);
01379 fireEntryAdded(val);
01380 }
01381 template<typename PO, typename Alloc>
01382 void ArrayOf<PO,Alloc>::setEntry(size_t index, PO* val, bool warnExists) {
01383 if(index>size())
01384 throw bad_format(NULL,"Error: attempted to setEntry() at index beyond one-past-end of plist::Array");
01385 else if(index==size()) {
01386 arr.push_back(val);
01387 fireEntryAdded(*val);
01388 } else {
01389 if(arr[index]==val)
01390 return;
01391 if(warnExists) {
01392 std::cerr << "Warning: new entry "<<index<<" ("<<val<<") conflicted with previous entry "<<index<<" ("<<(*arr[index])<<")"<<std::endl;
01393 std::cerr << " (use setEntry(...,false) if you expect you might need to overwrite)" << std::endl;
01394 }
01395 std::set<ObjectBase*>::iterator it=myRef.find(arr[index]);
01396 if(it!=myRef.end()) {
01397 myRef.erase(*it);
01398 delete arr[index];
01399 }
01400 arr[index]=val;
01401 takeObject(index,val);
01402 fireEntriesChanged();
01403 }
01404 }
01405 template<typename PO, typename Alloc>
01406 void ArrayOf<PO,Alloc>::addEntry(size_t index, PO* val, const std::string& comment) {
01407 if(index>size())
01408 throw bad_format(NULL,"Error: attempted to addEntry() at index beyond one-past-end of plist::Array");
01409 else if(index==size()) {
01410 arr.push_back(val);
01411 } else {
01412 ArrayBase::storage_t::iterator it=arr.begin();
01413 advance(it,index);
01414 arr.insert(it,val);
01415 }
01416 takeObject(index,val);
01417 if(comment.size()>0)
01418 setComment(index,comment);
01419 fireEntryAdded(*val);
01420 }
01421
01422
01423 PLIST_CLONE_IMPT2(PO,Alloc,ArrayOf,(new ArrayOf<PO,Alloc>(*this)));
01424
01425 template<typename PO, typename Alloc>
01426 bool ArrayOf<PO,Alloc>::loadXMLNode(size_t index, xmlNode* val, const std::string& comment) {
01427 if(index<size()) {
01428
01429 try {
01430
01431
01432 arr[index]->loadXML(val);
01433 if(comment.size()>0)
01434 setComment(index,comment);
01435 return true;
01436 } catch(...) {
01437
01438 if(loadPolicy!=SYNC)
01439 throw;
01440
01441 }
01442 } else if(!(savePolicy&ADDITIONS)) {
01443 if(warnUnused && savePolicy==FIXED)
01444 std::cerr << "Warning: plist::Array ran out of registered items (" << size() << ") during load. Ignoring extraneous items from source..." << std::endl;
01445 return false;
01446 }
01447 PO * cobj = plist::loadXML<PO>(val);
01448 if(index<size()) {
01449 setEntry(index,cobj,false);
01450 setComment(index,comment);
01451 } else {
01452 addEntry(index,cobj,comment);
01453 }
01454 return true;
01455 }
01456
01457 template<typename PO, typename Alloc>
01458 void ArrayOf<PO,Alloc>::set(const ArrayBase& a) {
01459 if(&a == this)
01460 return;
01461
01462 if(const ArrayOf* ao = dynamic_cast<const ArrayOf*>(&a)) {
01463 operator=(*ao);
01464 return;
01465 }
01466 ArrayBase::operator=(a);
01467
01468 for(unsigned int index=0; index<a.size(); ++index) {
01469 ObjectBase* val = &a[index];
01470 const std::string comment = a.getComment(index);
01471 if(index<size()) {
01472
01473 try {
01474
01475
01476 arr[index]->set(*val);
01477 if(comment.size()>0)
01478 setComment(index,comment);
01479 continue;
01480 } catch(const bad_format& ex) {
01481
01482 if(loadPolicy!=SYNC)
01483 throw;
01484
01485 }
01486 } else if(!(savePolicy&ADDITIONS)) {
01487 if(warnUnused && savePolicy==FIXED)
01488 std::cerr << "Warning: plist::Array ran out of registered items (" << size() << ") during load. Ignoring extraneous items from source..." << std::endl;
01489 break;
01490 }
01491 PO* obj=dynamic_cast<PO*>(val);
01492 if(obj==NULL) {
01493 obj = plist::allocate<PO>();
01494 try {
01495 obj->set(*val);
01496 } catch(...) {
01497 delete obj;
01498 throw;
01499 }
01500 myRef.insert(obj);
01501 } else {
01502 obj = dynamic_cast<PO*>(obj->clone());
01503 if(obj==NULL) {
01504
01505 throw std::runtime_error("plist::Array could not assign clone of object due to impossible type conflict (bad clone?)");
01506 }
01507 myRef.insert(obj);
01508 }
01509 if(index<size()) {
01510 setEntry(index,obj,false);
01511 setComment(index,comment);
01512 } else {
01513 addEntry(index,obj,comment);
01514 }
01515 }
01516 }
01517
01518 template<typename PO, typename Alloc>
01519 ArrayOf<PO,Alloc>& ArrayOf<PO,Alloc>::operator=(const ArrayOf& a) {
01520 if(&a==this)
01521 return *this;
01522 ArrayBase::operator=(a);
01523 for(unsigned int index=0; index<a.size(); ++index) {
01524 PO* val = &a[index];
01525 const std::string comment = a.getComment(index);
01526 if(index<size()) {
01527
01528 try {
01529
01530
01531 plist::assign(*dynamic_cast<PO*>(arr[index]),*val);
01532 if(comment.size()>0)
01533 setComment(index,comment);
01534 continue;
01535 } catch(const bad_format& ex) {
01536
01537 if(loadPolicy!=SYNC)
01538 throw;
01539
01540 }
01541 } else if(!(savePolicy&ADDITIONS)) {
01542 if(warnUnused && savePolicy==FIXED)
01543 std::cerr << "Warning: plist::Array ran out of registered items (" << size() << ") during load. Ignoring extraneous items from source..." << std::endl;
01544 break;
01545 }
01546 PO* obj = dynamic_cast<PO*>(val->clone());
01547 if(obj==NULL) {
01548
01549 throw std::runtime_error("plist::Array could not assign clone of object due to impossible type conflict (bad clone?)");
01550 }
01551 myRef.insert(obj);
01552 if(index<size()) {
01553 setEntry(index,obj,false);
01554 setComment(index,comment);
01555 } else {
01556 addEntry(index,obj,comment);
01557 }
01558 }
01559 return *this;
01560 }
01561
01562
01563
01564
01565
01566
01567
01568 std::ostream& filteredDisplay(std::ostream& os, const ObjectBase& c, const std::string& sel, int selType, unsigned int depth);
01569
01570
01571
01572
01573
01574
01575 std::ostream& filteredDisplay(std::ostream& os, const ObjectBase& c, const regex_t* reg, unsigned int depth);
01576
01577
01578 inline std::ostream& operator<<(std::ostream& os, const DictionaryBase& d) { return filteredDisplay(os,d,NULL,-1U); }
01579
01580
01581 inline std::ostream& operator<<(std::ostream& os, const ArrayBase& d) { return filteredDisplay(os,d,NULL,-1U); }
01582
01583 }
01584
01585
01586
01587
01588
01589
01590 #endif