llsdserialize.cpp

Go to the documentation of this file.
00001 
00034 #include "linden_common.h"
00035 #include "llsdserialize.h"
00036 #include "llmemory.h"
00037 #include "llstreamtools.h" // for fullread
00038 
00039 #include <iostream>
00040 #include "apr-1/apr_base64.h"
00041 
00042 #if !LL_WINDOWS
00043 #include <netinet/in.h> // htonl & ntohl
00044 #endif
00045 
00046 #include "lldate.h"
00047 #include "llsd.h"
00048 #include "lluri.h"
00049 
00050 // File constants
00051 static const int MAX_HDR_LEN = 20;
00052 static const char LEGACY_NON_HEADER[] = "<llsd>";
00053 
00054 //static
00055 const char* LLSDSerialize::LLSDBinaryHeader = "LLSD/Binary";
00056 
00057 //static
00058 const char* LLSDSerialize::LLSDXMLHeader =    "LLSD/XML";
00059 
00060 // virtual
00061 LLSDParser::~LLSDParser()
00062 { }
00063 
00064 // virtual
00065 LLSDNotationParser::~LLSDNotationParser()
00066 { }
00067 
00068 
00069 // static
00070 void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
00071 {
00072         LLPointer<LLSDFormatter> f = NULL;
00073 
00074         switch (type)
00075         {
00076         case LLSD_BINARY:
00077                 str << "<? " << LLSDBinaryHeader << " ?>\n";
00078                 f = new LLSDBinaryFormatter;
00079                 break;
00080 
00081         case LLSD_XML:
00082                 str << "<? " << LLSDXMLHeader << " ?>\n";
00083                 f = new LLSDXMLFormatter;
00084                 break;
00085 
00086         default:
00087                 llwarns << "serialize request for unkown ELLSD_Serialize" << llendl;
00088         }
00089 
00090         if (f.notNull())
00091         {
00092                 f->format(sd, str, options);
00093         }
00094 }
00095 
00096 // static
00097 bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
00098 {
00099         LLPointer<LLSDParser> p = NULL;
00100         char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
00101         int i;
00102         int inbuf = 0;
00103         bool legacy_no_header = false;
00104         bool fail_if_not_legacy = false;
00105         std::string header = "";
00106         
00107         /*
00108          * Get the first line before anything.
00109          */
00110         str.get(hdr_buf, MAX_HDR_LEN, '\n');
00111         if (str.fail())
00112         {
00113                 str.clear();
00114                 fail_if_not_legacy = true;
00115         }
00116 
00117         if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
00118         {
00119                 legacy_no_header = true;
00120                 inbuf = str.gcount();
00121         }
00122         else
00123         {
00124                 if (fail_if_not_legacy)
00125                         goto fail;
00126                 /*
00127                 * Remove the newline chars
00128                 */
00129                 for (i = 0; i < MAX_HDR_LEN; i++)
00130                 {
00131                         if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
00132                                 hdr_buf[i] == '\n')
00133                         {
00134                                 hdr_buf[i] = 0;
00135                                 break;
00136                         }
00137                 }
00138                 header = hdr_buf;
00139 
00140                 std::string::size_type start = std::string::npos;
00141                 std::string::size_type end = std::string::npos;
00142                 start = header.find_first_not_of("<? ");
00143                 if (start != std::string::npos)
00144                 {
00145                         end = header.find_first_of(" ?", start);
00146                 }
00147                 if ((start == std::string::npos) || (end == std::string::npos))
00148                         goto fail;
00149 
00150                 header = header.substr(start, end - start);
00151                 ws(str);
00152         }
00153         /*
00154          * Create the parser as appropriate
00155          */
00156         if (legacy_no_header)
00157         {
00158                 LLSDXMLParser *x = new LLSDXMLParser;
00159                 x->parsePart(hdr_buf, inbuf);
00160                 p = x;
00161         }
00162         else if (header == LLSDBinaryHeader)
00163         {
00164                 p = new LLSDBinaryParser;
00165         }
00166         else if (header == LLSDXMLHeader)
00167         {
00168                 p = new LLSDXMLParser;
00169         }
00170         else
00171         {
00172                 llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
00173         }
00174 
00175         if (p.notNull())
00176         {
00177                 p->parse(str, sd);
00178                 return true;
00179         }
00180 
00181 fail:
00182         llwarns << "deserialize LLSD parse failure" << llendl;
00183         return false;
00184 }
00185 
00189 #if LL_BIG_ENDIAN
00190 U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
00191 U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
00192 F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
00193 F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
00194 #else
00195 // I read some comments one a indicating that doing an integer add
00196 // here would be faster than a bitwise or. For now, the or has
00197 // programmer clarity, since the intended outcome matches the
00198 // operation.
00199 U64 ll_htonll(U64 hostlonglong)
00200 {
00201         return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
00202                         ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
00203 }
00204 U64 ll_ntohll(U64 netlonglong)
00205 {
00206         return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
00207                         ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
00208 }
00209 union LLEndianSwapper
00210 {
00211         F64 d;
00212         U64 i;
00213 };
00214 F64 ll_htond(F64 hostdouble)
00215 {
00216         LLEndianSwapper tmp;
00217         tmp.d = hostdouble;
00218         tmp.i = ll_htonll(tmp.i);
00219         return tmp.d;
00220 }
00221 F64 ll_ntohd(F64 netdouble)
00222 {
00223         LLEndianSwapper tmp;
00224         tmp.d = netdouble;
00225         tmp.i = ll_ntohll(tmp.i);
00226         return tmp.d;
00227 }
00228 #endif
00229 
00233 bool deserialize_string(std::istream& str, std::string& value);
00234 bool deserialize_string_delim(std::istream& str, std::string& value, char d);
00235 bool deserialize_string_raw(std::istream& str, std::string& value);
00236 void serialize_string(const std::string& value, std::ostream& str);
00237 
00241 static const std::string NOTATION_TRUE_SERIAL("true");
00242 static const std::string NOTATION_FALSE_SERIAL("false");
00243 
00244 static const char BINARY_TRUE_SERIAL = '1';
00245 static const char BINARY_FALSE_SERIAL = '0';
00246 
00247 static const S32 NOTATION_PARSE_FAILURE = -1;
00248 
00252 LLSDParser::LLSDParser()
00253 {
00254 }
00255 
00259 // virtual
00260 S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
00261 {
00262         // map: { string:object, string:object }
00263         // array: [ object, object, object ]
00264         // undef: !
00265         // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
00266         // integer: i####
00267         // real: r####
00268         // uuid: u####
00269         // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
00270         // uri: l"escaped"
00271         // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
00272         // binary: b##"ff3120ab1" | b(size)"raw data"
00273         char c;
00274         c = istr.peek();
00275         while(isspace(c))
00276         {
00277                 // pop the whitespace.
00278                 c = istr.get();
00279                 c = istr.peek();
00280                 continue;
00281         }
00282         if(!istr.good())
00283         {
00284                 return 0;
00285         }
00286         S32 parse_count = 1;
00287         switch(c)
00288         {
00289         case '{':
00290                 parse_count += parseMap(istr, data);
00291                 if(istr.fail())
00292                 {
00293                         llinfos << "STREAM FAILURE reading map." << llendl;
00294                 }
00295                 if(data.isUndefined())
00296                 {
00297                         parse_count = NOTATION_PARSE_FAILURE;
00298                 }
00299                 break;
00300 
00301         case '[':
00302                 parse_count += parseArray(istr, data);
00303                 if(istr.fail())
00304                 {
00305                         llinfos << "STREAM FAILURE reading array." << llendl;
00306                 }
00307                 if(data.isUndefined())
00308                 {
00309                         parse_count = NOTATION_PARSE_FAILURE;
00310                 }
00311                 break;
00312 
00313         case '!':
00314                 c = istr.get();
00315                 data.clear();
00316                 break;
00317 
00318         case '0':
00319                 c = istr.get();
00320                 data = false;
00321                 break;
00322 
00323         case 'F':
00324         case 'f':
00325                 do
00326                 {
00327                         istr.ignore();
00328                         c = istr.peek();
00329                 } while (isalpha(c));
00330                 data = false;
00331                 if(istr.fail())
00332                 {
00333                         llinfos << "STREAM FAILURE reading boolean." << llendl;
00334                 }
00335                 break;
00336 
00337         case '1':
00338                 c = istr.get();
00339                 data = true;
00340                 break;
00341 
00342         case 'T':
00343         case 't':
00344                 do
00345                 {
00346                         istr.ignore();
00347                         c = istr.peek();
00348                 } while (isalpha(c));
00349                 data = true;
00350                 if(istr.fail())
00351                 {
00352                         llinfos << "STREAM FAILURE reading boolean." << llendl;
00353                 }
00354                 break;
00355 
00356         case 'i':
00357         {
00358                 c = istr.get();
00359                 S32 integer = 0;
00360                 istr >> integer;
00361                 data = integer;
00362                 if(istr.fail())
00363                 {
00364                         llinfos << "STREAM FAILURE reading integer." << llendl;
00365                 }
00366                 break;
00367         }
00368 
00369         case 'r':
00370         {
00371                 c = istr.get();
00372                 F64 real = 0.0;
00373                 istr >> real;
00374                 data = real;
00375                 if(istr.fail())
00376                 {
00377                         llinfos << "STREAM FAILURE reading real." << llendl;
00378                 }
00379                 break;
00380         }
00381 
00382         case 'u':
00383         {
00384                 c = istr.get();
00385                 LLUUID id;
00386                 istr >> id;
00387                 data = id;
00388                 if(istr.fail())
00389                 {
00390                         llinfos << "STREAM FAILURE reading uuid." << llendl;
00391                 }
00392                 break;
00393         }
00394 
00395         case '\"':
00396         case '\'':
00397         case 's':
00398                 parseString(istr, data);
00399                 if(istr.fail())
00400                 {
00401                         llinfos << "STREAM FAILURE reading string." << llendl;
00402                 }
00403                 if(data.isUndefined())
00404                 {
00405                         parse_count = NOTATION_PARSE_FAILURE;
00406                 }
00407                 break;
00408 
00409         case 'l':
00410         {
00411                 c = istr.get(); // pop the 'l'
00412                 c = istr.get(); // pop the delimiter
00413                 std::string str;
00414                 deserialize_string_delim(istr, str, c);
00415                 data = LLURI(str);
00416                 if(istr.fail())
00417                 {
00418                         llinfos << "STREAM FAILURE reading link." << llendl;
00419                 }
00420                 break;
00421         }
00422 
00423         case 'd':
00424         {
00425                 c = istr.get(); // pop the 'd'
00426                 c = istr.get(); // pop the delimiter
00427                 std::string str;
00428                 deserialize_string_delim(istr, str, c);
00429                 data = LLDate(str);
00430                 if(istr.fail())
00431                 {
00432                         llinfos << "STREAM FAILURE reading date." << llendl;
00433                 }
00434                 break;
00435         }
00436 
00437         case 'b':
00438                 parseBinary(istr, data);
00439                 if(istr.fail())
00440                 {
00441                         llinfos << "STREAM FAILURE reading data." << llendl;
00442                 }
00443                 if(data.isUndefined())
00444                 {
00445                         parse_count = NOTATION_PARSE_FAILURE;
00446                 }
00447                 break;
00448 
00449         default:
00450                 data.clear();
00451                 parse_count = NOTATION_PARSE_FAILURE;
00452                 llinfos << "Unrecognized character while parsing: int(" << (int)c
00453                                 << ")" << llendl;
00454                 break;
00455         }
00456         return parse_count;
00457 }
00458 
00459 // static
00460 LLSD LLSDNotationParser::parse(std::istream& istr)
00461 {
00462         LLSDNotationParser parser;
00463         LLSD rv;
00464         S32 count = parser.parse(istr, rv);
00465         lldebugs << "LLSDNotationParser::parse parsed " << count << " objects."
00466                  << llendl;
00467         return rv;
00468 }
00469 
00470 S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
00471 {
00472         // map: { string:object, string:object }
00473         map = LLSD::emptyMap();
00474         S32 parse_count = 0;
00475         char c = istr.get();
00476         if(c == '{')
00477         {
00478                 // eat commas, white
00479                 bool found_name = false;
00480                 std::string name;
00481                 c = istr.get();
00482                 while(c != '}' && istr.good())
00483                 {
00484                         if(!found_name)
00485                         {
00486                                 if((c == '\"') || (c == '\'') || (c == 's'))
00487                                 {
00488                                         istr.putback(c);
00489                                         found_name = true;
00490                                         deserialize_string(istr, name);
00491                                 }
00492                                 c = istr.get();
00493                         }
00494                         else
00495                         {
00496                                 if(isspace(c) || (c == ':'))
00497                                 {
00498                                         c = istr.get();
00499                                         continue;
00500                                 }
00501                                 istr.putback(c);
00502                                 LLSD child;
00503                                 S32 count = parse(istr, child);
00504                                 if(count > 0)
00505                                 {
00506                                         parse_count += count;
00507                                         map.insert(name, child);
00508                                 }
00509                                 else
00510                                 {
00511                                         map.clear();
00512                                         return NOTATION_PARSE_FAILURE;
00513                                 }
00514                                 found_name = false;
00515                                 c = istr.get();
00516                         }
00517                 }
00518         }
00519         return parse_count;
00520 }
00521 
00522 S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
00523 {
00524         // array: [ object, object, object ]
00525         array = LLSD::emptyArray();
00526         S32 parse_count = 0;
00527         char c = istr.get();
00528         if(c == '[')
00529         {
00530                 // eat commas, white
00531                 c = istr.get();
00532                 while((c != ']') && istr.good())
00533                 {
00534                         LLSD child;
00535                         if(isspace(c) || (c == ','))
00536                         {
00537                                 c = istr.get();
00538                                 continue;
00539                         }
00540                         istr.putback(c);
00541                         S32 count = parse(istr, child);
00542                         if(count > 0)
00543                         {
00544                                 parse_count += count;
00545                                 array.append(child);
00546                         }
00547                         else
00548                         {
00549                                 array.clear();
00550                                 return NOTATION_PARSE_FAILURE;
00551                         }
00552                         c = istr.get();
00553                 }
00554         }
00555         return parse_count;
00556 }
00557 
00558 void LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
00559 {
00560         std::string value;
00561         if(deserialize_string(istr, value))
00562         {
00563                 data = value;
00564         }
00565         else
00566         {
00567                 // failed to parse.
00568                 data.clear();
00569         }
00570 }
00571 
00572 void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
00573 {
00574         // binary: b##"ff3120ab1"
00575         // or: b(len)"..."
00576 
00577         // I want to manually control those values here to make sure the
00578         // parser doesn't break when someone changes a constant somewhere
00579         // else.
00580         const U32 BINARY_BUFFER_SIZE = 256;
00581         const U32 STREAM_GET_COUNT = 255;
00582 
00583         // need to read the base out.
00584         char buf[BINARY_BUFFER_SIZE];           /* Flawfinder: ignore */
00585         istr.get(buf, STREAM_GET_COUNT, '"');
00586         char c = istr.get();
00587         if((c == '"') && (0 == strncmp("b(", buf, 2)))
00588         {
00589                 // We probably have a valid raw binary stream. determine
00590                 // the size, and read it.
00591                 // *FIX: Should we set a maximum size?
00592                 S32 len = strtol(buf + 2, NULL, 0);
00593                 std::vector<U8> value;
00594                 if(len)
00595                 {
00596                         value.resize(len);
00597                         fullread(istr, (char *)&value[0], len);
00598                 }
00599                 c = istr.get(); // strip off the trailing double-quote
00600                 data = value;
00601         }
00602         else if((c == '"') && (0 == strncmp("b64", buf, 3)))
00603         {
00604                 // *FIX: A bit inefficient, but works for now. To make the
00605                 // format better, I would need to add a hint into the
00606                 // serialization format that indicated how long it was.
00607                 std::stringstream coded_stream;
00608                 istr.get(*(coded_stream.rdbuf()), '\"');
00609                 c = istr.get();
00610                 std::string encoded(coded_stream.str());
00611                 S32 len = apr_base64_decode_len(encoded.c_str());
00612                 std::vector<U8> value;
00613                 value.resize(len);
00614                 len = apr_base64_decode_binary(&value[0], encoded.c_str());
00615                 value.resize(len);
00616                 data = value;
00617         }
00618         else if((c == '"') && (0 == strncmp("b16", buf, 3)))
00619         {
00620                 // yay, base 16. We pop the next character which is either a
00621                 // double quote or base 16 data. If it's a double quote, we're
00622                 // done parsing. If it's not, put the data back, and read the
00623                 // stream until the next double quote.
00624                 char* read;      /*Flawfinder: ignore*/
00625                 U8 byte;
00626                 U8 byte_buffer[BINARY_BUFFER_SIZE];
00627                 U8* write;
00628                 std::vector<U8> value;
00629                 c = istr.get();
00630                 while(c != '"')
00631                 {
00632                         istr.putback(c);
00633                         read = buf;
00634                         write = byte_buffer;
00635                         istr.get(buf, STREAM_GET_COUNT, '"');
00636                         c = istr.get();
00637                         while(*read != '\0')     /*Flawfinder: ignore*/
00638                         {
00639                                 byte = hex_as_nybble(*read++);
00640                                 byte = byte << 4;
00641                                 byte |= hex_as_nybble(*read++);
00642                                 *write++ = byte;
00643                         }
00644                         // copy the data out of the byte buffer
00645                         value.insert(value.end(), byte_buffer, write);
00646                 }
00647                 data = value;
00648         }
00649         else
00650         {
00651                 data.clear();
00652         }
00653 }
00654 
00655 
00659 LLSDBinaryParser::LLSDBinaryParser()
00660 {
00661 }
00662 
00663 // virtual
00664 LLSDBinaryParser::~LLSDBinaryParser()
00665 {
00666 }
00667 
00668 // virtual
00669 S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
00670 {
00687         char c;
00688         c = istr.get();
00689         if(!istr.good())
00690         {
00691                 return 0;
00692         }
00693         S32 parse_count = 1;
00694         switch(c)
00695         {
00696         case '{':
00697                 parse_count += parseMap(istr, data);
00698                 if(istr.fail())
00699                 {
00700                         llinfos << "STREAM FAILURE reading binary map." << llendl;
00701                 }
00702                 break;
00703 
00704         case '[':
00705                 parse_count += parseArray(istr, data);
00706                 if(istr.fail())
00707                 {
00708                         llinfos << "STREAM FAILURE reading binary array." << llendl;
00709                 }
00710                 break;
00711 
00712         case '!':
00713                 data.clear();
00714                 break;
00715 
00716         case '0':
00717                 data = false;
00718                 break;
00719 
00720         case '1':
00721                 data = true;
00722                 break;
00723 
00724         case 'i':
00725         {
00726                 U32 value_nbo = 0;
00727                 istr.read((char*)&value_nbo, sizeof(U32));       /*Flawfinder: ignore*/
00728                 data = (S32)ntohl(value_nbo);
00729                 if(istr.fail())
00730                 {
00731                         llinfos << "STREAM FAILURE reading binary integer." << llendl;
00732                 }
00733                 break;
00734         }
00735 
00736         case 'r':
00737         {
00738                 F64 real_nbo = 0.0;
00739                 istr.read((char*)&real_nbo, sizeof(F64));        /*Flawfinder: ignore*/
00740                 data = ll_ntohd(real_nbo);
00741                 if(istr.fail())
00742                 {
00743                         llinfos << "STREAM FAILURE reading binary real." << llendl;
00744                 }
00745                 break;
00746         }
00747 
00748         case 'u':
00749         {
00750                 LLUUID id;
00751                 istr.read((char*)(&id.mData), UUID_BYTES);       /*Flawfinder: ignore*/
00752                 data = id;
00753                 if(istr.fail())
00754                 {
00755                         llinfos << "STREAM FAILURE reading binary uuid." << llendl;
00756                 }
00757                 break;
00758         }
00759 
00760         case '\'':
00761         case '"':
00762         {
00763                 std::string value;
00764                 deserialize_string_delim(istr, value, c);
00765                 data = value;
00766                 break;
00767         }
00768 
00769         case 's':
00770         {
00771                 std::string value;
00772                 parseString(istr, value);
00773                 data = value;
00774                 if(istr.fail())
00775                 {
00776                         llinfos << "STREAM FAILURE reading binary string." << llendl;
00777                 }
00778                 break;
00779         }
00780 
00781         case 'l':
00782         {
00783                 std::string value;
00784                 parseString(istr, value);
00785                 data = LLURI(value);
00786                 if(istr.fail())
00787                 {
00788                         llinfos << "STREAM FAILURE reading binary link." << llendl;
00789                 }
00790                 break;
00791         }
00792 
00793         case 'd':
00794         {
00795                 F64 real = 0.0;
00796                 istr.read((char*)&real, sizeof(F64));    /*Flawfinder: ignore*/
00797                 data = LLDate(real);
00798                 if(istr.fail())
00799                 {
00800                         llinfos << "STREAM FAILURE reading binary date." << llendl;
00801                 }
00802                 break;
00803         }
00804 
00805         case 'b':
00806         {
00807                 // We probably have a valid raw binary stream. determine
00808                 // the size, and read it.
00809                 // *FIX: Should we set a maximum size?
00810                 U32 size_nbo = 0;
00811                 istr.read((char*)&size_nbo, sizeof(U32));       /*Flawfinder: ignore*/
00812                 S32 size = (S32)ntohl(size_nbo);
00813                 std::vector<U8> value;
00814                 if(size)
00815                 {
00816                         value.resize(size);
00817                         istr.read((char*)&value[0], size);               /*Flawfinder: ignore*/
00818                 }
00819                 data = value;
00820                 if(istr.fail())
00821                 {
00822                         llinfos << "STREAM FAILURE reading binary." << llendl;
00823                 }
00824                 break;
00825         }
00826 
00827         default:
00828                 --parse_count;
00829                 llinfos << "Unrecognized character while parsing: int(" << (int)c
00830                                 << ")" << llendl;
00831                 break;
00832         }
00833         return parse_count;
00834 }
00835 
00836 // static
00837 LLSD LLSDBinaryParser::parse(std::istream& istr)
00838 {
00839         LLSDBinaryParser parser;
00840         LLSD rv;
00841         S32 count = parser.parse(istr, rv);
00842         lldebugs << "LLSDBinaryParser::parse parsed " << count << " objects."
00843                  << llendl;
00844         return rv;
00845 }
00846 
00847 S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
00848 {
00849         map = LLSD::emptyMap();
00850         U32 value_nbo = 0;
00851         istr.read((char*)&value_nbo, sizeof(U32));               /*Flawfinder: ignore*/
00852         S32 size = (S32)ntohl(value_nbo);
00853         S32 parse_count = 0;
00854         S32 count = 0;
00855         char c = istr.get();
00856         while(c != '}' && (count < size) && istr.good())
00857         {
00858                 std::string name;
00859                 switch(c)
00860                 {
00861                 case 'k':
00862                         parseString(istr, name);
00863                         break;
00864                 case '\'':
00865                 case '"':
00866                         deserialize_string_delim(istr, name, c);
00867                         break;
00868                 }
00869                 LLSD child;
00870                 S32 child_count = parse(istr, child);
00871                 if(child_count)
00872                 {
00873                         parse_count += child_count;
00874                         map.insert(name, child);
00875                 }
00876                 ++count;
00877                 c = istr.get();
00878         }
00879         return parse_count;
00880 }
00881 
00882 S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
00883 {
00884         array = LLSD::emptyArray();
00885         U32 value_nbo = 0;
00886         istr.read((char*)&value_nbo, sizeof(U32));               /*Flawfinder: ignore*/
00887         S32 size = (S32)ntohl(value_nbo);
00888 
00889         // *FIX: This would be a good place to reserve some space in the
00890         // array...
00891 
00892         S32 parse_count = 0;
00893         S32 count = 0;
00894         char c = istr.peek();
00895         while((c != ']') && (count < size) && istr.good())
00896         {
00897                 LLSD child;
00898                 S32 child_count = parse(istr, child);
00899                 if(child_count)
00900                 {
00901                         parse_count += child_count;
00902                         array.append(child);
00903                 }
00904                 ++count;
00905                 c = istr.peek();
00906         }
00907         c = istr.get();
00908         return parse_count;
00909 }
00910 
00911 void LLSDBinaryParser::parseString(
00912         std::istream& istr,
00913         std::string& value) const
00914 {
00915         // *FIX: This is memory inefficient.
00916         U32 value_nbo = 0;
00917         istr.read((char*)&value_nbo, sizeof(U32));               /*Flawfinder: ignore*/
00918         S32 size = (S32)ntohl(value_nbo);
00919         std::vector<char> buf;
00920         buf.resize(size);
00921         istr.read(&buf[0], size);                /*Flawfinder: ignore*/
00922         value.assign(buf.begin(), buf.end());
00923 }
00924 
00925 
00929 LLSDFormatter::LLSDFormatter() :
00930         mBoolAlpha(false)
00931 {
00932 }
00933 
00934 // virtual
00935 LLSDFormatter::~LLSDFormatter()
00936 { }
00937 
00938 void LLSDFormatter::boolalpha(bool alpha)
00939 {
00940         mBoolAlpha = alpha;
00941 }
00942 
00943 void LLSDFormatter::realFormat(const std::string& format)
00944 {
00945         mRealFormat = format;
00946 }
00947 
00948 void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
00949 {
00950         char buffer[MAX_STRING];                /* Flawfinder: ignore */
00951         snprintf(buffer, MAX_STRING, mRealFormat.c_str(), real);        /* Flawfinder: ignore */
00952         ostr << buffer;
00953 }
00954 
00958 LLSDNotationFormatter::LLSDNotationFormatter()
00959 {
00960 }
00961 
00962 // virtual
00963 LLSDNotationFormatter::~LLSDNotationFormatter()
00964 { }
00965 
00966 // static
00967 std::string LLSDNotationFormatter::escapeString(const std::string& in)
00968 {
00969         std::ostringstream ostr;
00970         serialize_string(in, ostr);
00971         return ostr.str();
00972 }
00973 
00974 // virtual
00975 S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
00976 {
00977         S32 format_count = 1;
00978         switch(data.type())
00979         {
00980         case LLSD::TypeMap:
00981         {
00982                 ostr << "{";
00983                 bool need_comma = false;
00984                 LLSD::map_const_iterator iter = data.beginMap();
00985                 LLSD::map_const_iterator end = data.endMap();
00986                 for(; iter != end; ++iter)
00987                 {
00988                         if(need_comma) ostr << ",";
00989                         need_comma = true;
00990                         ostr << '\'';
00991                         serialize_string((*iter).first, ostr);
00992                         ostr << "':";
00993                         format_count += format((*iter).second, ostr);
00994                 }
00995                 ostr << "}";
00996                 break;
00997         }
00998 
00999         case LLSD::TypeArray:
01000         {
01001                 ostr << "[";
01002                 bool need_comma = false;
01003                 LLSD::array_const_iterator iter = data.beginArray();
01004                 LLSD::array_const_iterator end = data.endArray();
01005                 for(; iter != end; ++iter)
01006                 {
01007                         if(need_comma) ostr << ",";
01008                         need_comma = true;
01009                         format_count += format(*iter, ostr);
01010                 }
01011                 ostr << "]";
01012                 break;
01013         }
01014 
01015         case LLSD::TypeUndefined:
01016                 ostr << "!";
01017                 break;
01018 
01019         case LLSD::TypeBoolean:
01020                 if(mBoolAlpha ||
01021 #if( LL_WINDOWS || __GNUC__ > 2)
01022                    (ostr.flags() & std::ios::boolalpha)
01023 #else
01024                    (ostr.flags() & 0x0100)
01025 #endif
01026                         )
01027                 {
01028                         ostr << (data.asBoolean()
01029                                          ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
01030                 }
01031                 else
01032                 {
01033                         ostr << (data.asBoolean() ? 1 : 0);
01034                 }
01035                 break;
01036 
01037         case LLSD::TypeInteger:
01038                 ostr << "i" << data.asInteger();
01039                 break;
01040 
01041         case LLSD::TypeReal:
01042                 ostr << "r";
01043                 if(mRealFormat.empty())
01044                 {
01045                         ostr << data.asReal();
01046                 }
01047                 else
01048                 {
01049                         formatReal(data.asReal(), ostr);
01050                 }
01051                 break;
01052 
01053         case LLSD::TypeUUID:
01054                 ostr << "u" << data.asUUID();
01055                 break;
01056 
01057         case LLSD::TypeString:
01058                 ostr << '\'';
01059                 serialize_string(data.asString(), ostr);
01060                 ostr << '\'';
01061                 break;
01062 
01063         case LLSD::TypeDate:
01064                 ostr << "d\"" << data.asDate() << "\"";
01065                 break;
01066 
01067         case LLSD::TypeURI:
01068                 ostr << "l\"";
01069                 serialize_string(data.asString(), ostr);
01070                 ostr << "\"";
01071                 break;
01072 
01073         case LLSD::TypeBinary:
01074         {
01075                 // *FIX: memory inefficient.
01076                 std::vector<U8> buffer = data.asBinary();
01077                 ostr << "b(" << buffer.size() << ")\"";
01078                 if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
01079                 ostr << "\"";
01080                 break;
01081         }
01082 
01083         default:
01084                 // *NOTE: This should never happen.
01085                 ostr << "!";
01086                 break;
01087         }
01088         return format_count;
01089 }
01090 
01091 
01095 LLSDBinaryFormatter::LLSDBinaryFormatter()
01096 {
01097 }
01098 
01099 // virtual
01100 LLSDBinaryFormatter::~LLSDBinaryFormatter()
01101 { }
01102 
01103 // virtual
01104 S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
01105 {
01106         S32 format_count = 1;
01107         switch(data.type())
01108         {
01109         case LLSD::TypeMap:
01110         {
01111                 ostr.put('{');
01112                 U32 size_nbo = htonl(data.size());
01113                 ostr.write((const char*)(&size_nbo), sizeof(U32));
01114                 LLSD::map_const_iterator iter = data.beginMap();
01115                 LLSD::map_const_iterator end = data.endMap();
01116                 for(; iter != end; ++iter)
01117                 {
01118                         ostr.put('k');
01119                         formatString((*iter).first, ostr);
01120                         format_count += format((*iter).second, ostr);
01121                 }
01122                 ostr.put('}');
01123                 break;
01124         }
01125 
01126         case LLSD::TypeArray:
01127         {
01128                 ostr.put('[');
01129                 U32 size_nbo = htonl(data.size());
01130                 ostr.write((const char*)(&size_nbo), sizeof(U32));
01131                 LLSD::array_const_iterator iter = data.beginArray();
01132                 LLSD::array_const_iterator end = data.endArray();
01133                 for(; iter != end; ++iter)
01134                 {
01135                         format_count += format(*iter, ostr);
01136                 }
01137                 ostr.put(']');
01138                 break;
01139         }
01140 
01141         case LLSD::TypeUndefined:
01142                 ostr.put('!');
01143                 break;
01144 
01145         case LLSD::TypeBoolean:
01146                 if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
01147                 else ostr.put(BINARY_FALSE_SERIAL);
01148                 break;
01149 
01150         case LLSD::TypeInteger:
01151         {
01152                 ostr.put('i');
01153                 U32 value_nbo = htonl(data.asInteger());
01154                 ostr.write((const char*)(&value_nbo), sizeof(U32));
01155                 break;
01156         }
01157 
01158         case LLSD::TypeReal:
01159         {
01160                 ostr.put('r');
01161                 F64 value_nbo = ll_htond(data.asReal());
01162                 ostr.write((const char*)(&value_nbo), sizeof(F64));
01163                 break;
01164         }
01165 
01166         case LLSD::TypeUUID:
01167                 ostr.put('u');
01168                 ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
01169                 break;
01170 
01171         case LLSD::TypeString:
01172                 ostr.put('s');
01173                 formatString(data.asString(), ostr);
01174                 break;
01175 
01176         case LLSD::TypeDate:
01177         {
01178                 ostr.put('d');
01179                 F64 value = data.asReal();
01180                 ostr.write((const char*)(&value), sizeof(F64));
01181                 break;
01182         }
01183 
01184         case LLSD::TypeURI:
01185                 ostr.put('l');
01186                 formatString(data.asString(), ostr);
01187                 break;
01188 
01189         case LLSD::TypeBinary:
01190         {
01191                 // *FIX: memory inefficient.
01192                 ostr.put('b');
01193                 std::vector<U8> buffer = data.asBinary();
01194                 U32 size_nbo = htonl(buffer.size());
01195                 ostr.write((const char*)(&size_nbo), sizeof(U32));
01196                 if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
01197                 break;
01198         }
01199 
01200         default:
01201                 // *NOTE: This should never happen.
01202                 ostr.put('!');
01203                 break;
01204         }
01205         return format_count;
01206 }
01207 
01208 void LLSDBinaryFormatter::formatString(
01209         const std::string& string,
01210         std::ostream& ostr) const
01211 {
01212         U32 size_nbo = htonl(string.size());
01213         ostr.write((const char*)(&size_nbo), sizeof(U32));
01214         ostr.write(string.c_str(), string.size());
01215 }
01216 
01220 bool deserialize_string(std::istream& str, std::string& value)
01221 {
01222         char c = str.get();
01223         if (str.fail())
01224         {
01225                 // No data in stream, bail out
01226                 return false;
01227         }
01228 
01229         bool rv = false;
01230         switch(c)
01231         {
01232         case '\'':
01233         case '"':
01234                 rv = deserialize_string_delim(str, value, c);
01235                 break;
01236         case 's':
01237                 rv = deserialize_string_raw(str, value);
01238                 break;
01239         default:
01240                 break;
01241         }
01242         return rv;
01243 }
01244 
01245 bool deserialize_string_delim(
01246         std::istream& str,
01247         std::string& value,
01248         char delim)
01249 {
01250         std::ostringstream write_buffer;
01251         bool found_escape = false;
01252         bool found_hex = false;
01253         bool found_digit = false;
01254         U8 byte = 0;
01255         
01256         while (true)
01257         {
01258                 char next_char = str.get();
01259                 
01260                 if(str.fail())
01261                 {
01262                         // If our stream is empty, break out
01263                         value = write_buffer.str();
01264                         return false;
01265                 }
01266                 
01267                 if(found_escape)
01268                 {
01269                         // next character(s) is a special sequence.
01270                         if(found_hex)
01271                         {
01272                                 if(found_digit)
01273                                 {
01274                                         found_digit = false;
01275                                         found_hex = false;
01276                                         found_escape = false;
01277                                         byte = byte << 4;
01278                                         byte |= hex_as_nybble(next_char);
01279                                         write_buffer << byte;
01280                                         byte = 0;
01281                                 }
01282                                 else
01283                                 {
01284                                         // next character is the first nybble of
01285                                         //
01286                                         found_digit = true;
01287                                         byte = hex_as_nybble(next_char);
01288                                 }
01289                         }
01290                         else if(next_char == 'x')
01291                         {
01292                                 found_hex = true;
01293                         }
01294                         else
01295                         {
01296                                 switch(next_char)
01297                                 {
01298                                 case 'a':
01299                                         write_buffer << '\a';
01300                                         break;
01301                                 case 'b':
01302                                         write_buffer << '\b';
01303                                         break;
01304                                 case 'f':
01305                                         write_buffer << '\f';
01306                                         break;
01307                                 case 'n':
01308                                         write_buffer << '\n';
01309                                         break;
01310                                 case 'r':
01311                                         write_buffer << '\r';
01312                                         break;
01313                                 case 't':
01314                                         write_buffer << '\t';
01315                                         break;
01316                                 case 'v':
01317                                         write_buffer << '\v';
01318                                         break;
01319                                 default:
01320                                         write_buffer << next_char;
01321                                         break;
01322                                 }
01323                                 found_escape = false;
01324                         }
01325                 }
01326                 else if(next_char == '\\')
01327                 {
01328                         found_escape = true;
01329                 }
01330                 else if(next_char == delim)
01331                 {
01332                         break;
01333                 }
01334                 else
01335                 {
01336                         write_buffer << next_char;
01337                 }
01338         }
01339 
01340         value = write_buffer.str();
01341         return true;
01342 }
01343 
01344 bool deserialize_string_raw(std::istream& str, std::string& value)
01345 {
01346         bool ok = false;
01347         const S32 BUF_LEN = 20;
01348         char buf[BUF_LEN];              /* Flawfinder: ignore */
01349         str.get(buf, BUF_LEN - 1, ')');
01350         char c = str.get();
01351         c = str.get();
01352         if(((c == '"') || (c == '\'')) && (buf[0] == '('))
01353         {
01354                 // We probably have a valid raw string. determine
01355                 // the size, and read it.
01356                 // *FIX: Should we set a maximum size?
01357                 // *FIX: This is memory inefficient.
01358                 S32 len = strtol(buf + 1, NULL, 0);
01359                 std::vector<char> buf;
01360                 buf.resize(len);
01361                 str.read(&buf[0], len);          /*Flawfinder: ignore*/
01362                 value.assign(buf.begin(), buf.end());
01363                 c = str.get();
01364                 if((c == '"') || (c == '\''))
01365                 {
01366                         ok = true;
01367                 }
01368         }
01369         return ok;
01370 }
01371 
01372 static const char* NOTATION_STRING_CHARACTERS[256] =
01373 {
01374         "\\x00",        // 0
01375         "\\x01",        // 1
01376         "\\x02",        // 2
01377         "\\x03",        // 3
01378         "\\x04",        // 4
01379         "\\x05",        // 5
01380         "\\x06",        // 6
01381         "\\a",          // 7
01382         "\\b",          // 8
01383         "\\t",          // 9
01384         "\\n",          // 10
01385         "\\v",          // 11
01386         "\\f",          // 12
01387         "\\r",          // 13
01388         "\\x0e",        // 14
01389         "\\x0f",        // 15
01390         "\\x10",        // 16
01391         "\\x11",        // 17
01392         "\\x12",        // 18
01393         "\\x13",        // 19
01394         "\\x14",        // 20
01395         "\\x15",        // 21
01396         "\\x16",        // 22
01397         "\\x17",        // 23
01398         "\\x18",        // 24
01399         "\\x19",        // 25
01400         "\\x1a",        // 26
01401         "\\x1b",        // 27
01402         "\\x1c",        // 28
01403         "\\x1d",        // 29
01404         "\\x1e",        // 30
01405         "\\x1f",        // 31
01406         " ",            // 32
01407         "!",            // 33
01408         "\"",           // 34
01409         "#",            // 35
01410         "$",            // 36
01411         "%",            // 37
01412         "&",            // 38
01413         "\\'",          // 39
01414         "(",            // 40
01415         ")",            // 41
01416         "*",            // 42
01417         "+",            // 43
01418         ",",            // 44
01419         "-",            // 45
01420         ".",            // 46
01421         "/",            // 47
01422         "0",            // 48
01423         "1",            // 49
01424         "2",            // 50
01425         "3",            // 51
01426         "4",            // 52
01427         "5",            // 53
01428         "6",            // 54
01429         "7",            // 55
01430         "8",            // 56
01431         "9",            // 57
01432         ":",            // 58
01433         ";",            // 59
01434         "<",            // 60
01435         "=",            // 61
01436         ">",            // 62
01437         "?",            // 63
01438         "@",            // 64
01439         "A",            // 65
01440         "B",            // 66
01441         "C",            // 67
01442         "D",            // 68
01443         "E",            // 69
01444         "F",            // 70
01445         "G",            // 71
01446         "H",            // 72
01447         "I",            // 73
01448         "J",            // 74
01449         "K",            // 75
01450         "L",            // 76
01451         "M",            // 77
01452         "N",            // 78
01453         "O",            // 79
01454         "P",            // 80
01455         "Q",            // 81
01456         "R",            // 82
01457         "S",            // 83
01458         "T",            // 84
01459         "U",            // 85
01460         "V",            // 86
01461         "W",            // 87
01462         "X",            // 88
01463         "Y",            // 89
01464         "Z",            // 90
01465         "[",            // 91
01466         "\\\\",         // 92
01467         "]",            // 93
01468         "^",            // 94
01469         "_",            // 95
01470         "`",            // 96
01471         "a",            // 97
01472         "b",            // 98
01473         "c",            // 99
01474         "d",            // 100
01475         "e",            // 101
01476         "f",            // 102
01477         "g",            // 103
01478         "h",            // 104
01479         "i",            // 105
01480         "j",            // 106
01481         "k",            // 107
01482         "l",            // 108
01483         "m",            // 109
01484         "n",            // 110
01485         "o",            // 111
01486         "p",            // 112
01487         "q",            // 113
01488         "r",            // 114
01489         "s",            // 115
01490         "t",            // 116
01491         "u",            // 117
01492         "v",            // 118
01493         "w",            // 119
01494         "x",            // 120
01495         "y",            // 121
01496         "z",            // 122
01497         "{",            // 123
01498         "|",            // 124
01499         "}",            // 125
01500         "~",            // 126
01501         "\\x7f",        // 127
01502         "\\x80",        // 128
01503         "\\x81",        // 129
01504         "\\x82",        // 130
01505         "\\x83",        // 131
01506         "\\x84",        // 132
01507         "\\x85",        // 133
01508         "\\x86",        // 134
01509         "\\x87",        // 135
01510         "\\x88",        // 136
01511         "\\x89",        // 137
01512         "\\x8a",        // 138
01513         "\\x8b",        // 139
01514         "\\x8c",        // 140
01515         "\\x8d",        // 141
01516         "\\x8e",        // 142
01517         "\\x8f",        // 143
01518         "\\x90",        // 144
01519         "\\x91",        // 145
01520         "\\x92",        // 146
01521         "\\x93",        // 147
01522         "\\x94",        // 148
01523         "\\x95",        // 149
01524         "\\x96",        // 150
01525         "\\x97",        // 151
01526         "\\x98",        // 152
01527         "\\x99",        // 153
01528         "\\x9a",        // 154
01529         "\\x9b",        // 155
01530         "\\x9c",        // 156
01531         "\\x9d",        // 157
01532         "\\x9e",        // 158
01533         "\\x9f",        // 159
01534         "\\xa0",        // 160
01535         "\\xa1",        // 161
01536         "\\xa2",        // 162
01537         "\\xa3",        // 163
01538         "\\xa4",        // 164
01539         "\\xa5",        // 165
01540         "\\xa6",        // 166
01541         "\\xa7",        // 167
01542         "\\xa8",        // 168
01543         "\\xa9",        // 169
01544         "\\xaa",        // 170
01545         "\\xab",        // 171
01546         "\\xac",        // 172
01547         "\\xad",        // 173
01548         "\\xae",        // 174
01549         "\\xaf",        // 175
01550         "\\xb0",        // 176
01551         "\\xb1",        // 177
01552         "\\xb2",        // 178
01553         "\\xb3",        // 179
01554         "\\xb4",        // 180
01555         "\\xb5",        // 181
01556         "\\xb6",        // 182
01557         "\\xb7",        // 183
01558         "\\xb8",        // 184
01559         "\\xb9",        // 185
01560         "\\xba",        // 186
01561         "\\xbb",        // 187
01562         "\\xbc",        // 188
01563         "\\xbd",        // 189
01564         "\\xbe",        // 190
01565         "\\xbf",        // 191
01566         "\\xc0",        // 192
01567         "\\xc1",        // 193
01568         "\\xc2",        // 194
01569         "\\xc3",        // 195
01570         "\\xc4",        // 196
01571         "\\xc5",        // 197
01572         "\\xc6",        // 198
01573         "\\xc7",        // 199
01574         "\\xc8",        // 200
01575         "\\xc9",        // 201
01576         "\\xca",        // 202
01577         "\\xcb",        // 203
01578         "\\xcc",        // 204
01579         "\\xcd",        // 205
01580         "\\xce",        // 206
01581         "\\xcf",        // 207
01582         "\\xd0",        // 208
01583         "\\xd1",        // 209
01584         "\\xd2",        // 210
01585         "\\xd3",        // 211
01586         "\\xd4",        // 212
01587         "\\xd5",        // 213
01588         "\\xd6",        // 214
01589         "\\xd7",        // 215
01590         "\\xd8",        // 216
01591         "\\xd9",        // 217
01592         "\\xda",        // 218
01593         "\\xdb",        // 219
01594         "\\xdc",        // 220
01595         "\\xdd",        // 221
01596         "\\xde",        // 222
01597         "\\xdf",        // 223
01598         "\\xe0",        // 224
01599         "\\xe1",        // 225
01600         "\\xe2",        // 226
01601         "\\xe3",        // 227
01602         "\\xe4",        // 228
01603         "\\xe5",        // 229
01604         "\\xe6",        // 230
01605         "\\xe7",        // 231
01606         "\\xe8",        // 232
01607         "\\xe9",        // 233
01608         "\\xea",        // 234
01609         "\\xeb",        // 235
01610         "\\xec",        // 236
01611         "\\xed",        // 237
01612         "\\xee",        // 238
01613         "\\xef",        // 239
01614         "\\xf0",        // 240
01615         "\\xf1",        // 241
01616         "\\xf2",        // 242
01617         "\\xf3",        // 243
01618         "\\xf4",        // 244
01619         "\\xf5",        // 245
01620         "\\xf6",        // 246
01621         "\\xf7",        // 247
01622         "\\xf8",        // 248
01623         "\\xf9",        // 249
01624         "\\xfa",        // 250
01625         "\\xfb",        // 251
01626         "\\xfc",        // 252
01627         "\\xfd",        // 253
01628         "\\xfe",        // 254
01629         "\\xff"         // 255
01630 };
01631 
01632 void serialize_string(const std::string& value, std::ostream& str)
01633 {
01634         std::string::const_iterator it = value.begin();
01635         std::string::const_iterator end = value.end();
01636         U8 c;
01637         for(; it != end; ++it)
01638         {
01639                 c = (U8)(*it);
01640                 str << NOTATION_STRING_CHARACTERS[c];
01641         }
01642 }
01643 
01644 

Generated on Thu Jul 1 06:09:08 2010 for Second Life Viewer by  doxygen 1.4.7