summaryrefslogtreecommitdiffstats
path: root/raul
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-03-19 23:34:37 +0000
committerDavid Robillard <d@drobilla.net>2012-03-19 23:34:37 +0000
commit8350acca946fc925d359f2d7c8f342cef8f5b71b (patch)
tree539ca5696e7d8ef510228cb5099b90bb99b450d3 /raul
parent4b50b01f998e575e3c219146c969332a1b0163db (diff)
downloadraul-8350acca946fc925d359f2d7c8f342cef8f5b71b.tar.gz
raul-8350acca946fc925d359f2d7c8f342cef8f5b71b.tar.bz2
raul-8350acca946fc925d359f2d7c8f342cef8f5b71b.zip
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
Diffstat (limited to 'raul')
-rw-r--r--raul/Atom.hpp307
-rw-r--r--raul/AtomRDF.hpp143
-rw-r--r--raul/Configuration.hpp112
-rw-r--r--raul/URI.hpp3
4 files changed, 209 insertions, 356 deletions
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 <cassert>
#include <cstdlib>
#include <cstring>
+#include <iostream>
#include <map>
-#include <ostream>
#include <string>
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, &copy._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<Raul::Atom, Raul::Atom> 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<char*>(_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<char*>(_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<const char*>(_buf); }
- inline const void* data() const { return static_cast<const char*>(_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 <http://drobilla.net>
- *
- * 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 <cmath>
-#include <cstring>
-#include <string>
-#include <utility>
-
-#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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
#include <exception>
#include <list>
#include <map>
#include <ostream>
#include <string>
-#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<std::string>& 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 <exception>
#include <ostream>
#include <glib.h>
-#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;
};