summaryrefslogtreecommitdiff
path: root/odb-tests/pgsql/types/traits.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb-tests/pgsql/types/traits.hxx')
-rw-r--r--odb-tests/pgsql/types/traits.hxx171
1 files changed, 171 insertions, 0 deletions
diff --git a/odb-tests/pgsql/types/traits.hxx b/odb-tests/pgsql/types/traits.hxx
new file mode 100644
index 0000000..a1c8fbe
--- /dev/null
+++ b/odb-tests/pgsql/types/traits.hxx
@@ -0,0 +1,171 @@
+// file : pgsql/types/traits.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TRAITS_HXX
+#define TRAITS_HXX
+
+#include <cassert>
+#include <cstring> // std::memcpy, std::memset
+
+#include <odb/pgsql/traits.hxx>
+#include <odb/pgsql/details/endian-traits.hxx>
+
+#include "test.hxx" // varbit, ubuffer, string_ptr
+
+namespace odb
+{
+ namespace pgsql
+ {
+ // The first 4 bytes of the image is a signed int specifying the
+ // number of significant bits contained by the BIT. The following
+ // bytes contain the bit data.
+ //
+ template <>
+ class value_traits<bitfield, id_bit>
+ {
+ public:
+ typedef bitfield value_type;
+ typedef bitfield query_type;
+ typedef unsigned char* image_type;
+
+ static void
+ set_value (bitfield& v,
+ const unsigned char* i,
+ std::size_t,
+ bool is_null)
+ {
+ if (!is_null)
+ {
+ assert (
+ details::endian_traits::ntoh (
+ *reinterpret_cast<const int*> (i)) == 4);
+
+ const unsigned char* d (i + 4);
+
+ v.a = *d >> 4 & 1;
+ v.b = (*d >> 5) & 1;
+ v.c = (*d >> 6) & 1;
+ v.d = (*d >> 7) & 1;
+ }
+ else
+ v.a = v.b = v.c = v.d = 0;
+ }
+
+ static void
+ set_image (unsigned char* i,
+ std::size_t,
+ std::size_t& n,
+ bool& is_null,
+ bitfield v)
+ {
+ is_null = false;
+ n = 5;
+
+ *reinterpret_cast<int*> (i) = details::endian_traits::hton (4);
+ *(i + 4) = v.a << 4 | (v.b << 5) | (v.c << 6) | (v.d << 7);
+ }
+ };
+
+ // The first 4 bytes of the image is a signed int specifying the
+ // number of significant bits contained by the VARBIT. The following
+ // bytes contain the VARBIT data.
+ //
+ template <>
+ class value_traits<varbit, id_varbit>
+ {
+ public:
+ typedef varbit value_type;
+ typedef varbit query_type;
+ typedef details::ubuffer image_type;
+
+ static void
+ set_value (varbit& v,
+ const details::ubuffer& b,
+ std::size_t n,
+ bool is_null)
+ {
+ if (!is_null)
+ {
+ v.size = static_cast<std::size_t> (
+ details::endian_traits::ntoh (
+ *reinterpret_cast<const int*> (b.data ())));
+
+ std::size_t byte_len (v.size / 8 + (v.size % 8 > 0 ? 1 : 0));
+ assert (n >= byte_len + 4);
+
+ v.ubuffer_.assign (b.data () + 4, byte_len);
+ }
+
+ else
+ {
+ v.size = 0;
+ v.ubuffer_.assign (0, 0);
+ }
+ }
+
+ static void
+ set_image (details::ubuffer& b,
+ std::size_t& n,
+ bool& is_null,
+ const varbit& v)
+ {
+ is_null = false;
+ n = 4 + v.size / 8 + (v.size % 8 > 0 ? 1 : 0);
+
+ if (n > b.capacity ())
+ b.capacity (n);
+
+ // PostgreSQL requires all trailing bits of a VARBIT image
+ // to be zero.
+ //
+ std::memset (b.data (), 0, b.capacity ());
+
+ *reinterpret_cast<int*> (b.data ()) =
+ details::endian_traits::hton (static_cast<int> (v.size));
+
+ if (v.size != 0)
+ std::memcpy (b.data () + 4, v.ubuffer_.data (), n - 4);
+ }
+ };
+
+ template <>
+ class value_traits<string_ptr, id_string>
+ {
+ public:
+ typedef string_ptr value_type;
+ typedef std::string query_type;
+ typedef details::buffer image_type;
+
+ static void
+ set_value (string_ptr& v,
+ const details::buffer& b,
+ std::size_t n,
+ bool is_null)
+ {
+ v.reset (is_null ? 0 : new std::string (b.data (), n));
+ }
+
+ static void
+ set_image (details::buffer& b,
+ std::size_t& n,
+ bool& is_null,
+ const string_ptr& v)
+ {
+ is_null = v.get () == 0;
+
+ if (!is_null)
+ {
+ n = v->size ();
+
+ if (n > b.capacity ())
+ b.capacity (n);
+
+ if (n != 0)
+ std::memcpy (b.data (), v->c_str (), n);
+ }
+ }
+ };
+ }
+}
+
+#endif // TRAITS_HXX