From 8350acca946fc925d359f2d7c8f342cef8f5b71b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 19 Mar 2012 23:34:37 +0000 Subject: Use dynamic type IDs for Atoms (for direct compatibility with LV2 atoms). git-svn-id: http://svn.drobilla.net/lad/trunk/raul@4079 a436a847-0d15-0410-975c-d299462d15a1 --- raul/Atom.hpp | 307 ++++++++++++++++++------------------------------- raul/AtomRDF.hpp | 143 ----------------------- raul/Configuration.hpp | 112 +++++++++++++++--- raul/URI.hpp | 3 - 4 files changed, 209 insertions(+), 356 deletions(-) delete mode 100644 raul/AtomRDF.hpp (limited to 'raul') diff --git a/raul/Atom.hpp b/raul/Atom.hpp index b464a87..a10b79b 100644 --- a/raul/Atom.hpp +++ b/raul/Atom.hpp @@ -24,83 +24,60 @@ #include #include #include +#include #include -#include #include namespace Raul { -class URI; class Forge; /** A piece of data with some type. * - * Atoms can be of various primitive types (integer, float, etc) as well as - * a string or primitive. The primitive types are entirely contained within - * the Atom, i.e. the Atom is POD. String, URI, and blob atoms are not POD. + * An Atom is either a primitive type (int, float, etc.) or a blob. Primitives + * are contained entirely within this struct so everything is realtime safe. + * Blob creation/copying/destruction allocates and is not realtime safe. * * \ingroup raul */ class Atom { public: - Atom() : _type(NIL), _blob_val(0) {} - - enum Type { - NIL, - INT, - FLOAT, - BOOL, - URI, - STRING, - BLOB, - DICT - }; - + Atom() : _size(0), _type(0) { _val._blob = NULL; } ~Atom() { dealloc(); } + typedef uint32_t TypeID; + Atom(const Atom& copy) - : _type(copy._type) + : _size(copy._size) + , _type(copy._type) { - switch (_type) { - case NIL: _blob_val = 0; break; - case INT: _int_val = copy._int_val; break; - case FLOAT: _float_val = copy._float_val; break; - case BOOL: _bool_val = copy._bool_val; break; - case URI: _string_val = copy._string_val; break; - case STRING: _string_val = g_strdup(copy._string_val); break; - case BLOB: _blob_val = new BlobValue(*copy._blob_val); break; - case DICT: _dict_val = new DictValue(*copy._dict_val); break; + if (is_reference()) { + _val._blob = malloc(_size); + memcpy(_val._blob, copy._val._blob, _size); + } else { + memcpy(&_val, ©._val, _size); } } Atom& operator=(const Atom& other) { dealloc(); + _size = other._size; _type = other._type; - - switch (_type) { - case NIL: _blob_val = 0; break; - case INT: _int_val = other._int_val; break; - case FLOAT: _float_val = other._float_val; break; - case BOOL: _bool_val = other._bool_val; break; - case URI: _string_val = other._string_val; break; - case STRING: _string_val = g_strdup(other._string_val); break; - case BLOB: _blob_val = new BlobValue(*other._blob_val); break; - case DICT: _dict_val = new DictValue(*other._dict_val); break; + if (is_reference()) { + _val._blob = malloc(_size); + memcpy(_val._blob, other._val._blob, _size); + } else { + memcpy(&_val, &other._val, _size); } return *this; } inline bool operator==(const Atom& other) const { if (_type == other.type()) { - switch (_type) { - case NIL: return true; - case INT: return _int_val == other._int_val; - case FLOAT: return _float_val == other._float_val; - case BOOL: return _bool_val == other._bool_val; - case URI: return _string_val == other._string_val; - case STRING: return strcmp(_string_val, other._string_val) == 0; - case BLOB: return _blob_val == other._blob_val; - case DICT: return *_dict_val == *other._dict_val; + if (is_reference()) { + return !memcmp(_val._blob, other._val._blob, _size); + } else { + return !memcmp(&_val, &other._val, _size); } } return false; @@ -110,186 +87,124 @@ public: inline bool operator<(const Atom& other) const { if (_type == other.type()) { - switch (_type) { - case NIL: return true; - case INT: return _int_val < other._int_val; - case FLOAT: return _float_val < other._float_val; - case BOOL: return _bool_val < other._bool_val; - case URI: - if (_string_val == other._string_val) { - return false; - } // else fall through to STRING - case STRING: return strcmp(_string_val, other._string_val) < 0; - case BLOB: return _blob_val < other._blob_val; - case DICT: return *_dict_val < *other._dict_val; + if (is_reference()) { + return memcmp(_val._blob, other._val._blob, _size) < 0; + } else { + return memcmp(&_val, &other._val, _size) < 0; } } return _type < other.type(); } - inline size_t data_size() const { - switch (_type) { - case NIL: return 0; - case INT: return sizeof(uint32_t); - case FLOAT: return sizeof(float); - case BOOL: return sizeof(bool); - case URI: - case STRING: return strlen(_string_val) + 1; - case BLOB: return _blob_val->size(); - case DICT: return 0; // FIXME ? - } - return 0; - } + inline uint32_t size() const { return _size; } + inline bool is_valid() const { return _type; } + inline TypeID type() const { return _type; } - inline bool is_valid() const { return (_type != NIL); } - - /** Type of this atom. Always check this before attempting to get the - * value - attempting to get the incorrectly typed value is a fatal error. - */ - Type type() const { return _type; } - - inline int32_t get_int32() const { assert(_type == INT); return _int_val; } - inline float get_float() const { assert(_type == FLOAT); return _float_val; } - inline bool get_bool() const { assert(_type == BOOL); return _bool_val; } - inline const char* get_string() const { assert(_type == STRING); return _string_val; } - inline const char* get_uri() const { assert(_type == URI); return _string_val; } + inline const void* get_body() const { + return is_reference() ? _val._blob : &_val; + } - inline const char* get_blob_type() const { assert(_type == BLOB); return _blob_val->type(); } - inline const void* get_blob() const { assert(_type == BLOB); return _blob_val->data(); } + inline int32_t get_int32() const { return _val._int; } + inline float get_float() const { return _val._float; } + inline bool get_bool() const { return _val._bool; } + inline const char* get_uri() const { return (const char*)get_body(); } + inline const char* get_string() const { return (const char*)get_body(); } typedef std::map DictValue; - inline const DictValue& get_dict() const { assert(_type == DICT); return *_dict_val; } + inline const DictValue& get_dict() const { return *(DictValue*)_val._blob; } private: friend class Forge; - Atom(int32_t val) : _type(INT), _int_val(val) {} - Atom(float val) : _type(FLOAT), _float_val(val) {} - Atom(bool val) : _type(BOOL), _bool_val(val) {} - Atom(const char* val) : _type(STRING), _string_val(g_strdup(val)) {} - Atom(const std::string& val) : _type(STRING), _string_val(g_strdup(val.c_str())) {} + Atom(uint32_t s, TypeID t, const void* v) + : _size(s) + , _type(t) + { + if (is_reference()) { + _val._blob = malloc(s); + memcpy(_val._blob, v, s); + } else { + memcpy(&_val, v, s); + } + } - /** URI constructor (@a t must be URI) */ - Atom(Type t, const std::string& val) : _type(t), _string_val(g_intern_string(val.c_str())) { - assert(t == URI); + inline void dealloc() { + if (is_reference()) { + free(_val._blob); + } } - Atom(const char* type_uri, size_t size, void* val) - : _type(BLOB), _blob_val(new BlobValue(type_uri, size, val)) {} + inline bool is_reference() const { + return _size > sizeof(_val); + } - Atom(const DictValue& dict) : _type(DICT), _dict_val(new DictValue(dict)) {} + uint32_t _size; + TypeID _type; - Type _type; + union { + int32_t _int; + float _float; + int32_t _bool; + void* _blob; + } _val; +}; - friend class Raul::URI; - Atom(const char* str, uint32_t magic) : _type(URI), _string_val(str) { - assert(magic == 12345); - assert(g_intern_string(str) == str); +class Forge { +public: + Forge() + : Int(1) + , Float(2) + , Bool(3) + , URI(4) + , String(5) + , Dict(6) + {} + + Atom make() { return Atom(); } + Atom make(int32_t v) { return Atom(sizeof(int32_t), Int, &v); } + Atom make(float v) { return Atom(sizeof(float), Float, &v); } + + Atom alloc(uint32_t size, uint32_t type, const void* val) { + return Atom(size, type, val); } - inline void dealloc() { - switch (_type) { - case STRING: - g_free(const_cast(_string_val)); - break; - case BLOB: - delete _blob_val; - default: - break; - } + Atom make_bool(bool v) { + const int32_t iv = v ? 1 : 0; + return Atom(sizeof(int32_t), Bool, &iv); } - class BlobValue { - public: - BlobValue(const char* type, size_t size, void* data) - : _type_length(strlen(type) + 1) // + 1 for \0 - , _size(size) - , _buf(malloc(_type_length + _size)) - { - memcpy(_buf, type, _type_length); - memcpy(static_cast(_buf) + _type_length, data, size); - } + Atom alloc(const char* v) { + const size_t len = strlen(v); + return Atom(len + 1, String, v); + } - BlobValue(const BlobValue& copy) - : _type_length(copy._type_length) - , _size(copy._size) - , _buf(malloc(_type_length + _size)) - { - _type_length = copy._type_length; - memcpy(_buf, copy._buf, _type_length + _size); - } + Atom alloc(const std::string& v) { + return Atom(v.length() + 1, String, v.c_str()); + } - ~BlobValue() { free(_buf); } + Atom alloc(const Atom::DictValue& v) { + std::cerr << "FIXME: Atom dict" << std::endl; + return Atom(); + } - inline const char* type() const { return static_cast(_buf); } - inline const void* data() const { return static_cast(_buf) + _type_length; } - inline size_t size() const { return _size; } - private: - size_t _type_length; ///< Length of type string (first part of buffer, inc. \0) - size_t _size; ///< Length of data not including (after) type string - void* _buf; ///< Type string followed by data - }; + Atom alloc_uri(const char* v) { + const size_t len = strlen(v); + return Atom(len + 1, URI, v); + } - union { - int32_t _int_val; - float _float_val; - bool _bool_val; - const char* _string_val; - BlobValue* _blob_val; - const DictValue* _dict_val; - }; -}; + Atom alloc_uri(const std::string& v) { + return Atom(v.length() + 1, URI, v.c_str()); + } -class Forge { -public: - Atom make() { return Atom(); } - Atom make(int32_t v) { return Atom(v); } - Atom make(float v) { return Atom(v); } - Atom make(bool v) { return Atom(v); } - Atom make(const char* v) { return Atom(v); } - Atom alloc(const std::string& v) { return Atom(v); } - Atom alloc(const Atom::DictValue& v) { return Atom(v); } - Atom alloc(Atom::Type t, const std::string& v) { return Atom(t, v); } + Atom::TypeID Int; + Atom::TypeID Float; + Atom::TypeID Bool; + Atom::TypeID URI; + Atom::TypeID String; + Atom::TypeID Dict; }; } // namespace Raul -static inline std::ostream& operator<<(std::ostream& os, const Raul::Atom& atom) -{ - switch (atom.type()) { - case Raul::Atom::NIL: return os << "(nil)"; - case Raul::Atom::INT: return os << atom.get_int32(); - case Raul::Atom::FLOAT: return os << atom.get_float(); - case Raul::Atom::BOOL: return os << (atom.get_bool() ? "true" : "false"); - case Raul::Atom::URI: return os << "<" << atom.get_uri() << ">"; - case Raul::Atom::STRING: return os << atom.get_string(); - case Raul::Atom::BLOB: return os << atom.get_blob(); - case Raul::Atom::DICT: - os << "{"; - for (Raul::Atom::DictValue::const_iterator i = atom.get_dict().begin(); - i != atom.get_dict().end(); ++i) { - os << " " << i->first << " " << i->second << ";"; - } - os << " }"; - return os; - } - return os; -} - -static inline std::ostream& operator<<(std::ostream& os, Raul::Atom::Type type) -{ - switch (type) { - case Raul::Atom::NIL: return os << "Nil"; - case Raul::Atom::INT: return os << "Int"; - case Raul::Atom::FLOAT: return os << "Float"; - case Raul::Atom::BOOL: return os << "Bool"; - case Raul::Atom::URI: return os << "URI"; - case Raul::Atom::STRING: return os << "String"; - case Raul::Atom::BLOB: return os << "Blob"; - case Raul::Atom::DICT: return os << "Dict"; - } - return os; -} - #endif // RAUL_ATOM_HPP diff --git a/raul/AtomRDF.hpp b/raul/AtomRDF.hpp deleted file mode 100644 index 00a9332..0000000 --- a/raul/AtomRDF.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* This file is part of Raul. - * Copyright 2007-2011 David Robillard - * - * Raul is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Raul is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef RAUL_ATOM_RDF_HPP -#define RAUL_ATOM_RDF_HPP - -#include -#include -#include -#include - -#include "raul/Atom.hpp" -#include "raul/log.hpp" - -#include "sord/sordmm.hpp" - -#define CUC(x) ((const unsigned char*)(x)) - -namespace Raul { - -/** Conversion between Raul Atoms and Sord RDF nodes. - * This code (in header raul/AtomRDF.hpp) depends on sord, only apps - * which directly depend on both raul and sord should include it. - */ -namespace AtomRDF { - -/** Convert a Sord::Node to a Raul::Atom */ -inline Atom -node_to_atom(Forge& forge, Sord::Model& model, const Sord::Node& node) -{ - if (node.is_bool()) { - return forge.make(bool(node.to_bool())); - } else if (node.is_uri()) { - return forge.alloc(Atom::URI, node.to_c_string()); - } else if (node.is_float()) { - return forge.make(node.to_float()); - } else if (node.is_int()) { - return forge.make(node.to_int()); - } else if (node.is_blank()) { - Atom::DictValue dict; - Sord::Node nil; - for (Sord::Iter i = model.find(node, nil, nil); !i.end(); ++i) { - Sord::Node predicate = i.get_predicate(); - Sord::Node object = i.get_object(); - dict.insert(std::make_pair(node_to_atom(forge, model, predicate), - node_to_atom(forge, model, object))); - } - return forge.alloc(dict); - } else { - return forge.alloc(node.to_c_string()); - } -} - -#define RAUL_NS_XSD "http://www.w3.org/2001/XMLSchema#" - -/** Convert a Raul::Atom to a Sord::Node - * Note that not all Atoms are serialisable, the returned node should - * be checked (can be treated as a bool) before use. */ -inline Sord::Node -atom_to_node(Sord::Model& model, const Atom& atom) -{ - Sord::World& world = model.world(); - - std::string str; - SordNode* type = NULL; - SordNode* node = NULL; - SerdNode snode; - - switch (atom.type()) { - case Atom::INT: - snode = serd_node_new_integer(atom.get_int32()); - str = (const char*)snode.buf; - serd_node_free(&snode); - // xsd:integer -> pretty integer literals in Turtle - type = sord_new_uri(world.world(), CUC(RAUL_NS_XSD "integer")); - break; - case Atom::FLOAT: - if (std::isnan(atom.get_float()) || std::isinf(atom.get_float())) - break; - snode = serd_node_new_decimal(atom.get_float(), 8); - str = (const char*)snode.buf; - serd_node_free(&snode); - // xsd:decimal -> pretty decimal (float) literals in Turtle - type = sord_new_uri(world.world(), CUC(RAUL_NS_XSD "decimal")); - break; - case Atom::BOOL: - // xsd:boolean -> pretty boolean literals in Turtle - if (atom.get_bool()) - str = "true"; - else - str = "false"; - type = sord_new_uri(world.world(), CUC(RAUL_NS_XSD "boolean")); - break; - case Atom::URI: - str = atom.get_uri(); - node = sord_new_uri(world.world(), CUC(str.c_str())); - break; - case Atom::STRING: - str = atom.get_string(); - break; - case Atom::DICT: { - Sord::Node blank = Sord::Node::blank_id(model.world()); - for (Atom::DictValue::const_iterator i = atom.get_dict().begin(); - i != atom.get_dict().end(); ++i) { - model.add_statement(blank, - atom_to_node(model, i->first), - atom_to_node(model, i->second)); - } - node = blank.c_obj(); - break; - } - case Atom::BLOB: - case Atom::NIL: - default: - warn << "Unserializable Atom" << std::endl; - break; - } - - if (!node && str != "") - node = sord_new_literal(world.world(), type, CUC(str.c_str()), NULL); - - return Sord::Node(world, node); -} - -} // namespace AtomRDF -} // namespace Raul - -#endif // RAUL_ATOM_RDF_HPP - diff --git a/raul/Configuration.hpp b/raul/Configuration.hpp index 9efca42..7983850 100644 --- a/raul/Configuration.hpp +++ b/raul/Configuration.hpp @@ -18,14 +18,17 @@ #ifndef RAUL_CONFIGURATION_HPP #define RAUL_CONFIGURATION_HPP +#include +#include +#include +#include + #include #include #include #include #include -#include "raul/Atom.hpp" - namespace Raul { /** Program configuration (command line options and/or configuration file). @@ -34,20 +37,90 @@ namespace Raul { */ class Configuration { public: - Configuration(Forge* forge, - const std::string& shortdesc, + Configuration(const std::string& shortdesc, const std::string& desc) - : _forge(forge) - , _shortdesc(shortdesc) + : _shortdesc(shortdesc) , _desc(desc) , _max_name_length(0) {} + enum OptionType { + NOTHING, + BOOL, + INT, + STRING + }; + + class Value { + public: + Value() : _type(NOTHING) { _val._string = NULL; } + Value(bool v) : _type(BOOL) { _val._bool = v; } + Value(int v) : _type(INT) { _val._int = v; } + + Value(const char* v) : _type(STRING) { + const size_t len = strlen(v); + _val._string = (char*)calloc(len + 1, 1); + memcpy(_val._string, v, len + 1); + } + + Value(const std::string& v) : _type(STRING) { + _val._string = (char*)calloc(v.length() + 1, 1); + memcpy(_val._string, v.c_str(), v.length() + 1); + } + + Value(const Value& copy) + : _type(copy._type) + , _val(copy._val) + { + if (_type == STRING) { + const size_t len = strlen(copy.get_string()); + _val._string = (char*)malloc(len + 1); + memcpy(_val._string, copy.get_string(), len + 1); + } + } + + Value& operator=(const Value& other) + { + if (_type == STRING) { + free(_val._string); + } + _type = other._type; + _val = other._val; + if (_type == STRING) { + const size_t len = strlen(other.get_string()); + _val._string = (char*)malloc(len + 1); + memcpy(_val._string, other.get_string(), len + 1); + } + return *this; + } + + ~Value() { + if (_type == STRING) { + free(_val._string); + } + } + + inline OptionType type() const { return _type; } + inline bool is_valid() const { return _type != NOTHING; } + + inline int32_t get_int() const { assert(_type == INT); return _val._int; } + inline bool get_bool() const { assert(_type == BOOL); return _val._bool; } + inline const char* get_string() const { assert(_type == STRING); return _val._string; } + + private: + OptionType _type; + union { + bool _bool; + int32_t _int; + char* _string; + } _val; + }; + Configuration& add(const std::string& name, char letter, const std::string& desc, - const Atom::Type type, - const Atom& value); + OptionType type, + const Value& value); void print_usage(const std::string& program, std::ostream& os); @@ -62,23 +135,23 @@ public: void print(std::ostream& os, const std::string mime_type="text/plain") const; - const Raul::Atom& option(const std::string& long_name); + const Value& option(const std::string& long_name); const std::list& files() const { return _files; } private: struct Option { public: Option(const std::string& n, char l, const std::string& d, - const Atom::Type type, const Raul::Atom& def) + const OptionType type, const Value& def) : name(n), letter(l), desc(d), type(type), default_value(def), value(def) {} std::string name; char letter; std::string desc; - Atom::Type type; - Raul::Atom default_value; - Raul::Atom value; + OptionType type; + Value default_value; + Value value; }; struct OptionNameOrder { @@ -94,7 +167,6 @@ private: int set_value_from_string(Configuration::Option& option, const std::string& value) throw (Configuration::CommandLineError); - Forge* _forge; const std::string _shortdesc; const std::string _desc; Options _options; @@ -105,5 +177,17 @@ private: } // namespace Raul +static inline std::ostream& +operator<<(std::ostream& os, const Raul::Configuration::Value& value) +{ + switch (value.type()) { + case Raul::Configuration::NOTHING: return os << "(nil)"; + case Raul::Configuration::INT: return os << value.get_int(); + case Raul::Configuration::BOOL: return os << (value.get_bool() ? "true" : "false"); + case Raul::Configuration::STRING: return os << value.get_string(); + } + return os; +} + #endif // RAUL_CONFIGURATION_HPP diff --git a/raul/URI.hpp b/raul/URI.hpp index 569be41..90d285c 100644 --- a/raul/URI.hpp +++ b/raul/URI.hpp @@ -23,7 +23,6 @@ #include #include #include -#include "raul/Atom.hpp" namespace Raul { @@ -95,8 +94,6 @@ public: inline size_t find(const std::string& s) const { return str().find(s); } inline size_t find_last_of(char c) const { return str().find_last_of(c); } - inline operator Raul::Atom() const { return Raul::Atom(_str, 12345); } - private: const char* _str; }; -- cgit v1.2.1