BALL
1.4.1
|
00001 // -*- Mode: C++; tab-width: 2; -*- 00002 // vi: set ts=2: 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 /* deep */ = 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 // traits-specific: 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 00623 ResourceFile(const String& name); 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 /* Return true if the key exists somewhere in the tree. 00724 */ 00725 bool hasKey(const String& key_path) const; 00726 00727 /* Return true if the entry has no children. 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 } // namespace BALL 00816 00817 #endif // BALL_FORMAT_RESOURCEFILE_H