MMTF-C++
The C++ language MMTF libraries
Loading...
Searching...
No Matches
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, and
6// Daniel Farrell.
7//
8// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
9// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
10// Gazal Kalyan, Alexander Rose.
11//
12// *************************************************************************
13
14#ifndef MMTF_MAP_DECODER_H
15#define MMTF_MAP_DECODER_H
16
17#include "structure_data.hpp"
18#include "binary_decoder.hpp"
19#include "errors.hpp"
20
21#include <msgpack.hpp>
22#include <map>
23#include <iostream>
24
25namespace mmtf {
26
32public:
33
38
45 MapDecoder(const msgpack::object& obj);
46
52 MapDecoder(const std::map<std::string, msgpack::object>& map_in);
53
59 void initFromObject(const msgpack::object& obj);
64 void initFromBuffer(const char* buffer, size_t size);
65
78 template<typename T>
79 void decode(const std::string& key, bool required, T& target) const;
80
97 void
98 copy_decode(const std::string& key, bool required,
99 std::map<std::string, msgpack::object>& target,
100 msgpack::zone& zone) const;
101
107 void checkExtraKeys() const;
108
109private:
110 // when constructed with byte buffer, we keep unpacked object
111 // NOTE: this contains a unique pointer to msgpack data (cannot copy)
112 msgpack::object_handle object_handle_;
113 // key-value pairs extracted from msgpack map
114 typedef std::map<std::string, const msgpack::object*> data_map_type_;
115 data_map_type_ data_map_;
116 // set of keys that were successfully decoded
117 mutable std::set<std::string> decoded_keys_;
118
123 void init_from_msgpack_obj(const msgpack::object& obj);
124
125 // type checking (note: doesn't check array elements)
126 // -> only writes warning to cerr
127 // -> exception thrown by msgpack if conversion fails
128 void checkType_(const std::string& key, msgpack::type::object_type type,
129 const float& target) const;
130 void checkType_(const std::string& key, msgpack::type::object_type type,
131 const int32_t& target) const;
132 void checkType_(const std::string& key, msgpack::type::object_type type,
133 const char& target) const;
134 void checkType_(const std::string& key, msgpack::type::object_type type,
135 const std::string& target) const;
136 template <typename T>
137 void checkType_(const std::string& key, msgpack::type::object_type type,
138 const std::vector<T>& target) const;
139 template <typename T>
140 void checkType_(const std::string& key, msgpack::type::object_type type,
141 const T& target) const;
142};
143
144// *************************************************************************
145// IMPLEMENTATION
146// *************************************************************************
147
148inline MapDecoder::MapDecoder(const msgpack::object& obj) {
149 init_from_msgpack_obj(obj);
150}
151
152inline MapDecoder::MapDecoder(const std::map<std::string, msgpack::object>& map_in) {
153 std::map<std::string, msgpack::object>::const_iterator it;
154 for (it = map_in.begin(); it != map_in.end(); ++it) {
155 data_map_[it->first] = &(it->second);
156 }
157}
158
159inline void MapDecoder::initFromObject(const msgpack::object& obj) {
160 data_map_.clear();
161 decoded_keys_.clear();
162 init_from_msgpack_obj(obj);
163}
164
165inline void MapDecoder::initFromBuffer(const char* buffer, std::size_t size) {
166 msgpack::unpack(object_handle_, buffer, size);
167 initFromObject(object_handle_.get());
168}
169
170void
171inline MapDecoder::copy_decode(const std::string& key, bool required,
172 std::map<std::string, msgpack::object>& target,
173 msgpack::zone & zone) const {
174 // note: cost of O(M*log(N)) string comparisons (M parsed, N in map)
175 data_map_type_::const_iterator it = data_map_.find(key);
176 if (it != data_map_.end()) {
177 decoded_keys_.insert(key);
178 // expensive copy here
179 msgpack::object tmp_object(*it->second, zone);
180 tmp_object.convert(target);
181 }
182 else if (required) {
183 throw DecodeError("MsgPack MAP does not contain required entry "
184 + key);
185 }
186}
187
188template<typename T>
189inline void MapDecoder::decode(const std::string& key, bool required, T& target) const {
190 // note: cost of O(M*log(N)) string comparisons (M parsed, N in map)
191 data_map_type_::const_iterator it = data_map_.find(key);
192 if (it != data_map_.end()) {
193 checkType_(key, it->second->type, target);
194 if (it->second->type == msgpack::type::BIN) {
195 BinaryDecoder bd(*it->second, key);
196 bd.decode(target);
197 } else {
198 it->second->convert(target);
199 }
200 decoded_keys_.insert(key);
201 }
202 else if (required) {
203 throw DecodeError("MsgPack MAP does not contain required entry "
204 + key);
205 }
206}
207
208
209inline void MapDecoder::checkExtraKeys() const {
210 // note: cost of O(N*log(M))) string comparisons (M parsed, N in map)
211 // simple set difference algorithm
212 data_map_type_::const_iterator map_it;
213 std::set<std::string>::const_iterator parsed_it;
214 for (map_it = data_map_.begin(); map_it != data_map_.end(); ++map_it) {
215 parsed_it = decoded_keys_.find(map_it->first);
216 if (parsed_it == decoded_keys_.end()) {
217 std::cerr << "Warning: Found non-parsed key " << map_it->first
218 << " in MsgPack MAP.\n";
219 }
220 }
221}
222
223inline void MapDecoder::init_from_msgpack_obj(const msgpack::object& obj) {
224 // sanity checks
225 if (obj.type != msgpack::type::MAP) {
226 throw DecodeError("Expected msgpack type to be MAP");
227 }
228 // get data
229 msgpack::object_kv* current_key_value = obj.via.map.ptr;
230 msgpack::object_kv* last_key_value = current_key_value + obj.via.map.size;
231 for (; current_key_value != last_key_value; ++current_key_value) {
232 msgpack::object* key = &(current_key_value->key);
233 msgpack::object* value = &(current_key_value->val);
234 if (key->type == msgpack::type::STR) {
235 std::string data_map_key(key->via.str.ptr, key->via.str.size);
236 data_map_[data_map_key] = value;
237 } else {
238 std::cerr << "Warning: Found non-string key type " << key->type
239 << "! Skipping..." << std::endl;
240 }
241 }
242}
243
244inline void MapDecoder::checkType_(const std::string& key,
245 msgpack::type::object_type type,
246 const float&) const {
247 if (type != msgpack::type::FLOAT32 && type != msgpack::type::FLOAT64) {
248 std::cerr << "Warning: Non-float type " << type << " found for "
249 "entry " << key << std::endl;
250 }
251}
252inline void MapDecoder::checkType_(const std::string& key,
253 msgpack::type::object_type type,
254 const int32_t&) const {
255 if ( type != msgpack::type::POSITIVE_INTEGER
256 && type != msgpack::type::NEGATIVE_INTEGER) {
257 std::cerr << "Warning: Non-int type " << type << " found for "
258 "entry " << key << std::endl;
259 }
260}
261inline void MapDecoder::checkType_(const std::string& key,
262 msgpack::type::object_type type,
263 const char&) const {
264 if (type != msgpack::type::STR) {
265 std::cerr << "Warning: Non-string type " << type << " found for "
266 "entry " << key << std::endl;
267 }
268}
269inline void MapDecoder::checkType_(const std::string& key,
270 msgpack::type::object_type type,
271 const std::string&) const {
272 if (type != msgpack::type::STR) {
273 std::cerr << "Warning: Non-string type " << type << " found for "
274 "entry " << key << std::endl;
275 }
276}
277
278template <typename T>
279void MapDecoder::checkType_(const std::string& key,
280 msgpack::type::object_type type,
281 const std::vector<T>&) const {
282 if (type != msgpack::type::ARRAY && type != msgpack::type::BIN) {
283 std::cerr << "Warning: Non-array type " << type << " found for "
284 "entry " << key << std::endl;
285 }
286}
287
288
289template <typename T>
290void MapDecoder::checkType_(const std::string&,
291 msgpack::type::object_type,
292 const T &) const {
293 // Do nothing -- allow all through
294}
295
296} // mmtf namespace
297
298#endif
Helper class to decode msgpack binary into a vector.
Definition binary_decoder.hpp:30
void decode(T &target) const
Decode binary msgpack object into the given target.
Definition binary_decoder.hpp:220
Exception thrown when failing during decoding.
Definition errors.hpp:23
void initFromBuffer(const char *buffer, size_t size)
Initialize from byte buffer of given size. Unpacks data and then same effect as MapDecoder::initFromO...
Definition map_decoder.hpp:165
void copy_decode(const std::string &key, bool required, std::map< std::string, msgpack::object > &target, msgpack::zone &zone) const
Don't decode, but instead just copy map-contents onto a zone for later decoding/processing you should...
Definition map_decoder.hpp:171
void initFromObject(const msgpack::object &obj)
Initialize given a msgpack::object. Clears internal data and has same effect as MapDecoder::MapDecode...
Definition map_decoder.hpp:159
MapDecoder()
Construct empty decoder. Use init-functions to fill it.
Definition map_decoder.hpp:37
void checkExtraKeys() const
Check if there are any keys, that were not decoded. This is to be called after all expected fields ha...
Definition map_decoder.hpp:209
void decode(const std::string &key, bool required, T &target) const
Extract value from map and decode into target.
Definition map_decoder.hpp:189
Definition binary_decoder.hpp:25