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