uvalue-common.cc

Go to the documentation of this file.
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   | UValue Parsing.  |
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   | UValue.  |
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       //string
00108       type = DATA_STRING;
00109       //get terminating '"'
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; //parse error
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       //list message
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         //expect , or rbracket
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     //OBJ a [x:12, y:4]
00161     if (!strncmp(message + pos, "OBJ ", 4))
00162     {
00163       //obj message
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; //empty object
00180         //parse name
00181         int p = pos;
00182         while (message[p] && message[p] != ':')
00183           ++p;
00184         if (!message[p])
00185           return -p; //parse error
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         //expect , or rbracket
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       //void
00217       type = DATA_VOID;
00218       pos += 4;
00219       return pos;
00220     }
00221 
00222     if (!strncmp(message + pos, "BIN ", 4))
00223     {
00224       //binary message: delegate
00225       type = DATA_BINARY;
00226       binary = new UBinary();
00227       pos += 4;
00228       //parsing type
00229       int p = binary->parse(message, pos, bins, binpos);
00230       return p;
00231     }
00232 
00233     //last attempt: double
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   | USound.  |
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     // To pacify "warning: control reaches end of non-void function".
00315     abort();
00316   }
00317 
00318   /*---------.
00319   | UImage.  |
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     // To pacify "warning: control reaches end of non-void function".
00338     abort();
00339   }
00340 
00341   /*----------.
00342   | UBinary.  |
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     //find end of header
00353 
00354     if (binpos == bins.end()) //no binary data available
00355       return -1;
00356 
00357     //validate size
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; //parse error
00379     this->message = std::string(message + pos, p - pos);
00380     ++p;
00381 
00382     //trying to parse header to find type
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     //DEBUG fprintf(stderr, "%s:         %d %s %d %d\n", message, p1, type, p2, p3);
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     //unknown binary
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   | UValue.  |
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     // TODO: optimize
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   | UBinary.  |
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   | UList.  |
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) //relax, its a vector
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) //relax, its a vector
00826       delete array[i];
00827     array.clear();
00828   }
00829 
00830 
00831   /*----------------.
00832   | UObjectStruct.  |
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) // Relax, it's a vector.
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) //relax, it's a vector
00863       delete array[i].val;
00864     array.clear();
00865   }
00866 
00867 
00868   /*---------.
00869   | UValue.  |
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; // Gni?
00879   }
00880 
00881   /*-------.
00882   | UVar.  |
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         //TODO: do something!
00904         abort ();
00905         break;
00906       case DATA_OBJECT:
00907         // Not valid currently.
00908         abort ();
00909         break;
00910     }
00911   }
00912 
00913 } // namespace urbi

Generated on Tue Apr 10 17:45:45 2007 for URBISDK by  doxygen 1.5.1