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

Generated on Fri May 16 08:32:07 2008 for SecondLife by  doxygen 1.5.5