This is an automated email from the git hooks/post-receive script. rene pushed a commit to branch master in repository mdds.
commit 575080d0ce9222eb8c7b27af140224aba2c1f7f2 Author: Rene Engelhard <[email protected]> Date: Thu Apr 21 14:50:52 2016 +0200 Imported Upstream version 0.10.3 --- NEWS | 20 ++++ configure | 32 +++---- configure.ac | 2 +- include/mdds/multi_type_vector.hpp | 82 +++++++++++++++-- include/mdds/multi_type_vector_def.inl | 163 +++++++++++++++++++++++++++------ src/multi_type_vector_test_custom.cpp | 56 ++++++++++- src/multi_type_vector_test_default.cpp | 101 +++++++++++++++++++- 7 files changed, 399 insertions(+), 57 deletions(-) diff --git a/NEWS b/NEWS index b9657ff..db4b75f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,23 @@ +mdds 0.10.3 + +* multi_type_vector + + * added 2 variants of release_range() that take start and end positions, + to allow releasing of elements in specified interval. One of the + variants takes iterator as a block position hint. + + * iterator release_range(size_type start_pos, size_type end_pos) + + * iterator release_range(const iterator& pos_hint, size_type start_pos, size_type end_pos) + + * added push_back() and push_back_empty(), to allow efficient way to + append new values to the end of the container. + + * template<typename _T> + iterator push_back(const _T& value) + + * iterator push_back_empty() + mdds 0.10.2 * multi_type_vector diff --git a/configure b/configure index a9347d2..6880c85 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for mdds 0.10.2. +# Generated by GNU Autoconf 2.69 for mdds 0.10.3. # # Report bugs to <[email protected]>. # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='mdds' PACKAGE_TARNAME='mdds' -PACKAGE_VERSION='0.10.2' -PACKAGE_STRING='mdds 0.10.2' +PACKAGE_VERSION='0.10.3' +PACKAGE_STRING='mdds 0.10.3' PACKAGE_BUGREPORT='[email protected]' PACKAGE_URL='' @@ -1181,7 +1181,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures mdds 0.10.2 to adapt to many kinds of systems. +\`configure' configures mdds 0.10.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1242,7 +1242,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of mdds 0.10.2:";; + short | recursive ) echo "Configuration of mdds 0.10.3:";; esac cat <<\_ACEOF @@ -1335,7 +1335,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mdds configure 0.10.2 +mdds configure 0.10.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1352,7 +1352,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by mdds $as_me 0.10.2, which was +It was created by mdds $as_me 0.10.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1701,7 +1701,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -VERSION=0.10.2 +VERSION=0.10.3 PACKAGE_TARNAME=mdds @@ -2298,7 +2298,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mdds $as_me 0.10.2, which was +This file was extended by mdds $as_me 0.10.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -2351,7 +2351,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mdds config.status 0.10.2 +mdds config.status 0.10.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -3455,7 +3455,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mdds $as_me 0.10.2, which was +This file was extended by mdds $as_me 0.10.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -3508,7 +3508,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mdds config.status 0.10.2 +mdds config.status 0.10.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -4613,7 +4613,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mdds $as_me 0.10.2, which was +This file was extended by mdds $as_me 0.10.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4666,7 +4666,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mdds config.status 0.10.2 +mdds config.status 0.10.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -5772,7 +5772,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mdds $as_me 0.10.2, which was +This file was extended by mdds $as_me 0.10.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5825,7 +5825,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mdds config.status 0.10.2 +mdds config.status 0.10.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index bee551b..678d2a2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(mdds, 0.10.2, [email protected]) +AC_INIT(mdds, 0.10.3, [email protected]) VERSION=AC_PACKAGE_VERSION AC_SUBST(VERSION) diff --git a/include/mdds/multi_type_vector.hpp b/include/mdds/multi_type_vector.hpp index b48d5d6..57c8734 100644 --- a/include/mdds/multi_type_vector.hpp +++ b/include/mdds/multi_type_vector.hpp @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2011-2013 Kohei Yoshida + * Copyright (c) 2011-2014 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -261,7 +261,7 @@ public: * position to yield any performance benefit.</p> * * <p>The caller is responsible for ensuring that the passed iterator is - * valid. The behavior of this method when passing an invalid iteraotr is + * valid. The behavior of this method when passing an invalid iterator is * undefined.</p> * * <p>The method will throw an <code>std::out_of_range</code> exception @@ -319,7 +319,7 @@ public: * position to yield any performance benefit.</p> * * <p>The caller is responsible for ensuring that the passed iterator is - * valid. The behavior of this method when passing an invalid iteraotr is + * valid. The behavior of this method when passing an invalid iterator is * undefined.</p> * * <p>The method will throw an <code>std::out_of_range</code> exception if @@ -345,6 +345,27 @@ public: iterator set(const iterator& pos_hint, size_type pos, const _T& it_begin, const _T& it_end); /** + * Append a new value to the end of the container. + * + * @param value new value to be appended to the end of the container. + * + * @return iterator position pointing to the block where the value is + * appended, which in this case is always the last block of the + * container. + */ + template<typename _T> + iterator push_back(const _T& value); + + /** + * Append a new empty element to the end of the container. + * + * @return iterator position pointing to the block where the new empty + * element is appended, which in this case is always the last + * block of the container. + */ + iterator push_back_empty(); + + /** * Insert multiple values of identical type to a specified position. * Existing values that occur at or below the specified position will get * shifted after the insertion. No existing values will be overwritten by @@ -384,7 +405,7 @@ public: * position to yield any performance benefit.</p> * * <p>The caller is responsible for ensuring that the passed iterator is - * valid. The behavior of this method when passing an invalid iteraotr is + * valid. The behavior of this method when passing an invalid iterator is * undefined.</p> * * <p>The method will throw an <code>std::out_of_range</code> exception @@ -497,6 +518,49 @@ public: void release(); /** + * Make all elements within specified range empty, and relinquish the + * ownership of the elements in that range. All elements in the managed + * blocks within the range will be released and the container will no + * longer manage their life cycles after the call. + * + * <p>The method will throw an <code>std::out_of_range</code> exception if + * either the starting or the ending position is outside the current + * container size.</p> + * + * @param start_pos starting position + * @param end_pos ending position, inclusive. + * @return iterator position pointing to the block where the elements are + * released. + */ + iterator release_range(size_type start_pos, size_type end_pos); + + /** + * Make all elements within specified range empty, and relinquish the + * ownership of the elements in that range. All elements in the managed + * blocks within the range will be released and the container will no + * longer manage their life cycles after the call. + * + * <p>This variant takes an iterator as an additional parameter, which is + * used as a block position hint to speed up the lookup of the first block + * to empty. The other variant that doesn't take an iterator always + * starts the block lookup from the first block, which does not + * scale well as the block size grows.</p> + * + * <p>The method will throw an <code>std::out_of_range</code> exception if + * either the starting or the ending position is outside the current + * container size.</p> + * + * @param pos_hint iterator used as a block position hint, to specify + * which block to start when searching for the right + * blocks in which elements are to be released. + * @param start_pos starting position + * @param end_pos ending position, inclusive. + * @return iterator position pointing to the block where the elements are + * released. + */ + iterator release_range(const iterator& pos_hint, size_type start_pos, size_type end_pos); + + /** * Given the logical position of an element, get the iterator of the block * where the element is located, and its offset from the first element of * that block. @@ -661,7 +725,7 @@ public: * position to yield any performance benefit.</p> * * <p>The caller is responsible for ensuring that the passed iterator is - * valid. The behavior of this method when passing an invalid iteraotr is + * valid. The behavior of this method when passing an invalid iterator is * undefined.</p> * * <p>The method will throw an <code>std::out_of_range</code> exception if @@ -725,7 +789,7 @@ public: * position to yield any performance benefit.</p> * * <p>The caller is responsible for ensuring that the passed iterator is - * valid. The behavior of this method when passing an invalid iteraotr is + * valid. The behavior of this method when passing an invalid iterator is * undefined.</p> * * <p>The method will throw an <code>std::out_of_range</code> exception if @@ -910,7 +974,9 @@ private: size_type start_pos_in_block2, size_type block_index2, multi_type_vector& dest, size_type dest_pos); - iterator set_empty_impl(size_type start_pos, size_type end_pos, size_type start_pos_in_block1, size_type block_index1); + iterator set_empty_impl( + size_type start_pos, size_type end_pos, size_type start_pos_in_block1, size_type block_index1, + bool overwrite); void swap_impl( multi_type_vector& other, size_type start_pos, size_type end_pos, size_type other_pos, @@ -1060,6 +1126,8 @@ private: size_type dst_index1, size_type dst_offset1, size_type dst_index2, size_type dst_offset2, size_type len, blocks_type& new_blocks); + bool append_empty(size_type len); + inline iterator get_iterator(size_type block_index, size_type start_row) { typename blocks_type::iterator block_pos = m_blocks.begin(); diff --git a/include/mdds/multi_type_vector_def.inl b/include/mdds/multi_type_vector_def.inl index ed70404..d20a9df 100644 --- a/include/mdds/multi_type_vector_def.inl +++ b/include/mdds/multi_type_vector_def.inl @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2012-2013 Kohei Yoshida + * Copyright (c) 2012-2014 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -494,6 +494,69 @@ multi_type_vector<_CellBlockFunc>::set(const iterator& pos_hint, size_type pos, template<typename _CellBlockFunc> template<typename _T> typename multi_type_vector<_CellBlockFunc>::iterator +multi_type_vector<_CellBlockFunc>::push_back(const _T& value) +{ + element_category_type cat = mdds_mtv_get_element_type(value); + + block* blk_last = m_blocks.empty() ? NULL : m_blocks.back(); + if (!blk_last || !blk_last->mp_data || cat != get_block_type(*blk_last->mp_data)) + { + // Either there is no block, or the last block is empty or of + // different type. Append a new block. + size_type block_index = m_blocks.size(); + size_type start_pos = m_cur_size; + + m_blocks.push_back(new block(1)); + block* blk = m_blocks.back(); + create_new_block_with_new_cell(blk->mp_data, value); + ++m_cur_size; + + return get_iterator(block_index, start_pos); + } + + assert(blk_last); + assert(blk_last->mp_data); + assert(cat == get_block_type(*blk_last->mp_data)); + + // Append the new value to the last block. + size_type block_index = m_blocks.size() - 1; + size_type start_pos = m_cur_size - blk_last->m_size; + + mdds_mtv_append_value(*blk_last->mp_data, value); + ++blk_last->m_size; + ++m_cur_size; + + return get_iterator(block_index, start_pos); +} + +template<typename _CellBlockFunc> +typename multi_type_vector<_CellBlockFunc>::iterator +multi_type_vector<_CellBlockFunc>::push_back_empty() +{ + size_type last_block_size = 0; + if (!m_blocks.empty()) + last_block_size = m_blocks.back()->m_size; + + size_type block_index = m_blocks.size(); + size_type start_pos = m_cur_size; + + if (!append_empty(1)) + { + // Last empty block has been extended. + --block_index; + start_pos -= last_block_size; + } + + // Get the iterator of the last block. + typename blocks_type::iterator block_pos = m_blocks.end(); + --block_pos; + + return iterator(block_pos, m_blocks.end(), start_pos, block_index); +} + +template<typename _CellBlockFunc> +template<typename _T> +typename multi_type_vector<_CellBlockFunc>::iterator multi_type_vector<_CellBlockFunc>::insert(size_type pos, const _T& it_begin, const _T& it_end) { size_type block_index = 0, start_pos = 0; @@ -1204,6 +1267,29 @@ void multi_type_vector<_CellBlockFunc>::release() } template<typename _CellBlockFunc> +typename multi_type_vector<_CellBlockFunc>::iterator +multi_type_vector<_CellBlockFunc>::release_range(size_type start_pos, size_type end_pos) +{ + size_type start_pos_in_block1 = 0; + size_type block_index1 = 0; + if (!get_block_position(start_pos, start_pos_in_block1, block_index1)) + throw std::out_of_range("Block position not found!"); + + return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, false); +} + +template<typename _CellBlockFunc> +typename multi_type_vector<_CellBlockFunc>::iterator +multi_type_vector<_CellBlockFunc>::release_range( + const iterator& pos_hint, size_type start_pos, size_type end_pos) +{ + size_type start_pos_in_block1 = 0; + size_type block_index1 = 0; + get_block_position(pos_hint, start_pos, start_pos_in_block1, block_index1); + return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, false); +} + +template<typename _CellBlockFunc> typename multi_type_vector<_CellBlockFunc>::position_type multi_type_vector<_CellBlockFunc>::position(size_type pos) { @@ -1361,7 +1447,7 @@ multi_type_vector<_CellBlockFunc>::set_empty(size_type start_pos, size_type end_ if (!get_block_position(start_pos, start_pos_in_block1, block_index1)) throw std::out_of_range("Block position not found!"); - return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1); + return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, true); } template<typename _CellBlockFunc> @@ -1371,7 +1457,7 @@ multi_type_vector<_CellBlockFunc>::set_empty(const iterator& pos_hint, size_type size_type start_pos_in_block1 = 0; size_type block_index1 = 0; get_block_position(pos_hint, start_pos, start_pos_in_block1, block_index1); - return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1); + return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, true); } template<typename _CellBlockFunc> @@ -1381,7 +1467,12 @@ multi_type_vector<_CellBlockFunc>::transfer_impl( multi_type_vector& dest, size_type dest_pos) { if (start_pos > end_pos) - throw std::out_of_range("Start row is larger than the end row."); + { + std::ostringstream os; + os << "multi_type_vector::transfer_impl: start position is larger than the end position. (start="; + os << start_pos << ", end=" << end_pos << ")"; + throw std::out_of_range(os.str()); + } size_type start_pos_in_block2 = start_pos_in_block1; size_type block_index2 = block_index1; @@ -1744,7 +1835,8 @@ multi_type_vector<_CellBlockFunc>::transfer_multi_blocks( template<typename _CellBlockFunc> typename multi_type_vector<_CellBlockFunc>::iterator multi_type_vector<_CellBlockFunc>::set_empty_impl( - size_type start_pos, size_type end_pos, size_type start_pos_in_block1, size_type block_index1) + size_type start_pos, size_type end_pos, size_type start_pos_in_block1, size_type block_index1, + bool overwrite) { if (start_pos > end_pos) throw std::out_of_range("Start row is larger than the end row."); @@ -1761,10 +1853,10 @@ multi_type_vector<_CellBlockFunc>::set_empty_impl( iterator ret_it; if (block_index1 == block_index2) - ret_it = set_empty_in_single_block(start_pos, end_pos, block_index1, start_pos_in_block1, true); + ret_it = set_empty_in_single_block(start_pos, end_pos, block_index1, start_pos_in_block1, overwrite); else ret_it = set_empty_in_multi_blocks( - start_pos, end_pos, block_index1, start_pos_in_block1, block_index2, start_pos_in_block2, true); + start_pos, end_pos, block_index1, start_pos_in_block1, block_index2, start_pos_in_block2, overwrite); #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG if (!check_block_integrity()) @@ -2838,6 +2930,39 @@ multi_type_vector<_CellBlockFunc>::exchange_elements( } template<typename _CellBlockFunc> +bool multi_type_vector<_CellBlockFunc>::append_empty(size_type len) +{ + // Append empty cells. + if (m_blocks.empty()) + { + // No existing block. Create a new one. + assert(m_cur_size == 0); + m_blocks.push_back(new block(len)); + m_cur_size = len; + return true; + } + + bool new_block_added = false; + block* blk_last = m_blocks.back(); + + if (!blk_last->mp_data) + { + // Last block is empty. Just increase its size. + blk_last->m_size += len; + } + else + { + // Append a new empty block. + m_blocks.push_back(new block(len)); + new_block_added = true; + } + + m_cur_size += len; + + return new_block_added; +} + +template<typename _CellBlockFunc> void multi_type_vector<_CellBlockFunc>::exchange_elements( const element_block_type& src_data, size_type src_offset, size_type dst_index1, size_type dst_offset1, size_type dst_index2, size_type dst_offset2, @@ -3452,29 +3577,7 @@ void multi_type_vector<_CellBlockFunc>::resize(size_type new_size) if (new_size > m_cur_size) { // Append empty cells. - if (m_blocks.empty()) - { - // No existing block. Create a new one. - assert(m_cur_size == 0); - m_blocks.push_back(new block(new_size)); - m_cur_size = new_size; - return; - } - - block* blk_last = m_blocks.back(); - size_type delta = new_size - m_cur_size; - - if (!blk_last->mp_data) - { - // Last block is empty. Just increase its size. - blk_last->m_size += delta; - } - else - { - // Append a new empty block. - m_blocks.push_back(new block(delta)); - } - m_cur_size = new_size; + append_empty(new_size - m_cur_size); return; } diff --git a/src/multi_type_vector_test_custom.cpp b/src/multi_type_vector_test_custom.cpp index cf3e03a..42d9156 100644 --- a/src/multi_type_vector_test_custom.cpp +++ b/src/multi_type_vector_test_custom.cpp @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2012 Kohei Yoshida + * Copyright (c) 2012-2014 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -1430,10 +1430,62 @@ void mtv_test_release() { stack_printer __stack_printer__("::mtv_test_release"); mtv_type db(3); - muser_cell c1(1.2), c2(1.3); + muser_cell c1(1.2), c2(1.3); // allocated on the stack. db.set(0, &c1); db.set(2, &c2); db.release(); // Prevent invalid free when db goes out of scope. + + // Variant with no argument should make the container empty after the call. + assert(db.empty()); + + db.push_back(new muser_cell(10.0)); + db.push_back(&c1); + db.push_back(&c2); + db.push_back(new muser_cell(10.1)); + + assert(db.size() == 4); + assert(db.block_size() == 1); + + // Release those allocated on the stack to avoid double deletion. + mtv_type::iterator it = db.release_range(1, 2); + + // Check the integrity of the returned iterator. + assert(it->type == mtv::element_type_empty); + assert(it->size == 2); + mtv_type::iterator check = it; + --check; + assert(check == db.begin()); + check = it; + ++check; + ++check; + assert(check == db.end()); + + db.push_back(new muser_cell(10.2)); + assert(db.size() == 5); + + muser_cell* p1 = db.get<muser_cell*>(3); + muser_cell* p2 = db.get<muser_cell*>(4); + assert(p1->value == 10.1); + assert(p2->value == 10.2); + + // Pass iterator as a position hint. + it = db.release_range(it, 3, 4); + assert(db.block_size() == 2); + + // Check the returned iterator. + check = it; + --check; + assert(check == db.begin()); + assert(check->type == element_type_muser_block); + assert(check->size == 1); + assert(it->type == mtv::element_type_empty); + assert(it->size == 4); + ++it; + assert(it == db.end()); + + // It should be safe to delete these instances now that they've been released. + delete p1; + delete p2; } void mtv_test_construction_with_array() diff --git a/src/multi_type_vector_test_default.cpp b/src/multi_type_vector_test_default.cpp index b6bbc27..8345b0f 100644 --- a/src/multi_type_vector_test_default.cpp +++ b/src/multi_type_vector_test_default.cpp @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2011-2013 Kohei Yoshida + * Copyright (c) 2011-2014 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -4880,6 +4880,104 @@ void mtv_test_transfer() it = db1.transfer(1, 2, db2, 1); } +void mtv_test_push_back() +{ + stack_printer __stack_printer__("::mtv_test_push_back"); + + mtv_type db; + assert(db.size() == 0); + assert(db.block_size() == 0); + + // Append an empty element into an empty container. + mtv_type::iterator it = db.push_back_empty(); + assert(db.size() == 1); + assert(db.block_size() == 1); + assert(it->size == 1); + assert(it->type == mtv::element_type_empty); + assert(it->__private_data.block_index == 0); + assert(it == db.begin()); + ++it; + assert(it == db.end()); + + // ... and again. + it = db.push_back_empty(); + assert(db.size() == 2); + assert(db.block_size() == 1); + assert(it->size == 2); + assert(it->type == mtv::element_type_empty); + assert(it->__private_data.block_index == 0); + assert(it == db.begin()); + ++it; + assert(it == db.end()); + + // Append non-empty this time. + it = db.push_back(1.1); + assert(db.size() == 3); + assert(db.block_size() == 2); + assert(it->size == 1); + assert(it->type == mtv::element_type_numeric); + assert(it->__private_data.block_index == 1); + mtv_type::iterator check = it; + --check; + assert(check == db.begin()); + ++it; + assert(it == db.end()); + + // followed by an empty element again. + it = db.push_back_empty(); + assert(db.size() == 4); + assert(db.block_size() == 3); + assert(it->size == 1); + assert(it->type == mtv::element_type_empty); + assert(it->__private_data.block_index == 2); + check = it; + --check; + --check; + assert(check == db.begin()); + ++it; + assert(it == db.end()); + + // Check the values. + assert(db.is_empty(0)); + assert(db.is_empty(1)); + assert(db.get<double>(2) == 1.1); + assert(db.is_empty(3)); + + // Empty the container and push back a non-empty element. + db.clear(); + it = db.push_back(string("push me")); + assert(db.size() == 1); + assert(db.block_size() == 1); + assert(it->size == 1); + assert(it->type == mtv::element_type_string); + assert(it->__private_data.block_index == 0); + assert(it == db.begin()); + ++it; + assert(it == db.end()); + assert(db.get<string>(0) == "push me"); + + // Push back a non-empty element of the same type. + it = db.push_back(string("again")); + assert(db.size() == 2); + assert(db.block_size() == 1); + assert(it->size == 2); + assert(it->type == mtv::element_type_string); + assert(it->__private_data.block_index == 0); + assert(it == db.begin()); + ++it; + assert(it == db.end()); + + assert(db.get<string>(0) == "push me"); + assert(db.get<string>(1) == "again"); + + // Push back another non-empty element of a different type. + it = db.push_back(23.4); + assert(db.size() == 3); + assert(db.block_size() == 2); + assert(it->size == 1); + assert(it->type == mtv::element_type_numeric); +} + } int main (int argc, char **argv) @@ -4916,6 +5014,7 @@ int main (int argc, char **argv) mtv_test_value_type(); mtv_test_block_identifier(); mtv_test_transfer(); + mtv_test_push_back(); cout << "Test finished successfully!" << endl; return EXIT_SUCCESS; -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-openoffice/mdds.git

