00001
00002
00003
00004
00005 #ifndef BALL_FORMAT_RESOURCEFILE_H
00006 #define BALL_FORMAT_RESOURCEFILE_H
00007
00008 #ifndef BALL_COMMON_H
00009 # include <BALL/common.h>
00010 #endif
00011
00012 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00013 # include <BALL/CONCEPT/forwardIterator.h>
00014 #endif
00015
00016 #ifndef BALL_CONCEPT_VISITOR_H
00017 # include <BALL/CONCEPT/visitor.h>
00018 #endif
00019
00020 #ifndef BALL_CONCEPT_AUTODELETABLE_H
00021 # include <BALL/CONCEPT/autoDeletable.h>
00022 #endif
00023
00024 #ifndef BALL_CONCEPT_PROCESSOR_H
00025 # include <BALL/CONCEPT/processor.h>
00026 #endif
00027
00028 #ifndef BALL_SYSTEM_FILE_H
00029 # include <BALL/SYSTEM/file.h>
00030 #endif
00031
00032 namespace BALL
00033 {
00041 class BALL_EXPORT ResourceEntry
00042 : public AutoDeletable
00043 {
00044 public:
00045
00046 BALL_CREATE_DEEP(ResourceEntry)
00047
00048
00051
00054 ResourceEntry();
00055
00061 ResourceEntry(const ResourceEntry& entry, bool deep = true);
00062
00072 ResourceEntry(const String& key, const String& value, ResourceEntry* parent = 0);
00073
00076 virtual ~ResourceEntry();
00077
00080 void clear();
00081
00084 void destroy();
00085
00087
00091
00096 void set(const ResourceEntry& entry, bool deep = true);
00097
00101 const ResourceEntry& operator = (const ResourceEntry &entry);
00102
00107 void get(ResourceEntry& entry, bool deep = true) const;
00109
00110
00114
00117 bool operator == (const ResourceEntry& entry) const;
00118
00121 bool operator != (const ResourceEntry& entry) const;
00122
00125 ResourceEntry& getRoot();
00126
00129 const ResourceEntry& getRoot() const;
00130
00133 ResourceEntry* getParent();
00134
00137 const ResourceEntry* getParent() const;
00138
00142 ResourceEntry* getChild(Position index);
00143
00147 const ResourceEntry* getChild(Position index) const;
00148
00153 ResourceEntry* getEntry(const String& key_path);
00154
00159 const ResourceEntry* getEntry(const String& key_path) const;
00160
00163 const String& getKey() const;
00164
00167 void setValue(const String& value);
00168
00171 String& getValue();
00172
00175 const String& getValue() const;
00176
00179 String getPath() const;
00180
00183 Size countChildren() const;
00184
00187 Size countDescendants() const;
00188
00191 Size getSize() const;
00192
00195 Size getDepth() const;
00196
00200 ResourceEntry* insertChild(const String& key, const String& value, bool replace_value = true);
00201
00204 ResourceEntry* insertSibling(const String& key, const String& value, bool replace_value = true);
00205
00209 ResourceEntry* insertChild(ResourceEntry& entry, bool replace_value = true);
00210
00213 ResourceEntry* insert(const String& key_path, const String& name);
00214
00217 bool mergeChildrenOf(ResourceEntry& entry, bool replace_value = true);
00218
00221 bool removeChild(const String& key, ResourceEntry** removed = 0);
00222
00225 bool removeKey(const String& key_path);
00226
00229 ResourceEntry* findChild(const String& key);
00230
00233 const ResourceEntry* findChild(const String& key) const;
00234
00237 ResourceEntry* findDescendant(const String& key);
00238
00241 const ResourceEntry* findDescendant(const String& key) const;
00242
00245 ResourceEntry* findEntry(const String& key);
00246
00249 const ResourceEntry* findEntry(const String& key) const;
00251
00255
00258 bool hasChild(const String& key) const;
00259
00262 bool isEmpty() const;
00263
00266 bool isParentOf(const ResourceEntry& entry) const;
00267
00270 bool isChildOf(const ResourceEntry& entry) const;
00271
00274 bool isAncestorOf(const ResourceEntry& entry) const;
00275
00278 bool isDescendantOf(const ResourceEntry& entry) const;
00279
00282 bool isRelatedWith(const ResourceEntry& entry) const;
00283
00286 bool isRoot() const;
00287
00289
00295 bool isValid() const;
00298 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00300
00301
00305
00308 void host(Visitor<ResourceEntry>& visitor);
00309
00312 bool apply(UnaryProcessor<ResourceEntry>& processor);
00313
00316 bool applyChildren(UnaryProcessor<ResourceEntry>& processor);
00318
00319 typedef ResourceEntry* IteratorPosition;
00320
00321 class BALL_EXPORT IteratorTraits_
00322 {
00323 public:
00324
00325 BALL_CREATE_DEEP(IteratorTraits_)
00326
00327 IteratorTraits_()
00328 : bound_(0),
00329 position_(0),
00330 stack_index_(new Index[1]),
00331 stack_capacity_(1),
00332 stack_size_(0)
00333 {
00334 }
00335
00336 IteratorTraits_(const ResourceEntry& entry)
00337 : bound_((ResourceEntry *)&entry),
00338 position_(0),
00339 stack_index_(new Index[1]),
00340 stack_capacity_(1),
00341 stack_size_(0)
00342 {
00343 }
00344
00345 IteratorTraits_(const IteratorTraits_& traits, bool = true)
00346 : bound_(traits.bound_),
00347 position_(traits.position_),
00348 stack_index_(new Index[traits.stack_capacity_]),
00349 stack_capacity_(traits.stack_capacity_),
00350 stack_size_(traits.stack_size_)
00351 {
00352 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00353 stack_index_[index] = traits.stack_index_[index];
00354 }
00355
00356 virtual ~IteratorTraits_()
00357 {
00358 delete[] stack_index_;
00359 }
00360
00361 const IteratorTraits_& operator = (const IteratorTraits_ &traits)
00362 {
00363 bound_ = traits.bound_;
00364 position_ = traits.position_;
00365 delete[] stack_index_;
00366 stack_index_ = new Index[traits.stack_capacity_];
00367 stack_capacity_ = traits.stack_capacity_;
00368 stack_size_ = traits.stack_size_;
00369
00370 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00371 {
00372 stack_index_[index] = traits.stack_index_[index];
00373 }
00374
00375 return *this;
00376 }
00377
00378 ResourceEntry* getContainer()
00379 {
00380 return bound_;
00381 }
00382
00383 const ResourceEntry* getContainer() const
00384 {
00385 return bound_;
00386 }
00387
00388 bool isSingular() const
00389 {
00390 return (bound_ == 0);
00391 }
00392
00393 IteratorPosition& getPosition()
00394 {
00395 return position_;
00396 }
00397
00398 const IteratorPosition& getPosition() const
00399 {
00400 return position_;
00401 }
00402
00403 bool operator == (const IteratorTraits_& traits) const
00404 {
00405 return (position_ == traits.position_);
00406 }
00407
00408 bool operator != (const IteratorTraits_& traits) const
00409 {
00410 return (position_ != traits.position_);
00411 }
00412
00413 bool isValid() const
00414 {
00415 return (bound_ != 0 && position_ != 0
00416 && stack_index_ != 0
00417 && stack_size_ <= stack_capacity_
00418 && stack_capacity_ > 0);
00419 }
00420
00421 void invalidate()
00422 {
00423 bound_ = 0;
00424 position_ = 0;
00425 stack_size_ = 0;
00426 }
00427
00428 void toBegin()
00429 {
00430 stack_size_ = 0;
00431 position_ = bound_;
00432 }
00433
00434 bool isBegin() const
00435 {
00436 return (position_ == bound_);
00437 }
00438
00439 void toEnd()
00440 {
00441 position_ = 0;
00442 }
00443
00444 bool isEnd() const
00445 {
00446 return (position_ == 0);
00447 }
00448
00449 ResourceEntry& getData()
00450 {
00451 return *position_;
00452 }
00453
00454 const ResourceEntry& getData() const
00455 {
00456 return *position_;
00457 }
00458
00459 void forward()
00460 {
00461 if (position_->number_children_ > 0)
00462 {
00463 position_ = position_->child_[0];
00464 push(0);
00465
00466 }
00467 else
00468 {
00469 Index next_child = INVALID_INDEX;
00470
00471 do
00472 {
00473 next_child = pop();
00474 if (next_child == INVALID_INDEX)
00475 {
00476 position_ = 0;
00477 return;
00478 }
00479 else
00480 {
00481 position_ = position_->parent_;
00482 }
00483
00484 } while(++next_child >= (Index)position_->number_children_);
00485
00486 push(next_child);
00487 position_ = position_->child_[next_child];
00488 }
00489 }
00490
00491
00492 Size getDepth() const
00493 {
00494 return stack_size_;
00495 }
00496
00497 private:
00498
00499 void push(Index next_child)
00500 {
00501 if (stack_size_ >= stack_capacity_)
00502 {
00503 Index *new_stack_index = new Index[stack_capacity_ << 1];
00504
00505 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00506 {
00507 new_stack_index[index] = stack_index_[index];
00508 }
00509
00510 delete[] stack_index_;
00511 stack_index_ = new_stack_index;
00512 stack_capacity_ <<= 1;
00513 }
00514
00515 stack_index_[stack_size_] = next_child;
00516 ++stack_size_;
00517
00518 }
00519
00520 Index pop()
00521 {
00522 if (stack_size_ == 0)
00523 {
00524 return INVALID_INDEX;
00525 }
00526 else
00527 {
00528 return stack_index_[--stack_size_];
00529 }
00530 }
00531
00532 ResourceEntry* bound_;
00533 IteratorPosition position_;
00534 Index* stack_index_;
00535 Size stack_capacity_;
00536 Size stack_size_;
00537 };
00538
00539 friend class IteratorTraits_;
00540
00541 typedef ForwardIterator<ResourceEntry, ResourceEntry, ResourceEntry*, IteratorTraits_> Iterator;
00542 typedef ConstForwardIterator<ResourceEntry, ResourceEntry, ResourceEntry*, IteratorTraits_> ConstIterator;
00543
00544 Iterator begin() { return Iterator::begin(*this); }
00545 Iterator end() { return Iterator::end(*this); }
00546
00547
00548 ConstIterator begin() const { return ConstIterator::begin(*this); }
00549 ConstIterator end() const { return ConstIterator::end(*this); }
00550
00551 protected:
00552
00553 virtual ResourceEntry* newEntry
00554 (const String& key, const String& value, ResourceEntry* parent = 0) const;
00555
00556 virtual ResourceEntry** newEntryArray(Size size) const;
00557
00558 virtual void deleteEntry(ResourceEntry* entry) const;
00559
00560 virtual void deleteEntryArray(ResourceEntry** entry_array) const;
00561
00562 bool applyNostart_(UnaryProcessor<ResourceEntry>& processor);
00563
00564
00565 private:
00566
00567 ResourceEntry* clone_(ResourceEntry* parent) const;
00568 bool findGreaterOrEqual_(const String& key, Index& found) const;
00569
00570 String key_;
00571 String value_;
00572 ResourceEntry* parent_;
00573 ResourceEntry** child_;
00574 Size number_children_;
00575 };
00576
00577
00581 class BALL_EXPORT ResourceFile
00582 : public File
00583 {
00584 public:
00585
00589
00592 static char ENTRY_BEGIN;
00593
00596 static char ENTRY_END;
00597
00600 static char SEPARATOR;
00602
00606
00609 typedef ResourceEntry Entry;
00611
00615
00618 ResourceFile();
00619
00622 ResourceFile(const String& name)
00623 throw(Exception::FileNotFound);
00624
00627 virtual ~ResourceFile();
00628
00631 void destroy();
00632
00635 virtual void clear();
00636
00638
00639
00643
00644
00645
00646 bool open(const String& name);
00647
00648
00649
00650 void close();
00651
00652
00653
00654 static void saveAs(const Entry& entry, const String& name);
00655
00656
00657
00658 void saveAs(const String& name);
00659
00660
00661
00662 void save(const Entry& entry);
00663
00664
00665
00666 void save();
00668
00669
00673
00674
00675 Size getSize() const;
00676
00677
00678
00679 Entry& getRoot();
00680
00681
00682
00683 const Entry& getRoot() const;
00684
00685
00686
00687 Entry* getEntry(const String& key_path);
00688
00689
00690
00691 const Entry* getEntry(const String& key_path) const;
00692
00693
00694
00695 String* getValue(const String& key_path);
00696
00697
00698
00699 const String* getValue(const String& key_path) const;
00700
00701
00702
00703 Entry* insert(const String& key_path, const String& name);
00704
00705
00706
00707 bool removeKey(const String& key_path);
00708
00710
00714
00717 bool operator == (const ResourceFile& entry) const;
00718
00721 bool operator != (const ResourceFile& entry) const;
00722
00723
00724
00725 bool hasKey(const String& key_path) const;
00726
00727
00728
00729 bool isEmpty() const;
00731
00732
00736
00739 bool isValid() const;
00740
00743 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00745
00746
00750
00753 friend std::istream& operator >> (std::istream& s, ResourceFile& resource_file);
00755
00759
00762 void host(Visitor<ResourceFile>& visitor);
00763
00766 bool apply(UnaryProcessor<Entry>& processor);
00767
00770 static bool applyChildren(Entry& entry, UnaryProcessor<Entry>& processor);
00772
00773 typedef Entry::Iterator Iterator;
00774
00775 Iterator begin()
00776 {
00777 return Iterator::begin(root_);
00778 }
00779
00780 Iterator end()
00781 {
00782 return Iterator::end(root_);
00783 }
00784
00785
00786 typedef Entry::ConstIterator ConstIterator;
00787
00788 ConstIterator begin() const
00789 {
00790 return ConstIterator::begin(root_);
00791 }
00792
00793 ConstIterator end() const
00794 {
00795 return ConstIterator::end(root_);
00796 }
00797
00798
00799 private:
00800
00801 const ResourceFile& operator = (const ResourceFile& file);
00802
00803 static void save_(File& file, const Entry* entry, Size& depth);
00804
00805 bool validateSyntax_();
00806
00807 void skipWhitespaces_();
00808
00809 Entry root_;
00810 };
00811
00812 # ifndef BALL_NO_INLINE_FUNCTIONS
00813 # include <BALL/FORMAT/resourceFile.iC>
00814 # endif
00815 }
00816
00817 #endif // BALL_FORMAT_RESOURCEFILE_H