aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llsdserialize.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llcommon/llsdserialize.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llcommon/llsdserialize.cpp')
-rw-r--r--linden/indra/llcommon/llsdserialize.cpp1640
1 files changed, 1640 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llsdserialize.cpp b/linden/indra/llcommon/llsdserialize.cpp
new file mode 100644
index 0000000..4c00c98
--- /dev/null
+++ b/linden/indra/llcommon/llsdserialize.cpp
@@ -0,0 +1,1640 @@
1/**
2 * @file llsdserialize.cpp
3 * @author Phoenix
4 * @date 2006-03-05
5 * @brief Implementation of LLSD parsers and formatters
6 *
7 * Copyright (c) 2006-2007, Linden Research, Inc.
8 *
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 */
29
30#include "linden_common.h"
31#include "llsdserialize.h"
32#include "llmemory.h"
33#include "llstreamtools.h" // for fullread
34
35#include <iostream>
36#include "apr-1/apr_base64.h"
37
38#if !LL_WINDOWS
39#include <netinet/in.h> // htonl & ntohl
40#endif
41
42#include "lldate.h"
43#include "llsd.h"
44#include "lluri.h"
45
46// File constants
47static const int MAX_HDR_LEN = 20;
48static const char LEGACY_NON_HEADER[] = "<llsd>";
49
50//static
51const char* LLSDSerialize::LLSDBinaryHeader = "LLSD/Binary";
52
53//static
54const char* LLSDSerialize::LLSDXMLHeader = "LLSD/XML";
55
56// virtual
57LLSDParser::~LLSDParser()
58{ }
59
60// virtual
61LLSDNotationParser::~LLSDNotationParser()
62{ }
63
64
65// static
66void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
67{
68 LLPointer<LLSDFormatter> f = NULL;
69
70 switch (type)
71 {
72 case LLSD_BINARY:
73 str << "<? " << LLSDBinaryHeader << " ?>\n";
74 f = new LLSDBinaryFormatter;
75 break;
76
77 case LLSD_XML:
78 str << "<? " << LLSDXMLHeader << " ?>\n";
79 f = new LLSDXMLFormatter;
80 break;
81
82 default:
83 llwarns << "serialize request for unkown ELLSD_Serialize" << llendl;
84 }
85
86 if (f.notNull())
87 {
88 f->format(sd, str, options);
89 }
90}
91
92// static
93bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
94{
95 LLPointer<LLSDParser> p = NULL;
96 char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
97 int i;
98 int inbuf = 0;
99 bool legacy_no_header = false;
100 bool fail_if_not_legacy = false;
101 std::string header = "";
102
103 /*
104 * Get the first line before anything.
105 */
106 str.get(hdr_buf, MAX_HDR_LEN, '\n');
107 if (str.fail())
108 {
109 str.clear();
110 fail_if_not_legacy = true;
111 }
112
113 if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
114 {
115 legacy_no_header = true;
116 inbuf = str.gcount();
117 }
118 else
119 {
120 if (fail_if_not_legacy)
121 goto fail;
122 /*
123 * Remove the newline chars
124 */
125 for (i = 0; i < MAX_HDR_LEN; i++)
126 {
127 if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
128 hdr_buf[i] == '\n')
129 {
130 hdr_buf[i] = 0;
131 break;
132 }
133 }
134 header = hdr_buf;
135
136 std::string::size_type start = std::string::npos;
137 std::string::size_type end = std::string::npos;
138 start = header.find_first_not_of("<? ");
139 if (start != std::string::npos)
140 {
141 end = header.find_first_of(" ?", start);
142 }
143 if ((start == std::string::npos) || (end == std::string::npos))
144 goto fail;
145
146 header = header.substr(start, end - start);
147 ws(str);
148 }
149 /*
150 * Create the parser as appropriate
151 */
152 if (legacy_no_header)
153 {
154 LLSDXMLParser *x = new LLSDXMLParser;
155 x->parsePart(hdr_buf, inbuf);
156 p = x;
157 }
158 else if (header == LLSDBinaryHeader)
159 {
160 p = new LLSDBinaryParser;
161 }
162 else if (header == LLSDXMLHeader)
163 {
164 p = new LLSDXMLParser;
165 }
166 else
167 {
168 llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
169 }
170
171 if (p.notNull())
172 {
173 p->parse(str, sd);
174 return true;
175 }
176
177fail:
178 llwarns << "deserialize LLSD parse failure" << llendl;
179 return false;
180}
181
182/**
183 * Endian handlers
184 */
185#if LL_BIG_ENDIAN
186U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
187U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
188F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
189F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
190#else
191// I read some comments one a indicating that doing an integer add
192// here would be faster than a bitwise or. For now, the or has
193// programmer clarity, since the intended outcome matches the
194// operation.
195U64 ll_htonll(U64 hostlonglong)
196{
197 return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
198 ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
199}
200U64 ll_ntohll(U64 netlonglong)
201{
202 return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
203 ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
204}
205union LLEndianSwapper
206{
207 F64 d;
208 U64 i;
209};
210F64 ll_htond(F64 hostdouble)
211{
212 LLEndianSwapper tmp;
213 tmp.d = hostdouble;
214 tmp.i = ll_htonll(tmp.i);
215 return tmp.d;
216}
217F64 ll_ntohd(F64 netdouble)
218{
219 LLEndianSwapper tmp;
220 tmp.d = netdouble;
221 tmp.i = ll_ntohll(tmp.i);
222 return tmp.d;
223}
224#endif
225
226/**
227 * Local functions.
228 */
229bool deserialize_string(std::istream& str, std::string& value);
230bool deserialize_string_delim(std::istream& str, std::string& value, char d);
231bool deserialize_string_raw(std::istream& str, std::string& value);
232void serialize_string(const std::string& value, std::ostream& str);
233
234/**
235 * Local constants.
236 */
237static const std::string NOTATION_TRUE_SERIAL("true");
238static const std::string NOTATION_FALSE_SERIAL("false");
239
240static const char BINARY_TRUE_SERIAL = '1';
241static const char BINARY_FALSE_SERIAL = '0';
242
243static const S32 NOTATION_PARSE_FAILURE = -1;
244
245/**
246 * LLSDParser
247 */
248LLSDParser::LLSDParser()
249{
250}
251
252/**
253 * LLSDNotationParser
254 */
255// virtual
256S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
257{
258 // map: { string:object, string:object }
259 // array: [ object, object, object ]
260 // undef: !
261 // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
262 // integer: i####
263 // real: r####
264 // uuid: u####
265 // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
266 // uri: l"escaped"
267 // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
268 // binary: b##"ff3120ab1" | b(size)"raw data"
269 char c;
270 c = istr.peek();
271 while(isspace(c))
272 {
273 // pop the whitespace.
274 c = istr.get();
275 c = istr.peek();
276 continue;
277 }
278 if(!istr.good())
279 {
280 return 0;
281 }
282 S32 parse_count = 1;
283 switch(c)
284 {
285 case '{':
286 parse_count += parseMap(istr, data);
287 if(istr.fail())
288 {
289 llinfos << "STREAM FAILURE reading map." << llendl;
290 }
291 if(data.isUndefined())
292 {
293 parse_count = NOTATION_PARSE_FAILURE;
294 }
295 break;
296
297 case '[':
298 parse_count += parseArray(istr, data);
299 if(istr.fail())
300 {
301 llinfos << "STREAM FAILURE reading array." << llendl;
302 }
303 if(data.isUndefined())
304 {
305 parse_count = NOTATION_PARSE_FAILURE;
306 }
307 break;
308
309 case '!':
310 c = istr.get();
311 data.clear();
312 break;
313
314 case '0':
315 c = istr.get();
316 data = false;
317 break;
318
319 case 'F':
320 case 'f':
321 do
322 {
323 istr.ignore();
324 c = istr.peek();
325 } while (isalpha(c));
326 data = false;
327 if(istr.fail())
328 {
329 llinfos << "STREAM FAILURE reading boolean." << llendl;
330 }
331 break;
332
333 case '1':
334 c = istr.get();
335 data = true;
336 break;
337
338 case 'T':
339 case 't':
340 do
341 {
342 istr.ignore();
343 c = istr.peek();
344 } while (isalpha(c));
345 data = true;
346 if(istr.fail())
347 {
348 llinfos << "STREAM FAILURE reading boolean." << llendl;
349 }
350 break;
351
352 case 'i':
353 {
354 c = istr.get();
355 S32 integer = 0;
356 istr >> integer;
357 data = integer;
358 if(istr.fail())
359 {
360 llinfos << "STREAM FAILURE reading integer." << llendl;
361 }
362 break;
363 }
364
365 case 'r':
366 {
367 c = istr.get();
368 F64 real = 0.0;
369 istr >> real;
370 data = real;
371 if(istr.fail())
372 {
373 llinfos << "STREAM FAILURE reading real." << llendl;
374 }
375 break;
376 }
377
378 case 'u':
379 {
380 c = istr.get();
381 LLUUID id;
382 istr >> id;
383 data = id;
384 if(istr.fail())
385 {
386 llinfos << "STREAM FAILURE reading uuid." << llendl;
387 }
388 break;
389 }
390
391 case '\"':
392 case '\'':
393 case 's':
394 parseString(istr, data);
395 if(istr.fail())
396 {
397 llinfos << "STREAM FAILURE reading string." << llendl;
398 }
399 if(data.isUndefined())
400 {
401 parse_count = NOTATION_PARSE_FAILURE;
402 }
403 break;
404
405 case 'l':
406 {
407 c = istr.get(); // pop the 'l'
408 c = istr.get(); // pop the delimiter
409 std::string str;
410 deserialize_string_delim(istr, str, c);
411 data = LLURI(str);
412 if(istr.fail())
413 {
414 llinfos << "STREAM FAILURE reading link." << llendl;
415 }
416 break;
417 }
418
419 case 'd':
420 {
421 c = istr.get(); // pop the 'd'
422 c = istr.get(); // pop the delimiter
423 std::string str;
424 deserialize_string_delim(istr, str, c);
425 data = LLDate(str);
426 if(istr.fail())
427 {
428 llinfos << "STREAM FAILURE reading date." << llendl;
429 }
430 break;
431 }
432
433 case 'b':
434 parseBinary(istr, data);
435 if(istr.fail())
436 {
437 llinfos << "STREAM FAILURE reading data." << llendl;
438 }
439 if(data.isUndefined())
440 {
441 parse_count = NOTATION_PARSE_FAILURE;
442 }
443 break;
444
445 default:
446 data.clear();
447 parse_count = NOTATION_PARSE_FAILURE;
448 llinfos << "Unrecognized character while parsing: int(" << (int)c
449 << ")" << llendl;
450 break;
451 }
452 return parse_count;
453}
454
455// static
456LLSD LLSDNotationParser::parse(std::istream& istr)
457{
458 LLSDNotationParser parser;
459 LLSD rv;
460 S32 count = parser.parse(istr, rv);
461 lldebugs << "LLSDNotationParser::parse parsed " << count << " objects."
462 << llendl;
463 return rv;
464}
465
466S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
467{
468 // map: { string:object, string:object }
469 map = LLSD::emptyMap();
470 S32 parse_count = 0;
471 char c = istr.get();
472 if(c == '{')
473 {
474 // eat commas, white
475 bool found_name = false;
476 std::string name;
477 c = istr.get();
478 while(c != '}' && istr.good())
479 {
480 if(!found_name)
481 {
482 if((c == '\"') || (c == '\'') || (c == 's'))
483 {
484 istr.putback(c);
485 found_name = true;
486 deserialize_string(istr, name);
487 }
488 c = istr.get();
489 }
490 else
491 {
492 if(isspace(c) || (c == ':'))
493 {
494 c = istr.get();
495 continue;
496 }
497 istr.putback(c);
498 LLSD child;
499 S32 count = parse(istr, child);
500 if(count > 0)
501 {
502 parse_count += count;
503 map.insert(name, child);
504 }
505 else
506 {
507 map.clear();
508 return NOTATION_PARSE_FAILURE;
509 }
510 found_name = false;
511 c = istr.get();
512 }
513 }
514 }
515 return parse_count;
516}
517
518S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
519{
520 // array: [ object, object, object ]
521 array = LLSD::emptyArray();
522 S32 parse_count = 0;
523 char c = istr.get();
524 if(c == '[')
525 {
526 // eat commas, white
527 c = istr.get();
528 while((c != ']') && istr.good())
529 {
530 LLSD child;
531 if(isspace(c) || (c == ','))
532 {
533 c = istr.get();
534 continue;
535 }
536 istr.putback(c);
537 S32 count = parse(istr, child);
538 if(count > 0)
539 {
540 parse_count += count;
541 array.append(child);
542 }
543 else
544 {
545 array.clear();
546 return NOTATION_PARSE_FAILURE;
547 }
548 c = istr.get();
549 }
550 }
551 return parse_count;
552}
553
554void LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
555{
556 std::string value;
557 if(deserialize_string(istr, value))
558 {
559 data = value;
560 }
561 else
562 {
563 // failed to parse.
564 data.clear();
565 }
566}
567
568void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
569{
570 // binary: b##"ff3120ab1"
571 // or: b(len)"..."
572
573 // I want to manually control those values here to make sure the
574 // parser doesn't break when someone changes a constant somewhere
575 // else.
576 const U32 BINARY_BUFFER_SIZE = 256;
577 const U32 STREAM_GET_COUNT = 255;
578
579 // need to read the base out.
580 char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
581 istr.get(buf, STREAM_GET_COUNT, '"');
582 char c = istr.get();
583 if((c == '"') && (0 == strncmp("b(", buf, 2)))
584 {
585 // We probably have a valid raw binary stream. determine
586 // the size, and read it.
587 // *FIX: Should we set a maximum size?
588 S32 len = strtol(buf + 2, NULL, 0);
589 std::vector<U8> value;
590 if(len)
591 {
592 value.resize(len);
593 fullread(istr, (char *)&value[0], len);
594 }
595 c = istr.get(); // strip off the trailing double-quote
596 data = value;
597 }
598 else if((c == '"') && (0 == strncmp("b64", buf, 3)))
599 {
600 // *FIX: A bit inefficient, but works for now. To make the
601 // format better, I would need to add a hint into the
602 // serialization format that indicated how long it was.
603 std::stringstream coded_stream;
604 istr.get(*(coded_stream.rdbuf()), '\"');
605 c = istr.get();
606 std::string encoded(coded_stream.str());
607 S32 len = apr_base64_decode_len(encoded.c_str());
608 std::vector<U8> value;
609 value.resize(len);
610 len = apr_base64_decode_binary(&value[0], encoded.c_str());
611 value.resize(len);
612 data = value;
613 }
614 else if((c == '"') && (0 == strncmp("b16", buf, 3)))
615 {
616 // yay, base 16. We pop the next character which is either a
617 // double quote or base 16 data. If it's a double quote, we're
618 // done parsing. If it's not, put the data back, and read the
619 // stream until the next double quote.
620 char* read; /*Flawfinder: ignore*/
621 U8 byte;
622 U8 byte_buffer[BINARY_BUFFER_SIZE];
623 U8* write;
624 std::vector<U8> value;
625 c = istr.get();
626 while(c != '"')
627 {
628 istr.putback(c);
629 read = buf;
630 write = byte_buffer;
631 istr.get(buf, STREAM_GET_COUNT, '"');
632 c = istr.get();
633 while(*read != '\0') /*Flawfinder: ignore*/
634 {
635 byte = hex_as_nybble(*read++);
636 byte = byte << 4;
637 byte |= hex_as_nybble(*read++);
638 *write++ = byte;
639 }
640 // copy the data out of the byte buffer
641 value.insert(value.end(), byte_buffer, write);
642 }
643 data = value;
644 }
645 else
646 {
647 data.clear();
648 }
649}
650
651
652/**
653 * LLSDBinaryParser
654 */
655LLSDBinaryParser::LLSDBinaryParser()
656{
657}
658
659// virtual
660LLSDBinaryParser::~LLSDBinaryParser()
661{
662}
663
664// virtual
665S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
666{
667/**
668 * Undefined: '!'<br>
669 * Boolean: 't' for true 'f' for false<br>
670 * Integer: 'i' + 4 bytes network byte order<br>
671 * Real: 'r' + 8 bytes IEEE double<br>
672 * UUID: 'u' + 16 byte unsigned integer<br>
673 * String: 's' + 4 byte integer size + string<br>
674 * strings also secretly support the notation format
675 * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
676 * URI: 'l' + 4 byte integer size + string uri<br>
677 * Binary: 'b' + 4 byte integer size + binary data<br>
678 * Array: '[' + 4 byte integer size + all values + ']'<br>
679 * Map: '{' + 4 byte integer size every(key + value) + '}'<br>
680 * map keys are serialized as s + 4 byte integer size + string or in the
681 * notation format.
682 */
683 char c;
684 c = istr.get();
685 if(!istr.good())
686 {
687 return 0;
688 }
689 S32 parse_count = 1;
690 switch(c)
691 {
692 case '{':
693 parse_count += parseMap(istr, data);
694 if(istr.fail())
695 {
696 llinfos << "STREAM FAILURE reading binary map." << llendl;
697 }
698 break;
699
700 case '[':
701 parse_count += parseArray(istr, data);
702 if(istr.fail())
703 {
704 llinfos << "STREAM FAILURE reading binary array." << llendl;
705 }
706 break;
707
708 case '!':
709 data.clear();
710 break;
711
712 case '0':
713 data = false;
714 break;
715
716 case '1':
717 data = true;
718 break;
719
720 case 'i':
721 {
722 U32 value_nbo = 0;
723 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
724 data = (S32)ntohl(value_nbo);
725 if(istr.fail())
726 {
727 llinfos << "STREAM FAILURE reading binary integer." << llendl;
728 }
729 break;
730 }
731
732 case 'r':
733 {
734 F64 real_nbo = 0.0;
735 istr.read((char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
736 data = ll_ntohd(real_nbo);
737 if(istr.fail())
738 {
739 llinfos << "STREAM FAILURE reading binary real." << llendl;
740 }
741 break;
742 }
743
744 case 'u':
745 {
746 LLUUID id;
747 istr.read((char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
748 data = id;
749 if(istr.fail())
750 {
751 llinfos << "STREAM FAILURE reading binary uuid." << llendl;
752 }
753 break;
754 }
755
756 case '\'':
757 case '"':
758 {
759 std::string value;
760 deserialize_string_delim(istr, value, c);
761 data = value;
762 break;
763 }
764
765 case 's':
766 {
767 std::string value;
768 parseString(istr, value);
769 data = value;
770 if(istr.fail())
771 {
772 llinfos << "STREAM FAILURE reading binary string." << llendl;
773 }
774 break;
775 }
776
777 case 'l':
778 {
779 std::string value;
780 parseString(istr, value);
781 data = LLURI(value);
782 if(istr.fail())
783 {
784 llinfos << "STREAM FAILURE reading binary link." << llendl;
785 }
786 break;
787 }
788
789 case 'd':
790 {
791 F64 real = 0.0;
792 istr.read((char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
793 data = LLDate(real);
794 if(istr.fail())
795 {
796 llinfos << "STREAM FAILURE reading binary date." << llendl;
797 }
798 break;
799 }
800
801 case 'b':
802 {
803 // We probably have a valid raw binary stream. determine
804 // the size, and read it.
805 // *FIX: Should we set a maximum size?
806 U32 size_nbo = 0;
807 istr.read((char*)&size_nbo, sizeof(U32));
808 S32 size = (S32)ntohl(size_nbo);
809 std::vector<U8> value;
810 if(size)
811 {
812 value.resize(size);
813 istr.read((char*)&value[0], size); /*Flawfinder: ignore*/
814 }
815 data = value;
816 if(istr.fail())
817 {
818 llinfos << "STREAM FAILURE reading binary." << llendl;
819 }
820 break;
821 }
822
823 default:
824 --parse_count;
825 llinfos << "Unrecognized character while parsing: int(" << (int)c
826 << ")" << llendl;
827 break;
828 }
829 return parse_count;
830}
831
832// static
833LLSD LLSDBinaryParser::parse(std::istream& istr)
834{
835 LLSDBinaryParser parser;
836 LLSD rv;
837 S32 count = parser.parse(istr, rv);
838 lldebugs << "LLSDBinaryParser::parse parsed " << count << " objects."
839 << llendl;
840 return rv;
841}
842
843S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
844{
845 map = LLSD::emptyMap();
846 U32 value_nbo = 0;
847 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
848 S32 size = (S32)ntohl(value_nbo);
849 S32 parse_count = 0;
850 S32 count = 0;
851 char c = istr.get();
852 while(c != '}' && (count < size) && istr.good())
853 {
854 std::string name;
855 switch(c)
856 {
857 case 'k':
858 parseString(istr, name);
859 break;
860 case '\'':
861 case '"':
862 deserialize_string_delim(istr, name, c);
863 break;
864 }
865 LLSD child;
866 S32 child_count = parse(istr, child);
867 if(child_count)
868 {
869 parse_count += child_count;
870 map.insert(name, child);
871 }
872 ++count;
873 c = istr.get();
874 }
875 return parse_count;
876}
877
878S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
879{
880 array = LLSD::emptyArray();
881 U32 value_nbo = 0;
882 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
883 S32 size = (S32)ntohl(value_nbo);
884
885 // *FIX: This would be a good place to reserve some space in the
886 // array...
887
888 S32 parse_count = 0;
889 S32 count = 0;
890 char c = istr.peek();
891 while((c != ']') && (count < size) && istr.good())
892 {
893 LLSD child;
894 S32 child_count = parse(istr, child);
895 if(child_count)
896 {
897 parse_count += child_count;
898 array.append(child);
899 }
900 ++count;
901 c = istr.peek();
902 }
903 c = istr.get();
904 return parse_count;
905}
906
907void LLSDBinaryParser::parseString(
908 std::istream& istr,
909 std::string& value) const
910{
911 // *FIX: This is memory inefficient.
912 U32 value_nbo = 0;
913 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
914 S32 size = (S32)ntohl(value_nbo);
915 std::vector<char> buf;
916 buf.resize(size);
917 istr.read(&buf[0], size); /*Flawfinder: ignore*/
918 value.assign(buf.begin(), buf.end());
919}
920
921
922/**
923 * LLSDFormatter
924 */
925LLSDFormatter::LLSDFormatter() :
926 mBoolAlpha(false)
927{
928}
929
930// virtual
931LLSDFormatter::~LLSDFormatter()
932{ }
933
934void LLSDFormatter::boolalpha(bool alpha)
935{
936 mBoolAlpha = alpha;
937}
938
939void LLSDFormatter::realFormat(const std::string& format)
940{
941 mRealFormat = format;
942}
943
944void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
945{
946 char buffer[MAX_STRING]; /* Flawfinder: ignore */
947 snprintf(buffer, MAX_STRING, mRealFormat.c_str(), real);
948 ostr << buffer;
949}
950
951/**
952 * LLSDNotationFormatter
953 */
954LLSDNotationFormatter::LLSDNotationFormatter()
955{
956}
957
958// virtual
959LLSDNotationFormatter::~LLSDNotationFormatter()
960{ }
961
962// static
963std::string LLSDNotationFormatter::escapeString(const std::string& in)
964{
965 std::ostringstream ostr;
966 serialize_string(in, ostr);
967 return ostr.str();
968}
969
970// virtual
971S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
972{
973 S32 format_count = 1;
974 switch(data.type())
975 {
976 case LLSD::TypeMap:
977 {
978 ostr << "{";
979 bool need_comma = false;
980 LLSD::map_const_iterator iter = data.beginMap();
981 LLSD::map_const_iterator end = data.endMap();
982 for(; iter != end; ++iter)
983 {
984 if(need_comma) ostr << ",";
985 need_comma = true;
986 ostr << '\'';
987 serialize_string((*iter).first, ostr);
988 ostr << "':";
989 format_count += format((*iter).second, ostr);
990 }
991 ostr << "}";
992 break;
993 }
994
995 case LLSD::TypeArray:
996 {
997 ostr << "[";
998 bool need_comma = false;
999 LLSD::array_const_iterator iter = data.beginArray();
1000 LLSD::array_const_iterator end = data.endArray();
1001 for(; iter != end; ++iter)
1002 {
1003 if(need_comma) ostr << ",";
1004 need_comma = true;
1005 format_count += format(*iter, ostr);
1006 }
1007 ostr << "]";
1008 break;
1009 }
1010
1011 case LLSD::TypeUndefined:
1012 ostr << "!";
1013 break;
1014
1015 case LLSD::TypeBoolean:
1016 if(mBoolAlpha ||
1017#if( LL_WINDOWS || __GNUC__ > 2)
1018 (ostr.flags() & std::ios::boolalpha)
1019#else
1020 (ostr.flags() & 0x0100)
1021#endif
1022 )
1023 {
1024 ostr << (data.asBoolean()
1025 ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
1026 }
1027 else
1028 {
1029 ostr << (data.asBoolean() ? 1 : 0);
1030 }
1031 break;
1032
1033 case LLSD::TypeInteger:
1034 ostr << "i" << data.asInteger();
1035 break;
1036
1037 case LLSD::TypeReal:
1038 ostr << "r";
1039 if(mRealFormat.empty())
1040 {
1041 ostr << data.asReal();
1042 }
1043 else
1044 {
1045 formatReal(data.asReal(), ostr);
1046 }
1047 break;
1048
1049 case LLSD::TypeUUID:
1050 ostr << "u" << data.asUUID();
1051 break;
1052
1053 case LLSD::TypeString:
1054 ostr << '\'';
1055 serialize_string(data.asString(), ostr);
1056 ostr << '\'';
1057 break;
1058
1059 case LLSD::TypeDate:
1060 ostr << "d\"" << data.asDate() << "\"";
1061 break;
1062
1063 case LLSD::TypeURI:
1064 ostr << "l\"";
1065 serialize_string(data.asString(), ostr);
1066 ostr << "\"";
1067 break;
1068
1069 case LLSD::TypeBinary:
1070 {
1071 // *FIX: memory inefficient.
1072 std::vector<U8> buffer = data.asBinary();
1073 ostr << "b(" << buffer.size() << ")\"";
1074 if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
1075 ostr << "\"";
1076 break;
1077 }
1078
1079 default:
1080 // *NOTE: This should never happen.
1081 ostr << "!";
1082 break;
1083 }
1084 return format_count;
1085}
1086
1087
1088/**
1089 * LLSDBinaryFormatter
1090 */
1091LLSDBinaryFormatter::LLSDBinaryFormatter()
1092{
1093}
1094
1095// virtual
1096LLSDBinaryFormatter::~LLSDBinaryFormatter()
1097{ }
1098
1099// virtual
1100S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
1101{
1102 S32 format_count = 1;
1103 switch(data.type())
1104 {
1105 case LLSD::TypeMap:
1106 {
1107 ostr.put('{');
1108 U32 size_nbo = htonl(data.size());
1109 ostr.write((const char*)(&size_nbo), sizeof(U32));
1110 LLSD::map_const_iterator iter = data.beginMap();
1111 LLSD::map_const_iterator end = data.endMap();
1112 for(; iter != end; ++iter)
1113 {
1114 ostr.put('k');
1115 formatString((*iter).first, ostr);
1116 format_count += format((*iter).second, ostr);
1117 }
1118 ostr.put('}');
1119 break;
1120 }
1121
1122 case LLSD::TypeArray:
1123 {
1124 ostr.put('[');
1125 U32 size_nbo = htonl(data.size());
1126 ostr.write((const char*)(&size_nbo), sizeof(U32));
1127 LLSD::array_const_iterator iter = data.beginArray();
1128 LLSD::array_const_iterator end = data.endArray();
1129 for(; iter != end; ++iter)
1130 {
1131 format_count += format(*iter, ostr);
1132 }
1133 ostr.put(']');
1134 break;
1135 }
1136
1137 case LLSD::TypeUndefined:
1138 ostr.put('!');
1139 break;
1140
1141 case LLSD::TypeBoolean:
1142 if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
1143 else ostr.put(BINARY_FALSE_SERIAL);
1144 break;
1145
1146 case LLSD::TypeInteger:
1147 {
1148 ostr.put('i');
1149 U32 value_nbo = htonl(data.asInteger());
1150 ostr.write((const char*)(&value_nbo), sizeof(U32));
1151 break;
1152 }
1153
1154 case LLSD::TypeReal:
1155 {
1156 ostr.put('r');
1157 F64 value_nbo = ll_htond(data.asReal());
1158 ostr.write((const char*)(&value_nbo), sizeof(F64));
1159 break;
1160 }
1161
1162 case LLSD::TypeUUID:
1163 ostr.put('u');
1164 ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
1165 break;
1166
1167 case LLSD::TypeString:
1168 ostr.put('s');
1169 formatString(data.asString(), ostr);
1170 break;
1171
1172 case LLSD::TypeDate:
1173 {
1174 ostr.put('d');
1175 F64 value = data.asReal();
1176 ostr.write((const char*)(&value), sizeof(F64));
1177 break;
1178 }
1179
1180 case LLSD::TypeURI:
1181 ostr.put('l');
1182 formatString(data.asString(), ostr);
1183 break;
1184
1185 case LLSD::TypeBinary:
1186 {
1187 // *FIX: memory inefficient.
1188 ostr.put('b');
1189 std::vector<U8> buffer = data.asBinary();
1190 U32 size_nbo = htonl(buffer.size());
1191 ostr.write((const char*)(&size_nbo), sizeof(U32));
1192 if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
1193 break;
1194 }
1195
1196 default:
1197 // *NOTE: This should never happen.
1198 ostr.put('!');
1199 break;
1200 }
1201 return format_count;
1202}
1203
1204void LLSDBinaryFormatter::formatString(
1205 const std::string& string,
1206 std::ostream& ostr) const
1207{
1208 U32 size_nbo = htonl(string.size());
1209 ostr.write((const char*)(&size_nbo), sizeof(U32));
1210 ostr.write(string.c_str(), string.size());
1211}
1212
1213/**
1214 * local functions
1215 */
1216bool deserialize_string(std::istream& str, std::string& value)
1217{
1218 char c = str.get();
1219 if (str.fail())
1220 {
1221 // No data in stream, bail out
1222 return false;
1223 }
1224
1225 bool rv = false;
1226 switch(c)
1227 {
1228 case '\'':
1229 case '"':
1230 rv = deserialize_string_delim(str, value, c);
1231 break;
1232 case 's':
1233 rv = deserialize_string_raw(str, value);
1234 break;
1235 default:
1236 break;
1237 }
1238 return rv;
1239}
1240
1241bool deserialize_string_delim(
1242 std::istream& str,
1243 std::string& value,
1244 char delim)
1245{
1246 std::ostringstream write_buffer;
1247 bool found_escape = false;
1248 bool found_hex = false;
1249 bool found_digit = false;
1250 U8 byte = 0;
1251
1252 while (true)
1253 {
1254 char next_char = str.get();
1255
1256 if(str.fail())
1257 {
1258 // If our stream is empty, break out
1259 value = write_buffer.str();
1260 return false;
1261 }
1262
1263 if(found_escape)
1264 {
1265 // next character(s) is a special sequence.
1266 if(found_hex)
1267 {
1268 if(found_digit)
1269 {
1270 found_digit = false;
1271 found_hex = false;
1272 found_escape = false;
1273 byte = byte << 4;
1274 byte |= hex_as_nybble(next_char);
1275 write_buffer << byte;
1276 byte = 0;
1277 }
1278 else
1279 {
1280 // next character is the first nybble of
1281 //
1282 found_digit = true;
1283 byte = hex_as_nybble(next_char);
1284 }
1285 }
1286 else if(next_char == 'x')
1287 {
1288 found_hex = true;
1289 }
1290 else
1291 {
1292 switch(next_char)
1293 {
1294 case 'a':
1295 write_buffer << '\a';
1296 break;
1297 case 'b':
1298 write_buffer << '\b';
1299 break;
1300 case 'f':
1301 write_buffer << '\f';
1302 break;
1303 case 'n':
1304 write_buffer << '\n';
1305 break;
1306 case 'r':
1307 write_buffer << '\r';
1308 break;
1309 case 't':
1310 write_buffer << '\t';
1311 break;
1312 case 'v':
1313 write_buffer << '\v';
1314 break;
1315 default:
1316 write_buffer << next_char;
1317 break;
1318 }
1319 found_escape = false;
1320 }
1321 }
1322 else if(next_char == '\\')
1323 {
1324 found_escape = true;
1325 }
1326 else if(next_char == delim)
1327 {
1328 break;
1329 }
1330 else
1331 {
1332 write_buffer << next_char;
1333 }
1334 }
1335
1336 value = write_buffer.str();
1337 return true;
1338}
1339
1340bool deserialize_string_raw(std::istream& str, std::string& value)
1341{
1342 bool ok = false;
1343 const S32 BUF_LEN = 20;
1344 char buf[BUF_LEN]; /* Flawfinder: ignore */
1345 str.get(buf, BUF_LEN - 1, ')');
1346 char c = str.get();
1347 c = str.get();
1348 if(((c == '"') || (c == '\'')) && (buf[0] == '('))
1349 {
1350 // We probably have a valid raw string. determine
1351 // the size, and read it.
1352 // *FIX: Should we set a maximum size?
1353 // *FIX: This is memory inefficient.
1354 S32 len = strtol(buf + 1, NULL, 0);
1355 std::vector<char> buf;
1356 buf.resize(len);
1357 str.read(&buf[0], len); /*Flawfinder: ignore*/
1358 value.assign(buf.begin(), buf.end());
1359 c = str.get();
1360 if((c == '"') || (c == '\''))
1361 {
1362 ok = true;
1363 }
1364 }
1365 return ok;
1366}
1367
1368static const char* NOTATION_STRING_CHARACTERS[256] =
1369{
1370 "\\x00", // 0
1371 "\\x01", // 1
1372 "\\x02", // 2
1373 "\\x03", // 3
1374 "\\x04", // 4
1375 "\\x05", // 5
1376 "\\x06", // 6
1377 "\\a", // 7
1378 "\\b", // 8
1379 "\\t", // 9
1380 "\\n", // 10
1381 "\\v", // 11
1382 "\\f", // 12
1383 "\\r", // 13
1384 "\\x0e", // 14
1385 "\\x0f", // 15
1386 "\\x10", // 16
1387 "\\x11", // 17
1388 "\\x12", // 18
1389 "\\x13", // 19
1390 "\\x14", // 20
1391 "\\x15", // 21
1392 "\\x16", // 22
1393 "\\x17", // 23
1394 "\\x18", // 24
1395 "\\x19", // 25
1396 "\\x1a", // 26
1397 "\\x1b", // 27
1398 "\\x1c", // 28
1399 "\\x1d", // 29
1400 "\\x1e", // 30
1401 "\\x1f", // 31
1402 " ", // 32
1403 "!", // 33
1404 "\"", // 34
1405 "#", // 35
1406 "$", // 36
1407 "%", // 37
1408 "&", // 38
1409 "\\'", // 39
1410 "(", // 40
1411 ")", // 41
1412 "*", // 42
1413 "+", // 43
1414 ",", // 44
1415 "-", // 45
1416 ".", // 46
1417 "/", // 47
1418 "0", // 48
1419 "1", // 49
1420 "2", // 50
1421 "3", // 51
1422 "4", // 52
1423 "5", // 53
1424 "6", // 54
1425 "7", // 55
1426 "8", // 56
1427 "9", // 57
1428 ":", // 58
1429 ";", // 59
1430 "<", // 60
1431 "=", // 61
1432 ">", // 62
1433 "?", // 63
1434 "@", // 64
1435 "A", // 65
1436 "B", // 66
1437 "C", // 67
1438 "D", // 68
1439 "E", // 69
1440 "F", // 70
1441 "G", // 71
1442 "H", // 72
1443 "I", // 73
1444 "J", // 74
1445 "K", // 75
1446 "L", // 76
1447 "M", // 77
1448 "N", // 78
1449 "O", // 79
1450 "P", // 80
1451 "Q", // 81
1452 "R", // 82
1453 "S", // 83
1454 "T", // 84
1455 "U", // 85
1456 "V", // 86
1457 "W", // 87
1458 "X", // 88
1459 "Y", // 89
1460 "Z", // 90
1461 "[", // 91
1462 "\\\\", // 92
1463 "]", // 93
1464 "^", // 94
1465 "_", // 95
1466 "`", // 96
1467 "a", // 97
1468 "b", // 98
1469 "c", // 99
1470 "d", // 100
1471 "e", // 101
1472 "f", // 102
1473 "g", // 103
1474 "h", // 104
1475 "i", // 105
1476 "j", // 106
1477 "k", // 107
1478 "l", // 108
1479 "m", // 109
1480 "n", // 110
1481 "o", // 111
1482 "p", // 112
1483 "q", // 113
1484 "r", // 114
1485 "s", // 115
1486 "t", // 116
1487 "u", // 117
1488 "v", // 118
1489 "w", // 119
1490 "x", // 120
1491 "y", // 121
1492 "z", // 122
1493 "{", // 123
1494 "|", // 124
1495 "}", // 125
1496 "~", // 126
1497 "\\x7f", // 127
1498 "\\x80", // 128
1499 "\\x81", // 129
1500 "\\x82", // 130
1501 "\\x83", // 131
1502 "\\x84", // 132
1503 "\\x85", // 133
1504 "\\x86", // 134
1505 "\\x87", // 135
1506 "\\x88", // 136
1507 "\\x89", // 137
1508 "\\x8a", // 138
1509 "\\x8b", // 139
1510 "\\x8c", // 140
1511 "\\x8d", // 141
1512 "\\x8e", // 142
1513 "\\x8f", // 143
1514 "\\x90", // 144
1515 "\\x91", // 145
1516 "\\x92", // 146
1517 "\\x93", // 147
1518 "\\x94", // 148
1519 "\\x95", // 149
1520 "\\x96", // 150
1521 "\\x97", // 151
1522 "\\x98", // 152
1523 "\\x99", // 153
1524 "\\x9a", // 154
1525 "\\x9b", // 155
1526 "\\x9c", // 156
1527 "\\x9d", // 157
1528 "\\x9e", // 158
1529 "\\x9f", // 159
1530 "\\xa0", // 160
1531 "\\xa1", // 161
1532 "\\xa2", // 162
1533 "\\xa3", // 163
1534 "\\xa4", // 164
1535 "\\xa5", // 165
1536 "\\xa6", // 166
1537 "\\xa7", // 167
1538 "\\xa8", // 168
1539 "\\xa9", // 169
1540 "\\xaa", // 170
1541 "\\xab", // 171
1542 "\\xac", // 172
1543 "\\xad", // 173
1544 "\\xae", // 174
1545 "\\xaf", // 175
1546 "\\xb0", // 176
1547 "\\xb1", // 177
1548 "\\xb2", // 178
1549 "\\xb3", // 179
1550 "\\xb4", // 180
1551 "\\xb5", // 181
1552 "\\xb6", // 182
1553 "\\xb7", // 183
1554 "\\xb8", // 184
1555 "\\xb9", // 185
1556 "\\xba", // 186
1557 "\\xbb", // 187
1558 "\\xbc", // 188
1559 "\\xbd", // 189
1560 "\\xbe", // 190
1561 "\\xbf", // 191
1562 "\\xc0", // 192
1563 "\\xc1", // 193
1564 "\\xc2", // 194
1565 "\\xc3", // 195
1566 "\\xc4", // 196
1567 "\\xc5", // 197
1568 "\\xc6", // 198
1569 "\\xc7", // 199
1570 "\\xc8", // 200
1571 "\\xc9", // 201
1572 "\\xca", // 202
1573 "\\xcb", // 203
1574 "\\xcc", // 204
1575 "\\xcd", // 205
1576 "\\xce", // 206
1577 "\\xcf", // 207
1578 "\\xd0", // 208
1579 "\\xd1", // 209
1580 "\\xd2", // 210
1581 "\\xd3", // 211
1582 "\\xd4", // 212
1583 "\\xd5", // 213
1584 "\\xd6", // 214
1585 "\\xd7", // 215
1586 "\\xd8", // 216
1587 "\\xd9", // 217
1588 "\\xda", // 218
1589 "\\xdb", // 219
1590 "\\xdc", // 220
1591 "\\xdd", // 221
1592 "\\xde", // 222
1593 "\\xdf", // 223
1594 "\\xe0", // 224
1595 "\\xe1", // 225
1596 "\\xe2", // 226
1597 "\\xe3", // 227
1598 "\\xe4", // 228
1599 "\\xe5", // 229
1600 "\\xe6", // 230
1601 "\\xe7", // 231
1602 "\\xe8", // 232
1603 "\\xe9", // 233
1604 "\\xea", // 234
1605 "\\xeb", // 235
1606 "\\xec", // 236
1607 "\\xed", // 237
1608 "\\xee", // 238
1609 "\\xef", // 239
1610 "\\xf0", // 240
1611 "\\xf1", // 241
1612 "\\xf2", // 242
1613 "\\xf3", // 243
1614 "\\xf4", // 244
1615 "\\xf5", // 245
1616 "\\xf6", // 246
1617 "\\xf7", // 247
1618 "\\xf8", // 248
1619 "\\xf9", // 249
1620 "\\xfa", // 250
1621 "\\xfb", // 251
1622 "\\xfc", // 252
1623 "\\xfd", // 253
1624 "\\xfe", // 254
1625 "\\xff" // 255
1626};
1627
1628void serialize_string(const std::string& value, std::ostream& str)
1629{
1630 std::string::const_iterator it = value.begin();
1631 std::string::const_iterator end = value.end();
1632 U8 c;
1633 for(; it != end; ++it)
1634 {
1635 c = (U8)(*it);
1636 str << NOTATION_STRING_CHARACTERS[c];
1637 }
1638}
1639
1640