00001
00021 #include "libport/cstdio"
00022
00023 #include <sstream>
00024 #include <iostream>
00025
00026 #include "urbi/uobject.hh"
00027
00028 namespace urbi
00029 {
00030
00031
00032
00033
00034
00035 void unescape(std::string& data)
00036 {
00037 int src = 0;
00038 int dst = 0;
00039 while (data[src])
00040 {
00041 if (data[src] != '\\')
00042 data[dst] = data[src];
00043 else
00044 switch(data[++src])
00045 {
00046 case 'n':
00047 data[dst] = '\n';
00048 break;
00049 case '\\':
00050 data[dst] = '\\';
00051 break;
00052 case '"':
00053 data[dst] = '"';
00054 break;
00055 default:
00056 data[dst] = data[src];
00057 break;
00058 }
00059
00060 ++src;
00061 ++dst;
00062 }
00063 data[dst] = 0;
00064 }
00065
00066 void unescape(char* data)
00067 {
00068 char* src = data;
00069 char* dst = data;
00070 while (*src)
00071 {
00072 if (*src != '\\')
00073 *dst = *src;
00074 else
00075 switch (*(++src))
00076 {
00077 case 'n':
00078 *dst = '\n';
00079 break;
00080 case '\\':
00081 *dst = '\\';
00082 break;
00083 case '"':
00084 *dst = '"';
00085 break;
00086 default:
00087 *dst = *src;
00088 }
00089
00090 ++src;
00091 ++dst;
00092 }
00093 *dst = 0;
00094 }
00095
00096
00097
00098
00099 int UValue::parse(const char* message, int pos,
00100 std::list<BinaryData>& bins,
00101 std::list<BinaryData>::iterator& binpos)
00102 {
00103 while (message[pos] == ' ')
00104 ++pos;
00105 if (message[pos] == '"')
00106 {
00107
00108 type = DATA_STRING;
00109
00110 int p = pos + 1;
00111 while (message[p] && message[p] != '"')
00112 {
00113 if (message[p] == '\\')
00114 ++p;
00115 ++p;
00116 }
00117 if (!message[p])
00118 return -p;
00119
00120 stringValue = new std::string(message + pos + 1, p - pos - 1);
00121 unescape(*stringValue);
00122 return p + 1;
00123 }
00124
00125 if (message[pos] == '[')
00126 {
00127
00128 type = DATA_LIST;
00129 list = new UList();
00130 ++pos;
00131 while (message[pos] == ' ')
00132 ++pos;
00133 while (message[pos])
00134 {
00135 while (message[pos] == ' ')
00136 ++pos;
00137 if (message[pos] == ']')
00138 break;
00139 UValue* v = new UValue();
00140 int p = v->parse(message, pos, bins, binpos);
00141 if (p < 0)
00142 return p;
00143 list->array.push_back(v);
00144 pos = p;
00145 while (message[pos] == ' ')
00146 ++pos;
00147
00148 if (message[pos] == ']')
00149 break;
00150 if (message[pos] != ',')
00151 return -pos;
00152 ++pos;
00153 }
00154
00155 if (message[pos] != ']')
00156 return -pos;
00157 return pos + 1;
00158 }
00159
00160
00161 if (!strncmp(message + pos, "OBJ ", 4))
00162 {
00163
00164 pos += 4;
00165 type = DATA_OBJECT;
00166 object = new UObjectStruct();
00167
00168 while (message[pos] == ' ')
00169 ++pos;
00170 if (message[pos] != '[')
00171 return -pos;
00172 ++pos;
00173
00174 while (message[pos])
00175 {
00176 while (message[pos] == ' ')
00177 ++pos;
00178 if (message[pos] == ']')
00179 break;
00180
00181 int p = pos;
00182 while (message[p] && message[p] != ':')
00183 ++p;
00184 if (!message[p])
00185 return -p;
00186 ++p;
00187 UNamedValue nv;
00188 nv.name = std::string(message + pos, p - pos - 1);
00189 pos = p;
00190 while (message[pos] == ' ')
00191 ++pos;
00192 UValue* v = new UValue();
00193 p = v->parse(message, pos, bins, binpos);
00194 if (p < 0)
00195 return p;
00196 nv.val = v;
00197 object->array.push_back(nv);
00198 pos = p;
00199 while (message[pos] == ' ')
00200 ++pos;
00201
00202 if (message[pos] == ']')
00203 break;
00204 if (message[pos] != ',')
00205 return -pos;
00206 ++pos;
00207 }
00208
00209 if (message[pos] != ']')
00210 return -pos;
00211 return pos + 1;
00212 }
00213
00214 if (!strncmp(message+pos, "void", 4))
00215 {
00216
00217 type = DATA_VOID;
00218 pos += 4;
00219 return pos;
00220 }
00221
00222 if (!strncmp(message + pos, "BIN ", 4))
00223 {
00224
00225 type = DATA_BINARY;
00226 binary = new UBinary();
00227 pos += 4;
00228
00229 int p = binary->parse(message, pos, bins, binpos);
00230 return p;
00231 }
00232
00233
00234 int p;
00235 int count = sscanf(message+pos, "%lf%n", &val, &p);
00236 if (!count)
00237 return -pos;
00238 type = DATA_DOUBLE;
00239 pos += p;
00240 return pos;
00241 }
00242
00243 std::ostream&
00244 UValue::print (std::ostream& s) const
00245 {
00246 switch (type)
00247 {
00248 case DATA_DOUBLE:
00249 s << val;
00250 break;
00251 case DATA_STRING:
00252 s << '"' << *stringValue << '"';
00253 break;
00254 case DATA_BINARY:
00255 if (binary->type != BINARY_NONE
00256 && binary->type != BINARY_UNKNOWN)
00257 binary->buildMessage();
00258 s << "BIN "<< binary->common.size << ' ' << binary->message << ';';
00259 s.write((char*) binary->common.data, binary->common.size);
00260 break;
00261 case DATA_LIST:
00262 {
00263 s << '[';
00264 int sz = list->size();
00265 for (int i = 0; i < sz; ++i)
00266 {
00267 s << (*list)[i];
00268 if (i != sz - 1)
00269 s << " , ";
00270 }
00271 s << ']';
00272 }
00273 break;
00274 case DATA_OBJECT:
00275 {
00276 s << "OBJ "<<object->refName<<" [";
00277 int sz = object->size();
00278 for (int i = 0; i < sz; ++i)
00279 {
00280 s << (*object)[i].name << ':';
00281 s << (*object)[i].val;
00282 if (i != sz - 1)
00283 s << " , ";
00284 }
00285 s << ']';
00286 }
00287 break;
00288 default:
00289 s << "<<void>>";
00290 }
00291 return s;
00292 }
00293
00294
00295
00296
00297
00298
00299 const char* USound::format_string () const
00300 {
00301 switch (soundFormat)
00302 {
00303 case SOUND_RAW:
00304 return "raw";
00305 case SOUND_WAV:
00306 return "wav";
00307 case SOUND_MP3:
00308 return "mp3";
00309 case SOUND_OGG:
00310 return "ogg";
00311 case SOUND_UNKNOWN:
00312 return "unknown format";
00313 }
00314
00315 abort();
00316 }
00317
00318
00319
00320
00321
00322 const char* UImage::format_string () const
00323 {
00324 switch (imageFormat)
00325 {
00326 case IMAGE_RGB:
00327 return "rgb";
00328 case IMAGE_JPEG:
00329 return "jpeg";
00330 case IMAGE_YCbCr:
00331 return "YCbCr";
00332 case IMAGE_PPM:
00333 return "ppm";
00334 case IMAGE_UNKNOWN:
00335 return "unknown format";
00336 }
00337
00338 abort();
00339 }
00340
00341
00342
00343
00344
00345 int
00346 UBinary::parse(const char* message, int pos,
00347 std::list<BinaryData>& bins,
00348 std::list<BinaryData>::iterator& binpos)
00349 {
00350 while (message[pos] == ' ')
00351 ++pos;
00352
00353
00354 if (binpos == bins.end())
00355 return -1;
00356
00357
00358 int ps;
00359 unsigned psize;
00360 int count = sscanf(message+pos, "%u%n", &psize, &ps);
00361 if (count != 1)
00362 return -pos;
00363 if (psize != binpos->size)
00364 {
00365 std::cerr << "bin size inconsistency\n";
00366 return -pos;
00367 }
00368 pos += ps;
00369 common.size = psize;
00370 common.data = malloc(psize);
00371 memcpy(common.data, binpos->data, common.size);
00372 ++binpos;
00373
00374 int p = pos;
00375 while (message[p] && message[p] != '\n')
00376 ++p;
00377 if (!message[p])
00378 return -p;
00379 this->message = std::string(message + pos, p - pos);
00380 ++p;
00381
00382
00383 char type[64];
00384 memset(type, 0, 64);
00385 int p2, p3, p4, p5;
00386 count = sscanf(message + pos, "%63s %d %d %d %d",
00387 type, &p2, &p3, &p4, &p5);
00388
00389 if (STREQ(type, "jpeg"))
00390 {
00391 this->type = BINARY_IMAGE;
00392 image.size = common.size;
00393 image.width = p2;
00394 image.height = p3;
00395 image.imageFormat = IMAGE_JPEG;
00396 return p;
00397 }
00398
00399 if (STREQ(type, "YCbCr"))
00400 {
00401 this->type = BINARY_IMAGE;
00402 image.size = common.size;
00403 image.width = p2;
00404 image.height = p3;
00405 image.imageFormat = IMAGE_YCbCr;
00406 return p;
00407 }
00408
00409 if (STREQ(type, "rgb"))
00410 {
00411 this->type = BINARY_IMAGE;
00412 image.size = common.size;
00413 image.width = p2;
00414 image.height = p3;
00415 image.imageFormat = IMAGE_RGB;
00416 return p;
00417 }
00418
00419 if (STREQ(type, "raw"))
00420 {
00421 this->type = BINARY_SOUND;
00422 sound.soundFormat = SOUND_RAW;
00423 sound.size = common.size;
00424 sound.channels = p2;
00425 sound.rate = p3;
00426 sound.sampleSize = p4;
00427 sound.sampleFormat = (USoundSampleFormat) p5;
00428 return p;
00429 }
00430
00431 if (STREQ(type, "wav"))
00432 {
00433 this->type = BINARY_SOUND;
00434 sound.soundFormat = SOUND_WAV;
00435 sound.size = common.size;
00436 sound.channels = p2;
00437 sound.rate = p3;
00438 sound.sampleSize = p4;
00439 sound.sampleFormat = (USoundSampleFormat) p5;
00440 return p;
00441 }
00442
00443
00444 this->type = BINARY_UNKNOWN;
00445 return p;
00446 }
00447
00448 void UBinary::buildMessage()
00449 {
00450 message = getMessage();
00451 }
00452
00453 std::string UBinary::getMessage() const
00454 {
00455 std::ostringstream o;
00456 switch (type)
00457 {
00458 case BINARY_IMAGE:
00459 o << image.format_string()
00460 << ' ' << image.width << ' ' << image.height;
00461 break;
00462
00463 case BINARY_SOUND:
00464 o << sound.format_string()
00465 << ' ' << sound.channels
00466 << ' ' << sound.rate
00467 << ' ' << sound.sampleSize
00468 << ' ' << sound.sampleFormat;
00469 break;
00470
00471 case BINARY_UNKNOWN:
00472 o << message;
00473 break;
00474
00475 case BINARY_NONE:
00476 abort();
00477 }
00478 return o.str();
00479 }
00480
00481
00482
00483
00484
00486 UValue::UValue()
00487 : type(DATA_VOID), val (0), storage(0)
00488 {}
00489
00490
00491 UValue::UValue(ufloat v)
00492 : type(DATA_DOUBLE), val(v)
00493 {}
00494
00495 UValue::UValue(int v)
00496 : type(DATA_DOUBLE), val(v)
00497 {}
00498 UValue::UValue(unsigned int v)
00499 : type(DATA_DOUBLE), val(v)
00500 {}
00501 UValue::UValue(long v)
00502 : type(DATA_DOUBLE), val(v)
00503 {}
00504 UValue::UValue(unsigned long v)
00505 : type(DATA_DOUBLE), val(v)
00506 {}
00507
00508 UValue::UValue(void* v)
00509 : type(DATA_STRING)
00510 {
00511 std::ostringstream i;
00512 i << "%ptr_" << (unsigned long) v;
00513 stringValue = new std::string(i.str());
00514 }
00515 UValue::UValue(char* v)
00516 : type(DATA_STRING), stringValue(new std::string(v))
00517 {}
00518
00519 UValue::UValue(const std::string& v)
00520 : type(DATA_STRING), stringValue(new std::string(v))
00521 {}
00522
00523 UValue::UValue(const UBinary& b)
00524 : type(DATA_BINARY)
00525 {
00526 binary = new UBinary(b);
00527 }
00528
00529 UValue::UValue(const USound& s)
00530 : type(DATA_BINARY)
00531 {
00532 binary = new UBinary(s);
00533 }
00534
00535 UValue::UValue(const UImage& s)
00536 : type(DATA_BINARY)
00537 {
00538 binary = new UBinary(s);
00539 }
00540
00541 UValue::UValue(const UList& l)
00542 : type(DATA_LIST)
00543 {
00544 list = new UList(l);
00545 }
00546
00547 UValue::UValue(const UObjectStruct& o)
00548 : type(DATA_OBJECT)
00549 {
00550 object = new UObjectStruct(o);
00551 }
00552
00553 UValue::~UValue()
00554 {
00555 switch(type)
00556 {
00557 case DATA_STRING:
00558 delete stringValue;
00559 break;
00560 case DATA_BINARY:
00561 delete binary;
00562 break;
00563 case DATA_LIST:
00564 delete list;
00565 break;
00566 case DATA_OBJECT:
00567 delete object;
00568 break;
00569 case DATA_DOUBLE:
00570 case DATA_VOID:
00571 break;
00572 }
00573 }
00574
00575 UValue::operator ufloat () const
00576 {
00577 switch (type)
00578 {
00579 case DATA_DOUBLE:
00580 return val;
00581
00582 case DATA_STRING:
00583 {
00584 std::istringstream tstr(*stringValue);
00585 ufloat v;
00586 tstr >> v;
00587 return v;
00588 }
00589 break;
00590
00591 case DATA_BINARY:
00592 case DATA_LIST:
00593 case DATA_OBJECT:
00594 case DATA_VOID:
00595 break;
00596 }
00597
00598 return ufloat(0);
00599 }
00600
00601
00602 UValue::operator std::string() const
00603 {
00604 switch (type)
00605 {
00606 case DATA_DOUBLE:
00607 {
00608 std::ostringstream tstr;
00609 tstr << val;
00610 return tstr.str();
00611 }
00612 break;
00613 case DATA_STRING:
00614 return *stringValue;
00615 break;
00616 default:
00617 return std::string("invalid");
00618 }
00619 }
00620
00621 UValue::operator
00622 UBinary() const
00623 {
00624 if (type != DATA_BINARY)
00625 return UBinary();
00626 else
00627 return *binary;
00628 }
00629
00630 UValue::operator UImage() const
00631 {
00632 if (type != DATA_BINARY
00633 || binary->type != BINARY_IMAGE)
00634 {
00635 UImage i;
00636 i.data = 0;
00637 i.size = i.width = i.height = 0;
00638 i.imageFormat = IMAGE_UNKNOWN;
00639 return i;
00640 }
00641 else
00642 return binary->image;
00643 }
00644
00645 UValue::operator USound() const
00646 {
00647 if (type != DATA_BINARY || binary->type != BINARY_SOUND)
00648 {
00649 USound i;
00650 i.data = 0;
00651 i.size = i.sampleSize = i.channels = i.rate = 0;
00652 i.soundFormat = SOUND_UNKNOWN;
00653 i.sampleFormat = SAMPLE_UNSIGNED;
00654 return i;
00655 }
00656 else
00657 return binary->sound;
00658 }
00659
00660 UValue::operator UList() const
00661 {
00662 if (type != DATA_LIST)
00663 return UList();
00664 return UList(*list);
00665 }
00666
00667 UValue& UValue::operator= (const UValue& v)
00668 {
00669
00670 if (this == &v)
00671 return *this;
00672 switch (type)
00673 {
00674 case DATA_STRING:
00675 delete stringValue;
00676 break;
00677 case DATA_BINARY:
00678 delete binary;
00679 break;
00680 case DATA_LIST:
00681 delete list;
00682 break;
00683 case DATA_OBJECT:
00684 delete object;
00685 case DATA_DOUBLE:
00686 case DATA_VOID:
00687 break;
00688 }
00689
00690 type = v.type;
00691 switch (type)
00692 {
00693 case DATA_DOUBLE:
00694 val = v.val;
00695 break;
00696 case DATA_STRING:
00697 stringValue = new std::string(*v.stringValue);
00698 break;
00699 case DATA_BINARY:
00700 binary = new UBinary(*v.binary);
00701 break;
00702 case DATA_LIST:
00703 list = new UList(*v.list);
00704 break;
00705 case DATA_OBJECT:
00706 object = new UObjectStruct(*v.object);
00707 break;
00708 case DATA_VOID:
00709 break;
00710 }
00711 return *this;
00712 }
00713
00714
00715 UValue::UValue(const UValue& v)
00716 {
00717 type = DATA_VOID;
00718 *this = v;
00719 }
00720
00721
00722
00723
00724
00725 UBinary::UBinary()
00726 {
00727 common.data = 0;
00728 common.size = 0;
00729 type = BINARY_NONE;
00730 }
00731
00732 UBinary::~UBinary()
00733 {
00734 if (common.data)
00735 free(common.data);
00736 }
00737
00738 UBinary::UBinary(const UBinary& b)
00739 {
00740 type = BINARY_NONE;
00741 common.data = 0;
00742 *this = b;
00743 }
00744
00745 UBinary::UBinary(const UImage& i)
00746 {
00747 type = BINARY_IMAGE;
00748 image = i;
00749 image.data = static_cast<unsigned char*> (malloc (image.size));
00750 memcpy(image.data, i.data, image.size);
00751 }
00752
00753 UBinary::UBinary(const USound& i)
00754 {
00755 type = BINARY_SOUND;
00756 sound = i;
00757 sound.data = static_cast<char*> (malloc (sound.size));
00758 memcpy(sound.data, i.data, sound.size);
00759 }
00760
00761 UBinary& UBinary::operator= (const UBinary& b)
00762 {
00763 if (this == &b)
00764 return *this;
00765
00766 free(common.data);
00767
00768 type = b.type;
00769 message = b.message;
00770 common.size = b.common.size;
00771 switch(type)
00772 {
00773 case BINARY_IMAGE:
00774 image = b.image;
00775 break;
00776 case BINARY_SOUND:
00777 sound = b.sound;
00778 break;
00779 case BINARY_NONE:
00780 case BINARY_UNKNOWN:
00781 break;
00782 }
00783 common.data = malloc(common.size);
00784 memcpy(common.data, b.common.data, b.common.size);
00785 return *this;
00786 }
00787
00788
00789
00790
00791
00792
00793 UList::UList()
00794 : offset(0)
00795 {}
00796
00797 UList::UList(const UList& b)
00798 : offset(0)
00799 {
00800 *this = b;
00801 }
00802
00803 UList& UList::operator= (const UList& b)
00804 {
00805 if (this == &b)
00806 return *this;
00807
00808 offset = 0;
00809 for (int i = 0; i < size(); ++i)
00810 delete array[i];
00811 array.clear();
00812
00813 for (std::vector<UValue*>::const_iterator it = b.array.begin();
00814 it !=b.array.end();
00815 ++it)
00816 array.push_back(new UValue(**it));
00817 offset = b.offset;
00818
00819 return *this;
00820 }
00821
00822 UList::~UList()
00823 {
00824 offset = 0;
00825 for (int i = 0; i < size(); ++i)
00826 delete array[i];
00827 array.clear();
00828 }
00829
00830
00831
00832
00833
00834
00835 UObjectStruct::UObjectStruct()
00836 {}
00837
00838 UObjectStruct::UObjectStruct(const UObjectStruct& b)
00839 {
00840 *this = b;
00841 }
00842
00843 UObjectStruct& UObjectStruct::operator= (const UObjectStruct& b)
00844 {
00845 if (this == &b)
00846 return *this;
00847
00848 for (int i = 0; i < size(); ++i)
00849 delete array[i].val;
00850 array.clear();
00851
00852 for (std::vector<UNamedValue>::const_iterator it = b.array.begin();
00853 it != b.array.end();
00854 ++it)
00855 array.push_back(UNamedValue(it->name, new UValue(*(it->val))));
00856
00857 return *this;
00858 }
00859
00860 UObjectStruct::~UObjectStruct()
00861 {
00862 for (int i = 0; i < size(); ++i)
00863 delete array[i].val;
00864 array.clear();
00865 }
00866
00867
00868
00869
00870
00871
00872 UValue& UObjectStruct::operator[] (const std::string& s)
00873 {
00874 for (int i = 0; i < size(); ++i)
00875 if (array[i].name == s)
00876 return *array[i].val;
00877 static UValue n;
00878 return n;
00879 }
00880
00881
00882
00883
00884
00885 void
00886 UVar::operator= (const UValue& v)
00887 {
00888 switch (v.type)
00889 {
00890 case DATA_STRING:
00891 *this = *v.stringValue;
00892 break;
00893 case DATA_BINARY:
00894 *this = *v.binary;
00895 break;
00896 case DATA_LIST:
00897 *this = *v.list;
00898 break;
00899 case DATA_DOUBLE:
00900 *this = v.val;
00901 break;
00902 case DATA_VOID:
00903
00904 abort ();
00905 break;
00906 case DATA_OBJECT:
00907
00908 abort ();
00909 break;
00910 }
00911 }
00912
00913 }