Skip to content

File extensible_array.hpp

File List > base > extensible_array.hpp

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.
 *
 */

/* extensible_array.hpp -
 *
 *  This header file defines the extensible_array class template.
 */

#ifndef EXTENSIBLE_ARRAY_HPP_
#define EXTENSIBLE_ARRAY_HPP_

#include "mem_block.hpp"

#include <memory>

namespace cubmem
{
  template <size_t Size>
  class appendible_block : public cubmem::extensible_stack_block<Size>
  {
    private:
      using base_type = cubmem::extensible_stack_block<Size>;

    public:

      appendible_block ();
      appendible_block (const block_allocator &alloc);

      inline void append (const char *source, size_t length);    // append at the end of existing data
      inline void copy (const char *source, size_t length);      // overwrite entire array

      template <typename T>
      inline void append (const T &obj);

      inline std::size_t get_size () const;

    private:
      inline void reset ();

      size_t m_size;                                          // current size
  };

  template <typename T, size_t Size>
  class extensible_array : protected extensible_stack_block<sizeof (T) * Size>
  {
    private:
      using base_type = extensible_stack_block<sizeof (T) * Size>;

    public:
      void extend_by (size_t count);
      void extend_to (size_t count);

      const T *get_array (void) const;

    protected:
      T *get_data_ptr ();

      size_t get_memsize_for_count (size_t count) const;
  };

  template <typename T, size_t S>
  class appendable_array : public extensible_array<T, S>
  {
    private:
      using base_type = extensible_array<T, S>;

    public:
      appendable_array (void);
      appendable_array (const block_allocator &allocator);
      ~appendable_array ();

      inline void append (const T &source);
      inline void append (const T *source, size_t length);    // append at the end of existing data
      inline void copy (const T *source, size_t length);      // overwrite entire array
      void erase (size_t index);    // remove at index; does not preserve order

      inline size_t get_size (void) const;                    // get current size

      size_t get_memsize () const;

    private:
      inline void reset (void);                               // reset array
      inline T *get_append_ptr ();

      size_t m_size;                                          // current size
  };
} // namespace cubmem

/************************************************************************/
/* Implementation                                                       */
/************************************************************************/

#include <cassert>
#include <cstring>

namespace cubmem
{
  //
  //  appendible_block
  //
  template <size_t Size>
  appendible_block<Size>::appendible_block ()
    : extensible_stack_block<Size> ()
    , m_size (0)
  {
  }

  template <size_t Size>
  appendible_block<Size>::appendible_block (const block_allocator &alloc)
    : extensible_stack_block<Size> (alloc)
    , m_size (0)
  {
  }

  template <size_t Size>
  std::size_t
  appendible_block<Size>::get_size () const
  {
    return m_size;
  }

  template <size_t Size>
  void
  appendible_block<Size>::reset ()
  {
    m_size = 0;
  }

  template <size_t Size>
  void
  appendible_block<Size>::append (const char *source, size_t length)
  {
    base_type::extend_to (m_size + length);
    std::memcpy (base_type::get_ptr () + m_size, source, length);
    m_size += length;
  }

  template <size_t Size>
  template <typename T>
  void
  appendible_block<Size>::append (const T &obj)
  {
    append (reinterpret_cast<const char *> (&obj), sizeof (obj));
  }

  template <size_t Size>
  void
  appendible_block<Size>::copy (const char *source, size_t length)
  {
    reset ();
    append (source, length);
  }

  //
  // extensible_array
  //
  template <typename T, size_t Size>
  void
  extensible_array<T, Size>::extend_by (size_t count)
  {
    base_type::extend_by (get_memsize_for_count (count));
  }

  template <typename T, size_t Size>
  void
  extensible_array<T, Size>::extend_to (size_t count)
  {
    base_type::extend_to (get_memsize_for_count (count));
  }

  template <typename T, size_t Size>
  const T *
  extensible_array<T, Size>::get_array (void) const
  {
    return reinterpret_cast<const T *> (base_type::get_read_ptr ());
  }

  template <typename T, size_t Size>
  T *
  extensible_array<T, Size>::get_data_ptr ()
  {
    return reinterpret_cast<T *> (base_type::get_ptr ());
  }

  template <typename T, size_t Size>
  size_t
  extensible_array<T, Size>::get_memsize_for_count (size_t count) const
  {
    return count * sizeof (T);
  }

  //
  // appendable_array
  //
  template <typename T, size_t Size>
  appendable_array<T, Size>::appendable_array (void)
    : base_type ()
    , m_size (0)
  {
    //
  }

  template <typename T, size_t Size>
  appendable_array<T, Size>::appendable_array (const block_allocator &allocator)
    : base_type (allocator)
    , m_size (0)
  {
    // empty
  }

  template <typename T, size_t Size>
  appendable_array<T, Size>::~appendable_array ()
  {
    // empty
  }

  template <typename T, size_t Size>
  T *
  appendable_array<T, Size>::get_append_ptr ()
  {
    return base_type::get_data_ptr () + m_size;
  }

  template <typename T, size_t Size>
  void
  appendable_array<T, Size>::append (const T &source)
  {
    append (&source, 1);
  }

  template <typename T, size_t Size>
  void
  appendable_array<T, Size>::append (const T *source, size_t length)
  {
    // make sure memory is enough
    base_type::extend_to (m_size + length);

    // copy data at the end of the array
    std::memcpy (base_type::get_data_ptr () + m_size, source, length * sizeof (T));
    m_size += length;
  }

  template <typename T, size_t Size>
  void
  appendable_array<T, Size>::copy (const T *source, size_t length)
  {
    // copy = reset + append
    reset ();
    append (source, length);
  }

  template <typename T, size_t Size>
  void
  appendable_array<T, Size>::erase (size_t index)
  {
    if (index >= m_size)
      {
    // no op
    return;
      }
    if (index < m_size - 1)
      {
    // overwrite with last
    base_type::get_data_ptr ()[index] = base_type::get_data_ptr ()[m_size - 1];
      }
    --m_size;
  }

  template <typename T, size_t Size>
  size_t
  appendable_array<T, Size>::get_size (void) const
  {
    return m_size;
  }

  template<typename T, size_t S>
  size_t
  appendable_array<T, S>::get_memsize () const
  {
    return base_type::get_memsize_for_count (m_size);
  }

  template <typename T, size_t Size>
  void
  appendable_array<T, Size>::reset (void)
  {
    // set size to zero
    m_size = 0;
  }

} // namespace cubmem

#endif /* !EXTENSIBLE_ARRAY_HPP_ */