BALL  1.4.1
resourceFile.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines