123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2.0, as
- * published by the Free Software Foundation.
- *
- * This program is also distributed with certain software (including
- * but not limited to OpenSSL) that is licensed under separate terms,
- * as designated in a particular file or component or in included license
- * documentation. The authors of MySQL hereby grant you an
- * additional permission to link the program and your derivative works
- * with the separately licensed software that they have included with
- * MySQL.
- *
- * Without limiting anything contained in the foregoing, this file,
- * which is part of MySQL Connector/C++, is also subject to the
- * Universal FOSS Exception, version 1.0, a copy of which can be found at
- * http://oss.oracle.com/licenses/universal-foss-exception.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License, version 2.0, for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #ifndef MYSQLX_COMMON_VALUE_H
- #define MYSQLX_COMMON_VALUE_H
- #include <string>
- #include "api.h"
- #include "error.h"
- #include "util.h"
- namespace mysqlx {
- namespace common {
- class Value_conv;
- /*
- Class representing a polymorphic value of one of the supported types.
- TODO: Extend it with array and document types (currently these are implemented
- in derived mysqlx::Value class of DevAPI).
- TODO: When storing raw bytes, currently they are copied inside the Value
- object. Consider if this can be avoided.
- */
- class PUBLIC_API Value
- : public virtual Printable
- {
- public:
- enum Type
- {
- VNULL, ///< Null value
- UINT64, ///< Unsigned integer
- INT64, ///< Signed integer
- FLOAT, ///< Float number
- DOUBLE, ///< Double number
- BOOL, ///< Boolean
- STRING, ///< String
- WSTRING, ///< Wide string
- RAW, ///< Raw bytes
- EXPR, ///< String to be interpreted as an expression
- JSON, ///< JSON string
- };
- protected:
- Type m_type;
- // TODO: Use std::variant to save space
- DLL_WARNINGS_PUSH
- std::string m_str;
- std::wstring m_wstr;
- DLL_WARNINGS_POP
- union {
- double v_double;
- float v_float;
- int64_t v_sint;
- uint64_t v_uint;
- bool v_bool;
- } m_val;
- void print(std::ostream&) const override;
- template <typename T>
- Value(Type type, T &&init)
- : Value(std::forward<T>(init))
- {
- m_type = type;
- }
- public:
- // Construct a NULL item
- Value() : m_type(VNULL)
- {}
- // Construct an item from a string
- Value(const std::string& str) : m_type(STRING), m_str(str)
- {
- m_val.v_bool = false;
- }
- // Construct an item from a string
- Value(const std::wstring& str) : m_type(WSTRING), m_wstr(str)
- {
- m_val.v_bool = false;
- }
- // Construct an item from a signed 64-bit integer
- Value(int64_t v) : m_type(INT64)
- { m_val.v_sint = v; }
- // Construct an item from an unsigned 64-bit integer
- Value(uint64_t v) : m_type(UINT64)
- { m_val.v_uint = v; }
- // Construct an item from a float
- Value(float v) : m_type(FLOAT)
- { m_val.v_float = v; }
- // Construct an item from a double
- Value(double v) : m_type(DOUBLE)
- { m_val.v_double = v; }
- // Construct an item from a bool
- Value(bool v) : m_type(BOOL)
- { m_val.v_bool = v; }
- // Construct an item from bytes
- Value(const byte *ptr, size_t len) : m_type(RAW)
- {
- // Note: bytes are copied to m_str member.
- m_str.assign((const char*)ptr, len);
- }
- // Other numeric conversions
- template <
- typename T,
- typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr
- >
- Value(T val)
- : Value(uint64_t(val))
- {}
- template <
- typename T,
- typename std::enable_if<!std::is_unsigned<T>::value>::type* = nullptr,
- typename std::enable_if<std::is_integral<T>::value>::type* = nullptr
- >
- Value(T val)
- : Value(int64_t(val))
- {}
- bool is_null() const
- {
- return VNULL == m_type;
- }
- bool get_bool() const
- {
- switch (m_type)
- {
- case BOOL: return m_val.v_bool;
- case UINT64: return 0 != m_val.v_uint;
- case INT64: return 0 != m_val.v_sint;
- default:
- throw Error("Can not convert to Boolean value");
- }
- }
- uint64_t get_uint() const
- {
- if (UINT64 != m_type && INT64 != m_type && BOOL != m_type)
- throw Error("Can not convert to integer value");
- if (BOOL == m_type)
- return m_val.v_bool ? 1 : 0;
- if (INT64 == m_type && 0 > m_val.v_sint)
- throw Error("Converting negative integer to unsigned value");
- uint64_t val = (UINT64 == m_type ? m_val.v_uint: (uint64_t)m_val.v_sint);
- return val;
- }
- int64_t get_sint() const
- {
- if (INT64 == m_type)
- return m_val.v_sint;
- uint64_t val = get_uint();
- if (!check_num_limits<int64_t>(val))
- throw Error("Value cannot be converted to signed integer number");
- return val;
- }
- float get_float() const
- {
- switch (m_type)
- {
- case INT64: return 1.0F*m_val.v_sint;
- case UINT64: return 1.0F*m_val.v_uint;
- case FLOAT: return m_val.v_float;
- default:
- throw Error("Value cannot be converted to float number");
- }
- }
- double get_double() const
- {
- switch (m_type)
- {
- case INT64: return 1.0*m_val.v_sint;
- case UINT64: return 1.0*m_val.v_uint;
- case FLOAT: return m_val.v_float;
- case DOUBLE: return m_val.v_double;
- default:
- throw Error("Value can not be converted to double number");
- }
- }
- const byte* get_bytes(size_t *size) const
- {
- switch (m_type)
- {
- case WSTRING: // TODO
- default:
- if (m_str.empty())
- throw Error("Value cannot be converted to raw bytes");
- FALLTHROUGH;
- case RAW:
- case STRING:
- if (size)
- *size = m_str.length();
- return (const byte*)m_str.data();
- }
- }
- // Note: these methods perform utf8 conversions as necessary.
- const std::string& get_string() const;
- const std::wstring& get_wstring() const;
- Type get_type() const
- {
- return m_type;
- }
- private:
- /*
- Note: Avoid implicit conversion from pointer types to bool.
- Without this declaration, Value(bool) constructor is invoked
- for pointer types. Here we declare and hide an explicit constructor
- for pointer types which prevents compiler to pick Value(bool).
- */
- template <typename T>
- Value(const T*);
- public:
- friend Value_conv;
- struct Access;
- friend Access;
- };
- }} // mysqlx::internal namespace
- #endif
|