From 6f4f07fea0f98bdb1debffcc40a32d6af61ab5c0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 18 Apr 2011 18:50:04 +0200 Subject: Implement automatic mapping for C++ enums --- odb/mysql/enum.cxx | 34 +++++++++++++ odb/mysql/enum.hxx | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ odb/mysql/makefile | 1 + odb/mysql/query.hxx | 17 +++---- odb/mysql/traits.hxx | 31 ++++++++++++ 5 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 odb/mysql/enum.cxx create mode 100644 odb/mysql/enum.hxx diff --git a/odb/mysql/enum.cxx b/odb/mysql/enum.cxx new file mode 100644 index 0000000..d2c8676 --- /dev/null +++ b/odb/mysql/enum.cxx @@ -0,0 +1,34 @@ +// file : odb/mysql/enums.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::memmove +#include + +#include + +namespace odb +{ + namespace mysql + { + void enum_traits:: + strip_value (const details::buffer& i, unsigned long& size) + { + char* d (const_cast (i.data ())); + + unsigned long p (0); + for (; p < size && d[p] != ' '; ++p) ; + assert (p != size); + + p++; // Skip space; + size -= p; + + std::memmove (d, d + p, size); + } + } +} + +#include + +#endif // ODB_MYSQL_ENUMS_HXX diff --git a/odb/mysql/enum.hxx b/odb/mysql/enum.hxx new file mode 100644 index 0000000..95f4ed4 --- /dev/null +++ b/odb/mysql/enum.hxx @@ -0,0 +1,131 @@ +// file : odb/mysql/enums.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_MYSQL_ENUMS_HXX +#define ODB_MYSQL_ENUMS_HXX + +#include + +#include // std::size_t +#include // std::memmove +#include + +#include + +#include +#include +#include + +#include + +namespace odb +{ + namespace mysql + { + // Common interface for working with the dual enum image (integer or + // string). Used by the generated code and query machinery. + // + // We use overload resolution instead of template specialization to + // avoid having to specify the image type explicitly. + // + struct LIBODB_MYSQL_EXPORT enum_traits + { + // + // Integer image. + // + static void + bind (MYSQL_BIND& b, unsigned short& i, unsigned long&, my_bool* is_null) + { + b.buffer_type = MYSQL_TYPE_SHORT; + b.is_unsigned = 1; + b.buffer = &i; + b.is_null = is_null; + } + + static bool + grow (unsigned short&, unsigned long&) + { + return false; + } + + template + static bool + set_image (unsigned short& i, unsigned long&, bool& is_null, const T& v) + { + value_traits::set_image (i, is_null, v); + return false; + } + + template + static void + set_value (T& v, unsigned short i, unsigned long, bool is_null) + { + value_traits::set_value (v, i, is_null); + } + + // + // String image. + // + + static void + bind (MYSQL_BIND& b, + details::buffer& i, + unsigned long& size, + my_bool* is_null) + { + b.buffer_type = MYSQL_TYPE_STRING; + b.buffer = i.data (); + b.buffer_length = static_cast (i.capacity ()); + b.length = &size; + b.is_null = is_null; + } + + static bool + grow (details::buffer& i, unsigned long& size) + { + i.capacity (size); + return true; + } + + template + static bool + set_image (details::buffer& i, + unsigned long& size, + bool& is_null, + const T& v) + { + std::size_t n (0), c (i.capacity ()); + value_traits::set_image (i, n, is_null, v); + size = static_cast (n); + return c != i.capacity (); + } + + template + static void + set_value (T& v, + const details::buffer& i, + unsigned long size, + bool is_null) + { + // The buffer has the following content: " ". Get rid of + // the numeric value so that we have "". For more information + // why it is done this way, see mysql::object_columns class in the + // ODB compiler. + // + strip_value (i, size); + + value_traits::set_value (v, i, size, is_null); + } + + private: + void + strip_value (const details::buffer& i, unsigned long& size); + }; + } +} + +#include + +#endif // ODB_MYSQL_ENUMS_HXX diff --git a/odb/mysql/makefile b/odb/mysql/makefile index 018fd20..91eca19 100644 --- a/odb/mysql/makefile +++ b/odb/mysql/makefile @@ -9,6 +9,7 @@ cxx := \ connection.cxx \ connection-factory.cxx \ database.cxx \ +enum.cxx \ error.cxx \ exceptions.cxx \ object-statements.cxx \ diff --git a/odb/mysql/query.hxx b/odb/mysql/query.hxx index f4845cf..ca95f1c 100644 --- a/odb/mysql/query.hxx +++ b/odb/mysql/query.hxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1676,6 +1677,8 @@ namespace odb // ENUM // + // The image type can be either integer or string. + // template struct query_param_impl: query_param { @@ -1691,10 +1694,7 @@ namespace odb virtual void bind (MYSQL_BIND* b) { - b->buffer_type = MYSQL_TYPE_STRING; - b->buffer = buffer_.data (); - b->buffer_length = static_cast (buffer_.capacity ()); - b->length = &size_; + enum_traits::bind (*b, image_, size_, 0); } private: @@ -1702,15 +1702,12 @@ namespace odb init (const T& v) { bool dummy; - std::size_t size, cap (buffer_.capacity ()); - value_traits::set_image (buffer_, size, dummy, v); - size_ = static_cast (size); - return cap != buffer_.capacity (); + return enum_traits::set_image (image_, size_, dummy, v); } private: - details::buffer buffer_; - unsigned long size_; + typename value_traits::image_type image_; + unsigned long size_; // Keep size in case it is a string. }; // SET diff --git a/odb/mysql/traits.hxx b/odb/mysql/traits.hxx index 5418fa1..7f96c0b 100644 --- a/odb/mysql/traits.hxx +++ b/odb/mysql/traits.hxx @@ -162,6 +162,37 @@ namespace odb } }; + // 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 + struct default_value_traits + { + 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 (i - 1); + else + v = T (); + } + + static void + set_image (unsigned short& i, bool& is_null, const T& v) + { + is_null = false; + i = static_cast (v) + 1; + } + }; + // std::string specialization. // class LIBODB_MYSQL_EXPORT string_value_traits -- cgit v1.1