PageRenderTime 26ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/src/table_entry.cpp

http://github.com/alanxz/libamqp-cpp
C++ | 351 lines | 313 code | 38 blank | 0 comment | 23 complexity | e3e1b2aad8c97f0781233a0497db0f2b MD5 | raw file
  1. #include "table_entry.h"
  2. #include "detail/string_utils.h"
  3. #include <boost/mpl/at.hpp>
  4. #include <boost/mpl/int.hpp>
  5. #include <boost/mpl/map.hpp>
  6. #include <boost/mpl/pair.hpp>
  7. #include <boost/mpl/string.hpp>
  8. #include <boost/variant/apply_visitor.hpp>
  9. #include <boost/variant/static_visitor.hpp>
  10. #include <iomanip>
  11. #include <istream>
  12. #include <ostream>
  13. namespace amqpp {
  14. namespace detail
  15. {
  16. namespace mpl = boost::mpl;
  17. typedef mpl::map<
  18. mpl::pair<bool, mpl::int_<table_entry::boolean_type> >,
  19. mpl::pair<int8_t, mpl::int_<table_entry::int8_type> >,
  20. mpl::pair<int16_t, mpl::int_<table_entry::int16_type> >,
  21. mpl::pair<int32_t, mpl::int_<table_entry::int32_type> >,
  22. mpl::pair<int64_t, mpl::int_<table_entry::int64_type> >,
  23. mpl::pair<float, mpl::int_<table_entry::float_type> >,
  24. mpl::pair<double, mpl::int_<table_entry::double_type> >,
  25. mpl::pair<table_entry::decimal_t, mpl::int_<table_entry::decimal_type> >,
  26. mpl::pair<std::string, mpl::int_<table_entry::longstring_type> >,
  27. mpl::pair<table_entry::array_t, mpl::int_<table_entry::fieldarray_type> >,
  28. mpl::pair<table_entry::timestamp_t,mpl::int_<table_entry::timestamp_type> >,
  29. mpl::pair<table, mpl::int_<table_entry::fieldtable_type> >,
  30. mpl::pair<table_entry::void_t, mpl::int_<table_entry::void_type> >,
  31. mpl::pair<table_entry::bytes_t, mpl::int_<table_entry::bytes_type> >
  32. > field_type_to_field_value_t_map;
  33. class type_getter : public boost::static_visitor<table_entry::field_type>
  34. {
  35. public:
  36. template <class T>
  37. table_entry::field_type operator()(const T&) const
  38. {
  39. typedef typename mpl::at<field_type_to_field_value_t_map, T>::type enum_type;
  40. return table_entry::field_type(enum_type::value);
  41. }
  42. };
  43. class datatype_size_counter : public boost::static_visitor<uint32_t>
  44. {
  45. public:
  46. template <class T>
  47. uint32_t operator()(const T&) const
  48. {
  49. return sizeof(T);
  50. }
  51. uint32_t operator()(const bool) const
  52. {
  53. return sizeof(uint8_t);
  54. }
  55. uint32_t operator()(const std::string& v) const
  56. {
  57. return detail::wireformat_size_longstring(v);
  58. }
  59. uint32_t operator()(const table_entry::array_t& a) const
  60. {
  61. uint32_t size = 0;
  62. for (table_entry::array_t::const_iterator it = a.begin();
  63. it != a.end(); ++it)
  64. {
  65. size += table_entry::wireformat_data_size(*it);
  66. }
  67. return size;
  68. }
  69. uint32_t operator()(const table& t) const
  70. {
  71. return t.wireformat_size();
  72. }
  73. uint32_t operator()(const table_entry::void_t) const
  74. {
  75. return 0;
  76. }
  77. uint32_t operator()(const table_entry::bytes_t& v) const
  78. {
  79. return sizeof(uint32_t) + sizeof(uint8_t) * static_cast<uint32_t>(v.size());
  80. }
  81. };
  82. typedef mpl::map<
  83. mpl::pair<int8_t, mpl::string<'<int','8>: '> >,
  84. mpl::pair<int16_t, mpl::string<'<int','16>:',' '> >,
  85. mpl::pair<int32_t, mpl::string<'<int','32>:',' '> >,
  86. mpl::pair<int64_t, mpl::string<'<int','64>:',' '> >,
  87. mpl::pair<float, mpl::string<'<flo','at>:',' '> >,
  88. mpl::pair<double, mpl::string<'<dou','ble>',': '> >,
  89. mpl::pair<table_entry::timestamp_t,mpl::string<'<tim','esta','mp>:',' '> >
  90. > field_type_to_string_t;
  91. class data_stringifier : public boost::static_visitor<void>
  92. {
  93. private:
  94. std::ostream& os;
  95. public:
  96. explicit data_stringifier(std::ostream& o) : os(o) {}
  97. template <class T>
  98. void operator()(T d) const
  99. {
  100. typedef typename mpl::at<field_type_to_string_t, T>::type field_type_name;
  101. os << mpl::c_str<field_type_name>::value << d;
  102. }
  103. void operator()(bool d) const
  104. {
  105. os << "<boolean>: " << (d ? "true" : "false");
  106. }
  107. void operator()(table_entry::decimal_t d) const
  108. {
  109. os << "<decimal>: mag: " << static_cast<unsigned int>(d.first) << " val: " << d.second;
  110. }
  111. void operator()(const std::string& s) const
  112. {
  113. os << "<longstring>: len:" << s.length() << " \"" << s << "\"";
  114. }
  115. void operator()(const table_entry::array_t& a) const
  116. {
  117. os << "<fieldarray>: len:" << a.size() << " {";
  118. for (table_entry::array_t::const_iterator it = a.begin();
  119. it != a.end(); ++it)
  120. {
  121. table_entry::value_to_string(os, *it);
  122. os << ", ";
  123. }
  124. os << "}";
  125. }
  126. void operator()(const table& t) const
  127. {
  128. os << "<fieldtable>: " << t.to_string();
  129. }
  130. void operator()(table_entry::void_t) const
  131. {
  132. os << "<void>";
  133. }
  134. void operator()(const table_entry::bytes_t& d) const
  135. {
  136. os << "<bytes>: { len: " << d.size();
  137. os << std::hex;
  138. for (table_entry::bytes_t::const_iterator it = d.begin();
  139. it != d.end(); ++it)
  140. {
  141. os << static_cast<int>(*it);
  142. }
  143. os << std::dec;
  144. }
  145. };
  146. }
  147. table_entry::table_entry(const std::string& key, bool value) :
  148. m_key(key), m_data(field_value_t(value))
  149. {
  150. if (!validate_key_name(m_key))
  151. {
  152. throw std:: runtime_error("Table entry key name is not valid.");
  153. }
  154. }
  155. table_entry::table_entry(const std::string& key, int8_t value) :
  156. m_key(key), m_data(field_value_t(value))
  157. {
  158. if (!validate_key_name(m_key))
  159. {
  160. throw std::runtime_error("Table entry key name is not valid.");
  161. }
  162. }
  163. table_entry::table_entry(const std::string& key, int16_t value):
  164. m_key(key), m_data(field_value_t(value))
  165. {
  166. if (!validate_key_name(m_key))
  167. {
  168. throw std:: runtime_error("Table entry key name is not valid.");
  169. }
  170. }
  171. table_entry::table_entry(const std::string& key, int32_t value):
  172. m_key(key), m_data(field_value_t(value))
  173. {
  174. if (!validate_key_name(m_key))
  175. {
  176. throw std:: runtime_error("Table entry key name is not valid.");
  177. }
  178. }
  179. table_entry::table_entry(const std::string& key, int64_t value):
  180. m_key(key), m_data(field_value_t(value))
  181. {
  182. if (!validate_key_name(m_key))
  183. {
  184. throw std:: runtime_error("Table entry key name is not valid.");
  185. }
  186. }
  187. table_entry::table_entry(const std::string& key, float value):
  188. m_key(key), m_data(field_value_t(value))
  189. {
  190. if (!validate_key_name(m_key))
  191. {
  192. throw std:: runtime_error("Table entry key name is not valid.");
  193. }
  194. }
  195. table_entry::table_entry(const std::string& key, double value):
  196. m_key(key), m_data(field_value_t(value))
  197. {
  198. if (!validate_key_name(m_key))
  199. {
  200. throw std:: runtime_error("Table entry key name is not valid.");
  201. }
  202. }
  203. table_entry::table_entry(const std::string& key, decimal_t value):
  204. m_key(key), m_data(field_value_t(value))
  205. {
  206. if (!validate_key_name(m_key))
  207. {
  208. throw std:: runtime_error("Table entry key name is not valid.");
  209. }
  210. }
  211. table_entry::table_entry(const std::string& key, const char* value):
  212. m_key(key), m_data(field_value_t(std::string(value)))
  213. {
  214. if (!validate_key_name(m_key))
  215. {
  216. throw std:: runtime_error("Table entry key name is not valid.");
  217. }
  218. }
  219. table_entry::table_entry(const std::string& key, const std::string& value):
  220. m_key(key), m_data(field_value_t(value))
  221. {
  222. if (!validate_key_name(m_key))
  223. {
  224. throw std:: runtime_error("Table entry key name is not valid.");
  225. }
  226. }
  227. table_entry::table_entry(const std::string& key, const array_t& value):
  228. m_key(key), m_data(field_value_t(value))
  229. {
  230. if (!validate_key_name(m_key))
  231. {
  232. throw std:: runtime_error("Table entry key name is not valid.");
  233. }
  234. }
  235. table_entry::table_entry(const std::string& key, timestamp_t value):
  236. m_key(key), m_data(field_value_t(value))
  237. {
  238. if (!validate_key_name(m_key))
  239. {
  240. throw std:: runtime_error("Table entry key name is not valid.");
  241. }
  242. }
  243. table_entry::table_entry(const std::string& key, const table& value):
  244. m_key(key), m_data(field_value_t(value))
  245. {
  246. if (!validate_key_name(m_key))
  247. {
  248. throw std:: runtime_error("Table entry key name is not valid.");
  249. }
  250. }
  251. table_entry::table_entry(const std::string& key, void_t value):
  252. m_key(key), m_data(field_value_t(value))
  253. {
  254. if (!validate_key_name(m_key))
  255. {
  256. throw std:: runtime_error("Table entry key name is not valid.");
  257. }
  258. }
  259. table_entry::table_entry(const std::string& key, bytes_t value):
  260. m_key(key), m_data(field_value_t(value))
  261. {
  262. if (!validate_key_name(m_key))
  263. {
  264. throw std:: runtime_error("Table entry key name is not valid.");
  265. }
  266. }
  267. table_entry::table_entry(const std::string& key, const field_value_t& data) :
  268. m_key(key), m_data(data)
  269. {
  270. if (!validate_key_name(m_key))
  271. {
  272. throw std::runtime_error("Key name is invalid");
  273. }
  274. }
  275. table_entry::~table_entry()
  276. {
  277. }
  278. table_entry::field_type table_entry::get_type() const
  279. {
  280. return boost::apply_visitor(detail::type_getter(), m_data);
  281. }
  282. bool table_entry::validate_key_name(const std::string& key)
  283. {
  284. if (key.length() > 128)
  285. {
  286. return false;
  287. }
  288. return true;
  289. }
  290. std::string table_entry::to_string() const
  291. {
  292. std::ostringstream os;
  293. os << get_key();
  294. value_to_string(os, get_data());
  295. return os.str();
  296. }
  297. void table_entry::value_to_string(std::ostream& os, const field_value_t& data)
  298. {
  299. boost::apply_visitor(detail::data_stringifier(os), data);
  300. }
  301. uint32_t table_entry::wireformat_size() const
  302. {
  303. uint32_t size = detail::wireformat_size_shortstring(m_key);
  304. size += wireformat_data_size(m_data);
  305. return size;
  306. }
  307. uint32_t table_entry::wireformat_data_size(const table_entry::field_value_t& data)
  308. {
  309. uint32_t size = sizeof(uint8_t); // size of datatype
  310. size += boost::apply_visitor(detail::datatype_size_counter(), data);
  311. return size;
  312. }
  313. } // namespace amqpp