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