|
Urbi SDK Remote for C++
2.7.3
|
00001 /* 00002 * Copyright (C) 2006-2011, Gostai S.A.S. 00003 * 00004 * This software is provided "as is" without warranty of any kind, 00005 * either expressed or implied, including but not limited to the 00006 * implied warranties of fitness for a particular purpose. 00007 * 00008 * See the LICENSE file for more information. 00009 */ 00010 00012 #include <boost/algorithm/string/erase.hpp> 00013 #include <boost/algorithm/string/predicate.hpp> 00014 00015 #include <libport/cassert> 00016 #include <libport/compiler.hh> 00017 #include <libport/cstdio> 00018 #include <libport/cstdlib> 00019 #include <libport/cstring> 00020 #include <libport/debug.hh> 00021 #include <libport/escape.hh> 00022 #include <libport/foreach.hh> 00023 #include <libport/format.hh> 00024 #include <libport/iostream> 00025 #include <libport/lexical-cast.hh> 00026 #include <libport/xalloc.hh> 00027 #include <sstream> 00028 #include <iomanip> 00029 00030 #include <urbi/ubinary.hh> 00031 #include <urbi/uvalue.hh> 00032 00033 GD_CATEGORY(Urbi.UValue); 00034 00035 namespace urbi 00036 { 00037 00038 int& 00039 kernelMajor(std::ostream& o) 00040 { 00041 typedef libport::xalloc<int> version_type; 00042 static version_type version; 00043 return version(o); 00044 } 00045 00046 /*---------------. 00047 | UValue Casts. | 00048 `---------------*/ 00049 00050 UBinary 00051 uvalue_caster<UBinary>::operator() (UValue& v) 00052 { 00053 if (v.type == DATA_BINARY) 00054 return UBinary(*v.binary); 00055 return UBinary(); 00056 } 00057 00058 UList 00059 uvalue_caster<UList>::operator() (UValue& v) 00060 { 00061 if (v.type == DATA_LIST) 00062 return UList(*v.list); 00063 return UList(); 00064 } 00065 00066 UDictionary 00067 uvalue_caster<UDictionary>::operator() (UValue& v) 00068 { 00069 if (v.type == DATA_DICTIONARY) 00070 return UDictionary(*v.dictionary); 00071 return UDictionary(); 00072 } 00073 00074 const char* 00075 uvalue_caster<const char*>::operator() (UValue& v) 00076 { 00077 if (v.type == DATA_STRING) 00078 return v.stringValue->c_str(); 00079 return "invalid"; 00080 } 00081 00082 00083 /*---------. 00084 | UValue. | 00085 `---------*/ 00086 00087 UValue& 00088 UValue::error() 00089 { 00090 static UValue instance("<<UValue::error (denotes an error)>>"); 00091 return instance; 00092 } 00093 00094 static const char* formats[] = { 00095 "binary", 00096 "dictionary", 00097 "double", 00098 "list", 00099 "object", 00100 "string", 00101 "void" 00102 }; 00103 00104 const char* 00105 UValue::format_string() const 00106 { 00107 int f = static_cast<int>(type); 00108 if (f < 0 || f > DATA_VOID) 00109 return "unknown"; 00110 return formats[f]; 00111 } 00112 00113 #define SKIP_SPACES() \ 00114 while (message[pos] == ' ') \ 00115 ++pos 00116 00117 namespace 00118 { 00119 static 00120 bool 00121 strprefix(const char* prefix, const char* string) 00122 { 00123 return !strncmp(prefix, string, strlen(prefix)); 00124 } 00125 } 00126 00127 // Works on message[pos]. 00128 #define EXPECT(Char) \ 00129 do { \ 00130 if (message[pos] != Char) \ 00131 { \ 00132 GD_FERROR("unexpected `%s', expected `%s'", \ 00133 message[pos], Char); \ 00134 return -pos; \ 00135 } \ 00136 } while(0) 00137 00138 // Works on message[p] (not pos). 00139 #define CHECK_NEOF() \ 00140 do { \ 00141 if (!message[p]) \ 00142 { \ 00143 GD_ERROR("unexpected end of file"); \ 00144 return -p; \ 00145 } \ 00146 } while (0) 00147 00148 int 00149 UValue::parse(const char* message, int pos, 00150 const binaries_type& bins, 00151 binaries_type::const_iterator& binpos) 00152 { 00153 SKIP_SPACES(); 00154 if (message[pos] == '"') 00155 { 00156 //string 00157 type = DATA_STRING; 00158 //get terminating '"' 00159 int p = pos + 1; 00160 while (message[p] && message[p] != '"') 00161 p += 1 + (message[p] == '\\'); 00162 CHECK_NEOF(); 00163 00164 stringValue = new std::string( 00165 libport::unescape(std::string(message + pos + 1, p - pos - 1))); 00166 return p + 1; 00167 } 00168 00169 if (message[pos] == '[') 00170 { 00171 // List or Dictionary message. 00172 ++pos; 00173 bool hasElt = 0; 00174 while (message[pos]) 00175 { 00176 SKIP_SPACES(); 00177 if (!hasElt && !::strncmp(message + pos, "=>", 2)) 00178 { 00179 // Detect empty dictionaries. 00180 type = DATA_DICTIONARY; 00181 dictionary = new UDictionary(); 00182 pos += 2; 00183 SKIP_SPACES(); 00184 continue; 00185 } 00186 if (message[pos] == ']') 00187 { 00188 // End of an empty list / dictionary (created above). 00189 if (type == DATA_VOID) 00190 { 00191 // End of an empty list, create it. 00192 type = DATA_LIST; 00193 list = new UList(); 00194 } 00195 break; 00196 } 00197 UValue* v = new UValue(); 00198 pos = v->parse(message, pos, bins, binpos); 00199 if (pos < 0) 00200 { 00201 delete v; 00202 return pos; 00203 } 00204 SKIP_SPACES(); 00205 // Here is a dictionary key. 00206 if ((type == DATA_DICTIONARY || type == DATA_VOID) 00207 && !::strncmp(message + pos, "=>", 2) && v->type == DATA_STRING) 00208 { 00209 if (type == DATA_VOID) 00210 { 00211 type = DATA_DICTIONARY; 00212 dictionary = new UDictionary(); 00213 } 00214 00215 pos += 2; 00216 SKIP_SPACES(); 00217 // Handle value associated with given key. 00218 std::string key = *(v->stringValue); 00219 (*dictionary)[key] = UValue(); 00220 pos = (*dictionary)[key].parse(message, pos, bins, binpos); 00221 if (pos < 0) 00222 { 00223 delete v; 00224 return pos; 00225 } 00226 } 00227 else 00228 { 00229 if (type == DATA_VOID) 00230 { 00231 type = DATA_LIST; 00232 list = new UList(); 00233 } 00234 list->array.push_back(v); 00235 } 00236 SKIP_SPACES(); 00237 // Expect "," or "]". 00238 if (message[pos] == ']') 00239 break; 00240 EXPECT(','); 00241 hasElt = true; 00242 ++pos; 00243 } 00244 00245 EXPECT(']'); 00246 return pos + 1; 00247 } 00248 00249 if (strprefix("void", message+pos)) 00250 { 00251 //void 00252 type = DATA_VOID; 00253 pos += 4; 00254 return pos; 00255 } 00256 if (strprefix("nil", message+pos)) 00257 { 00258 //void 00259 type = DATA_VOID; 00260 pos += 3; 00261 return pos; 00262 } 00263 if (strprefix("BIN ", message + pos)) 00264 { 00265 //binary message: delegate 00266 type = DATA_BINARY; 00267 binary = new UBinary(); 00268 pos += 4; 00269 //parsing type 00270 return binary->parse(message, pos, bins, binpos); 00271 } 00272 00273 // true and false used by k2 00274 if (strprefix("true", message + pos)) 00275 { 00276 type = DATA_DOUBLE; 00277 val = 1; 00278 return pos+4; 00279 } 00280 00281 if (strprefix("false", message + pos)) 00282 { 00283 type = DATA_DOUBLE; 00284 val = 0; 00285 return pos+5; 00286 } 00287 00288 // Last attempt: it should be a double. 00289 { 00290 int p; 00291 double dval; // in case ufloat is not double 00292 if (sscanf(message+pos, "%lf%n", &dval, &p)) 00293 { 00294 type = DATA_DOUBLE; 00295 pos += p; 00296 val = dval; 00297 return pos; 00298 } 00299 } 00300 00301 // Anything else is an error, but be resilient and ignore it. 00302 GD_FWARN("syntax error (ignored): \"%s\"", libport::escape(message + pos)); 00303 return -pos; 00304 } 00305 00306 std::ostream& 00307 UValue::print(std::ostream& s) const 00308 { 00309 switch (type) 00310 { 00311 case DATA_DOUBLE: 00312 s << std::setprecision(21) << val; 00313 break; 00314 case DATA_STRING: 00315 s << '"' << libport::escape(*stringValue, '"') << '"'; 00316 break; 00317 case DATA_SLOTNAME: 00318 s << *stringValue; 00319 break; 00320 case DATA_BINARY: 00321 s << *binary; 00322 break; 00323 case DATA_LIST: 00324 s << *list; 00325 break; 00326 case DATA_DICTIONARY: 00327 s << *dictionary; 00328 break; 00329 case DATA_VOID: 00330 s << "nil"; 00331 break; 00332 } 00333 return s; 00334 } 00335 00336 00337 00338 /*---------. 00339 | UValue. | 00340 `---------*/ 00341 00343 UValue::UValue() 00344 : type(DATA_VOID), val (0), storage(0) 00345 {} 00346 00347 // All the following mess could be avoid if we used templates... 00348 // boost::any could be very useful here. Some day, hopefully... 00349 00350 #define UVALUE_OPERATORS(Args, DataType, Field, Value) \ 00351 UValue::UValue(Args, bool copy) \ 00352 : type(DataType) \ 00353 , Field(Value) \ 00354 { \ 00355 LIBPORT_USE(copy); \ 00356 } \ 00357 \ 00358 UValue& UValue::operator=(Args) \ 00359 { \ 00360 clear(); \ 00361 type = DataType; \ 00362 Field = Value; \ 00363 return *this; \ 00364 } 00365 00366 #define UVALUE_DOUBLE(Type) \ 00367 UVALUE_OPERATORS(Type v, DATA_DOUBLE, val, v) 00368 00369 UVALUE_DOUBLE(ufloat) 00370 UVALUE_DOUBLE(int) 00371 UVALUE_DOUBLE(unsigned int) 00372 UVALUE_DOUBLE(long) 00373 UVALUE_DOUBLE(unsigned long) 00374 UVALUE_DOUBLE(long long) 00375 UVALUE_DOUBLE(unsigned long long) 00376 00377 #undef UVALUE_DOUBLE 00378 00379 00380 /*----------------------. 00381 | UValue: DATA_STRING. | 00382 `----------------------*/ 00383 00384 #define UVALUE_STRING(Type, Value) \ 00385 UVALUE_OPERATORS(Type v, DATA_STRING, stringValue, new std::string(Value)) 00386 00387 UVALUE_STRING(const char*, v) 00388 UVALUE_STRING(const std::string&, v) 00389 UVALUE_STRING(const void*, (libport::format("%%ptr_%x", v))) 00390 00391 #undef UVALUE_STRING 00392 00393 /*----------------------. 00394 | UValue: DATA_BINARY. | 00395 `----------------------*/ 00396 00397 #define UVALUE_BINARY(Type) \ 00398 UVALUE_OPERATORS(Type v, DATA_BINARY, binary, new UBinary(v, copy)) 00399 00400 UVALUE_BINARY(const UBinary&) 00401 UVALUE_BINARY(const USound&) 00402 UVALUE_BINARY(const UImage&) 00403 00404 #undef UVALUE_BINARY 00405 00406 UVALUE_OPERATORS(const UList& v, DATA_LIST, list, new UList(v)) 00407 UVALUE_OPERATORS(const UDictionary& d, 00408 DATA_DICTIONARY, dictionary, new UDictionary(d)); 00409 00410 #undef UVALUE_OPERATORS 00411 00412 void 00413 UValue::clear() 00414 { 00415 switch(type) 00416 { 00417 case DATA_STRING: 00418 case DATA_SLOTNAME: 00419 delete stringValue; 00420 break; 00421 case DATA_BINARY: 00422 delete binary; 00423 break; 00424 case DATA_LIST: 00425 delete list; 00426 break; 00427 case DATA_DICTIONARY: 00428 delete dictionary; 00429 break; 00430 case DATA_DOUBLE: 00431 case DATA_VOID: 00432 break; 00433 } 00434 type = DATA_VOID; 00435 } 00436 00437 UValue::~UValue() 00438 { 00439 clear(); 00440 } 00441 00442 UValue::operator ufloat() const 00443 { 00444 switch (type) 00445 { 00446 case DATA_DOUBLE: 00447 return val; 00448 case DATA_STRING: 00449 return lexical_cast<ufloat>(*stringValue); 00450 case DATA_BINARY: 00451 case DATA_LIST: 00452 case DATA_DICTIONARY: 00453 case DATA_VOID: 00454 case DATA_SLOTNAME: 00455 break; 00456 } 00457 return ufloat(0); 00458 } 00459 00460 00461 UValue::operator std::string() const 00462 { 00463 switch (type) 00464 { 00465 case DATA_DOUBLE: 00466 return string_cast(val); 00467 case DATA_STRING: 00468 case DATA_SLOTNAME: 00469 return *stringValue; 00470 // We cannot convert to UBinary because it is ambigous so we 00471 // try until we found the right type. 00472 case DATA_BINARY: 00473 { 00474 USound snd(*this); 00475 if (snd.soundFormat != SOUND_UNKNOWN) 00476 return string_cast(snd); 00477 break; 00478 } 00479 default: 00480 break; 00481 } 00482 return "invalid"; 00483 } 00484 00485 UValue::operator const UBinary&() const 00486 { 00487 static UBinary dummy; 00488 if (type != DATA_BINARY) 00489 return dummy; 00490 else 00491 return *binary; 00492 } 00493 00494 UValue::operator UImage() const 00495 { 00496 if (type == DATA_BINARY && binary->type == BINARY_IMAGE) 00497 return binary->image; 00498 return UImage::make(); 00499 } 00500 00501 UValue::operator USound() const 00502 { 00503 if (type == DATA_BINARY && binary->type == BINARY_SOUND) 00504 return binary->sound; 00505 return USound::make(); 00506 } 00507 00508 UValue::operator UList() const 00509 { 00510 if (type == DATA_LIST) 00511 return UList(*list); 00512 return UList(); 00513 } 00514 00515 UValue::operator UDictionary() const 00516 { 00517 if (type == DATA_DICTIONARY) 00518 return UDictionary(*dictionary); 00519 return UDictionary(); 00520 } 00521 00522 UValue& UValue::operator= (const UValue& v) 00523 { 00524 return set(v); 00525 } 00526 00527 UValue& UValue::set(const UValue& v, bool copy) 00528 { 00529 // TODO: optimize 00530 if (this == &v) 00531 return *this; 00532 bool sameType = type == v.type; 00533 if (!sameType) 00534 clear(); 00535 00536 switch (v.type) 00537 { 00538 case DATA_DOUBLE: 00539 val = v.val; 00540 break; 00541 case DATA_STRING: 00542 case DATA_SLOTNAME: 00543 if (sameType) 00544 *stringValue = *v.stringValue; 00545 else 00546 stringValue = new std::string(*v.stringValue); 00547 break; 00548 case DATA_BINARY: 00549 if (sameType) 00550 delete binary; 00551 binary = new UBinary(*v.binary, copy); 00552 break; 00553 case DATA_LIST: 00554 if (sameType) 00555 { 00556 list->offset = v.list->offset; 00557 unsigned int mins 00558 = std::min(v.list->array.size(), list->array.size()); 00559 // Reuse existing uvalues 00560 for (unsigned int i = 0; i<mins; ++i) 00561 list->array[i]->set(*v.list->array[i]); 00562 // Destroy extra ones 00563 for(unsigned int k= 0; k<list->array.size() - mins; ++k) 00564 { 00565 delete list->array.back(); 00566 list->array.pop_back(); 00567 } 00568 // Or push new ones 00569 for (unsigned int j = mins; j< v.list->array.size(); ++j) 00570 list->array.push_back(new UValue(v.list->array[j])); 00571 } 00572 else 00573 list = new UList(*v.list); 00574 break; 00575 case DATA_DICTIONARY: 00576 if (sameType) 00577 { 00578 dictionary->clear(); 00579 dictionary->insert(v.dictionary->begin(), v.dictionary->end()); 00580 } 00581 else 00582 dictionary = new UDictionary(*v.dictionary); 00583 break; 00584 case DATA_VOID: 00585 storage = v.storage; 00586 break; 00587 } 00588 type = v.type; 00589 return *this; 00590 } 00591 00592 00593 UValue::UValue(const UValue& v) 00594 : type(DATA_VOID) 00595 { 00596 *this = v; 00597 } 00598 /*--------. 00599 | UList. | 00600 `--------*/ 00601 00602 UList::UList() 00603 : offset(0) 00604 {} 00605 00606 UList::UList(const UList& b) 00607 : offset(0) 00608 { 00609 *this = b; 00610 } 00611 00612 UList& UList::operator= (const UList& b) 00613 { 00614 if (this == &b) 00615 return *this; 00616 clear(); 00617 foreach (UValue* v, b.array) 00618 array.push_back(new UValue(*v)); 00619 offset = b.offset; 00620 return *this; 00621 } 00622 00623 UList::~UList() 00624 { 00625 clear(); 00626 } 00627 00628 void UList::clear() 00629 { 00630 offset = 0; 00631 foreach (UValue *v, array) 00632 delete v; 00633 array.clear(); 00634 } 00635 00636 std::ostream& 00637 UList::print(std::ostream& o) const 00638 { 00639 o << '['; 00640 size_t sz = size(); 00641 for (unsigned i = 0; i < sz; ++i) 00642 o << (*this)[i] 00643 << (i != sz - 1 ? ", " : ""); 00644 o << ']'; 00645 return o; 00646 } 00647 00648 std::ostream& 00649 operator<< (std::ostream& o, const UList& t) 00650 { 00651 return t.print(o); 00652 } 00653 00654 std::ostream& 00655 operator<<(std::ostream& s, const urbi::UDictionary& d) 00656 { 00657 s << "["; 00658 if (d.empty()) 00659 s << "=>"; 00660 else 00661 { 00662 bool isFirst = true; 00663 foreach (const UDictionary::value_type& t, d) 00664 { 00665 if (!isFirst) 00666 s << ","; 00667 s << "\"" << libport::escape(t.first) << "\"=>"; 00668 t.second.print(s); 00669 isFirst = false; 00670 } 00671 } 00672 return s << "]"; 00673 } 00674 00675 00676 00677 00678 std::string 00679 syncline_push(const std::string& srcdir, std::string file, unsigned line) 00680 { 00681 if (boost::algorithm::starts_with(file, srcdir + "/")) 00682 boost::algorithm::erase_head(file, srcdir.size() + 1); 00683 return libport::format("//#push %d \"%s\"\n", line, file); 00684 } 00685 00686 } // namespace urbi