RAUL 0.8.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

Atom.hpp

    00001 /* This file is part of Raul.
    00002  * Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
    00003  *
    00004  * Raul is free software; you can redistribute it and/or modify it under the
    00005  * terms of the GNU General Public License as published by the Free Software
    00006  * Foundation; either version 2 of the License, or (at your option) any later
    00007  * version.
    00008  *
    00009  * Raul is distributed in the hope that it will be useful, but WITHOUT ANY
    00010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00011  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
    00012  *
    00013  * You should have received a copy of the GNU General Public License along
    00014  * with this program; if not, write to the Free Software Foundation, Inc.,
    00015  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
    00016  */
    00017
    00018 #ifndef RAUL_ATOM_HPP
    00019 #define RAUL_ATOM_HPP
    00020
    00021 #include <stdint.h>
    00022 #include <glib.h>
    00023
    00024 #include <cassert>
    00025 #include <cstdlib>
    00026 #include <cstring>
    00027 #include <map>
    00028 #include <ostream>
    00029 #include <string>
    00030
    00031 namespace Raul {
    00032
    00033 class URI;
    00034
    00043 class Atom {
    00044 public:
    00045     enum Type {
    00046         NIL,
    00047         INT,
    00048         FLOAT,
    00049         BOOL,
    00050         URI,
    00051         STRING,
    00052         BLOB,
    00053         DICT
    00054     };
    00055
    00056     Atom()                : _type(NIL),    _blob_val(0)             {}
    00057     Atom(int32_t val)     : _type(INT),    _int_val(val)            {}
    00058     Atom(float val)       : _type(FLOAT),  _float_val(val)          {}
    00059     Atom(bool val)        : _type(BOOL),   _bool_val(val)           {}
    00060     Atom(const char* val) : _type(STRING), _string_val(strdup(val)) {}
    00061
    00062     Atom(const std::string& val) : _type(STRING), _string_val(strdup(val.c_str())) {}
    00063
    00065     Atom(Type t, const std::string& val) : _type(t), _string_val(g_intern_string(val.c_str())) {
    00066         assert(t == URI);
    00067     }
    00068
    00069     Atom(const char* type_uri, size_t size, void* val)
    00070         : _type(BLOB), _blob_val(new BlobValue(type_uri, size, val)) {}
    00071
    00072     typedef std::map<Raul::Atom, Raul::Atom> DictValue;
    00073     Atom(const DictValue& dict) : _type(DICT), _dict_val(new DictValue(dict)) {}
    00074
    00075     ~Atom() { dealloc(); }
    00076
    00077     Atom(const Atom& copy)
    00078         : _type(copy._type)
    00079     {
    00080         switch (_type) {
    00081         case NIL:    _blob_val   = 0;                              break;
    00082         case INT:    _int_val    = copy._int_val;                  break;
    00083         case FLOAT:  _float_val  = copy._float_val;                break;
    00084         case BOOL:   _bool_val   = copy._bool_val;                 break;
    00085         case URI:    _string_val = copy._string_val;               break;
    00086         case STRING: _string_val = strdup(copy._string_val);       break;
    00087         case BLOB:   _blob_val   = new BlobValue(*copy._blob_val); break;
    00088         case DICT:   _dict_val   = new DictValue(*copy._dict_val); break;
    00089         }
    00090     }
    00091
    00092     Atom& operator=(const Atom& other) {
    00093         dealloc();
    00094         _type = other._type;
    00095
    00096         switch (_type) {
    00097         case NIL:    _blob_val   = 0;                               break;
    00098         case INT:    _int_val    = other._int_val;                  break;
    00099         case FLOAT:  _float_val  = other._float_val;                break;
    00100         case BOOL:   _bool_val   = other._bool_val;                 break;
    00101         case URI:    _string_val = other._string_val;               break;
    00102         case STRING: _string_val = strdup(other._string_val);       break;
    00103         case BLOB:   _blob_val   = new BlobValue(*other._blob_val); break;
    00104         case DICT:   _dict_val   = new DictValue(*other._dict_val); break;
    00105         }
    00106         return *this;
    00107     }
    00108
    00109     inline bool operator==(const Atom& other) const {
    00110         if (_type == other.type()) {
    00111             switch (_type) {
    00112             case NIL:    return true;
    00113             case INT:    return _int_val    == other._int_val;
    00114             case FLOAT:  return _float_val  == other._float_val;
    00115             case BOOL:   return _bool_val   == other._bool_val;
    00116             case URI:    return _string_val == other._string_val;
    00117             case STRING: return strcmp(_string_val, other._string_val) == 0;
    00118             case BLOB:   return _blob_val == other._blob_val;
    00119             case DICT:   return *_dict_val == *other._dict_val;
    00120             }
    00121         }
    00122         return false;
    00123     }
    00124
    00125     inline bool operator!=(const Atom& other) const { return ! operator==(other); }
    00126
    00127     inline bool operator<(const Atom& other) const {
    00128         if (_type == other.type()) {
    00129             switch (_type) {
    00130             case NIL:    return true;
    00131             case INT:    return _int_val    < other._int_val;
    00132             case FLOAT:  return _float_val  < other._float_val;
    00133             case BOOL:   return _bool_val   < other._bool_val;
    00134             case URI:
    00135                 if (_string_val == other._string_val) {
    00136                     return false;
    00137                 } // else fall through to STRING
    00138             case STRING: return strcmp(_string_val, other._string_val) < 0;
    00139             case BLOB:   return _blob_val   < other._blob_val;
    00140             case DICT:   return *_dict_val  < *other._dict_val;
    00141             }
    00142         }
    00143         return _type < other.type();
    00144     }
    00145
    00146     inline size_t data_size() const {
    00147         switch (_type) {
    00148         case NIL:    return 0;
    00149         case INT:    return sizeof(uint32_t);
    00150         case FLOAT:  return sizeof(float);
    00151         case BOOL:   return sizeof(bool);
    00152         case URI:
    00153         case STRING: return strlen(_string_val) + 1;
    00154         case BLOB:   return _blob_val->size();
    00155         case DICT:   return 0; // FIXME ?
    00156         }
    00157         return 0;
    00158     }
    00159
    00160     inline bool is_valid() const { return (_type != NIL); }
    00161
    00165     Type type() const { return _type; }
    00166
    00167     inline int32_t     get_int32()  const { assert(_type == INT);    return _int_val; }
    00168     inline float       get_float()  const { assert(_type == FLOAT);  return _float_val; }
    00169     inline bool        get_bool()   const { assert(_type == BOOL);   return _bool_val; }
    00170     inline const char* get_string() const { assert(_type == STRING); return _string_val; }
    00171     inline const char* get_uri()    const { assert(_type == URI);    return _string_val; }
    00172
    00173     inline const char* get_blob_type() const { assert(_type == BLOB); return _blob_val->type(); }
    00174     inline const void* get_blob()      const { assert(_type == BLOB); return _blob_val->data(); }
    00175
    00176     inline const DictValue& get_dict() const { assert(_type == DICT); return *_dict_val; }
    00177
    00178 private:
    00179     Type _type;
    00180
    00181     friend class Raul::URI;
    00182     Atom(const char* str, uint32_t magic) : _type(URI), _string_val(str) {
    00183         assert(magic == 12345);
    00184         assert(g_intern_string(str) == str);
    00185     }
    00186
    00187     inline void dealloc() {
    00188         switch (_type) {
    00189         case STRING:
    00190             free(const_cast<char*>(_string_val));
    00191             break;
    00192         case BLOB:
    00193             delete _blob_val;
    00194         default:
    00195             break;
    00196         }
    00197     }
    00198
    00199     class BlobValue {
    00200     public:
    00201         BlobValue(const char* type, size_t size, void* data)
    00202             : _type_length(strlen(type) + 1) // + 1 for \0
    00203             , _size(size)
    00204             , _buf(malloc(_type_length + _size))
    00205         {
    00206             memcpy(_buf, type, _type_length);
    00207             memcpy(static_cast<char*>(_buf) + _type_length, data, size);
    00208         }
    00209
    00210         BlobValue(const BlobValue& copy)
    00211             : _type_length(copy._type_length)
    00212             , _size(copy._size)
    00213             , _buf(malloc(_type_length + _size))
    00214         {
    00215             _type_length = copy._type_length;
    00216             memcpy(_buf, copy._buf, _type_length + _size);
    00217         }
    00218
    00219         ~BlobValue() { free(_buf); }
    00220
    00221         inline const char* type() const { return static_cast<const char*>(_buf); }
    00222         inline const void* data() const { return static_cast<const char*>(_buf) + _type_length; }
    00223         inline size_t      size() const { return _size; }
    00224     private:
    00225         size_t _type_length;
    00226         size_t _size;
    00227         void*  _buf;
    00228     };
    00229
    00230     union {
    00231         int32_t          _int_val;
    00232         float            _float_val;
    00233         bool             _bool_val;
    00234         const char*      _string_val;
    00235         BlobValue*       _blob_val;
    00236         const DictValue* _dict_val;
    00237     };
    00238 };
    00239
    00240
    00241 } // namespace Raul
    00242
    00243 static inline std::ostream& operator<<(std::ostream& os, const Raul::Atom& atom)
    00244 {
    00245     switch (atom.type()) {
    00246     case Raul::Atom::NIL:    return os << "(nil)";
    00247     case Raul::Atom::INT:    return os << atom.get_int32();
    00248     case Raul::Atom::FLOAT:  return os << atom.get_float();
    00249     case Raul::Atom::BOOL:   return os << (atom.get_bool() ? "true" : "false");
    00250     case Raul::Atom::URI:    return os << "<" << atom.get_uri() << ">";
    00251     case Raul::Atom::STRING: return os << atom.get_string();
    00252     case Raul::Atom::BLOB:   return os << atom.get_blob();
    00253     case Raul::Atom::DICT:
    00254         os << "{";
    00255         for (Raul::Atom::DictValue::const_iterator i = atom.get_dict().begin();
    00256                 i != atom.get_dict().end(); ++i) {
    00257             os << " " << i->first << " " << i->second << ";";
    00258         }
    00259         os << " }";
    00260         return os;
    00261     }
    00262     return os;
    00263 }
    00264
    00265 static inline std::ostream& operator<<(std::ostream& os, Raul::Atom::Type type)
    00266 {
    00267     switch (type) {
    00268     case Raul::Atom::NIL:    return os << "Nil";
    00269     case Raul::Atom::INT:    return os << "Int";
    00270     case Raul::Atom::FLOAT:  return os << "Float";
    00271     case Raul::Atom::BOOL:   return os << "Bool";
    00272     case Raul::Atom::URI:    return os << "URI";
    00273     case Raul::Atom::STRING: return os << "String";
    00274     case Raul::Atom::BLOB:   return os << "Blob";
    00275     case Raul::Atom::DICT:   return os << "Dict";
    00276     }
    00277     return os;
    00278 }
    00279
    00280 #endif // RAUL_ATOM_HPP