resourceFile.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: resourceFile.h,v 1.27 2005/12/23 17:01:46 amoll Exp $
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 /* deep */ = 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       // traits-specific:
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     /*  Return true if the key exists somewhere in the tree.
00733     */
00734     bool hasKey(const String& key_path) const;
00735 
00736     /*  Return true if the entry has no children.
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 } // namespace BALL
00825 
00826 #endif // BALL_FORMAT_RESOURCEFILE_H