00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef RAUL_ATOM_HPP
00019 #define RAUL_ATOM_HPP
00020
00021 #include <stdint.h>
00022 #include <cstdlib>
00023 #include <cassert>
00024 #include <cstring>
00025 #include <string>
00026 #include <sstream>
00027 #include <iostream>
00028
00029 #define CUC(x) ((const unsigned char*)(x))
00030
00031 namespace Raul {
00032
00033
00042 class Atom {
00043 public:
00044 enum Type {
00045 NIL,
00046 INT,
00047 FLOAT,
00048 BOOL,
00049 URI,
00050 STRING,
00051 BLOB
00052 };
00053
00054 Atom() : _type(NIL), _blob_val(0) {}
00055 Atom(int32_t val) : _type(INT), _int_val(val) {}
00056 Atom(float val) : _type(FLOAT), _float_val(val) {}
00057 Atom(bool val) : _type(BOOL), _bool_val(val) {}
00058 Atom(const char* val) : _type(STRING), _string_val(strdup(val)) {}
00059
00060 Atom(Type t, const std::string& val) : _type(t), _string_val(strdup(val.c_str())) {}
00061
00062 Atom(const char* type_uri, size_t size, void* val) : _type(BLOB) {
00063 _blob_type_length = strlen(type_uri) + 1;
00064 _blob_size = size;
00065 _blob_val = malloc(_blob_type_length + _blob_size);
00066 memcpy(_blob_val, type_uri, _blob_type_length);
00067 memcpy((char*)_blob_val + _blob_type_length, val, size);
00068 }
00069
00070 ~Atom() {
00071 if (_type == URI || _type == STRING)
00072 free(_string_val);
00073 else if (_type == BLOB)
00074 free(_blob_val);
00075 }
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:
00086 case STRING: _string_val = strdup(copy._string_val); break;
00087 case BLOB: _blob_size = copy._blob_size;
00088 _blob_type_length = copy._blob_type_length;
00089 _blob_val = malloc(_blob_type_length + _blob_size);
00090 memcpy(_blob_val, copy._blob_val, _blob_type_length + _blob_size);
00091 break;
00092 }
00093 }
00094
00095 Atom& operator=(const Atom& other) {
00096 if (_type == BLOB)
00097 free(_blob_val);
00098 else if (_type == STRING)
00099 free(_string_val);
00100
00101 _type = other._type;
00102
00103 switch (_type) {
00104 case NIL: _blob_val = 0; break;
00105 case INT: _int_val = other._int_val; break;
00106 case FLOAT: _float_val = other._float_val; break;
00107 case BOOL: _bool_val = other._bool_val; break;
00108 case URI:
00109 case STRING: _string_val = strdup(other._string_val); break;
00110 case BLOB: _blob_size = other._blob_size;
00111 _blob_type_length = other._blob_type_length;
00112 _blob_val = malloc(_blob_type_length + _blob_size);
00113 memcpy(_blob_val, other._blob_val, _blob_type_length + _blob_size);
00114 break;
00115 }
00116 return *this;
00117 }
00118
00119 inline bool operator==(const Atom& other) const {
00120 if (_type == other.type()) {
00121 switch (_type) {
00122 case NIL: return true;
00123 case INT: return _int_val == other._int_val;
00124 case FLOAT: return _float_val == other._float_val;
00125 case BOOL: return _bool_val == other._bool_val;
00126 case URI:
00127 case STRING: return strcmp(_string_val, other._string_val) == 0;
00128 case BLOB: return _blob_val == other._blob_val;
00129 }
00130 }
00131 return false;
00132 }
00133
00134 inline bool operator!=(const Atom& other) const { return ! operator==(other); }
00135
00136 inline bool operator<(const Atom& other) const {
00137 if (_type == other.type()) {
00138 switch (_type) {
00139 case NIL: return true;
00140 case INT: return _int_val < other._int_val;
00141 case FLOAT: return _float_val < other._float_val;
00142 case BOOL: return _bool_val < other._bool_val;
00143 case URI:
00144 case STRING: return strcmp(_string_val, other._string_val) < 0;
00145 case BLOB: return _blob_val < other._blob_val;
00146 }
00147 }
00148 return _type < other.type();
00149 }
00150
00151 inline size_t data_size() const {
00152 switch (_type) {
00153 case NIL: return 0;
00154 case INT: return sizeof(uint32_t);
00155 case FLOAT: return sizeof(float);
00156 case BOOL: return sizeof(bool);
00157 case URI:
00158 case STRING: return strlen(_string_val);
00159 case BLOB: return _blob_size;
00160 }
00161 return 0;
00162 }
00163
00164 inline bool is_valid() const { return (_type != NIL); }
00165
00169 Type type() const { return _type; }
00170
00171 inline int32_t get_int32() const { assert(_type == INT); return _int_val; }
00172 inline float get_float() const { assert(_type == FLOAT); return _float_val; }
00173 inline bool get_bool() const { assert(_type == BOOL); return _bool_val; }
00174 inline const char* get_string() const { assert(_type == STRING); return _string_val; }
00175 inline const char* get_uri() const { assert(_type == URI); return _string_val; }
00176
00177 inline const char* get_blob_type() const { assert(_type == BLOB); return (const char*)_blob_val; }
00178 inline const void* get_blob() const { assert(_type == BLOB); return (const char*)_blob_val + _blob_type_length; }
00179
00180 private:
00181 Type _type;
00182
00183 union {
00184 int32_t _int_val;
00185 float _float_val;
00186 bool _bool_val;
00187 char* _string_val;
00188 struct {
00189 size_t _blob_type_length;
00190 size_t _blob_size;
00191 void* _blob_val;
00192 };
00193 };
00194 };
00195
00196
00197 }
00198
00199 static inline std::ostream& operator<<(std::ostream& os, const Raul::Atom& atom)
00200 {
00201 switch (atom.type()) {
00202 case Raul::Atom::NIL: return os << "(nil)";
00203 case Raul::Atom::INT: return os << atom.get_int32();
00204 case Raul::Atom::FLOAT: return os << atom.get_float();
00205 case Raul::Atom::BOOL: return os << atom.get_bool();
00206 case Raul::Atom::URI: return os << "<" << atom.get_uri() << ">";
00207 case Raul::Atom::STRING: return os << atom.get_string();
00208 case Raul::Atom::BLOB: return os << atom.get_blob();
00209 }
00210 return os;
00211 }
00212
00213 #endif // RAUL_ATOM_HPP