|
27 | 27 | #include <string>
|
28 | 28 | #include <stdexcept>
|
29 | 29 | #include <vector>
|
| 30 | +#include <unordered_map> |
30 | 31 | #include <map>
|
| 32 | +#include <deque> |
31 | 33 | #include <iostream>
|
32 | 34 |
|
33 | 35 | #include <rapidjson/pointer.h>
|
@@ -206,7 +208,7 @@ inline void ParseJson(rapidjson::Value& r, rapidjson::Document::AllocatorType& a
|
206 | 208 | throw MujinJSONException(boost::str(boost::format("Json stream is invalid (offset %u) %s")%((unsigned)rTemp.GetErrorOffset())%GetParseError_En(rTemp.GetParseError())));
|
207 | 209 | }
|
208 | 210 | r.Swap(rTemp);
|
209 |
| - |
| 211 | + |
210 | 212 | // rapidjson::ParseResult parseResult = reader.template Parse<rapidjson::kParseFullPrecisionFlag>(isw, rTemp);
|
211 | 213 | // if( parseResult.IsError() ) {
|
212 | 214 | // *stack_.template Pop<ValueType>(1)
|
@@ -490,17 +492,60 @@ template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::map<
|
490 | 492 | }
|
491 | 493 | } else if (v.IsObject()) {
|
492 | 494 | t.clear();
|
493 |
| - U value; |
494 | 495 | for (rapidjson::Value::ConstMemberIterator it = v.MemberBegin();
|
495 | 496 | it != v.MemberEnd(); ++it) {
|
496 |
| - LoadJsonValue(it->value, value); |
497 |
| - t[std::string(it->name.GetString(), it->name.GetStringLength())] = value; // string can contain null character |
| 497 | + // Deserialize directly into the map to avoid copying temporaries. |
| 498 | + // Note that our key needs to be explicitly length-constructed since |
| 499 | + // it may contain \0 bytes. |
| 500 | + LoadJsonValue(it->value, |
| 501 | + t[std::string(it->name.GetString(), |
| 502 | + it->name.GetStringLength())]); |
498 | 503 | }
|
499 | 504 | } else {
|
500 | 505 | throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to Map");
|
501 | 506 | }
|
502 | 507 | }
|
503 | 508 |
|
| 509 | +template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::deque<U>& t) { |
| 510 | + // It doesn't make sense to construct a deque from anything other than a JSON array |
| 511 | + if (!v.IsArray()) { |
| 512 | + throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to deque"); |
| 513 | + } |
| 514 | + |
| 515 | + // Ensure our output is a blank slate |
| 516 | + t.clear(); |
| 517 | + |
| 518 | + // Preallocate to fit the incoming data. Deque has no reserve, only resize. |
| 519 | + t.resize(v.Size()); |
| 520 | + |
| 521 | + // Iterate each array entry and attempt to deserialize it directly as a member type |
| 522 | + typename std::deque<U>::size_type emplaceIndex = 0; |
| 523 | + for (rapidjson::Value::ConstValueIterator it = v.Begin(); it != v.End(); ++it) { |
| 524 | + // Deserialize directly into the map to avoid copying temporaries. |
| 525 | + LoadJsonValue(*it, t[emplaceIndex++]); |
| 526 | + } |
| 527 | +} |
| 528 | + |
| 529 | +template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::unordered_map<std::string, U>& t) { |
| 530 | + // It doesn't make sense to construct an unordered map from anything other |
| 531 | + // than a full JSON object |
| 532 | + if (!v.IsObject()) { |
| 533 | + throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to unordered_map"); |
| 534 | + } |
| 535 | + |
| 536 | + // Ensure our output is a blank slate |
| 537 | + t.clear(); |
| 538 | + for (rapidjson::Value::ConstMemberIterator it = v.MemberBegin(); |
| 539 | + it != v.MemberEnd(); ++it) { |
| 540 | + // Deserialize directly into the map to avoid copying temporaries. |
| 541 | + // Note that our key needs to be explicitly length-constructed since it |
| 542 | + // may contain \0 bytes. |
| 543 | + LoadJsonValue( |
| 544 | + it->value, |
| 545 | + t[std::string(it->name.GetString(), it->name.GetStringLength())]); |
| 546 | + } |
| 547 | +} |
| 548 | + |
504 | 549 | //Save a data structure to rapidjson::Value format
|
505 | 550 |
|
506 | 551 | /*template<class T> inline void SaveJsonValue(rapidjson::Value& v, const T& t, rapidjson::Document::AllocatorType& alloc) {*/
|
@@ -650,6 +695,26 @@ template<class U> inline void SaveJsonValue(rapidjson::Value& v, const std::map<
|
650 | 695 | }
|
651 | 696 | }
|
652 | 697 |
|
| 698 | +template<class U> inline void SaveJsonValue(rapidjson::Value& v, const std::unordered_map<std::string, U>& t, rapidjson::Document::AllocatorType& alloc) { |
| 699 | + v.SetObject(); |
| 700 | + for (typename std::unordered_map<std::string, U>::const_iterator it = t.begin(); it != t.end(); ++it) { |
| 701 | + rapidjson::Value name, value; |
| 702 | + SaveJsonValue(name, it->first, alloc); |
| 703 | + SaveJsonValue(value, it->second, alloc); |
| 704 | + v.AddMember(name, value, alloc); |
| 705 | + } |
| 706 | +} |
| 707 | + |
| 708 | +template <class T, class AllocT> inline void SaveJsonValue(rapidjson::Value& v, const std::deque<T, AllocT>& t, rapidjson::Document::AllocatorType& alloc) { |
| 709 | + v.SetArray(); |
| 710 | + v.Reserve(t.size(), alloc); |
| 711 | + for (typename std::deque<T, AllocT>::const_iterator it = t.begin(); it != t.end(); ++it) { |
| 712 | + rapidjson::Value value; |
| 713 | + SaveJsonValue(value, *it, alloc); |
| 714 | + v.PushBack(value, alloc); |
| 715 | + } |
| 716 | +} |
| 717 | + |
653 | 718 | template<class T> inline void SaveJsonValue(rapidjson::Document& v, const T& t) {
|
654 | 719 | // rapidjson::Value::CopyFrom also doesn't free up memory, need to clear memory
|
655 | 720 | // see note in: void ParseJson(rapidjson::Document& d, const std::string& str)
|
|
0 commit comments