diff options
author | Constantin Michael <constantin@codesynthesis.com> | 2011-09-23 11:22:06 +0200 |
---|---|---|
committer | Constantin Michael <constantin@codesynthesis.com> | 2011-09-23 11:22:06 +0200 |
commit | 0198441b5e7d3ed5f9307d400feca87cc63ad1a6 (patch) | |
tree | b5efa498be39221336aa0952adddf3c3eda209a3 | |
parent | 992ec5b8a4f22204c935c5072c6ba4de0018959a (diff) |
Add traits implementation
-rw-r--r-- | odb/oracle/traits.cxx | 138 | ||||
-rw-r--r-- | odb/oracle/traits.hxx | 590 |
2 files changed, 728 insertions, 0 deletions
diff --git a/odb/oracle/traits.cxx b/odb/oracle/traits.cxx new file mode 100644 index 0000000..c842755 --- /dev/null +++ b/odb/oracle/traits.cxx @@ -0,0 +1,138 @@ +// file : odb/oracle/traits.cxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cmath> +#include <deque> + +#include <odb/oracle/traits.hxx> + +namespace odb +{ + namespace oracle + { + long long + out (unsigned char const* n) + { + // The first byte specifies the length of the number representation, + // including the exponent byte and significant digits but not the length + // itself. + // + int len (n[0]); + + if (len == 1) + return 0; + + long long v (0); + if (n[1] & 0x80) + { + // The exponent of a positive number is calculated as n[1] - 193. + // The base-100 exponent of the least significant digit can be + // calculated as exp - sig - 1, where sig is the number of significant + // digits. sig may be calculated as len - 2. + // + int exp (n[1] - 191 - len); + + for (unsigned char const* m (n + len), *e (n + 1); m > e; --m, ++exp) + v += (*m - 1) * pow (100, exp); + } + else + { + // The exponent of a negative number is calculated as ~n[1] - 193. + // The base-100 exponent of the least significant digit can be + // calculated as exp - sig - 1, where sig is the number of significant + // digits. sig may be calculated as len - 2. + // + int exp (~n[1] - 190 - len); + + for (unsigned char const* m (n + len - 1), *e (n + 1); m > e; + --m, ++exp) + v -= (101 - *m) * pow (100, exp); + } + + return v; + } + + void + in (unsigned char b[22], long long n) + { + if (n == 0) + { + b[0] = 1; + b[1] = 128; + + return; + } + + // @@ Is there some sort of reserve() implementation for deque? + // + deque<unsigned char> s; + + bool sig (false); + size_t c (0); + unsigned char exp (0); + + if (n < 0) + { + // Termination marker for negative numbers. + // + s.push_front (102); + + while (n != 0) + { + int v (static_cast<int> (n % 100)); + sig = sig ? true : v != 0; + + if (sig) + s.push_front (static_cast<unsigned char> (101 + v)); + + n /= 100; + ++c; + } + + // The exponent is one less than the number of base 100 digits. It is + // inverted for negative values. + // + exp = static_cast<unsigned char> (~(c + 192)); + } + else + { + while (n != 0) + { + int v (static_cast<int> (n % 100)); + sig = sig ? true : v != 0; + + if (sig) + s.push_front (static_cast<unsigned char> (v + 1)); + + n /= 100; + ++c; + } + + // Exponent is one less than the number of base 100 digits. + // + exp = static_cast<unsigned char> (c + 192); + } + + // Set the length. + // + b[0] = static_cast<unsigned char> (s.size () + 1); + + // Set the exponent. + // + b[1] = exp; + + // Set the significant digits (big-endian byte order) and the terminator, + // if any. + // + c = 2; + while (!s.empty ()) + { + b[i] = s.front (); + s.pop_front (); + ++c; + } + } + } +} diff --git a/odb/oracle/traits.hxx b/odb/oracle/traits.hxx new file mode 100644 index 0000000..532f091 --- /dev/null +++ b/odb/oracle/traits.hxx @@ -0,0 +1,590 @@ +// file : odb/oracle/traits.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_ORACLE_TRAITS_HXX +#define ODB_ORACLE_TRAITS_HXX + +#include <odb/pre.hxx> + +#include <string> +#include <vector> +#include <cstddef> // std::size_t + +#include <odb/traits.hxx> +#include <odb/wrapper-traits.hxx> + +#include <odb/oracle/version.hxx> +#include <odb/oracle/oracle-types.hxx> + +#include <odb/details/buffer.hxx> +#include <odb/details/wrapper-p.hxx> + +#include <odb/oracle/details/export.hxx> + +namespace odb +{ + namespace oracle + { + enum database_type_id + { + id_int32, + id_int64, + + id_big_int, + + id_float, + id_double, + + id_big_float, + + id_date, + id_timestamp, + + id_string, + id_nstring, + + id_raw, + + id_blob, + id_clob, + id_nclob, + }; + + // + // image_traits + // + + template <database_type_id> + struct image_traits; + + template <> + struct image_traits<id_int32> {typedef int image_type;}; + + template <> + struct image_traits<id_int64> {typedef long long image_type;}; + + template <> + struct image_traits<id_big_int> {typedef unsigned char[21] image_type;}; + + template <> + struct image_traits<id_float> {typedef float image_type;}; + + template <> + struct image_traits<id_double> {typedef double image_type;}; + + template <> + struct image_traits<id_big_float> {typedef unsigned char[21] image_type;}; + + template <> + struct image_traits<id_date> {typedef unsigned char[7] image_type;}; + + template <> + struct image_traits<id_timestamp> {typedef unsigned char* image_type;}; + + template <> + struct image_traits<id_string> {typedef char* image_type;}; + + template <> + struct image_traits<id_nstring> {typedef char* image_type;}; + + template <> + struct image_traits<id_raw> {typedef char* image_type;}; + + template <> + struct image_traits<id_blob> {typedef lob_callback image_type;}; + + template <> + struct image_traits<id_clob> {typedef lob_callback image_type;}; + + template <> + struct image_traits<id_nclob> {typedef lob_callback image_type;}; + + // + // value_traits + // + + template <typename W, database_type_id, bool null_handler> + struct wrapped_value_traits; + + template <typename T, database_type_id> + struct default_value_traits; + + template <typename T, database_type_id, bool w = details::wrapper_p<T>::r> + struct select_traits; + + // template <typename T, database_type_id ID> + // struct select_traits<T, ID, false> + // { + // typedef default_value_traits<T, ID> type; + // }; + + // template <typename W, database_type_id ID> + // struct select_traits<W, ID, true> + // { + // typedef + // wrapped_value_traits<W, ID, wrapper_traits<W>::null_handler> + // type; + // }; + + // template <typename T, database_type_id ID> + // class value_traits: public select_traits<T, ID>::type + // { + // }; + + // // The wrapped_value_traits specializations should be able to handle + // // any value type which means we have to have every possible signature + // // of the set_value() and set_image() functions. + // // + // template <typename W, database_type_id ID> + // struct wrapped_value_traits<W, ID, false> + // { + // typedef wrapper_traits<W> wtraits; + // typedef typename wtraits::wrapped_type wrapped_type; + + // typedef W value_type; + // typedef wrapped_type query_type; + // typedef typename image_traits<ID>::image_type image_type; + + // typedef value_traits<wrapped_type, ID> vtraits; + + // static void + // set_value (W& v, const image_type& i, bool is_null) + // { + // vtraits::set_value (wtraits::set_ref (v), i, is_null); + // } + + // static void + // set_image (image_type& i, bool& is_null, const W& v) + // { + // vtraits::set_image (i, is_null, wtraits::get_ref (v)); + // } + + // // String, BLOB, ENUM, and SET. + // // + // static void + // set_value (W& v, const details::buffer& b, std::size_t n, bool is_null) + // { + // vtraits::set_value (wtraits::set_ref (v), b, n, is_null); + // } + + // static void + // set_image (details::buffer& b, std::size_t& n, bool& is_null, const W& v) + // { + // vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); + // } + + // // BIT. + // // + // static void + // set_value (W& v, const unsigned char* i, std::size_t n, bool is_null) + // { + // vtraits::set_value (wtraits::set_ref (v), i, n, is_null); + // } + + // static void + // set_image (unsigned char* i, + // std::size_t c, + // std::size_t& n, + // bool& is_null, + // const W& v) + // { + // vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); + // } + // }; + + // template <typename W, database_type_id ID> + // struct wrapped_value_traits<W, ID, true> + // { + // typedef wrapper_traits<W> wtraits; + // typedef typename wtraits::wrapped_type wrapped_type; + + // typedef W value_type; + // typedef wrapped_type query_type; + // typedef typename image_traits<ID>::image_type image_type; + + // typedef value_traits<wrapped_type, ID> vtraits; + + // static void + // set_value (W& v, const image_type& i, bool is_null) + // { + // if (is_null) + // wtraits::set_null (v); + // else + // vtraits::set_value (wtraits::set_ref (v), i, is_null); + // } + + // static void + // set_image (image_type& i, bool& is_null, const W& v) + // { + // is_null = wtraits::get_null (v); + + // if (!is_null) + // vtraits::set_image (i, is_null, wtraits::get_ref (v)); + // } + + // // String, BLOB, ENUM, and SET. + // // + // static void + // set_value (W& v, const details::buffer& b, std::size_t n, bool is_null) + // { + // if (is_null) + // wtraits::set_null (v); + // else + // vtraits::set_value (wtraits::set_ref (v), b, n, is_null); + // } + + // static void + // set_image (details::buffer& b, std::size_t& n, bool& is_null, const W& v) + // { + // is_null = wtraits::get_null (v); + + // if (!is_null) + // vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); + // } + + // // BIT. + // // + // static void + // set_value (W& v, const unsigned char* i, std::size_t n, bool is_null) + // { + // if (is_null) + // wtraits::set_null (v); + // else + // vtraits::set_value (wtraits::set_ref (v), i, n, is_null); + // } + + // static void + // set_image (unsigned char* i, + // std::size_t c, + // std::size_t& n, + // bool& is_null, + // const W& v) + // { + // is_null = wtraits::get_null (v); + + // if (!is_null) + // vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); + // } + // }; + + // template <typename T, database_type_id ID> + // struct default_value_traits + // { + // typedef T value_type; + // typedef T query_type; + // typedef typename image_traits<ID>::image_type image_type; + + // static void + // set_value (T& v, const image_type& i, bool is_null) + // { + // if (!is_null) + // v = T (i); + // else + // v = T (); + // } + + // static void + // set_image (image_type& i, bool& is_null, T v) + // { + // is_null = false; + // i = image_type (v); + // } + // }; + + // // Specialization for numeric enum representations (C++ enum, integer + // // types, etc). In particular, this specialization works only for C++ + // // enum type as long as its numeric value space starts with 0, is + // // ascending and contiguous (i.e., the default enumerator assignment). + // // + // template <typename T> + // struct default_value_traits<T, id_enum> + // { + // typedef T value_type; + // typedef T query_type; + // typedef unsigned short image_type; + + // static void + // set_value (T& v, unsigned short i, bool is_null) + // { + // // In MySQL first enumerator has index 1. + // // + // if (!is_null) + // v = static_cast<T> (i - 1); + // else + // v = T (); + // } + + // static void + // set_image (unsigned short& i, bool& is_null, const T& v) + // { + // is_null = false; + // i = static_cast<unsigned short> (v) + 1; + // } + // }; + + // // std::string specialization. + // // + // class LIBODB_MYSQL_EXPORT string_value_traits + // { + // public: + // typedef std::string value_type; + // typedef std::string query_type; + // typedef details::buffer image_type; + + // static void + // set_value (std::string& v, + // const details::buffer& b, + // std::size_t n, + // bool is_null) + // { + // if (!is_null) + // v.assign (b.data (), n); + // else + // v.erase (); + // } + + // static void + // set_image (details::buffer&, + // std::size_t& n, + // bool& is_null, + // const std::string&); + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_string>: + // string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_decimal>: + // string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_enum>: + // string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_set>: + // string_value_traits + // { + // }; + + // // const char* specialization + // // + // // Specialization for const char* which only supports initialization + // // of an image from the value but not the other way around. This way + // // we can pass such values to the queries. + // // + // class LIBODB_MYSQL_EXPORT c_string_value_traits + // { + // public: + // typedef const char* value_type; + // typedef const char* query_type; + // typedef details::buffer image_type; + + // static void + // set_image (details::buffer&, + // std::size_t& n, + // bool& is_null, + // const char*); + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_string>: + // c_string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_decimal>: + // c_string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_enum>: + // c_string_value_traits + // { + // }; + + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_set>: + // c_string_value_traits + // { + // }; + + // template <std::size_t n> + // struct default_value_traits<char[n], id_string>: c_string_value_traits + // { + // }; + + // template <std::size_t n> + // struct default_value_traits<char[n], id_decimal>: c_string_value_traits + // { + // }; + + // template <std::size_t n> + // struct default_value_traits<char[n], id_enum>: c_string_value_traits + // { + // }; + + // template <std::size_t n> + // struct default_value_traits<char[n], id_set>: c_string_value_traits + // { + // }; + + // // std::vector<char> (buffer) specialization. + // // + // template <> + // struct LIBODB_MYSQL_EXPORT default_value_traits<std::vector<char>, id_blob> + // { + // public: + // typedef std::vector<char> value_type; + // typedef std::vector<char> query_type; + // typedef details::buffer image_type; + + // static void + // set_value (value_type& v, + // const details::buffer& b, + // std::size_t n, + // bool is_null) + // { + // if (!is_null) + // v.assign (b.data (), b.data () + n); + // else + // v.clear (); + // } + + // static void + // set_image (details::buffer&, + // std::size_t& n, + // bool& is_null, + // const value_type&); + // }; + + // + // type_traits + // + + template <typename T> + struct default_type_traits; + + template <typename T> + class type_traits: public default_type_traits<T> + { + }; + + // Integral types. + // + template <> + struct default_type_traits<bool> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<signed char> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<unsigned char> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<short> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<unsigned short> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<int> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<unsigned int> + { + static const database_type_id db_type_id = id_int32; + }; + + template <> + struct default_type_traits<long> + { + static const database_type_id db_type_id = id_int64; + }; + + template <> + struct default_type_traits<unsigned long> + { + static const database_type_id db_type_id = id_int64; + }; + + template <> + struct default_type_traits<long long> + { + static const database_type_id db_type_id = id_int64; + }; + + template <> + struct default_type_traits<unsigned long long> + { + static const database_type_id db_type_id = id_int64; + }; + + // Float types. + // + template <> + struct default_type_traits<float> + { + static const database_type_id db_type_id = id_float; + }; + + template <> + struct default_type_traits<double> + { + static const database_type_id db_type_id = id_double; + }; + + // String type. + // + template <> + struct default_type_traits<std::string> + { + static const database_type_id db_type_id = id_string; + }; + + template <> + struct default_type_traits<const char*> + { + static const database_type_id db_type_id = id_string; + }; + + template <std::size_t n> + struct default_type_traits<char[n]> + { + static const database_type_id db_type_id = id_string; + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_ORACLE_TRAITS_HXX |