MMTF-C++
The C++ language MMTF libraries
map_decoder.hpp
Go to the documentation of this file.
1// *************************************************************************
2//
3// Licensed under the MIT License (see accompanying LICENSE file).
4//
5// The authors of this code are: Gabriel Studer, Gerardo Tauriello
6//
7// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
8// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
9// Gazal Kalyan, Alexander Rose.
10//
11// *************************************************************************
12
13#ifndef MMTF_MAP_DECODER_H
14#define MMTF_MAP_DECODER_H
15
16#include "structure_data.hpp"
17#include "binary_decoder.hpp"
18#include "errors.hpp"
19
20#include <msgpack.hpp>
21#include <map>
22#include <iostream>
23
24namespace mmtf {
25
30public:
37 MapDecoder(const msgpack::object& obj);
38
51 template<typename T>
52 void decode(const std::string& key, bool required, T& target);
53
59 void checkExtraKeys();
60
61private:
62 // key-value pairs extracted from msgpack map
63 std::map<std::string, msgpack::object*> data_map_;
64 // set of keys that were successfully decoded
65 std::set<std::string> decoded_keys_;
66
67 // type checking (note: doesn't check array elements)
68 // -> only writes warning to cerr
69 // -> exception thrown by msgpack if conversion fails
70 void checkType_(const std::string& key, msgpack::type::object_type type,
71 const float& target);
72 void checkType_(const std::string& key, msgpack::type::object_type type,
73 const int32_t& target);
74 void checkType_(const std::string& key, msgpack::type::object_type type,
75 const char& target);
76 void checkType_(const std::string& key, msgpack::type::object_type type,
77 const std::string& target);
78 template <typename T>
79 void checkType_(const std::string& key, msgpack::type::object_type type,
80 const std::vector<T>& target);
81 template <typename T>
82 void checkType_(const std::string& key, msgpack::type::object_type type,
83 T* target);
84};
85
86// *************************************************************************
87// IMPLEMENTATION
88// *************************************************************************
89
90inline MapDecoder::MapDecoder(const msgpack::object& obj) {
91 // sanity checks
92 if (obj.type != msgpack::type::MAP) {
93 throw DecodeError("Expected msgpack type to be MAP");
94 }
95 // get data
96 msgpack::object_kv* current_key_value = obj.via.map.ptr;
97 msgpack::object_kv* last_key_value = current_key_value + obj.via.map.size;
98 for (; current_key_value != last_key_value; ++current_key_value) {
99 msgpack::object* key = &(current_key_value->key);
100 msgpack::object* value = &(current_key_value->val);
101 if (key->type == msgpack::type::STR) {
102 std::string data_map_key(key->via.str.ptr, key->via.str.size);
103 data_map_[data_map_key] = value;
104 } else {
105 std::cerr << "Warning: Found non-string key type " << key->type
106 << "! Skipping..." << std::endl;
107 }
108 }
109}
110
111template<typename T>
112void MapDecoder::decode(const std::string& key, bool required, T& target) {
113 // note: cost of O(M*log(N)) string comparisons (M parsed, N in map)
114 std::map<std::string, msgpack::object*>::iterator it;
115 it = data_map_.find(key);
116 if (it != data_map_.end()) {
117 checkType_(key, it->second->type, target);
118 if (it->second->type == msgpack::type::BIN) {
119 BinaryDecoder bd(*it->second, key);
120 bd.decode(target);
121 } else {
122 it->second->convert(target);
123 }
124 decoded_keys_.insert(key);
125 }
126 else if (required) {
127 throw DecodeError("MsgPack MAP does not contain required entry "
128 + key);
129 }
130}
131
133 // note: cost of O(N*log(M))) string comparisons (M parsed, N in map)
134 // simple set difference algorithm
135 std::map<std::string, msgpack::object*>::iterator map_it;
136 std::set<std::string>::iterator parsed_it;
137 for (map_it = data_map_.begin(); map_it != data_map_.end(); ++map_it) {
138 parsed_it = decoded_keys_.find(map_it->first);
139 if (parsed_it == decoded_keys_.end()) {
140 std::cerr << "Warning: Found non-parsed key " << map_it->first
141 << " in MsgPack MAP.\n";
142 }
143 }
144}
145
146inline void MapDecoder::checkType_(const std::string& key,
147 msgpack::type::object_type type,
148 const float& target) {
149 if (type != msgpack::type::FLOAT32 && type != msgpack::type::FLOAT64) {
150 std::cerr << "Warning: Non-float type " << type << " found for "
151 "entry " << key << std::endl;
152 }
153}
154inline void MapDecoder::checkType_(const std::string& key,
155 msgpack::type::object_type type,
156 const int32_t& target) {
157 if ( type != msgpack::type::POSITIVE_INTEGER
158 && type != msgpack::type::NEGATIVE_INTEGER) {
159 std::cerr << "Warning: Non-int type " << type << " found for "
160 "entry " << key << std::endl;
161 }
162}
163inline void MapDecoder::checkType_(const std::string& key,
164 msgpack::type::object_type type,
165 const char& target) {
166 if (type != msgpack::type::STR) {
167 std::cerr << "Warning: Non-string type " << type << " found for "
168 "entry " << key << std::endl;
169 }
170}
171inline void MapDecoder::checkType_(const std::string& key,
172 msgpack::type::object_type type,
173 const std::string& target) {
174 if (type != msgpack::type::STR) {
175 std::cerr << "Warning: Non-string type " << type << " found for "
176 "entry " << key << std::endl;
177 }
178}
179template <typename T>
180void MapDecoder::checkType_(const std::string& key,
181 msgpack::type::object_type type,
182 const std::vector<T>& target) {
183 if (type != msgpack::type::ARRAY && type != msgpack::type::BIN) {
184 std::cerr << "Warning: Non-array type " << type << " found for "
185 "entry " << key << std::endl;
186 }
187}
188template <typename T>
189void MapDecoder::checkType_(const std::string& key,
190 msgpack::type::object_type type,
191 T* target) {
192 if (type != msgpack::type::ARRAY && type != msgpack::type::BIN) {
193 std::cerr << "Warning: Non-array type " << type << " found for "
194 "entry " << key << std::endl;
195 }
196}
197
198} // mmtf namespace
199
200#endif
Helper class to decode msgpack binary into a vector.
Definition: binary_decoder.hpp:29
void decode(T &target)
Decode binary msgpack object into the given target.
Definition: binary_decoder.hpp:185
Exception thrown when failing during decoding.
Definition: errors.hpp:23
Helper class to decode msgpack maps into object fields.
Definition: map_decoder.hpp:29
void decode(const std::string &key, bool required, T &target)
Extract value from map and decode into target.
Definition: map_decoder.hpp:112
void checkExtraKeys()
Check if there are any keys, that were not decoded. This is to be called after all expected fields ha...
Definition: map_decoder.hpp:132
MapDecoder(const msgpack::object &obj)
Initialize object given a msgpack object. Reads out all key-value pairs and converts key to string if...
Definition: map_decoder.hpp:90
Definition: binary_decoder.hpp:24