[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[mdds] 46/62: Imported Upstream version 0.11.0



This is an automated email from the git hooks/post-receive script.

rene pushed a commit to branch master
in repository mdds.

commit 409b8520dd73438cf23bfdcf09d0c9398abb5a4e
Author: Rene Engelhard <rene@debian.org>
Date:   Thu Apr 21 14:50:53 2016 +0200

    Imported Upstream version 0.11.0
---
 Makefile.in                                        |  21 ++++-
 NEWS                                               |  21 +++++
 configure                                          |  34 +++----
 configure.ac                                       |   4 +-
 include/mdds/global.hpp                            |   8 +-
 include/mdds/multi_type_matrix.hpp                 |   5 +
 include/mdds/multi_type_vector.hpp                 |   7 +-
 include/mdds/multi_type_vector_custom_func1.hpp    |  12 +++
 include/mdds/multi_type_vector_custom_func2.hpp    |  15 +++
 include/mdds/multi_type_vector_custom_func3.hpp    |  18 ++++
 include/mdds/multi_type_vector_def.inl             |  73 ++++++++++-----
 include/mdds/multi_type_vector_trait.hpp           |  44 +++++++++
 include/mdds/multi_type_vector_types.hpp           |  20 +++-
 include/mdds/sorted_string_map.hpp                 | 101 +++++++++++++++++++++
 .../mdds/{global.hpp => sorted_string_map_def.inl} |  58 +++++++-----
 src/multi_type_vector_test_custom.cpp              |  54 +++++++++++
 src/multi_type_vector_test_default.cpp             |  90 ++++++++++++++++++
 src/sorted_string_map_test.cpp                     |  94 +++++++++++++++++++
 18 files changed, 609 insertions(+), 70 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index 3c824b4..828df63 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -19,7 +19,8 @@ EXECS= \
 	multi_type_matrix_test \
 	rectangle_set_test \
 	multi_type_vector_test_default \
-	multi_type_vector_test_custom
+	multi_type_vector_test_custom \
+	sorted_string_map_test
 
 HEADERS= \
 	@top_srcdir@/$(INCDIR)/mdds/compat/unique_ptr.hpp \
@@ -43,6 +44,8 @@ HEADERS= \
 	@top_srcdir@/$(INCDIR)/mdds/rectangle_set_def.inl \
 	@top_srcdir@/$(INCDIR)/mdds/rectangle_set.hpp \
 	@top_srcdir@/$(INCDIR)/mdds/segment_tree.hpp \
+	@top_srcdir@/$(INCDIR)/mdds/sorted_string_map_def.inl \
+	@top_srcdir@/$(INCDIR)/mdds/sorted_string_map.hpp \
 	@top_srcdir@/$(INCDIR)/mdds/multi_type_vector.hpp \
 	@top_srcdir@/$(INCDIR)/mdds/multi_type_vector_custom_func1.hpp \
 	@top_srcdir@/$(INCDIR)/mdds/multi_type_vector_custom_func2.hpp \
@@ -63,7 +66,8 @@ TESTS = \
 	test.st \
 	test.mtm \
 	test.mtv \
-	test.mtmatrix
+	test.mtmatrix \
+	test.ssmap
 
 TESTS_MEM = \
 	test.pqt.mem \
@@ -72,6 +76,7 @@ TESTS_MEM = \
 	test.st.mem \
 	test.mtm.mem \
 	test.mtmatrix \
+	test.ssmap
 
 # You may add $(TESTS_MEM) if valgrind is available on your platform
 ALL_TESTS = $(TESTS)
@@ -111,6 +116,9 @@ $(OBJDIR)/multi_type_vector_test_perf.o: @top_srcdir@/$(SRCDIR)/multi_type_vecto
 $(OBJDIR)/multi_type_matrix_test.o: @top_srcdir@/$(SRCDIR)/multi_type_matrix_test.cpp $(DEPENDS)
 	$(CXX) $(CPPFLAGS) -c -o $@ @top_srcdir@/$(SRCDIR)/multi_type_matrix_test.cpp
 
+$(OBJDIR)/sorted_string_map_test.o: @top_srcdir@/$(SRCDIR)/sorted_string_map_test.cpp $(DEPENDS)
+	$(CXX) $(CPPFLAGS) -c -o $@ @top_srcdir@/$(SRCDIR)/sorted_string_map_test.cpp
+
 flat_segment_tree_test: pre $(OBJDIR)/flat_segment_tree_test.o
 	$(CXX) $(LDFLAGS) $(OBJDIR)/flat_segment_tree_test.o -o $@
 
@@ -138,6 +146,9 @@ multi_type_vector_test_perf: pre $(OBJDIR)/multi_type_vector_test_perf.o
 multi_type_matrix_test: pre $(OBJDIR)/multi_type_matrix_test.o
 	$(CXX) $(LDFLAGS) $(OBJDIR)/multi_type_matrix_test.o -o $@
 
+sorted_string_map_test: pre $(OBJDIR)/sorted_string_map_test.o
+	$(CXX) $(LDFLAGS) $(OBJDIR)/sorted_string_map_test.o -o $@
+
 multi_type_vector_test: multi_type_vector_test_default multi_type_vector_test_custom multi_type_vector_test_perf
 
 stlperf_test: pre @top_srcdir@/$(SRCDIR)/stlperf_test.cpp
@@ -208,6 +219,12 @@ test.mtmatrix.perf: multi_type_matrix_test
 test.mtmatrix.mem: multi_type_matrix_test
 	valgrind --tool=memcheck --leak-check=full ./multi_type_matrix_test func
 
+test.ssmap: sorted_string_map_test
+	./sorted_string_map_test func
+
+test.ssmap.mem: sorted_string_map_test
+	valgrind --tool=memcheck --leak-check=full ./sorted_string_map_test func
+
 test.stl: stlperf_test
 	./stlperf_test
 
diff --git a/NEWS b/NEWS
index db4b75f..65287d3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,24 @@
+mdds 0.11.0
+
+* sorted_string_map (new)
+
+  * new data structure to support efficient mapping of textural keys
+    to numeric values when the key values are known at compile time.
+
+* multi_type_vector
+
+  * fixed a bug in transfer() where two adjacent blocks of identical
+    type would fail to be merged in some circumstances.
+
+  * added shrink_to_fit() to allow trimming of any excess capacity
+    from all non-empty blocks.
+
+  * fixed a double-free bug in the variant of swap() that allows
+    segmented swapping.
+
+  * improved the exception message when the block position lookup
+    fails to find valid block position, to make it easier to debug.
+
 mdds 0.10.3
 
 * multi_type_vector
diff --git a/configure b/configure
index 6880c85..46d9ba5 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.3.
+# Generated by GNU Autoconf 2.69 for mdds 0.11.0.
 #
 # Report bugs to <kohei.yoshida@gmail.com>.
 #
@@ -579,8 +579,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='mdds'
 PACKAGE_TARNAME='mdds'
-PACKAGE_VERSION='0.10.3'
-PACKAGE_STRING='mdds 0.10.3'
+PACKAGE_VERSION='0.11.0'
+PACKAGE_STRING='mdds 0.11.0'
 PACKAGE_BUGREPORT='kohei.yoshida@gmail.com'
 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.3 to adapt to many kinds of systems.
+\`configure' configures mdds 0.11.0 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.3:";;
+     short | recursive ) echo "Configuration of mdds 0.11.0:";;
    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.3
+mdds configure 0.11.0
 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.3, which was
+It was created by mdds $as_me 0.11.0, 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.3
+VERSION=0.11.0
 
 
 PACKAGE_TARNAME=mdds
@@ -1745,7 +1745,7 @@ elif test $with_hash_container = boost; then
   CPPFLAGS_NODEBUG="$CPPFLAGS_NODEBUG -DMDDS_HASH_CONTAINER_BOOST"
 fi
 
-CPPFLAGS="$CPPFLAGS_NODEBUG -DMDDS_DEBUG_NODE_BASE -DMDDS_UNIT_TEST -std=c++0x"
+CPPFLAGS="$CPPFLAGS $CPPFLAGS_NODEBUG -DMDDS_DEBUG_NODE_BASE -DMDDS_UNIT_TEST -std=c++0x"
 
 if test "$debug_stdcxx" = "yes"; then
   CPPFLAGS="$CPPFLAGS -D_GLIBCXX_DEBUG"
@@ -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.3, which was
+This file was extended by mdds $as_me 0.11.0, 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.3
+mdds config.status 0.11.0
 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.3, which was
+This file was extended by mdds $as_me 0.11.0, 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.3
+mdds config.status 0.11.0
 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.3, which was
+This file was extended by mdds $as_me 0.11.0, 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.3
+mdds config.status 0.11.0
 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.3, which was
+This file was extended by mdds $as_me 0.11.0, 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.3
+mdds config.status 0.11.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 678d2a2..25e597b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(mdds, 0.10.3, kohei.yoshida@gmail.com)
+AC_INIT(mdds, 0.11.0, kohei.yoshida@gmail.com)
 
 VERSION=AC_PACKAGE_VERSION
 AC_SUBST(VERSION)
@@ -49,7 +49,7 @@ elif test $with_hash_container = boost; then
   CPPFLAGS_NODEBUG="$CPPFLAGS_NODEBUG -DMDDS_HASH_CONTAINER_BOOST"
 fi
 
-CPPFLAGS="$CPPFLAGS_NODEBUG -DMDDS_DEBUG_NODE_BASE -DMDDS_UNIT_TEST -std=c++0x"
+CPPFLAGS="$CPPFLAGS $CPPFLAGS_NODEBUG -DMDDS_DEBUG_NODE_BASE -DMDDS_UNIT_TEST -std=c++0x"
 
 if test "$debug_stdcxx" = "yes"; then
   CPPFLAGS="$CPPFLAGS -D_GLIBCXX_DEBUG"
diff --git a/include/mdds/global.hpp b/include/mdds/global.hpp
index 7e70588..b54fba8 100644
--- a/include/mdds/global.hpp
+++ b/include/mdds/global.hpp
@@ -1,6 +1,6 @@
 /*************************************************************************
  *
- * Copyright (c) 2008-2011 Kohei Yoshida
+ * Copyright (c) 2008-2014 Kohei Yoshida
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -25,12 +25,14 @@
  *
  ************************************************************************/
 
-#ifndef __MDDS_GLOBAL_HPP__
-#define __MDDS_GLOBAL_HPP__
+#ifndef MDDS_GLOBAL_HPP
+#define MDDS_GLOBAL_HPP
 
 #include <exception>
 #include <string>
 
+#define MDDS_ASCII(literal) literal, sizeof(literal)-1
+
 namespace mdds {
 
 class general_error : public ::std::exception
diff --git a/include/mdds/multi_type_matrix.hpp b/include/mdds/multi_type_matrix.hpp
index 0574466..d555162 100644
--- a/include/mdds/multi_type_matrix.hpp
+++ b/include/mdds/multi_type_matrix.hpp
@@ -63,6 +63,11 @@ struct std_string_trait
 
 }
 
+/**
+ * Matrix that can store double, bool, empty and string types.  The string
+ * type is specified by the string trait template parameter.  To use
+ * std::string as the string type, use mdds::mtm::std_string_trait.
+ */
 template<typename _StringTrait>
 class multi_type_matrix
 {
diff --git a/include/mdds/multi_type_vector.hpp b/include/mdds/multi_type_vector.hpp
index 57c8734..7baecef 100644
--- a/include/mdds/multi_type_vector.hpp
+++ b/include/mdds/multi_type_vector.hpp
@@ -37,9 +37,9 @@
 #include <vector>
 #include <algorithm>
 #include <cassert>
+#include <sstream>
 
 #if defined(MDDS_UNIT_TEST) || defined (MDDS_MULTI_TYPE_VECTOR_DEBUG)
-#include <sstream>
 #include <iostream>
 using std::cout;
 using std::cerr;
@@ -872,6 +872,11 @@ public:
      */
     void swap(size_type start_pos, size_type end_pos, multi_type_vector& other, size_type other_pos);
 
+    /**
+     * Trim excess capacity from all non-empty blocks.
+     */
+    void shrink_to_fit();
+
     bool operator== (const multi_type_vector& other) const;
     bool operator!= (const multi_type_vector& other) const;
 
diff --git a/include/mdds/multi_type_vector_custom_func1.hpp b/include/mdds/multi_type_vector_custom_func1.hpp
index 7f91886..3717e06 100644
--- a/include/mdds/multi_type_vector_custom_func1.hpp
+++ b/include/mdds/multi_type_vector_custom_func1.hpp
@@ -219,6 +219,18 @@ struct custom_block_func1
                 element_block_func::overwrite_values(block, pos, len);
         }
     }
+
+    static void shrink_to_fit(base_element_block& block)
+    {
+        switch (get_block_type(block))
+        {
+            case _Block::block_type:
+                _Block::shrink_to_fit(block);
+            break;
+            default:
+                element_block_func::shrink_to_fit(block);
+        }
+    }
 };
 
 }}
diff --git a/include/mdds/multi_type_vector_custom_func2.hpp b/include/mdds/multi_type_vector_custom_func2.hpp
index b6e9d3b..bc05bef 100644
--- a/include/mdds/multi_type_vector_custom_func2.hpp
+++ b/include/mdds/multi_type_vector_custom_func2.hpp
@@ -266,6 +266,21 @@ struct custom_block_func2
                 element_block_func::overwrite_values(block, pos, len);
         }
     }
+
+    static void shrink_to_fit(base_element_block& block)
+    {
+        switch (get_block_type(block))
+        {
+            case _Block1::block_type:
+                _Block1::shrink_to_fit(block);
+            break;
+            case _Block2::block_type:
+                _Block2::shrink_to_fit(block);
+            break;
+            default:
+                element_block_func::shrink_to_fit(block);
+        }
+    }
 };
 
 }}
diff --git a/include/mdds/multi_type_vector_custom_func3.hpp b/include/mdds/multi_type_vector_custom_func3.hpp
index b107801..7ee0555 100644
--- a/include/mdds/multi_type_vector_custom_func3.hpp
+++ b/include/mdds/multi_type_vector_custom_func3.hpp
@@ -310,6 +310,24 @@ struct custom_block_func3
                 element_block_func::overwrite_values(block, pos, len);
         }
     }
+
+    static void shrink_to_fit(base_element_block& block)
+    {
+        switch (get_block_type(block))
+        {
+            case _Block1::block_type:
+                _Block1::shrink_to_fit(block);
+            break;
+            case _Block2::block_type:
+                _Block2::shrink_to_fit(block);
+            break;
+            case _Block3::block_type:
+                _Block3::shrink_to_fit(block);
+            break;
+            default:
+                element_block_func::shrink_to_fit(block);
+        }
+    }
 };
 
 }}
diff --git a/include/mdds/multi_type_vector_def.inl b/include/mdds/multi_type_vector_def.inl
index d20a9df..ba2cfeb 100644
--- a/include/mdds/multi_type_vector_def.inl
+++ b/include/mdds/multi_type_vector_def.inl
@@ -31,6 +31,19 @@
 
 namespace mdds {
 
+namespace detail {
+
+inline void throw_block_position_not_found(
+    const char* method_sig, int line, size_t pos, size_t block_size, size_t container_size)
+{
+    std::ostringstream os;
+    os << method_sig << "#" << line << ": block position not found! (logical pos="
+        << pos << ", block size=" << block_size << ", logical size=" << container_size << ")";
+    throw std::out_of_range(os.str());
+}
+
+}
+
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(double, mtv::element_type_numeric, 0.0, mtv::numeric_element_block)
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(std::string, mtv::element_type_string, std::string(), mtv::string_element_block)
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(short, mtv::element_type_short, 0, mtv::short_element_block)
@@ -250,7 +263,7 @@ multi_type_vector<_CellBlockFunc>::set(size_type pos, const _T& value)
     size_type start_row = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::set", __LINE__, pos, block_size(), size());
 
 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
     std::ostringstream os_prev_block;
@@ -471,7 +484,7 @@ multi_type_vector<_CellBlockFunc>::set(size_type pos, const _T& it_begin, const
 
     size_type block_index1 = 0, start_row1 = 0;
     if (!get_block_position(pos, start_row1, block_index1))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::set", __LINE__, pos, block_size(), size());
 
     return set_cells_impl(pos, end_pos, start_row1, block_index1, it_begin, it_end);
 }
@@ -561,7 +574,7 @@ multi_type_vector<_CellBlockFunc>::insert(size_type pos, const _T& it_begin, con
 {
     size_type block_index = 0, start_pos = 0;
     if (!get_block_position(pos, start_pos, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::insert", __LINE__, pos, block_size(), size());
 
 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
     std::ostringstream os_prev_block;
@@ -657,7 +670,7 @@ void multi_type_vector<_CellBlockFunc>::get_block_position(
     }
 
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::get_block_position", __LINE__, pos, block_size(), size());
 }
 
 template<typename _CellBlockFunc>
@@ -1184,7 +1197,7 @@ void multi_type_vector<_CellBlockFunc>::get(size_type pos, _T& value) const
     size_type start_row = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::get", __LINE__, pos, block_size(), size());
 
     const block* blk = m_blocks[block_index];
     assert(blk);
@@ -1218,7 +1231,7 @@ _T multi_type_vector<_CellBlockFunc>::release(size_type pos)
     size_type start_pos = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_pos, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::release", __LINE__, pos, block_size(), size());
 
     _T value;
     release_impl(pos, start_pos, block_index, value);
@@ -1233,7 +1246,7 @@ multi_type_vector<_CellBlockFunc>::release(size_type pos, _T& value)
     size_type start_pos = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_pos, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::release", __LINE__, pos, block_size(), size());
 
     return release_impl(pos, start_pos, block_index, value);
 }
@@ -1273,7 +1286,7 @@ multi_type_vector<_CellBlockFunc>::release_range(size_type start_pos, size_type
     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!");
+        detail::throw_block_position_not_found("multi_type_vector::release_range", __LINE__, start_pos, block_size(), size());
 
     return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, false);
 }
@@ -1296,7 +1309,7 @@ multi_type_vector<_CellBlockFunc>::position(size_type pos)
     size_type start_pos = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_pos, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::position", __LINE__, pos, block_size(), size());
 
     iterator it = get_iterator(block_index, start_pos);
     return position_type(it, pos - start_pos);
@@ -1321,7 +1334,7 @@ multi_type_vector<_CellBlockFunc>::position(size_type pos) const
     size_type start_row = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::position", __LINE__, pos, block_size(), size());
 
     typename blocks_type::const_iterator block_pos = m_blocks.begin();
     std::advance(block_pos, block_index);
@@ -1352,7 +1365,7 @@ multi_type_vector<_CellBlockFunc>::transfer(
     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!");
+        detail::throw_block_position_not_found("multi_type_vector::transfer", __LINE__, start_pos, block_size(), size());
 
 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
     std::ostringstream os_prev_block;
@@ -1418,7 +1431,7 @@ mtv::element_t multi_type_vector<_CellBlockFunc>::get_type(size_type pos) const
     size_type start_row = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::get_type", __LINE__, pos, block_size(), size());
 
     const block* blk = m_blocks[block_index];
     if (!blk->mp_data)
@@ -1433,7 +1446,7 @@ bool multi_type_vector<_CellBlockFunc>::is_empty(size_type pos) const
     size_type start_row = 0;
     size_type block_index = 0;
     if (!get_block_position(pos, start_row, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::is_empty", __LINE__, pos, block_size(), size());
 
     return m_blocks[block_index]->mp_data == NULL;
 }
@@ -1445,7 +1458,7 @@ multi_type_vector<_CellBlockFunc>::set_empty(size_type start_pos, size_type end_
     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!");
+        detail::throw_block_position_not_found("multi_type_vector::set_empty", __LINE__, start_pos, block_size(), size());
 
     return set_empty_impl(start_pos, end_pos, start_pos_in_block1, block_index1, true);
 }
@@ -1477,7 +1490,7 @@ multi_type_vector<_CellBlockFunc>::transfer_impl(
     size_type start_pos_in_block2 = start_pos_in_block1;
     size_type block_index2 = block_index1;
     if (!get_block_position(end_pos, start_pos_in_block2, block_index2))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::transfer_impl", __LINE__, end_pos, block_size(), size());
 
     size_type len = end_pos - start_pos + 1;
     size_type last_dest_pos = dest_pos + len - 1;
@@ -1545,6 +1558,7 @@ multi_type_vector<_CellBlockFunc>::transfer_single_block(
         dest.m_blocks.insert(dest.m_blocks.begin()+dest_block_index+1, new block(len));
         blk_dest->m_size -= len;
         blk_dest = dest.m_blocks[dest_block_index+1];
+        ++dest_block_index; // Must point to the new copied block.
     }
     else
     {
@@ -1558,6 +1572,8 @@ multi_type_vector<_CellBlockFunc>::transfer_single_block(
         blk_dest->m_size = dest_pos_in_block;
 
         blk_dest = dest.m_blocks[dest_block_index+1];
+
+        ++dest_block_index; // Must point to the new copied block.
     }
 
     assert(blk_dest->m_size == len);
@@ -1844,7 +1860,7 @@ multi_type_vector<_CellBlockFunc>::set_empty_impl(
     size_type start_pos_in_block2 = start_pos_in_block1;
     size_type block_index2 = block_index1;
     if (!get_block_position(end_pos, start_pos_in_block2, block_index2))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::set_empty_impl", __LINE__, end_pos, block_size(), size());
 
 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
     std::ostringstream os_prev_block;
@@ -1974,6 +1990,8 @@ void multi_type_vector<_CellBlockFunc>::swap_single_blocks(
             mdds::unique_ptr<element_block_type, element_block_deleter> src_data(blk_src->mp_data);
             blk_src->mp_data = other.exchange_elements(
                 *src_data, src_offset, other_block_index, dst_offset, len);
+            // Release elements in the source block to prevent double-deletion.
+            element_block_func::resize_block(*src_data, 0);
             merge_with_adjacent_blocks(block_index);
             return;
         }
@@ -2270,12 +2288,12 @@ void multi_type_vector<_CellBlockFunc>::erase_impl(size_type start_row, size_typ
     size_type start_row_in_block1 = 0;
     size_type block_pos1 = 0;
     if (!get_block_position(start_row, start_row_in_block1, block_pos1))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::erase_impl", __LINE__, start_row, block_size(), size());
 
     size_type start_row_in_block2 = start_row_in_block1;
     size_type block_pos2 = block_pos1;
     if (!get_block_position(end_row, start_row_in_block2, block_pos2))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::erase_impl", __LINE__, end_row, block_size(), size());
 
     if (block_pos1 == block_pos2)
     {
@@ -2418,7 +2436,7 @@ multi_type_vector<_CellBlockFunc>::insert_empty(size_type pos, size_type length)
 
     size_type start_pos = 0, block_index = 0;
     if (!get_block_position(pos, start_pos, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::insert_empty", __LINE__, pos, block_size(), size());
 
 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
     std::ostringstream os_prev_block;
@@ -2561,7 +2579,7 @@ multi_type_vector<_CellBlockFunc>::set_cells_impl(
     size_type start_row2 = start_row1;
     size_type block_index2 = block_index1;
     if (!get_block_position(end_row, start_row2, block_index2))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::set_cells_impl", __LINE__, end_row, block_size(), size());
 
     if (block_index1 == block_index2)
     {
@@ -3587,7 +3605,7 @@ void multi_type_vector<_CellBlockFunc>::resize(size_type new_size)
     size_type new_end_row = new_size - 1;
     size_type start_row_in_block = 0, block_index = 0;
     if (!get_block_position(new_end_row, start_row_in_block, block_index))
-        throw std::out_of_range("Block position not found!");
+        detail::throw_block_position_not_found("multi_type_vector::resize", __LINE__, new_end_row, block_size(), size());
 
     block* blk = m_blocks[block_index];
     size_type end_row_in_block = start_row_in_block + blk->m_size - 1;
@@ -3673,6 +3691,19 @@ void multi_type_vector<_CellBlockFunc>::swap(size_type start_pos, size_type end_
 }
 
 template<typename _CellBlockFunc>
+void multi_type_vector<_CellBlockFunc>::shrink_to_fit()
+{
+    typename blocks_type::iterator it = m_blocks.begin(), it_end = m_blocks.end();
+    for (; it != it_end; ++it)
+    {
+        block* blk = *it;
+        assert(blk);
+        if (blk->mp_data)
+            element_block_func::shrink_to_fit(*blk->mp_data);
+    }
+}
+
+template<typename _CellBlockFunc>
 bool multi_type_vector<_CellBlockFunc>::operator== (const multi_type_vector& other) const
 {
     if (this == &other)
diff --git a/include/mdds/multi_type_vector_trait.hpp b/include/mdds/multi_type_vector_trait.hpp
index c99ec17..03ed36b 100644
--- a/include/mdds/multi_type_vector_trait.hpp
+++ b/include/mdds/multi_type_vector_trait.hpp
@@ -74,6 +74,8 @@ struct element_block_func_base
      * store primitive values), this method can be left empty.
      */
     inline static void overwrite_values(base_element_block& block, size_t pos, size_t len);
+
+    inline static void shrink_to_fit(base_element_block& block);
 };
 
 base_element_block* element_block_func_base::create_new_block(element_t type, size_t init_size)
@@ -608,6 +610,48 @@ void element_block_func_base::overwrite_values(base_element_block&, size_t, size
     // Do nothing for the standard types.
 }
 
+void element_block_func_base::shrink_to_fit(base_element_block& block)
+{
+    switch (get_block_type(block))
+    {
+        case element_type_numeric:
+            numeric_element_block::shrink_to_fit(block);
+        break;
+        case element_type_string:
+            string_element_block::shrink_to_fit(block);
+        break;
+        case element_type_short:
+            short_element_block::shrink_to_fit(block);
+        break;
+        case element_type_ushort:
+            ushort_element_block::shrink_to_fit(block);
+        break;
+        case element_type_int:
+            int_element_block::shrink_to_fit(block);
+        break;
+        case element_type_uint:
+            uint_element_block::shrink_to_fit(block);
+        break;
+        case element_type_long:
+            long_element_block::shrink_to_fit(block);
+        break;
+        case element_type_ulong:
+            ulong_element_block::shrink_to_fit(block);
+        break;
+        case element_type_boolean:
+            boolean_element_block::shrink_to_fit(block);
+        break;
+        case element_type_char:
+            char_element_block::shrink_to_fit(block);
+        break;
+        case element_type_uchar:
+            uchar_element_block::shrink_to_fit(block);
+        break;
+        default:
+            throw general_error("shrink_to_fit: failed to print a block of unknown type.");
+    }
+}
+
 /**
  * Default cell block function definitions.  Implementation can use this if
  * it only uses the default block types implemented by the library.
diff --git a/include/mdds/multi_type_vector_types.hpp b/include/mdds/multi_type_vector_types.hpp
index 3fb31cc..bb8fdbe 100644
--- a/include/mdds/multi_type_vector_types.hpp
+++ b/include/mdds/multi_type_vector_types.hpp
@@ -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
@@ -378,6 +378,24 @@ public:
         blk.insert(blk.begin()+pos, it_begin, it_end);
     }
 
+    static size_t capacity(const base_element_block& block)
+    {
+#ifdef MDDS_MULTI_TYPE_VECTOR_USE_DEQUE
+        return 0;
+#else
+        const store_type& blk = get(block).m_array;
+        return blk.capacity();
+#endif
+    }
+
+    static void shrink_to_fit(base_element_block& block)
+    {
+#ifndef MDDS_MULTI_TYPE_VECTOR_USE_DEQUE
+        store_type& blk = get(block).m_array;
+        store_type(blk).swap(blk);
+#endif
+    }
+
 private:
     static std::pair<const_iterator,const_iterator>
     get_iterator_pair(const store_type& array, size_t begin_pos, size_t len)
diff --git a/include/mdds/sorted_string_map.hpp b/include/mdds/sorted_string_map.hpp
new file mode 100644
index 0000000..e98b930
--- /dev/null
+++ b/include/mdds/sorted_string_map.hpp
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2014 Kohei Yoshida
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************/
+
+#ifndef MDDS_SORTED_STRING_MAP_HPP
+#define MDDS_SORTED_STRING_MAP_HPP
+
+#include <cstdlib>
+
+namespace mdds {
+
+/**
+ * sorted_string_map provides an efficient way to map string keys to
+ * arbitrary values, provided that the keys are known at compile time and
+ * are sorted in ascending order.
+ */
+template<typename _ValueT>
+class sorted_string_map
+{
+public:
+    typedef _ValueT value_type;
+    typedef size_t size_type;
+
+    /**
+     * Single key-value entry.  Caller must provide at compile time a static
+     * array of these entries.
+     */
+    struct entry
+    {
+        const char* key;
+        size_type keylen;
+        value_type value;
+    };
+
+    /**
+     * Constructor.
+     *
+     * @param entries pointer to the array of key-value entries.
+     * @param entry_size size of the key-value entry array.
+     * @param null_value null value to return when the find method fails to
+     *                   find a matching entry.
+     */
+    sorted_string_map(const entry* entries, size_type entry_size, value_type null_value);
+
+    /**
+     * Find a value associated with a specified string key.
+     *
+     * @param input pointer to a C-style string whose value represents the key
+     *              to match.
+     * @param len length of the matching string value.
+     *
+     * @return value associated with the key, or the null value in case the
+     *         key is not found.
+     */
+    value_type find(const char* input, size_type len) const;
+
+    /**
+     * Return the number of entries in the map.  Since the number of entries
+     * is statically defined at compile time, this method always returns the
+     * same value.
+     *
+     * @return the number of entries in the map.
+     */
+    size_type size() const;
+
+private:
+
+    const entry* m_entries;
+    value_type m_null_value;
+    size_type m_entry_size;
+    const entry* m_entry_end;
+};
+
+}
+
+#include "sorted_string_map_def.inl"
+
+#endif
diff --git a/include/mdds/global.hpp b/include/mdds/sorted_string_map_def.inl
similarity index 54%
copy from include/mdds/global.hpp
copy to include/mdds/sorted_string_map_def.inl
index 7e70588..20d9dc9 100644
--- a/include/mdds/global.hpp
+++ b/include/mdds/sorted_string_map_def.inl
@@ -1,6 +1,6 @@
 /*************************************************************************
  *
- * Copyright (c) 2008-2011 Kohei Yoshida
+ * Copyright (c) 2014 Kohei Yoshida
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -25,34 +25,46 @@
  *
  ************************************************************************/
 
-#ifndef __MDDS_GLOBAL_HPP__
-#define __MDDS_GLOBAL_HPP__
-
-#include <exception>
-#include <string>
-
 namespace mdds {
 
-class general_error : public ::std::exception
-{
-public:
-    general_error(const ::std::string& msg) : m_msg(msg) {}
-    virtual ~general_error() throw() {}
+template<typename _ValueT>
+sorted_string_map<_ValueT>::sorted_string_map(const entry* entries, size_type entry_size, value_type null_value) :
+    m_entries(entries),
+    m_null_value(null_value),
+    m_entry_size(entry_size),
+    m_entry_end(m_entries+m_entry_size) {}
 
-    virtual const char* what() const throw()
+template<typename _ValueT>
+typename sorted_string_map<_ValueT>::value_type
+sorted_string_map<_ValueT>::find(const char* input, size_type len) const
+{
+    const entry* p = m_entries;
+    size_type pos = 0;
+    for (; p != m_entry_end; ++p)
     {
-        return m_msg.c_str();
+        const char* key = p->key;
+        size_type keylen = p->keylen;
+        for (; pos < len && pos < keylen; ++pos)
+        {
+            if (input[pos] != key[pos])
+                // Move to the next entry.
+                break;
+        }
+
+        if (pos == len && len == keylen)
+        {
+            // Match found!
+            return p->value;
+        }
     }
-private:
-    ::std::string m_msg;
-};
+    return m_null_value;
+}
 
-class invalid_arg_error : public general_error
+template<typename _ValueT>
+typename sorted_string_map<_ValueT>::size_type
+sorted_string_map<_ValueT>::size() const
 {
-public:
-    invalid_arg_error(const ::std::string& msg) : general_error(msg) {}
-};
-
+    return m_entry_size;
 }
 
-#endif
+}
diff --git a/src/multi_type_vector_test_custom.cpp b/src/multi_type_vector_test_custom.cpp
index 42d9156..96b61ee 100644
--- a/src/multi_type_vector_test_custom.cpp
+++ b/src/multi_type_vector_test_custom.cpp
@@ -1395,6 +1395,60 @@ void mtv_test_swap()
     db2.set(1, string("B"));
 
     db1.swap(2, 3, db2, 0);
+
+    // swap blocks of equal size, one managed, and one default.
+
+    db1.clear();
+    db1.resize(10);
+    db2.clear();
+    db2.resize(10);
+
+    db1.set(3, 2.1);
+    db1.set(4, 2.2);
+    db1.set(5, 2.3);
+
+    db2.set(3, new muser_cell(3.1));
+    db2.set(4, new muser_cell(3.2));
+    db2.set(5, new muser_cell(3.3));
+
+    db2.swap(3, 5, db1, 3);
+
+    assert(db1.size() == 10);
+    assert(db1.block_size() == 3);
+    assert(db2.size() == 10);
+    assert(db2.block_size() == 3);
+
+    assert(db1.get<muser_cell*>(3)->value == 3.1);
+    assert(db1.get<muser_cell*>(4)->value == 3.2);
+    assert(db1.get<muser_cell*>(5)->value == 3.3);
+    assert(db2.get<double>(3) == 2.1);
+    assert(db2.get<double>(4) == 2.2);
+    assert(db2.get<double>(5) == 2.3);
+
+    db2.swap(3, 5, db1, 3);
+
+    assert(db1.get<double>(3) == 2.1);
+    assert(db1.get<double>(4) == 2.2);
+    assert(db1.get<double>(5) == 2.3);
+    assert(db2.get<muser_cell*>(3)->value == 3.1);
+    assert(db2.get<muser_cell*>(4)->value == 3.2);
+    assert(db2.get<muser_cell*>(5)->value == 3.3);
+
+    // Same as above, except that the source segment splits the block into 2.
+
+    db1.clear();
+    db1.resize(10);
+    db2.clear();
+    db2.resize(10);
+
+    db1.set(3, 2.1);
+    db1.set(4, 2.2);
+
+    db2.set(3, new muser_cell(3.1));
+    db2.set(4, new muser_cell(3.2));
+    db2.set(5, new muser_cell(3.3));
+
+    db2.swap(3, 4, db1, 3);
 }
 
 void mtv_test_custom_block_func3()
diff --git a/src/multi_type_vector_test_default.cpp b/src/multi_type_vector_test_default.cpp
index 8345b0f..28ff59e 100644
--- a/src/multi_type_vector_test_default.cpp
+++ b/src/multi_type_vector_test_default.cpp
@@ -4878,6 +4878,76 @@ void mtv_test_transfer()
 
     db1.set(2, 12.8);
     it = db1.transfer(1, 2, db2, 1);
+
+    // Reset and start over.
+    db1.clear();
+    db1.resize(20);
+    db2.clear();
+    db2.resize(20);
+
+    db1.set(9, 1.1);
+
+    db2.set(10, 1.2);
+    db2.set(11, 1.3);
+
+    it = db1.transfer(9, 9, db2, 9);
+
+    // The source should be entirely empty after the transfer.
+    assert(db1.block_size() == 1);
+    assert(it == db1.begin());
+    assert(it->__private_data.block_index == 0);
+    assert(it->size == 20);
+    assert(it->type == mtv::element_type_empty);
+    ++it;
+    assert(it == db1.end());
+
+    // Check the destination as well.
+    assert(db2.block_size() == 3);
+    it = db2.begin();
+    assert(it->size == 9);
+    assert(it->__private_data.block_index == 0);
+    assert(it->type == mtv::element_type_empty);
+    ++it;
+    assert(it->size == 3);
+    assert(it->__private_data.block_index == 1);
+    assert(it->type == mtv::element_type_numeric);
+    ++it;
+    assert(it->size == 8);
+    assert(it->__private_data.block_index == 2);
+    assert(it->type == mtv::element_type_empty);
+    ++it;
+    assert(it == db2.end());
+    assert(db2.get<double>(9) == 1.1);
+    assert(db2.get<double>(10) == 1.2);
+    assert(db2.get<double>(11) == 1.3);
+
+    // Reset and start over.
+    db1.clear();
+    db1.resize(20);
+    db2.clear();
+    db2.resize(20);
+
+    db1.set(8, 1.0);
+    db1.set(9, 1.1);
+
+    db2.set(10, 1.2);
+    db2.set(11, 1.3);
+
+    it = db1.transfer(9, 9, db2, 9);
+    assert(it->__private_data.block_index == 2);
+    assert(db1.block_size() == 3);
+    assert(db1.get<double>(8) == 1.0);
+    it = db1.begin();
+    assert(it->size == 8);
+    assert(it->type == mtv::element_type_empty);
+    ++it;
+    assert(it->size == 1);
+    assert(it->type == mtv::element_type_numeric);
+    ++it;
+    assert(it->size == 11);
+    assert(it->type == mtv::element_type_empty);
+    ++it;
+    assert(it == db1.end());
 }
 
 void mtv_test_push_back()
@@ -4978,6 +5048,25 @@ void mtv_test_push_back()
     assert(it->type == mtv::element_type_numeric);
 }
 
+void mtv_test_capacity()
+{
+    stack_printer __stack_printer__("::mtv_test_capacity");
+    mtv_type db(10, 1.1);
+    assert(db.block_size() == 1);
+    mtv_type::const_iterator it = db.begin();
+    assert(it->type == mtv::element_type_numeric);
+    size_t cap = mtv::numeric_element_block::capacity(*it->data);
+    assert(cap == 10);
+
+    db.set_empty(3, 3);
+    assert(db.block_size() == 3);
+    db.shrink_to_fit();
+    it = db.begin();
+    assert(it->type == mtv::element_type_numeric);
+    cap = mtv::numeric_element_block::capacity(*it->data);
+    assert(cap == 3);
+}
+
 }
 
 int main (int argc, char **argv)
@@ -5015,6 +5104,7 @@ int main (int argc, char **argv)
     mtv_test_block_identifier();
     mtv_test_transfer();
     mtv_test_push_back();
+    mtv_test_capacity();
 
     cout << "Test finished successfully!" << endl;
     return EXIT_SUCCESS;
diff --git a/src/sorted_string_map_test.cpp b/src/sorted_string_map_test.cpp
new file mode 100644
index 0000000..7d2070d
--- /dev/null
+++ b/src/sorted_string_map_test.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2014 Kohei Yoshida
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************/
+
+#define MDDS_MULTI_TYPE_VECTOR_DEBUG 1
+#include "mdds/sorted_string_map.hpp"
+#include "mdds/global.hpp"
+
+#include "test_global.hpp"
+
+#include <cassert>
+
+using namespace std;
+
+enum name_type {
+    name_none = 0,
+    name_andy,
+    name_bruce,
+    name_charlie,
+    name_david
+};
+
+void ssmap_test_basic()
+{
+    stack_printer __stack_printer__("::ssmap_test_basic");
+
+    typedef mdds::sorted_string_map<name_type> map_type;
+
+    map_type::entry entries[] =
+    {
+        { MDDS_ASCII("andy"), name_andy },
+        { MDDS_ASCII("andy1"), name_andy },
+        { MDDS_ASCII("andy13"), name_andy },
+        { MDDS_ASCII("bruce"), name_bruce },
+        { MDDS_ASCII("charlie"), name_charlie },
+        { MDDS_ASCII("david"), name_david },
+    };
+
+    size_t entry_count = sizeof(entries)/sizeof(entries[0]);
+    map_type names(entries, entry_count, name_none);
+    for (size_t i = 0; i < entry_count; ++i)
+    {
+        cout << "* key = " << entries[i].key << endl;
+        bool res = names.find(entries[i].key, strlen(entries[i].key)) == entries[i].value;
+        assert(res);
+    }
+
+    // Try invalid keys.
+    assert(names.find("foo", 3) == name_none);
+    assert(names.find("andy133", 7) == name_none);
+}
+
+int main (int argc, char **argv)
+{
+    cmd_options opt;
+    if (!parse_cmd_options(argc, argv, opt))
+        return EXIT_FAILURE;
+
+    if (opt.test_func)
+    {
+        ssmap_test_basic();
+    }
+
+    if (opt.test_perf)
+    {
+    }
+
+    fprintf(stdout, "Test finished successfully!\n");
+    return 0;
+}
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-openoffice/mdds.git


Reply to: