diff options
Diffstat (limited to 'src/value.h')
-rw-r--r-- | src/value.h | 134 |
1 files changed, 93 insertions, 41 deletions
diff --git a/src/value.h b/src/value.h index 2371b74e..c9281121 100644 --- a/src/value.h +++ b/src/value.h @@ -61,6 +61,10 @@ class value_t public: typedef std::vector<value_t> sequence_t; + typedef sequence_t::iterator iterator; + typedef sequence_t::const_iterator const_iterator; + typedef sequence_t::difference_type difference_type; + enum type_t { VOID, BOOLEAN, @@ -72,7 +76,6 @@ public: STRING, SEQUENCE, XML_NODE, - CONST_XML_NODE, POINTER }; @@ -217,12 +220,9 @@ public: TRACE_CTOR(value_t, "xml::node_t *"); set_xml_node(xml_node); } - value_t(const xml::node_t * xml_node) { - TRACE_CTOR(value_t, "const xml::node_t *"); - set_xml_node(xml_node); - } - value_t(void * item) { - TRACE_CTOR(value_t, "void *"); + template <typename T> + value_t(T * item) { + TRACE_CTOR(value_t, "T *"); set_pointer(item); } ~value_t() { @@ -254,11 +254,22 @@ public: else storage->destroy(); } + void _reset() { + if (storage) { + storage->destroy(); + storage = intrusive_ptr<storage_t>(); + } + } operator bool() const; bool is_null() const { - return ! storage || is_type(VOID); + if (! storage) { + return true; + } else { + assert(! is_type(VOID)); + return false; + } } type_t type() const { type_t result = storage ? storage->type : VOID; @@ -272,9 +283,14 @@ private: } void set_type(type_t new_type) { assert(new_type >= VOID && new_type <= POINTER); - _clear(); - storage->type = new_type; - assert(is_type(new_type)); + if (new_type == VOID) { + _reset(); + assert(is_null()); + } else { + _clear(); + storage->type = new_type; + assert(is_type(new_type)); + } } public: @@ -415,36 +431,21 @@ public: } bool is_xml_node() const { - return is_type(XML_NODE) || is_type(CONST_XML_NODE); + return is_type(XML_NODE); } xml::node_t *& as_xml_node_lval() { assert(is_xml_node()); - assert(! is_type(CONST_XML_NODE)); _dup(); return *(xml::node_t **) storage->data; } - xml::node_t * as_xml_node_mutable() { + xml::node_t * as_xml_node() const { assert(is_xml_node()); - assert(! is_type(CONST_XML_NODE)); return *(xml::node_t **) storage->data; } - const xml::node_t * as_xml_node() const { - assert(is_xml_node()); - return *(const xml::node_t **) storage->data; - } - template <typename T> - T * as_xml_node() const { - assert(is_xml_node()); - return *(T **) storage->data; - } void set_xml_node(xml::node_t * val) { set_type(XML_NODE); *(xml::node_t **) storage->data = val; } - void set_xml_node(const xml::node_t * val) { - set_type(CONST_XML_NODE); - *(const xml::node_t **) storage->data = val; - } bool is_pointer() const { return is_type(POINTER); @@ -460,6 +461,12 @@ public: _dup(); return any_cast<T *>(*(boost::any *) storage->data); } + template <typename T> + T& as_ref_lval() { + assert(is_pointer()); + _dup(); + return *any_cast<T *>(*(boost::any *) storage->data); + } boost::any as_any_pointer() const { assert(is_pointer()); return *(boost::any *) storage->data; @@ -469,6 +476,11 @@ public: assert(is_pointer()); return any_cast<T *>(*(boost::any *) storage->data); } + template <typename T> + T& as_ref() const { + assert(is_pointer()); + return *any_cast<T *>(*(boost::any *) storage->data); + } void set_any_pointer(const boost::any& val) { set_type(POINTER); new((boost::any *) storage->data) boost::any(val); @@ -496,18 +508,66 @@ public: void in_place_simplify(); value_t& operator[](const int index) { - return as_sequence_lval()[index]; + assert(! is_null()); + if (is_sequence()) + return as_sequence_lval()[index]; + else if (index == 0) + return *this; + + assert(false); + static value_t null; + return null; } const value_t& operator[](const int index) const { - return as_sequence()[index]; + assert(! is_null()); + if (is_sequence()) + return as_sequence()[index]; + else if (index == 0) + return *this; + + assert(false); + static value_t null; + return null; } void push_back(const value_t& val) { - return as_sequence_lval().push_back(val); + if (is_null()) { + *this = val; + } else { + if (! is_sequence()) + in_place_cast(SEQUENCE); + + if (! val.is_sequence()) + as_sequence_lval().push_back(val); + else + std::copy(val.as_sequence().begin(), val.as_sequence().end(), + as_sequence_lval().end()); + } + } + + void pop_back() { + assert(! is_null()); + + if (! is_sequence()) { + _reset(); + } else { + as_sequence_lval().pop_back(); + + std::size_t new_size = as_sequence().size(); + if (new_size == 0) + _reset(); + else if (new_size == 1) + *this = as_sequence().front(); + } } const std::size_t size() const { - return as_sequence().size(); + if (is_null()) + return 0; + else if (is_sequence()) + return as_sequence().size(); + else + return 1; } value_t& operator+=(const value_t& val); @@ -542,7 +602,6 @@ public: case SEQUENCE: return "a sequence"; case XML_NODE: - case CONST_XML_NODE: return "an xml node"; case POINTER: return "a pointer"; @@ -602,19 +661,12 @@ public: friend std::ostream& operator<<(std::ostream& out, const value_t& val); }; -template <> -inline const xml::node_t * value_t::as_xml_node() const { - assert(is_xml_node()); - assert(! is_type(CONST_XML_NODE)); - return *(const xml::node_t **) storage->data; -} +#define NULL_VALUE (value_t()) std::ostream& operator<<(std::ostream& out, const value_t& val); DECLARE_EXCEPTION(value_error); -#define NULL_VALUE (value_t()) - } // namespace ledger #endif // _VALUE_H |