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 
24 namespace mmtf {
25 
29 class MapDecoder {
30 public:
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 
61 private:
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 
90 inline 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 
111 template<typename T>
112 void 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 
146 inline 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 }
154 inline 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 }
163 inline 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 }
171 inline 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 }
179 template <typename T>
180 void 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 }
188 template <typename T>
189 void 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
errors.hpp
structure_data.hpp
mmtf::MapDecoder::MapDecoder
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
mmtf::DecodeError
Exception thrown when failing during decoding.
Definition: errors.hpp:23
mmtf::BinaryDecoder::decode
void decode(T &target)
Decode binary msgpack object into the given target.
Definition: binary_decoder.hpp:185
mmtf::BinaryDecoder
Helper class to decode msgpack binary into a vector.
Definition: binary_decoder.hpp:29
mmtf
Definition: binary_decoder.hpp:24
mmtf::MapDecoder::checkExtraKeys
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
binary_decoder.hpp
mmtf::MapDecoder
Helper class to decode msgpack maps into object fields.
Definition: map_decoder.hpp:29
mmtf::MapDecoder::decode
void decode(const std::string &key, bool required, T &target)
Extract value from map and decode into target.
Definition: map_decoder.hpp:112