Line data Source code
1 : /*
2 : * Distributed under the OpenDDS License.
3 : * See: http://www.opendds.org/license.html
4 : */
5 :
6 : #ifndef OPENDDS_DCPS_JSON_VALUE_READER_H
7 : #define OPENDDS_DCPS_JSON_VALUE_READER_H
8 :
9 : #if defined OPENDDS_RAPIDJSON && !defined OPENDDS_SAFETY_PROFILE
10 : # define OPENDDS_HAS_JSON_VALUE_READER 1
11 : #else
12 : # define OPENDDS_HAS_JSON_VALUE_READER 0
13 : #endif
14 :
15 : #if OPENDDS_HAS_JSON_VALUE_READER
16 :
17 : #include "dcps_export.h"
18 : #include "ValueReader.h"
19 : #include "RapidJsonWrapper.h"
20 : #include "TypeSupportImpl.h"
21 : #include "Definitions.h"
22 :
23 : #include <iosfwd>
24 : #include <sstream>
25 :
26 : #if !defined (ACE_LACKS_PRAGMA_ONCE)
27 : #pragma once
28 : #endif /* ACE_LACKS_PRAGMA_ONCE */
29 :
30 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
31 :
32 : namespace OpenDDS {
33 : namespace DCPS {
34 :
35 : /// Convert JSON to values.
36 : template <typename InputStream = rapidjson::StringStream>
37 : class JsonValueReader
38 : : public ValueReader,
39 : public rapidjson::BaseReaderHandler<rapidjson::UTF8<> > {
40 : public:
41 13 : explicit JsonValueReader(InputStream& input_stream)
42 13 : : token_type_(kUnknown)
43 13 : , input_stream_(input_stream)
44 13 : , bool_value_(false)
45 13 : , int_value_(0)
46 13 : , uint_value_(0)
47 13 : , int64_value_(0)
48 13 : , uint64_value_(0)
49 13 : , double_value_(0)
50 : {
51 13 : reader_.IterativeParseInit();
52 13 : }
53 :
54 : bool begin_struct();
55 : bool end_struct();
56 : bool begin_struct_member(XTypes::MemberId& member_id, const MemberHelper& helper);
57 : bool end_struct_member();
58 :
59 : bool begin_union();
60 : bool end_union();
61 : bool begin_discriminator();
62 : bool end_discriminator();
63 : bool begin_union_member();
64 : bool end_union_member();
65 :
66 : bool begin_array();
67 : bool end_array();
68 : bool begin_sequence();
69 : bool elements_remaining();
70 : bool end_sequence();
71 : bool begin_element();
72 : bool end_element();
73 :
74 : bool read_boolean(ACE_CDR::Boolean& value);
75 : bool read_byte(ACE_CDR::Octet& value);
76 : #if OPENDDS_HAS_EXPLICIT_INTS
77 : bool read_int8(ACE_CDR::Int8& value);
78 : bool read_uint8(ACE_CDR::UInt8& value);
79 : #endif
80 : bool read_int16(ACE_CDR::Short& value);
81 : bool read_uint16(ACE_CDR::UShort& value);
82 : bool read_int32(ACE_CDR::Long& value);
83 : bool read_uint32(ACE_CDR::ULong& value);
84 : bool read_int64(ACE_CDR::LongLong& value);
85 : bool read_uint64(ACE_CDR::ULongLong& value);
86 : bool read_float32(ACE_CDR::Float& value);
87 : bool read_float64(ACE_CDR::Double& value);
88 : bool read_float128(ACE_CDR::LongDouble& value);
89 : bool read_fixed(OpenDDS::FaceTypes::Fixed& value);
90 : bool read_char8(ACE_CDR::Char& value);
91 : bool read_char16(ACE_CDR::WChar& value);
92 : bool read_string(std::string& value);
93 : bool read_wstring(std::wstring& value);
94 : bool read_long_enum(ACE_CDR::Long& value, const EnumHelper& helper);
95 :
96 0 : bool Null() { token_type_ = kNull; return true; }
97 8 : bool Bool(bool b) { token_type_ = kBool; bool_value_ = b; return true; }
98 3 : bool Int(int i) { token_type_ = kInt; int_value_ = i; return true; }
99 53 : bool Uint(unsigned i) { token_type_ = kUint; uint_value_ = i; return true; }
100 1 : bool Int64(int64_t i) { token_type_ = kInt64; int64_value_ = i; return true; }
101 2 : bool Uint64(uint64_t i) { token_type_ = kUint64; uint64_value_ = i; return true; }
102 9 : bool Double(double d) { token_type_ = kDouble; double_value_ = d; return true; }
103 : bool RawNumber(const Ch* /* str */, rapidjson::SizeType /* length */, bool /* copy */) { token_type_ = kRawNumber; return true; }
104 12 : bool String(const Ch* str, rapidjson::SizeType length, bool /* copy */)
105 : {
106 12 : token_type_ = kString;
107 12 : string_value_ = std::string(str, length);
108 12 : return true;
109 : }
110 10 : bool StartObject() { token_type_ = kStartObject; return true; }
111 41 : bool Key(const Ch* str, rapidjson::SizeType /* length */, bool /* copy */) { token_type_ = kKey; key_value_ = str; return true; }
112 10 : bool EndObject(rapidjson::SizeType /* memberCount */) { token_type_ = kEndObject; return true; }
113 9 : bool StartArray() { token_type_ = kStartArray; return true; }
114 9 : bool EndArray(rapidjson::SizeType /* elementCount */) { token_type_ = kEndArray; return true; }
115 :
116 : private:
117 : enum TokenType {
118 : kUnknown,
119 : kNull,
120 : kBool,
121 : kInt,
122 : kUint,
123 : kInt64,
124 : kUint64,
125 : kDouble,
126 : kRawNumber,
127 : kString,
128 : kStartObject,
129 : kKey,
130 : kEndObject,
131 : kStartArray,
132 : kEndArray,
133 : kError,
134 : kEnd
135 : };
136 :
137 201 : TokenType peek()
138 : {
139 201 : if (token_type_ != kUnknown) {
140 34 : return token_type_;
141 : }
142 :
143 167 : if (reader_.IterativeParseComplete()) {
144 0 : token_type_ = kEnd;
145 0 : return token_type_;
146 : }
147 :
148 167 : if (!reader_.IterativeParseNext<rapidjson::kParseStopWhenDoneFlag>(input_stream_, *this)) {
149 0 : token_type_ = kError;
150 : }
151 :
152 167 : return token_type_;
153 : }
154 :
155 167 : bool consume(TokenType expected)
156 : {
157 167 : if (token_type_ == expected) {
158 167 : token_type_ = kUnknown;
159 167 : return true;
160 : }
161 0 : return false;
162 : }
163 :
164 : // consume tokens until peek() would return 'expected'
165 : // skips over objects and arrays atomically
166 3 : bool skip_to(TokenType expected)
167 : {
168 3 : int skip_level = 0;
169 :
170 40 : while (peek() != kEnd) {
171 40 : if (skip_level == 0 && token_type_ == expected) {
172 3 : return true;
173 : }
174 37 : switch (token_type_) {
175 6 : case kStartArray:
176 : case kStartObject:
177 6 : ++skip_level;
178 6 : break;
179 6 : case kEndArray:
180 : case kEndObject:
181 6 : --skip_level;
182 6 : break;
183 25 : default:
184 25 : break;
185 : }
186 37 : consume(token_type_);
187 : }
188 :
189 0 : return false;
190 : }
191 :
192 : TokenType token_type_;
193 : InputStream& input_stream_;
194 : rapidjson::Reader reader_;
195 : bool bool_value_;
196 : int int_value_;
197 : unsigned int uint_value_;
198 : int64_t int64_value_;
199 : uint64_t uint64_value_;
200 : double double_value_;
201 : std::string string_value_;
202 : std::string key_value_;
203 : };
204 :
205 : template <typename InputStream>
206 6 : bool JsonValueReader<InputStream>::begin_struct()
207 : {
208 6 : peek();
209 6 : return consume(kStartObject);
210 : }
211 :
212 : template <typename InputStream>
213 6 : bool JsonValueReader<InputStream>::end_struct()
214 : {
215 6 : if (peek() == kKey) { // skip any unknown members at the end
216 1 : if (!skip_to(kEndObject)) {
217 0 : return false;
218 : }
219 : }
220 6 : return consume(kEndObject);
221 : }
222 :
223 : template <typename InputStream>
224 30 : bool JsonValueReader<InputStream>::begin_struct_member(XTypes::MemberId& member_id, const MemberHelper& helper)
225 : {
226 32 : while (peek() == kKey) {
227 32 : consume(kKey);
228 32 : if (helper.get_value(member_id, key_value_.c_str())) {
229 30 : return true;
230 : }
231 2 : if (!skip_to(kKey)) { // skip unknown members when expecting a known member
232 0 : return false;
233 : }
234 : }
235 0 : return false;
236 : }
237 :
238 : template <typename InputStream>
239 30 : bool JsonValueReader<InputStream>::end_struct_member()
240 : {
241 30 : return true;
242 : }
243 :
244 : template <typename InputStream>
245 1 : bool JsonValueReader<InputStream>::begin_union()
246 : {
247 1 : peek();
248 1 : return consume(kStartObject);
249 : }
250 :
251 : template <typename InputStream>
252 1 : bool JsonValueReader<InputStream>::end_union()
253 : {
254 1 : peek();
255 1 : return consume(kEndObject);
256 : }
257 :
258 : template <typename InputStream>
259 1 : bool JsonValueReader<InputStream>::begin_discriminator()
260 : {
261 1 : if (peek() == kKey && key_value_ == "$discriminator") {
262 1 : return consume(kKey);
263 : }
264 0 : return false;
265 : }
266 :
267 : template <typename InputStream>
268 1 : bool JsonValueReader<InputStream>::end_discriminator()
269 : {
270 1 : return true;
271 : }
272 :
273 : template <typename InputStream>
274 1 : bool JsonValueReader<InputStream>::begin_union_member()
275 : {
276 1 : if (peek() == kKey) {
277 1 : return consume(kKey);
278 : }
279 0 : return false;
280 : }
281 :
282 : template <typename InputStream>
283 1 : bool JsonValueReader<InputStream>::end_union_member()
284 : {
285 1 : return true;
286 : }
287 :
288 : template <typename InputStream>
289 3 : bool JsonValueReader<InputStream>::begin_array()
290 : {
291 3 : peek();
292 3 : return consume(kStartArray);
293 : }
294 :
295 : template <typename InputStream>
296 3 : bool JsonValueReader<InputStream>::end_array()
297 : {
298 3 : peek();
299 3 : return consume(kEndArray);
300 : }
301 :
302 : template <typename InputStream>
303 3 : bool JsonValueReader<InputStream>::begin_sequence()
304 : {
305 3 : peek();
306 3 : return consume(kStartArray);
307 : }
308 :
309 : template <typename InputStream>
310 21 : bool JsonValueReader<InputStream>::elements_remaining()
311 : {
312 21 : peek();
313 21 : return token_type_ != kEndArray;
314 : }
315 :
316 : template <typename InputStream>
317 3 : bool JsonValueReader<InputStream>::end_sequence()
318 : {
319 3 : peek();
320 3 : return consume(kEndArray);
321 : }
322 :
323 : template <typename InputStream>
324 38 : bool JsonValueReader<InputStream>::begin_element()
325 : {
326 38 : return true;
327 : }
328 :
329 : template <typename InputStream>
330 38 : bool JsonValueReader<InputStream>::end_element()
331 : {
332 38 : return true;
333 : }
334 :
335 : template <typename InputStream>
336 8 : bool JsonValueReader<InputStream>::read_boolean(ACE_CDR::Boolean& value)
337 : {
338 8 : if (peek() == kBool) {
339 8 : value = bool_value_;
340 8 : return consume(kBool);
341 : }
342 0 : return false;
343 : }
344 :
345 : template <typename InputStream>
346 6 : bool JsonValueReader<InputStream>::read_byte(ACE_CDR::Octet& value)
347 : {
348 6 : if (peek() == kUint) {
349 6 : value = uint_value_;
350 6 : return consume(kUint);
351 : }
352 0 : return false;
353 : }
354 :
355 : #if OPENDDS_HAS_EXPLICIT_INTS
356 : template <typename InputStream>
357 3 : bool JsonValueReader<InputStream>::read_int8(ACE_CDR::Int8& value)
358 : {
359 3 : switch (peek()) {
360 1 : case kInt:
361 1 : value = int_value_;
362 1 : return consume(kInt);
363 2 : case kUint:
364 2 : value = uint_value_;
365 2 : return consume(kUint);
366 0 : default:
367 0 : return false;
368 : }
369 : }
370 :
371 : template <typename InputStream>
372 3 : bool JsonValueReader<InputStream>::read_uint8(ACE_CDR::UInt8& value)
373 : {
374 3 : if (peek() == kUint) {
375 3 : value = uint_value_;
376 3 : return consume(kUint);
377 : }
378 0 : return false;
379 : }
380 : #endif
381 :
382 : template <typename InputStream>
383 10 : bool JsonValueReader<InputStream>::read_int16(ACE_CDR::Short& value)
384 : {
385 10 : peek();
386 10 : switch (peek()) {
387 1 : case kInt:
388 1 : value = int_value_;
389 1 : return consume(kInt);
390 9 : case kUint:
391 9 : value = uint_value_;
392 9 : return consume(kUint);
393 0 : default:
394 0 : return false;
395 : }
396 : }
397 :
398 : template <typename InputStream>
399 6 : bool JsonValueReader<InputStream>::read_uint16(ACE_CDR::UShort& value)
400 : {
401 6 : if (peek() == kUint) {
402 6 : value = uint_value_;
403 6 : return consume(kUint);
404 : }
405 0 : return false;
406 : }
407 :
408 : template <typename InputStream>
409 4 : bool JsonValueReader<InputStream>::read_int32(ACE_CDR::Long& value)
410 : {
411 4 : switch (peek()) {
412 1 : case kInt:
413 1 : value = int_value_;
414 1 : return consume(kInt);
415 3 : case kUint:
416 3 : value = uint_value_;
417 3 : return consume(kUint);
418 0 : default:
419 0 : return false;
420 : }
421 : }
422 :
423 : template <typename InputStream>
424 3 : bool JsonValueReader<InputStream>::read_uint32(ACE_CDR::ULong& value)
425 : {
426 3 : if (peek() == kUint) {
427 3 : value = uint_value_;
428 3 : return consume(kUint);
429 : }
430 0 : return false;
431 : }
432 :
433 : template <typename InputStream>
434 3 : bool JsonValueReader<InputStream>::read_int64(ACE_CDR::LongLong& value)
435 : {
436 3 : switch (peek()) {
437 1 : case kInt64:
438 1 : value = int64_value_;
439 1 : return consume(kInt64);
440 1 : case kUint64:
441 1 : value = uint64_value_;
442 1 : return consume(kUint64);
443 0 : case kInt:
444 0 : value = int_value_;
445 0 : return consume(kInt);
446 1 : case kUint:
447 1 : value = uint_value_;
448 1 : return consume(kUint);
449 0 : default:
450 0 : return false;
451 : }
452 : }
453 :
454 : template <typename InputStream>
455 3 : bool JsonValueReader<InputStream>::read_uint64(ACE_CDR::ULongLong& value)
456 : {
457 3 : switch (peek()) {
458 1 : case kUint64:
459 1 : value = uint64_value_;
460 1 : return consume(kUint64);
461 2 : case kUint:
462 2 : value = uint_value_;
463 2 : return consume(kUint);
464 0 : default:
465 0 : return false;
466 : }
467 : }
468 :
469 : template <typename InputStream>
470 3 : bool JsonValueReader<InputStream>::read_float32(ACE_CDR::Float& value)
471 : {
472 3 : switch (peek()) {
473 2 : case kDouble:
474 2 : value = ACE_CDR::Float(double_value_);
475 2 : return consume(kDouble);
476 0 : case kUint64:
477 0 : value = ACE_CDR::Float(uint64_value_);
478 0 : return consume(kUint64);
479 1 : case kUint:
480 1 : value = ACE_CDR::Float(uint_value_);
481 1 : return consume(kUint);
482 0 : case kInt64:
483 0 : value = ACE_CDR::Float(int64_value_);
484 0 : return consume(kInt64);
485 0 : case kInt:
486 0 : value = ACE_CDR::Float(int_value_);
487 0 : return consume(kUint);
488 0 : default:
489 0 : return false;
490 : }
491 : }
492 :
493 : template <typename InputStream>
494 3 : bool JsonValueReader<InputStream>::read_float64(ACE_CDR::Double& value)
495 : {
496 3 : switch (peek()) {
497 2 : case kDouble:
498 2 : value = double_value_;
499 2 : return consume(kDouble);
500 0 : case kUint64:
501 0 : value = ACE_CDR::Double(uint64_value_);
502 0 : return consume(kUint64);
503 1 : case kUint:
504 1 : value = uint_value_;
505 1 : return consume(kUint);
506 0 : case kInt64:
507 0 : value = ACE_CDR::Double(int64_value_);
508 0 : return consume(kInt64);
509 0 : case kInt:
510 0 : value = int_value_;
511 0 : return consume(kUint);
512 0 : default:
513 0 : return false;
514 : }
515 : }
516 :
517 : template <typename InputStream>
518 3 : bool JsonValueReader<InputStream>::read_float128(ACE_CDR::LongDouble& value)
519 : {
520 3 : switch (peek()) {
521 2 : case kDouble:
522 2 : ACE_CDR_LONG_DOUBLE_ASSIGNMENT(value, double_value_);
523 2 : return consume(kDouble);
524 0 : case kUint64:
525 : #ifdef ACE_WIN32
526 : # pragma warning(disable:4244)
527 : #endif
528 0 : ACE_CDR_LONG_DOUBLE_ASSIGNMENT(value, uint64_value_);
529 : #ifdef ACE_WIN32
530 : # pragma warning(default:4244)
531 : #endif
532 0 : return consume(kUint64);
533 1 : case kUint:
534 1 : ACE_CDR_LONG_DOUBLE_ASSIGNMENT(value, uint_value_);
535 1 : return consume(kUint);
536 0 : case kInt64:
537 : #ifdef ACE_WIN32
538 : # pragma warning(disable:4244)
539 : #endif
540 0 : ACE_CDR_LONG_DOUBLE_ASSIGNMENT(value, int64_value_);
541 : #ifdef ACE_WIN32
542 : # pragma warning(default:4244)
543 : #endif
544 0 : return consume(kInt64);
545 0 : case kInt:
546 0 : ACE_CDR_LONG_DOUBLE_ASSIGNMENT(value, int_value_);
547 0 : return consume(kUint);
548 0 : default:
549 0 : return false;
550 : }
551 : }
552 :
553 : template <typename InputStream>
554 0 : bool JsonValueReader<InputStream>::read_fixed(OpenDDS::FaceTypes::Fixed& /*value*/)
555 : {
556 : // TODO
557 0 : if (peek() == kString) {
558 0 : return consume(kString);
559 : }
560 0 : return false;
561 : }
562 :
563 : template <typename InputStream>
564 3 : bool JsonValueReader<InputStream>::read_char8(ACE_CDR::Char& value)
565 : {
566 3 : if (peek() == kString) {
567 3 : if (string_value_.length() == 1) {
568 3 : value = string_value_[0];
569 3 : return consume(kString);
570 : }
571 : }
572 0 : return false;
573 : }
574 :
575 : template <typename InputStream>
576 3 : bool JsonValueReader<InputStream>::read_char16(ACE_CDR::WChar& value)
577 : {
578 3 : if (peek() == kString) {
579 3 : rapidjson::StringStream source(string_value_.c_str());
580 3 : rapidjson::GenericStringBuffer<rapidjson::UTF16<> > target;
581 :
582 6 : while (source.Tell() != string_value_.size()) {
583 3 : if (!rapidjson::Transcoder<rapidjson::UTF8<>, rapidjson::UTF16<> >::Transcode(source, target)) {
584 0 : return false;
585 : }
586 : }
587 :
588 3 : if (target.GetLength() == 1) {
589 3 : value = target.GetString()[0];
590 3 : return consume(kString);
591 : }
592 3 : }
593 0 : return false;
594 : }
595 :
596 : template <typename InputStream>
597 3 : bool JsonValueReader<InputStream>::read_string(std::string& value)
598 : {
599 3 : if (peek() == kString) {
600 3 : value = string_value_;
601 3 : return consume(kString);
602 : }
603 0 : return false;
604 : }
605 :
606 : template <typename InputStream>
607 0 : bool JsonValueReader<InputStream>::read_wstring(std::wstring& value)
608 : {
609 0 : if (peek() == kString) {
610 0 : rapidjson::StringStream source(string_value_.c_str());
611 0 : rapidjson::GenericStringBuffer<rapidjson::UTF16<> > target;
612 :
613 0 : while (source.Tell() != string_value_.size()) {
614 0 : if (!rapidjson::Transcoder<rapidjson::UTF8<>, rapidjson::UTF16<> >::Transcode(source, target)) {
615 0 : return false;
616 : }
617 : }
618 :
619 0 : value = target.GetString();
620 0 : return consume(kString);
621 0 : }
622 0 : return false;
623 : }
624 :
625 : template <typename InputStream>
626 3 : bool JsonValueReader<InputStream>::read_long_enum(ACE_CDR::Long& value, const EnumHelper& helper)
627 : {
628 3 : switch (peek()) {
629 3 : case kString:
630 3 : if (helper.get_value(value, string_value_.c_str())) {
631 3 : return consume(kString);
632 : }
633 0 : return false;
634 : break;
635 0 : case kInt:
636 0 : value = int_value_;
637 0 : return consume(kInt);
638 0 : case kUint:
639 0 : value = uint_value_;
640 0 : return consume(kUint);
641 0 : default:
642 0 : return false;
643 : }
644 : }
645 :
646 : template<typename T, typename InputStream>
647 1 : bool from_json(T& value, InputStream& stream)
648 : {
649 1 : set_default(value);
650 1 : JsonValueReader<InputStream> jvr(stream);
651 2 : return vread(jvr, value);
652 1 : }
653 :
654 : } // namespace DCPS
655 : } // namespace OpenDDS
656 :
657 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
658 :
659 : #endif
660 :
661 : #endif /* OPENDDS_DCPS_JSON_VALUE_READER_H */
|