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