Go to the documentation of this file.00001 # if ! defined(TS_CONFIG_VALUE_HEADER)
00002 # define TS_CONFIG_VALUE_HEADER
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 # include <string.h>
00028 # include <ts/TsBuffer.h>
00029 # include <tsconfig/NumericType.h>
00030 # include <tsconfig/IntrusivePtr.h>
00031 # include <tsconfig/Errata.h>
00032 # include <vector>
00033 
00034 namespace ts { namespace config {
00035 
00036 
00037 class Value;
00038 class Path;
00039 
00040 namespace detail {
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048   struct PseudoBool {
00049     typedef bool (PseudoBool::*Type)() const; 
00050     bool operator ! () const; 
00051     static Type const TRUE; 
00052     static Type const FALSE; 
00053   };
00054 }
00055 
00056 
00057 enum ValueType {
00058   VoidValue, 
00059   ListValue, 
00060   GroupValue, 
00061   StringValue, 
00062   IntegerValue, 
00063   PathValue, 
00064   
00065 };
00066 
00067 static size_t const N_VALUE_TYPES = PathValue + 1;
00068 
00069 
00070 
00071 class Path {
00072   friend class Value;
00073 protected:
00074   class ImplType : public IntrusivePtrCounter {
00075     friend class Path;
00076   public:
00077     ImplType(); 
00078   protected:
00079 
00080 
00081 
00082 
00083 
00084     typedef std::vector<ConstBuffer> Elements;
00085     Elements _elements; 
00086   };
00087 public:
00088   typedef Path self; 
00089 
00090   Path(); 
00091 
00092 
00093   self& append(
00094     ConstBuffer const& tag 
00095   );
00096 
00097   self& append(
00098     size_t idx 
00099   );
00100 
00101   self& reset();
00102 
00103 
00104   size_t count() const;
00105 
00106 
00107   ConstBuffer const& operator [] (
00108     size_t index 
00109   ) const;
00110 
00111 
00112 
00113 
00114 
00115   class Parser {
00116   public:
00117     typedef Parser self; 
00118 
00119     Parser(); 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128     Parser(
00129       ConstBuffer const& text 
00130     );
00131 
00132 
00133 
00134 
00135 
00136     self& setInput(
00137       ConstBuffer const& text 
00138     );
00139 
00140 
00141     enum Result {
00142       ERROR, 
00143       TAG, 
00144       INDEX, 
00145       EOP, 
00146     };
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160     Rv<Result> parse(
00161       ConstBuffer* cbuff = 0 
00162     );
00163 
00164 
00165     bool hasInput() const;
00166 
00167   protected:
00168     ConstBuffer _input; 
00169     char const* _c; 
00170   };
00171 protected:
00172   typedef IntrusivePtr<ImplType> ImplPtr; 
00173   ImplPtr _ptr; 
00174 
00175   ImplType* instance();
00176 };
00177 
00178 namespace detail {
00179 
00180   extern Buffer const NULL_BUFFER;
00181 
00182   extern ConstBuffer const NULL_CONST_BUFFER;
00183 
00184   typedef NumericType<size_t, struct ValueIndexTag> ValueIndex;
00185 
00186   static ValueIndex const NULL_VALUE_INDEX = static_cast<ValueIndex::raw_type>(-1);
00187 
00188   typedef NumericType<size_t, struct GenerationTag> Generation;
00189 
00190 
00191 
00192 
00193   static unsigned int const IS_VALID = 1;
00194   static unsigned int const IS_LITERAL = 1<<1;
00195   static unsigned int const IS_CONTAINER = 1<<2;
00196 
00197 
00198   extern unsigned int const Type_Property[N_VALUE_TYPES];
00199 
00200 
00201 
00202 
00203 
00204 
00205   class ValueItem {
00206     
00207     
00208     
00209     friend class ts::config::Value;
00210     friend class ValueTable;
00211   public:
00212 
00213     ValueItem();
00214 
00215     ValueItem(ValueType type);
00216 
00217     ValueType getType() const;
00218   protected:
00219     ValueType _type;      
00220     ValueIndex _parent;   
00221     ConstBuffer _text;    
00222     ConstBuffer _name;    
00223     size_t _local_index;  
00224     int _srcLine;         
00225     int _srcColumn;       
00226 
00227 
00228     typedef std::vector<ValueIndex> ChildGroup;
00229 
00230     ChildGroup _children;
00231 
00232     Path _path;
00233 
00234     
00235 
00236     struct Name {
00237       ConstBuffer _text; 
00238       ValueIndex _index; 
00239     };
00240 
00241     typedef std::vector<Name> NameGroup;
00242 
00243 
00244 
00245 
00246 
00247     NameGroup _names;
00248   };
00249 
00250   class ValueTable;
00251 
00252 
00253 
00254 
00255   class ValueTableImpl : public IntrusivePtrCounter {
00256     friend class ValueTable;
00257   public:
00258     typedef ValueTableImpl self; 
00259 
00260     ValueTableImpl(); 
00261     ~ValueTableImpl(); 
00262   protected:
00263 
00264     typedef std::vector<ValueItem> ItemTable;
00265     ItemTable _values; 
00266     Generation _generation; 
00267 
00268     typedef std::vector<Buffer> BufferGroup;
00269 
00270 
00271 
00272     BufferGroup _buffers;
00273 
00274     static ValueItem NULL_ITEM; 
00275   };
00276 
00277 
00278 
00279 
00280 
00281   class ValueTable {
00282   public:
00283     typedef ValueTable self; 
00284     typedef ValueTableImpl ImplType; 
00285 
00286 
00287 
00288     size_t size() const;
00289 
00290 
00291     Generation generation() const;
00292 
00293 
00294 
00295     ValueItem const& operator [] (
00296       ValueIndex idx 
00297     ) const;
00298 
00299 
00300     ValueItem& operator [] (
00301       ValueIndex idx 
00302     );
00303 
00304 
00305 
00306     self& forceRootItem();
00307 
00308 
00309 
00310 
00311 
00312     Rv<ValueIndex> make(
00313       ValueIndex parent, 
00314       ValueType type, 
00315       ConstBuffer const& name = NULL_BUFFER 
00316     );
00317 
00318 
00319 
00320     bool operator ! () const;
00321 
00322 
00323     operator PseudoBool::Type() const;
00324 
00325 
00326     self& reset();
00327 
00328 
00329 
00330 
00331 
00332 
00333     Buffer alloc(size_t n);
00334   protected:
00335     typedef IntrusivePtr<ImplType> ImplPtr; 
00336     ImplPtr _ptr; 
00337 
00338 
00339     ImplType* instance();
00340   };
00341 } 
00342 
00343 
00344 
00345 
00346 class Configuration {
00347   friend class Value;
00348 public:
00349   typedef Configuration self; 
00350 
00351 
00352 
00353 
00354   bool operator ! () const;
00355 
00356 
00357 
00358 
00359   operator detail::PseudoBool::Type () const;
00360 
00361 
00362 
00363 
00364   Value getRoot() const;
00365 
00366 
00367   size_t childCount() const;
00368 
00369 
00370 
00371   Value operator [] (
00372     size_t idx 
00373   ) const;
00374 
00375 
00376 
00377   Value operator [] (
00378     ConstBuffer const& name
00379   ) const;
00380 
00381 
00382 
00383   Value operator [] (
00384     char const* name 
00385   ) const;
00386 
00387 
00388 
00389 
00390   Value find(
00391     char const* path 
00392   );
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400   static Rv<self> loadFromPath(
00401     char const* path 
00402   );
00403 
00404 
00405 
00406 
00407 
00408   Buffer alloc(
00409     size_t n 
00410   );
00411 protected:
00412   detail::ValueTable _table; 
00413 };
00414 
00415 
00416 
00417 
00418 
00419 
00420 class Value {
00421   friend class Configuration;
00422 public:
00423   typedef Value self; 
00424 
00425 
00426   Value();
00427 
00428   ~Value();
00429 
00430 
00431   ValueType getType() const;
00432 
00433 
00434   bool hasValue() const;
00435 
00436 
00437 
00438 
00439   bool operator ! () const;
00440 
00441 
00442 
00443 
00444 
00445   operator detail::PseudoBool::Type () const;
00446 
00447 
00448 
00449 
00450 
00451   ConstBuffer const& getText() const;
00452 
00453   self& setText(
00454     ConstBuffer const& text
00455   );
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467   ConstBuffer const& getName() const;
00468 
00469 
00470 
00471 
00472 
00473   size_t getIndex() const;
00474 
00475 
00476 
00477 
00478   bool isLiteral() const;
00479 
00480 
00481 
00482   bool isContainer() const;
00483 
00484   Value getParent() const;
00485 
00486   bool isRoot() const;
00487 
00488 
00489   size_t childCount() const;
00490 
00491 
00492 
00493   Value operator [] (
00494     size_t idx 
00495   ) const;
00496 
00497 
00498 
00499   Value operator [] (
00500     ConstBuffer const& name
00501   ) const;
00502 
00503 
00504 
00505   Value operator [] (
00506     char const* name 
00507   ) const;
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533   Rv<Value> makeString(
00534     ConstBuffer const& text, 
00535     ConstBuffer const& name = detail::NULL_BUFFER
00536   );
00537 
00538   Rv<Value> makeInteger(
00539     ConstBuffer const& text, 
00540     ConstBuffer const& name = detail::NULL_BUFFER
00541   );
00542 
00543   Rv<Value> makeGroup(
00544     ConstBuffer const& name = detail::NULL_BUFFER
00545   );
00546 
00547   Rv<Value> makeList(
00548     ConstBuffer const& name = detail::NULL_BUFFER
00549   );
00550 
00551   Rv<Value> makePath(
00552     Path const& path, 
00553     ConstBuffer const& name = detail::NULL_BUFFER
00554   );
00555 
00556 
00557   Rv<Value> makeChild(
00558     ValueType type, 
00559     ConstBuffer const& name = detail::NULL_BUFFER
00560   );
00561 
00562 
00563 
00564 
00565 
00566   Value find(
00567     ConstBuffer const& path 
00568   );
00569 
00570 
00571 
00572   Value find(
00573     char const* path 
00574   );
00575 
00576 
00577 
00578   Value find(
00579     Path const& path 
00580   );
00581 
00582 
00583 
00584 
00585 
00586   self& reset();
00587 
00588 
00589 
00590   self& setSourceLine(
00591     int line 
00592   );
00593 
00594 
00595   self& setSourceColumn(
00596     int col 
00597   );
00598 
00599   self& setSource(
00600     int line, 
00601     int col 
00602   );
00603 
00604 
00605   int getSourceLine() const;
00606 
00607 
00608   int getSourceColumn() const;
00609 
00610 protected:
00611   
00612   
00613   
00614   
00615   Configuration _config; 
00616   detail::ValueIndex _vidx; 
00617 
00618   static Buffer const NULL_BUFFER; 
00619 
00620 
00621   Value(
00622     Configuration cfg, 
00623     detail::ValueIndex vidx  
00624   );
00625 
00626 
00627 
00628 
00629 
00630   detail::ValueItem* item();
00631 
00632 
00633 
00634 
00635   detail::ValueItem const* item() const;
00636 };
00637 
00638 
00639 namespace detail {
00640   inline bool ValueTable::operator ! () const { return ! _ptr; }
00641   inline ValueTable::operator PseudoBool::Type () const { return _ptr ? PseudoBool::TRUE : PseudoBool::FALSE; }
00642   inline size_t ValueTable::size() const { return _ptr ? _ptr->_values.size() : 0; }
00643   inline Generation ValueTable::generation() const { return _ptr ? _ptr->_generation : Generation(0); }
00644   inline ValueItem const& ValueTable::operator [] (ValueIndex idx) const { return const_cast<self*>(this)->operator [] (idx); }
00645   inline ValueTable& ValueTable::reset() { _ptr = 0; return *this; }
00646 
00647   inline ValueItem::ValueItem() : _type(VoidValue) {}
00648   inline ValueItem::ValueItem(ValueType type) : _type(type) {}
00649   inline ValueType ValueItem::getType() const { return _type; }
00650 }
00651 
00652 inline Value::~Value() { }
00653 inline Value::Value() : _vidx(detail::NULL_VALUE_INDEX) {}
00654 inline Value::Value(Configuration cfg, detail::ValueIndex vidx) : _config(cfg), _vidx(vidx) { }
00655 inline bool Value::hasValue() const { return _config && _vidx != detail::NULL_VALUE_INDEX; }
00656 inline Value::operator detail::PseudoBool::Type () const { return this->hasValue() ? detail::PseudoBool::TRUE : detail::PseudoBool::FALSE; }
00657 inline bool Value::operator ! () const { return ! this->hasValue(); }
00658 inline ValueType Value::getType() const { return this->hasValue() ? _config._table[_vidx]._type : VoidValue; }
00659 inline ConstBuffer const& Value::getText() const {
00660   return this->hasValue() ? _config._table[_vidx]._text : detail::NULL_CONST_BUFFER;
00661 }
00662 inline Value& Value::setText(ConstBuffer const& text) {
00663   detail::ValueItem* item = this->item();
00664   if (item) item->_text = text;
00665   return *this;
00666 }
00667 inline ConstBuffer const& Value::getName() const {
00668   detail::ValueItem const* item = this->item();
00669   return item ? item->_name : detail::NULL_CONST_BUFFER;
00670 }
00671 inline size_t Value::getIndex() const {
00672   detail::ValueItem const* item = this->item();
00673   return item ? item->_local_index : 0;
00674 }
00675   
00676 inline bool Value::isLiteral() const { return 0 != (detail::IS_LITERAL & detail::Type_Property[this->getType()]); }
00677 inline bool Value::isContainer() const { return 0 != (detail::IS_CONTAINER & detail::Type_Property[this->getType()]); }
00678 inline Value Value::getParent() const { return this->hasValue() ? Value(_config, _config._table[_vidx]._parent) : Value(); }
00679 inline bool Value::isRoot() const { return this->hasValue() && _vidx == 0; }
00680 inline Value& Value::reset() { _config = Configuration(); _vidx = detail::NULL_VALUE_INDEX; return *this; }
00681 inline detail::ValueItem* Value::item() { return this->hasValue() ? &(_config._table[_vidx]) : 0; }
00682 inline detail::ValueItem const* Value::item() const { return const_cast<self*>(this)->item(); }
00683 inline Value Value::operator [] (char const* name) const { return (*this)[ConstBuffer(name, strlen(name))]; }
00684 inline size_t Value::childCount() const {
00685   detail::ValueItem const* item = this->item();
00686   return item ? item->_children.size() : 0;
00687 }
00688 inline Value Value::find(char const* path) { return this->find(ConstBuffer(path, strlen(path))); }
00689 inline int Value::getSourceLine() const {
00690   detail::ValueItem const* item = this->item();
00691   return item ? item->_srcLine : 0;
00692 }
00693 inline int Value::getSourceColumn() const {
00694   detail::ValueItem const* item = this->item();
00695   return item ? item->_srcColumn : 0;
00696 }
00697 inline Value& Value::setSourceLine(int line) {
00698   detail::ValueItem* item = this->item();
00699   if (item) item->_srcLine = line;
00700   return *this;
00701 }
00702 inline Value& Value::setSourceColumn(int col) {
00703   detail::ValueItem* item = this->item();
00704   if (item) item->_srcColumn = col;
00705   return *this;
00706 }
00707 inline Value& Value::setSource(int line, int col) {
00708   detail::ValueItem* item = this->item();
00709   if (item) {
00710     item->_srcLine = line;
00711     item->_srcColumn = col;
00712   }
00713   return *this;
00714 }
00715 
00716 inline Path::ImplType::ImplType() { }
00717 
00718 inline Path::Path() { }
00719 inline Path::ImplType* Path::instance() { if (!_ptr) _ptr = new ImplType; return _ptr.get(); }
00720 inline Path& Path::append(ConstBuffer const& tag) { this->instance()->_elements.push_back(tag); return *this; }
00721 inline Path& Path::append(size_t index) { this->instance()->_elements.push_back(ConstBuffer(0, index)); return *this; }
00722 inline size_t Path::count() const { return _ptr ? _ptr->_elements.size() : 0; }
00723 inline ConstBuffer const& Path::operator [] (size_t idx) const { return _ptr ? _ptr->_elements[idx] : detail::NULL_CONST_BUFFER; }
00724 
00725 inline Path::Parser::Parser() { }
00726 inline Path::Parser::Parser( ConstBuffer const& text ) : _input(text), _c(text._ptr) { }
00727 inline bool Path::Parser::hasInput() const { return _input._ptr && _input._ptr + _input._size > _c; }
00728 
00729 inline bool Configuration::operator ! () const { return ! _table; }
00730 inline Configuration::operator detail::PseudoBool::Type() const { return _table.operator detail::PseudoBool::Type(); }
00731 inline Value Configuration::find( char const* path ) { return this->getRoot().find(path); }
00732 inline Buffer Configuration::alloc(size_t n) { return _table.alloc(n);  }
00733 inline size_t Configuration::childCount() const { return this->getRoot().childCount(); }
00734 inline Value Configuration::operator [] (size_t idx) const { return (this->getRoot())[idx]; }
00735 inline Value Configuration::operator [] ( ConstBuffer const& name ) const { return (this->getRoot())[name]; }
00736 inline Value Configuration::operator [] ( char const* name ) const { return (this->getRoot())[name]; }
00737 
00738 }} 
00739 
00740 # endif