From f2a1bfb98f447e6c922c12f4403a387243dd65c5 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Thu, 3 Nov 2011 08:16:50 +0200
Subject: Add support for mapping std::vector<unsigned char> to BLOB types

---
 odb/oracle/traits.cxx | 72 +++++++++++++++++++++++++++++++++++++++++++++
 odb/oracle/traits.hxx | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 152 insertions(+), 1 deletion(-)

diff --git a/odb/oracle/traits.cxx b/odb/oracle/traits.cxx
index f9de006..40543ba 100644
--- a/odb/oracle/traits.cxx
+++ b/odb/oracle/traits.cxx
@@ -78,6 +78,28 @@ namespace odb
     }
 
     //
+    // default_value_traits<vector<unsigned char>, id_raw>
+    //
+
+    void default_value_traits<vector<unsigned char>, id_raw>::
+    set_image (char* b,
+               size_t c,
+               size_t& n,
+               bool& is_null,
+               const value_type& v)
+    {
+      is_null = false;
+      n = v.size ();
+
+      assert (n <= c);
+
+      // std::vector::data() may not be available in older compilers.
+      //
+      if (n != 0)
+        memcpy (b, &v.front (), n);
+    }
+
+    //
     // string_lob_value_traits
     //
 
@@ -149,6 +171,7 @@ namespace odb
     //
     // default_value_traits<std::vector<char>, id_blob>
     //
+
     bool default_value_traits<std::vector<char>, id_blob>::
     result_callback (void* c, void* b, ub4 s, chunk_position p)
     {
@@ -193,5 +216,54 @@ namespace odb
 
       return true;
     }
+
+    //
+    // default_value_traits<std::vector<unsigned char>, id_blob>
+    //
+
+    bool default_value_traits<std::vector<unsigned char>, id_blob>::
+    result_callback (void* c, void* b, ub4 s, chunk_position p)
+    {
+      value_type& v (*static_cast<value_type*> (c));
+
+      switch (p)
+      {
+      case one_chunk:
+      case first_chunk:
+        {
+          v.clear ();
+
+          // Falling through.
+        }
+      case next_chunk:
+      case last_chunk:
+        {
+          unsigned char* cb (static_cast<unsigned char*> (b));
+          v.insert (v.end (), cb, cb + s);
+
+          break;
+        }
+      }
+
+      return true;
+    }
+
+    bool default_value_traits<std::vector<unsigned char>, id_blob>::
+    param_callback (const void* ctx,
+                    ub4*,
+                    const void** b,
+                    ub4* s,
+                    chunk_position* p,
+                    void*,
+                    ub4)
+    {
+      const value_type& v (*static_cast<const value_type*> (ctx));
+
+      *p = one_chunk;
+      *s = static_cast<ub4> (v.size ());
+      *b = &v.front ();
+
+      return true;
+    }
   }
 }
diff --git a/odb/oracle/traits.hxx b/odb/oracle/traits.hxx
index bcad915..edaeebf 100644
--- a/odb/oracle/traits.hxx
+++ b/odb/oracle/traits.hxx
@@ -575,7 +575,7 @@ namespace odb
     {
     };
 
-    // std::vector specialization for RAW.
+    // std::vector<char> (buffer) specialization for RAW.
     //
     template <>
     struct default_value_traits<std::vector<char>, id_raw>
@@ -602,6 +602,36 @@ namespace odb
                  const value_type& v);
     };
 
+    // std::vector<unsigned char> (buffer) specialization for RAW.
+    //
+    template <>
+    struct default_value_traits<std::vector<unsigned char>, id_raw>
+    {
+    public:
+      typedef std::vector<unsigned char> value_type;
+      typedef std::vector<unsigned char> query_type;
+      typedef lob_callback image_type;
+
+      static void
+      set_value (value_type& v, const char* b, std::size_t n, bool is_null)
+      {
+        if (!is_null)
+        {
+          const unsigned char* ub (reinterpret_cast<const unsigned char*> (b));
+          v.assign (ub, ub + n);
+        }
+        else
+          v.clear ();
+      }
+
+      static void
+      set_image (char* b,
+                 std::size_t c,
+                 std::size_t& n,
+                 bool& is_null,
+                 const value_type& v);
+    };
+
     // std::string specialization for LOBs.
     //
     class string_lob_value_traits
@@ -781,6 +811,55 @@ namespace odb
                       ub4 capacity);
     };
 
+    // std::vector<unsigned char> (buffer) specialization for BLOBs.
+    //
+    template <>
+    struct default_value_traits<std::vector<unsigned char>, id_blob>
+    {
+    public:
+      typedef std::vector<unsigned char> value_type;
+      typedef std::vector<unsigned char> query_type;
+      typedef lob_callback image_type;
+
+      static void
+      set_value (value_type& v,
+                 result_callback_type& cb,
+                 void*& context,
+                 bool is_null)
+      {
+        if (!is_null)
+        {
+          cb = &result_callback;
+          context = &v;
+        }
+        else
+          v.clear ();
+      }
+
+      static void
+      set_image (param_callback_type& cb,
+                 const void*& context,
+                 bool& is_null,
+                 const value_type& v)
+      {
+        is_null = false;
+        cb = &param_callback;
+        context = &v;
+      }
+
+      static bool
+      result_callback (void* context, void* buffer, ub4 size, chunk_position);
+
+      static bool
+      param_callback (const void* context,
+                      ub4* position_context,
+                      const void** buffer,
+                      ub4* size,
+                      chunk_position*,
+                      void* temp_buffer,
+                      ub4 capacity);
+    };
+
     //
     // type_traits
     //
-- 
cgit v1.1