1 /* 2 * Copyright (C) 2002-2003 Fhg Fokus 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the SEMS software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 28 #ifndef _AmArg_h_ 29 #define _AmArg_h_ 30 31 #include <assert.h> 32 #include <string.h> 33 #include <stdlib.h> 34 35 #include <vector> 36 using std::vector; 37 38 #include <string> 39 using std::string; 40 41 #include <map> 42 43 #include "log.h" 44 45 /** base for Objects as @see AmArg parameter, not owned by AmArg (!) */ 46 class AmObject { 47 public: 48 AmObject() { } 49 virtual ~AmObject() { } 50 }; 51 52 struct ArgBlob { 53 54 void* data; 55 int len; 56 57 ArgBlob() 58 : data(NULL),len(0) 59 { 60 } 61 62 ArgBlob(const ArgBlob& a) { 63 len = a.len; 64 data = malloc(len); 65 if (data) 66 memcpy(data, a.data, len); 67 } 68 69 ArgBlob(const void* _data, int _len) { 70 len = _len; 71 data = malloc(len); 72 if (data) 73 memcpy(data, _data, len); 74 } 75 76 ~ArgBlob() { if (data) free(data); } 77 }; 78 79 class AmDynInvoke; 80 81 /** \brief variable type argument for DynInvoke APIs */ 82 class AmArg 83 : public AmObject 84 { 85 public: 86 // type enum 87 enum { 88 Undef=0, 89 90 Int, 91 LongLong, 92 Bool, 93 Double, 94 CStr, 95 AObject, // pointer to an object not owned by AmArg 96 ADynInv, // pointer to a AmDynInvoke (useful for call backs) 97 Blob, 98 99 Array, 100 Struct 101 }; 102 103 struct OutOfBoundsException { 104 OutOfBoundsException() { } 105 }; 106 107 struct TypeMismatchException { 108 TypeMismatchException() { } 109 }; 110 111 typedef std::vector<AmArg> ValueArray; 112 typedef std::map<std::string, AmArg> ValueStruct; 113 114 private: 115 // type 116 short type; 117 118 // value 119 union { 120 long int v_int; 121 long long int v_long; 122 bool v_bool; 123 double v_double; 124 const char* v_cstr; 125 AmObject* v_obj; 126 AmDynInvoke* v_inv; 127 ArgBlob* v_blob; 128 ValueArray* v_array; 129 ValueStruct* v_struct; 130 }; 131 132 void invalidate(); 133 134 public: 135 136 AmArg() 137 : type(Undef) 138 { } 139 140 AmArg(const AmArg& v); 141 142 AmArg(const int& v) 143 : type(Int), 144 v_int(v) 145 { } 146 147 AmArg(const long int& v) 148 : type(Int), 149 v_int(v) 150 { } 151 152 AmArg(const long long int& v) 153 : type(LongLong), 154 v_long(v) 155 { } 156 157 AmArg(const bool& v) 158 : type(Bool), 159 v_bool(v) 160 { } 161 162 AmArg(const double& v) 163 : type(Double), 164 v_double(v) 165 { } 166 167 AmArg(const char* v) 168 : type(CStr) 169 { 170 v_cstr = strdup(v); 171 } 172 173 AmArg(const string &v) 174 : type(CStr) 175 { 176 v_cstr = strdup(v.c_str()); 177 } 178 179 AmArg(const ArgBlob v) 180 : type(Blob) 181 { 182 v_blob = new ArgBlob(v); 183 } 184 185 AmArg(AmObject* v) 186 : type(AObject), 187 v_obj(v) 188 { } 189 190 AmArg(AmDynInvoke* v) 191 : type(ADynInv), 192 v_inv(v) 193 { } 194 195 // convenience constructors 196 AmArg(vector<std::string>& v); 197 AmArg(const vector<int>& v ); 198 AmArg(const vector<double>& v); 199 AmArg(std::map<std::string, std::string>& v); 200 AmArg(std::map<std::string, AmArg>& v); 201 202 ~AmArg() { invalidate(); } 203 204 void assertArray(); 205 void assertArray() const; 206 207 void assertStruct(); 208 void assertStruct() const; 209 210 short getType() const { return type; } 211 212 AmArg& operator=(const AmArg& rhs); 213 214 #define isArgUndef(a) (AmArg::Undef == a.getType()) 215 #define isArgArray(a) (AmArg::Array == a.getType()) 216 #define isArgStruct(a)(AmArg::Struct == a.getType()) 217 #define isArgDouble(a) (AmArg::Double == a.getType()) 218 #define isArgInt(a) (AmArg::Int == a.getType()) 219 #define isArgLongLong(a) (AmArg::LongLong == a.getType()) 220 #define isArgBool(a) (AmArg::Bool == a.getType()) 221 #define isArgCStr(a) (AmArg::CStr == a.getType()) 222 #define isArgAObject(a) (AmArg::AObject == a.getType()) 223 #define isArgADynInv(a) (AmArg::ADynInv == a.getType()) 224 #define isArgBlob(a) (AmArg::Blob == a.getType()) 225 226 #define _THROW_TYPE_MISMATCH(exp,got) \ 227 do { \ 228 ERROR("type mismatch: expected: %d; received: %d.\n", AmArg::exp, got.getType()); \ 229 throw AmArg::TypeMismatchException(); \ 230 } while (0) 231 232 #define assertArgArray(a) \ 233 if (!isArgArray(a)) \ 234 _THROW_TYPE_MISMATCH(Array,a); 235 #define assertArgDouble(a) \ 236 if (!isArgDouble(a)) \ 237 _THROW_TYPE_MISMATCH(Double,a); 238 #define assertArgInt(a) \ 239 if (!isArgInt(a)) \ 240 _THROW_TYPE_MISMATCH(Int,a); 241 #define assertArgLongLong(a) \ 242 if (!isArgLongLong(a)) \ 243 _THROW_TYPE_MISMATCH(LongLong,a); 244 #define assertArgBool(a) \ 245 if (!isArgBool(a)) \ 246 _THROW_TYPE_MISMATCH(Bool,a); 247 #define assertArgCStr(a) \ 248 if (!isArgCStr(a)) \ 249 _THROW_TYPE_MISMATCH(CStr,a); 250 #define assertArgAObject(a) \ 251 if (!isArgAObject(a)) \ 252 _THROW_TYPE_MISMATCH(AObject,a); 253 #define assertArgADynInv(a) \ 254 if (!isArgADynInv(a)) \ 255 _THROW_TYPE_MISMATCH(ADynInv,a); 256 #define assertArgBlob(a) \ 257 if (!isArgBlob(a)) \ 258 _THROW_TYPE_MISMATCH(Blob,a); 259 #define assertArgStruct(a) \ 260 if (!isArgStruct(a)) \ 261 _THROW_TYPE_MISMATCH(Struct,a); 262 263 void setBorrowedPointer(AmObject* v) { 264 invalidate(); 265 type = AObject; 266 v_obj = v; 267 } 268 269 int asInt() const { return (int)v_int; } 270 long int asLong() const { return v_int; } 271 long long asLongLong() const { return v_long; } 272 int asBool() const { return v_bool; } 273 double asDouble() const { return v_double; } 274 const char* asCStr() const { return v_cstr; } 275 AmObject* asObject() const { return v_obj; } 276 AmDynInvoke* asDynInv() const { return v_inv; } 277 ArgBlob* asBlob() const { return v_blob; } 278 ValueStruct* asStruct() const { return v_struct; } 279 280 vector<string> asStringVector() const; 281 vector<int> asIntVector() const; 282 vector<bool> asBoolVector() const; 283 vector<double> asDoubleVector() const; 284 vector<AmObject*> asAmObjectVector() const; 285 vector<ArgBlob> asArgBlobVector() const; 286 287 // operations on arrays 288 void assertArray(size_t s); 289 290 void push(const AmArg& a); 291 void push(const string &key, const AmArg &val); 292 void pop(AmArg &a); 293 void pop_back(AmArg &a); 294 void pop_back(); 295 296 void concat(const AmArg& a); 297 298 size_t size() const; 299 300 /** throws OutOfBoundsException if array too small */ 301 AmArg& get(size_t idx); 302 303 /** throws OutOfBoundsException if array too small */ 304 AmArg& get(size_t idx) const; 305 306 /** throws OutOfBoundsException if array too small */ 307 AmArg& back(); 308 309 /** throws OutOfBoundsException if array too small */ 310 AmArg& back() const; 311 312 /** resizes array if too small */ 313 AmArg& operator[](size_t idx); 314 /** throws OutOfBoundsException if array too small */ 315 AmArg& operator[](size_t idx) const; 316 317 /** resizes array if too small */ 318 AmArg& operator[](int idx); 319 /** throws OutOfBoundsException if array too small */ 320 AmArg& operator[](int idx) const; 321 322 AmArg& operator[](std::string key); 323 AmArg& operator[](std::string key) const; 324 AmArg& operator[](const char* key); 325 AmArg& operator[](const char* key) const; 326 327 /** Check for the existence of a struct member by name. */ 328 bool hasMember(const std::string& name) const; 329 bool hasMember(const char* name) const; 330 331 std::vector<std::string> enumerateKeys() const; 332 ValueStruct::const_iterator begin() const; 333 ValueStruct::const_iterator end() const; 334 335 /** remove struct member */ 336 void erase(const char* name); 337 /** remove struct member */ 338 void erase(const std::string& name); 339 340 /** 341 * throws exception if arg array does not conform to spec 342 * i - int 343 * l - long long 344 * t - bool 345 * f - double 346 * s - cstr 347 * o - object 348 * d - dyninvoke 349 * b - blob 350 * a - array 351 * u - struct 352 * 353 * e.g. "ssif" -> [cstr, cstr, int, double] 354 */ 355 void assertArrayFmt(const char* format) const; 356 357 void clear(); 358 friend bool operator==(const AmArg& lhs, const AmArg& rhs); 359 360 friend bool json2arg(std::istream& input, AmArg& res); 361 362 static string print(const AmArg &a); 363 364 static const char* t2str(int type); 365 }; 366 367 // equality 368 bool operator==(const AmArg& lhs, const AmArg& rhs); 369 370 int arg2int(const AmArg &a); 371 string arg2str(const AmArg &a); 372 373 #endif 374 375