|
Urbi SDK Remote for C++
2.7.5
|
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("parse error: unexpected `%s', expected `%s'" \ 00133 " in `%s' at %s", \ 00134 message[pos], Char, message, pos); \ 00135 return -pos; \ 00136 } \ 00137 } while (false) 00138 00139 // Works on message[p] (not pos). 00140 #define CHECK_NEOF() \ 00141 do { \ 00142 if (!message[p]) \ 00143 { \ 00144 GD_ERROR("parse error: unexpected end of file"); \ 00145 return -p; \ 00146 } \ 00147 } while (false) 00148 00149 int 00150 UValue::parse(const char* message, int pos, 00151 const binaries_type& bins, 00152 binaries_type::const_iterator& binpos) 00153 { 00154 SKIP_SPACES(); 00155 if (message[pos] == '"') 00156 { 00157 //string 00158 type = DATA_STRING; 00159 //get terminating '"' 00160 int p = pos + 1; 00161 while (message[p] && message[p] != '"') 00162 p += 1 + (message[p] == '\\'); 00163 CHECK_NEOF(); 00164 00165 stringValue = new std::string( 00166 libport::unescape(std::string(message + pos + 1, p - pos - 1))); 00167 return p + 1; 00168 } 00169 00170 if (message[pos] == '[') 00171 { 00172 // List or Dictionary message. 00173 ++pos; 00174 bool hasElt = false; 00175 while (message[pos]) 00176 { 00177 SKIP_SPACES(); 00178 // Detect empty dictionaries. 00179 if (!hasElt && !::strncmp(message + pos, "=>", 2)) 00180 { 00181 type = DATA_DICTIONARY; 00182 dictionary = new UDictionary(); 00183 pos += 2; 00184 SKIP_SPACES(); 00185 continue; 00186 } 00187 if (message[pos] == ']') 00188 { 00189 // End of an empty list / dictionary (created above). 00190 if (type == DATA_VOID) 00191 { 00192 // End of an empty list, create it. 00193 type = DATA_LIST; 00194 list = new UList(); 00195 } 00196 break; 00197 } 00198 UValue* v = new UValue(); 00199 pos = v->parse(message, pos, bins, binpos); 00200 if (pos < 0) 00201 { 00202 delete v; 00203 return pos; 00204 } 00205 SKIP_SPACES(); 00206 // Here is a dictionary key. 00207 if ((type == DATA_DICTIONARY || type == DATA_VOID) 00208 && !::strncmp(message + pos, "=>", 2) && v->type == DATA_STRING) 00209 { 00210 if (type == DATA_VOID) 00211 { 00212 type = DATA_DICTIONARY; 00213 dictionary = new UDictionary(); 00214 } 00215 00216 pos += 2; 00217 SKIP_SPACES(); 00218 // Handle value associated with given key. 00219 std::string key = *(v->stringValue); 00220 (*dictionary)[key] = UValue(); 00221 pos = (*dictionary)[key].parse(message, pos, bins, binpos); 00222 if (pos < 0) 00223 { 00224 delete v; 00225 return pos; 00226 } 00227 } 00228 else 00229 { 00230 if (type == DATA_VOID) 00231 { 00232 type = DATA_LIST; 00233 list = new UList(); 00234 } 00235 list->array.push_back(v); 00236 } 00237 SKIP_SPACES(); 00238 // Expect "," or "]". 00239 if (message[pos] == ']') 00240 break; 00241 EXPECT(','); 00242 hasElt = true; 00243 ++pos; 00244 } 00245 00246 EXPECT(']'); 00247 return pos + 1; 00248 } 00249 00250 if (strprefix("void", message+pos)) 00251 { 00252 //void 00253 type = DATA_VOID; 00254 pos += 4; 00255 return pos; 00256 } 00257 if (strprefix("nil", message+pos)) 00258 { 00259 //void 00260 type = DATA_VOID; 00261 pos += 3; 00262 return pos; 00263 } 00264 if (strprefix("BIN ", message + pos)) 00265 { 00266 //binary message: delegate 00267 type = DATA_BINARY; 00268 binary = new UBinary(); 00269 pos += 4; 00270 //parsing type 00271 return binary->parse(message, pos, bins, binpos); 00272 } 00273 00274 // true and false used by k2 00275 if (strprefix("true", message + pos)) 00276 { 00277 type = DATA_DOUBLE; 00278 val = 1; 00279 return pos+4; 00280 } 00281 00282 if (strprefix("false", message + pos)) 00283 { 00284 type = DATA_DOUBLE; 00285 val = 0; 00286 return pos+5; 00287 } 00288 00289 // Last attempt: it should be a double. 00290 { 00291 int p; 00292 double dval; // in case ufloat is not double 00293 if (sscanf(message+pos, "%lf%n", &dval, &p)) 00294 { 00295 type = DATA_DOUBLE; 00296 pos += p; 00297 val = dval; 00298 return pos; 00299 } 00300 } 00301 00302 // Anything else is an error, but be resilient and ignore it. 00303 GD_FWARN("parse error (ignored): \"%s\"", libport::escape(message + pos)); 00304 return -pos; 00305 } 00306 00307 std::ostream& 00308 UValue::print(std::ostream& s) const 00309 { 00310 switch (type) 00311 { 00312 case DATA_DOUBLE: 00313 s << std::setprecision(21) << val; 00314 break; 00315 case DATA_STRING: 00316 s << '"' << libport::escape(*stringValue, '"') << '"'; 00317 break; 00318 case DATA_SLOTNAME: 00319 s << *stringValue; 00320 break; 00321 case DATA_BINARY: 00322 s << *binary; 00323 break; 00324 case DATA_LIST: 00325 s << *list; 00326 break; 00327 case DATA_DICTIONARY: 00328 s << *dictionary; 00329 break; 00330 case DATA_VOID: 00331 s << "nil"; 00332 break; 00333 } 00334 return s; 00335 } 00336 00337 00338 00339 /*---------. 00340 | UValue. | 00341 `---------*/ 00342 00344 UValue::UValue() 00345 : type(DATA_VOID), val (0), storage(0) 00346 {} 00347 00348 // All the following mess could be avoid if we used templates... 00349 // boost::any could be very useful here. Some day, hopefully... 00350 00351 #define UVALUE_OPERATORS(Args, DataType, Field, Value) \ 00352 UValue::UValue(Args, bool copy) \ 00353 : type(DataType) \ 00354 , Field(Value) \ 00355 { \ 00356 LIBPORT_USE(copy); \ 00357 } \ 00358 \ 00359 UValue& UValue::operator=(Args) \ 00360 { \ 00361 clear(); \ 00362 type = DataType; \ 00363 Field = Value; \ 00364 return *this; \ 00365 } 00366 00367 #define UVALUE_DOUBLE(Type) \ 00368 UVALUE_OPERATORS(Type v, DATA_DOUBLE, val, v) 00369 00370 UVALUE_DOUBLE(ufloat) 00371 UVALUE_DOUBLE(int) 00372 UVALUE_DOUBLE(unsigned int) 00373 UVALUE_DOUBLE(long) 00374 UVALUE_DOUBLE(unsigned long) 00375 UVALUE_DOUBLE(long long) 00376 UVALUE_DOUBLE(unsigned long long) 00377 00378 #undef UVALUE_DOUBLE 00379 00380 00381 /*----------------------. 00382 | UValue: DATA_STRING. | 00383 `----------------------*/ 00384 00385 #define UVALUE_STRING(Type, Value) \ 00386 UVALUE_OPERATORS(Type v, DATA_STRING, stringValue, new std::string(Value)) 00387 00388 UVALUE_STRING(const char*, v) 00389 UVALUE_STRING(const std::string&, v) 00390 UVALUE_STRING(const void*, (libport::format("%%ptr_%x", v))) 00391 00392 #undef UVALUE_STRING 00393 00394 /*----------------------. 00395 | UValue: DATA_BINARY. | 00396 `----------------------*/ 00397 00398 #define UVALUE_BINARY(Type) \ 00399 UVALUE_OPERATORS(Type v, DATA_BINARY, binary, new UBinary(v, copy)) 00400 00401 UVALUE_BINARY(const UBinary&) 00402 UVALUE_BINARY(const USound&) 00403 UVALUE_BINARY(const UImage&) 00404 00405 #undef UVALUE_BINARY 00406 00407 UVALUE_OPERATORS(const UList& v, DATA_LIST, list, new UList(v)) 00408 UVALUE_OPERATORS(const UDictionary& d, 00409 DATA_DICTIONARY, dictionary, new UDictionary(d)); 00410 00411 #undef UVALUE_OPERATORS 00412 00413 void 00414 UValue::clear() 00415 { 00416 switch(type) 00417 { 00418 case DATA_STRING: 00419 case DATA_SLOTNAME: 00420 delete stringValue; 00421 break; 00422 case DATA_BINARY: 00423 delete binary; 00424 break; 00425 case DATA_LIST: 00426 delete list; 00427 break; 00428 case DATA_DICTIONARY: 00429 delete dictionary; 00430 break; 00431 case DATA_DOUBLE: 00432 case DATA_VOID: 00433 break; 00434 } 00435 type = DATA_VOID; 00436 } 00437 00438 UValue::~UValue() 00439 { 00440 clear(); 00441 } 00442 00443 UValue::operator ufloat() const 00444 { 00445 switch (type) 00446 { 00447 case DATA_DOUBLE: 00448 return val; 00449 case DATA_STRING: 00450 return lexical_cast<ufloat>(*stringValue); 00451 case DATA_BINARY: 00452 case DATA_LIST: 00453 case DATA_DICTIONARY: 00454 case DATA_VOID: 00455 case DATA_SLOTNAME: 00456 break; 00457 } 00458 return ufloat(0); 00459 } 00460 00461 00462 UValue::operator std::string() const 00463 { 00464 switch (type) 00465 { 00466 case DATA_DOUBLE: 00467 return string_cast(val); 00468 case DATA_STRING: 00469 case DATA_SLOTNAME: 00470 return *stringValue; 00471 // We cannot convert to UBinary because it is ambigous so we 00472 // try until we found the right type. 00473 case DATA_BINARY: 00474 { 00475 USound snd(*this); 00476 if (snd.soundFormat != SOUND_UNKNOWN) 00477 return string_cast(snd); 00478 break; 00479 } 00480 default: 00481 break; 00482 } 00483 return "invalid"; 00484 } 00485 00486 UValue::operator const UBinary&() const 00487 { 00488 static UBinary dummy; 00489 if (type != DATA_BINARY) 00490 return dummy; 00491 else 00492 return *binary; 00493 } 00494 00495 UValue::operator UImage() const 00496 { 00497 if (type == DATA_BINARY && binary->type == BINARY_IMAGE) 00498 return binary->image; 00499 return UImage::make(); 00500 } 00501 00502 UValue::operator USound() const 00503 { 00504 if (type == DATA_BINARY && binary->type == BINARY_SOUND) 00505 return binary->sound; 00506 return USound::make(); 00507 } 00508 00509 UValue::operator UList() const 00510 { 00511 if (type == DATA_LIST) 00512 return UList(*list); 00513 return UList(); 00514 } 00515 00516 UValue::operator UDictionary() const 00517 { 00518 if (type == DATA_DICTIONARY) 00519 return UDictionary(*dictionary); 00520 return UDictionary(); 00521 } 00522 00523 UValue& UValue::operator= (const UValue& v) 00524 { 00525 return set(v); 00526 } 00527 00528 UValue& UValue::set(const UValue& v, bool copy) 00529 { 00530 // TODO: optimize 00531 if (this == &v) 00532 return *this; 00533 bool sameType = type == v.type; 00534 if (!sameType) 00535 clear(); 00536 00537 switch (v.type) 00538 { 00539 case DATA_DOUBLE: 00540 val = v.val; 00541 break; 00542 case DATA_STRING: 00543 case DATA_SLOTNAME: 00544 if (sameType) 00545 *stringValue = *v.stringValue; 00546 else 00547 stringValue = new std::string(*v.stringValue); 00548 break; 00549 case DATA_BINARY: 00550 if (sameType) 00551 delete binary; 00552 binary = new UBinary(*v.binary, copy); 00553 break; 00554 case DATA_LIST: 00555 if (sameType) 00556 { 00557 list->offset = v.list->offset; 00558 unsigned int mins 00559 = std::min(v.list->array.size(), list->array.size()); 00560 // Reuse existing uvalues 00561 for (unsigned int i = 0; i<mins; ++i) 00562 list->array[i]->set(*v.list->array[i]); 00563 // Destroy extra ones 00564 for(unsigned int k= 0; k<list->array.size() - mins; ++k) 00565 { 00566 delete list->array.back(); 00567 list->array.pop_back(); 00568 } 00569 // Or push new ones 00570 for (unsigned int j = mins; j< v.list->array.size(); ++j) 00571 list->array.push_back(new UValue(v.list->array[j])); 00572 } 00573 else 00574 list = new UList(*v.list); 00575 break; 00576 case DATA_DICTIONARY: 00577 if (sameType) 00578 { 00579 dictionary->clear(); 00580 dictionary->insert(v.dictionary->begin(), v.dictionary->end()); 00581 } 00582 else 00583 dictionary = new UDictionary(*v.dictionary); 00584 break; 00585 case DATA_VOID: 00586 storage = v.storage; 00587 break; 00588 } 00589 type = v.type; 00590 return *this; 00591 } 00592 00593 00594 UValue::UValue(const UValue& v) 00595 : type(DATA_VOID) 00596 { 00597 *this = v; 00598 } 00599 /*--------. 00600 | UList. | 00601 `--------*/ 00602 00603 UList::UList() 00604 : offset(0) 00605 {} 00606 00607 UList::UList(const UList& b) 00608 : offset(0) 00609 { 00610 *this = b; 00611 } 00612 00613 UList& UList::operator= (const UList& b) 00614 { 00615 if (this == &b) 00616 return *this; 00617 clear(); 00618 foreach (UValue* v, b.array) 00619 array.push_back(new UValue(*v)); 00620 offset = b.offset; 00621 return *this; 00622 } 00623 00624 UList::~UList() 00625 { 00626 clear(); 00627 } 00628 00629 void UList::clear() 00630 { 00631 offset = 0; 00632 foreach (UValue *v, array) 00633 delete v; 00634 array.clear(); 00635 } 00636 00637 std::ostream& 00638 UList::print(std::ostream& o) const 00639 { 00640 o << '['; 00641 size_t sz = size(); 00642 for (unsigned i = 0; i < sz; ++i) 00643 o << (*this)[i] 00644 << (i != sz - 1 ? ", " : ""); 00645 o << ']'; 00646 return o; 00647 } 00648 00649 std::ostream& 00650 operator<< (std::ostream& o, const UList& t) 00651 { 00652 return t.print(o); 00653 } 00654 00655 std::ostream& 00656 operator<<(std::ostream& s, const urbi::UDictionary& d) 00657 { 00658 s << "["; 00659 if (d.empty()) 00660 s << "=>"; 00661 else 00662 { 00663 bool isFirst = true; 00664 foreach (const UDictionary::value_type& t, d) 00665 { 00666 if (!isFirst) 00667 s << ","; 00668 s << "\"" << libport::escape(t.first) << "\"=>"; 00669 t.second.print(s); 00670 isFirst = false; 00671 } 00672 } 00673 return s << "]"; 00674 } 00675 00676 00677 00678 00679 std::string 00680 syncline_push(const std::string& srcdir, std::string file, unsigned line) 00681 { 00682 if (boost::algorithm::starts_with(file, srcdir + "/")) 00683 boost::algorithm::erase_head(file, srcdir.size() + 1); 00684 return libport::format("//#push %d \"%s\"\n", line, file); 00685 } 00686 00687 } // namespace urbi