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