value.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2.0, as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is also distributed with certain software (including
  9. * but not limited to OpenSSL) that is licensed under separate terms,
  10. * as designated in a particular file or component or in included license
  11. * documentation. The authors of MySQL hereby grant you an
  12. * additional permission to link the program and your derivative works
  13. * with the separately licensed software that they have included with
  14. * MySQL.
  15. *
  16. * Without limiting anything contained in the foregoing, this file,
  17. * which is part of MySQL Connector/C++, is also subject to the
  18. * Universal FOSS Exception, version 1.0, a copy of which can be found at
  19. * http://oss.oracle.com/licenses/universal-foss-exception.
  20. *
  21. * This program is distributed in the hope that it will be useful, but
  22. * WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. * See the GNU General Public License, version 2.0, for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #ifndef MYSQLX_COMMON_VALUE_H
  31. #define MYSQLX_COMMON_VALUE_H
  32. #include <string>
  33. #include "api.h"
  34. #include "error.h"
  35. #include "util.h"
  36. namespace mysqlx {
  37. namespace common {
  38. class Value_conv;
  39. /*
  40. Class representing a polymorphic value of one of the supported types.
  41. TODO: Extend it with array and document types (currently these are implemented
  42. in derived mysqlx::Value class of DevAPI).
  43. TODO: When storing raw bytes, currently they are copied inside the Value
  44. object. Consider if this can be avoided.
  45. */
  46. class PUBLIC_API Value
  47. : public virtual Printable
  48. {
  49. public:
  50. enum Type
  51. {
  52. VNULL, ///< Null value
  53. UINT64, ///< Unsigned integer
  54. INT64, ///< Signed integer
  55. FLOAT, ///< Float number
  56. DOUBLE, ///< Double number
  57. BOOL, ///< Boolean
  58. STRING, ///< String
  59. WSTRING, ///< Wide string
  60. RAW, ///< Raw bytes
  61. EXPR, ///< String to be interpreted as an expression
  62. JSON, ///< JSON string
  63. };
  64. protected:
  65. Type m_type;
  66. // TODO: Use std::variant to save space
  67. DLL_WARNINGS_PUSH
  68. std::string m_str;
  69. std::wstring m_wstr;
  70. DLL_WARNINGS_POP
  71. union {
  72. double v_double;
  73. float v_float;
  74. int64_t v_sint;
  75. uint64_t v_uint;
  76. bool v_bool;
  77. } m_val;
  78. void print(std::ostream&) const override;
  79. template <typename T>
  80. Value(Type type, T &&init)
  81. : Value(std::forward<T>(init))
  82. {
  83. m_type = type;
  84. }
  85. public:
  86. // Construct a NULL item
  87. Value() : m_type(VNULL)
  88. {}
  89. // Construct an item from a string
  90. Value(const std::string& str) : m_type(STRING), m_str(str)
  91. {
  92. m_val.v_bool = false;
  93. }
  94. // Construct an item from a string
  95. Value(const std::wstring& str) : m_type(WSTRING), m_wstr(str)
  96. {
  97. m_val.v_bool = false;
  98. }
  99. // Construct an item from a signed 64-bit integer
  100. Value(int64_t v) : m_type(INT64)
  101. { m_val.v_sint = v; }
  102. // Construct an item from an unsigned 64-bit integer
  103. Value(uint64_t v) : m_type(UINT64)
  104. { m_val.v_uint = v; }
  105. // Construct an item from a float
  106. Value(float v) : m_type(FLOAT)
  107. { m_val.v_float = v; }
  108. // Construct an item from a double
  109. Value(double v) : m_type(DOUBLE)
  110. { m_val.v_double = v; }
  111. // Construct an item from a bool
  112. Value(bool v) : m_type(BOOL)
  113. { m_val.v_bool = v; }
  114. // Construct an item from bytes
  115. Value(const byte *ptr, size_t len) : m_type(RAW)
  116. {
  117. // Note: bytes are copied to m_str member.
  118. m_str.assign((const char*)ptr, len);
  119. }
  120. // Other numeric conversions
  121. template <
  122. typename T,
  123. typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr
  124. >
  125. Value(T val)
  126. : Value(uint64_t(val))
  127. {}
  128. template <
  129. typename T,
  130. typename std::enable_if<!std::is_unsigned<T>::value>::type* = nullptr,
  131. typename std::enable_if<std::is_integral<T>::value>::type* = nullptr
  132. >
  133. Value(T val)
  134. : Value(int64_t(val))
  135. {}
  136. bool is_null() const
  137. {
  138. return VNULL == m_type;
  139. }
  140. bool get_bool() const
  141. {
  142. switch (m_type)
  143. {
  144. case BOOL: return m_val.v_bool;
  145. case UINT64: return 0 != m_val.v_uint;
  146. case INT64: return 0 != m_val.v_sint;
  147. default:
  148. throw Error("Can not convert to Boolean value");
  149. }
  150. }
  151. uint64_t get_uint() const
  152. {
  153. if (UINT64 != m_type && INT64 != m_type && BOOL != m_type)
  154. throw Error("Can not convert to integer value");
  155. if (BOOL == m_type)
  156. return m_val.v_bool ? 1 : 0;
  157. if (INT64 == m_type && 0 > m_val.v_sint)
  158. throw Error("Converting negative integer to unsigned value");
  159. uint64_t val = (UINT64 == m_type ? m_val.v_uint: (uint64_t)m_val.v_sint);
  160. return val;
  161. }
  162. int64_t get_sint() const
  163. {
  164. if (INT64 == m_type)
  165. return m_val.v_sint;
  166. uint64_t val = get_uint();
  167. if (!check_num_limits<int64_t>(val))
  168. throw Error("Value cannot be converted to signed integer number");
  169. return val;
  170. }
  171. float get_float() const
  172. {
  173. switch (m_type)
  174. {
  175. case INT64: return 1.0F*m_val.v_sint;
  176. case UINT64: return 1.0F*m_val.v_uint;
  177. case FLOAT: return m_val.v_float;
  178. default:
  179. throw Error("Value cannot be converted to float number");
  180. }
  181. }
  182. double get_double() const
  183. {
  184. switch (m_type)
  185. {
  186. case INT64: return 1.0*m_val.v_sint;
  187. case UINT64: return 1.0*m_val.v_uint;
  188. case FLOAT: return m_val.v_float;
  189. case DOUBLE: return m_val.v_double;
  190. default:
  191. throw Error("Value can not be converted to double number");
  192. }
  193. }
  194. const byte* get_bytes(size_t *size) const
  195. {
  196. switch (m_type)
  197. {
  198. case WSTRING: // TODO
  199. default:
  200. if (m_str.empty())
  201. throw Error("Value cannot be converted to raw bytes");
  202. FALLTHROUGH;
  203. case RAW:
  204. case STRING:
  205. if (size)
  206. *size = m_str.length();
  207. return (const byte*)m_str.data();
  208. }
  209. }
  210. // Note: these methods perform utf8 conversions as necessary.
  211. const std::string& get_string() const;
  212. const std::wstring& get_wstring() const;
  213. Type get_type() const
  214. {
  215. return m_type;
  216. }
  217. private:
  218. /*
  219. Note: Avoid implicit conversion from pointer types to bool.
  220. Without this declaration, Value(bool) constructor is invoked
  221. for pointer types. Here we declare and hide an explicit constructor
  222. for pointer types which prevents compiler to pick Value(bool).
  223. */
  224. template <typename T>
  225. Value(const T*);
  226. public:
  227. friend Value_conv;
  228. struct Access;
  229. friend Access;
  230. };
  231. }} // mysqlx::internal namespace
  232. #endif