00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_FORMAT_RESOURCEFILE_H
00008 #define BALL_FORMAT_RESOURCEFILE_H
00009
00010 #ifndef BALL_COMMON_H
00011 # include <BALL/common.h>
00012 #endif
00013
00014 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00015 # include <BALL/CONCEPT/forwardIterator.h>
00016 #endif
00017
00018 #ifndef BALL_CONCEPT_VISITOR_H
00019 # include <BALL/CONCEPT/visitor.h>
00020 #endif
00021
00022 #ifndef BALL_CONCEPT_AUTODELETABLE_H
00023 # include <BALL/CONCEPT/autoDeletable.h>
00024 #endif
00025
00026 #ifndef BALL_CONCEPT_PROCESSOR_H
00027 # include <BALL/CONCEPT/processor.h>
00028 #endif
00029
00030 #ifndef BALL_SYSTEM_FILE_H
00031 # include <BALL/SYSTEM/file.h>
00032 #endif
00033
00034 namespace BALL
00035 {
00043 class BALL_EXPORT ResourceEntry
00044 : public AutoDeletable
00045 {
00046 public:
00047
00048 BALL_CREATE_DEEP(ResourceEntry)
00049
00050
00053
00056 ResourceEntry();
00057
00063 ResourceEntry(const ResourceEntry& entry, bool deep = true);
00064
00074 ResourceEntry(const String& key, const String& value, ResourceEntry* parent = 0);
00075
00078 virtual ~ResourceEntry()
00079 ;
00080
00083 void clear();
00084
00087 void destroy();
00088
00090
00094
00099 void set(const ResourceEntry& entry, bool deep = true);
00100
00104 const ResourceEntry& operator = (const ResourceEntry &entry);
00105
00110 void get(ResourceEntry& entry, bool deep = true) const;
00112
00113
00117
00120 bool operator == (const ResourceEntry& entry) const;
00121
00124 bool operator != (const ResourceEntry& entry) const;
00125
00128 ResourceEntry& getRoot();
00129
00132 const ResourceEntry& getRoot() const;
00133
00136 ResourceEntry* getParent();
00137
00140 const ResourceEntry* getParent() const;
00141
00145 ResourceEntry* getChild(Position index);
00146
00150 const ResourceEntry* getChild(Position index) const;
00151
00156 ResourceEntry* getEntry(const String& key_path);
00157
00162 const ResourceEntry* getEntry(const String& key_path) const;
00163
00166 const String& getKey() const;
00167
00170 void setValue(const String& value);
00171
00174 String& getValue();
00175
00178 const String& getValue() const;
00179
00182 String getPath() const;
00183
00186 Size countChildren() const;
00187
00190 Size countDescendants() const;
00191
00194 Size getSize() const;
00195
00198 Size getDepth() const;
00199
00203 ResourceEntry* insertChild(const String& key, const String& value, bool replace_value = true);
00204
00207 ResourceEntry* insertSibling(const String& key, const String& value, bool replace_value = true);
00208
00212 ResourceEntry* insertChild(ResourceEntry& entry, bool replace_value = true);
00213
00216 ResourceEntry* insert(const String& key_path, const String& name);
00217
00220 bool mergeChildrenOf(ResourceEntry& entry, bool replace_value = true);
00221
00224 bool removeChild(const String& key, ResourceEntry** removed = 0);
00225
00228 bool removeKey(const String& key_path);
00229
00232 ResourceEntry* findChild(const String& key);
00233
00236 const ResourceEntry* findChild(const String& key) const;
00237
00240 ResourceEntry* findDescendant(const String& key);
00241
00244 const ResourceEntry* findDescendant(const String& key) const;
00245
00248 ResourceEntry* findEntry(const String& key);
00249
00252 const ResourceEntry* findEntry(const String& key) const;
00254
00258
00261 bool hasChild(const String& key) const;
00262
00265 bool isEmpty() const;
00266
00269 bool isParentOf(const ResourceEntry& entry) const;
00270
00273 bool isChildOf(const ResourceEntry& entry) const;
00274
00277 bool isAncestorOf(const ResourceEntry& entry) const;
00278
00281 bool isDescendantOf(const ResourceEntry& entry) const;
00282
00285 bool isRelatedWith(const ResourceEntry& entry) const;
00286
00289 bool isRoot() const;
00290
00292
00298 bool isValid() const;
00301 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00303
00304
00308
00311 void host(Visitor<ResourceEntry>& visitor);
00312
00315 bool apply(UnaryProcessor<ResourceEntry>& processor);
00316
00319 bool applyChildren(UnaryProcessor<ResourceEntry>& processor);
00321
00322 typedef ResourceEntry* IteratorPosition;
00323
00324 class BALL_EXPORT IteratorTraits_
00325 {
00326 public:
00327
00328 BALL_CREATE_DEEP(IteratorTraits_)
00329
00330 IteratorTraits_()
00331 : bound_(0),
00332 position_(0),
00333 stack_index_(new Index[1]),
00334 stack_capacity_(1),
00335 stack_size_(0)
00336 {
00337 }
00338
00339 IteratorTraits_(const ResourceEntry& entry)
00340 : bound_((ResourceEntry *)&entry),
00341 position_(0),
00342 stack_index_(new Index[1]),
00343 stack_capacity_(1),
00344 stack_size_(0)
00345 {
00346 }
00347
00348 IteratorTraits_(const IteratorTraits_& traits, bool = true)
00349 : bound_(traits.bound_),
00350 position_(traits.position_),
00351 stack_index_(new Index[traits.stack_capacity_]),
00352 stack_capacity_(traits.stack_capacity_),
00353 stack_size_(traits.stack_size_)
00354 {
00355 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00356 stack_index_[index] = traits.stack_index_[index];
00357 }
00358
00359 virtual ~IteratorTraits_()
00360 {
00361 delete[] stack_index_;
00362 }
00363
00364 const IteratorTraits_& operator = (const IteratorTraits_ &traits)
00365 {
00366 bound_ = traits.bound_;
00367 position_ = traits.position_;
00368 delete[] stack_index_;
00369 stack_index_ = new Index[traits.stack_capacity_];
00370 stack_capacity_ = traits.stack_capacity_;
00371 stack_size_ = traits.stack_size_;
00372
00373 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00374 {
00375 stack_index_[index] = traits.stack_index_[index];
00376 }
00377
00378 return *this;
00379 }
00380
00381 ResourceEntry* getContainer()
00382 {
00383 return bound_;
00384 }
00385
00386 const ResourceEntry* getContainer() const
00387 {
00388 return bound_;
00389 }
00390
00391 bool isSingular() const
00392 {
00393 return (bound_ == 0);
00394 }
00395
00396 IteratorPosition& getPosition()
00397 {
00398 return position_;
00399 }
00400
00401 const IteratorPosition& getPosition() const
00402 {
00403 return position_;
00404 }
00405
00406 bool operator == (const IteratorTraits_& traits) const
00407 {
00408 return (position_ == traits.position_);
00409 }
00410
00411 bool operator != (const IteratorTraits_& traits) const
00412 {
00413 return (position_ != traits.position_);
00414 }
00415
00416 bool isValid() const
00417 {
00418 return (bound_ != 0 && position_ != 0
00419 && stack_index_ != 0
00420 && stack_size_ <= stack_capacity_
00421 && stack_capacity_ > 0);
00422 }
00423
00424 void invalidate()
00425 {
00426 bound_ = 0;
00427 position_ = 0;
00428 stack_size_ = 0;
00429 }
00430
00431 void toBegin()
00432 {
00433 stack_size_ = 0;
00434 position_ = bound_;
00435 }
00436
00437 bool isBegin() const
00438 {
00439 return (position_ == bound_);
00440 }
00441
00442 void toEnd()
00443 {
00444 position_ = 0;
00445 }
00446
00447 bool isEnd() const
00448 {
00449 return (position_ == 0);
00450 }
00451
00452 ResourceEntry& getData()
00453 {
00454 return *position_;
00455 }
00456
00457 const ResourceEntry& getData() const
00458 {
00459 return *position_;
00460 }
00461
00462 void forward()
00463 {
00464 if (position_->number_children_ > 0)
00465 {
00466 position_ = position_->child_[0];
00467 push(0);
00468
00469 }
00470 else
00471 {
00472 Index next_child = INVALID_INDEX;
00473
00474 do
00475 {
00476 next_child = pop();
00477 if (next_child == INVALID_INDEX)
00478 {
00479 position_ = 0;
00480 return;
00481 }
00482 else
00483 {
00484 position_ = position_->parent_;
00485 }
00486
00487 } while(++next_child >= (Index)position_->number_children_);
00488
00489 push(next_child);
00490 position_ = position_->child_[next_child];
00491 }
00492 }
00493
00494
00495 Size getDepth() const
00496 {
00497 return stack_size_;
00498 }
00499
00500 private:
00501
00502 void push(Index next_child)
00503 {
00504 if (stack_size_ >= stack_capacity_)
00505 {
00506 Index *new_stack_index = new Index[stack_capacity_ << 1];
00507
00508 for (Index index = 0; index < (Index)stack_capacity_; ++index)
00509 {
00510 new_stack_index[index] = stack_index_[index];
00511 }
00512
00513 delete[] stack_index_;
00514 stack_index_ = new_stack_index;
00515 stack_capacity_ <<= 1;
00516 }
00517
00518 stack_index_[stack_size_] = next_child;
00519 ++stack_size_;
00520
00521 }
00522
00523 Index pop()
00524 {
00525 if (stack_size_ == 0)
00526 {
00527 return INVALID_INDEX;
00528 }
00529 else
00530 {
00531 return stack_index_[--stack_size_];
00532 }
00533 }
00534
00535 ResourceEntry* bound_;
00536 IteratorPosition position_;
00537 Index* stack_index_;
00538 Size stack_capacity_;
00539 Size stack_size_ ;
00540 };
00541
00542 friend class IteratorTraits_;
00543
00544 typedef ForwardIterator<ResourceEntry, ResourceEntry, ResourceEntry*, IteratorTraits_> Iterator;
00545 typedef ConstForwardIterator<ResourceEntry, ResourceEntry, ResourceEntry*, IteratorTraits_> ConstIterator;
00546
00547 Iterator begin() { return Iterator::begin(*this); }
00548 Iterator end() { return Iterator::end(*this); }
00549
00550
00551 ConstIterator begin() const { return ConstIterator::begin(*this); }
00552 ConstIterator end() const { return ConstIterator::end(*this); }
00553
00554 protected:
00555
00556 virtual ResourceEntry* newEntry
00557 (const String& key, const String& value, ResourceEntry* parent = 0) const;
00558
00559 virtual ResourceEntry** newEntryArray(Size size) const;
00560
00561 virtual void deleteEntry(ResourceEntry* entry) const;
00562
00563 virtual void deleteEntryArray(ResourceEntry** entry_array) const;
00564
00565 bool applyNostart_(UnaryProcessor<ResourceEntry>& processor);
00566
00567
00568 private:
00569
00570 ResourceEntry* clone_(ResourceEntry* parent) const;
00571 bool findGreaterOrEqual_(const String& key, Index& found) const;
00572
00573 String key_;
00574 String value_;
00575 ResourceEntry* parent_;
00576 ResourceEntry** child_;
00577 Size number_children_;
00578 };
00579
00580
00584 class BALL_EXPORT ResourceFile
00585 : public File
00586 {
00587 public:
00588
00592
00595 static char ENTRY_BEGIN;
00596
00599 static char ENTRY_END;
00600
00603 static char SEPARATOR;
00605
00609
00612 typedef ResourceEntry Entry;
00614
00618
00621 ResourceFile();
00622
00625 ResourceFile(const String& name)
00626 throw(Exception::FileNotFound);
00627
00630 ResourceFile(const ResourceFile& file)
00631 throw(Exception::FileNotFound);
00632
00635 virtual ~ResourceFile()
00636 ;
00637
00640 void destroy();
00641
00644 virtual void clear() ;
00645
00647
00648
00652
00653
00654
00655 bool open(const String& name);
00656
00657
00658
00659 void close();
00660
00661
00662
00663 static void saveAs(const Entry& entry, const String& name);
00664
00665
00666
00667 void saveAs(const String& name);
00668
00669
00670
00671 void save(const Entry& entry);
00672
00673
00674
00675 void save();
00677
00678
00682
00683
00684 Size getSize() const;
00685
00686
00687
00688 Entry& getRoot();
00689
00690
00691
00692 const Entry& getRoot() const;
00693
00694
00695
00696 Entry* getEntry(const String& key_path);
00697
00698
00699
00700 const Entry* getEntry(const String& key_path) const;
00701
00702
00703
00704 String* getValue(const String& key_path);
00705
00706
00707
00708 const String* getValue(const String& key_path) const;
00709
00710
00711
00712 Entry* insert(const String& key_path, const String& name);
00713
00714
00715
00716 bool removeKey(const String& key_path);
00717
00719
00723
00726 bool operator == (const ResourceFile& entry) const;
00727
00730 bool operator != (const ResourceFile& entry) const;
00731
00732
00733
00734 bool hasKey(const String& key_path) const;
00735
00736
00737
00738 bool isEmpty() const;
00740
00741
00745
00748 bool isValid() const;
00749
00752 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00754
00755
00759
00762 friend std::istream& operator >> (std::istream& s, ResourceFile& resource_file);
00764
00768
00771 void host(Visitor<ResourceFile>& visitor);
00772
00775 bool apply(UnaryProcessor<Entry>& processor);
00776
00779 static bool applyChildren(Entry& entry, UnaryProcessor<Entry>& processor);
00781
00782 typedef Entry::Iterator Iterator;
00783
00784 Iterator begin()
00785 {
00786 return Iterator::begin(root_);
00787 }
00788
00789 Iterator end()
00790 {
00791 return Iterator::end(root_);
00792 }
00793
00794
00795 typedef Entry::ConstIterator ConstIterator;
00796
00797 ConstIterator begin() const
00798 {
00799 return ConstIterator::begin(root_);
00800 }
00801
00802 ConstIterator end() const
00803 {
00804 return ConstIterator::end(root_);
00805 }
00806
00807
00808 private:
00809
00810 const ResourceFile& operator = (const ResourceFile& file);
00811
00812 static void save_(File& file, const Entry* entry, Size& depth);
00813
00814 bool validateSyntax_();
00815
00816 void skipWhitespaces_();
00817
00818 Entry root_;
00819 };
00820
00821 # ifndef BALL_NO_INLINE_FUNCTIONS
00822 # include <BALL/FORMAT/resourceFile.iC>
00823 # endif
00824 }
00825
00826 #endif // BALL_FORMAT_RESOURCEFILE_H