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 #include "AmArg.h"
29 #include "log.h"
30 #include "AmUtils.h"
31 
t2str(int type)32 const char* AmArg::t2str(int type) {
33   switch (type) {
34   case AmArg::Undef:   return "Undef";
35   case AmArg::Int:     return "Int";
36   case AmArg::LongLong: return "LongLong";
37   case AmArg::Bool:    return "Bool";
38   case AmArg::Double:  return "Double";
39   case AmArg::CStr:    return "CStr";
40   case AmArg::AObject: return "AObject";
41   case AmArg::ADynInv: return "ADynInv";
42   case AmArg::Blob:    return "Blob";
43   case AmArg::Array:   return "Array";
44   case AmArg::Struct:  return "Struct";
45   default: return "unknown";
46   }
47 }
48 
AmArg(const AmArg & v)49 AmArg::AmArg(const AmArg& v)
50 {
51   type = Undef;
52 
53   *this = v;
54 }
55 
operator =(const AmArg & v)56 AmArg& AmArg::operator=(const AmArg& v) {
57   if (this != &v) {
58     invalidate();
59 
60     type = v.type;
61     switch(type){
62     case Int:    { v_int = v.v_int; } break;
63     case LongLong: { v_long = v.v_long; } break;
64     case Bool:   { v_bool = v.v_bool; } break;
65     case Double: { v_double = v.v_double; } break;
66     case CStr:   { v_cstr = strdup(v.v_cstr); } break;
67     case AObject:{ v_obj = v.v_obj; } break;
68     case ADynInv:{ v_inv = v.v_inv; } break;
69     case Array:  { v_array = new ValueArray(*v.v_array); } break;
70     case Struct: { v_struct = new ValueStruct(*v.v_struct); } break;
71     case Blob:   {  v_blob = new ArgBlob(*v.v_blob); } break;
72     case Undef: break;
73     default: assert(0);
74     }
75   }
76   return *this;
77 }
78 
AmArg(std::map<std::string,std::string> & v)79 AmArg::AmArg(std::map<std::string, std::string>& v)
80   : type(Undef) {
81   assertStruct();
82   for (std::map<std::string, std::string>::iterator it=
83 	 v.begin();it!= v.end();it++)
84     (*v_struct)[it->first] = AmArg(it->second.c_str());
85 }
86 
AmArg(std::map<std::string,AmArg> & v)87 AmArg::AmArg(std::map<std::string, AmArg>& v)
88   : type(Undef) {
89   assertStruct();
90   for (std::map<std::string, AmArg>::iterator it=
91 	 v.begin();it!= v.end();it++)
92     (*v_struct)[it->first] = it->second;
93 }
94 
AmArg(vector<std::string> & v)95 AmArg::AmArg(vector<std::string>& v)
96   : type(Array) {
97   assertArray(0);
98   for (vector<std::string>::iterator it
99 	 = v.begin(); it != v.end(); it++) {
100     push(AmArg(it->c_str()));
101   }
102 }
103 
AmArg(const vector<int> & v)104 AmArg::AmArg(const vector<int>& v )
105   : type(Array) {
106   assertArray(0);
107   for (vector<int>::const_iterator it
108 	 = v.begin(); it != v.end(); it++) {
109     push(AmArg(*it));
110   }
111 }
112 
AmArg(const vector<double> & v)113 AmArg::AmArg(const vector<double>& v)
114   : type(Array) {
115   assertArray(0);
116   for (vector<double>::const_iterator it
117 	 = v.begin(); it != v.end(); it++) {
118     push(AmArg(*it));
119   }
120 }
121 
assertArray()122 void AmArg::assertArray() {
123   if (Array == type)
124     return;
125   if (Undef == type) {
126     type = Array;
127     v_array = new ValueArray();
128     return;
129   }
130   throw TypeMismatchException();
131 }
132 
assertArray() const133 void AmArg::assertArray() const {
134   if (Array != type)
135     throw TypeMismatchException();
136 }
137 
assertArray(size_t s)138 void AmArg::assertArray(size_t s) {
139 
140   if (Undef == type) {
141     type = Array;
142     v_array = new ValueArray();
143   } else if (Array != type) {
144     throw TypeMismatchException();
145   }
146   if (v_array->size() < s)
147     v_array->resize(s);
148 }
149 
assertStruct()150 void AmArg::assertStruct() {
151   if (Struct == type)
152     return;
153   if (Undef == type) {
154     type = Struct;
155     v_struct = new ValueStruct();
156     return;
157   }
158   throw TypeMismatchException();
159 }
160 
assertStruct() const161 void AmArg::assertStruct() const {
162   if (Struct != type)
163     throw TypeMismatchException();
164 }
165 
invalidate()166 void AmArg::invalidate() {
167   if(type == CStr) { free((void*)v_cstr); }
168   else if(type == Array) { delete v_array; }
169   else if(type == Struct) { delete v_struct; }
170   else if(type == Blob) { delete v_blob; }
171   type = Undef;
172 }
173 
push(const AmArg & a)174 void AmArg::push(const AmArg& a) {
175   assertArray();
176   v_array->push_back(a);
177 }
178 
push(const string & key,const AmArg & val)179 void AmArg::push(const string &key, const AmArg &val) {
180   assertStruct();
181   (*v_struct)[key] = val;
182 }
183 
pop(AmArg & a)184 void AmArg::pop(AmArg &a) {
185   assertArray();
186   if (!size()) {
187     if (a.getType() == AmArg::Undef)
188       return;
189     a = AmArg();
190     return;
191   }
192   a = v_array->front();
193   v_array->erase(v_array->begin());
194 }
195 
pop_back(AmArg & a)196 void AmArg::pop_back(AmArg &a) {
197   assertArray();
198   if (!size()) {
199     if (a.getType() == AmArg::Undef)
200       return;
201     a = AmArg();
202     return;
203   }
204   a = v_array->back();
205   v_array->erase(v_array->end());
206 }
207 
pop_back()208 void AmArg::pop_back() {
209   assertArray();
210   if (!size())
211     return;
212   v_array->erase(v_array->end());
213 }
214 
concat(const AmArg & a)215 void AmArg::concat(const AmArg& a) {
216   assertArray();
217   if (a.getType() == Array) {
218   for (size_t i=0;i<a.size();i++)
219     v_array->push_back(a[i]);
220   } else {
221     v_array->push_back(a);
222   }
223 }
224 
size() const225 size_t AmArg::size() const {
226   if (Array == type)
227     return v_array->size();
228 
229   if (Struct == type)
230     return v_struct->size();
231 
232   throw TypeMismatchException();
233 }
234 
back()235 AmArg& AmArg::back() {
236   assertArray();
237   if (!v_array->size())
238     throw OutOfBoundsException();
239 
240   return (*v_array)[v_array->size()-1];
241 }
242 
back() const243 AmArg& AmArg::back() const {
244   assertArray();
245   if (!v_array->size())
246     throw OutOfBoundsException();
247 
248   return (*v_array)[v_array->size()-1];
249 }
250 
get(size_t idx)251 AmArg& AmArg::get(size_t idx) {
252   assertArray();
253   if (idx >= v_array->size())
254     throw OutOfBoundsException();
255 
256   return (*v_array)[idx];
257 }
258 
get(size_t idx) const259 AmArg& AmArg::get(size_t idx) const {
260   assertArray();
261   if (idx >= v_array->size())
262     throw OutOfBoundsException();
263 
264   return (*v_array)[idx];
265 }
266 
operator [](size_t idx)267 AmArg& AmArg::operator[](size_t idx) {
268   assertArray(idx+1);
269   return (*v_array)[idx];
270 }
271 
operator [](size_t idx) const272 AmArg& AmArg::operator[](size_t idx) const {
273   assertArray();
274   if (idx >= v_array->size())
275     throw OutOfBoundsException();
276 
277   return (*v_array)[idx];
278 }
279 
operator [](int idx)280 AmArg& AmArg::operator[](int idx) {
281   if (idx<0)
282     throw OutOfBoundsException();
283 
284   assertArray(idx+1);
285   return (*v_array)[idx];
286 }
287 
operator [](int idx) const288 AmArg& AmArg::operator[](int idx) const {
289   if (idx<0)
290     throw OutOfBoundsException();
291 
292   assertArray();
293   if ((size_t)idx >= v_array->size())
294     throw OutOfBoundsException();
295 
296   return (*v_array)[idx];
297 }
298 
operator [](std::string key)299 AmArg& AmArg::operator[](std::string key) {
300   assertStruct();
301   return (*v_struct)[key];
302 }
303 
operator [](std::string key) const304 AmArg& AmArg::operator[](std::string key) const {
305   assertStruct();
306   return (*v_struct)[key];
307 }
308 
operator [](const char * key)309 AmArg& AmArg::operator[](const char* key) {
310   assertStruct();
311   return (*v_struct)[key];
312 }
313 
operator [](const char * key) const314 AmArg& AmArg::operator[](const char* key) const {
315   assertStruct();
316   return (*v_struct)[key];
317 }
318 
operator ==(const AmArg & lhs,const AmArg & rhs)319 bool operator==(const AmArg& lhs, const AmArg& rhs) {
320   if (lhs.type != rhs.type)
321     return false;
322 
323   switch(lhs.type){
324   case AmArg::Int:    { return lhs.v_int == rhs.v_int; } break;
325   case AmArg::LongLong: { return lhs.v_long == rhs.v_long; } break;
326   case AmArg::Bool:   { return lhs.v_bool == rhs.v_bool; } break;
327   case AmArg::Double: { return lhs.v_double == rhs.v_double; } break;
328   case AmArg::CStr:   { return !strcmp(lhs.v_cstr,rhs.v_cstr); } break;
329   case AmArg::AObject:{ return lhs.v_obj == rhs.v_obj; } break;
330   case AmArg::ADynInv:{ return lhs.v_inv == rhs.v_inv; } break;
331   case AmArg::Array:  { return lhs.v_array == rhs.v_array;  } break;
332   case AmArg::Struct: { return lhs.v_struct == rhs.v_struct;  } break;
333   case AmArg::Blob:   {  return (lhs.v_blob->len == rhs.v_blob->len) &&
334 	!memcmp(lhs.v_blob->data, rhs.v_blob->data, lhs.v_blob->len); } break;
335   case AmArg::Undef:  return true;
336   default: assert(0);
337   }
338 }
339 
hasMember(const char * name) const340 bool AmArg::hasMember(const char* name) const {
341   return type == Struct && v_struct->find(name) != v_struct->end();
342 }
343 
hasMember(const string & name) const344 bool AmArg::hasMember(const string& name) const {
345   return type == Struct && v_struct->find(name) != v_struct->end();
346 }
347 
enumerateKeys() const348 std::vector<std::string> AmArg::enumerateKeys() const {
349   assertStruct();
350   std::vector<std::string> res;
351   for (ValueStruct::iterator it =
352 	 v_struct->begin(); it != v_struct->end(); it++)
353     res.push_back(it->first);
354   return res;
355 }
356 
begin() const357 AmArg::ValueStruct::const_iterator AmArg::begin() const {
358   assertStruct();
359   return v_struct->begin();
360 }
361 
end() const362 AmArg::ValueStruct::const_iterator AmArg::end() const {
363   assertStruct();
364   return v_struct->end();
365 }
366 
erase(const char * name)367 void AmArg::erase(const char* name) {
368   assertStruct();
369   v_struct->erase(name);
370 }
371 
erase(const std::string & name)372 void AmArg::erase(const std::string& name) {
373   assertStruct();
374   v_struct->erase(name);
375 }
376 
assertArrayFmt(const char * format) const377 void AmArg::assertArrayFmt(const char* format) const {
378   size_t fmt_len = strlen(format);
379   string got;
380   try {
381     for (size_t i=0;i<fmt_len;i++) {
382       switch (format[i]) {
383       case 'i': assertArgInt(get(i)); got+='i';  break;
384       case 'l': assertArgLongLong(get(i)); got+='l';  break;
385       case 't': assertArgBool(get(i)); got+='t';  break;
386       case 'f': assertArgDouble(get(i)); got+='f'; break;
387       case 's': assertArgCStr(get(i)); got+='s'; break;
388       case 'o': assertArgAObject(get(i)); got+='o'; break;
389       case 'd': assertArgADynInv(get(i)); got+='d'; break;
390       case 'a': assertArgArray(get(i)); got+='a'; break;
391       case 'b': assertArgBlob(get(i)); got+='b'; break;
392       case 'u': assertArgStruct(get(i)); got+='u'; break;
393       default: got+='?'; ERROR("ignoring unknown format type '%c'\n",
394 			       format[i]); break;
395       }
396     }
397   } catch (...) {
398     ERROR("parameter mismatch: expected '%s', got '%s...'\n",
399 	  format, got.c_str());
400     throw;
401   }
402 }
403 
404 #define VECTOR_GETTER(type, name, getter)	\
405   vector<type> AmArg::name() const {		\
406     vector<type> res;				\
407     for (size_t i=0;i<size();i++)		\
408       res.push_back(get(i).getter());		\
409     return res;					\
410   }
VECTOR_GETTER(string,asStringVector,asCStr)411 VECTOR_GETTER(string, asStringVector, asCStr)
412 VECTOR_GETTER(int, asIntVector, asInt)
413 VECTOR_GETTER(bool, asBoolVector, asBool)
414 VECTOR_GETTER(double, asDoubleVector, asDouble)
415 VECTOR_GETTER(AmObject*, asAmObjectVector, asObject)
416 #undef  VECTOR_GETTER
417 
418 vector<ArgBlob> AmArg::asArgBlobVector() const {
419   vector<ArgBlob> res;
420   for (size_t i=0;i<size();i++)
421     res.push_back(*get(i).asBlob());
422   return res;
423 }
424 
clear()425 void AmArg::clear() {
426   invalidate();
427 }
428 
print(const AmArg & a)429 string AmArg::print(const AmArg &a) {
430   string s;
431   switch (a.getType()) {
432     case Undef:
433       return "";
434     case Int:
435       return a.asInt()<0?"-"+int2str(abs(a.asInt())):int2str(abs(a.asInt()));
436     case LongLong:
437       return longlong2str(a.asLongLong());
438     case Bool:
439       return a.asBool()?"true":"false";
440     case Double:
441       return double2str(a.asDouble());
442     case CStr:
443       return "'" + string(a.asCStr()) + "'";
444     case AObject:
445       return "<Object>";
446     case ADynInv:
447       return "<DynInv>";
448     case Blob:
449       s = "<Blob of size:" + int2str(a.asBlob()->len) + ">";
450     case Array:
451       s = "[";
452       for (size_t i = 0; i < a.size(); i ++)
453         s += print(a[i]) + ", ";
454       if (1 < s.size())
455         s.resize(s.size() - 2); // strip last ", "
456       s += "]";
457       return s;
458     case Struct:
459       s = "{";
460       for (AmArg::ValueStruct::const_iterator it = a.asStruct()->begin();
461           it != a.asStruct()->end(); it ++) {
462         s += "'"+it->first + "': ";
463         s += print(it->second);
464         s += ", ";
465       }
466       if (1 < s.size())
467         s.resize(s.size() - 2); // strip last ", "
468       s += "}";
469       return s;
470     default: break;
471   }
472   return "<UNKONWN TYPE>";
473 }
474 
arg2int(const AmArg & a)475 int arg2int(const AmArg &a)
476 {
477   if (isArgInt(a)) return a.asInt();
478   if (isArgBool(a)) return a.asBool();
479   if (isArgCStr(a)) {
480     int res;
481     if (!str2int(a.asCStr(), res)) {
482       throw std::string("can't convert arg to int: " + string(a.asCStr()));
483     }
484     return res;
485   }
486 
487   throw std::string("can't convert arg to int");
488 }
489 
arg2str(const AmArg & a)490 string arg2str(const AmArg &a)
491 {
492   if (isArgUndef(a)) return "";
493   if (isArgInt(a)) return int2str(a.asInt());
494   if (isArgBool(a)) return int2str(a.asBool());
495   if (isArgCStr(a)) return a.asCStr();
496 
497   throw std::string("can't convert arg to string");
498 }
499