Skip to content

File packer.cpp

File List > base > packer.cpp

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/*
 * packer.cpp
 */

#ident "$Id$"

#include "packer.hpp"

#include "dbtype_def.h"
#include "memory_alloc.h"
#include "object_representation.h"
#include "packable_object.hpp"

#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"

namespace cubpacking
{
#define MAX_SMALL_STRING_SIZE 255
#define LARGE_STRING_CODE 0xff

  //
  // static function definitions
  static inline int check_range (const char *ptr, const char *endptr, const size_t amount)
  {
    assert (ptr + amount <= endptr);
    return (ptr + amount <= endptr) ? NO_ERROR : ER_FAILED;
  }

  //
  // packer
  //

  packer::packer (void)
  {
    // all pointers are initialized to NULL
    m_error_code = NO_ERROR;
  }

  packer::packer (char *storage, const size_t amount)
  {
    set_buffer (storage, amount);
    m_error_code = NO_ERROR;
  }

  void
  packer::set_buffer (char *storage, const size_t amount)
  {
    m_start_ptr = storage;
    m_ptr = storage;
    m_end_ptr = m_start_ptr + amount;
  }

  unpacker::unpacker (const char *storage, const size_t amount)
  {
    set_buffer (storage, amount);
    m_error_code = NO_ERROR;
  }

  unpacker::unpacker (const cubmem::block &blk)
  {
    set_buffer (blk.ptr, blk.dim);
    m_error_code = NO_ERROR;
  }

  void
  unpacker::set_buffer (const char *storage, const size_t amount)
  {
    m_start_ptr = storage;
    m_ptr = storage;
    m_end_ptr = m_start_ptr + amount;
  }

  bool
  packer::has_error (void) const
  {
    return m_error_code != NO_ERROR;
  }

  bool
  unpacker::has_error (void) const
  {
    return m_error_code != NO_ERROR;
  }

  size_t
  packer::get_packed_int_size (size_t curr_offset)
  {
    return DB_ALIGN (curr_offset, INT_ALIGNMENT) - curr_offset + OR_INT_SIZE;
  }

  void
  packer::pack_int (const int value)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT (m_ptr, value);
    m_ptr += OR_INT_SIZE;
  }

  size_t
  packer::get_packed_size_overloaded (int value, size_t curr_offset)
  {
    return get_packed_int_size (curr_offset);
  }

  void
  packer::pack_overloaded (const int value)
  {
    pack_int (value);
  }

  void
  unpacker::unpack_int (int &value)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    value = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;
  }

  void
  unpacker::unpack_overloaded (int &value)
  {
    unpack_int (value);
  }

  void
  unpacker::peek_unpack_int (int &value)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    value = OR_GET_INT (m_ptr);
  }

  size_t
  packer::get_packed_bool_size (size_t curr_offset)
  {
    return get_packed_int_size (curr_offset);
  }

  void
  packer::pack_bool (const bool value)
  {
    pack_int (value ? 1 : 0);
  }

  size_t
  packer::get_packed_size_overloaded (bool value, size_t curr_offset)
  {
    return get_packed_bool_size (curr_offset);
  }

  void
  packer::pack_overloaded (const bool value)
  {
    pack_bool (value);
  }

  void
  unpacker::unpack_bool (bool &value)
  {
    int int_val;
    unpack_int (int_val);
    assert (int_val == 1 || int_val == 0);
    value = int_val != 0;
  }

  void
  unpacker::unpack_overloaded (bool &value)
  {
    unpack_bool (value);
  }

  size_t
  packer::get_packed_short_size (size_t curr_offset)
  {
    return DB_ALIGN (curr_offset, SHORT_ALIGNMENT) - curr_offset + OR_SHORT_SIZE;
  }

  void
  packer::pack_short (const short value)
  {
    align (SHORT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_SHORT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_SHORT (m_ptr, value);
    m_ptr += OR_SHORT_SIZE;
  }

  size_t
  packer::get_packed_size_overloaded (short value, size_t curr_offset)
  {
    return get_packed_short_size (curr_offset);
  }

  void
  packer::pack_overloaded (short value)
  {
    pack_short (value);
  }

  void
  unpacker::unpack_short (short &value)
  {
    align (SHORT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_SHORT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    value = OR_GET_SHORT (m_ptr);
    m_ptr += OR_SHORT_SIZE;
  }

  void
  unpacker::unpack_overloaded (short &value)
  {
    unpack_short (value);
  }

  size_t
  packer::get_packed_bigint_size (size_t curr_offset)
  {
    return DB_ALIGN (curr_offset, MAX_ALIGNMENT) - curr_offset + OR_BIGINT_SIZE;
  }

  void
  packer::pack_bigint (const std::int64_t &value)
  {
    align (MAX_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_BIGINT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT64 (m_ptr, &value);
    m_ptr += OR_BIGINT_SIZE;
  }

  void
  unpacker::unpack_bigint (std::int64_t &value)
  {
    align (MAX_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_BIGINT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_GET_INT64 (m_ptr, &value);
    m_ptr += OR_BIGINT_SIZE;
  }

  void
  packer::pack_bigint (const std::uint64_t &value)
  {
    align (MAX_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_BIGINT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT64 (m_ptr, &value);
    m_ptr += OR_BIGINT_SIZE;
  }

  size_t
  packer::get_packed_size_overloaded (const std::int64_t &value, size_t curr_offset)
  {
    return get_packed_bigint_size (curr_offset);
  }

  size_t
  packer::get_packed_size_overloaded (const std::uint64_t &value, size_t curr_offset)
  {
    return get_packed_bigint_size (curr_offset);
  }

  void
  packer::pack_overloaded (const std::int64_t &value)
  {
    pack_bigint (value);
  }

  void
  packer::pack_overloaded (const std::uint64_t &value)
  {
    pack_bigint (value);
  }

  void
  unpacker::unpack_bigint (std::uint64_t &value)
  {
    align (MAX_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_BIGINT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_GET_INT64 (m_ptr, &value);
    m_ptr += OR_BIGINT_SIZE;
  }

  void
  unpacker::unpack_overloaded (std::int64_t &value)
  {
    unpack_bigint (value);
  }

  void
  unpacker::unpack_overloaded (std::uint64_t &value)
  {
    unpack_bigint (value);
  }

  void
  packer::pack_int_array (const int *array, const int count)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, (OR_INT_SIZE * (count + 1))) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT (m_ptr, count);
    m_ptr += OR_INT_SIZE;
    for (int i = 0; i < count; i++)
      {
    OR_PUT_INT (m_ptr, array[i]);
    m_ptr += OR_INT_SIZE;
      }
  }

  void
  unpacker::unpack_int_array (int *array, int &count)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    count = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;

    if (count == 0)
      {
    return;
      }

    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE * count) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    for (int i = 0; i < count; i++)
      {
    array[i] = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;
      }
  }

  size_t
  packer::get_packed_int_array_size (size_t curr_offset, const size_t count)
  {
    return DB_ALIGN (curr_offset, INT_ALIGNMENT) - curr_offset + (OR_INT_SIZE * (count + 1));
  }

  size_t
  packer::get_packed_db_value_size (const db_value &value, size_t curr_offset)
  {
    size_t aligned_offset = DB_ALIGN (curr_offset, MAX_ALIGNMENT);
    size_t unaligned_size = or_packed_value_size (&value, 1, 1, 0);
    size_t aligned_size = unaligned_size;
    return aligned_size + aligned_offset - curr_offset;
  }

  void
  packer::pack_db_value (const db_value &value)
  {
    size_t value_size = or_packed_value_size (&value, 1, 1, 0);

    align (MAX_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, value_size) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_BUF orbuf;
    delegate_to_or_buf (value_size, orbuf);
    or_put_value (&orbuf, (db_value *) &value, 1, 1, 0);

    if (check_range (m_ptr, m_end_ptr, 0) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }
  }

  size_t
  packer::get_packed_size_overloaded (const db_value &value, size_t curr_offset)
  {
    return get_packed_db_value_size (value, curr_offset);
  }

  void
  packer::pack_overloaded (const db_value &value)
  {
    pack_db_value (value);
  }

  void
  unpacker::unpack_db_value (db_value &value)
  {
    const char *old_ptr;

    align (MAX_ALIGNMENT);
    old_ptr = m_ptr;
    m_ptr = or_unpack_value (m_ptr, &value);

    size_t value_size = or_packed_value_size (&value, 1, 1, 0);
    assert (old_ptr + value_size == m_ptr);

    if (check_range (m_ptr, m_end_ptr, 0) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }
  }

  void
  unpacker::unpack_overloaded (db_value &value)
  {
    unpack_db_value (value);
  }

  void
  packer::pack_small_c_string (const char *string, const size_t str_size)
  {
    assert (str_size < MAX_SMALL_STRING_SIZE);

    if (check_range (m_ptr, m_end_ptr, str_size + 1) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_BYTE (m_ptr, str_size);
    m_ptr += OR_BYTE_SIZE;
    if (str_size > 0)
      {
    std::memcpy (m_ptr, string, str_size);
    m_ptr += str_size;
      }

    align (INT_ALIGNMENT);
  }

  void
  packer::pack_large_c_string (const char *string, const size_t str_size)
  {
    size_t len;

    if (str_size == 0)
      {
    len = strlen (string);
      }
    else
      {
    len = str_size;
      }

    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, len + OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT (m_ptr, len);
    m_ptr += OR_INT_SIZE;

    std::memcpy (m_ptr, string, len);
    m_ptr += len;

    align (INT_ALIGNMENT);
  }

  void
  unpacker::unpack_large_string (std::string &str)
  {
    size_t len;

    align (INT_ALIGNMENT);

    if (check_range (m_ptr, m_end_ptr, OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    len = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;

    if (len > 0)
      {
    if (check_range (m_ptr, m_end_ptr, len) != NO_ERROR)
      {
        er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
        m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
        return;
      }
    str = std::string (m_ptr, len);
    m_ptr += len;
      }

    align (INT_ALIGNMENT);
  }

  size_t
  packer::get_packed_string_size (const std::string &str, const size_t curr_offset)
  {
    return get_packed_c_string_size (str.c_str (), str.size (), curr_offset);
  }

  void
  packer::pack_string (const std::string &str)
  {
    pack_c_string (str.c_str (), str.size ());
  }

  size_t
  packer::get_packed_size_overloaded (const std::string &value, size_t curr_offset)
  {
    return get_packed_string_size (value, curr_offset);
  }

  void
  packer::pack_overloaded (const std::string &str)
  {
    pack_string (str);
  }

  size_t
  packer::get_packed_size_overloaded (const char *value, size_t curr_offset)
  {
    return get_packed_c_string_size (value, strlen (value), curr_offset);
  }

  void
  packer::pack_overloaded (const char *str)
  {
    pack_c_string (str, strlen (str));
  }

  void
  unpacker::unpack_string (std::string &str)
  {
    size_t len;

    if (check_range (m_ptr, m_end_ptr, 1) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    len = OR_GET_BYTE (m_ptr);

    if (len == LARGE_STRING_CODE)
      {
    m_ptr++;
    unpack_large_string (str);
      }
    else
      {
    m_ptr++;

    str = std::string (m_ptr, len);
    m_ptr += len;

    align (INT_ALIGNMENT);
      }
  }

  void
  unpacker::unpack_overloaded (std::string &str)
  {
    return unpack_string (str);
  }

  size_t
  packer::get_packed_c_string_size (const char *str, const size_t str_size, const size_t curr_offset)
  {
    size_t entry_size;

    if (str_size < MAX_SMALL_STRING_SIZE)
      {
    entry_size = OR_BYTE_SIZE + str_size;
      }
    else
      {
    entry_size = DB_ALIGN (OR_BYTE_SIZE, INT_ALIGNMENT) + OR_INT_SIZE + str_size;
      }

    return DB_ALIGN (curr_offset + entry_size, INT_ALIGNMENT) - curr_offset;
  }

  void
  packer::pack_c_string (const char *str, const size_t str_size)
  {
    if (str_size < MAX_SMALL_STRING_SIZE)
      {
    pack_small_c_string (str, str_size);
      }
    else
      {
    if (check_range (m_ptr, m_end_ptr, str_size + 1 + OR_INT_SIZE) != NO_ERROR)
      {
        er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
        m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
        return;
      }

    OR_PUT_BYTE (m_ptr, LARGE_STRING_CODE);
    m_ptr++;

    pack_large_c_string (str, str_size);
      }
  }

  void
  unpacker::unpack_string_size (size_t &len)
  {
    if (check_range (m_ptr, m_end_ptr, 1) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }
    len = OR_GET_BYTE (m_ptr);
    if (len == LARGE_STRING_CODE)
      {
    m_ptr++;

    align (OR_INT_SIZE);

    len = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;
      }
    else
      {
    m_ptr++;
      }
    if (len > 0)
      {
    if (check_range (m_ptr, m_end_ptr, len) != NO_ERROR)
      {
        er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
        m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
        return;
      }
      }
  }

  void
  unpacker::unpack_c_string (char *str, const size_t max_str_size)
  {
    size_t len = 0;

    unpack_string_size (len);

    if (len >= max_str_size)
      {
    assert (max_str_size == 0);
    align (INT_ALIGNMENT);
    return;
      }
    if (len > 0)
      {
    std::memcpy (str, m_ptr, len);
    m_ptr += len;
      }

    str[len] = '\0';

    align (INT_ALIGNMENT);
  }

  void
  unpacker::unpack_string_to_memblock (cubmem::extensible_block &blk)
  {
    size_t len;
    unpack_string_size (len);

    // make sure memory size is enough
    blk.extend_to (len + 1);

    if (len > 0)
      {
    std::memcpy (blk.get_ptr (), m_ptr, len);
    m_ptr += len;
      }
    blk.get_ptr ()[len] = '\0';

    align (INT_ALIGNMENT);
  }

  size_t
  packer::get_packed_size_overloaded (const packable_object &po, size_t curr_offset)
  {
    // align first
    size_t aligned_offset = DB_ALIGN (curr_offset, MAX_ALIGNMENT);
    return po.get_packed_size (*this) + aligned_offset - curr_offset;
  }

  void
  packer::pack_overloaded (const packable_object &po)
  {
    po.pack (*this);
  }

  void
  cubpacking::unpacker::unpack_overloaded (packable_object &po)
  {
    po.unpack (*this);
  }

  size_t
  packer::get_packed_oid_size (const size_t curr_offset)
  {
    return DB_ALIGN (curr_offset + OR_OID_SIZE, INT_ALIGNMENT) - curr_offset;
  }

  void
  packer::pack_oid (const OID &oid)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_OID_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_OID (m_ptr, &oid);
    m_ptr += OR_OID_SIZE;
  }

  size_t
  packer::get_packed_size_overloaded (const OID &oid, size_t curr_offset)
  {
    return get_packed_oid_size (curr_offset);
  }

  void
  packer::pack_overloaded (const OID &oid)
  {
    pack_oid (oid);
  }

  void
  unpacker::unpack_oid (OID &oid)
  {
    align (INT_ALIGNMENT);
    if (check_range (m_ptr, m_end_ptr, OR_OID_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_GET_OID (m_ptr, &oid);
    m_ptr += OR_OID_SIZE;
  }

  void
  unpacker::unpack_overloaded (OID &oid)
  {
    return unpack_oid (oid);
  }

  size_t
  packer::get_packed_size_overloaded (const cubmem::block &blk, size_t curr_offset)
  {
    return get_packed_buffer_size (blk.ptr, blk.dim, curr_offset);
  }

  void
  packer::pack_overloaded (const cubmem::block &blk)
  {
    pack_buffer_with_length (blk.ptr, blk.dim);
  }

  void
  unpacker::unpack_overloaded (cubmem::block &blk)
  {
    return unpack_buffer_with_length (blk.ptr, blk.dim);
  }

  const char *
  unpacker::get_curr_ptr (void)
  {
    return m_ptr;
  }

  void
  unpacker::align (const size_t req_alignment)
  {
    m_ptr = PTR_ALIGN (m_ptr, req_alignment);
  }

  size_t
  unpacker::get_current_size (void)
  {
    return get_curr_ptr () - get_buffer_start ();
  }

  const char *
  unpacker::get_buffer_start (void)
  {
    return m_start_ptr;
  }

  const char *
  unpacker::get_buffer_end (void)
  {
    return m_end_ptr;
  }

  bool
  unpacker::is_ended (void)
  {
    return get_curr_ptr () == get_buffer_end ();
  }

  size_t
  packer::get_packed_buffer_size (const char *stream, const size_t length, const size_t curr_offset) const
  {
    size_t actual_length = 0;

    if (stream != NULL)
      {
    actual_length = length;
      }

    size_t entry_size = OR_INT_SIZE + actual_length;

    return DB_ALIGN (curr_offset, INT_ALIGNMENT) + entry_size - curr_offset;
  }

  void
  packer::pack_buffer_with_length (const char *stream, const size_t length)
  {
    align (INT_ALIGNMENT);

    if (check_range (m_ptr, m_end_ptr, length + OR_INT_SIZE) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    OR_PUT_INT (m_ptr, length);
    m_ptr += OR_INT_SIZE;

    if (length > 0)
      {
    std::memcpy (m_ptr, stream, length);
    m_ptr += length;

    align (INT_ALIGNMENT);
      }
  }

  void unpacker::peek_unpack_buffer_length (int &value)
  {
    return peek_unpack_int (value);
  }

  /*
   * unpack_buffer_with_length : unpacks a stream into a preallocated buffer
   * stream (in/out) : output stream
   * max_length (in) : maximum length to unpack
   *
   * Note : the unpacker pointer is incremented with the actual length of buffer (found in unpacker)
   */
  void
  unpacker::unpack_buffer_with_length (char *stream, const size_t max_length)
  {
    size_t actual_len, copy_length;

    align (INT_ALIGNMENT);

    actual_len = OR_GET_INT (m_ptr);
    m_ptr += OR_INT_SIZE;

    assert (actual_len <= max_length);
    copy_length = std::min (actual_len, max_length);

    if (check_range (m_ptr, m_end_ptr, actual_len) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }

    if (copy_length > 0)
      {
    memcpy (stream, m_ptr, copy_length);
      }

    m_ptr += actual_len;
    align (INT_ALIGNMENT);
  }


  void
  packer::delegate_to_or_buf (const size_t size, or_buf &buf)
  {
    if (check_range (m_ptr, m_end_ptr, size) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }
    or_init (&buf, m_ptr, size);
    m_ptr += size;
  }

  const char *
  packer::get_curr_ptr (void)
  {
    return m_ptr;
  }

  size_t
  packer::get_current_size (void)
  {
    return get_curr_ptr () - get_buffer_start ();
  }

  void
  packer::align (const size_t req_alignment)
  {
    m_ptr = PTR_ALIGN (m_ptr, req_alignment);
  }

  const char *
  packer::get_buffer_start (void)
  {
    return m_start_ptr;
  }

  const char *
  packer::get_buffer_end (void)
  {
    return m_end_ptr;
  }

  bool
  packer::is_ended (void)
  {
    return get_curr_ptr () == get_buffer_end ();
  }

  void
  unpacker::delegate_to_or_buf (const size_t size, or_buf &buf)
  {
    if (check_range (m_ptr, m_end_ptr, size) != NO_ERROR)
      {
    er_set (ER_FATAL_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_ENOUGH_DATA_SIZE, 0);
    m_error_code = ER_INTERFACE_NOT_ENOUGH_DATA_SIZE;
    return;
      }
    // promise you won't write on it!
    or_init (&buf, const_cast <char *> (m_ptr), size);
    m_ptr += size;
  }

} /* namespace cubpacking */