Version in base suite: 2.1.1-2 Base version: mdds_2.1.1-2 Target version: mdds_3.1.0-3~bpo13+1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/m/mdds/mdds_2.1.1-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/m/mdds/mdds_3.1.0-3~bpo13+1.dsc /srv/release.debian.org/tmp/HY8FhnzTdU/mdds-3.1.0/doc/figures.odg |binary mdds-3.1.0/CHANGELOG | 82 mdds-3.1.0/Makefile.am | 104 mdds-3.1.0/Makefile.in | 105 mdds-3.1.0/configure | 101 mdds-3.1.0/configure.ac | 10 mdds-3.1.0/debian/changelog | 28 mdds-3.1.0/debian/tests/patches/system-includes.diff | 2 mdds-3.1.0/debian/watch | 4 mdds-3.1.0/doc/api.rst | 41 mdds-3.1.0/doc/conf.py | 10 mdds-3.1.0/doc/environment.yml | 8 mdds-3.1.0/doc/flat_segment_tree.rst | 268 mdds-3.1.0/doc/flat_segment_tree/api.rst | 6 mdds-3.1.0/doc/flat_segment_tree/index.rst | 30 mdds-3.1.0/doc/flat_segment_tree/iterate-segments.rst | 96 mdds-3.1.0/doc/flat_segment_tree/quickstart.rst | 138 mdds-3.1.0/doc/index.rst | 10 mdds-3.1.0/doc/requirements.txt | 2 mdds-3.1.0/doc/rtree.rst | 727 mdds-3.1.0/doc/rtree/api.rst | 18 mdds-3.1.0/doc/rtree/bulkload.rst | 90 mdds-3.1.0/doc/rtree/index.rst | 35 mdds-3.1.0/doc/rtree/quickstart.rst | 212 mdds-3.1.0/doc/rtree/remove-value.rst | 49 mdds-3.1.0/doc/rtree/visualize.rst | 88 mdds-3.1.0/doc/segment_tree.rst | 11 mdds-3.1.0/doc/segment_tree/api.rst | 7 mdds-3.1.0/doc/segment_tree/index.rst | 21 mdds-3.1.0/doc/segment_tree/perf.rst | 34 mdds-3.1.0/doc/segment_tree/quickstart.rst | 122 mdds-3.1.0/doc/segment_tree/remove-segments.rst | 98 mdds-3.1.0/doc/sorted_string_map.rst | 11 mdds-3.1.0/doc/sorted_string_map/api.rst | 11 mdds-3.1.0/doc/sorted_string_map/index.rst | 20 mdds-3.1.0/doc/sorted_string_map/quickstart.rst | 133 mdds-3.1.0/doc/trie_map.rst | 767 mdds-3.1.0/doc/trie_map/api.rst | 60 mdds-3.1.0/doc/trie_map/direct-packed-trie-map.rst | 50 mdds-3.1.0/doc/trie_map/index.rst | 28 mdds-3.1.0/doc/trie_map/pack-trie-map.rst | 86 mdds-3.1.0/doc/trie_map/populate-trie-map.rst | 83 mdds-3.1.0/doc/trie_map/save-load-packed-trie-map-custom-value.rst | 182 mdds-3.1.0/doc/trie_map/save-load-packed-trie-map.rst | 169 mdds-3.1.0/example/Makefile.am | 3 mdds-3.1.0/example/Makefile.in | 39 mdds-3.1.0/example/multi_type_vector/Makefile.in | 1 mdds-3.1.0/example/packed_trie_map.cpp | 35 mdds-3.1.0/example/packed_trie_state_custom.cpp | 58 mdds-3.1.0/example/packed_trie_state_int.cpp | 64 mdds-3.1.0/example/rtree_erase.cpp | 3 mdds-3.1.0/example/rtree_medium.cpp | 8 mdds-3.1.0/example/rtree_medium_bulkload.cpp | 8 mdds-3.1.0/example/rtree_simple.cpp | 32 mdds-3.1.0/example/segment_tree.cpp | 104 mdds-3.1.0/example/sorted_string_map.cpp | 185 mdds-3.1.0/example/trie_map.cpp | 46 mdds-3.1.0/include/Makefile.in | 1 mdds-3.1.0/include/mdds/Makefile.am | 1 mdds-3.1.0/include/mdds/Makefile.in | 2 mdds-3.1.0/include/mdds/cref_wrapper.hpp | 78 mdds-3.1.0/include/mdds/flat_segment_tree.hpp | 188 mdds-3.1.0/include/mdds/flat_segment_tree_def.inl | 137 mdds-3.1.0/include/mdds/flat_segment_tree_itr.hpp | 49 mdds-3.1.0/include/mdds/multi_type_vector/Makefile.am | 1 mdds-3.1.0/include/mdds/multi_type_vector/Makefile.in | 2 mdds-3.1.0/include/mdds/multi_type_vector/aos/Makefile.in | 1 mdds-3.1.0/include/mdds/multi_type_vector/aos/main.hpp | 41 mdds-3.1.0/include/mdds/multi_type_vector/aos/main_def.inl | 109 mdds-3.1.0/include/mdds/multi_type_vector/delayed_delete_vector.hpp | 253 mdds-3.1.0/include/mdds/multi_type_vector/macro.hpp | 11 mdds-3.1.0/include/mdds/multi_type_vector/soa/Makefile.in | 1 mdds-3.1.0/include/mdds/multi_type_vector/soa/main.hpp | 41 mdds-3.1.0/include/mdds/multi_type_vector/soa/main_def.inl | 106 mdds-3.1.0/include/mdds/multi_type_vector/types.hpp | 223 mdds-3.1.0/include/mdds/node.hpp | 277 mdds-3.1.0/include/mdds/ref_pair.hpp | 5 mdds-3.1.0/include/mdds/rtree.hpp | 4 mdds-3.1.0/include/mdds/rtree_def.inl | 12 mdds-3.1.0/include/mdds/segment_tree.hpp | 738 mdds-3.1.0/include/mdds/segment_tree_def.inl | 929 mdds-3.1.0/include/mdds/sorted_string_map.hpp | 128 mdds-3.1.0/include/mdds/sorted_string_map_def.inl | 155 mdds-3.1.0/include/mdds/trie_map.hpp | 427 mdds-3.1.0/include/mdds/trie_map_def.inl | 1537 - mdds-3.1.0/include/mdds/trie_map_itr.hpp | 239 mdds-3.1.0/m4/ax_cxx_compile_stdcxx.m4 | 151 mdds-3.1.0/misc/sorted_string_data.dat |10000 ++++++++++ mdds-3.1.0/quickcheck/flat_segment_tree.cpp | 512 mdds-3.1.0/test/Makefile.in | 1 mdds-3.1.0/test/flat_segment_tree/Makefile.in | 1 mdds-3.1.0/test/flat_segment_tree/test_main.cpp | 884 mdds-3.1.0/test/gdb/Makefile.in | 1 mdds-3.1.0/test/gdb/src/Makefile.in | 1 mdds-3.1.0/test/gdb/src/sorted_string_map.cpp | 14 mdds-3.1.0/test/gdb/src/trie_map.cpp | 16 mdds-3.1.0/test/include/Makefile.in | 1 mdds-3.1.0/test/include/test_global.hpp | 19 mdds-3.1.0/test/multi_type_matrix/Makefile.in | 1 mdds-3.1.0/test/multi_type_matrix/test_main.cpp | 682 mdds-3.1.0/test/multi_type_matrix/test_walk.cpp | 145 mdds-3.1.0/test/multi_type_vector/Makefile.am | 11 mdds-3.1.0/test/multi_type_vector/Makefile.in | 13 mdds-3.1.0/test/multi_type_vector/collection/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/collection/aos/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/collection/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/collection/tc/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/collection/tc/all.inl | 215 mdds-3.1.0/test/multi_type_vector/custom-trait/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom-trait/aos/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom-trait/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom-trait/soa/test_loop_unrolling_simd.cpp | 28 mdds-3.1.0/test/multi_type_vector/custom-trait/tc/loop_unrolling.inl | 10 mdds-3.1.0/test/multi_type_vector/custom/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom/aos/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom/tc/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/custom/tc/basic.inl | 94 mdds-3.1.0/test/multi_type_vector/custom/tc/managed_block.inl | 260 mdds-3.1.0/test/multi_type_vector/custom/tc/misc.inl | 128 mdds-3.1.0/test/multi_type_vector/custom/tc/swap.inl | 100 mdds-3.1.0/test/multi_type_vector/custom/tc/transfer.inl | 457 mdds-3.1.0/test/multi_type_vector/debug-util/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/debug-util/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/debug-util/soa/test_trace.cpp | 6 mdds-3.1.0/test/multi_type_vector/default/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/default/aos/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/default/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/default/tc/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/default/tc/basic.inl | 326 mdds-3.1.0/test/multi_type_vector/default/tc/construction.inl | 52 mdds-3.1.0/test/multi_type_vector/default/tc/empty_cells.inl | 302 mdds-3.1.0/test/multi_type_vector/default/tc/erase.inl | 162 mdds-3.1.0/test/multi_type_vector/default/tc/hints.inl | 128 mdds-3.1.0/test/multi_type_vector/default/tc/insert.inl | 288 mdds-3.1.0/test/multi_type_vector/default/tc/iterators.inl | 249 mdds-3.1.0/test/multi_type_vector/default/tc/iterators_insert.inl | 159 mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set.inl | 583 mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set_empty.inl | 155 mdds-3.1.0/test/multi_type_vector/default/tc/misc.inl | 317 mdds-3.1.0/test/multi_type_vector/default/tc/position.inl | 131 mdds-3.1.0/test/multi_type_vector/default/tc/set.inl | 357 mdds-3.1.0/test/multi_type_vector/default/tc/swap_range.inl | 555 mdds-3.1.0/test/multi_type_vector/default/tc/transfer.inl | 383 mdds-3.1.0/test/multi_type_vector/element-blocks/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/element-blocks/no_standard_blocks_funcs.inl | 14 mdds-3.1.0/test/multi_type_vector/element-blocks/test_functions.cpp | 36 mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_aos.cpp | 1 mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_soa.cpp | 1 mdds-3.1.0/test/multi_type_vector/element-blocks/test_store_types.cpp | 12 mdds-3.1.0/test/multi_type_vector/event/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/event/aos/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/event/soa/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/event/tc/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/event/tc/block_counter.inl | 702 mdds-3.1.0/test/multi_type_vector/event/tc/block_init.inl | 16 mdds-3.1.0/test/multi_type_vector/event/tc/swap.inl | 18 mdds-3.1.0/test/multi_type_vector/perf/Makefile.in | 1 mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.am | 3 mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.in | 638 mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.am | 22 mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.in | 1048 + mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.cpp | 47 mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.hpp | 42 mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_push_back.cpp | 34 mdds-3.1.0/test/multi_type_vector/push-emplace-back/common_types.hpp | 152 mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.am | 22 mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.in | 1048 + mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.cpp | 47 mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.hpp | 42 mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_push_back.cpp | 34 mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.am | 2 mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.in | 461 mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/push_back.inl | 108 mdds-3.1.0/test/point_quad_tree/Makefile.in | 1 mdds-3.1.0/test/point_quad_tree/test_main.cpp | 271 mdds-3.1.0/test/ref_pair_test.cpp | 32 mdds-3.1.0/test/rtree/Makefile.in | 1 mdds-3.1.0/test/rtree/test_basic.cpp | 54 mdds-3.1.0/test/rtree/test_bulkload_main.cpp | 41 mdds-3.1.0/test/rtree/test_copy.cpp | 38 mdds-3.1.0/test/rtree/test_directory_node_split.cpp | 9 mdds-3.1.0/test/rtree/test_erase_directories.cpp | 15 mdds-3.1.0/test/rtree/test_exact_search_by_extent.cpp | 18 mdds-3.1.0/test/rtree/test_exact_search_by_point.cpp | 34 mdds-3.1.0/test/rtree/test_forced_reinsertion.cpp | 10 mdds-3.1.0/test/rtree/test_geometry.cpp | 10 mdds-3.1.0/test/rtree/test_intersection.cpp | 15 mdds-3.1.0/test/rtree/test_main.cpp | 6 mdds-3.1.0/test/rtree/test_move.cpp | 24 mdds-3.1.0/test/rtree/test_node_split.cpp | 31 mdds-3.1.0/test/rtree/test_point_objects.cpp | 8 mdds-3.1.0/test/rtree/test_square_distance.cpp | 11 mdds-3.1.0/test/segment_tree/Makefile.am | 2 mdds-3.1.0/test/segment_tree/Makefile.in | 22 mdds-3.1.0/test/segment_tree/test_main.cpp | 1006 - mdds-3.1.0/test/segment_tree/test_main.hpp | 55 mdds-3.1.0/test/segment_tree/test_move_value.cpp | 142 mdds-3.1.0/test/sorted_string_map/Makefile.in | 1 mdds-3.1.0/test/sorted_string_map/test_main.cpp | 310 mdds-3.1.0/test/trie_map/Makefile.am | 7 mdds-3.1.0/test/trie_map/Makefile.in | 28 mdds-3.1.0/test/trie_map/test_main.cpp | 1518 - mdds-3.1.0/test/trie_map/test_main.hpp | 94 mdds-3.1.0/test/trie_map/test_move_value.cpp | 244 mdds-3.1.0/test/trie_map/test_node.cpp | 208 mdds-3.1.0/test/trie_map/test_pack_value_type.cpp | 169 mdds-3.1.0/test/trie_map/test_state.cpp | 576 mdds-3.1.0/tools/Makefile.in | 1 mdds-3.1.0/tools/runtime-env/Makefile.in | 1 210 files changed, 27194 insertions(+), 10729 deletions(-) diff -Nru mdds-2.1.1/CHANGELOG mdds-3.1.0/CHANGELOG --- mdds-2.1.1/CHANGELOG 2023-04-29 13:06:19.000000000 +0000 +++ mdds-3.1.0/CHANGELOG 2025-07-10 01:41:45.000000000 +0000 @@ -1,3 +1,85 @@ +mdds 3.1.0 + +* multi_type_vector + + * revised push_back() to also accept an rvalue reference. + + * added emplace_back() to allow in-place construction of values. However, + due to limitation of how the value type is determined, the type of an + inserted value must be default constructible, and the call incurs the + overhead of one default construction. + +* rtree + + * the erase() methods to take their iterator parameter by value. + +* flat_segment_tree + + * both insert() and search() methods to take their const_iterator parameter + by value. + + * the size of its const_iterator type has been reduced by not caching key + and value as its data members. Its size is now equal to the sum of the + sizes of two pointers and one boolean value. It also now returns + immutable references to the stored key and value. + +mdds 3.0.0 + +* trie_map and packed_trie_map + + * implemented equal (==) and non-equal (!=) operators in trie_map. Previously + only packed_trie_map implemented these operators. + + * added support for storing values that are only movable but not copyable. + Note that when using move-only values, the copy constructors do not work. + Also, due to this change, the trie_map::pack() method is no longer const; it + now moves the stored values into the packed variant. If you need to + preserve the original values stored in the non-packed variant, make a copy + first before calling the trie_map::pack() method. + + * simplified the template parameters so that the first template parameter + specifies the key type. + + * revised value storage in packed_trie_map so that the size of the unit value + type of its internal buffer would not be forced to be the size of a pointer. + The user can now optionally specify a different-sized unsigned integer type + as the value type of the internal buffer. This will benefit mostly when the + number of stored values is small so that a smaller-sized integer type can + sufficiently store all values. In such cases, the size of the in-memory + buffer as well as the size of a state file will become smaller. + + * implemented a method to allow traversal of the trie structure one node at a + time. This can be done by first calling the root_node() method to retrieve + the root node of the trie then traverse through its child nodes. + + * added overview section in the documentation. + +* segment_tree + + * significantly revised its API design to give it necessary polish in order to + bring its usability to an acceptable level. + + * added boundary_keys() method that returns a sorted sequence of boundary + keys. + + * re-implemented the equal and non-equal operators to work with move-only + values. + + * added documentation with code examples. + +* sorted_string_map + + * EntryT template parameter has been removed which was previously used to + optionally allow defining keys in the entry array as std::string_view. + After the removal of the template parameter, keys in the entry array are + always defined as std::string_view. + + * added find_key() method to perform reverse lookup of the key from a value, + with two lookup algorithms to choose from - linear search and hash-based + search. + + * added documentation with code examples. + mdds 2.1.1 * flat_segment_tree diff -Nru mdds-2.1.1/Makefile.am mdds-3.1.0/Makefile.am --- mdds-2.1.1/Makefile.am 2023-04-29 13:12:16.000000000 +0000 +++ mdds-3.1.0/Makefile.am 2025-01-22 02:40:24.000000000 +0000 @@ -17,57 +17,83 @@ autogen.sh \ CHANGELOG \ LICENSE \ + doc/_static/images/fst-example1-initial.svg \ + doc/_static/images/fst-example1-insert1.svg \ + doc/_static/images/fst-example1-insert2.svg \ + doc/_static/images/mtv-block-structure.svg \ + doc/_static/images/mtv_collection_sheet.png \ + doc/_static/images/rtree_bounds2_tree.png \ + doc/_static/images/rtree_bounds2_tree_bulkload.png \ + doc/_static/images/rtree_bounds_src.png \ + doc/_static/images/rtree_bounds_tree.png \ + doc/api.rst \ doc/conf.py \ doc/doxygen.conf \ - doc/point_quad_tree.rst \ - doc/rtree.rst \ - doc/api.rst \ + doc/environment.yml \ + doc/figures.odg \ + doc/flat_segment_tree/api.rst \ + doc/flat_segment_tree/index.rst \ + doc/flat_segment_tree/iterate-segments.rst \ + doc/flat_segment_tree/quickstart.rst \ + doc/global.rst \ doc/index.rst \ - doc/flat_segment_tree.rst \ - doc/segment_tree.rst \ doc/multi_type_matrix.rst \ - doc/trie_map.rst \ - doc/sorted_string_map.rst \ - doc/global.rst \ - doc/multi_type_vector/index.rst \ - doc/multi_type_vector/examples.rst \ doc/multi_type_vector/api-ref.rst \ - doc/_static/images/mtv-block-structure.svg \ - doc/_static/images/rtree_bounds_src.png \ - doc/_static/images/mtv_collection_sheet.png \ - doc/_static/images/rtree_bounds2_tree_bulkload.png \ - doc/_static/images/rtree_bounds2_tree.png \ - doc/_static/images/fst-example1-initial.svg \ - doc/_static/images/fst-example1-insert2.svg \ - doc/_static/images/rtree_bounds_tree.png \ - doc/_static/images/fst-example1-insert1.svg \ - example/rtree_simple.cpp \ - example/packed_trie_state_int.cpp \ - example/multi_type_matrix.cpp \ - example/rtree_erase.cpp \ - example/packed_trie_map.cpp \ - example/trie_map.cpp \ - example/rtree_medium_bulkload.cpp \ - example/packed_trie_state_custom.cpp \ - example/segment_tree.cpp \ - example/point_quad_tree.cpp \ + doc/multi_type_vector/examples.rst \ + doc/multi_type_vector/index.rst \ + doc/point_quad_tree.rst \ + doc/requirements.txt \ + doc/rtree/api.rst \ + doc/rtree/bulkload.rst \ + doc/rtree/index.rst \ + doc/rtree/quickstart.rst \ + doc/rtree/remove-value.rst \ + doc/rtree/visualize.rst \ + doc/segment_tree/api.rst \ + doc/segment_tree/index.rst \ + doc/segment_tree/perf.rst \ + doc/segment_tree/quickstart.rst \ + doc/segment_tree/remove-segments.rst \ + doc/sorted_string_map/api.rst \ + doc/sorted_string_map/index.rst \ + doc/sorted_string_map/quickstart.rst \ + doc/trie_map/api.rst \ + doc/trie_map/direct-packed-trie-map.rst \ + doc/trie_map/index.rst \ + doc/trie_map/pack-trie-map.rst \ + doc/trie_map/populate-trie-map.rst \ + doc/trie_map/save-load-packed-trie-map-custom-value.rst \ + doc/trie_map/save-load-packed-trie-map.rst \ + example/Makefile.am \ + example/flat_segment_tree.cpp \ example/flat_segment_tree_itrs.cpp \ - example/multi_type_vector/pos_hint.cpp \ + example/multi_type_matrix.cpp \ + example/multi_type_vector/Makefile.am \ example/multi_type_vector/basic.cpp \ - example/multi_type_vector/debug_trace.cpp \ example/multi_type_vector/custom_value_types.cpp \ example/multi_type_vector/custom_value_types_custom_store.cpp \ + example/multi_type_vector/debug_trace.cpp \ + example/multi_type_vector/element_block1.cpp \ + example/multi_type_vector/event1.cpp \ example/multi_type_vector/mtv_collection.cpp \ + example/multi_type_vector/pos_hint.cpp \ example/multi_type_vector/standard_custom_store.cpp \ - example/multi_type_vector/event1.cpp \ - example/multi_type_vector/element_block1.cpp \ + example/packed_trie_map.cpp \ + example/packed_trie_state_custom.cpp \ + example/packed_trie_state_int.cpp \ + example/point_quad_tree.cpp \ + example/rtree_erase.cpp \ example/rtree_medium.cpp \ - example/flat_segment_tree.cpp \ + example/rtree_medium_bulkload.cpp \ + example/rtree_simple.cpp \ + example/segment_tree.cpp \ + example/sorted_string_map.cpp \ + example/trie_map.cpp \ misc/gdb/mdds/__init__.py \ misc/matrix_perf.cpp \ misc/mdds.pc.in \ - misc/sorted_string_map_perf.cpp \ - quickcheck/flat_segment_tree.cpp + misc/sorted_string_data.dat \ + misc/sorted_string_map_perf.cpp install-data-local: $(MKDIR_P) $(DESTDIR)$(docdir) @@ -89,6 +115,12 @@ doc: doc-doxygen doc-sphinx +doc-open: + @xdg-open ./doc/_build/index.html + +doc-clean: + @rm -rf ./doc/_build ./doc/_doxygen + endif check-gdb: diff -Nru mdds-2.1.1/Makefile.in mdds-3.1.0/Makefile.in --- mdds-2.1.1/Makefile.in 2023-04-29 13:12:29.000000000 +0000 +++ mdds-3.1.0/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -292,7 +292,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -363,57 +362,83 @@ autogen.sh \ CHANGELOG \ LICENSE \ + doc/_static/images/fst-example1-initial.svg \ + doc/_static/images/fst-example1-insert1.svg \ + doc/_static/images/fst-example1-insert2.svg \ + doc/_static/images/mtv-block-structure.svg \ + doc/_static/images/mtv_collection_sheet.png \ + doc/_static/images/rtree_bounds2_tree.png \ + doc/_static/images/rtree_bounds2_tree_bulkload.png \ + doc/_static/images/rtree_bounds_src.png \ + doc/_static/images/rtree_bounds_tree.png \ + doc/api.rst \ doc/conf.py \ doc/doxygen.conf \ - doc/point_quad_tree.rst \ - doc/rtree.rst \ - doc/api.rst \ + doc/environment.yml \ + doc/figures.odg \ + doc/flat_segment_tree/api.rst \ + doc/flat_segment_tree/index.rst \ + doc/flat_segment_tree/iterate-segments.rst \ + doc/flat_segment_tree/quickstart.rst \ + doc/global.rst \ doc/index.rst \ - doc/flat_segment_tree.rst \ - doc/segment_tree.rst \ doc/multi_type_matrix.rst \ - doc/trie_map.rst \ - doc/sorted_string_map.rst \ - doc/global.rst \ - doc/multi_type_vector/index.rst \ - doc/multi_type_vector/examples.rst \ doc/multi_type_vector/api-ref.rst \ - doc/_static/images/mtv-block-structure.svg \ - doc/_static/images/rtree_bounds_src.png \ - doc/_static/images/mtv_collection_sheet.png \ - doc/_static/images/rtree_bounds2_tree_bulkload.png \ - doc/_static/images/rtree_bounds2_tree.png \ - doc/_static/images/fst-example1-initial.svg \ - doc/_static/images/fst-example1-insert2.svg \ - doc/_static/images/rtree_bounds_tree.png \ - doc/_static/images/fst-example1-insert1.svg \ - example/rtree_simple.cpp \ - example/packed_trie_state_int.cpp \ - example/multi_type_matrix.cpp \ - example/rtree_erase.cpp \ - example/packed_trie_map.cpp \ - example/trie_map.cpp \ - example/rtree_medium_bulkload.cpp \ - example/packed_trie_state_custom.cpp \ - example/segment_tree.cpp \ - example/point_quad_tree.cpp \ + doc/multi_type_vector/examples.rst \ + doc/multi_type_vector/index.rst \ + doc/point_quad_tree.rst \ + doc/requirements.txt \ + doc/rtree/api.rst \ + doc/rtree/bulkload.rst \ + doc/rtree/index.rst \ + doc/rtree/quickstart.rst \ + doc/rtree/remove-value.rst \ + doc/rtree/visualize.rst \ + doc/segment_tree/api.rst \ + doc/segment_tree/index.rst \ + doc/segment_tree/perf.rst \ + doc/segment_tree/quickstart.rst \ + doc/segment_tree/remove-segments.rst \ + doc/sorted_string_map/api.rst \ + doc/sorted_string_map/index.rst \ + doc/sorted_string_map/quickstart.rst \ + doc/trie_map/api.rst \ + doc/trie_map/direct-packed-trie-map.rst \ + doc/trie_map/index.rst \ + doc/trie_map/pack-trie-map.rst \ + doc/trie_map/populate-trie-map.rst \ + doc/trie_map/save-load-packed-trie-map-custom-value.rst \ + doc/trie_map/save-load-packed-trie-map.rst \ + example/Makefile.am \ + example/flat_segment_tree.cpp \ example/flat_segment_tree_itrs.cpp \ - example/multi_type_vector/pos_hint.cpp \ + example/multi_type_matrix.cpp \ + example/multi_type_vector/Makefile.am \ example/multi_type_vector/basic.cpp \ - example/multi_type_vector/debug_trace.cpp \ example/multi_type_vector/custom_value_types.cpp \ example/multi_type_vector/custom_value_types_custom_store.cpp \ + example/multi_type_vector/debug_trace.cpp \ + example/multi_type_vector/element_block1.cpp \ + example/multi_type_vector/event1.cpp \ example/multi_type_vector/mtv_collection.cpp \ + example/multi_type_vector/pos_hint.cpp \ example/multi_type_vector/standard_custom_store.cpp \ - example/multi_type_vector/event1.cpp \ - example/multi_type_vector/element_block1.cpp \ + example/packed_trie_map.cpp \ + example/packed_trie_state_custom.cpp \ + example/packed_trie_state_int.cpp \ + example/point_quad_tree.cpp \ + example/rtree_erase.cpp \ example/rtree_medium.cpp \ - example/flat_segment_tree.cpp \ + example/rtree_medium_bulkload.cpp \ + example/rtree_simple.cpp \ + example/segment_tree.cpp \ + example/sorted_string_map.cpp \ + example/trie_map.cpp \ misc/gdb/mdds/__init__.py \ misc/matrix_perf.cpp \ misc/mdds.pc.in \ - misc/sorted_string_map_perf.cpp \ - quickcheck/flat_segment_tree.cpp + misc/sorted_string_data.dat \ + misc/sorted_string_map_perf.cpp all: all-recursive @@ -975,6 +1000,12 @@ @BUILD_DOCS_TRUE@doc: doc-doxygen doc-sphinx +@BUILD_DOCS_TRUE@doc-open: +@BUILD_DOCS_TRUE@ @xdg-open ./doc/_build/index.html + +@BUILD_DOCS_TRUE@doc-clean: +@BUILD_DOCS_TRUE@ @rm -rf ./doc/_build ./doc/_doxygen + check-gdb: make -C test/gdb check diff -Nru mdds-2.1.1/configure mdds-3.1.0/configure --- mdds-2.1.1/configure 2023-04-29 13:07:54.000000000 +0000 +++ mdds-3.1.0/configure 2025-07-10 01:41:52.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for mdds 2.1.1. +# Generated by GNU Autoconf 2.71 for mdds 3.1.0. # # Report bugs to . # @@ -611,8 +611,8 @@ # Identity of this package. PACKAGE_NAME='mdds' PACKAGE_TARNAME='mdds' -PACKAGE_VERSION='2.1.1' -PACKAGE_STRING='mdds 2.1.1' +PACKAGE_VERSION='3.1.0' +PACKAGE_STRING='mdds 3.1.0' PACKAGE_BUGREPORT='kohei.yoshida@gmail.com' PACKAGE_URL='' @@ -695,7 +695,6 @@ LDFLAGS CXXFLAGS CXX -QUICKCHECKDIR MISCDIR INCDIR OBJDIR @@ -1352,7 +1351,7 @@ # 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 2.1.1 to adapt to many kinds of systems. +\`configure' configures mdds 3.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1419,7 +1418,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of mdds 2.1.1:";; + short | recursive ) echo "Configuration of mdds 3.1.0:";; esac cat <<\_ACEOF @@ -1539,7 +1538,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mdds configure 2.1.1 +mdds configure 3.1.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1919,7 +1918,7 @@ 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 2.1.1, which was +It was created by mdds $as_me 3.1.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3404,7 +3403,7 @@ # Define the identity of the package. PACKAGE='mdds' - VERSION='2.1.1' + VERSION='3.1.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -3532,8 +3531,8 @@ -VERSION=2.1.1 -API_VERSION=2.1 +VERSION=3.1.0 +API_VERSION=3.0 @@ -3545,8 +3544,6 @@ OBJDIR=obj INCDIR=include MISCDIR=misc -QUICKCHECKDIR=quickcheck - @@ -4150,11 +4147,11 @@ then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } -if test ${ac_cv_prog_cxx_11+y} +if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_11=no + ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4196,11 +4193,11 @@ then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } -if test ${ac_cv_prog_cxx_98+y} +if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_98=no + ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4386,18 +4383,18 @@ if test x$ac_success = xno; then - for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx17_$switch" | $as_tr_sh` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features with $switch" >&5 + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx17_$switch" | $as_tr_sh` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features with $switch" >&5 printf %s "checking whether $CXX supports C++17 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" - CXX="$CXX $switch" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + CXX="$CXX $switch" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4408,7 +4405,21 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201103L +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" @@ -4695,7 +4706,7 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201402L +#elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" @@ -4815,7 +4826,7 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201703L +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L #error "This is not a C++17 compiler" @@ -5181,7 +5192,7 @@ } // namespace cxx17 -#endif // __cplusplus < 201703L +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L @@ -5193,25 +5204,23 @@ eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - CXX="$ac_save_CXX" + CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" fi - done - if test x$ac_success = xyes; then + ac_success=yes break fi done fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -6608,11 +6617,11 @@ then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } -if test ${ac_cv_prog_cxx_11+y} +if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_11=no + ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -6654,11 +6663,11 @@ then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } -if test ${ac_cv_prog_cxx_98+y} +if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_98=no + ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -7558,7 +7567,7 @@ -ac_config_files="$ac_config_files Makefile include/Makefile include/mdds/Makefile include/mdds/multi_type_vector/Makefile include/mdds/multi_type_vector/aos/Makefile include/mdds/multi_type_vector/soa/Makefile example/Makefile example/multi_type_vector/Makefile test/Makefile test/gdb/Makefile test/gdb/src/Makefile test/flat_segment_tree/Makefile test/include/Makefile test/multi_type_matrix/Makefile test/multi_type_vector/Makefile test/multi_type_vector/collection/Makefile test/multi_type_vector/collection/aos/Makefile test/multi_type_vector/collection/soa/Makefile test/multi_type_vector/collection/tc/Makefile test/multi_type_vector/custom/Makefile test/multi_type_vector/custom/aos/Makefile test/multi_type_vector/custom/soa/Makefile test/multi_type_vector/custom/tc/Makefile test/multi_type_vector/custom-trait/Makefile test/multi_type_vector/custom-trait/aos/Makefile test/multi_type_vector/custom-trait/soa/Makefile test/multi_type_vector/debug-util/Makefile test/multi_type_vector/debug-util/soa/Makefile test/multi_type_vector/default/Makefile test/multi_type_vector/default/aos/Makefile test/multi_type_vector/default/soa/Makefile test/multi_type_vector/default/tc/Makefile test/multi_type_vector/element-blocks/Makefile test/multi_type_vector/event/Makefile test/multi_type_vector/event/aos/Makefile test/multi_type_vector/event/soa/Makefile test/multi_type_vector/event/tc/Makefile test/multi_type_vector/perf/Makefile test/point_quad_tree/Makefile test/rtree/Makefile test/segment_tree/Makefile test/sorted_string_map/Makefile test/trie_map/Makefile tools/Makefile tools/runtime-env/Makefile misc/mdds-$API_VERSION.pc:misc/mdds.pc.in" +ac_config_files="$ac_config_files Makefile include/Makefile include/mdds/Makefile include/mdds/multi_type_vector/Makefile include/mdds/multi_type_vector/aos/Makefile include/mdds/multi_type_vector/soa/Makefile example/Makefile example/multi_type_vector/Makefile test/Makefile test/gdb/Makefile test/gdb/src/Makefile test/flat_segment_tree/Makefile test/include/Makefile test/multi_type_matrix/Makefile test/multi_type_vector/Makefile test/multi_type_vector/collection/Makefile test/multi_type_vector/collection/aos/Makefile test/multi_type_vector/collection/soa/Makefile test/multi_type_vector/collection/tc/Makefile test/multi_type_vector/custom/Makefile test/multi_type_vector/custom/aos/Makefile test/multi_type_vector/custom/soa/Makefile test/multi_type_vector/custom/tc/Makefile test/multi_type_vector/custom-trait/Makefile test/multi_type_vector/custom-trait/aos/Makefile test/multi_type_vector/custom-trait/soa/Makefile test/multi_type_vector/debug-util/Makefile test/multi_type_vector/debug-util/soa/Makefile test/multi_type_vector/default/Makefile test/multi_type_vector/default/aos/Makefile test/multi_type_vector/default/soa/Makefile test/multi_type_vector/default/tc/Makefile test/multi_type_vector/element-blocks/Makefile test/multi_type_vector/event/Makefile test/multi_type_vector/event/aos/Makefile test/multi_type_vector/event/soa/Makefile test/multi_type_vector/event/tc/Makefile test/multi_type_vector/perf/Makefile test/multi_type_vector/push-emplace-back/Makefile test/multi_type_vector/push-emplace-back/aos/Makefile test/multi_type_vector/push-emplace-back/soa/Makefile test/multi_type_vector/push-emplace-back/tc/Makefile test/point_quad_tree/Makefile test/rtree/Makefile test/segment_tree/Makefile test/sorted_string_map/Makefile test/trie_map/Makefile tools/Makefile tools/runtime-env/Makefile misc/mdds-$API_VERSION.pc:misc/mdds.pc.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8139,7 +8148,7 @@ # 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 2.1.1, which was +This file was extended by mdds $as_me 3.1.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8198,7 +8207,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -mdds config.status 2.1.1 +mdds config.status 3.1.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" @@ -8355,6 +8364,10 @@ "test/multi_type_vector/event/soa/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/event/soa/Makefile" ;; "test/multi_type_vector/event/tc/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/event/tc/Makefile" ;; "test/multi_type_vector/perf/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/perf/Makefile" ;; + "test/multi_type_vector/push-emplace-back/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/push-emplace-back/Makefile" ;; + "test/multi_type_vector/push-emplace-back/aos/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/push-emplace-back/aos/Makefile" ;; + "test/multi_type_vector/push-emplace-back/soa/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/push-emplace-back/soa/Makefile" ;; + "test/multi_type_vector/push-emplace-back/tc/Makefile") CONFIG_FILES="$CONFIG_FILES test/multi_type_vector/push-emplace-back/tc/Makefile" ;; "test/point_quad_tree/Makefile") CONFIG_FILES="$CONFIG_FILES test/point_quad_tree/Makefile" ;; "test/rtree/Makefile") CONFIG_FILES="$CONFIG_FILES test/rtree/Makefile" ;; "test/segment_tree/Makefile") CONFIG_FILES="$CONFIG_FILES test/segment_tree/Makefile" ;; diff -Nru mdds-2.1.1/configure.ac mdds-3.1.0/configure.ac --- mdds-2.1.1/configure.ac 2023-04-29 13:06:19.000000000 +0000 +++ mdds-3.1.0/configure.ac 2025-07-10 01:41:45.000000000 +0000 @@ -1,9 +1,9 @@ -AC_INIT(mdds, 2.1.1, kohei.yoshida@gmail.com) +AC_INIT(mdds, 3.1.0, kohei.yoshida@gmail.com) AM_INIT_AUTOMAKE([foreign dist-bzip2 dist-xz subdir-objects]) AM_MAINTAINER_MODE VERSION=AC_PACKAGE_VERSION -API_VERSION=2.1 +API_VERSION=3.0 AC_SUBST(VERSION) AC_SUBST(API_VERSION) @@ -15,11 +15,9 @@ OBJDIR=obj INCDIR=include MISCDIR=misc -QUICKCHECKDIR=quickcheck AC_SUBST(OBJDIR) AC_SUBST(INCDIR) AC_SUBST(MISCDIR) -AC_SUBST(QUICKCHECKDIR) AX_CXX_COMPILE_STDCXX_17([noext], [mandatory]) @@ -162,6 +160,10 @@ test/multi_type_vector/event/soa/Makefile test/multi_type_vector/event/tc/Makefile test/multi_type_vector/perf/Makefile +test/multi_type_vector/push-emplace-back/Makefile +test/multi_type_vector/push-emplace-back/aos/Makefile +test/multi_type_vector/push-emplace-back/soa/Makefile +test/multi_type_vector/push-emplace-back/tc/Makefile test/point_quad_tree/Makefile test/rtree/Makefile test/segment_tree/Makefile diff -Nru mdds-2.1.1/debian/changelog mdds-3.1.0/debian/changelog --- mdds-2.1.1/debian/changelog 2023-11-24 16:38:44.000000000 +0000 +++ mdds-3.1.0/debian/changelog 2025-08-26 19:38:02.000000000 +0000 @@ -1,8 +1,32 @@ -mdds (2.1.1-2) unstable; urgency=medium +mdds (3.1.0-3~bpo13+1) trixie-backports; urgency=medium + + * rebuild for trixie-backports + + -- Rene Engelhard Tue, 26 Aug 2025 21:38:02 +0200 + +mdds (3.1.0-3) unstable; urgency=medium * upload to unstable - -- Rene Engelhard Fri, 24 Nov 2023 17:38:44 +0100 + -- Rene Engelhard Fri, 22 Aug 2025 13:24:07 +0200 + +mdds (3.1.0-2) experimental; urgency=medium + + * debian/watch: fix, based on liborcus + + -- Rene Engelhard Tue, 12 Aug 2025 22:31:48 +0200 + +mdds (3.1.0-1) experimental; urgency=medium + + * New upstream version 3.1.0 + + -- Rene Engelhard Fri, 11 Jul 2025 17:10:13 +0200 + +mdds (3.0.0-1) experimental; urgency=medium + + * New upstream version 3.0.0 + + -- Rene Engelhard Wed, 29 Jan 2025 17:56:27 +0100 mdds (2.1.1-1) experimental; urgency=medium diff -Nru mdds-2.1.1/debian/tests/patches/system-includes.diff mdds-3.1.0/debian/tests/patches/system-includes.diff --- mdds-2.1.1/debian/tests/patches/system-includes.diff 2023-11-24 16:38:41.000000000 +0000 +++ mdds-3.1.0/debian/tests/patches/system-includes.diff 2025-08-22 11:24:03.000000000 +0000 @@ -5,7 +5,7 @@ @@ -1,5 +1,5 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG -+AM_CPPFLAGS = $(shell pkg-config --cflags mdds-2.1) -DNDEBUG ++AM_CPPFLAGS = $(shell pkg-config --cflags mdds-3.0) -DNDEBUG EXTRA_PROGRAMS = \ flat-segment-tree \ diff -Nru mdds-2.1.1/debian/watch mdds-3.1.0/debian/watch --- mdds-2.1.1/debian/watch 2023-11-24 16:38:18.000000000 +0000 +++ mdds-3.1.0/debian/watch 2025-08-12 20:32:47.000000000 +0000 @@ -1,4 +1,4 @@ version=4 -opts=downloadurlmangle=s|gitlab.com/mdds/mdds/repository/(@ANY_VERSION@)/archive.tar.gz|kohei.us/files/mdds/src/@PACKAGE@-$1.tar.bz2|,repack,compression=bz2 \ -http://gitlab.com/mdds/mdds/tags .*/@ANY_VERSION@/archive\.tar\.gz +opts=searchmode=plain,downloadurlmangle=s|gitlab.com/mdds/mdds/repository/(@ANY_VERSION@)/archive.tar.gz|kohei.us/files/mdds/src/@PACKAGE@-$1.tar.xz|,repack,compression=xz \ +https://gitlab.com/mdds/mdds/tags?sort=updated_desc /mdds/mdds/-/archive/@ANY_VERSION@/[^/]+\.tar\.gz diff -Nru mdds-2.1.1/doc/api.rst mdds-3.1.0/doc/api.rst --- mdds-2.1.1/doc/api.rst 2022-11-17 02:13:32.000000000 +0000 +++ mdds-3.1.0/doc/api.rst 2025-02-08 04:41:45.000000000 +0000 @@ -2,6 +2,47 @@ API Incompatibility Notes ========================= +v3.0 +---- + +trie_map & packed_trie_map +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* The template parameter for the key type has been simplified such that the user + can now directly specify the key type as the first template argument. Previously, + one would need to specify a rather complex key traits type whose design allowed + an internal key buffer that is different from the external key type. But this + made the API much less intuitive especially when one wants to switch between + different key types. + +* ``trie_map::pack()`` method was previously a const method and would copy the + stored values and put the copies into the packed variant. In 3.0, that ``const`` + qualifier has been removed. This is because this method now moves all stored + values into the packed variant if the value supports move construction. If + one wants to preserve the original values, create a copy first then call + ``trie_map::pack()``. + +sorted_string_map +^^^^^^^^^^^^^^^^^ + +* The ``EntryT`` template parameter, which was previously used to define the + key-value entry type, has been removed. This was used mostly to allow initialization + of key values as ``std::string_view`` type without breaking backward compatibility. + In 3.0, key values are always initialized as ``std::string_view`` type. + +segment_tree +^^^^^^^^^^^^ + +* Previous implementation was still in its experimental stage, and its usability + and API design was not on par with the other data structures in this library. + In 3.0, its API has been revamped to give it proper polish and acceptable + usability. + +flat_segment_tree +^^^^^^^^^^^^^^^^^ + +* ``is_tree_valid()`` method has been renamed to ``valid_tree()``. + v2.1 ---- diff -Nru mdds-2.1.1/doc/conf.py mdds-3.1.0/doc/conf.py --- mdds-2.1.1/doc/conf.py 2023-04-29 13:06:19.000000000 +0000 +++ mdds-3.1.0/doc/conf.py 2025-07-10 01:41:45.000000000 +0000 @@ -51,16 +51,16 @@ # General information about the project. project = 'mdds' -copyright = '2022, Kohei Yoshida' +copyright = '2025, Kohei Yoshida' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = "2.1" +version = "3.1" # The full version, including alpha/beta/rc tags. -release = "2.1.1" +release = "3.1.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -105,7 +105,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = 'piccolo_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -265,7 +265,5 @@ #texinfo_no_detailmenu = False breathe_projects = {"mdds": "./_doxygen/xml"} - breathe_default_project = "mdds" - breathe_default_members = ('members', 'undoc-members') diff -Nru mdds-2.1.1/doc/environment.yml mdds-3.1.0/doc/environment.yml --- mdds-2.1.1/doc/environment.yml 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/environment.yml 2022-04-22 00:12:40.000000000 +0000 @@ -0,0 +1,8 @@ +name: RTD +channels: + - conda-forge + - defaults +dependencies: + - python=3.8 + - doxygen>=1.9.1 + - breathe Binary files /srv/release.debian.org/tmp/L4iuToZBUg/mdds-2.1.1/doc/figures.odg and /srv/release.debian.org/tmp/HY8FhnzTdU/mdds-3.1.0/doc/figures.odg differ diff -Nru mdds-2.1.1/doc/flat_segment_tree/api.rst mdds-3.1.0/doc/flat_segment_tree/api.rst --- mdds-2.1.1/doc/flat_segment_tree/api.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/flat_segment_tree/api.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,6 @@ + +API Reference +============= + +.. doxygenclass:: mdds::flat_segment_tree + :members: diff -Nru mdds-2.1.1/doc/flat_segment_tree/index.rst mdds-3.1.0/doc/flat_segment_tree/index.rst --- mdds-2.1.1/doc/flat_segment_tree/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/flat_segment_tree/index.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,30 @@ +.. highlight:: cpp + +Flat Segment Tree +================= + +Flat segment tree is a derivative of `segment tree +`_, and is designed to store +non-overlapping 1-dimensional range values such that *the values of the +neighboring ranges are guaranteed to be different.* An insertion of a range +value into this structure will always overwrite one or more existing ranges +that overlap with the new range. If an insertion of a new range would cause +any adjacent ranges to have the equal value, those ranges will be merged into +one range. + +An instance of this structure is initialized with fixed lower and upper +bounaries, which will not change throughout the life time of the instance. + +The flat segment tree structure consists of two parts: the leaf-node part +which also forms a doubly-linked list, and the non-leaf-node part which forms +a balanced-binary tree and is used only when performing tree-based queries. +The range values are stored in the leaf-nodes, while the non-leaf nodes are +used only for queries. + +.. toctree:: + :maxdepth: 1 + + quickstart.rst + iterate-segments.rst + api.rst + diff -Nru mdds-2.1.1/doc/flat_segment_tree/iterate-segments.rst mdds-3.1.0/doc/flat_segment_tree/iterate-segments.rst --- mdds-2.1.1/doc/flat_segment_tree/iterate-segments.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/flat_segment_tree/iterate-segments.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,96 @@ + +Iterate through stored segments +=============================== + +:cpp:class:`~mdds::flat_segment_tree` supports two types of iterators to allow +you to iterate through the segments stored in your tree. The first way is to +iterate through the individual leaf nodes one at a time by using +:cpp:func:`~mdds::flat_segment_tree::begin` and :cpp:func:`~mdds::flat_segment_tree::end`: + +.. literalinclude:: ../../example/flat_segment_tree_itrs.cpp + :language: C++ + :start-after: //!code-start: iterate-nodes + :end-before: //!code-end: iterate-nodes + :dedent: 4 + +Each iterator value contains a pair of two values named ``first`` and ``second``, +with the first one being the key of the segment that the node initiates, and the +second one being the value associated with that segment. When executing this +code with the tree from the example code above, you'll get the following output: + +.. code-block:: none + + key: 0; value: 0 + key: 10; value: 10 + key: 20; value: 0 + key: 50; value: 15 + key: 60; value: 5 + key: 65; value: 15 + key: 70; value: 0 + key: 500; value: 0 + +Each node stores the start key and the value of the segment it initiates, and +the key stored in each node is also the end key of the segment that the +previous node initiates except for the first node. Note that the value stored +in the last node is currently not used. It is set to be the zero value of the +value type, but this may change in the future. + +One thing to keep in mind is that :cpp:class:`~mdds::flat_segment_tree` does +not support mutable iterators that let you modify the stored keys or values. + +.. note:: + + :cpp:class:`~mdds::flat_segment_tree` does not support mutable iterators; + you can only traverse the values in a read-only fashion. + +You can also use range-based for loop to iterate through the leaf nodes in a +similar fashion: + +.. literalinclude:: ../../example/flat_segment_tree_itrs.cpp + :language: C++ + :start-after: //!code-start: loop-nodes + :end-before: //!code-end: loop-nodes + :dedent: 4 + +The output from this code is identical to that from the previous one. + +Now, one major inconvenience of navigating through the individual leaf nodes +is that you need to manually keep track of the start and end points of each +segment if you need to operate on the segments rather than the nodes that +comprise the segments. The good news is that +:cpp:class:`~mdds::flat_segment_tree` does provide a way to iterate through +the segments directly as the following code demonstrates: + +.. literalinclude:: ../../example/flat_segment_tree_itrs.cpp + :language: C++ + :start-after: //!code-start: iterate-segments + :end-before: //!code-end: iterate-segments + :dedent: 4 + +This code uses :cpp:func:`~mdds::flat_segment_tree::begin_segment` and +:cpp:func:`~mdds::flat_segment_tree::end_segment` to iterate through one +segment at a time with the value of each iterator containing ``start``, +``end`` and ``value`` members that correspond with the start key, end key and +the value of the segment, respectively. Running this code produces the +following output: + +.. code-block:: none + + start: 0; end: 10; value: 0 + start: 10; end: 20; value: 10 + start: 20; end: 50; value: 0 + start: 50; end: 60; value: 15 + start: 60; end: 65; value: 5 + start: 65; end: 70; value: 15 + start: 70; end: 500; value: 0 + +It's also possible to iterate through the segments in a range-based for loop, by +calling :cpp:func:`~mdds::flat_segment_tree::segment_range()`: + +.. literalinclude:: ../../example/flat_segment_tree_itrs.cpp + :language: C++ + :start-after: //!code-start: loop-segments + :end-before: //!code-end: loop-segments + :dedent: 4 + +This code should generate output identical to that of the previous code. diff -Nru mdds-2.1.1/doc/flat_segment_tree/quickstart.rst mdds-3.1.0/doc/flat_segment_tree/quickstart.rst --- mdds-2.1.1/doc/flat_segment_tree/quickstart.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/flat_segment_tree/quickstart.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,138 @@ + +Quick start +=========== + +This section demonstrates a simple use case of storing non-overlapping ranged +values and performing queries using :cpp:class:`~mdds::flat_segment_tree`. + +First, we need to instantiate a concrete type from the template: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + :dedent: 4 + +then create an instance of this type: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: instance + :end-before: //!code-end: instance + :dedent: 4 + +Here, the first and second arguments specify the lower and upper boundaries of +the whole segment. The third argument specifies the value for the empty +segments. What this line does is to create a new instance and initializes it +with one initial segment ranging from 0 to 500 with a value of 0: + +.. figure:: ../_static/images/fst-example1-initial.svg + :align: center + + The new instance is initialized with an initial segment. + +Internally, this initial range is represented by two leaf nodes, with the +first one storing the start key and the value for the segment both of which +happen to be 0 in this example, and the second one storing the end key of 500. +Note that the end key of a segment is not inclusive. + +The following lines insert two new segments into this structure: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: insert-1 + :end-before: //!code-end: insert-1 + :dedent: 4 + +The first line inserts a segment ranging from 10 to 20 with a value of 10, and +the second line from 50 to 70 with a value of 15: + +.. figure:: ../_static/images/fst-example1-insert1.svg + :align: center + + Two new segments have been inserted. + +You can insert a new segment either via :cpp:func:`~mdds::flat_segment_tree::insert_front` +or :cpp:func:`~mdds::flat_segment_tree::insert_back`. The end result will be +the same regardless of which method you use; the difference is that +:cpp:func:`~mdds::flat_segment_tree::insert_front` begins its search for +the insertion point from the first node associated with the minimum key value, +whereas :cpp:func:`~mdds::flat_segment_tree::insert_back` starts its search +from the last node associated with the maximum key value. + +After the insertions, the tree now contains a total of six leaf nodes to +represent all stored segments. Note that one leaf node typically represents +both the end of a segment and the start of the adjacent segment that comes +after it, unless it's either the first or the last node. + +The next line inserts another segment ranging from 60 to 65 having a value of +5: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: insert-2 + :end-before: //!code-end: insert-2 + :dedent: 4 + +As this new segment overlaps with the existing segment of 50 to 70, it will +cut into a middle part of that segment to make room for the new segment. At +this point, the tree contains a total of eight leaf nodes representing seven +segments: + +.. figure:: ../_static/images/fst-example1-insert2.svg + :align: center + + A new segment has been inserted that overlaps an existing non-empty segment. + +Next, we are going to query the value associated with a key of 15 via +:cpp:func:`~mdds::flat_segment_tree::search`: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: linear-search + :end-before: //!code-end: linear-search + :dedent: 4 + +Executing this code will yield the following output: + +.. code-block:: none + + The value at 15 is 10, and this segment spans from 10 to 20 + +One thing to note is that the :cpp:func:`~mdds::flat_segment_tree::search` +method performs a linear search which involves traversing only through the +leaf nodes in this data structure in order to find the target segment. As +such, the worst-case lookup performance is directly proportional to the number +of leaf nodes. + +There is another way to perform the query with better worse-case performance, +that is through :cpp:func:`~mdds::flat_segment_tree::search_tree` as seen in +the following code: + +.. literalinclude:: ../../example/flat_segment_tree.cpp + :language: C++ + :start-after: //!code-start: tree-search + :end-before: //!code-end: tree-search + :dedent: 4 + +The signature of the :cpp:func:`~mdds::flat_segment_tree::search_tree` method +is identical to that of the :cpp:func:`~mdds::flat_segment_tree::search` method +except for the name. This code generates the following output: + +.. code-block:: none + + The value at 62 is 5, and this segment spans from 60 to 65 + +Query via :cpp:func:`~mdds::flat_segment_tree::search_tree` generally performs +better since it traverses through the search tree to find the target segment. +But it does require the search tree to be built ahead of time by calling +:cpp:func:`~mdds::flat_segment_tree::build_tree`. Please be aware that if the +segments have been modified after the tree was last built, you will have to rebuild +the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree`. + +.. warning:: + + You need to build the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree` + before performing a tree-based search via :cpp:func:`~mdds::flat_segment_tree::search_tree`. + If the segments have been modified after the tree was last built, you will have to + rebuild the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree` again. diff -Nru mdds-2.1.1/doc/flat_segment_tree.rst mdds-3.1.0/doc/flat_segment_tree.rst --- mdds-2.1.1/doc/flat_segment_tree.rst 2023-04-29 13:06:19.000000000 +0000 +++ mdds-3.1.0/doc/flat_segment_tree.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,268 +0,0 @@ -.. highlight:: cpp - -Flat Segment Tree -================= - -Overview --------- - -Flat segment tree is a derivative of `segment tree -`_, and is designed to store -non-overlapping 1-dimensional range values such that *the values of the -neighboring ranges are guaranteed to be different.* An insertion of a range -value into this structure will always overwrite one or more existing ranges -that overlap with the new range. If an insertion of a new range would cause -any adjacent ranges to have the equal value, those ranges will be merged into -one range. - -An instance of this structure is initialized with fixed lower and upper -bounaries, which will not change throughout the life time of the instance. - -The flat segment tree structure consists of two parts: the leaf-node part -which also forms a doubly-linked list, and the non-leaf-node part which forms -a balanced-binary tree and is used only when performing tree-based queries. -The range values are stored in the leaf-nodes, while the non-leaf nodes are -used only for queries. - - -Quick start ------------ - -This section demonstrates a simple use case of storing non-overlapping ranged -values and performing queries using :cpp:class:`~mdds::flat_segment_tree`. - -First, we need to instantiate a concrete type from the template: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: type - :end-before: //!code-end: type - :dedent: 4 - -then create an instance of this type: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: instance - :end-before: //!code-end: instance - :dedent: 4 - -Here, the first and second arguments specify the lower and upper boundaries of -the whole segment. The third argument specifies the value for the empty -segments. What this line does is to create a new instance and initializes it -with one initial segment ranging from 0 to 500 with a value of 0: - -.. figure:: _static/images/fst-example1-initial.svg - :align: center - - The new instance is initialized with an initial segment. - -Internally, this initial range is represented by two leaf nodes, with the -first one storing the start key and the value for the segment both of which -happen to be 0 in this example, and the second one storing the end key of 500. -Note that the end key of a segment is not inclusive. - -The following lines insert two new segments into this structure: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: insert-1 - :end-before: //!code-end: insert-1 - :dedent: 4 - -The first line inserts a segment ranging from 10 to 20 with a value of 10, and -the second line from 50 to 70 with a value of 15: - -.. figure:: _static/images/fst-example1-insert1.svg - :align: center - - Two new segments have been inserted. - -You can insert a new segment either via :cpp:func:`~mdds::flat_segment_tree::insert_front` -or :cpp:func:`~mdds::flat_segment_tree::insert_back`. The end result will be -the same regardless of which method you use; the difference is that -:cpp:func:`~mdds::flat_segment_tree::insert_front` begins its search for -the insertion point from the first node associated with the minimum key value, -whereas :cpp:func:`~mdds::flat_segment_tree::insert_back` starts its search -from the last node associated with the maximum key value. - -After the insertions, the tree now contains a total of six leaf nodes to -represent all stored segments. Note that one leaf node typically represents -both the end of a segment and the start of the adjacent segment that comes -after it, unless it's either the first or the last node. - -The next line inserts another segment ranging from 60 to 65 having a value of -5: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: insert-2 - :end-before: //!code-end: insert-2 - :dedent: 4 - -As this new segment overlaps with the existing segment of 50 to 70, it will -cut into a middle part of that segment to make room for the new segment. At -this point, the tree contains a total of eight leaf nodes representing seven -segments: - -.. figure:: _static/images/fst-example1-insert2.svg - :align: center - - A new segment has been inserted that overlaps an existing non-empty segment. - -Next, we are going to query the value associated with a key of 15 via -:cpp:func:`~mdds::flat_segment_tree::search`: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: linear-search - :end-before: //!code-end: linear-search - :dedent: 4 - -Executing this code will yield the following output: - -.. code-block:: none - - The value at 15 is 10, and this segment spans from 10 to 20 - -One thing to note is that the :cpp:func:`~mdds::flat_segment_tree::search` -method performs a linear search which involves traversing only through the -leaf nodes in this data structure in order to find the target segment. As -such, the worst-case lookup performance is directly proportional to the number -of leaf nodes. - -There is another way to perform the query with better worse-case performance, -that is through :cpp:func:`~mdds::flat_segment_tree::search_tree` as seen in -the following code: - -.. literalinclude:: ../example/flat_segment_tree.cpp - :language: C++ - :start-after: //!code-start: tree-search - :end-before: //!code-end: tree-search - :dedent: 4 - -The signature of the :cpp:func:`~mdds::flat_segment_tree::search_tree` method -is identical to that of the :cpp:func:`~mdds::flat_segment_tree::search` method -except for the name. This code generates the following output: - -.. code-block:: none - - The value at 62 is 5, and this segment spans from 60 to 65 - -Query via :cpp:func:`~mdds::flat_segment_tree::search_tree` generally performs -better since it traverses through the search tree to find the target segment. -But it does require the search tree to be built ahead of time by calling -:cpp:func:`~mdds::flat_segment_tree::build_tree`. Please be aware that if the -segments have been modified after the tree was last built, you will have to rebuild -the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree`. - -.. warning:: - - You need to build the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree` - before performing a tree-based search via :cpp:func:`~mdds::flat_segment_tree::search_tree`. - If the segments have been modified after the tree was last built, you will have to - rebuild the tree by calling :cpp:func:`~mdds::flat_segment_tree::build_tree` again. - - -Iterate through stored segments -------------------------------- - -:cpp:class:`~mdds::flat_segment_tree` supports two types of iterators to allow -you to iterate through the segments stored in your tree. The first way is to -iterate through the individual leaf nodes one at a time by using -:cpp:func:`~mdds::flat_segment_tree::begin` and :cpp:func:`~mdds::flat_segment_tree::end`: - -.. literalinclude:: ../example/flat_segment_tree_itrs.cpp - :language: C++ - :start-after: //!code-start: iterate-nodes - :end-before: //!code-end: iterate-nodes - :dedent: 4 - -Each iterator value contains a pair of two values named ``first`` and ``second``, -with the first one being the key of the segment that the node initiates, and the -second one being the value associated with that segment. When executing this -code with the tree from the example code above, you'll get the following output: - -.. code-block:: none - - key: 0; value: 0 - key: 10; value: 10 - key: 20; value: 0 - key: 50; value: 15 - key: 60; value: 5 - key: 65; value: 15 - key: 70; value: 0 - key: 500; value: 0 - -Each node stores the start key and the value of the segment it initiates, and -the key stored in each node is also the end key of the segment that the -previous node initiates except for the first node. Note that the value stored -in the last node is currently not used. It is set to be the zero value of the -value type, but this may change in the future. - -One thing to keep in mind is that :cpp:class:`~mdds::flat_segment_tree` does -not support mutable iterators that let you modify the stored keys or values. - -.. note:: - - :cpp:class:`~mdds::flat_segment_tree` does not support mutable iterators; - you can only traverse the values in a read-only fashion. - -You can also use range-based for loop to iterate through the leaf nodes in a -similar fashion: - -.. literalinclude:: ../example/flat_segment_tree_itrs.cpp - :language: C++ - :start-after: //!code-start: loop-nodes - :end-before: //!code-end: loop-nodes - :dedent: 4 - -The output from this code is identical to that from the previous one. - -Now, one major inconvenience of navigating through the individual leaf nodes -is that you need to manually keep track of the start and end points of each -segment if you need to operate on the segments rather than the nodes that -comprise the segments. The good news is that -:cpp:class:`~mdds::flat_segment_tree` does provide a way to iterate through -the segments directly as the following code demonstrates: - -.. literalinclude:: ../example/flat_segment_tree_itrs.cpp - :language: C++ - :start-after: //!code-start: iterate-segments - :end-before: //!code-end: iterate-segments - :dedent: 4 - -This code uses :cpp:func:`~mdds::flat_segment_tree::begin_segment` and -:cpp:func:`~mdds::flat_segment_tree::end_segment` to iterate through one -segment at a time with the value of each iterator containing ``start``, -``end`` and ``value`` members that correspond with the start key, end key and -the value of the segment, respectively. Running this code produces the -following output: - -.. code-block:: none - - start: 0; end: 10; value: 0 - start: 10; end: 20; value: 10 - start: 20; end: 50; value: 0 - start: 50; end: 60; value: 15 - start: 60; end: 65; value: 5 - start: 65; end: 70; value: 15 - start: 70; end: 500; value: 0 - -It's also possible to iterate through the segments in a range-based for loop, by -calling :cpp:func:`~mdds::flat_segment_tree::segment_range()`: - -.. literalinclude:: ../example/flat_segment_tree_itrs.cpp - :language: C++ - :start-after: //!code-start: loop-segments - :end-before: //!code-end: loop-segments - :dedent: 4 - -This code should generate output identical to that of the previous code. - - -API Reference -------------- - -.. doxygenclass:: mdds::flat_segment_tree - :members: diff -Nru mdds-2.1.1/doc/index.rst mdds-3.1.0/doc/index.rst --- mdds-2.1.1/doc/index.rst 2023-01-07 17:49:03.000000000 +0000 +++ mdds-3.1.0/doc/index.rst 2025-01-22 02:40:24.000000000 +0000 @@ -18,14 +18,14 @@ :maxdepth: 1 global.rst - flat_segment_tree.rst - segment_tree.rst + flat_segment_tree/index.rst + segment_tree/index.rst point_quad_tree.rst multi_type_vector/index.rst multi_type_matrix.rst - sorted_string_map.rst - trie_map.rst - rtree.rst + sorted_string_map/index.rst + trie_map/index.rst + rtree/index.rst api.rst diff -Nru mdds-2.1.1/doc/requirements.txt mdds-3.1.0/doc/requirements.txt --- mdds-2.1.1/doc/requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/requirements.txt 2024-02-29 23:33:04.000000000 +0000 @@ -0,0 +1,2 @@ +breathe +piccolo-theme diff -Nru mdds-2.1.1/doc/rtree/api.rst mdds-3.1.0/doc/rtree/api.rst --- mdds-2.1.1/doc/rtree/api.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/api.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,18 @@ + +API Reference +============= + +.. doxygenclass:: mdds::rtree + :members: + +.. doxygenstruct:: mdds::detail::rtree::default_rtree_traits + :members: + +.. doxygenstruct:: mdds::detail::rtree::integrity_check_properties + :members: + +.. doxygenenum:: mdds::detail::rtree::export_tree_type + :project: mdds + +.. doxygenenum:: mdds::detail::rtree::search_type + :project: mdds diff -Nru mdds-2.1.1/doc/rtree/bulkload.rst mdds-3.1.0/doc/rtree/bulkload.rst --- mdds-2.1.1/doc/rtree/bulkload.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/bulkload.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,90 @@ + +.. highlight:: cpp + +Bulk-loading data +================= + +In this section we will explore on how to bulk-load data into an +:cpp:class:`~mdds::rtree` instance via rtree's own +:cpp:class:`~mdds::rtree::bulk_loader` class. In this example, we'll be using +the same custom trait we've used in the previous section in order to +artificially promote the rate of node splits. The first part of the code: + +.. literalinclude:: ../../example/rtree_medium_bulkload.cpp + :language: C++ + :start-after: //!code-start: tree-type + :end-before: //!code-end: tree-type + +is pretty much identical to the example in the last section. The next part of +the code defines what bounding rectangles to be inserted. Here, we are using a +somewhat larger rectangle set than the one used in the previous example to +better highlight the difference between normal insertions and bulk-loading: + +.. literalinclude:: ../../example/rtree_medium_bulkload.cpp + :language: C++ + :start-after: //!code-start: input-data + :end-before: //!code-end: input-data + +As with the previous example, each line in the ``rects`` initialization block +contains the top-left position of a rectangle (``x`` and ``y``) as well as its +size (``w`` and ``h``). But unlike the previous example, We are going to insert +them in two different ways. + +First, we are going to insert them via normal :cpp:func:`~mdds::rtree::insert()` +method: + +.. literalinclude:: ../../example/rtree_medium_bulkload.cpp + :language: C++ + :start-after: //!code-start: normal-load + :end-before: //!code-end: normal-load + :dedent: 4 + +This code should look familiar since it's nearly identical to the code in the +previous example. After the insertion is done, we export the tree as an SVG +to visualize its structure. + +Next, we insert the same set of rectangles via +:cpp:class:`~mdds::rtree::bulk_loader`: + +.. literalinclude:: ../../example/rtree_medium_bulkload.cpp + :language: C++ + :start-after: //!code-start: bulkload + :end-before: //!code-end: bulkload + :dedent: 4 + +Inserting via :cpp:class:`~mdds::rtree::bulk_loader` shouldn't be too different +than inserting via rtree's own insert methods. The only difference is that you +instantiate a :cpp:class:`~mdds::rtree::bulk_loader` instance to insert all your +data to it first, then call its :cpp:func:`~mdds::rtree::bulk_loader::pack()` +method at the end to construct the final :cpp:class:`~mdds::rtree` instance. + +When the insertion is done and the tree instance created, we are once again +exporting its structure to an SVG file for visualization. + +There are primarily two advantages to using +:cpp:class:`~mdds::rtree::bulk_loader` to load data. First, unlike the normal +insertion, bulk-loading does not trigger dynamic re-insertion nor node splits +during insertion. Second, a tree created from the bulk loader is typically well +balanced than if you insert the same data through normal insertion. That is +because the bulk loader sorts the data with respect to their bounding rectangles +ahead of time to partition them evenly. The tree is then populated from the +bottom-up. You can visually see the effect of this when comparing the two trees +built in our current example. + +The first one is from the tree built via normal insertion: + +.. figure:: ../_static/images/rtree_bounds2_tree.png + :align: center + +The top part of the picture looks very "busy" indicated by a darker green area +indicative of more directory nodes overlaping with each other. In general, the +bounding rectangles look bigger and are more overlapped. + +The one below, on the other hand, is from the tree built with the same data +set but through bulk-loading: + +.. figure:: ../_static/images/rtree_bounds2_tree_bulkload.png + :align: center + +The bounding rectangles generally look smaller and show much less overlaps than +the previous tree - traits indicative of a more balanced R-tree structure. diff -Nru mdds-2.1.1/doc/rtree/index.rst mdds-3.1.0/doc/rtree/index.rst --- mdds-2.1.1/doc/rtree/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/index.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,35 @@ + +.. highlight:: cpp + +R-tree +====== + +`R-tree `_ is a tree-based data +structure designed for optimal query performance on multi-dimensional spatial +objects with rectangular bounding shapes. The R-tree implementation included +in this library is a variant of R-tree known as `R*-tree +`_ which differs from the original +R-tree in that it may re-insert an object if the insertion of that object +would cause the original target directory to overflow. Such re-insertions +lead to more balanced tree which in turn lead to better query performance, at +the expense of slightly more overhead at insertion time. + +Our implementation of R-tree theoretically supports any number of dimensions +although certain functionalities, especially those related to visualization, +are only supported for 2-dimensional instances. + +R-tree consists of three types of nodes. Value nodes store the values +inserted externally and always sit at the bottom of the tree. Leaf directory +nodes sit directly above the value nodes, and store only value nodes as their +child nodes. The rest are all non-leaf directory nodes which can either store +leaf or non-leaf directory nodes. + +.. toctree:: + :maxdepth: 1 + + quickstart.rst + remove-value.rst + visualize.rst + bulkload.rst + api.rst + diff -Nru mdds-2.1.1/doc/rtree/quickstart.rst mdds-3.1.0/doc/rtree/quickstart.rst --- mdds-2.1.1/doc/rtree/quickstart.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/quickstart.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,212 @@ + +Quick start +=========== + +Let's go through a very simple example to demonstrate how to use +:cpp:class:`~mdds::rtree`. First, you need to specify a concrete type by +specifying the key type and value type to use: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + +You'll only need to specify the types of key and value here unless you want to +customize other properties of :cpp:class:`~mdds::rtree` including the number +of dimensions. By default, :cpp:class:`~mdds::rtree` sets the number of +dimensions to 2. + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: instantiate + :end-before: //!code-end: instantiate + :dedent: 4 + +Instantiating an rtree instance should be no brainer as it requires no input +parameters. Now, let's insert some data: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: insert-1 + :end-before: //!code-end: insert-1 + :dedent: 4 + +This inserts a string value associated with a bounding rectangle of (0, 0) - +(15, 20). Note that in the above code we are passing the bounding rectangle +parameter to rtree's :cpp:func:`~mdds::rtree::insert` method as a nested +initializer list, which implicitly gets converted to +:cpp:class:`~mdds::rtree::extent_type`. You can also use the underlying type +directly as follows: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: insert-2 + :end-before: //!code-end: insert-2 + :dedent: 4 + +which inserts a string value associated with a bounding rectangle of (-2, -1) +to (1, 2). You may have noticed that this code also uses extent_type's +:cpp:func:`~mdds::rtree::extent_type::to_string` method which returns a string +representation of the bounding rectangle. This may come in handy when +debugging your code. This method should work as long as the key type used in +your rtree class overloads ``std::ostream``'s ``<<`` operator function. + +Running this code will generate the following output: + +.. code-block:: none + + inserting value for (-2, -1) - (1, 2) + +As :cpp:class:`~mdds::rtree::extent_type` consists of two members called +``start`` and ``end`` both of which are of type +:cpp:class:`~mdds::rtree::point_type`, which in turn contains an array of keys +called ``d`` whose size equals the number of dimensions, you can modify the +extent directly: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: insert-3 + :end-before: //!code-end: insert-3 + :dedent: 4 + +This code will insert a string value associated with a rectangle of (-1, -1) +to (1, 3), and will generate the following output: + +.. code-block:: none + + inserting value for (-1, -1) - (1, 3) + +So far we have only inserted data associated with rectangle shapes, but +:cpp:class:`~mdds::rtree` also allows data associated with points to co-exist +in the same tree. The following code inserts a string value associated with a +point (5, 6): + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: insert-pt-1 + :end-before: //!code-end: insert-pt-1 + :dedent: 4 + +Like the very first rectangle data we inserted, we are passing the point data as +an initializer list of two elements (for 2-dimensional data storage), which will +implicitly get converted to :cpp:class:`~mdds::rtree::point_type` before it +enters into the call. + +Now that some data have been inserted, it's time to run some queries. Let's +query all objects that overlap with a certain rectangular region either +partially or fully. The following code will do just that: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: search-overlap + :end-before: //!code-end: search-overlap + :dedent: 8 + +In this query, we are specifying the search region to be (4, 4) to (7, 7) +which should overlap with the first rectangle data and the first point data. +Indeed, when you execute this code, you will see the following output: + +.. code-block:: none + + value: first rectangle data + value: first point data + +indicating that the query region does overlap with two of the stored values. + +Note that the :cpp:func:`~mdds::rtree::search` method takes exactly two +arguments; the first one specifies the search region while the second two +specifies the type of search to be performed. In the above call we passed +:cpp:type:`~mdds::detail::rtree::search_type`'s ``overlap`` enum value which +picks up all values whose bounding rectangles overlap with the search region +either partially or fully. + +Sometimes, however, you may need to find a value whose bounding rectangle +matches exactly the search region you specify in your query. You can achieve +that by setting the search type to ``match``. + +Here is an example: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: search-match-1 + :end-before: //!code-end: search-match-1 + :dedent: 8 + +The search region is identical to that of the previous example, but the search +type is set to ``match`` instead. Then the next line will count the number of +results and print it out. The output you will see is as follows: + +.. code-block:: none + + number of results: 0 + +indicating that the results are empty. That is expected since none of the +objects stored in the tree have an exact bounding rectangle of (4, 4) - (7, +7). When you change the search region to (0, 0) - (15, 20), however, you'll +get one object back. Here is the actual code: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: search-match-2 + :end-before: //!code-end: search-match-2 + :dedent: 8 + +which is identical to the previous one except for the search region. This is +its output: + +.. code-block:: none + + number of results: 1 + +indicating that it has found exactly one object whose bounding rectangle +exactly matches the search region. + +It's worth mentioning that :cpp:class:`~mdds::rtree` supports storage of +multiple objects with identical bounding rectangle. As such, searching with +the search type of ``match`` can return more than one result. + +As you may have noticed in these example codes, the +:cpp:class:`~mdds::rtree::search_results` object does provide +:cpp:func:`~mdds::rtree::search_results::begin` and +:cpp:func:`~mdds::rtree::search_results::end` methods that return standard +iterators which you can plug into various iterator algorithms from the STL. +Dereferencing the iterator will return a reference to the stored value i.e. +this line: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: iterator-deref + :end-before: //!code-end: iterator-deref + :dedent: 8 + +which immediately follows the previous code block will output: + +.. code-block:: none + + value: first rectangle data + +In addition to accessing the value that the iterator references, you can also +query from the same iterator object the bounding rectangle associated with the +value as well as its depth in the tree by calling its +:cpp:func:`~mdds::rtree::iterator_base::extent` and +:cpp:func:`~mdds::rtree::iterator_base::depth` methods, respectively: + +.. literalinclude:: ../../example/rtree_simple.cpp + :language: C++ + :start-after: //!code-start: iterator-attrs + :end-before: //!code-end: iterator-attrs + :dedent: 8 + +Running this code will produce the following output: + +.. code-block:: none + + value: first rectangle data + extent: (0, 0) - (15, 20) + depth: 1 + +This depth value represents the distance of the node that stores the value +from the root node of the tree, and is technically 0-based. However, you will +never see a depth of 0 in the search results since the root node of a R-tree +is always a directory node, and a directory node only stores other child nodes +and never stores a value, hence it never appears in the search results. diff -Nru mdds-2.1.1/doc/rtree/remove-value.rst mdds-3.1.0/doc/rtree/remove-value.rst --- mdds-2.1.1/doc/rtree/remove-value.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/remove-value.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,49 @@ + +.. highlight:: cpp + +Removing a value from tree +========================== + +Removing an existing value from the tree first requires you to perform a search to +obtain search results, then from the search results get an iterator and advance +it to the position of the value you want to remove. Once you have your iterator +set to the right position, pass it to the :cpp:func:`~mdds::rtree::erase` method +to remove that value. + +Note that you can only remove one value at a time, and the iterator becomes +invalid each time you call the :cpp:func:`~mdds::rtree::erase` method to +remove a value. + +.. note:: + + The iterator becomes invalid each time you call the :cpp:func:`~mdds::rtree::erase` + method to remove a value. + +Here is a contrived example to demonstrate how erasing a value works: + +.. literalinclude:: ../../example/rtree_erase.cpp + :language: C++ + :start-after: //!code-start: remove-value + :end-before: //!code-end: remove-value + :dedent: 4 + +In this code, we are intentionally putting 5 values to the same 2-dimensional +point (1, 1), then removing one of them based on matching criteria (of being +equal to "C"). + +Compiling and running this code will generate the following output: + +.. code-block:: none + + A + B + C + D + E + 'C' has been erased. + A + B + D + E + +which clearly shows that the 'C' has been successfully erased. diff -Nru mdds-2.1.1/doc/rtree/visualize.rst mdds-3.1.0/doc/rtree/visualize.rst --- mdds-2.1.1/doc/rtree/visualize.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/rtree/visualize.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,88 @@ + +.. highlight:: cpp + +Visualize R-tree structure +========================== + +In this section we will illustrate a way to visualize the structure of an R-tree +via :cpp:func:`~mdds::rtree::export_tree()`, which can be useful when you need +to visually inspect the tree structure to see how well balanced it is (or not). + +We will be using the following set of 2-dimensional rectangles as the bounding +rectangles for input values. + +.. figure:: ../_static/images/rtree_bounds_src.png + :align: center + +For input values, we'll simply use linearly increasing series of integer values, +but the values themselves are not the focus of this section, so we'll not focus +much on that. We will also intentionally make the capacity of the directory +nodes smaller so that the tree will split more frequently during insertion even +with smaller number of inputs. + +First, we need to talk about how the concrete rtree type is defined: + +.. literalinclude:: ../../example/rtree_medium.cpp + :language: C++ + :start-after: //!code-start: tree-type + :end-before: //!code-end: tree-type + +The first and second template arguments specify the key and value types to be +both ``int``. This time around, however, we are specifying the third template +argument to be a struct containing several static constant values. These +constant values define various traits of your R-tree, and there are some +constraints you need to be aware of in case you need to define your own custom +traits. Refer to :cpp:class:`~mdds::detail::rtree::default_rtree_traits`, which +is the default traits used when you don't specify a custom one, for the +descriptions of the individual constants that your traits struct is expected to +include as well as their constraints. + +Also be aware that these constants must all be constant expressions with +``constexpr`` specifiers, as some of them are used within ``static_assert`` +declarations, and even those that are currently not used within +``static_assert`` may be used in ``static_assert`` in the future. + +The only part of the custom traits we need to highlight in our current example +is that we are setting the directory node size to 2 to 5 instead of the default +size of 40 to 100, to trigger more node splits and make the tree artificially +deeper. + +Let's move on to the next part of the code: + +.. literalinclude:: ../../example/rtree_medium.cpp + :language: C++ + :start-after: //!code-start: input-data + :end-before: //!code-end: input-data + :dedent: 4 + +This ``rects`` variable holds an array of 2-dimensional rectangle data that +represent the positions and sizes of rectangles shown earlier in this section. +This will be used as bounding rectangles for the input values in the next part +of the code: + +.. literalinclude:: ../../example/rtree_medium.cpp + :language: C++ + :start-after: //!code-start: insert + :end-before: //!code-end: insert + :dedent: 4 + +Here, the tree is instantiated, and the input rectangles are inserted with their +associated values one at a time. Once the tree is populated, the code that +follows will export the structure of the tree as an SVG string, which will +then be saved to a file on disk: + +.. literalinclude:: ../../example/rtree_medium.cpp + :language: C++ + :start-after: //!code-start: export + :end-before: //!code-end: export + :dedent: 4 + +When you open the exported SVG file named **bounds.svg** in a SVG viewer, +you'll see something similar to this: + +.. figure:: ../_static/images/rtree_bounds_tree.png + :align: center + +which depicts not only the bounding rectangles of the inserted values +(the red rectangles), but also the bounding rectangles of the directory +nodes as well (the light green rectangles). diff -Nru mdds-2.1.1/doc/rtree.rst mdds-3.1.0/doc/rtree.rst --- mdds-2.1.1/doc/rtree.rst 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/doc/rtree.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,727 +0,0 @@ - -.. highlight:: cpp - -R-tree -====== - -Overview --------- - -`R-tree `_ is a tree-based data -structure designed for optimal query performance on multi-dimensional spatial -objects with rectangular bounding shapes. The R-tree implementation included -in this library is a variant of R-tree known as `R*-tree -`_ which differs from the original -R-tree in that it may re-insert an object if the insertion of that object -would cause the original target directory to overflow. Such re-insertions -lead to more balanced tree which in turn lead to better query performance, at -the expense of slightly more overhead at insertion time. - -Our implementation of R-tree theoretically supports any number of dimensions -although certain functionalities, especially those related to visualization, -are only supported for 2-dimensional instances. - -R-tree consists of three types of nodes. Value nodes store the values -inserted externally and always sit at the bottom of the tree. Leaf directory -nodes sit directly above the value nodes, and store only value nodes as their -child nodes. The rest are all non-leaf directory nodes which can either store -leaf or non-leaf directory nodes. - - -Quick start ------------ - -Let's go through a very simple example to demonstrate how to use -:cpp:class:`~mdds::rtree`. First, you need to specify a concrete type by -specifying the key type and value type to use:: - - #include - - #include - #include - - // key values are of type double, and we are storing std::string as a - // value for each spatial object. By default, tree becomes 2-dimensional - // object store unless otherwise specified. - using rt_type = mdds::rtree; - -You'll only need to specify the types of key and value here unless you want to -customize other properties of :cpp:class:`~mdds::rtree` including the number -of dimensions. By default, :cpp:class:`~mdds::rtree` sets the number of -dimensions to 2. - -:: - - rt_type tree; - -Instantiating an rtree instance should be no brainer as it requires no input -parameters. Now, let's insert some data:: - - tree.insert({{0.0, 0.0}, {15.0, 20.0}}, "first rectangle data"); - -This inserts a string value associated with a bounding rectangle of (0, 0) - -(15, 20). Note that in the above code we are passing the bounding rectangle -parameter to rtree's :cpp:func:`~mdds::rtree::insert` method as a nested -initializer list, which implicitly gets converted to -:cpp:class:`~mdds::rtree::extent_type`. You can also use the underlying type -directly as follows:: - - rt_type::extent_type bounds({-2.0, -1.0}, {1.0, 2.0}); - std::cout << "inserting value for " << bounds.to_string() << std::endl; - tree.insert(bounds, "second rectangle data"); - -which inserts a string value associated with a bounding rectangle of (-2, -1) -to (1, 2). You may have noticed that this code also uses extent_type's -:cpp:func:`~mdds::rtree::extent_type::to_string` method which returns a string -representation of the bounding rectangle. This may come in handy when -debugging your code. This method should work as long as the key type used in -your rtree class overloads ``std::ostream``'s ``<<`` operator function. - -Running this code will generate the following output: - -.. code-block:: none - - inserting value for (-2, -1) - (1, 2) - -As :cpp:class:`~mdds::rtree::extent_type` consists of two members called -``start`` and ``end`` both of which are of type -:cpp:class:`~mdds::rtree::point_type`, which in turn contains an array of keys -called ``d`` whose size equals the number of dimensions, you can modify the -extent directly:: - - bounds.start.d[0] = -1.0; // Change the first dimension value of the start rectangle point. - bounds.end.d[1] += 1.0; // Increment the second dimension value of the end rectangle point. - std::cout << "inserting value for " << bounds.to_string() << std::endl; - tree.insert(bounds, "third rectangle data"); - -This code will insert a string value associated with a rectangle of (-1, -1) -to (1, 3), and will generate the following output: - -.. code-block:: none - - inserting value for (-1, -1) - (1, 3) - -So far we have only inserted data associated with rectangle shapes, but -:cpp:class:`~mdds::rtree` also allows data associated with points to co-exist -in the same tree. The following code inserts a string value associated with a -point (5, 6):: - - tree.insert({5.0, 6.0}, "first point data"); - -Like the verfy first rectangle data we've inserted, we are passing the point -data as an initializer list of two elements (for 2-dimensional data storage), -which will implicitly get converted to :cpp:class:`~mdds::rtree::point_type` -before it enters into the call. - -Now that some data have been inserted, it's time to run some queries. Let's -query all objects that overlap with a certain rectangular region either -partially or fully. The following code will do just that:: - - // Search for all objects that overlap with a (4, 4) - (7, 7) rectangle. - auto results = tree.search({{4.0, 4.0}, {7.0, 7.0}}, rt_type::search_type::overlap); - - for (const std::string& v : results) - std::cout << "value: " << v << std::endl; - -In this query, we are specifying the search region to be (4, 4) to (7, 7) -which should overlap with the first rectangle data and the first point data. -Indeed, when you execute this code, you will see the following output: - -.. code-block:: none - - value: first rectangle data - value: first point data - -indicating that the query region does overlap with two of the stored values - -Note that the :cpp:func:`~mdds::rtree::search` method takes exactly two -arguments; the first one specifies the search region while the second two -specifies the type of search to be performed. In the above call we passed -:cpp:type:`~mdds::detail::rtree::search_type`'s ``overlap`` enum value which -picks up all values whose bounding rectangles overlap with the search region -either partially or fully. - -Sometimes, however, you may need to find a value whose bounding rectangle -matches exactly the search region you specify in your query. You can achieve -that by setting the search type to ``match``. - -Here is an example:: - - // Search for all objects whose bounding rectangles are exactly (4, 4) - (7, 7). - auto results = tree.search({{4.0, 4.0}, {7.0, 7.0}}, rt_type::search_type::match); - std::cout << "number of results: " << std::distance(results.begin(), results.end()) << std::endl; - -The search region is identical to that of the previous example, but the search -type is set to ``match`` instead. Then the next line will count the number of -results and print it out. The output you will see is as follows: - -.. code-block:: none - - number of results: 0 - -indicating that the results are empty. That is expected since none of the -objects stored in the tree have an exact bounding rectangle of (4, 4) - (7, -7). When you change the search region to (0, 0) - (15, 20), however, you'll -get one object back. Here is the actual code:: - - // Search for all objects whose bounding rectangles are exactly (0, 0) - (15, 20). - auto results = tree.search({{0.0, 0.0}, {15.0, 20.0}}, rt_type::search_type::match); - std::cout << "number of results: " << std::distance(results.begin(), results.end()) << std::endl; - -which is identical to the previous one except for the search resion. This is -its output: - -.. code-block:: none - - number of results: 1 - -indicating that it has found exactly one object whose bounding rectangle -exactly matches the search region. - -It's worth mentioning that :cpp:class:`~mdds::rtree` supports storage of -multiple objects with identical bounding rectangle. As such, searching with -the search type of ``match`` can return more than one result. - -As you may have noticed in these example codes, the -:cpp:class:`~mdds::rtree::search_results` object does provide -:cpp:func:`~mdds::rtree::search_results::begin` and -:cpp:func:`~mdds::rtree::search_results::end` methods that return standard -iterators which you can plug into various iterator algorithms from the STL. -Dereferencing the iterator will return a reference to the stored value i.e. -this line:: - - std::cout << "value: " << *results.begin() << std::endl; - -which immediately comes after the previous search will output: - -.. code-block:: none - - value: first rectangle data - -In addition to accessing the value that the iterator references, you can also -query from the same iterator object the bounding rectangle associated with the -value as well as its depth in the tree by calling its -:cpp:func:`~mdds::rtree::iterator_base::extent` and -:cpp:func:`~mdds::rtree::iterator_base::depth` methods, respectively, as in -the following code:: - - auto it = results.begin(); - std::cout << "value: " << *it << std::endl; - std::cout << "extent: " << it.extent().to_string() << std::endl; - std::cout << "depth: " << it.depth() << std::endl; - -Running this code will produce the following output: - -.. code-block:: none - - value: first rectangle data - extent: (0, 0) - (15, 20) - depth: 1 - -A depth value represents the distance of the node where the value is stored -from the root node of the tree, and is technically 0-based. However, you will -never see a depth of 0 in the search results since the root node of a R-tree -is always a directory node, and a directory node only stores other child nodes -and never a value (hence never appears in the search results). - - -Removing a value from tree --------------------------- - -Removing an existing value from the tree first requires you to perform the -search to obtian search results, then from the search results get the iterator -and advance it to the position of the value you wish to remove. Once you have -your iterator set to the right position, pass it to the -:cpp:func:`~mdds::rtree::erase` method to remove that value. - -Note that you can only remove one value at a time, and the iterator becomes -invalid each time you call the :cpp:func:`~mdds::rtree::erase` method to -remove a value. - -Here is a contrived example to demonstrate how erasing a value works:: - - #include - - #include - #include - - int main() - { - using rt_type = mdds::rtree; - - rt_type tree; - - // Insert multiple values at the same point. - tree.insert({1, 1}, "A"); - tree.insert({1, 1}, "B"); - tree.insert({1, 1}, "C"); - tree.insert({1, 1}, "D"); - tree.insert({1, 1}, "E"); - - // This should return all five values. - auto results = tree.search({1, 1}, rt_type::search_type::match); - - for (const std::string& v : results) - std::cout << v << std::endl; - - // Erase "C". - for (auto it = results.begin(); it != results.end(); ++it) - { - if (*it == "C") - { - tree.erase(it); - break; // This invalidates the iterator. Bail out. - } - } - - std::cout << "'C' has been erased." << std::endl; - - // Now this should only return A, B, D and E. - results = tree.search({1, 1}, rt_type::search_type::match); - - for (const std::string& v : results) - std::cout << v << std::endl; - - return EXIT_SUCCESS; - } - -In this code, we are intentionally putting 5 values to the same 2-dimensional -point (1, 1), then removing one of them based on matching criteria (of being -equal to "C"). - -Compiling and running this code will generate the following output: - -.. code-block:: none - - A - B - C - D - E - 'C' has been erased. - A - B - D - E - -which clearly shows that the 'C' has been successfully erased. - - -Visualize R-tree structure --------------------------- - -In this section we will illustrate a way to visualize an R-tree structure via -:cpp:func:`~mdds::rtree::export_tree` method, which can be useful when you -need to visually inspect the tree structure to see how well balanced it is (or -not). - -We will be using the following set of 2-dimensional rectangles as the bounding -rectangles for input values. - -.. figure:: _static/images/rtree_bounds_src.png - :align: center - -For input values, we'll simply use linearly increasing series of integer -values, but the values themselves are not the focus of this section, and we'll -not talk much about that. We will also intentionally make the capacity of -directory nodes smaller so that the tree will split more frequently during -insertion even for smaller number of inputs. - -Now, let's take a look at the code:: - - #include - - #include - #include - - // Make the node capacity intentionally small. - struct tiny_trait_2d - { - constexpr static size_t dimensions = 2; - constexpr static size_t min_node_size = 2; - constexpr static size_t max_node_size = 5; - constexpr static size_t max_tree_depth = 100; - - constexpr static bool enable_forced_reinsertion = true; - constexpr static size_t reinsertion_size = 2; - }; - - using rt_type = mdds::rtree; - - int main() - { - // 2D rectangle with the top-left position (x, y), width and height. - struct rect - { - int x; - int y; - int w; - int h; - }; - - std::vector rects = - { - { 3731, 2433, 1356, 937 }, - { 6003, 3172, 1066, 743 }, - { 4119, 6403, 825, 1949 }, - { 10305, 2315, 776, 548 }, - { 13930, 5468, 1742, 626 }, - { 8614, 4107, 2709, 1793 }, - { 14606, 1887, 5368, 1326 }, - { 17990, 5196, 1163, 1911 }, - { 6728, 7881, 3676, 1210 }, - { 14704, 9789, 5271, 1092 }, - { 4071, 10723, 4739, 898 }, - { 11755, 9010, 1357, 2806 }, - { 13978, 4068, 776, 509 }, - { 17507, 3717, 777, 471 }, - { 20358, 6092, 824, 1093 }, - { 6390, 4535, 1066, 1715 }, - { 13978, 7182, 2516, 1365 }, - { 17942, 11580, 2854, 665 }, - { 9919, 10450, 873, 1716 }, - { 5568, 13215, 7446, 509 }, - { 7357, 15277, 3145, 3234 }, - { 3539, 12592, 631, 509 }, - { 4747, 14498, 825, 626 }, - { 4554, 16913, 969, 1443 }, - { 12771, 14693, 2323, 548 }, - { 18714, 8193, 2372, 586 }, - { 22292, 2743, 487, 1638 }, - { 20987, 17535, 1163, 1249 }, - { 19536, 18859, 632, 431 }, - { 19778, 15394, 1356, 626 }, - { 22969, 15394, 631, 2066 }, - }; - - rt_type tree; - - // Insert the rectangle objects into the tree. - int value = 0; - for (const auto& rect : rects) - tree.insert({{rect.x, rect.y}, {rect.x + rect.w, rect.y + rect.h}}, value++); - - // Export the tree structure as a SVG for visualization. - std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); - std::ofstream fout("bounds.svg"); - fout << tree_svg; - - return EXIT_SUCCESS; - } - -First, we need to talk about how the concrete rtree type is instantiated:: - - // Make the node capacity intentionally small. - struct tiny_trait_2d - { - constexpr static size_t dimensions = 2; - constexpr static size_t min_node_size = 2; - constexpr static size_t max_node_size = 5; - constexpr static size_t max_tree_depth = 100; - - constexpr static bool enable_forced_reinsertion = true; - constexpr static size_t reinsertion_size = 2; - }; - - using rt_type = mdds::rtree; - -The first and second template arguments specify the key and value types to be -both ``int``. This time around, however, we are passing a third template -argument which is a struct containing several static constant values. These -constant values define certain characteristics of your R-tree, and there are -some restrictions you need to be aware of in case you need to use your own -custom trait for your R-tree. Refer to -:cpp:class:`~mdds::detail::rtree::default_rtree_traits`, which is the default -trait used when you don't specify your own, for the descriptions of the -individual constants that your trait struct is expected to have as well as -restrictions that you must be aware of. - -Also be aware that these constants must all be constant expressions with -``constexpr`` specifiers, as some of them are used within ``static_assert`` -declarations, and even those that are currently not used within -``static_assert`` may be used in ``static_assert`` in the future. - -As far as our current example goes, the only part of the custom trait we need -to highlight is that we are setting the directory node size to 2-to-5 instead -of the default size of 40-to-100, to trigger more node splits and make the -tree artificially deeper. - -Let's move on to the next part of the code:: - - // 2D rectangle with the top-left position (x, y), width and height. - struct rect - { - int x; - int y; - int w; - int h; - }; - - std::vector rects = - { - { 3731, 2433, 1356, 937 }, - { 6003, 3172, 1066, 743 }, - { 4119, 6403, 825, 1949 }, - { 10305, 2315, 776, 548 }, - { 13930, 5468, 1742, 626 }, - { 8614, 4107, 2709, 1793 }, - { 14606, 1887, 5368, 1326 }, - { 17990, 5196, 1163, 1911 }, - { 6728, 7881, 3676, 1210 }, - { 14704, 9789, 5271, 1092 }, - { 4071, 10723, 4739, 898 }, - { 11755, 9010, 1357, 2806 }, - { 13978, 4068, 776, 509 }, - { 17507, 3717, 777, 471 }, - { 20358, 6092, 824, 1093 }, - { 6390, 4535, 1066, 1715 }, - { 13978, 7182, 2516, 1365 }, - { 17942, 11580, 2854, 665 }, - { 9919, 10450, 873, 1716 }, - { 5568, 13215, 7446, 509 }, - { 7357, 15277, 3145, 3234 }, - { 3539, 12592, 631, 509 }, - { 4747, 14498, 825, 626 }, - { 4554, 16913, 969, 1443 }, - { 12771, 14693, 2323, 548 }, - { 18714, 8193, 2372, 586 }, - { 22292, 2743, 487, 1638 }, - { 20987, 17535, 1163, 1249 }, - { 19536, 18859, 632, 431 }, - { 19778, 15394, 1356, 626 }, - { 22969, 15394, 631, 2066 }, - }; - -This ``rects`` variable holds an array of 2-dimensional rectangle data that -represent the positions and sizes of rectangles shown earlier in this section. -This will be used as bounding rectangles for the input values in the next part -of the code:: - - rt_type tree; - - // Insert the rectangle objects into the tree. - int value = 0; - for (const auto& rect : rects) - tree.insert({{rect.x, rect.y}, {rect.x + rect.w, rect.y + rect.h}}, value++); - -Here, the tree is instantiated, and the rectangles are inserted with their -associated values one at a time. Once the tree is populated, the code that -follows will export the structure of the tree as an SVG string, which will -then be saved to a file on disk:: - - // Export the tree structure as a SVG for visualization. - std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); - std::ofstream fout("bounds.svg"); - fout << tree_svg; - -When you open the exported SVG file named **bounds.svg** in a SVG viewer, -you'll see something similar to this: - -.. figure:: _static/images/rtree_bounds_tree.png - :align: center - -which depicts not only the bounding rectangles of the inserted values -(the red rectangles), but also the bounding rectangles of the directory -nodes as well (the light green rectangles). - - -Bulk-loading data ------------------ - -In this section we will explore on how to bulk-load data into an -:cpp:class:`~mdds::rtree` instance via rtree's own -:cpp:class:`~mdds::rtree::bulk_loader` class. In this example, we'll be using -the same custom trait we've used in the previous section in order to -artificially promote the rate of node splits. The first part of the code:: - - #include - - #include - #include - - // Make the node capacity intentionally small. - struct tiny_trait_2d - { - constexpr static size_t dimensions = 2; - constexpr static size_t min_node_size = 2; - constexpr static size_t max_node_size = 5; - constexpr static size_t max_tree_depth = 100; - - constexpr static bool enable_forced_reinsertion = true; - constexpr static size_t reinsertion_size = 2; - }; - - using rt_type = mdds::rtree; - -is pretty much identical to the example in the last section. The next part of -the code defines what bounding rectangles to be inserted. Here, we are using -a different set of rectangles than the previous example to illustrate the -difference between a series of normal insertions and bulk-loading:: - - // 2D rectangle with the top-left position (x, y), width and height. - struct rect - { - int x; - int y; - int w; - int h; - }; - - std::vector rects = - { - { 3538, 9126, 1908, 1908 }, - { 34272, 52053, 2416, 2543 }, - { 32113, 9761, 2416, 638 }, - { 16493, 16747, 7369, 2289 }, - { 29192, 23732, 3432, 2035 }, - { 35797, 17000, 1781, 892 }, - { 15857, 29319, 2162, 1654 }, - { 5825, 24239, 3559, 8512 }, - { 9127, 46846, 2543, 1019 }, - { 7094, 54338, 5210, 892 }, - { 18779, 39734, 3813, 10417 }, - { 32749, 35923, 2289, 2924 }, - { 26018, 31098, 257, 2797 }, - { 6713, 37066, 2924, 1146 }, - { 19541, 3157, 3305, 1146 }, - { 21953, 10904, 4448, 892 }, - { 15984, 24240, 5210, 1273 }, - { 8237, 15350, 2670, 2797 }, - { 17001, 13826, 4067, 1273 }, - { 30970, 13826, 3940, 765 }, - { 9634, 6587, 1654, 1781 }, - { 38464, 47099, 511, 1400 }, - { 20556, 54085, 1400, 1527 }, - { 37575, 24113, 1019, 765 }, - { 20429, 21064, 1146, 1400 }, - { 31733, 4427, 2543, 638 }, - { 2142, 27161, 1273, 7369 }, - { 3920, 43289, 8131, 1146 }, - { 14714, 34272, 1400, 4956 }, - { 38464, 41258, 1273, 1273 }, - { 35542, 45703, 892, 1273 }, - { 25891, 50783, 1273, 5083 }, - { 35415, 28431, 2924, 1781 }, - { 15476, 7349, 1908, 765 }, - { 12555, 11159, 1654, 2035 }, - { 11158, 21445, 1908, 2416 }, - { 23350, 28049, 3432, 892 }, - { 28684, 15985, 2416, 4321 }, - { 24620, 21953, 1654, 638 }, - { 30208, 30716, 2670, 2162 }, - { 26907, 44179, 2797, 4067 }, - { 21191, 35416, 2162, 1019 }, - { 27668, 38717, 638, 3178 }, - { 3666, 50528, 2035, 1400 }, - { 15349, 48750, 2670, 1654 }, - { 28430, 7221, 2162, 892 }, - { 4808, 3158, 2416, 1273 }, - { 38464, 3666, 1527, 1781 }, - { 2777, 20937, 2289, 1146 }, - { 38209, 9254, 1908, 1781 }, - { 2269, 56497, 2289, 892 }, - }; - -As with the previous example, each line contains the top-left position as well -as the size of a rectangle. We are now going to insert these rectangles in -two different ways. - -First, we insert them via normal :cpp:func:`~mdds::rtree::insert` method:: - - void load_tree() - { - rt_type tree; - - // Insert the rectangle objects into the tree. - int value = 0; - for (const auto& rect : rects) - tree.insert({{rect.x, rect.y}, {rect.x + rect.w, rect.y + rect.h}}, value++); - - // Export the tree structure as a SVG for visualization. - std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); - std::ofstream fout("bounds2.svg"); - fout << tree_svg; - } - -This code should look familiar since it's nearly identical to the code in the -previous section. After the insertion is done, we export the tree as an SVG -to visualize its structure. - -Next, we insert the same set of rectangles via -:cpp:class:`~mdds::rtree::bulk_loader`:: - - void bulkload_tree() - { - rt_type::bulk_loader loader; - - // Insert the rectangle objects into the tree. - int value = 0; - for (const auto& rect : rects) - loader.insert({{rect.x, rect.y}, {rect.x + rect.w, rect.y + rect.h}}, value++); - - // Start bulk-loading the tree. - rt_type tree = loader.pack(); - - // Export the tree structure as a SVG for visualization. - std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); - std::ofstream fout("bounds2-bulkload.svg"); - fout << tree_svg; - } - -Inserting via :cpp:class:`~mdds::rtree::bulk_loader` shouldn't be too -different than inserting via rtree's own insert methods. The only -difference is that you instantiate a -:cpp:class:`~mdds::rtree::bulk_loader` instance to insert all your data -to it, then call its :cpp:func:`~mdds::rtree::bulk_loader::pack` method -at the end to construct the final :cpp:class:`~mdds::rtree` instance. - -When the insertion is done and the tree instance created, we are once again -exporting its structure to an SVG file for visualization. - -There are primarily two advantages to using -:cpp:class:`~mdds::rtree::bulk_loader` to load data. First, unlike the -normal insertion, bulk-loading does not trigger re-insertion nor node -splits on the fly. Second, a tree created from bulk loader is typically -well balanced than if you insert the same data through normal insertion. -That is because the bulk loader sorts the data with respect to their -bounding rectangles ahead of time and partition them evenly. The tree -is then built from the bottom-up. You can visually see the effect of -this when comparing the two trees built in our current example. - -The first one is from the tree built via normal insertion: - -.. figure:: _static/images/rtree_bounds2_tree.png - :align: center - -The top part of the picture looks very "busy" indicated by a darker -green area representative of more directory nodes overlaping with each -other. In general, the rectangles look bigger and show higher degree of -overlaps. - -This one, on the other hand, is from the tree built with the same data -set but through bulk-loading: - -.. figure:: _static/images/rtree_bounds2_tree_bulkload.png - :align: center - -The rectangles generally look smaller and show much less overlaps than the -previous picture, which is considered to be a more balanced R-tree structure. - - -API Reference -------------- - -.. doxygenclass:: mdds::rtree - :members: - -.. doxygenstruct:: mdds::detail::rtree::default_rtree_traits - :members: - -.. doxygenstruct:: mdds::detail::rtree::integrity_check_properties - :members: - -.. doxygenenum:: mdds::detail::rtree::export_tree_type - :project: mdds - -.. doxygenenum:: mdds::detail::rtree::search_type - :project: mdds diff -Nru mdds-2.1.1/doc/segment_tree/api.rst mdds-3.1.0/doc/segment_tree/api.rst --- mdds-2.1.1/doc/segment_tree/api.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree/api.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,7 @@ + +API Reference +============= + +.. doxygenclass:: mdds::segment_tree + :members: + diff -Nru mdds-2.1.1/doc/segment_tree/index.rst mdds-3.1.0/doc/segment_tree/index.rst --- mdds-2.1.1/doc/segment_tree/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree/index.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,21 @@ +.. highlight:: cpp + +Segment Tree +============ + +`Segment tree `_ is a data structure +designed for storing one-dimensional intervals or segments, either overlapping +or non-overlapping. It is useful for detecting all the segments that contain a +specific point. Each segment has start and end positions where the start +position is inclusive while the end position is not. The version of segment +tree implemented in mdds allows associating a value with each segment so that +you can use it as an associative container. + +.. toctree:: + :maxdepth: 1 + + quickstart.rst + remove-segments.rst + perf.rst + api.rst + diff -Nru mdds-2.1.1/doc/segment_tree/perf.rst mdds-3.1.0/doc/segment_tree/perf.rst --- mdds-2.1.1/doc/segment_tree/perf.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree/perf.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,34 @@ + +Performance considerations +========================== + +Given a set of segments, the cost of building a tree increases with the number +of unique start and end positions of all of the segments combined, as that +determines how deep the tree has to be. The tree building process involves +building the tree structure itself, followed by the "insertions" of individual +segments into the tree. The insertion of a segment involves descending the tree +from the root node and marking the appropriate nodes. This gets repeated for +the number of segments to be inserted. This process is moderately expensive. + +The search process, on the other hand, typically consists of two steps: 1) +retrieving the results set, and 2) iterating through the results. Step 1 is +proportional to the depth of the tree, and should be a quick process even with a +sufficiently large number of segments. Step 2, on the other hand, is +proportional to the number of the results one needs to iterate through, +regardless of the size of the results set. + +Removing a segment can be considerably expensive especially when a large number +of segments need to be removed from the tree. Excessive use of either +:cpp:func:`~mdds::segment_tree::erase()` or +:cpp:func:`~mdds::segment_tree::erase_if()` is therefore not recommended. Use +them sparingly. + +Given these performance characteristics of :cpp:class:`~mdds::segment_tree`, an +ideal use case for this data structure would be one where: + +* you already have all or most of the segments known ahead of time, +* you can only build the tree once, and mostly need to run queries afterward, and +* you need to remove segments only in some rare occasions, or none at all. + +Note that occasionally updating the data set and re-building the tree is +reasonable, as long as your use case can tolerate the cost of building the tree. diff -Nru mdds-2.1.1/doc/segment_tree/quickstart.rst mdds-3.1.0/doc/segment_tree/quickstart.rst --- mdds-2.1.1/doc/segment_tree/quickstart.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree/quickstart.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,122 @@ + +Quick start +=========== + +In this section we are going to demonstrate how to use +:cpp:class:`~mdds::segment_tree` with some code examples. First, let's include +some headers: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: header + :end-before: //!code-end: header + +The ```` header defines the +:cpp:class:`mdds::segment_tree` template class, and we need to include the +```` so that we can use ``std::string`` as its value type. We also need +the ```` header to write some outputs. The next step is to define a +type alias for the concrete type instance of :cpp:class:`~mdds::segment_tree`: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + +Here, we are using ``long`` as the key type and ``std::string`` as the value type. +Let's create an instance of this type and insert some segments with values: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: insert + :end-before: //!code-end: insert + :dedent: 4 + +We have created a new instance called ``tree``, and inserted five segment values +into it using the :cpp:func:`~mdds::segment_tree::insert()` method, which takes: + +* start position of the segment, +* end position of the segment, and +* the value associated with the segment + +as its arguments. As mentioned earlier, the start position of a segment is +inclusive but the end position isn't. Once all the segment data have been +inserted, the next step is to build the tree by simply calling the +:cpp:func:`~mdds::segment_tree::build_tree()` method: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: build + :end-before: //!code-end: build + :dedent: 4 + +Building the tree is required before you can perform any queries. Now that the +tree is built, let's run some queries. But first we are going to define the +following helper function: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: search-and-print + :end-before: //!code-end: search-and-print + +This helper function takes the segment tree instance and a search point, +performs a search by calling :cpp:func:`~mdds::segment_tree::search()`, and +iterates through and prints its results. The return value from +:cpp:func:`~mdds::segment_tree::search()` is of type +:cpp:class:`~mdds::segment_tree::search_results`, which provides the +:cpp:func:`~mdds::segment_tree::search_results::size()` method to quickly find +the total number of the results. It also allows you to iterate through the +results through its :cpp:func:`~mdds::segment_tree::search_results::begin()` +:cpp:func:`~mdds::segment_tree::search_results::end()` methods, or simply by +plugging it into a `range-based for loop +`_ as you see in this +function. + +With this help function in place, let's find all the segments that contain 5 by +calling: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: search-5 + :end-before: //!code-end: search-5 + :dedent: 4 + +which will print the following output: + +.. code-block:: none + + -- + search at 5 + number of results: 3 + range: [2:15); value: B + range: [0:10); value: A + range: [5:22); value: D + +It's worth pointing out that the results here don't include the "C" segment, +which extends from -2 to 5, because the end point is not inclusive. Given a +search point of ``x``, For a segment to be included in the results, it must +satisfy ``start <= x < end``. On the other hand, the results *do* include the +"D" segment because the start point *is* inclusive. + +Let's do another search, and this time let's find all the segments that contain +0: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: search-0 + :end-before: //!code-end: search-0 + :dedent: 4 + +This will print the following output: + +.. code-block:: none + + -- + search at 0 + number of results: 2 + range: [-2:5); value: C + range: [0:10); value: A + +The results look just about right. As an aside, it is entirely safe to call +:cpp:func:`~mdds::segment_tree::search()` with points that are below the minimum +position or above the maximum position in the tree; you will simply get empty +results in such cases. diff -Nru mdds-2.1.1/doc/segment_tree/remove-segments.rst mdds-3.1.0/doc/segment_tree/remove-segments.rst --- mdds-2.1.1/doc/segment_tree/remove-segments.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree/remove-segments.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,98 @@ + +Removing segments +================= + +So far we have covered how to insert segment values and perform searches, but +you can also remove values from the tree. There are two ways to remove values: +one is to use an iterator from the search results object, and another is to +specify a match condition predicate and remove all values that the predicate +evaluates to true. + +Removing with iterator +---------------------- + +Let's first cover how to remove a value with an iterator. Our goal here is to +remove the segment value "A" that extends from 0 to 10. To obtain an iterator, +you first need to perform a search then get an iterator from the results object. +Once you have an iterator, iterate through the result set until it finds the +right iterator position, then call :cpp:func:`~mdds::segment_tree::erase()` to +remove that value, as the following code illustrates: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: erase-by-iterator + :end-before: //!code-end: erase-by-iterator + :dedent: 4 + +Let's run the same search with the search point of 5: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: search-5-after-erase-by-iterator + :end-before: //!code-end: search-5-after-erase-by-iterator + :dedent: 4 + +This time it will produce: + +.. code-block:: none + + -- + search at 5 + number of results: 2 + range: [2:15); value: B + range: [5:22); value: D + +As you can see, the "A" segment has been removed. + +One thing to note is that removing a value does *not* invalidate the tree +itself; you can continue to perform follow-up searches without having to +re-build the tree. However, *it does invalidate the iterators*, which +necessitates you to exit your iteration once a value has been removed using an +iterator. Note that the search results object itself remains valid even after +the value removal. + +Even though removing a value does not invalidate the tree, if you remove a large +enough number of values re-building it may reduce the overall size of the tree, +as the size of the tree is dependent upon the number of unique end points of all +the stored segments. And smaller the tree, the better the search performance. + +Removing with predicate +----------------------- + +Another way to remove values is to call :cpp:func:`~mdds::segment_tree::erase_if()` +with a predicate that matches the value to be removed. The following code removes +all the segments that contains 5: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: erase-by-predicate + :end-before: //!code-end: erase-by-predicate + :dedent: 4 + +The predicate function takes three parameters that are start position, end +position, and a value of a segment. Running this code produces the following +output: + +.. code-block:: none + + -- + 3 segments have been removed + +indicating that a total of 3 segments have been removed with this call. Running +the same search again after the value removal: + +.. literalinclude:: ../../example/segment_tree.cpp + :language: C++ + :start-after: //!code-start: search-5-after-erase-by-predicate + :end-before: //!code-end: search-5-after-erase-by-predicate + :dedent: 4 + +yields the following output: + +.. code-block:: none + + -- + search at 5 + number of results: 0 + +indicating that the tree no longer stores segments that contain 5. diff -Nru mdds-2.1.1/doc/segment_tree.rst mdds-3.1.0/doc/segment_tree.rst --- mdds-2.1.1/doc/segment_tree.rst 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/doc/segment_tree.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -.. highlight:: cpp - -Segment Tree -============ - -API Reference -------------- - -.. doxygenclass:: mdds::segment_tree - :members: - diff -Nru mdds-2.1.1/doc/sorted_string_map/api.rst mdds-3.1.0/doc/sorted_string_map/api.rst --- mdds-2.1.1/doc/sorted_string_map/api.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/sorted_string_map/api.rst 2024-01-10 23:45:35.000000000 +0000 @@ -0,0 +1,11 @@ + +API Reference +============= + +.. doxygenclass:: mdds::sorted_string_map + :members: + +.. doxygenclass:: mdds::ssmap::linear_key_finder + +.. doxygenclass:: mdds::ssmap::hash_key_finder + diff -Nru mdds-2.1.1/doc/sorted_string_map/index.rst mdds-3.1.0/doc/sorted_string_map/index.rst --- mdds-2.1.1/doc/sorted_string_map/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/sorted_string_map/index.rst 2024-01-10 23:45:35.000000000 +0000 @@ -0,0 +1,20 @@ + +Sorted String Map +================= + +Sorted string map is an immutable associative container that provides an +efficient way to map string keys to values of a user-specified type. Both keys +and values must be known at compile time and the key-value entries must be +sorted by the keys in ascending order. The lookup algorithm takes advantage of +the pre-sorted entries and performs binary search to find the value from a key. + +Besides the minimal amount of memory required to store the size and memory +address of the caller-provided key-value entries and a few extra data, it does +not allocate any additional memory; it simply re-uses the caller-provided +key-value entries in all of its operations. + +.. toctree:: + :maxdepth: 1 + + quickstart.rst + api.rst diff -Nru mdds-2.1.1/doc/sorted_string_map/quickstart.rst mdds-3.1.0/doc/sorted_string_map/quickstart.rst --- mdds-2.1.1/doc/sorted_string_map/quickstart.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/sorted_string_map/quickstart.rst 2024-01-10 23:45:35.000000000 +0000 @@ -0,0 +1,133 @@ +.. highlight:: cpp + +Quick Start +=========== + +Let's go over how to use :cpp:class:`~mdds::sorted_string_map` with a code +example. In this example, we will define an enum type that includes all 50 US +states, and associate them with their names as string keys. + +Let's include some headers first: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: header + :end-before: //!code-end: header + :dedent: 0 + +We include ```` to make the +:cpp:class:`~mdds::sorted_string_map` class available, and ```` so +that we can print some debug statements. + +Next, let's define the enum type for the US states: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: enum + :end-before: //!code-end: enum + :dedent: 0 + +This enum type enumerates values for all 50 states plus ``unknown`` as its first +member. This value is inplicitly assigned the value of 0 by virtue of it being +the first member, and we will be using it as the null value for the container. +A null value is the value returned by the +:cpp:func:`~mdds::sorted_string_map::find()` method when it fails to find an +associated value for the key passed by the caller. It is required during +construction. + +The next step is to define a concrete type: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + :dedent: 0 + +We are defining a type alias named ``us_state_map_type`` that uses +:cpp:class:`~mdds::sorted_string_map` with ``us_state_t`` as its value type. + +Once the concrete type is defined, we can then define the key-value entries as +a static array of type :cpp:type:`mdds::sorted_string_map::entry_type`: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: entries + :end-before: //!code-end: entries + :dedent: 0 + +Each entry contains two members of types :cpp:class:`std::string_view` and +:cpp:type:`mdds::sorted_string_map::value_type`, respectively. Here, you must +ensure that these entries are sorted alphabetically by the keys in ascending +order. + +Now we can construct an instance of this container. To create an instance, you +must pass the pointer to the key-value entries array, the size of the array, and +the null value: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: init + :end-before: //!code-end: init + :dedent: 4 + +We are marking it as a const instance since it's immutable; its state won't +change once it is constructed. + +Now we can perform some lookups by calling the +:cpp:func:`~mdds::sorted_string_map::find()` method: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: find + :end-before: //!code-end: find + :dedent: 4 + +Running this code generates the following output: + +.. code-block:: none + + virginia? true + north_carolina? true + +When calling :cpp:func:`~mdds::sorted_string_map::find()` with a string key not +included in the pre-defined entries, it will return the null value: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: find-null + :end-before: //!code-end: find-null + :dedent: 4 + +Running this code generates the following output: + +.. code-block:: none + + unknown? true + +You can also perform reverse lookup of finding a key from a value by calling the +:cpp:func:`~mdds::sorted_string_map::find_key()` method: + +.. literalinclude:: ../../example/sorted_string_map.cpp + :language: C++ + :start-after: //!code-start: find-key + :end-before: //!code-end: find-key + :dedent: 4 + +Running this code generates the following output: + +.. code-block:: none + + key for rhode_island: Rhode Island + +Note however, that :cpp:func:`~mdds::sorted_string_map::find_key()` by default +performs linear search through the pre-defined entries to find the key from the +value, so its runtime performance is not as efficient as that of +:cpp:func:`~mdds::sorted_string_map::find()`, which performs binary search. + +The algorithm used in :cpp:func:`~mdds::sorted_string_map::find_key()` depends +on the second template argument passed to the +:cpp:class:`~mdds::sorted_string_map` class, which by default is assigned the +type :cpp:class:`mdds::ssmap::linear_key_finder`. In case linear search is not +desirable, one can specify :cpp:class:`mdds::ssmap::hash_key_finder` as the +second template argument to switch to a hash-table based lookup algorithm +instead. diff -Nru mdds-2.1.1/doc/sorted_string_map.rst mdds-3.1.0/doc/sorted_string_map.rst --- mdds-2.1.1/doc/sorted_string_map.rst 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/doc/sorted_string_map.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -.. highlight:: cpp - -Sorted String Map -================= - -API Reference -------------- - -.. doxygenclass:: mdds::sorted_string_map - :members: - diff -Nru mdds-2.1.1/doc/trie_map/api.rst mdds-3.1.0/doc/trie_map/api.rst --- mdds-2.1.1/doc/trie_map/api.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/api.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,60 @@ + +API Reference +============= + +Containers +---------- + +mdds::trie_map +^^^^^^^^^^^^^^ + +.. doxygenclass:: mdds::trie_map + :members: + +mdds::packed_trie_map +^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenclass:: mdds::packed_trie_map + :members: + +Value Serializers +----------------- + +mdds::trie::value_serializer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenstruct:: mdds::trie::value_serializer + :members: + +mdds::trie::numeric_value_serializer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenstruct:: mdds::trie::numeric_value_serializer + :members: + +mdds::trie::variable_value_serializer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenstruct:: mdds::trie::variable_value_serializer + :members: + +mdds::trie::numeric_sequence_value_serializer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenstruct:: mdds::trie::numeric_sequence_value_serializer + :members: + + +Other Types +----------- + +mdds::trie::default_traits +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenstruct:: mdds::trie::default_traits + :members: + +mdds::trie::dump_structure_type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenenum:: mdds::trie::dump_structure_type diff -Nru mdds-2.1.1/doc/trie_map/direct-packed-trie-map.rst mdds-3.1.0/doc/trie_map/direct-packed-trie-map.rst --- mdds-2.1.1/doc/trie_map/direct-packed-trie-map.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/direct-packed-trie-map.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,50 @@ + +Using packed_trie_map directly +============================== + +In the previous example, we showed a way to create an instance of :cpp:class:`~mdds::packed_trie_map` +from a populated instance of :cpp:class:`~mdds::trie_map`. There is also a way +to instantiate and populate an instance of :cpp:class:`~mdds::packed_trie_map` +directly, and that is what we will cover in this section. + +First, declare the type: + +.. literalinclude:: ../../example/packed_trie_map.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + :dedent: 4 + +Once again, we are using ``std::string`` as its key, and ``int`` as its value +type. The next step is to prepare its entries ahead of time: + +.. literalinclude:: ../../example/packed_trie_map.cpp + :language: C++ + :start-after: //!code-start: populate + :end-before: //!code-end: populate + :dedent: 4 + +We need to do this since :cpp:class:`~mdds::packed_trie_map` is immutable, and +the only time we can populate its content is at instantiation time. Here, we +are using the :c:macro:`MDDS_ASCII` macro to expand a string literal to its +pointer value and size. Note that you need to ensure that *the entries are sorted +by the key in ascending order.* + +.. warning:: + + When instantiating :cpp:class:`~mdds::packed_trie_map` directly with a static + set of entries, the entries must be sorted by the key in ascending order. + +You can then pass this list of entries to construct the instance: + +.. literalinclude:: ../../example/packed_trie_map.cpp + :language: C++ + :start-after: //!code-start: inst + :end-before: //!code-end: inst + :dedent: 4 + +Once it's instantiated, the rest of the example for performing searches will be +the same as in the previous section, which we will not repeat here. + +The complete source code for the example in this section is available +`here `__. diff -Nru mdds-2.1.1/doc/trie_map/index.rst mdds-3.1.0/doc/trie_map/index.rst --- mdds-2.1.1/doc/trie_map/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/index.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,28 @@ +.. highlight:: cpp + + +Trie Maps +========= + +The :cpp:class:`~mdds::trie_map` class is an associative container that stores +multiple key-value pairs similar to ``std::map``, but the key-value pairs are +stored in a `trie structure `_ to optimize +for prefix searches. + +Another data structure similar to :cpp:class:`~mdds::trie_map` is +:cpp:class:`~mdds::packed_trie_map`, which provides search API nearly identical +to that of :cpp:class:`~mdds::trie_map` but is immutable once created. Instead, +:cpp:class:`~mdds::packed_trie_map` stores all of its content in a contiguous +memory region to improve memory locality, and also supports serialization of its +state to an external buffer. + +.. toctree:: + :maxdepth: 1 + + populate-trie-map.rst + pack-trie-map.rst + direct-packed-trie-map.rst + save-load-packed-trie-map.rst + save-load-packed-trie-map-custom-value.rst + api.rst + diff -Nru mdds-2.1.1/doc/trie_map/pack-trie-map.rst mdds-3.1.0/doc/trie_map/pack-trie-map.rst --- mdds-2.1.1/doc/trie_map/pack-trie-map.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/pack-trie-map.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,86 @@ + +Creating packed_trie_map from trie_map +====================================== + +There is also another variant of trie called :cpp:class:`~mdds::packed_trie_map` +which is designed to store all its data in contiguous memory region. Unlike +:cpp:class:`~mdds::trie_map` which is mutable, :cpp:class:`~mdds::packed_trie_map` +is immutable; once populated, you can only perform queries and it is no longer +possible to add new entries into the container. + +One way to create an instance of :cpp:class:`~mdds::packed_trie_map` is from +:cpp:class:`~mdds::trie_map` by calling its :cpp:func:`~mdds::trie_map::pack` +method: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: pack + :end-before: //!code-end: pack + :dedent: 4 + +When creating a :cpp:class:`~mdds::packed_trie_map` instance this way, however, +you need to be aware that the values get moved from the original instance to the +new instance. As such, it is not advisable to keep the original instance around +afterward. If you need to keep the original instance intact, you can first +create a copy of it and then call its :cpp:func:`~mdds::trie_map::pack` method +to create the packed variant. + +.. warning:: + + Calling :cpp:func:`~mdds::trie_map::pack` will move all the stored values to + the packed variant. Make a copy first if you need to keep the original instance + intact. + +The query methods of :cpp:class:`~mdds::packed_trie_map` are identical to those +of :cpp:class:`~mdds::trie_map`. For instance, performing prefix search to find +all entries whose key begins with "C" can be done as follows: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: search-c + :end-before: //!code-end: search-c + :dedent: 4 + +Running this code will generate the following output: + +.. code-block:: none + + Cities that start with 'C' and their populations: + Cary: 151088 + Chapel Hill: 59635 + Charlotte: 792862 + Concord: 83506 + +You can also perform an exact-match query via :cpp:func:`~mdds::packed_trie_map::find` +method which returns an iterator associated with the key-value pair entry: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: find-one + :end-before: //!code-end: find-one + :dedent: 4 + +You'll see the following output with this code: + +.. code-block:: none + + Population of Wilmington: 112067 + +What if you performed an exact-match query with a key that doesn't exist in the +container? You will basically get the end iterator position as its return value. +Thus, running this code: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: find-none + :end-before: //!code-end: find-none + :dedent: 4 + +will generate the following output: + +.. code-block:: none + + Population of Asheboro: not found + +The complete source code for the examples in these two sections is available +`here `__. diff -Nru mdds-2.1.1/doc/trie_map/populate-trie-map.rst mdds-3.1.0/doc/trie_map/populate-trie-map.rst --- mdds-2.1.1/doc/trie_map/populate-trie-map.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/populate-trie-map.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,83 @@ + +Populating trie_map +=================== + +This section illustrates how to use :cpp:class:`~mdds::trie_map` to build a +database of city populations and perform prefix searches. In this example, +we will use the 2013 populations of cities in North Carolina, and use the city +names as keys. + +Let's define the type first: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + :dedent: 4 + +The first template argument specifies the key type, while the second template +argument specifies the value type. In this example we are using ``std::string`` +and ``int``, respectively. + +Once the type is defined, the next step is instantiation: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: inst + :end-before: //!code-end: inst + :dedent: 4 + +It's pretty simple as you don't need to pass any arguments to the constructor. +Now, let's populate this data structure with some population data: + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: populate + :end-before: //!code-end: populate + :dedent: 4 + +It's pretty straight-forward. Each :cpp:func:`~mdds::trie_map::insert` call +expects a pair of string key and an integer value. You can insert your data +in any order regardless of key's sort order. + +Now that the data is in, let's perform prefix search to query all cities whose +name begins with "Cha": + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: search-cha + :end-before: //!code-end: search-cha + :dedent: 4 + +You can perform prefix search via :cpp:func:`~mdds::trie_map::prefix_search` +method, which returns a results object that can be iterated over using a range-based +for loop. Running this code will produce the following output: + +.. code-block:: none + + Cities that start with 'Cha' and their populations: + Chapel Hill: 59635 + Charlotte: 792862 + +Let's perform another prefix search, this time with a prefix of "W": + +.. literalinclude:: ../../example/trie_map.cpp + :language: C++ + :start-after: //!code-start: search-w + :end-before: //!code-end: search-w + :dedent: 4 + +You'll see the following output when running this code: + +.. code-block:: none + + Cities that start with 'W' and their populations: + Wilmington: 112067 + Wilson: 49628 + Winston-Salem: 236441 + +Note that the results are sorted in key's ascending order. + +.. note:: + + Results from the prefix search are sorted in key's ascending order. diff -Nru mdds-2.1.1/doc/trie_map/save-load-packed-trie-map-custom-value.rst mdds-3.1.0/doc/trie_map/save-load-packed-trie-map-custom-value.rst --- mdds-2.1.1/doc/trie_map/save-load-packed-trie-map-custom-value.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/save-load-packed-trie-map-custom-value.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,182 @@ + +Saving packed_trie_map with custom value type +============================================= + +In the previos example, you didn't have to explicitly specify the serializer type +to the :cpp:func:`~mdds::packed_trie_map::save_state` and +:cpp:func:`~mdds::packed_trie_map::load_state` methods, even though these two +methods require the serializer type as their template arguments. That's because +the library provides default serializer types for + +* numeric value types i.e. integers, float and double, +* ``std::string``, and +* the standard sequence types, such as ``std::vector``, whose elements are of + numeric value types, + +and the previous example used ``int`` as the value type. + +In this section, we are going to illustrate how you can write your own custom +serializer to allow serialization of your own custom value type. In this example, +we are going to use `the list of presidents of the United States +`__, +with the names of the presidents as the keys, and their years of inauguration +and political affiliations as the values. + +We will use the following structure to store the values: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: value-type + :end-before: //!code-end: value-type + :dedent: 0 + +Each entry stores the year as a 16-bit integer and the affiliated party as an enum +value of 8-bit width. + +Next, let's define the container type: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: trie-type + :end-before: //!code-end: trie-type + :dedent: 4 + +As with the previous example, the first step is to define the entries that are +sorted by the keys, which in this case are the president's names: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: entries + :end-before: //!code-end: entries + :dedent: 4 + +Note that we need to add numeric suffixes to the entries for Grover Cleveland, +who became president twice in two separate periods, in order to make the keys +for his entries unique. + +Now, proceed to create an instance of :cpp:class:`~mdds::packed_trie_map`: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: inst + :end-before: //!code-end: inst + :dedent: 4 + +and inspect its size to make sure it is instantiated properly: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: print-n-entries + :end-before: //!code-end: print-n-entries + :dedent: 4 + +You should see the following output: + +.. code-block:: none + + Number of entries: 45 + +Before we proceed to save the state of this instance, let's define the custom +serializer type first: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: custom-serializer + :end-before: //!code-end: custom-serializer + :dedent: 0 + +A custom value type can be either variable-size or fixed-size. For a variable-size +value type, each value segment is preceded by the byte length of that segment. +For a fixed-size value type, the byte length of all of the value segments +is written only once up-front, followed by one or more value segments of equal +byte length. + +Since the value type in this example is fixed-size, we set the value of the +``variable_size`` static constant to false, and define the size of the value to 3 (bytes) +as the ``value_size`` static constant. Keep in mind that you need to define +the ``value_size`` constant *only* for fixed-size value types; if your value +type is variable-size, you can leave it out. + +Additionally, you need to define two static methods - one for writing to the +output stream, and one for reading from the input stream. The ``write`` method +must have the following signature:: + + static void write(std::ostream& os, const T& v); + +where the ``T`` is the value type. In the body of this method you write to the +output stream the bytes that represent the value. The length of the bytes you +write must match the size specified by the ``value_size`` constant. + +The ``read`` method must have the following signature:: + + static void read(std::istream& is, size_t n, T& v); + +where the ``T`` is the value type, and the ``n`` specifies the length of the +bytes you need to read for the value. For a fixed-size value type, the value +of ``n`` should equal the ``value_size`` constant. Your job is to read the +bytes off of the input stream for the length specified by the ``n``, and +populate the value instance passed to the method as the third argument. + +Now that we have defined the custom serializer type, let's proceed to save the +state to a file: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: save-state + :end-before: //!code-end: save-state + :dedent: 8 + +This time around, we are specifying the serializer type explicitly as the template +argument to the :cpp:func:`~mdds::packed_trie_map::save_state` method. Otherwise +it is no different than what we did in the previous example. + +Let's create another instance of :cpp:class:`~mdds::packed_trie_map` and restore +the state back from the file we just created: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: load-state + :end-before: //!code-end: load-state + :dedent: 4 + +Once again, aside from explicitly specifying the serializer type as the template +argument to the :cpp:func:`~mdds::packed_trie_map::load_state` method, it is +identical to the way we did in the previous example. + +Let's compare the new instance with the old one to see if the two are equal: + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: compare + :end-before: //!code-end: compare + :dedent: 4 + +The output says: + +.. code-block:: none + + Equal to the original? true + +They are. While we are at it, let's run a simple prefix search to find out +all the US presidents whose first name is 'John': + +.. literalinclude:: ../../example/packed_trie_state_custom.cpp + :language: C++ + :start-after: //!code-start: search-john + :end-before: //!code-end: search-john + :dedent: 4 + +Here is the output: + +.. code-block:: none + + Presidents whose first name is 'John': + * John Adams (1797; Federalist) + * John F. Kennedy (1961; Democratic) + * John Quincy Adams (1825; Democratic Republican) + * John Tyler (1841; Whig) + +This looks like the correct results! + +You can find the complete source code for this example `here +`__. diff -Nru mdds-2.1.1/doc/trie_map/save-load-packed-trie-map.rst mdds-3.1.0/doc/trie_map/save-load-packed-trie-map.rst --- mdds-2.1.1/doc/trie_map/save-load-packed-trie-map.rst 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/doc/trie_map/save-load-packed-trie-map.rst 2025-01-22 02:40:24.000000000 +0000 @@ -0,0 +1,169 @@ + +Saving and loading packed_trie_map +================================== + +There are times when you need to save the state of a :cpp:class:`~mdds::packed_trie_map` +instance to a file, or an in-memory buffer, and load it back later. Doing that +is now possible by using the :cpp:func:`~mdds::packed_trie_map::save_state` and +:cpp:func:`~mdds::packed_trie_map::load_state` member methods of the +:cpp:class:`~mdds::packed_trie_map` class. + +First, let's define the type of use: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: type + :end-before: //!code-end: type + :dedent: 4 + +As with the previous examples, we will use ``std::string`` as the key type and +``int`` as the value type. In this example, we are going to use `the world's +largest cities and their 2018 populations +`__ as the data to store +in the container. + +The following code defines the entries: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: entries + :end-before: //!code-end: entries + :dedent: 4 + +It's a bit long as it contains entries for 81 cities. We are then going to +create an instance of the :cpp:class:`~mdds::packed_trie_map` class directly: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: inst + :end-before: //!code-end: inst + :dedent: 4 + +Let's print the size of the container to make sure the container has been +successfully populated: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: print-n-cities + :end-before: //!code-end: print-n-cities + :dedent: 4 + +You will see the following output: + +.. code-block:: none + + Number of cities: 81 + +if the container has been successfully populated. Now, let's run a prefix +search on names beginning with an 'S': + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: search-s + :end-before: //!code-end: search-s + :dedent: 8 + +to make sure you get the following ten cities and their populations as the +output: + +.. code-block:: none + + Cities that begin with 'S': + * Saint Petersburg: 5383000 + * Santiago: 6680000 + * Sao Paulo: 21650000 + * Seoul: 9963000 + * Shanghai: 25582000 + * Shenyang: 6921000 + * Shenzhen: 11908000 + * Singapore: 5792000 + * Surat: 6564000 + * Suzhou: 6339000 + +So far so good. Next, we will use the :cpp:func:`~mdds::packed_trie_map::save_state` +method to dump the internal state of this container to a file named **cities.bin**: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: save-state-cities + :end-before: //!code-end: save-state-cities + :dedent: 8 + +This will create a file named **cities.bin** which contains a binary blob +representing the content of this container in the current working directory. +Run the ``ls -l cities.bin`` command to make sure the file has been created: + +.. code-block:: none + + -rw-r--r-- 1 kohei kohei 17713 Jun 20 12:49 cities.bin + +Now that the state of the container has been fully serialized to a file, let's +work on restoring its content in another, brand-new instance of +:cpp:class:`~mdds::packed_trie_map`. + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: load-state-cities + :end-before: //!code-end: load-state-cities + :dedent: 4 + +Here, we used the :cpp:func:`~mdds::packed_trie_map::load_state` method to +restore the state from the file we have previously created. Let's make sure +that this new instance has content equivalent to that of the original: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: check-equal + :end-before: //!code-end: check-equal + :dedent: 4 + +If you see the following output: + +.. code-block:: none + + Equal to the original? true + +then this new instance has equivalent contant as the original one. Let's also +make sure that it contains the same number of entries as the original: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: print-n-cities-2 + :end-before: //!code-end: print-n-cities-2 + :dedent: 4 + +Hopefully you will see the following output: + +.. code-block:: none + + Number of cities: 81 + +Lastly, let's run on this new instance the same prefix search we did on the +original instance, to make sure we still get the same results: + +.. literalinclude:: ../../example/packed_trie_state_int.cpp + :language: C++ + :start-after: //!code-start: search-s-2 + :end-before: //!code-end: search-s-2 + :dedent: 4 + +You should see the following output: + +.. code-block:: none + + Cities that begin with 'S': + * Saint Petersburg: 5383000 + * Santiago: 6680000 + * Sao Paulo: 21650000 + * Seoul: 9963000 + * Shanghai: 25582000 + * Shenyang: 6921000 + * Shenzhen: 11908000 + * Singapore: 5792000 + * Surat: 6564000 + * Suzhou: 6339000 + +which is the same output we saw in the first prefix search. + +The complete source code for this example is found +`here `__. diff -Nru mdds-2.1.1/doc/trie_map.rst mdds-3.1.0/doc/trie_map.rst --- mdds-2.1.1/doc/trie_map.rst 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/doc/trie_map.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,767 +0,0 @@ -.. highlight:: cpp - - -Trie Maps -========= - -Examples --------- - -Populating Trie Map -^^^^^^^^^^^^^^^^^^^ - -This section illustrates how to use :cpp:class:`~mdds::trie_map` to build a -database of city populations and perform prefix searches. In this example, -we will use the 2013 populations of cities in North Carolina, and use the city -names as keys. - -Let's define the type first:: - - using trie_map_type = mdds::trie_map; - -The first template argument specifies the trait of the key. In this example, -we are using a pre-defined trait for std::string, which is defined in -:cpp:type:`~mdds::trie::std_string_traits`. The second template argument -specifies the value type, which in this example is simply an ``int``. - -Once the type is defined, the next step is instantiation:: - - trie_map_type nc_cities; - -It's pretty simple as you don't need to pass any arguments to the constructor. -Now, let's populate this data structure with some population data:: - - // Insert key-value pairs. - nc_cities.insert("Charlotte", 792862); - nc_cities.insert("Raleigh", 431746); - nc_cities.insert("Greensboro", 279639); - nc_cities.insert("Durham", 245475); - nc_cities.insert("Winston-Salem", 236441); - nc_cities.insert("Fayetteville", 204408); - nc_cities.insert("Cary", 151088); - nc_cities.insert("Wilmington", 112067); - nc_cities.insert("High Point", 107741); - nc_cities.insert("Greenville", 89130); - nc_cities.insert("Asheville", 87236); - nc_cities.insert("Concord", 83506); - nc_cities.insert("Gastonia", 73209); - nc_cities.insert("Jacksonville", 69079); - nc_cities.insert("Chapel Hill", 59635); - nc_cities.insert("Rocky Mount", 56954); - nc_cities.insert("Burlington", 51510); - nc_cities.insert("Huntersville", 50458); - nc_cities.insert("Wilson", 49628); - nc_cities.insert("Kannapolis", 44359); - nc_cities.insert("Apex", 42214); - nc_cities.insert("Hickory", 40361); - nc_cities.insert("Goldsboro", 36306); - -It's pretty straight-forward. Each :cpp:func:`~mdds::trie_map::insert` call -expects a pair of string key and an integer value. You can insert your data -in any order regardless of key's sort order. - -Now that the data is in, let's perform prefix search to query all cities whose -name begins with "Cha":: - - cout << "Cities that start with 'Cha' and their populations:" << endl; - auto results = nc_cities.prefix_search("Cha"); - for (const auto& kv : results) - { - cout << " " << kv.first << ": " << kv.second << endl; - } - -You can perform prefix search via :cpp:func:`~mdds::trie_map::prefix_search` -method, which returns a results object that can be iterated over using a range-based -for loop. Running this code will produce the following output: - -.. code-block:: none - - Cities that start with 'Cha' and their populations: - Chapel Hill: 59635 - Charlotte: 792862 - -Let's perform another prefix search, this time with a prefix of "W":: - - cout << "Cities that start with 'W' and their populations:" << endl; - results = nc_cities.prefix_search("W"); - for (const auto& kv : results) - { - cout << " " << kv.first << ": " << kv.second << endl; - } - -You'll see the following output when running this code: - -.. code-block:: none - - Cities that start with 'W' and their populations: - Wilmington: 112067 - Wilson: 49628 - Winston-Salem: 236441 - -Note that the results are sorted in key's ascending order. - -.. note:: - - Results from the prefix search are sorted in key's ascending order. - - -Creating Packed Trie Map from Trie Map -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -There is also another variant of trie called :cpp:class:`~mdds::packed_trie_map` -which is designed to store all its data in contiguous memory region. Unlike -:cpp:class:`~mdds::trie_map` which is mutable, :cpp:class:`~mdds::packed_trie_map` -is immutable; once populated, you can only perform queries and it is no longer -possible to add new entries into the container. - -One way to create an instance of :cpp:class:`~mdds::packed_trie_map` is from -:cpp:class:`~mdds::trie_map` by calling its :cpp:func:`~mdds::trie_map::pack` -method:: - - auto packed = nc_cities.pack(); - -The query methods of :cpp:class:`~mdds::packed_trie_map` are identical to those -of :cpp:class:`~mdds::trie_map`. For instance, performing prefix search to find -all entries whose key begins with "C" can be done as follows:: - - cout << "Cities that start with 'C' and their populations:" << endl; - auto packed_results = packed.prefix_search("C"); - for (const auto& kv : packed_results) - { - cout << " " << kv.first << ": " << kv.second << endl; - } - -Running this code will generate the following output: - -.. code-block:: none - - Cities that start with 'C' and their populations: - Cary: 151088 - Chapel Hill: 59635 - Charlotte: 792862 - Concord: 83506 - -You can also perform an exact-match query via :cpp:func:`~mdds::packed_trie_map::find` -method which returns an iterator associated with the key-value pair entry:: - - // Individual search. - auto it = packed.find("Wilmington"); - cout << "Population of Wilmington: " << it->second << endl; - -You'll see the following output with this code: - -.. code-block:: none - - Population of Wilmington: 112067 - -What if you performed an exact-match query with a key that doesn't exist in the -container? You will basically get the end iterator position as its return value. -Thus, running this code:: - - // You get an end position iterator when the container doesn't have the - // specified key. - it = packed.find("Asheboro"); - - cout << "Population of Asheboro: "; - - if (it == packed.end()) - cout << "not found"; - else - cout << it->second; - - cout << endl; - -will generate the following output: - -.. code-block:: none - - Population of Asheboro: not found - -The complete source code for the examples in these two sections is available -`here `__. - - -Using Packed Trie Map directly -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In the previous example, we showed a way to create an instance of :cpp:class:`~mdds::packed_trie_map` -from a populated instance of :cpp:class:`~mdds::trie_map`. There is also a way -to instantiate and populate an instance of :cpp:class:`~mdds::packed_trie_map` -directly, and that is what we will cover in this section. - -First, declare the type:: - - using trie_map_type = mdds::packed_trie_map; - -Once again, we are using the pre-defined trait for std::string as its key, and int -as its value type. The next step is to prepare its entries ahead of time:: - - trie_map_type::entry entries[] = - { - { MDDS_ASCII("Apex"), 42214 }, - { MDDS_ASCII("Asheville"), 87236 }, - { MDDS_ASCII("Burlington"), 51510 }, - { MDDS_ASCII("Cary"), 151088 }, - { MDDS_ASCII("Chapel Hill"), 59635 }, - { MDDS_ASCII("Charlotte"), 792862 }, - { MDDS_ASCII("Concord"), 83506 }, - { MDDS_ASCII("Durham"), 245475 }, - { MDDS_ASCII("Fayetteville"), 204408 }, - { MDDS_ASCII("Gastonia"), 73209 }, - { MDDS_ASCII("Goldsboro"), 36306 }, - { MDDS_ASCII("Greensboro"), 279639 }, - { MDDS_ASCII("Greenville"), 89130 }, - { MDDS_ASCII("Hickory"), 40361 }, - { MDDS_ASCII("High Point"), 107741 }, - { MDDS_ASCII("Huntersville"), 50458 }, - { MDDS_ASCII("Jacksonville"), 69079 }, - { MDDS_ASCII("Kannapolis"), 44359 }, - { MDDS_ASCII("Raleigh"), 431746 }, - { MDDS_ASCII("Rocky Mount"), 56954 }, - { MDDS_ASCII("Wilmington"), 112067 }, - { MDDS_ASCII("Wilson"), 49628 }, - { MDDS_ASCII("Winston-Salem"), 236441 }, - }; - -We need to do this since :cpp:class:`~mdds::packed_trie_map` is immutable, and -the only time we can populate its content is at instantiation time. Here, we -are using the :c:macro:`MDDS_ASCII` macro to expand a string literal to its -pointer value and size. Note that you need to ensure that the entries are sorted -by the key in ascending order. - -.. warning:: - - When instantiating :cpp:class:`~mdds::packed_trie_map` directly with a static - set of entries, the entries must be sorted by the key in ascending order. - -You can then pass this list of entries to construct the instance:: - - trie_map_type nc_cities(entries, MDDS_N_ELEMENTS(entries)); - -The :c:macro:`MDDS_N_ELEMENTS` macro will infer the size of a fixed-size array -from its static definition. Once it's instantiated, the rest of the example -for performing searches will be the same as in the previous section, which we -will not repeat here. - -The complete source code for the example in this section is available -`here `__. - - -Saving and loading Packed Trie Map instances -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -There are times when you need to save the state of a :cpp:class:`~mdds::packed_trie_map` -instance to a file, or an in-memory buffer, and load it back later. Doing that -is now possible by using the :cpp:func:`~mdds::packed_trie_map::save_state` and -:cpp:func:`~mdds::packed_trie_map::load_state` member methods of the -:cpp:class:`~mdds::packed_trie_map` class. - -First, let's define the type of use:: - - using map_type = mdds::packed_trie_map; - -As with the previous examples, we will use ``std::string`` as the key type and -``int`` as the value type. In this example, we are going to use `the world's -largest cities and their 2018 populations -`__ as the data to store -in the container. - -The following code defines the entries:: - - std::vector entries = - { - { MDDS_ASCII("Ahmedabad"), 7681000 }, - { MDDS_ASCII("Alexandria"), 5086000 }, - { MDDS_ASCII("Atlanta"), 5572000 }, - { MDDS_ASCII("Baghdad"), 6812000 }, - { MDDS_ASCII("Bangalore"), 11440000 }, - { MDDS_ASCII("Bangkok"), 10156000 }, - { MDDS_ASCII("Barcelona"), 5494000 }, - { MDDS_ASCII("Beijing"), 19618000 }, - { MDDS_ASCII("Belo Horizonte"), 5972000 }, - { MDDS_ASCII("Bogota"), 10574000 }, - { MDDS_ASCII("Buenos Aires"), 14967000 }, - { MDDS_ASCII("Cairo"), 20076000 }, - { MDDS_ASCII("Chengdu"), 8813000 }, - { MDDS_ASCII("Chennai"), 10456000 }, - { MDDS_ASCII("Chicago"), 8864000 }, - { MDDS_ASCII("Chongqing"), 14838000 }, - { MDDS_ASCII("Dalian"), 5300000 }, - { MDDS_ASCII("Dallas"), 6099000 }, - { MDDS_ASCII("Dar es Salaam"), 6048000 }, - { MDDS_ASCII("Delhi"), 28514000 }, - { MDDS_ASCII("Dhaka"), 19578000 }, - { MDDS_ASCII("Dongguan"), 7360000 }, - { MDDS_ASCII("Foshan"), 7236000 }, - { MDDS_ASCII("Fukuoka"), 5551000 }, - { MDDS_ASCII("Guadalajara"), 5023000 }, - { MDDS_ASCII("Guangzhou"), 12638000 }, - { MDDS_ASCII("Hangzhou"), 7236000 }, - { MDDS_ASCII("Harbin"), 6115000 }, - { MDDS_ASCII("Ho Chi Minh City"), 8145000 }, - { MDDS_ASCII("Hong Kong"), 7429000 }, - { MDDS_ASCII("Houston"), 6115000 }, - { MDDS_ASCII("Hyderabad"), 9482000 }, - { MDDS_ASCII("Istanbul"), 14751000 }, - { MDDS_ASCII("Jakarta"), 10517000 }, - { MDDS_ASCII("Jinan"), 5052000 }, - { MDDS_ASCII("Johannesburg"), 5486000 }, - { MDDS_ASCII("Karachi"), 15400000 }, - { MDDS_ASCII("Khartoum"), 5534000 }, - { MDDS_ASCII("Kinshasa"), 13171000 }, - { MDDS_ASCII("Kolkata"), 14681000 }, - { MDDS_ASCII("Kuala Lumpur"), 7564000 }, - { MDDS_ASCII("Lagos"), 13463000 }, - { MDDS_ASCII("Lahore"), 11738000 }, - { MDDS_ASCII("Lima"), 10391000 }, - { MDDS_ASCII("London"), 9046000 }, - { MDDS_ASCII("Los Angeles"), 12458000 }, - { MDDS_ASCII("Luanda"), 7774000 }, - { MDDS_ASCII("Madrid"), 6497000 }, - { MDDS_ASCII("Manila"), 13482000 }, - { MDDS_ASCII("Mexico City"), 21581000 }, - { MDDS_ASCII("Miami"), 6036000 }, - { MDDS_ASCII("Moscow"), 12410000 }, - { MDDS_ASCII("Mumbai"), 19980000 }, - { MDDS_ASCII("Nagoya"), 9507000 }, - { MDDS_ASCII("Nanjing"), 8245000 }, - { MDDS_ASCII("New York City"), 18819000 }, - { MDDS_ASCII("Osaka"), 19281000 }, - { MDDS_ASCII("Paris"), 10901000 }, - { MDDS_ASCII("Philadelphia"), 5695000 }, - { MDDS_ASCII("Pune"), 6276000 }, - { MDDS_ASCII("Qingdao"), 5381000 }, - { MDDS_ASCII("Rio de Janeiro"), 13293000 }, - { MDDS_ASCII("Riyadh"), 6907000 }, - { MDDS_ASCII("Saint Petersburg"), 5383000 }, - { MDDS_ASCII("Santiago"), 6680000 }, - { MDDS_ASCII("Sao Paulo"), 21650000 }, - { MDDS_ASCII("Seoul"), 9963000 }, - { MDDS_ASCII("Shanghai"), 25582000 }, - { MDDS_ASCII("Shenyang"), 6921000 }, - { MDDS_ASCII("Shenzhen"), 11908000 }, - { MDDS_ASCII("Singapore"), 5792000 }, - { MDDS_ASCII("Surat"), 6564000 }, - { MDDS_ASCII("Suzhou"), 6339000 }, - { MDDS_ASCII("Tehran"), 8896000 }, - { MDDS_ASCII("Tianjin"), 13215000 }, - { MDDS_ASCII("Tokyo"), 37400068 }, - { MDDS_ASCII("Toronto"), 6082000 }, - { MDDS_ASCII("Washington, D.C."), 5207000 }, - { MDDS_ASCII("Wuhan"), 8176000 }, - { MDDS_ASCII("Xi'an"), 7444000 }, - { MDDS_ASCII("Yangon"), 5157000 }, - }; - -It's a bit long as it contains entries for 81 cities. We are then going to -create an instance of the :cpp:class:`~mdds::packed_trie_map` class directly:: - - map_type cities(entries.data(), entries.size()); - -Let's print the size of the container to make sure the container has been -successfully populated:: - - cout << "Number of cities: " << cities.size() << endl; - -You will see the following output: - -.. code-block:: none - - Number of cities: 81 - -if the container has been successfully populated. Now, let's run a prefix -search on names beginning with an 'S':: - - cout << "Cities that begin with 'S':" << endl; - auto results = cities.prefix_search("S"); - for (const auto& city : results) - cout << " * " << city.first << ": " << city.second << endl; - -to make sure you get the following ten cities and their populations as the -output: - -.. code-block:: none - - Cities that begin with 'S': - * Saint Petersburg: 5383000 - * Santiago: 6680000 - * Sao Paulo: 21650000 - * Seoul: 9963000 - * Shanghai: 25582000 - * Shenyang: 6921000 - * Shenzhen: 11908000 - * Singapore: 5792000 - * Surat: 6564000 - * Suzhou: 6339000 - -So far so good. Next, we will use the :cpp:func:`~mdds::packed_trie_map::save_state` -method to dump the internal state of this container to a file named **cities.bin**:: - - std::ofstream outfile("cities.bin", std::ios::binary); - cities.save_state(outfile); - -This will create a file named **cities.bin** which contains a binary blob -representing the content of this container in the current working directory. -Run the ``ls -l cities.bin`` command to make sure the file has been created: - -.. code-block:: none - - -rw-r--r-- 1 kohei kohei 17713 Jun 20 12:49 cities.bin - -Now that the state of the container has been fully serialized to a file, let's -work on restoring its content in another, brand-new instance of -:cpp:class:`~mdds::packed_trie_map`. - -:: - - map_type cities_loaded; - - std::ifstream infile("cities.bin", std::ios::binary); - cities_loaded.load_state(infile); - -Here, we used the :cpp:func:`~mdds::packed_trie_map::load_state` method to -restore the state from the file we have previously created. Let's make sure -that this new instance has content equivalent to that of the original:: - - cout << "Equal to the original? " << std::boolalpha << (cities == cities_loaded) << endl; - -If you see the following output: - -.. code-block:: none - - Equal to the original? true - -then this new instance has equivalent contant as the original one. Let's also -make sure that it contains the same number of entries as the original:: - - cout << "Number of cities: " << cities_loaded.size() << endl; - -Hopefully you will see the following output: - -.. code-block:: none - - Number of cities: 81 - -Lastly, let's run on this new instance the same prefix search we did on the -original instance, to make sure we still get the same results:: - - cout << "Cities that begin with 'S':" << endl; - auto results = cities_loaded.prefix_search("S"); - for (const auto& city : results) - cout << " * " << city.first << ": " << city.second << endl; - -You should see the following output: - -.. code-block:: none - - Cities that begin with 'S': - * Saint Petersburg: 5383000 - * Santiago: 6680000 - * Sao Paulo: 21650000 - * Seoul: 9963000 - * Shanghai: 25582000 - * Shenyang: 6921000 - * Shenzhen: 11908000 - * Singapore: 5792000 - * Surat: 6564000 - * Suzhou: 6339000 - -which is the same output we saw in the first prefix search. - -The complete source code for this example is found -`here `__. - - -Saving Packed Trie Map with custom value type -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In the previos example, you didn't have to explicitly specify the serializer type -to the :cpp:func:`~mdds::packed_trie_map::save_state` and -:cpp:func:`~mdds::packed_trie_map::load_state` methods, even though these two -methods require the serializer type as their template arguments. That's because -the library provides default serializer types for - -* numeric value types i.e. integers, float and double, -* ``std::string``, and -* the standard sequence types, such as ``std::vector``, whose elements are of - numeric value types, - -and the previous example used ``int`` as the value type. - -In this section, we are going to illustrate how you can write your own custom -serializer to allow serialization of your own custom value type. In this example, -we are going to use `the list of presidents of the United States -`__, -with the names of the presidents as the keys, and their years of inauguration -and political affiliations as the values. - -We will use the following structure to store the values:: - - enum affiliated_party_t : uint8_t - { - unaffiliated = 0, - federalist, - democratic_republican, - democratic, - whig, - republican, - national_union, - republican_national_union, - }; - - struct us_president - { - uint16_t year; - affiliated_party_t party; - }; - -Each entry stores the year as a 16-bit integer and the affiliated party as an enum -value of 8-bit width. - -Next, let's define the container type:: - - using map_type = mdds::packed_trie_map; - -As with the previous example, the first step is to define the entries that are -sorted by the keys, which in this case are the president's names:: - - std::vector entries = - { - { MDDS_ASCII("Abraham Lincoln"), { 1861, republican_national_union } }, - { MDDS_ASCII("Andrew Jackson"), { 1829, democratic } }, - { MDDS_ASCII("Andrew Johnson"), { 1865, national_union } }, - { MDDS_ASCII("Barack Obama"), { 2009, democratic } }, - { MDDS_ASCII("Benjamin Harrison"), { 1889, republican } }, - { MDDS_ASCII("Bill Clinton"), { 1993, democratic } }, - { MDDS_ASCII("Calvin Coolidge"), { 1923, republican } }, - { MDDS_ASCII("Chester A. Arthur"), { 1881, republican } }, - { MDDS_ASCII("Donald Trump"), { 2017, republican } }, - { MDDS_ASCII("Dwight D. Eisenhower"), { 1953, republican } }, - { MDDS_ASCII("Franklin D. Roosevelt"), { 1933, democratic } }, - { MDDS_ASCII("Franklin Pierce"), { 1853, democratic } }, - { MDDS_ASCII("George H. W. Bush"), { 1989, republican } }, - { MDDS_ASCII("George W. Bush"), { 2001, republican } }, - { MDDS_ASCII("George Washington"), { 1789, unaffiliated } }, - { MDDS_ASCII("Gerald Ford"), { 1974, republican } }, - { MDDS_ASCII("Grover Cleveland 1"), { 1885, democratic } }, - { MDDS_ASCII("Grover Cleveland 2"), { 1893, democratic } }, - { MDDS_ASCII("Harry S. Truman"), { 1945, democratic } }, - { MDDS_ASCII("Herbert Hoover"), { 1929, republican } }, - { MDDS_ASCII("James A. Garfield"), { 1881, republican } }, - { MDDS_ASCII("James Buchanan"), { 1857, democratic } }, - { MDDS_ASCII("James K. Polk"), { 1845, democratic } }, - { MDDS_ASCII("James Madison"), { 1809, democratic_republican } }, - { MDDS_ASCII("James Monroe"), { 1817, democratic_republican } }, - { MDDS_ASCII("Jimmy Carter"), { 1977, democratic } }, - { MDDS_ASCII("John Adams"), { 1797, federalist } }, - { MDDS_ASCII("John F. Kennedy"), { 1961, democratic } }, - { MDDS_ASCII("John Quincy Adams"), { 1825, democratic_republican } }, - { MDDS_ASCII("John Tyler"), { 1841, whig } }, - { MDDS_ASCII("Lyndon B. Johnson"), { 1963, democratic } }, - { MDDS_ASCII("Martin Van Buren"), { 1837, democratic } }, - { MDDS_ASCII("Millard Fillmore"), { 1850, whig } }, - { MDDS_ASCII("Richard Nixon"), { 1969, republican } }, - { MDDS_ASCII("Ronald Reagan"), { 1981, republican } }, - { MDDS_ASCII("Rutherford B. Hayes"), { 1877, republican } }, - { MDDS_ASCII("Theodore Roosevelt"), { 1901, republican } }, - { MDDS_ASCII("Thomas Jefferson"), { 1801, democratic_republican } }, - { MDDS_ASCII("Ulysses S. Grant"), { 1869, republican } }, - { MDDS_ASCII("Warren G. Harding"), { 1921, republican } }, - { MDDS_ASCII("William Henry Harrison"), { 1841, whig } }, - { MDDS_ASCII("William Howard Taft"), { 1909, republican } }, - { MDDS_ASCII("William McKinley"), { 1897, republican } }, - { MDDS_ASCII("Woodrow Wilson"), { 1913, democratic } }, - { MDDS_ASCII("Zachary Taylor"), { 1849, whig } }, - }; - -Note that we need to add numeric suffixes to the entries for Grover Cleveland, -who became president twice in two separate periods, in order to make the keys -for his entries unique. - -Now, proceed to create an instance of :cpp:class:`~mdds::packed_trie_map`:: - - map_type us_presidents(entries.data(), entries.size()); - -and inspect its size to make sure it is instantiated properly:: - - cout << "Number of entries: " << us_presidents.size() << endl; - -You should see the following output: - -.. code-block:: none - - Number of entries: 45 - -Before we proceed to save the state of this instance, let's define the custom -serializer type first:: - - struct us_president_serializer - { - union bin_buffer - { - char buffer[2]; - uint16_t i16; - affiliated_party_t party; - }; - - static constexpr bool variable_size = false; - static constexpr size_t value_size = 3; - - static void write(std::ostream& os, const us_president& v) - { - bin_buffer buf; - - // Write the year value first. - buf.i16 = v.year; - os.write(buf.buffer, 2); - - // Write the affiliated party value. - buf.party = v.party; - os.write(buf.buffer, 1); - } - - static void read(std::istream& is, size_t n, us_president& v) - { - // For a fixed-size value type, this should equal the defined value size. - assert(n == 3); - - bin_buffer buf; - - // Read the year value. - is.read(buf.buffer, 2); - v.year = buf.i16; - - // Read the affiliated party value. - is.read(buf.buffer, 1); - v.party = buf.party; - } - }; - -A custom value type can be either variable-size or fixed-size. For a variable-size -value type, each value segment is preceded by the byte length of that segment. -For a fixed-size value type, the byte length of all of the value segments -is written only once up-front, followed by one or more value segments of equal -byte length. - -Since the value type in this example is fixed-size, we set the value of the -``variable_size`` static constant to false, and define the size of the value to 3 (bytes) -as the ``value_size`` static constant. Keep in mind that you need to define -the ``value_size`` constant *only* for fixed-size value types; if your value -type is variable-size, you can leave it out. - -Additionally, you need to define two static methods - one for writing to the -output stream, and one for reading from the input stream. The write method -must have the following signature:: - - static void write(std::ostream& os, const T& v); - -where the ``T`` is the value type. In the body of this method you write to the -output stream the bytes that represent the value. The length of the bytes you -write must match the size specified by the ``value_size`` constant. - -The read method must have the following signature:: - - static void read(std::istream& is, size_t n, T& v); - -where the ``T`` is the value type, and the ``n`` specifies the length of the -bytes you need to read for the value. For a fixed-size value type, the value -of ``n`` should equal the ``value_size`` constant. Your job is to read the -bytes off of the input stream for the length specified by the ``n``, and -populate the value instance passed to the method as the third argument. - -Now that we have defined the custom serializer type, let's proceed to save the -state to a file:: - - std::ofstream outfile("us-presidents.bin", std::ios::binary); - us_presidents.save_state(outfile); - -This time around, we are specifying the serializer type explicitly as the template -argument to the :cpp:func:`~mdds::packed_trie_map::save_state` method. Otherwise -it is no different than what we did in the previous example. - -Let's create another instance of :cpp:class:`~mdds::packed_trie_map` and restore -the state back from the file we just created:: - - map_type us_presidents_loaded; - - std::ifstream infile("us-presidents.bin", std::ios::binary); - us_presidents_loaded.load_state(infile); - -Once again, aside from explicitly specifying the serializer type as the template -argument to the :cpp:func:`~mdds::packed_trie_map::load_state` method, it is -identical to the way we did in the previous example. - -Let's compare the new instance with the old one to see if the two are equal:: - - cout << "Equal to the original? " << std::boolalpha << (us_presidents == us_presidents_loaded) << endl; - -The output says: - -.. code-block:: none - - Equal to the original? true - -They are. While we are at it, let's run a simple prefix search to find out -all the US presidents whose first name is 'John':: - - cout << "Presidents whose first name is 'John':" << endl; - auto results = us_presidents_loaded.prefix_search("John"); - for (const auto& entry : results) - cout << " * " << entry.first << " (" << entry.second.year << "; " << entry.second.party << ")" << endl; - -Here is the output: - -.. code-block:: none - - Presidents whose first name is 'John': - * John Adams (1797; Federalist) - * John F. Kennedy (1961; Democratic) - * John Quincy Adams (1825; Democratic Republican) - * John Tyler (1841; Whig) - -This looks like the correct results! - -You can find the complete source code for this example `here -`__. - - -API Reference -------------- - -Trie Map -^^^^^^^^ - -.. doxygenclass:: mdds::trie_map - :members: - - -Packed Trie Map -^^^^^^^^^^^^^^^ - -.. doxygenclass:: mdds::packed_trie_map - :members: - - -Traits -^^^^^^ - -.. doxygenstruct:: mdds::trie::std_container_traits - :members: - -.. doxygentypedef:: mdds::trie::std_string_traits - - -Value Serializers -^^^^^^^^^^^^^^^^^ - -.. doxygenstruct:: mdds::trie::value_serializer - :members: - -.. doxygenstruct:: mdds::trie::numeric_value_serializer - :members: - -.. doxygenstruct:: mdds::trie::variable_value_serializer - :members: - -.. doxygenstruct:: mdds::trie::numeric_sequence_value_serializer - :members: diff -Nru mdds-2.1.1/example/Makefile.am mdds-3.1.0/example/Makefile.am --- mdds-2.1.1/example/Makefile.am 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/example/Makefile.am 2024-01-10 23:45:35.000000000 +0000 @@ -11,6 +11,7 @@ packed-trie-state-int \ point-quad-tree \ segment-tree \ + sorted-string-map \ trie-map \ rtree-simple \ rtree-erase \ @@ -25,6 +26,7 @@ packed_trie_state_int_SOURCES = packed_trie_state_int.cpp point_quad_tree_SOURCES = point_quad_tree.cpp segment_tree_SOURCES = segment_tree.cpp +sorted_string_map_SOURCES = sorted_string_map.cpp trie_map_SOURCES = trie_map.cpp rtree_simple_SOURCES = rtree_simple.cpp rtree_erase_SOURCES = rtree_erase.cpp @@ -40,6 +42,7 @@ packed-trie-state-int \ point-quad-tree \ segment-tree \ + sorted-string-map \ trie-map \ rtree-simple \ rtree-erase \ diff -Nru mdds-2.1.1/example/Makefile.in mdds-3.1.0/example/Makefile.in --- mdds-2.1.1/example/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/example/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -89,16 +89,16 @@ flat-segment-tree-itrs$(EXEEXT) multi-type-matrix$(EXEEXT) \ packed-trie-map$(EXEEXT) packed-trie-state-custom$(EXEEXT) \ packed-trie-state-int$(EXEEXT) point-quad-tree$(EXEEXT) \ - segment-tree$(EXEEXT) trie-map$(EXEEXT) rtree-simple$(EXEEXT) \ - rtree-erase$(EXEEXT) rtree-medium$(EXEEXT) \ - rtree-medium-bulkload$(EXEEXT) + segment-tree$(EXEEXT) sorted-string-map$(EXEEXT) \ + trie-map$(EXEEXT) rtree-simple$(EXEEXT) rtree-erase$(EXEEXT) \ + rtree-medium$(EXEEXT) rtree-medium-bulkload$(EXEEXT) TESTS = flat-segment-tree$(EXEEXT) flat-segment-tree-itrs$(EXEEXT) \ multi-type-matrix$(EXEEXT) packed-trie-map$(EXEEXT) \ packed-trie-state-custom$(EXEEXT) \ packed-trie-state-int$(EXEEXT) point-quad-tree$(EXEEXT) \ - segment-tree$(EXEEXT) trie-map$(EXEEXT) rtree-simple$(EXEEXT) \ - rtree-erase$(EXEEXT) rtree-medium$(EXEEXT) \ - rtree-medium-bulkload$(EXEEXT) + segment-tree$(EXEEXT) sorted-string-map$(EXEEXT) \ + trie-map$(EXEEXT) rtree-simple$(EXEEXT) rtree-erase$(EXEEXT) \ + rtree-medium$(EXEEXT) rtree-medium-bulkload$(EXEEXT) subdir = example ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ @@ -149,6 +149,9 @@ am_segment_tree_OBJECTS = segment_tree.$(OBJEXT) segment_tree_OBJECTS = $(am_segment_tree_OBJECTS) segment_tree_LDADD = $(LDADD) +am_sorted_string_map_OBJECTS = sorted_string_map.$(OBJEXT) +sorted_string_map_OBJECTS = $(am_sorted_string_map_OBJECTS) +sorted_string_map_LDADD = $(LDADD) am_trie_map_OBJECTS = trie_map.$(OBJEXT) trie_map_OBJECTS = $(am_trie_map_OBJECTS) trie_map_LDADD = $(LDADD) @@ -177,7 +180,7 @@ ./$(DEPDIR)/rtree_medium.Po \ ./$(DEPDIR)/rtree_medium_bulkload.Po \ ./$(DEPDIR)/rtree_simple.Po ./$(DEPDIR)/segment_tree.Po \ - ./$(DEPDIR)/trie_map.Po + ./$(DEPDIR)/sorted_string_map.Po ./$(DEPDIR)/trie_map.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -198,14 +201,16 @@ $(packed_trie_state_int_SOURCES) $(point_quad_tree_SOURCES) \ $(rtree_erase_SOURCES) $(rtree_medium_SOURCES) \ $(rtree_medium_bulkload_SOURCES) $(rtree_simple_SOURCES) \ - $(segment_tree_SOURCES) $(trie_map_SOURCES) + $(segment_tree_SOURCES) $(sorted_string_map_SOURCES) \ + $(trie_map_SOURCES) DIST_SOURCES = $(flat_segment_tree_SOURCES) \ $(flat_segment_tree_itrs_SOURCES) $(multi_type_matrix_SOURCES) \ $(packed_trie_map_SOURCES) $(packed_trie_state_custom_SOURCES) \ $(packed_trie_state_int_SOURCES) $(point_quad_tree_SOURCES) \ $(rtree_erase_SOURCES) $(rtree_medium_SOURCES) \ $(rtree_medium_bulkload_SOURCES) $(rtree_simple_SOURCES) \ - $(segment_tree_SOURCES) $(trie_map_SOURCES) + $(segment_tree_SOURCES) $(sorted_string_map_SOURCES) \ + $(trie_map_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -540,7 +545,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -605,6 +609,7 @@ packed_trie_state_int_SOURCES = packed_trie_state_int.cpp point_quad_tree_SOURCES = point_quad_tree.cpp segment_tree_SOURCES = segment_tree.cpp +sorted_string_map_SOURCES = sorted_string_map.cpp trie_map_SOURCES = trie_map.cpp rtree_simple_SOURCES = rtree_simple.cpp rtree_erase_SOURCES = rtree_erase.cpp @@ -697,6 +702,10 @@ @rm -f segment-tree$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(segment_tree_OBJECTS) $(segment_tree_LDADD) $(LIBS) +sorted-string-map$(EXEEXT): $(sorted_string_map_OBJECTS) $(sorted_string_map_DEPENDENCIES) $(EXTRA_sorted_string_map_DEPENDENCIES) + @rm -f sorted-string-map$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(sorted_string_map_OBJECTS) $(sorted_string_map_LDADD) $(LIBS) + trie-map$(EXEEXT): $(trie_map_OBJECTS) $(trie_map_DEPENDENCIES) $(EXTRA_trie_map_DEPENDENCIES) @rm -f trie-map$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(trie_map_OBJECTS) $(trie_map_LDADD) $(LIBS) @@ -719,6 +728,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtree_medium_bulkload.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtree_simple.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/segment_tree.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sorted_string_map.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trie_map.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @@ -1044,6 +1054,13 @@ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +sorted-string-map.log: sorted-string-map$(EXEEXT) + @p='sorted-string-map$(EXEEXT)'; \ + b='sorted-string-map'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) trie-map.log: trie-map$(EXEEXT) @p='trie-map$(EXEEXT)'; \ b='trie-map'; \ @@ -1227,6 +1244,7 @@ -rm -f ./$(DEPDIR)/rtree_medium_bulkload.Po -rm -f ./$(DEPDIR)/rtree_simple.Po -rm -f ./$(DEPDIR)/segment_tree.Po + -rm -f ./$(DEPDIR)/sorted_string_map.Po -rm -f ./$(DEPDIR)/trie_map.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ @@ -1285,6 +1303,7 @@ -rm -f ./$(DEPDIR)/rtree_medium_bulkload.Po -rm -f ./$(DEPDIR)/rtree_simple.Po -rm -f ./$(DEPDIR)/segment_tree.Po + -rm -f ./$(DEPDIR)/sorted_string_map.Po -rm -f ./$(DEPDIR)/trie_map.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff -Nru mdds-2.1.1/example/multi_type_vector/Makefile.in mdds-3.1.0/example/multi_type_vector/Makefile.in --- mdds-2.1.1/example/multi_type_vector/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/example/multi_type_vector/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -474,7 +474,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/example/packed_trie_map.cpp mdds-3.1.0/example/packed_trie_map.cpp --- mdds-2.1.1/example/packed_trie_map.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/packed_trie_map.cpp 2024-02-07 03:12:37.000000000 +0000 @@ -30,15 +30,15 @@ #include #include -using std::cout; -using std::endl; - int main() { - using trie_map_type = mdds::packed_trie_map; + //!code-start: type + using trie_map_type = mdds::packed_trie_map; + //!code-end: type // Entries must be known prior to creating the instance, and they must be // sorted by the key in ascending order. + //!code-start: populate trie_map_type::entry entries[] = { { MDDS_ASCII("Apex"), 42214 }, @@ -65,47 +65,50 @@ { MDDS_ASCII("Wilson"), 49628 }, { MDDS_ASCII("Winston-Salem"), 236441 }, }; + //!code-end: populate // Cities in North Carolina and their populations in 2013. - trie_map_type nc_cities(entries, MDDS_N_ELEMENTS(entries)); + //!code-start: inst + trie_map_type nc_cities(entries, std::size(entries)); + //!code-end: inst - cout << "Cities that start with 'Cha' and their populations:" << endl; + std::cout << "Cities that start with 'Cha' and their populations:" << std::endl; auto results = nc_cities.prefix_search("Cha"); for (const auto& kv : results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } - cout << "Cities that start with 'W' and their populations:" << endl; + std::cout << "Cities that start with 'W' and their populations:" << std::endl; results = nc_cities.prefix_search("W"); for (const auto& kv : results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } - cout << "Cities that start with 'C' and their populations:" << endl; + std::cout << "Cities that start with 'C' and their populations:" << std::endl; results = nc_cities.prefix_search("C"); for (const auto& kv : results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } // Individual search. auto it = nc_cities.find("Wilmington"); - cout << "Population of Wilmington: " << it->second << endl; + std::cout << "Population of Wilmington: " << it->second << std::endl; // You get an end position iterator when the container doesn't have the // specified key. it = nc_cities.find("Asheboro"); - cout << "Population of Asheboro: "; + std::cout << "Population of Asheboro: "; if (it == nc_cities.end()) - cout << "not found"; + std::cout << "not found"; else - cout << it->second; + std::cout << it->second; - cout << endl; + std::cout << std::endl; return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/example/packed_trie_state_custom.cpp mdds-3.1.0/example/packed_trie_state_custom.cpp --- mdds-2.1.1/example/packed_trie_state_custom.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/packed_trie_state_custom.cpp 2024-02-07 03:12:37.000000000 +0000 @@ -26,13 +26,15 @@ * ************************************************************************/ +#ifdef NDEBUG +#undef NDEBUG +#endif +#include #include #include #include -using std::cout; -using std::endl; - +//!code-start: value-type enum affiliated_party_t : uint8_t { unaffiliated = 0, @@ -50,6 +52,7 @@ uint16_t year; affiliated_party_t party; }; +//!code-end: value-type std::ostream& operator<< (std::ostream& os, affiliated_party_t v) { @@ -73,6 +76,7 @@ return left.year == right.year && left.party == right.party; } +//!code-start: custom-serializer struct us_president_serializer { union bin_buffer @@ -83,7 +87,7 @@ }; static constexpr bool variable_size = false; - static constexpr size_t value_size = 3; + static constexpr std::size_t value_size = 3; static void write(std::ostream& os, const us_president& v) { @@ -98,7 +102,7 @@ os.write(buf.buffer, 1); } - static void read(std::istream& is, size_t /*n*/, us_president& v) + static void read(std::istream& is, std::size_t n, us_president& v) { // For a fixed-size value type, this should equal the defined value size. assert(n == 3); @@ -114,16 +118,19 @@ v.party = buf.party; } }; +//!code-end: custom-serializer int main() try { - - using map_type = mdds::packed_trie_map; + //!code-start: trie-type + using map_type = mdds::packed_trie_map; + //!code-end: trie-type // source: https://en.wikipedia.org/wiki/List_of_presidents_of_the_United_States // // The entries must be sorted by the keys. + //!code-start: entries std::vector entries = { { MDDS_ASCII("Abraham Lincoln"), { 1861, republican_national_union } }, @@ -172,34 +179,45 @@ { MDDS_ASCII("Woodrow Wilson"), { 1913, democratic } }, { MDDS_ASCII("Zachary Taylor"), { 1849, whig } }, }; + //!code-end: entries + //!code-start: inst map_type us_presidents(entries.data(), entries.size()); - cout << "Number of entries: " << us_presidents.size() << endl; + //!code-end: inst + //!code-start: print-n-entries + std::cout << "Number of entries: " << us_presidents.size() << std::endl; + //!code-end: print-n-entries - cout << endl; + std::cout << std::endl; { + //!code-start: save-state std::ofstream outfile("us-presidents.bin", std::ios::binary); us_presidents.save_state(outfile); + //!code-end: save-state } + //!code-start: load-state map_type us_presidents_loaded; - { - std::ifstream infile("us-presidents.bin", std::ios::binary); - us_presidents_loaded.load_state(infile); - } - - std::ios_base::fmtflags origflags = cout.flags(); - cout << "Equal to the original? " << std::boolalpha << (us_presidents == us_presidents_loaded) << endl; - cout.setf(origflags); + std::ifstream infile("us-presidents.bin", std::ios::binary); + us_presidents_loaded.load_state(infile); + //!code-end: load-state + + std::ios_base::fmtflags origflags = std::cout.flags(); + //!code-start: compare + std::cout << "Equal to the original? " << std::boolalpha << (us_presidents == us_presidents_loaded) << std::endl; + //!code-end: compare + std::cout.setf(origflags); - cout << endl; + std::cout << std::endl; - cout << "Presidents whose first name is 'John':" << endl; + //!code-start: search-john + std::cout << "Presidents whose first name is 'John':" << std::endl; auto results = us_presidents_loaded.prefix_search("John"); for (const auto& entry : results) - cout << " * " << entry.first << " (" << entry.second.year << "; " << entry.second.party << ")" << endl; + std::cout << " * " << entry.first << " (" << entry.second.year << "; " << entry.second.party << ")" << std::endl; + //!code-end: search-john return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/example/packed_trie_state_int.cpp mdds-3.1.0/example/packed_trie_state_int.cpp --- mdds-2.1.1/example/packed_trie_state_int.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/packed_trie_state_int.cpp 2024-02-07 03:12:37.000000000 +0000 @@ -31,18 +31,18 @@ #include #include -using std::cout; -using std::endl; - int main() try { - using map_type = mdds::packed_trie_map; + //!code-start: type + using map_type = mdds::packed_trie_map; + //!code-end: type // List of world's largest cities and their populations. The entries must // be sorted by the keys. // // c.f. https://en.wikipedia.org/wiki/List_of_largest_cities#cities + //!code-start: entries std::vector entries = { { MDDS_ASCII("Ahmedabad"), 7681000 }, @@ -127,47 +127,63 @@ { MDDS_ASCII("Xi'an"), 7444000 }, { MDDS_ASCII("Yangon"), 5157000 }, }; + //!code-end: entries + //!code-start: inst map_type cities(entries.data(), entries.size()); - cout << "Number of cities: " << cities.size() << endl; + //!code-end: inst + + //!code-start: print-n-cities + std::cout << "Number of cities: " << cities.size() << std::endl; + //!code-end: print-n-cities - cout << endl; + std::cout << std::endl; { - cout << "Cities that begin with 'S':" << endl; + //!code-start: search-s + std::cout << "Cities that begin with 'S':" << std::endl; auto results = cities.prefix_search("S"); for (const auto& city : results) - cout << " * " << city.first << ": " << city.second << endl; + std::cout << " * " << city.first << ": " << city.second << std::endl; + //!code-end: search-s } - cout << endl; + std::cout << std::endl; { + //!code-start: save-state-cities std::ofstream outfile("cities.bin", std::ios::binary); cities.save_state(outfile); + //!code-end: save-state-cities } + //!code-start: load-state-cities map_type cities_loaded; - { - std::ifstream infile("cities.bin", std::ios::binary); - cities_loaded.load_state(infile); - } - - std::ios_base::fmtflags origflags = cout.flags(); - cout << "Equal to the original? " << std::boolalpha << (cities == cities_loaded) << endl; - cout.setf(origflags); - - cout << endl; - - cout << "Number of cities: " << cities_loaded.size() << endl; + std::ifstream infile("cities.bin", std::ios::binary); + cities_loaded.load_state(infile); + //!code-end: load-state-cities + + std::ios_base::fmtflags origflags = std::cout.flags(); + //!code-start: check-equal + std::cout << "Equal to the original? " << std::boolalpha << (cities == cities_loaded) << std::endl; + //!code-end: check-equal + std::cout.setf(origflags); + + std::cout << std::endl; + + //!code-start: print-n-cities-2 + std::cout << "Number of cities: " << cities_loaded.size() << std::endl; + //!code-end: print-n-cities-2 - cout << endl; + std::cout << std::endl; - cout << "Cities that begin with 'S':" << endl; + //!code-start: search-s-2 + std::cout << "Cities that begin with 'S':" << std::endl; auto results = cities_loaded.prefix_search("S"); for (const auto& city : results) - cout << " * " << city.first << ": " << city.second << endl; + std::cout << " * " << city.first << ": " << city.second << std::endl; + //!code-end: search-s-2 return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/example/rtree_erase.cpp mdds-3.1.0/example/rtree_erase.cpp --- mdds-2.1.1/example/rtree_erase.cpp 2022-08-08 23:42:16.000000000 +0000 +++ mdds-3.1.0/example/rtree_erase.cpp 2025-01-22 02:40:24.000000000 +0000 @@ -33,6 +33,7 @@ int main() try { + //!code-start: remove-value using rt_type = mdds::rtree; rt_type tree; @@ -68,6 +69,8 @@ for (const std::string& v : results) std::cout << v << std::endl; + //!code-end: remove-value + return EXIT_SUCCESS; } catch (...) diff -Nru mdds-2.1.1/example/rtree_medium.cpp mdds-3.1.0/example/rtree_medium.cpp --- mdds-2.1.1/example/rtree_medium.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/rtree_medium.cpp 2025-01-22 02:40:24.000000000 +0000 @@ -31,6 +31,7 @@ #include #include +//!code-start: tree-type // Make the node capacity intentionally small. struct tiny_traits_2d { @@ -44,9 +45,11 @@ }; using rt_type = mdds::rtree; +//!code-end: tree-type int main() try { + //!code-start: input-data // 2D rectangle with the top-left position (x, y), width and height. struct rect { @@ -90,18 +93,23 @@ { 19778, 15394, 1356, 626 }, { 22969, 15394, 631, 2066 }, }; + //!code-end: input-data + //!code-start: insert rt_type tree; // Insert the rectangle objects into the tree. int value = 0; for (const auto& rect : rects) tree.insert({{rect.x, rect.y}, {rect.x + rect.w, rect.y + rect.h}}, value++); + //!code-end: insert + //!code-start: export // Export the tree structure as a SVG for visualization. std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); std::ofstream fout("bounds.svg"); fout << tree_svg; + //!code-end: export return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/example/rtree_medium_bulkload.cpp mdds-3.1.0/example/rtree_medium_bulkload.cpp --- mdds-2.1.1/example/rtree_medium_bulkload.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/rtree_medium_bulkload.cpp 2025-01-22 02:40:24.000000000 +0000 @@ -31,6 +31,7 @@ #include #include +//!code-start: tree-type // Make the node capacity intentionally small. struct tiny_traits_2d { @@ -44,7 +45,9 @@ }; using rt_type = mdds::rtree; +//!code-end: tree-type +//!code-start: input-data // 2D rectangle with the top-left position (x, y), width and height. struct rect { @@ -108,9 +111,11 @@ { 38209, 9254, 1908, 1781 }, { 2269, 56497, 2289, 892 }, }; +//!code-end: input-data void load_tree() { + //!code-start: normal-load rt_type tree; // Insert the rectangle objects into the tree. @@ -122,10 +127,12 @@ std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); std::ofstream fout("bounds2.svg"); fout << tree_svg; + //!code-end: normal-load } void bulkload_tree() { + //!code-start: bulkload rt_type::bulk_loader loader; // Insert the rectangle objects into the tree. @@ -140,6 +147,7 @@ std::string tree_svg = tree.export_tree(rt_type::export_tree_type::extent_as_svg); std::ofstream fout("bounds2-bulkload.svg"); fout << tree_svg; + //!code-end: bulkload } int main() try diff -Nru mdds-2.1.1/example/rtree_simple.cpp mdds-3.1.0/example/rtree_simple.cpp --- mdds-2.1.1/example/rtree_simple.cpp 2022-08-08 23:42:16.000000000 +0000 +++ mdds-3.1.0/example/rtree_simple.cpp 2025-01-22 02:40:24.000000000 +0000 @@ -26,60 +26,82 @@ * ************************************************************************/ +//!code-start: type #include #include #include +// key values are of type double, and we are storing std::string as a +// value for each spatial object. By default, tree becomes 2-dimensional +// object store unless otherwise specified. +using rt_type = mdds::rtree; +//!code-end: type + int main() try { - // key values are of type double, and we are storing std::string as a - // value for each spatial object. By default, tree becomes 2-dimensional - // object store unless otherwise specified. - using rt_type = mdds::rtree; - + //!code-start: instantiate rt_type tree; + //!code-end: instantiate + //!code-start: insert-1 tree.insert({{0.0, 0.0}, {15.0, 20.0}}, "first rectangle data"); + //!code-end: insert-1 + //!code-start: insert-2 rt_type::extent_type bounds({-2.0, -1.0}, {1.0, 2.0}); std::cout << "inserting value for " << bounds.to_string() << std::endl; tree.insert(bounds, "second rectangle data"); + //!code-end: insert-2 + //!code-start: insert-3 bounds.start.d[0] = -1.0; // Change the first dimension value of the start rectangle point. bounds.end.d[1] += 1.0; // Increment the second dimension value of the end rectangle point. std::cout << "inserting value for " << bounds.to_string() << std::endl; tree.insert(bounds, "third rectangle data"); + //!code-end: insert-3 + //!code-start: insert-pt-1 tree.insert({5.0, 6.0}, "first point data"); + //!code-end: insert-pt-1 { + //!code-start: search-overlap // Search for all objects that overlap with a (4, 4) - (7, 7) rectangle. auto results = tree.search({{4.0, 4.0}, {7.0, 7.0}}, rt_type::search_type::overlap); for (const std::string& v : results) std::cout << "value: " << v << std::endl; + //!code-end: search-overlap } { + //!code-start: search-match-1 // Search for all objects whose bounding rectangles are exactly (4, 4) - (7, 7). auto results = tree.search({{4.0, 4.0}, {7.0, 7.0}}, rt_type::search_type::match); std::cout << "number of results: " << std::distance(results.begin(), results.end()) << std::endl; + //!code-end: search-match-1 } { + //!code-start: search-match-2 // Search for all objects whose bounding rectangles are exactly (0, 0) - (15, 20). auto results = tree.search({{0.0, 0.0}, {15.0, 20.0}}, rt_type::search_type::match); std::cout << "number of results: " << std::distance(results.begin(), results.end()) << std::endl; + //!code-end: search-match-2 + //!code-start: iterator-deref std::cout << "value: " << *results.begin() << std::endl; + //!code-end: iterator-deref std::cout << "--" << std::endl; + //!code-start: iterator-attrs auto it = results.begin(); std::cout << "value: " << *it << std::endl; std::cout << "extent: " << it.extent().to_string() << std::endl; std::cout << "depth: " << it.depth() << std::endl; + //!code-end: iterator-attrs } return EXIT_SUCCESS; diff -Nru mdds-2.1.1/example/segment_tree.cpp mdds-3.1.0/example/segment_tree.cpp --- mdds-2.1.1/example/segment_tree.cpp 2022-08-08 23:42:16.000000000 +0000 +++ mdds-3.1.0/example/segment_tree.cpp 2023-12-22 02:48:40.000000000 +0000 @@ -1,7 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * - * Copyright (c) 2020 Kohei Yoshida + * Copyright (c) 2020-2023 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,44 +26,94 @@ * ************************************************************************/ +//!code-start: header #include #include #include +//!code-end: header -using std::cout; -using std::endl; +//!code-start: type +using tree_type = mdds::segment_tree; +//!code-end: type -typedef ::mdds::segment_tree db_type; +//!code-start: search-and-print +void search_and_print(const tree_type& tree, long pos) +{ + auto results = tree.search(pos); + + std::cout << "--" << std::endl; + std::cout << "search at " << pos << std::endl; + std::cout << "number of results: " << results.size() << std::endl; + + for (const auto& [start, end, value] : results) + std::cout << "range: [" << start << ":" << end << "); value: " << value << std::endl; +} +//!code-end: search-and-print -struct string_printer +void erase_by_iterator(tree_type tree) { - void operator() (const std::string& s) const + //!code-start: erase-by-iterator + auto results = tree.search(5); + for (auto it = results.begin(); it != results.end(); ++it) { - cout << "search hit: " << s << endl; + if (it->value == "A") + { + tree.erase(it); + break; + } } -}; + //!code-end: erase-by-iterator + + //!code-start: search-5-after-erase-by-iterator + search_and_print(tree, 5); + //!code-end: search-5-after-erase-by-iterator +} + +void erase_by_predicate(tree_type tree) +{ + //!code-start: erase-by-predicate + auto pred = [](long start, long end, const std::string& /*value*/) + { + return start <= 5 && 5 < end; + }; + + auto n = tree.erase_if(pred); + + std::cout << "--" << std::endl; + std::cout << n << " segments have been removed" << std::endl; + //!code-end: erase-by-predicate + + //!code-start: search-5-after-erase-by-predicate + search_and_print(tree, 5); + //!code-end: search-5-after-erase-by-predicate +} int main() try { - db_type db; - std::string A("A"); - std::string B("B"); - std::string C("C"); - - // Insert data into the tree. - db.insert(0, 10, A); - db.insert(2, 20, B); - db.insert(10, 15, C); - - // Don't forget to build it before calling search(). - db.build_tree(); - - // Run search and get the result. - db_type::search_results result = db.search(5); - - // Print the result. - cout << "result size: " << result.size() << endl; - std::for_each(result.begin(), result.end(), string_printer()); + //!code-start: insert + tree_type tree; + + tree.insert(0, 10, "A"); + tree.insert(2, 15, "B"); + tree.insert(-2, 5, "C"); + tree.insert(5, 22, "D"); + tree.insert(20, 35, "E"); + //!code-end: insert + + //!code-start: build + tree.build_tree(); + //!code-end: build + + //!code-start: search-5 + search_and_print(tree, 5); + //!code-end: search-5 + + //!code-start: search-0 + search_and_print(tree, 0); + //!code-end: search-0 + + erase_by_iterator(tree); + erase_by_predicate(tree); } catch (...) { diff -Nru mdds-2.1.1/example/sorted_string_map.cpp mdds-3.1.0/example/sorted_string_map.cpp --- mdds-2.1.1/example/sorted_string_map.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/example/sorted_string_map.cpp 2024-01-10 23:45:35.000000000 +0000 @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +//!code-start: header +#include +#include +//!code-end: header + +//!code-start: enum +enum class us_state_t +{ + unknown, + alabama, + alaska, + arizona, + arkansas, + california, + colorado, + connecticut, + delaware, + florida, + georgia, + hawaii, + idaho, + illinois, + indiana, + iowa, + kansas, + kentucky, + louisiana, + maine, + maryland, + massachusetts, + michigan, + minnesota, + mississippi, + missouri, + montana, + nebraska, + nevada, + new_hampshire, + new_jersey, + new_mexico, + new_york, + north_carolina, + north_dakota, + ohio, + oklahoma, + oregon, + pennsylvania, + rhode_island, + south_carolina, + south_dakota, + tennessee, + texas, + utah, + vermont, + virginia, + washington, + west_virginia, + wisconsin, + wyoming, +}; +//!code-end: enum + +//!code-start: type +using us_state_map_type = mdds::sorted_string_map; +//!code-end: type + +//!code-start: entries +// Keys must be sorted in ascending order. +constexpr us_state_map_type::entry_type us_state_entries[] = { + { "Alabama", us_state_t::alabama }, + { "Alaska", us_state_t::alaska }, + { "Arizona", us_state_t::arizona }, + { "Arkansas", us_state_t::arkansas }, + { "California", us_state_t::california }, + { "Colorado", us_state_t::colorado }, + { "Connecticut", us_state_t::connecticut }, + { "Delaware", us_state_t::delaware }, + { "Florida", us_state_t::florida }, + { "Georgia", us_state_t::georgia }, + { "Hawaii", us_state_t::hawaii }, + { "Idaho", us_state_t::idaho }, + { "Illinois", us_state_t::illinois }, + { "Indiana", us_state_t::indiana }, + { "Iowa", us_state_t::iowa }, + { "Kansas", us_state_t::kansas }, + { "Kentucky", us_state_t::kentucky }, + { "Louisiana", us_state_t::louisiana }, + { "Maine", us_state_t::maine }, + { "Maryland", us_state_t::maryland }, + { "Massachusetts", us_state_t::massachusetts }, + { "Michigan", us_state_t::michigan }, + { "Minnesota", us_state_t::minnesota }, + { "Mississippi", us_state_t::mississippi }, + { "Missouri", us_state_t::missouri }, + { "Montana", us_state_t::montana }, + { "Nebraska", us_state_t::nebraska }, + { "Nevada", us_state_t::nevada }, + { "New Hampshire", us_state_t::new_hampshire }, + { "New Jersey", us_state_t::new_jersey }, + { "New Mexico", us_state_t::new_mexico }, + { "New York", us_state_t::new_york }, + { "North Carolina", us_state_t::north_carolina }, + { "North Dakota", us_state_t::north_dakota }, + { "Ohio", us_state_t::ohio }, + { "Oklahoma", us_state_t::oklahoma }, + { "Oregon", us_state_t::oregon }, + { "Pennsylvania", us_state_t::pennsylvania }, + { "Rhode Island", us_state_t::rhode_island }, + { "South Carolina", us_state_t::south_carolina }, + { "South Dakota", us_state_t::south_dakota }, + { "Tennessee", us_state_t::tennessee }, + { "Texas", us_state_t::texas }, + { "Utah", us_state_t::utah }, + { "Vermont", us_state_t::vermont }, + { "Virginia", us_state_t::virginia }, + { "Washington", us_state_t::washington }, + { "West Virginia", us_state_t::west_virginia }, + { "Wisconsin", us_state_t::wisconsin }, + { "Wyoming", us_state_t::wyoming }, +}; +//!code-end: entries + +int main() try +{ + auto zero = us_state_t{}; + std::cout << "unknown? " << std::boolalpha << (zero == us_state_t::unknown) << std::endl; + + //!code-start: init + const us_state_map_type state_map(us_state_entries, std::size(us_state_entries), us_state_t::unknown); + //!code-end: init + + //!code-start: find + auto state = state_map.find("Virginia"); + std::cout << "virginia? " << std::boolalpha << (state == us_state_t::virginia) << std::endl; + state = state_map.find("North Carolina"); + std::cout << "north_carolina? " << std::boolalpha << (state == us_state_t::north_carolina) << std::endl; + //!code-end: find + + //!code-start: find-null + state = state_map.find("Alberta"); + std::cout << "unknown? " << std::boolalpha << (state == us_state_t::unknown) << std::endl; + //!code-end: find-null + + //!code-start: find-key + auto key = state_map.find_key(us_state_t::rhode_island); + std::cout << "key for rhode_island: " << key << std::endl; + //!code-end: find-key + + return EXIT_SUCCESS; +} +catch (...) +{ + return EXIT_FAILURE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff -Nru mdds-2.1.1/example/trie_map.cpp mdds-3.1.0/example/trie_map.cpp --- mdds-2.1.1/example/trie_map.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/example/trie_map.cpp 2024-02-07 03:12:37.000000000 +0000 @@ -29,16 +29,18 @@ #include #include -using std::cout; -using std::endl; - int main() { - using trie_map_type = mdds::trie_map; + //!code-start: type + using trie_map_type = mdds::trie_map; + //!code-end: type + //!code-start: inst // Cities in North Carolina and their populations in 2013. trie_map_type nc_cities; + //!code-end: inst + //!code-start: populate // Insert key-value pairs. nc_cities.insert("Charlotte", 792862); nc_cities.insert("Raleigh", 431746); @@ -63,47 +65,59 @@ nc_cities.insert("Apex", 42214); nc_cities.insert("Hickory", 40361); nc_cities.insert("Goldsboro", 36306); + //!code-end: populate - cout << "Cities that start with 'Cha' and their populations:" << endl; + //!code-start: search-cha + std::cout << "Cities that start with 'Cha' and their populations:" << std::endl; auto results = nc_cities.prefix_search("Cha"); for (const auto& kv : results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } + //!code-end: search-cha - cout << "Cities that start with 'W' and their populations:" << endl; + //!code-start: search-w + std::cout << "Cities that start with 'W' and their populations:" << std::endl; results = nc_cities.prefix_search("W"); for (const auto& kv : results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } + //!code-end: search-w - // Create a compressed version of the container. It works nearly identically. + //!code-start: pack auto packed = nc_cities.pack(); + //!code-end: pack - cout << "Cities that start with 'C' and their populations:" << endl; + //!code-start: search-c + std::cout << "Cities that start with 'C' and their populations:" << std::endl; auto packed_results = packed.prefix_search("C"); for (const auto& kv : packed_results) { - cout << " " << kv.first << ": " << kv.second << endl; + std::cout << " " << kv.first << ": " << kv.second << std::endl; } + //!code-end: search-c + //!code-start: find-one // Individual search. auto it = packed.find("Wilmington"); - cout << "Population of Wilmington: " << it->second << endl; + std::cout << "Population of Wilmington: " << it->second << std::endl; + //!code-end: find-one + //!code-start: find-none // You get an end position iterator when the container doesn't have the // specified key. it = packed.find("Asheboro"); - cout << "Population of Asheboro: "; + std::cout << "Population of Asheboro: "; if (it == packed.end()) - cout << "not found"; + std::cout << "not found"; else - cout << it->second; + std::cout << it->second; - cout << endl; + std::cout << std::endl; + //!code-end: find-none return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/include/Makefile.in mdds-3.1.0/include/Makefile.in --- mdds-2.1.1/include/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/include/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/include/mdds/Makefile.am mdds-3.1.0/include/mdds/Makefile.am --- mdds-2.1.1/include/mdds/Makefile.am 2022-08-07 16:37:53.000000000 +0000 +++ mdds-3.1.0/include/mdds/Makefile.am 2024-01-17 01:43:30.000000000 +0000 @@ -3,6 +3,7 @@ headersdir = $(includedir)/mdds-@API_VERSION@/mdds headers_HEADERS = \ + cref_wrapper.hpp \ flat_segment_tree_def.inl \ flat_segment_tree.hpp \ flat_segment_tree_itr.hpp \ diff -Nru mdds-2.1.1/include/mdds/Makefile.in mdds-3.1.0/include/mdds/Makefile.in --- mdds-2.1.1/include/mdds/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/include/mdds/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -271,7 +271,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -329,6 +328,7 @@ SUBDIRS = multi_type_vector headersdir = $(includedir)/mdds-@API_VERSION@/mdds headers_HEADERS = \ + cref_wrapper.hpp \ flat_segment_tree_def.inl \ flat_segment_tree.hpp \ flat_segment_tree_itr.hpp \ diff -Nru mdds-2.1.1/include/mdds/cref_wrapper.hpp mdds-3.1.0/include/mdds/cref_wrapper.hpp --- mdds-2.1.1/include/mdds/cref_wrapper.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/include/mdds/cref_wrapper.hpp 2024-01-10 23:45:35.000000000 +0000 @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#pragma once + +#include +#include + +namespace mdds { namespace detail { + +/** + * Custom const reference wrapper with an equality operator and a hash + * adaptor. + */ +template +class cref_wrapper +{ + std::reference_wrapper> m_value; + +public: + cref_wrapper(const T& v) : m_value(std::cref(v)) + {} + + const T& get() const + { + return m_value; + } + + bool operator==(const cref_wrapper& r) const + { + return get() == r.get(); + } + + bool operator!=(const cref_wrapper& r) const + { + return !operator==(r); + } + + struct hash + { + std::size_t operator()(const cref_wrapper& v) const + { + // NB: hash value must be based on the wrapped value, else two + // identical values located in different memory locations may end up + // in different buckets, and the lookup may fail. + return std::hash{}(v.m_value); + } + }; +}; + +}} // namespace mdds::detail + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/flat_segment_tree.hpp mdds-3.1.0/include/mdds/flat_segment_tree.hpp --- mdds-2.1.1/include/mdds/flat_segment_tree.hpp 2023-04-24 23:21:34.000000000 +0000 +++ mdds-3.1.0/include/mdds/flat_segment_tree.hpp 2025-07-05 20:55:53.000000000 +0000 @@ -26,17 +26,16 @@ * ************************************************************************/ -#ifndef INCLUDED_MDDS_FLAT_SEGMENT_TREE_HPP -#define INCLUDED_MDDS_FLAT_SEGMENT_TREE_HPP +#pragma once #include #include #include #include -#include "mdds/node.hpp" -#include "mdds/flat_segment_tree_itr.hpp" -#include "mdds/global.hpp" +#include "./node.hpp" +#include "./flat_segment_tree_itr.hpp" +#include "./global.hpp" #ifdef MDDS_UNIT_TEST #include @@ -55,126 +54,29 @@ struct nonleaf_value_type { - key_type low; /// low range value (inclusive) - key_type high; /// high range value (non-inclusive) - - bool operator==(const nonleaf_value_type& r) const - { - return low == r.low && high == r.high; - } - - nonleaf_value_type() : low{}, high{} - {} }; struct leaf_value_type { - key_type key; value_type value; bool operator==(const leaf_value_type& r) const { - return key == r.key && value == r.value; + return value == r.value; } - leaf_value_type() : key{}, value{} - {} - }; - - // Handlers required by the node template class. - struct fill_nonleaf_value_handler; - struct init_handler; - struct dispose_handler; -#ifdef MDDS_UNIT_TEST - struct to_string_handler; -#endif - - typedef __st::node node; - typedef typename node::node_ptr node_ptr; - - typedef __st::nonleaf_node nonleaf_node; - - struct fill_nonleaf_value_handler - { - void operator()( - __st::nonleaf_node& _self, const __st::node_base* left_node, - const __st::node_base* right_node) + bool operator!=(const leaf_value_type& r) const { - // Parent node should carry the range of all of its child nodes. - if (left_node) - { - _self.value_nonleaf.low = left_node->is_leaf - ? static_cast(left_node)->value_leaf.key - : static_cast(left_node)->value_nonleaf.low; - } - else - { - // Having a left node is prerequisite. - throw general_error( - "flat_segment_tree::fill_nonleaf_value_handler: Having a left node is prerequisite."); - } - - if (right_node) - { - if (right_node->is_leaf) - { - // When the child nodes are leaf nodes, the upper bound - // must be the value of the node that comes after the - // right leaf node (if such node exists). - const node* p = static_cast(right_node); - if (p->next) - _self.value_nonleaf.high = p->next->value_leaf.key; - else - _self.value_nonleaf.high = p->value_leaf.key; - } - else - { - _self.value_nonleaf.high = static_cast(right_node)->value_nonleaf.high; - } - } - else - { - _self.value_nonleaf.high = left_node->is_leaf - ? static_cast(left_node)->value_leaf.key - : static_cast(left_node)->value_nonleaf.high; - } + return !operator==(r); } - }; -#ifdef MDDS_UNIT_TEST - struct to_string_handler - { - std::string operator()(const node& _self) const - { - std::ostringstream os; - os << "(" << _self.value_leaf.key << ") "; - return os.str(); - } - - std::string operator()(const mdds::__st::nonleaf_node& _self) const - { - std::ostringstream os; - os << "(" << _self.value_nonleaf.low << "-" << _self.value_nonleaf.high << ") "; - return os.str(); - } - }; -#endif - - struct init_handler - { - void operator()(node& /*_self*/) - {} - void operator()(__st::nonleaf_node& /*_self*/) + leaf_value_type() : value{} {} }; - struct dispose_handler - { - void operator()(node& /*_self*/) - {} - void operator()(__st::nonleaf_node& /*_self*/) - {} - }; + using node = st::detail::node; + using node_ptr = typename node::node_ptr; + using nonleaf_node = st::detail::nonleaf_node; private: friend struct ::mdds::fst::detail::forward_itr_handler; @@ -438,8 +340,7 @@ * the inserted segment, and a boolean value indicating whether or * not the insertion has modified the tree. */ - std::pair insert( - const const_iterator& pos, key_type start_key, key_type end_key, value_type val); + std::pair insert(const_iterator pos, key_type start_key, key_type end_key, value_type val); /** * Remove a segment specified by the start and end key values, and shift @@ -505,7 +406,7 @@ * whether or not the search has been successful. */ std::pair search( - const const_iterator& pos, key_type key, value_type& value, key_type* start_key = nullptr, + const_iterator pos, key_type key, value_type& value, key_type* start_key = nullptr, key_type* end_key = nullptr) const; /** @@ -531,7 +432,7 @@ * segment containing the key, or end iterator position if the * search has failed. */ - const_iterator search(const const_iterator& pos, key_type key) const; + const_iterator search(const_iterator pos, key_type key) const; /** * Perform tree search for a value associated with a key. This method @@ -578,7 +479,7 @@ * @return true if the tree is valid, otherwise false. The tree must be * valid before you can call the search_tree() method. */ - bool is_tree_valid() const + bool valid_tree() const noexcept { return m_valid_tree; } @@ -597,12 +498,12 @@ key_type min_key() const { - return m_left_leaf->value_leaf.key; + return m_left_leaf->key; } key_type max_key() const { - return m_right_leaf->value_leaf.key; + return m_right_leaf->key; } value_type default_value() const @@ -623,6 +524,29 @@ return m_root_node; } + struct tree_dumper_traits + { + using leaf_type = node; + using nonleaf_type = nonleaf_node; + using tree_type = flat_segment_tree; + + struct to_string + { + to_string(const tree_type&) + {} + + std::string operator()(const leaf_type& leaf) const + { + return leaf.to_string(); + } + + std::string operator()(const nonleaf_type& nonleaf) const + { + return nonleaf.to_string(); + } + }; + }; + void dump_tree() const { using ::std::cout; @@ -631,7 +555,7 @@ if (!m_valid_tree) assert(!"attempted to dump an invalid tree!"); - size_t node_count = mdds::__st::tree_dumper::dump(m_root_node); + size_t node_count = mdds::st::detail::tree_dumper::dump(std::cout, *this, m_root_node); size_t node_instance_count = node::get_instance_count(); size_t leaf_count = leaf_size(); @@ -652,8 +576,8 @@ long node_id = 0; while (cur_node) { - cout << " node " << node_id++ << ": key = " << cur_node->value_leaf.key - << "; value = " << cur_node->value_leaf.value << endl; + cout << " node " << node_id++ << ": key = " << cur_node->key << "; value = " << cur_node->value_leaf.value + << endl; cur_node = cur_node->next; } cout << endl << " node instance count = " << node::get_instance_count() << endl; @@ -678,7 +602,7 @@ // Position past the right-mode node. Invalid. return false; - if (cur_node->value_leaf.key != *itr) + if (cur_node->key != *itr) // Key values differ. return false; @@ -702,7 +626,7 @@ // Position past the left-mode node. Invalid. return false; - if (cur_node->value_leaf.key != *itr) + if (cur_node->key != *itr) // Key values differ. return false; @@ -758,7 +682,7 @@ void append_new_segment(key_type start_key) { - if (m_right_leaf->prev->value_leaf.key == start_key) + if (m_right_leaf->prev->key == start_key) { m_right_leaf->prev->value_leaf.value = m_init_val; return; @@ -767,7 +691,7 @@ #ifdef MDDS_UNIT_TEST // The start position must come after the position of the last node // before the right-most node. - assert(m_right_leaf->prev->value_leaf.key < start_key); + assert(m_right_leaf->prev->key < start_key); #endif if (m_right_leaf->prev->value_leaf.value == m_init_val) @@ -776,12 +700,12 @@ return; node_ptr new_node(new node); - new_node->value_leaf.key = start_key; + new_node->key = start_key; new_node->value_leaf.value = m_init_val; new_node->prev = m_right_leaf->prev; new_node->next = m_right_leaf; m_right_leaf->prev->next = new_node; - m_right_leaf->prev = new_node; + m_right_leaf->prev = std::move(new_node); m_valid_tree = false; } @@ -814,18 +738,18 @@ node* end_node_p = end_node.get(); while (cur_node_p != end_node_p) { - cur_node_p->value_leaf.key -= shift_value; + cur_node_p->key -= shift_value; cur_node_p = cur_node_p->next.get(); } } static void shift_leaf_key_right(node_ptr& cur_node, node_ptr& end_node, key_type shift_value) { - key_type end_node_key = end_node->value_leaf.key; + key_type end_node_key = end_node->key; while (cur_node.get() != end_node.get()) { - cur_node->value_leaf.key += shift_value; - if (cur_node->value_leaf.key < end_node_key) + cur_node->key += shift_value; + if (cur_node->key < end_node_key) { // The node is still in-bound. Keep shifting. cur_node = cur_node->next; @@ -841,10 +765,10 @@ { node_ptr next_node = cur_node->next; disconnect_all_nodes(cur_node.get()); - cur_node = next_node; + cur_node = std::move(next_node); } last_node->next = end_node; - end_node->prev = last_node; + end_node->prev = std::move(last_node); return; } } @@ -880,6 +804,4 @@ #include "flat_segment_tree_def.inl" -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/flat_segment_tree_def.inl mdds-3.1.0/include/mdds/flat_segment_tree_def.inl --- mdds-2.1.1/include/mdds/flat_segment_tree_def.inl 2023-04-19 19:28:17.000000000 +0000 +++ mdds-3.1.0/include/mdds/flat_segment_tree_def.inl 2025-07-05 20:55:53.000000000 +0000 @@ -83,11 +83,11 @@ m_valid_tree(false) { // we need to create two end nodes during initialization. - m_left_leaf->value_leaf.key = std::move(min_val); + m_left_leaf->key = std::move(min_val); m_left_leaf->value_leaf.value = m_init_val; // copy m_left_leaf->next = m_right_leaf; - m_right_leaf->value_leaf.key = std::move(max_val); + m_right_leaf->key = std::move(max_val); m_right_leaf->prev = m_left_leaf; // We don't ever use the value of the right leaf node, but we need the @@ -115,7 +115,7 @@ // back to the previous node. node_ptr old_node = dest_node; dest_node = dest_node->next; - dest_node->prev = old_node; + dest_node->prev = std::move(old_node); if (src_node == r.m_right_leaf.get()) { @@ -183,7 +183,7 @@ destroy(); // and construct the default tree - __st::link_nodes(m_left_leaf, m_right_leaf); + st::detail::link_nodes(m_left_leaf, m_right_leaf); m_left_leaf->value_leaf.value = m_init_val; m_valid_tree = false; } @@ -221,7 +221,7 @@ return ret_type(const_iterator(this, true), false); } - return insert_to_pos(start_pos, std::move(start_key), std::move(end_key), std::move(val)); + return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val)); } template @@ -243,7 +243,7 @@ bool changed = false; - if (start_pos->value_leaf.key == start_key) + if (start_pos->key == start_key) { // Re-use the existing node, but save the old value for later. @@ -258,7 +258,7 @@ // Update the value of the existing node. old_value = start_pos->value_leaf.value; start_pos->value_leaf.value = val; - new_start_node = start_pos; + new_start_node = std::move(start_pos); changed = (old_value != val); } @@ -273,7 +273,7 @@ { // Insert a new node before the insertion position node. node_ptr new_node(new node); - new_node->value_leaf.key = std::move(start_key); + new_node->key = std::move(start_key); new_node->value_leaf.value = val; new_start_node = new_node; @@ -281,10 +281,10 @@ old_value = left_node->value_leaf.value; // Link to the left node. - __st::link_nodes(left_node, new_node); + st::detail::link_nodes(left_node, new_node); // Link to the right node. - __st::link_nodes(new_node, start_pos); + st::detail::link_nodes(new_node, start_pos); changed = true; } @@ -302,7 +302,7 @@ // Set the end node. - if (end_pos->value_leaf.key == end_key) + if (end_pos->key == end_key) { // The new segment ends exactly at the end node position. @@ -328,7 +328,7 @@ { if (new_start_node->next != end_pos) { - __st::link_nodes(new_start_node, end_pos); + st::detail::link_nodes(new_start_node, end_pos); changed = true; } } @@ -336,14 +336,14 @@ { // Insert a new node before the insertion position node. node_ptr new_node(new node); - new_node->value_leaf.key = std::move(end_key); - new_node->value_leaf.value = old_value; + new_node->key = std::move(end_key); + new_node->value_leaf.value = std::move(old_value); // Link to the left node. - __st::link_nodes(new_start_node, new_node); + st::detail::link_nodes(new_start_node, new_node); // Link to the right node. - __st::link_nodes(new_node, end_pos); + st::detail::link_nodes(new_node, end_pos); changed = true; } @@ -355,7 +355,7 @@ template ::std::pair::const_iterator, bool> flat_segment_tree::insert( - const const_iterator& pos, key_type start_key, key_type end_key, value_type val) + const_iterator pos, key_type start_key, key_type end_key, value_type val) { const node* p = pos.get_pos(); if (!p || this != pos.get_parent()) @@ -366,7 +366,7 @@ assert(p->is_leaf); - if (start_key < p->value_leaf.key) + if (start_key < p->key) { // Specified position is already past the start key position. Not good. return insert_front(start_key, end_key, val); @@ -380,7 +380,7 @@ p = get_insertion_pos_leaf(start_key, p); node_ptr start_pos(const_cast(p)); - return insert_to_pos(start_pos, start_key, end_key, val); + return insert_to_pos(std::move(start_pos), start_key, end_key, std::move(val)); } template @@ -389,8 +389,8 @@ if (start_key >= end_key) return; - key_type left_leaf_key = m_left_leaf->value_leaf.key; - key_type right_leaf_key = m_right_leaf->value_leaf.key; + key_type left_leaf_key = m_left_leaf->key; + key_type right_leaf_key = m_right_leaf->key; if (start_key < left_leaf_key || end_key < left_leaf_key) // invalid key value return; @@ -434,7 +434,7 @@ return; } - if (end_key < node_pos->value_leaf.key) + if (end_key < node_pos->key) { // The removed segment does not overlap with any nodes. Simply // shift the key values of those nodes that come after the removed @@ -447,16 +447,16 @@ // Move the first node to the starting position, and from there search // for the first node whose key value is greater than the end value. - node_pos->value_leaf.key = start_key; + node_pos->key = start_key; node_ptr start_pos = node_pos; node_pos = node_pos->next; value_type last_seg_value = start_pos->value_leaf.value; - while (node_pos.get() != m_right_leaf.get() && node_pos->value_leaf.key <= end_key) + while (node_pos.get() != m_right_leaf.get() && node_pos->key <= end_key) { last_seg_value = node_pos->value_leaf.value; node_ptr next = node_pos->next; disconnect_all_nodes(node_pos.get()); - node_pos = next; + node_pos = std::move(next); } start_pos->value_leaf.value = last_seg_value; @@ -486,11 +486,11 @@ if (size <= 0) return; - if (pos < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= pos) + if (pos < m_left_leaf->key || m_right_leaf->key <= pos) // specified position is out-of-bound return; - if (m_left_leaf->value_leaf.key == pos) + if (m_left_leaf->key == pos) { // Position is at the leftmost node. Shift all the other nodes, // and insert a new node at (pos + size) position. @@ -499,18 +499,18 @@ if (m_left_leaf->value_leaf.value != m_init_val && !skip_start_node) { - if (size < m_right_leaf->value_leaf.key - m_left_leaf->value_leaf.key) + if (size < m_right_leaf->key - m_left_leaf->key) { // The leftmost leaf node has a non-initial value. We need to // insert a new node to carry that value after the shift. node_ptr new_node(new node); - new_node->value_leaf.key = pos + size; + new_node->key = pos + size; new_node->value_leaf.value = m_left_leaf->value_leaf.value; m_left_leaf->value_leaf.value = m_init_val; new_node->prev = m_left_leaf; new_node->next = m_left_leaf->next; m_left_leaf->next->prev = new_node; - m_left_leaf->next = new_node; + m_left_leaf->next = std::move(new_node); } else { @@ -532,7 +532,7 @@ // If the point of insertion is at an existing node position, don't // shift that node but start with the one after it if that's // requested. - if (skip_start_node && cur_node && cur_node->value_leaf.key == pos) + if (skip_start_node && cur_node && cur_node->key == pos) cur_node = cur_node->next; if (!cur_node) @@ -548,22 +548,22 @@ { typedef ::std::pair ret_type; - if (pos->value_leaf.key == key) + if (pos->key == key) { value = pos->value_leaf.value; if (start_key) - *start_key = pos->value_leaf.key; + *start_key = pos->key; if (end_key && pos->next) - *end_key = pos->next->value_leaf.key; + *end_key = pos->next->key; return ret_type(const_iterator(this, pos), true); } - else if (pos->prev && pos->prev->value_leaf.key < key) + else if (pos->prev && pos->prev->key < key) { value = pos->prev->value_leaf.value; if (start_key) - *start_key = pos->prev->value_leaf.key; + *start_key = pos->prev->key; if (end_key) - *end_key = pos->value_leaf.key; + *end_key = pos->key; return ret_type(const_iterator(this, pos->prev.get()), true); } @@ -576,7 +576,7 @@ { typedef ::std::pair ret_type; - if (key < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= key) + if (key < m_left_leaf->key || m_right_leaf->key <= key) // key value is out-of-bound. return ret_type(const_iterator(this, true), false); @@ -586,11 +586,11 @@ template ::std::pair::const_iterator, bool> flat_segment_tree::search( - const const_iterator& pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const + const_iterator pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const { typedef ::std::pair ret_type; - if (key < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= key) + if (key < m_left_leaf->key || m_right_leaf->key <= key) // key value is out-of-bound. return ret_type(const_iterator(this, true), false); @@ -603,7 +603,7 @@ assert(p->is_leaf); - if (key < p->value_leaf.key) + if (key < p->key) { // Specified position is already past the start key position. Fall // back to normal search. @@ -622,7 +622,7 @@ template typename flat_segment_tree::const_iterator flat_segment_tree::search( - const const_iterator& pos, key_type key) const + const_iterator pos, key_type key) const { return search_by_key_impl(pos.get_pos(), key); } @@ -631,7 +631,7 @@ typename flat_segment_tree::const_iterator flat_segment_tree::search_by_key_impl( const node* start_pos, key_type key) const { - if (key < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= key) + if (key < m_left_leaf->key || m_right_leaf->key <= key) // key value is out-of-bound. return const_iterator(this, true); @@ -639,9 +639,9 @@ if (!pos) return const_iterator(this, true); - if (pos->value_leaf.key == key) + if (pos->key == key) return const_iterator(this, pos); - else if (pos->prev && pos->prev->value_leaf.key < key) + else if (pos->prev && pos->prev->key < key) return const_iterator(this, pos->prev.get()); return const_iterator(this, true); @@ -659,16 +659,16 @@ value = dest_node->value_leaf.value; if (start_key) - *start_key = dest_node->value_leaf.key; + *start_key = dest_node->key; if (end_key) { assert(dest_node->next); if (dest_node->next) - *end_key = dest_node->next->value_leaf.key; + *end_key = dest_node->next->key; else // This should never happen, but just in case.... - *end_key = m_right_leaf->value_leaf.key; + *end_key = m_right_leaf->key; } return ret_type(const_iterator(this, dest_node), true); @@ -694,7 +694,7 @@ return nullptr; } - if (key < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= key) + if (key < m_left_leaf->key || m_right_leaf->key <= key) { // key value is out-of-bound. return nullptr; @@ -711,8 +711,7 @@ break; const nonleaf_node* left_nonleaf = static_cast(cur_node->left); - const nonleaf_value_type& v = left_nonleaf->value_nonleaf; - if (v.low <= key && key < v.high) + if (left_nonleaf->low <= key && key < left_nonleaf->high) { // Descend one level through the left child node. cur_node = left_nonleaf; @@ -729,8 +728,7 @@ { assert(!cur_node->right->is_leaf); const nonleaf_node* right_nonleaf = static_cast(cur_node->right); - const nonleaf_value_type& v = right_nonleaf->value_nonleaf; - if (v.low <= key && key < v.high) + if (right_nonleaf->low <= key && key < right_nonleaf->high) { // Descend one level through the right child node. cur_node = right_nonleaf; @@ -746,14 +744,14 @@ const node* dest_node = nullptr; const node* leaf_left = static_cast(cur_node->left); const node* leaf_right = static_cast(cur_node->right); - key_type key1 = leaf_left->value_leaf.key; - key_type key2 = leaf_right->value_leaf.key; + key_type key1 = leaf_left->key; + key_type key2 = leaf_right->key; if (key1 <= key && key < key2) { dest_node = leaf_left; } - else if (key2 <= key && key < cur_node->value_nonleaf.high) + else if (key2 <= key && key < cur_node->high) { dest_node = leaf_right; } @@ -776,10 +774,10 @@ size_t leaf_count = leaf_size(); // Determine the total number of non-leaf nodes needed to build the whole tree. - size_t nonleaf_count = __st::count_needed_nonleaf_nodes(leaf_count); + size_t nonleaf_count = st::detail::count_needed_nonleaf_nodes(leaf_count); m_nonleaf_node_pool.resize(nonleaf_count); - mdds::__st::tree_builder builder(m_nonleaf_node_pool); + mdds::st::detail::tree_builder builder(m_nonleaf_node_pool); m_root_node = builder.build(m_left_leaf); m_valid_tree = true; } @@ -787,7 +785,7 @@ template typename flat_segment_tree::size_type flat_segment_tree::leaf_size() const { - return __st::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); + return st::detail::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); } template @@ -805,7 +803,10 @@ if (!n2) return false; - if (!n1->equals(*n2)) + if (n1->key != n2->key) + return false; + + if (n1->value_leaf != n2->value_leaf) return false; n1 = n1->next.get(); @@ -827,7 +828,7 @@ const node* cur_node = start_pos; while (cur_node) { - if (cur_node->value_leaf.key < key) + if (cur_node->key < key) { // Found the insertion position. return cur_node; @@ -841,12 +842,12 @@ const typename flat_segment_tree::node* flat_segment_tree::get_insertion_pos_leaf( const key_type& key, const node* start_pos) const { - assert(m_left_leaf->value_leaf.key <= key); + assert(m_left_leaf->key <= key); const node* cur_node = start_pos; while (cur_node) { - if (key <= cur_node->value_leaf.key) + if (key <= cur_node->key) { // Found the insertion position. return cur_node; @@ -871,17 +872,17 @@ // Invalid order of segment range. return false; - if (end_key < m_left_leaf->value_leaf.key || m_right_leaf->value_leaf.key <= start_key) + if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key) // The new segment does not overlap the current interval. return false; - if (start_key < m_left_leaf->value_leaf.key) + if (start_key < m_left_leaf->key) // The start value should not be smaller than the current minimum. - start_key = m_left_leaf->value_leaf.key; + start_key = m_left_leaf->key; - if (m_right_leaf->value_leaf.key < end_key) + if (m_right_leaf->key < end_key) // The end value should not be larger than the current maximum. - end_key = m_right_leaf->value_leaf.key; + end_key = m_right_leaf->key; return true; } diff -Nru mdds-2.1.1/include/mdds/flat_segment_tree_itr.hpp mdds-3.1.0/include/mdds/flat_segment_tree_itr.hpp --- mdds-2.1.1/include/mdds/flat_segment_tree_itr.hpp 2023-04-19 19:28:17.000000000 +0000 +++ mdds-3.1.0/include/mdds/flat_segment_tree_itr.hpp 2025-07-05 20:40:36.000000000 +0000 @@ -25,8 +25,10 @@ * ************************************************************************/ -#ifndef INCLUDED_MDDS_FLAT_SEGMENT_TREE_ITR_HPP -#define INCLUDED_MDDS_FLAT_SEGMENT_TREE_ITR_HPP +#pragma once + +#include "./ref_pair.hpp" +#include namespace mdds { namespace fst { namespace detail { @@ -99,13 +101,14 @@ typedef FstType fst_type; // iterator traits - typedef ::std::pair value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef ptrdiff_t difference_type; - typedef ::std::bidirectional_iterator_tag iterator_category; + using value_type = mdds::detail::ref_pair< + std::add_const_t, std::add_const_t>; + using pointer = value_type*; + using reference = value_type&; + using difference_type = ptrdiff_t; + using iterator_category = ::std::bidirectional_iterator_tag; - explicit const_iterator_base(const fst_type* _db, bool _end) : m_db(_db), m_pos(nullptr), m_end_pos(_end) + explicit const_iterator_base(const fst_type* _db, bool _end) : m_db(_db), m_end_pos(_end) { if (!_db) return; @@ -113,8 +116,7 @@ m_pos = handler_type::init_pos(_db, _end); } - explicit const_iterator_base(const fst_type* _db, const typename fst_type::node* pos) - : m_db(_db), m_pos(pos), m_end_pos(false) + explicit const_iterator_base(const fst_type* _db, const typename fst_type::node* pos) : m_db(_db), m_pos(pos) {} const_iterator_base(const const_iterator_base& r) : m_db(r.m_db), m_pos(r.m_pos), m_end_pos(r.m_end_pos) @@ -155,14 +157,14 @@ return !operator==(r); } - const value_type& operator*() + value_type operator*() { - return get_current_node_pair(); + return value_type(m_pos->key, m_pos->value_leaf.value); } - const value_type* operator->() + value_type operator->() { - return &get_current_node_pair(); + return value_type(m_pos->key, m_pos->value_leaf.value); } protected: @@ -182,16 +184,9 @@ } private: - const value_type& get_current_node_pair() - { - m_current_pair = value_type(m_pos->value_leaf.key, m_pos->value_leaf.value); - return m_current_pair; - } - - const fst_type* m_db; - const typename fst_type::node* m_pos; - value_type m_current_pair; - bool m_end_pos; + const fst_type* m_db = nullptr; + const typename fst_type::node* m_pos = nullptr; + bool m_end_pos = false; }; template @@ -332,8 +327,8 @@ // The iterator is at its end position. Nothing to do. return; - m_node.start = m_start->value_leaf.key; - m_node.end = m_end->value_leaf.key; + m_node.start = m_start->key; + m_node.end = m_end->key; m_node.value = m_start->value_leaf.value; } @@ -344,5 +339,3 @@ }; }}} // namespace mdds::fst::detail - -#endif diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/Makefile.am mdds-3.1.0/include/mdds/multi_type_vector/Makefile.am --- mdds-2.1.1/include/mdds/multi_type_vector/Makefile.am 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/Makefile.am 2025-05-29 02:14:48.000000000 +0000 @@ -6,6 +6,7 @@ block_funcs.hpp \ collection_def.inl \ collection.hpp \ + delayed_delete_vector.hpp \ env.hpp \ iterator_node.hpp \ macro.hpp \ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/Makefile.in mdds-3.1.0/include/mdds/multi_type_vector/Makefile.in --- mdds-2.1.1/include/mdds/multi_type_vector/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -271,7 +271,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -332,6 +331,7 @@ block_funcs.hpp \ collection_def.inl \ collection.hpp \ + delayed_delete_vector.hpp \ env.hpp \ iterator_node.hpp \ macro.hpp \ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/aos/Makefile.in mdds-3.1.0/include/mdds/multi_type_vector/aos/Makefile.in --- mdds-2.1.1/include/mdds/multi_type_vector/aos/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -229,7 +229,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/aos/main.hpp mdds-3.1.0/include/mdds/multi_type_vector/aos/main.hpp --- mdds-2.1.1/include/mdds/multi_type_vector/aos/main.hpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/aos/main.hpp 2025-06-13 02:56:24.000000000 +0000 @@ -476,14 +476,21 @@ /** * Append a new value to the end of the container. * - * @param value new value to be appended to the end of the container. + * This method takes the value either as an lvalue or rvalue reference and + * moves the passed value into the destination element block if the value is + * passed as an rvalue reference. Note, however, that the value may still + * be copied even if it is passed as an rvalue reference if the insertion + * triggers reallocation of the buffer in the destination block and the + * value type does not have a move constructor marked as noexcept. + * + * @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 - iterator push_back(const T& value); + iterator push_back(T&& value); /** * Append a new empty element to the end of the container. @@ -495,6 +502,26 @@ iterator push_back_empty(); /** + * Append a new element to the end of the container. + * + * The new element is constructed by using the emplace_back() method of the + * destination element block, and the arguments `args...` are forwarded to + * it via `std::forward(args)...`. + * + * @param args Arguments to forward to the emplace_back() method of the + * destination element block. + * + * @return Iterator position pointing to the block where the value is + * appended, which in this case is always the last block of the + * container. + * + * @note Due to the limitation of the current implementation, this method + * requires the value type `T` to be default-constructible. + */ + template + iterator emplace_back(Args&&... args); + + /** * 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 @@ -1082,7 +1109,10 @@ iterator release_impl(size_type pos, size_type block_index, T& value); template - iterator push_back_impl(const T& value); + iterator push_back_impl(T&& value); + + template + iterator emplace_back_impl(Args&&... args); /** * Find the correct block position for a given logical row ID. @@ -1104,7 +1134,10 @@ void resize_impl(size_type new_size); template - void create_new_block_with_new_cell(element_block_type*& data, const T& cell); + void create_new_block_with_new_cell(element_block_type*& data, T&& cell); + + template + void create_new_block_with_emplace_back(element_block_type*& data, const T& t, Args&&... args); template iterator set_cell_to_middle_of_block(size_type block_index, size_type pos_in_block, const T& cell); diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/aos/main_def.inl mdds-3.1.0/include/mdds/multi_type_vector/aos/main_def.inl --- mdds-2.1.1/include/mdds/multi_type_vector/aos/main_def.inl 2023-02-15 22:32:05.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/aos/main_def.inl 2025-06-17 00:32:19.000000000 +0000 @@ -674,14 +674,14 @@ template template -typename multi_type_vector::iterator multi_type_vector::push_back(const T& value) +typename multi_type_vector::iterator multi_type_vector::push_back(T&& value) { #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG std::ostringstream os_prev_block; dump_blocks(os_prev_block); #endif - auto ret = push_back_impl(value); + auto ret = push_back_impl(std::forward(value)); #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG try @@ -704,8 +704,39 @@ } template +template +typename multi_type_vector::iterator multi_type_vector::emplace_back(Args&&... args) +{ +#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG + std::ostringstream os_prev_block; + dump_blocks(os_prev_block); +#endif + + auto ret = emplace_back_impl(std::forward(args)...); + +#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG + try + { + check_block_integrity(); + } + catch (const mdds::integrity_error& e) + { + std::ostringstream os; + os << e.what() << std::endl; + os << "block integrity check failed in emplace_back" << std::endl; + os << "previous block state:" << std::endl; + os << os_prev_block.str(); + std::cerr << os.str() << std::endl; + abort(); + } +#endif + + return ret; +} + +template template -typename multi_type_vector::iterator multi_type_vector::push_back_impl(const T& value) +typename multi_type_vector::iterator multi_type_vector::push_back_impl(T&& value) { element_category_type cat = mdds_mtv_get_element_type(value); @@ -718,7 +749,43 @@ size_type start_pos = m_cur_size; m_blocks.emplace_back(start_pos, 1); - create_new_block_with_new_cell(m_blocks.back().data, value); + create_new_block_with_new_cell(m_blocks.back().data, std::forward(value)); + ++m_cur_size; + + return get_iterator(block_index); + } + + assert(blk_last); + assert(blk_last->data); + assert(cat == get_block_type(*blk_last->data)); + + // Append the new value to the last block. + size_type block_index = m_blocks.size() - 1; + + mdds_mtv_append_value(*blk_last->data, std::forward(value)); + ++blk_last->size; + ++m_cur_size; + + return get_iterator(block_index); +} + +template +template +typename multi_type_vector::iterator multi_type_vector::emplace_back_impl(Args&&... args) +{ + T t{}; + element_category_type cat = mdds_mtv_get_element_type(t); + + block* blk_last = m_blocks.empty() ? nullptr : &m_blocks.back(); + if (!blk_last || !blk_last->data || cat != get_block_type(*blk_last->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.emplace_back(start_pos, 1); + create_new_block_with_emplace_back(m_blocks.back().data, t, std::forward(args)...); ++m_cur_size; return get_iterator(block_index); @@ -731,7 +798,7 @@ // Append the new value to the last block. size_type block_index = m_blocks.size() - 1; - mdds_mtv_append_value(*blk_last->data, value); + mdds_mtv_emplace_back_value(*blk_last->data, t, std::forward(args)...); ++blk_last->size; ++m_cur_size; @@ -896,7 +963,27 @@ template template -void multi_type_vector::create_new_block_with_new_cell(element_block_type*& data, const T& cell) +void multi_type_vector::create_new_block_with_new_cell(element_block_type*& data, T&& cell) +{ + if (data) + { + m_hdl_event.element_block_released(data); + block_funcs::delete_block(data); + } + + // create an empty block + data = mdds_mtv_create_new_block(0, cell); + if (!data) + throw general_error("Failed to create new block."); + + m_hdl_event.element_block_acquired(data); + mdds_mtv_append_value(*data, std::forward(cell)); +} + +template +template +void multi_type_vector::create_new_block_with_emplace_back( + element_block_type*& data, const T& t, Args&&... args) { if (data) { @@ -904,12 +991,13 @@ block_funcs::delete_block(data); } - // New cell block with size 1. - data = mdds_mtv_create_new_block(1, cell); + // create an empty block + data = mdds_mtv_create_new_block(0, t); if (!data) throw general_error("Failed to create new block."); m_hdl_event.element_block_acquired(data); + mdds_mtv_emplace_back_value(*data, t, std::forward(args)...); } template @@ -4740,14 +4828,15 @@ template void multi_type_vector::dump_blocks(std::ostream& os) const { - os << "--- blocks" << endl; + os << "--- blocks" << std::endl; for (size_type i = 0, n = m_blocks.size(); i < n; ++i) { const block* blk = &m_blocks[i]; element_category_type cat = mtv::element_type_empty; if (blk->data) cat = mtv::get_block_type(*blk->data); - os << " block " << i << ": position=" << blk->position << " size=" << blk->size << " type=" << cat << endl; + os << " block " << i << ": position=" << blk->position << " size=" << blk->size << " type=" << cat + << std::endl; } } diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/delayed_delete_vector.hpp mdds-3.1.0/include/mdds/multi_type_vector/delayed_delete_vector.hpp --- mdds-2.1.1/include/mdds/multi_type_vector/delayed_delete_vector.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/delayed_delete_vector.hpp 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace mdds { namespace mtv { + +/** + * Vector that delays deleting from the front of the vector, which avoids + * O(n^2) memory move operations when code needs to delete items from one + * element block and add to another element block. + */ +template> +class delayed_delete_vector +{ + typedef std::vector store_type; + store_type m_vec; + size_t m_front_offset = 0; // number of elements removed from front of array +public: + typedef typename store_type::value_type value_type; + typedef typename store_type::size_type size_type; + typedef typename store_type::difference_type difference_type; + typedef typename store_type::reference reference; + typedef typename store_type::const_reference const_reference; + typedef typename store_type::pointer pointer; + typedef typename store_type::const_pointer const_pointer; + typedef typename store_type::iterator iterator; + typedef typename store_type::reverse_iterator reverse_iterator; + typedef typename store_type::const_iterator const_iterator; + typedef typename store_type::const_reverse_iterator const_reverse_iterator; + + delayed_delete_vector() : m_vec() + {} + + delayed_delete_vector(size_t n, const T& val) : m_vec(n, val) + {} + + delayed_delete_vector(size_t n) : m_vec(n) + {} + + template + delayed_delete_vector(InputIt first, InputIt last) : m_vec(first, last) + {} + + iterator begin() noexcept + { + return m_vec.begin() + m_front_offset; + } + + iterator end() noexcept + { + return m_vec.end(); + } + + const_iterator begin() const noexcept + { + return m_vec.begin() + m_front_offset; + } + + const_iterator end() const noexcept + { + return m_vec.end(); + } + + reverse_iterator rbegin() noexcept + { + return m_vec.rbegin(); + } + + const_reverse_iterator rbegin() const noexcept + { + return m_vec.rbegin(); + } + + reverse_iterator rend() noexcept + { + return m_vec.rend() - m_front_offset; + } + + const_reverse_iterator rend() const noexcept + { + return m_vec.rend() - m_front_offset; + } + + reference operator[](size_type pos) + { + return m_vec[pos + m_front_offset]; + } + + const_reference operator[](size_type pos) const + { + return m_vec[pos + m_front_offset]; + } + + reference at(size_type pos) + { + return m_vec.at(pos + m_front_offset); + } + + const_reference at(size_type pos) const + { + return m_vec.at(pos + m_front_offset); + } + + void push_back(const T& value) + { + m_vec.push_back(value); + } + + void push_back(T&& value) + { + m_vec.push_back(std::move(value)); + } + + template + void emplace_back(Args&&... args) + { + m_vec.emplace_back(std::forward(args)...); + } + + iterator insert(iterator pos, const T& value) + { + return m_vec.insert(pos, value); + } + + iterator insert(const_iterator pos, T&& value) + { + return m_vec.insert(pos, std::move(value)); + } + + template + void insert(iterator pos, InputIt first, InputIt last) + { + m_vec.insert(pos, first, last); + } + + void resize(size_type count) + { + clear_removed(); + m_vec.resize(count); + } + + iterator erase(iterator pos) + { + if (pos == m_vec.begin() + m_front_offset) + { + ++m_front_offset; + return m_vec.begin() + m_front_offset; + } + else + return m_vec.erase(pos); + } + + iterator erase(iterator first, iterator last) + { + return m_vec.erase(first, last); + } + + size_type capacity() const noexcept + { + return m_vec.capacity(); + } + + void shrink_to_fit() + { + clear_removed(); + m_vec.shrink_to_fit(); + } + + void reserve(size_type new_cap) + { + clear_removed(); + m_vec.reserve(new_cap); + } + + size_type size() const + { + return m_vec.size() - m_front_offset; + } + + template + void assign(InputIt first, InputIt last) + { + clear_removed(); + m_vec.assign(first, last); + } + + T* data() + { + return m_vec.data() + m_front_offset; + } + + const T* data() const + { + return m_vec.data() + m_front_offset; + } + +private: + void clear_removed() + { + m_vec.erase(m_vec.begin(), m_vec.begin() + m_front_offset); + m_front_offset = 0; + } +}; + +template +bool operator==(const delayed_delete_vector& lhs, const delayed_delete_vector& rhs) +{ + return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +namespace detail { + +template<> +struct is_std_vector_bool_store> +{ + using type = std::true_type; +}; + +} // namespace detail + +}} // namespace mdds::mtv + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/macro.hpp mdds-3.1.0/include/mdds/multi_type_vector/macro.hpp --- mdds-2.1.1/include/mdds/multi_type_vector/macro.hpp 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/macro.hpp 2025-06-17 00:32:19.000000000 +0000 @@ -75,6 +75,17 @@ block_type::append_value(block, val); \ } \ \ + inline void mdds_mtv_append_value(mdds::mtv::base_element_block& block, type&& val) \ + { \ + block_type::append_value(block, std::move(val)); \ + } \ +\ + template \ + inline void mdds_mtv_emplace_back_value(mdds::mtv::base_element_block& block, const type&, Args&&... args) \ + { \ + block_type::emplace_back_value(block, std::forward(args)...); \ + } \ +\ inline void mdds_mtv_prepend_value(mdds::mtv::base_element_block& block, const type& val) \ { \ block_type::prepend_value(block, val); \ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/soa/Makefile.in mdds-3.1.0/include/mdds/multi_type_vector/soa/Makefile.in --- mdds-2.1.1/include/mdds/multi_type_vector/soa/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -229,7 +229,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/soa/main.hpp mdds-3.1.0/include/mdds/multi_type_vector/soa/main.hpp --- mdds-2.1.1/include/mdds/multi_type_vector/soa/main.hpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/soa/main.hpp 2025-06-13 02:56:24.000000000 +0000 @@ -659,14 +659,21 @@ /** * Append a new value to the end of the container. * - * @param value new value to be appended to the end of the container. + * This method takes the value either as an lvalue or rvalue reference and + * moves the passed value into the destination element block if the value is + * passed as an rvalue reference. Note, however, that the value may still + * be copied even if it is passed as an rvalue reference if the insertion + * triggers reallocation of the buffer in the destination block and the + * value type does not have a move constructor marked as noexcept. + * + * @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 - iterator push_back(const T& value); + iterator push_back(T&& value); /** * Append a new empty element to the end of the container. @@ -678,6 +685,26 @@ iterator push_back_empty(); /** + * Append a new element to the end of the container. + * + * The new element is constructed by using the `emplace_back()` method of + * the destination element block, and the arguments `args` are forwarded to + * it via `std::forward(args)...`. + * + * @param args Arguments to forward to the `emplace_back()` method of the + * destination element block. + * + * @return Iterator position pointing to the block where the value is + * appended, which in this case is always the last block of the + * container. + * + * @note Due to the limitation of the current implementation, this method + * requires the value type `T` to be default-constructible. + */ + template + iterator emplace_back(Args&&... args); + + /** * 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 @@ -1219,7 +1246,10 @@ iterator set_whole_block_empty(size_type block_index, bool overwrite); template - iterator push_back_impl(const T& value); + iterator push_back_impl(T&& value); + + template + iterator emplace_back_impl(Args&&... args); template iterator set_cells_impl( @@ -1268,7 +1298,10 @@ size_type get_block_position(const typename value_type::private_data& pos_data, size_type row) const; template - void create_new_block_with_new_cell(size_type block_index, const T& cell); + void create_new_block_with_new_cell(size_type block_index, T&& cell); + + template + void create_new_block_with_emplace_back(size_type block_index, const T& t, Args&&... args); template void append_cell_to_block(size_type block_index, const T& cell); diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/soa/main_def.inl mdds-3.1.0/include/mdds/multi_type_vector/soa/main_def.inl --- mdds-2.1.1/include/mdds/multi_type_vector/soa/main_def.inl 2023-02-15 22:32:05.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/soa/main_def.inl 2025-06-17 00:32:19.000000000 +0000 @@ -848,7 +848,7 @@ template template -typename multi_type_vector::iterator multi_type_vector::push_back(const T& value) +typename multi_type_vector::iterator multi_type_vector::push_back(T&& value) { MDDS_MTV_TRACE_ARGS(mutator, "value=? (type=" << mdds_mtv_get_element_type(value) << ")"); @@ -857,7 +857,7 @@ dump_blocks(os_prev_block); #endif - auto ret = push_back_impl(value); + auto ret = push_back_impl(std::forward(value)); #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG try @@ -897,6 +897,37 @@ } template +template +typename multi_type_vector::iterator multi_type_vector::emplace_back(Args&&... args) +{ +#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG + std::ostringstream os_prev_block; + dump_blocks(os_prev_block); +#endif + + auto ret = emplace_back_impl(std::forward(args)...); + +#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG + try + { + check_block_integrity(); + } + catch (const mdds::integrity_error& e) + { + std::ostringstream os; + os << e.what() << std::endl; + os << "block integrity check failed in emplace_back" << std::endl; + os << "previous block state:" << std::endl; + os << os_prev_block.str(); + std::cerr << os.str() << std::endl; + abort(); + } +#endif + + return ret; +} + +template template typename multi_type_vector::iterator multi_type_vector::insert( size_type pos, const T& it_begin, const T& it_end) @@ -983,7 +1014,7 @@ template template -typename multi_type_vector::iterator multi_type_vector::push_back_impl(const T& value) +typename multi_type_vector::iterator multi_type_vector::push_back_impl(T&& value) { element_category_type cat = mdds_mtv_get_element_type(value); element_block_type* last_data = @@ -997,7 +1028,43 @@ size_type start_pos = m_cur_size; m_block_store.push_back(start_pos, 1, nullptr); - create_new_block_with_new_cell(block_index, value); + create_new_block_with_new_cell(block_index, std::forward(value)); + ++m_cur_size; + + return get_iterator(block_index); + } + + assert(last_data); + assert(cat == get_block_type(*last_data)); + + // Append the new value to the last block. + size_type block_index = m_block_store.positions.size() - 1; + + mdds_mtv_append_value(*last_data, std::forward(value)); + ++m_block_store.sizes.back(); + ++m_cur_size; + + return get_iterator(block_index); +} + +template +template +typename multi_type_vector::iterator multi_type_vector::emplace_back_impl(Args&&... args) +{ + T t{}; + element_category_type cat = mdds_mtv_get_element_type(t); + element_block_type* last_data = + m_block_store.element_blocks.empty() ? nullptr : m_block_store.element_blocks.back(); + + if (!last_data || cat != get_block_type(*last_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_block_store.positions.size(); + size_type start_pos = m_cur_size; + + m_block_store.push_back(start_pos, 1, nullptr); + create_new_block_with_emplace_back(block_index, t, std::forward(args)...); ++m_cur_size; return get_iterator(block_index); @@ -1009,7 +1076,7 @@ // Append the new value to the last block. size_type block_index = m_block_store.positions.size() - 1; - mdds_mtv_append_value(*last_data, value); + mdds_mtv_emplace_back_value(*last_data, t, std::forward(args)...); ++m_block_store.sizes.back(); ++m_cur_size; @@ -3870,7 +3937,7 @@ template template -void multi_type_vector::create_new_block_with_new_cell(size_type block_index, const T& cell) +void multi_type_vector::create_new_block_with_new_cell(size_type block_index, T&& cell) { element_block_type* data = m_block_store.element_blocks[block_index]; if (data) @@ -3879,14 +3946,37 @@ block_funcs::delete_block(data); } - // New cell block with size 1. - data = mdds_mtv_create_new_block(1, cell); + // create an empty block + data = mdds_mtv_create_new_block(0, cell); if (!data) throw general_error("Failed to create new block."); + m_block_store.element_blocks[block_index] = data; + m_hdl_event.element_block_acquired(data); + mdds_mtv_append_value(*data, std::forward(cell)); +} + +template +template +void multi_type_vector::create_new_block_with_emplace_back(size_type block_index, const T& t, Args&&... args) +{ + element_block_type* data = m_block_store.element_blocks[block_index]; + if (data) + { + m_hdl_event.element_block_released(data); + block_funcs::delete_block(data); + } + + // create an empty block + data = mdds_mtv_create_new_block(0, t); + if (!data) + throw general_error("Failed to create new block."); m_block_store.element_blocks[block_index] = data; + + m_hdl_event.element_block_acquired(data); + mdds_mtv_emplace_back_value(*data, t, std::forward(args)...); } template diff -Nru mdds-2.1.1/include/mdds/multi_type_vector/types.hpp mdds-3.1.0/include/mdds/multi_type_vector/types.hpp --- mdds-2.1.1/include/mdds/multi_type_vector/types.hpp 2023-04-21 02:32:52.000000000 +0000 +++ mdds-3.1.0/include/mdds/multi_type_vector/types.hpp 2025-06-13 02:56:24.000000000 +0000 @@ -26,11 +26,11 @@ * ************************************************************************/ -#ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP -#define INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP +#pragma once #include "../global.hpp" #include "./types_util.hpp" +#include "./delayed_delete_vector.hpp" #include #include @@ -41,9 +41,6 @@ #if defined(MDDS_UNIT_TEST) || defined(MDDS_MULTI_TYPE_VECTOR_DEBUG) #include #include -using std::cerr; -using std::cout; -using std::endl; #endif namespace mdds { namespace mtv { @@ -166,209 +163,6 @@ {} }; -/** - * Vector that delays deleting from the front of the vector, which avoids - * O(n^2) memory move operations when code needs to delete items from one - * element block and add to another element block. - */ -template> -class delayed_delete_vector -{ - typedef std::vector store_type; - store_type m_vec; - size_t m_front_offset = 0; // number of elements removed from front of array -public: - typedef typename store_type::value_type value_type; - typedef typename store_type::size_type size_type; - typedef typename store_type::difference_type difference_type; - typedef typename store_type::reference reference; - typedef typename store_type::const_reference const_reference; - typedef typename store_type::pointer pointer; - typedef typename store_type::const_pointer const_pointer; - typedef typename store_type::iterator iterator; - typedef typename store_type::reverse_iterator reverse_iterator; - typedef typename store_type::const_iterator const_iterator; - typedef typename store_type::const_reverse_iterator const_reverse_iterator; - - delayed_delete_vector() : m_vec() - {} - - delayed_delete_vector(size_t n, const T& val) : m_vec(n, val) - {} - - delayed_delete_vector(size_t n) : m_vec(n) - {} - - template - delayed_delete_vector(InputIt first, InputIt last) : m_vec(first, last) - {} - - iterator begin() noexcept - { - return m_vec.begin() + m_front_offset; - } - - iterator end() noexcept - { - return m_vec.end(); - } - - const_iterator begin() const noexcept - { - return m_vec.begin() + m_front_offset; - } - - const_iterator end() const noexcept - { - return m_vec.end(); - } - - reverse_iterator rbegin() noexcept - { - return m_vec.rbegin(); - } - - const_reverse_iterator rbegin() const noexcept - { - return m_vec.rbegin(); - } - - reverse_iterator rend() noexcept - { - return m_vec.rend() - m_front_offset; - } - - const_reverse_iterator rend() const noexcept - { - return m_vec.rend() - m_front_offset; - } - - reference operator[](size_type pos) - { - return m_vec[pos + m_front_offset]; - } - - const_reference operator[](size_type pos) const - { - return m_vec[pos + m_front_offset]; - } - - reference at(size_type pos) - { - return m_vec.at(pos + m_front_offset); - } - - const_reference at(size_type pos) const - { - return m_vec.at(pos + m_front_offset); - } - - void push_back(const T& value) - { - m_vec.push_back(value); - } - - iterator insert(iterator pos, const T& value) - { - return m_vec.insert(pos, value); - } - - iterator insert(const_iterator pos, T&& value) - { - return m_vec.insert(pos, std::move(value)); - } - - template - void insert(iterator pos, InputIt first, InputIt last) - { - m_vec.insert(pos, first, last); - } - - void resize(size_type count) - { - clear_removed(); - m_vec.resize(count); - } - - iterator erase(iterator pos) - { - if (pos == m_vec.begin() + m_front_offset) - { - ++m_front_offset; - return m_vec.begin() + m_front_offset; - } - else - return m_vec.erase(pos); - } - - iterator erase(iterator first, iterator last) - { - return m_vec.erase(first, last); - } - - size_type capacity() const noexcept - { - return m_vec.capacity(); - } - - void shrink_to_fit() - { - clear_removed(); - m_vec.shrink_to_fit(); - } - - void reserve(size_type new_cap) - { - clear_removed(); - m_vec.reserve(new_cap); - } - - size_type size() const - { - return m_vec.size() - m_front_offset; - } - - template - void assign(InputIt first, InputIt last) - { - clear_removed(); - m_vec.assign(first, last); - } - - T* data() - { - return m_vec.data() + m_front_offset; - } - - const T* data() const - { - return m_vec.data() + m_front_offset; - } - -private: - void clear_removed() - { - m_vec.erase(m_vec.begin(), m_vec.begin() + m_front_offset); - m_front_offset = 0; - } -}; - -namespace detail { - -template<> -struct is_std_vector_bool_store> -{ - using type = std::true_type; -}; - -} // namespace detail - -template -bool operator==(const delayed_delete_vector& lhs, const delayed_delete_vector& rhs) -{ - return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); -} - template class StoreT> class element_block : public base_element_block { @@ -568,9 +362,16 @@ return get(blk).m_array[pos]; } - static void append_value(base_element_block& blk, const ValueT& val) + template + static void append_value(base_element_block& blk, T&& val) { - get(blk).m_array.push_back(val); + get(blk).m_array.push_back(std::forward(val)); + } + + template + static void emplace_back_value(base_element_block& blk, Args&&... args) + { + get(blk).m_array.emplace_back(std::forward(args)...); } static void prepend_value(base_element_block& blk, const ValueT& val) @@ -1006,6 +807,4 @@ }} // namespace mdds::mtv -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/node.hpp mdds-3.1.0/include/mdds/node.hpp --- mdds-2.1.1/include/mdds/node.hpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/include/mdds/node.hpp 2025-02-07 02:52:12.000000000 +0000 @@ -28,16 +28,21 @@ #ifndef __MDDS_NODE_HXX__ #define __MDDS_NODE_HXX__ +#include "mdds/global.hpp" + #include #include #include +#include #include -namespace mdds { namespace __st { +namespace mdds { namespace st { namespace detail { #ifdef MDDS_DEBUG_NODE_BASE -size_t node_instance_count = 0; + +inline std::size_t node_instance_count = 0; + #endif struct node_base @@ -51,43 +56,33 @@ {} }; -template +/** + * Represents a non-leaf node in a segment-tree like structure. + */ +template struct nonleaf_node : public node_base { - typedef typename T::nonleaf_value_type nonleaf_value_type; - typedef typename T::fill_nonleaf_value_handler fill_nonleaf_value_handler; - typedef typename T::init_handler init_handler; - typedef typename T::dispose_handler dispose_handler; -#ifdef MDDS_UNIT_TEST - typedef typename T::to_string_handler to_string_handler; -#endif + using key_type = KeyT; + using nonleaf_value_type = ValueT; + nonleaf_value_type value_nonleaf; - node_base* left; /// left child nonleaf_node - node_base* right; /// right child nonleaf_node + key_type low = {}; /// low range value (inclusive) + key_type high = {}; /// high range value (non-inclusive) -private: - fill_nonleaf_value_handler _hdl_fill_nonleaf; - init_handler _hdl_init; - dispose_handler _hdl_dispose; -#ifdef MDDS_UNIT_TEST - to_string_handler _hdl_to_string; -#endif + node_base* left = nullptr; /// left child nonleaf_node + node_base* right = nullptr; /// right child nonleaf_node public: - nonleaf_node() : node_base(false), left(nullptr), right(nullptr) - { - _hdl_init(*this); - } + nonleaf_node() : node_base(false), value_nonleaf() + {} /** * When copying nonleaf_node, only the stored values should be copied. * Connections to the parent, left and right nodes must not be copied. */ - nonleaf_node(const nonleaf_node& r) : node_base(r), left(nullptr), right(nullptr) - { - value_nonleaf = r.value_nonleaf; - } + nonleaf_node(const nonleaf_node& r) : node_base(r), value_nonleaf(r.value_nonleaf), low(r.low), high(r.high) + {} /** * Like the copy constructor, only the stored values should be copied. @@ -102,50 +97,33 @@ return *this; } - ~nonleaf_node() - { - dispose(); - } - - void dispose() + bool operator==(const nonleaf_node& r) const { - _hdl_dispose(*this); + return low == r.low && high == r.high && value_nonleaf == r.value_nonleaf; } - bool equals(const nonleaf_node& r) const + bool operator!=(const nonleaf_node& r) const { - return value_nonleaf == r.value_nonleaf; + return !operator==(r); } - void fill_nonleaf_value(const node_base* left_node, const node_base* right_node) + std::string to_string() const { - _hdl_fill_nonleaf(*this, left_node, right_node); + std::ostringstream os; + os << "[" << low << "-" << high << ")"; + return os.str(); } - -#ifdef MDDS_UNIT_TEST - void dump_value() const - { - ::std::cout << _hdl_to_string(*this); - } - - ::std::string to_string() const - { - return _hdl_to_string(*this); - } -#endif }; -template -struct node : public node_base -{ - typedef ::boost::intrusive_ptr node_ptr; - - typedef typename T::leaf_value_type leaf_value_type; - typedef typename T::init_handler init_handler; - typedef typename T::dispose_handler dispose_handler; -#ifdef MDDS_UNIT_TEST - typedef typename T::to_string_handler to_string_handler; -#endif +/** + * Represents a leaf node in a segment-tree like structure. + */ +template +struct node : node_base +{ + using key_type = KeyT; + using leaf_value_type = ValueT; + using node_ptr = boost::intrusive_ptr; static size_t get_instance_count() { @@ -158,32 +136,26 @@ leaf_value_type value_leaf; + key_type key = {}; + node_ptr prev; /// previous sibling leaf node. node_ptr next; /// next sibling leaf node. - size_t refcount; - -private: - init_handler _hdl_init; - dispose_handler _hdl_dispose; -#ifdef MDDS_UNIT_TEST - to_string_handler _hdl_to_string; -#endif + std::size_t refcount = 0; public: - node() : node_base(true), refcount(0) + node() : node_base(true) { #ifdef MDDS_DEBUG_NODE_BASE ++node_instance_count; #endif - _hdl_init(*this); } /** * When copying node, only the stored values should be copied. * Connections to the parent, left and right nodes must not be copied. */ - node(const node& r) : node_base(r), refcount(0) + node(const node& r) : node_base(r), key(r.key) { #ifdef MDDS_DEBUG_NODE_BASE ++node_instance_count; @@ -209,48 +181,42 @@ #ifdef MDDS_DEBUG_NODE_BASE --node_instance_count; #endif - dispose(); - } - - void dispose() - { - _hdl_dispose(*this); } - bool equals(const node& r) const + bool operator==(const node& r) const { - return value_leaf == r.value_leaf; + return key == r.key && value_leaf == r.value_leaf; } -#ifdef MDDS_UNIT_TEST - void dump_value() const + bool operator!=(const node& r) const { - ::std::cout << _hdl_to_string(*this); + return !operator==(r); } - ::std::string to_string() const + std::string to_string() const { - return _hdl_to_string(*this); + std::ostringstream os; + os << "[" << key << "]"; + return os.str(); } -#endif }; -template -inline void intrusive_ptr_add_ref(node* p) +template +inline void intrusive_ptr_add_ref(node* p) { ++p->refcount; } -template -inline void intrusive_ptr_release(node* p) +template +inline void intrusive_ptr_release(node* p) { --p->refcount; if (!p->refcount) delete p; } -template -void link_nodes(typename node::node_ptr& left, typename node::node_ptr& right) +template +void link_nodes(NodePtrT& left, NodePtrT& right) { left->next = right; right->prev = left; @@ -260,9 +226,9 @@ class tree_builder { public: - typedef mdds::__st::node leaf_node; - typedef typename mdds::__st::node::node_ptr leaf_node_ptr; - typedef mdds::__st::nonleaf_node nonleaf_node; + typedef typename T::node leaf_node; + typedef typename leaf_node::node_ptr leaf_node_ptr; + typedef typename T::nonleaf_node nonleaf_node; typedef std::vector nonleaf_node_pool_type; tree_builder(nonleaf_node_pool_type& pool) : m_pool(pool), m_pool_pos(pool.begin()), m_pool_pos_end(pool.end()) @@ -308,10 +274,50 @@ parent_node->right = node2; } - parent_node->fill_nonleaf_value(node1, node2); + fill_nonleaf_parent_node(parent_node, node1, node2); return parent_node; } + void fill_nonleaf_parent_node(nonleaf_node* parent_node, const node_base* left_node, const node_base* right_node) + { + // Parent node should carry the range of all of its child nodes. + if (left_node) + { + parent_node->low = left_node->is_leaf ? static_cast(left_node)->key + : static_cast(left_node)->low; + } + else + { + // Having a left node is prerequisite. + throw general_error("fill_nonleaf_parent_node: Having a left node is prerequisite."); + } + + if (right_node) + { + if (right_node->is_leaf) + { + // When the child nodes are leaf nodes, the upper bound + // must be the value of the node that comes after the + // right leaf node (if such node exists). + + const auto* p = static_cast(right_node); + if (p->next) + parent_node->high = p->next->key; + else + parent_node->high = p->key; + } + else + { + parent_node->high = static_cast(right_node)->high; + } + } + else + { + parent_node->high = left_node->is_leaf ? static_cast(left_node)->key + : static_cast(left_node)->high; + } + } + nonleaf_node* build_tree_non_leaf(const std::vector& node_list) { size_t node_count = node_list.size(); @@ -356,8 +362,8 @@ typename nonleaf_node_pool_type::iterator m_pool_pos_end; }; -template -void disconnect_all_nodes(node* p) +template +void disconnect_all_nodes(node* p) { if (!p) return; @@ -367,17 +373,17 @@ p->parent = nullptr; } -template -void disconnect_leaf_nodes(node* left_node, node* right_node) +template +void disconnect_leaf_nodes(node* left_node, node* right_node) { if (!left_node || !right_node) return; // Go through all leaf nodes, and disconnect their links. - node* cur_node = left_node; + auto* cur_node = left_node; do { - node* next_node = cur_node->next.get(); + auto* next_node = cur_node->next.get(); disconnect_all_nodes(cur_node); cur_node = next_node; } while (cur_node != right_node); @@ -385,12 +391,12 @@ disconnect_all_nodes(right_node); } -template -size_t count_leaf_nodes(const node* left_end, const node* right_end) +template +size_t count_leaf_nodes(const node* left_end, const node* right_end) { size_t leaf_count = 1; - const node* p = left_end; - const node* p_end = right_end; + const auto* p = left_end; + const auto* p_end = right_end; for (; p != p_end; p = p->next.get(), ++leaf_count) ; @@ -416,29 +422,30 @@ return nonleaf_count; } -#ifdef MDDS_UNIT_TEST - -template +template class tree_dumper { - typedef std::vector node_list_type; + using node_list_type = std::vector; + using tree_type = typename TraitsT::tree_type; public: - static size_t dump(const node_base* root_node) + static size_t dump(std::ostream& os, const tree_type& tree, const node_base* root_node) { if (!root_node) return 0; node_list_type node_list; node_list.push_back(root_node); - return dump_layer(node_list, 0); + return dump_layer(os, tree, node_list, 0); } private: - static size_t dump_layer(const node_list_type& node_list, unsigned int level) + static size_t dump_layer( + std::ostream& os, const tree_type& tree, const node_list_type& node_list, unsigned int level) { - using ::std::cout; - using ::std::endl; + using leaf_type = typename TraitsT::leaf_type; + using nonleaf_type = typename TraitsT::nonleaf_type; + using to_string = typename TraitsT::to_string; if (node_list.empty()) return 0; @@ -446,45 +453,47 @@ size_t node_count = node_list.size(); bool is_leaf = node_list.front()->is_leaf; - cout << "level " << level << " (" << (is_leaf ? "leaf" : "non-leaf") << ")" << endl; + os << "level " << level << ':' << std::endl; + os << " type: " << (is_leaf ? "leaf" : "non-leaf") << std::endl; + os << " nodes:" << std::endl; node_list_type new_list; - typename node_list_type::const_iterator it = node_list.begin(), it_end = node_list.end(); - for (; it != it_end; ++it) + + for (const node_base* p : node_list) { - const node_base* p = *it; + os << " - '"; + if (!p) { - cout << "(x) "; + os << "*'" << std::endl; continue; } if (p->is_leaf) - static_cast(p)->dump_value(); - else - static_cast(p)->dump_value(); - - if (p->is_leaf) + { + const auto* pl = static_cast(p); + os << to_string{tree}(*pl) << "'" << std::endl; continue; + } + + const auto* pnl = static_cast(p); + os << to_string{tree}(*pnl) << "'" << std::endl; - if (static_cast(p)->left) + if (pnl->left) { - new_list.push_back(static_cast(p)->left); - if (static_cast(p)->right) - new_list.push_back(static_cast(p)->right); + new_list.push_back(pnl->left); + if (pnl->right) + new_list.push_back(pnl->right); } } - cout << endl; if (!new_list.empty()) - node_count += dump_layer(new_list, level + 1); + node_count += dump_layer(os, tree, new_list, level + 1); return node_count; } }; -#endif - -}} // namespace mdds::__st +}}} // namespace mdds::st::detail #endif diff -Nru mdds-2.1.1/include/mdds/ref_pair.hpp mdds-3.1.0/include/mdds/ref_pair.hpp --- mdds-2.1.1/include/mdds/ref_pair.hpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/include/mdds/ref_pair.hpp 2025-07-05 20:22:32.000000000 +0000 @@ -26,8 +26,7 @@ * ************************************************************************/ -#ifndef INCLUDED_MDDS_REF_PAIR_HPP -#define INCLUDED_MDDS_REF_PAIR_HPP +#pragma once #include @@ -75,6 +74,4 @@ }} // namespace mdds::detail -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/rtree.hpp mdds-3.1.0/include/mdds/rtree.hpp --- mdds-2.1.1/include/mdds/rtree.hpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/include/mdds/rtree.hpp 2025-07-05 19:26:41.000000000 +0000 @@ -683,7 +683,7 @@ * * @param pos iterator that refernces the value object to erase. */ - void erase(const const_iterator& pos); + void erase(const_iterator pos); /** * Erase the value object referenced by the iterator passed to this @@ -694,7 +694,7 @@ * * @param pos iterator that refernces the value object to erase. */ - void erase(const iterator& pos); + void erase(iterator pos); /** * Get the minimum bounding extent of the root node of the tree. The diff -Nru mdds-2.1.1/include/mdds/rtree_def.inl mdds-3.1.0/include/mdds/rtree_def.inl --- mdds-2.1.1/include/mdds/rtree_def.inl 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/include/mdds/rtree_def.inl 2025-07-05 19:26:41.000000000 +0000 @@ -1594,19 +1594,15 @@ } template -void rtree::erase(const const_iterator& pos) +void rtree::erase(const_iterator pos) { - const node_store* ns = pos.m_pos->ns; - size_t depth = pos.m_pos->depth; - erase_impl(ns, depth); + erase_impl(pos.m_pos->ns, pos.m_pos->depth); } template -void rtree::erase(const iterator& pos) +void rtree::erase(iterator pos) { - const node_store* ns = pos.m_pos->ns; - size_t depth = pos.m_pos->depth; - erase_impl(ns, depth); + erase_impl(pos.m_pos->ns, pos.m_pos->depth); } template diff -Nru mdds-2.1.1/include/mdds/segment_tree.hpp mdds-3.1.0/include/mdds/segment_tree.hpp --- mdds-2.1.1/include/mdds/segment_tree.hpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/include/mdds/segment_tree.hpp 2024-02-29 23:33:04.000000000 +0000 @@ -32,507 +32,330 @@ #include "mdds/global.hpp" #include +#include #include #include #include #include - -#ifdef MDDS_UNIT_TEST #include -#endif namespace mdds { -template +/** + * Segment tree is a data structure designed for storing one-dimensional + * intervals or segments, either overlapping or non-overlapping. + * It is useful for detecting all the segments that contain a specific point. + * + * Each segment has start and end positions where the start position is + * inclusive while the end position is not. This segment tree implementation + * allows associating a value with each segment so that you can use it as an + * associative container. + * + * @tparam KeyT Key type. The key type must be copyable. If it's moveable + * then it gets moved instead of copied where possible. Additionally, + * the key type must support the @p <, @p <= and @p == operators. + * To use to_string(), the key type must support the ostream operator. + * @tparam ValueT Value type. The value type does not need to be copyable but + * must be at least moveable. Additionally, the value type must + * support the @p == operator. To use to_string(), the value type + * must support the ostream operator. + */ +template class segment_tree { public: - typedef _Key key_type; - typedef _Value value_type; - typedef size_t size_type; - typedef std::vector search_results_type; - -#ifdef MDDS_UNIT_TEST - struct segment_data - { - key_type begin_key; - key_type end_key; - value_type pdata; - - segment_data(key_type _beg, key_type _end, value_type p) : begin_key(_beg), end_key(_end), pdata(p) - {} - - bool operator==(const segment_data& r) const - { - return begin_key == r.begin_key && end_key == r.end_key && pdata == r.pdata; - } - - bool operator!=(const segment_data& r) const - { - return !operator==(r); - } - }; + /** The key type must be copyable, and may be moveable. */ + using key_type = KeyT; + /** The value type must be either copyable or moveable. */ + using value_type = ValueT; + using size_type = std::size_t; - struct segment_map_printer +private: + struct segment_type { - void operator()(const ::std::pair>& r) const - { - using namespace std; - cout << r.second.first << "-" << r.second.second << ": " << r.first->name << endl; - } - }; -#endif + key_type start; + key_type end; + value_type value; + + segment_type(); + segment_type(key_type _start, key_type _end, value_type _value); + segment_type(const segment_type&) = default; + segment_type(segment_type&&) = default; + + segment_type& operator=(const segment_type& r) = default; + segment_type& operator=(segment_type&& r) = default; + bool operator<(const segment_type& r) const; + bool operator==(const segment_type& r) const; + bool operator!=(const segment_type& r) const; + }; + + using segment_store_type = std::deque; + using value_pos_type = typename segment_store_type::size_type; + using value_chain_type = std::vector; -public: - typedef ::std::vector data_chain_type; - typedef std::unordered_map> segment_map_type; - typedef ::std::map> sorted_segment_map_type; + using node_chain_type = std::vector; + using value_to_nodes_type = std::map; struct nonleaf_value_type { - key_type low; /// low range value (inclusive) - key_type high; /// high range value (non-inclusive) - data_chain_type* data_chain; - - bool operator==(const nonleaf_value_type& r) const - { - return low == r.low && high == r.high && data_chain == r.data_chain; - } - }; - - struct leaf_value_type - { - key_type key; - data_chain_type* data_chain; + std::unique_ptr data_chain; - bool operator==(const leaf_value_type& r) const + nonleaf_value_type() + {} + nonleaf_value_type(const nonleaf_value_type& r) { - return key == r.key && data_chain == r.data_chain; + if (r.data_chain) + data_chain = std::make_unique(*r.data_chain); } - }; - - struct fill_nonleaf_value_handler; - struct init_handler; - struct dispose_handler; -#ifdef MDDS_UNIT_TEST - struct to_string_handler; -#endif - typedef __st::node node; - typedef typename node::node_ptr node_ptr; - - typedef typename __st::nonleaf_node nonleaf_node; - - struct fill_nonleaf_value_handler - { - void operator()( - __st::nonleaf_node& _self, const __st::node_base* left_node, - const __st::node_base* right_node) - { - // Parent node should carry the range of all of its child nodes. - if (left_node) - { - _self.value_nonleaf.low = left_node->is_leaf - ? static_cast(left_node)->value_leaf.key - : static_cast(left_node)->value_nonleaf.low; - } - else - { - // Having a left node is prerequisite. - throw general_error("segment_tree::fill_nonleaf_value_handler: Having a left node is prerequisite."); - } - - if (right_node) - { - if (right_node->is_leaf) - { - // When the child nodes are leaf nodes, the upper bound - // must be the value of the node that comes after the - // right leaf node (if such node exists). - - const node* p = static_cast(right_node); - if (p->next) - _self.value_nonleaf.high = p->next->value_leaf.key; - else - _self.value_nonleaf.high = p->value_leaf.key; - } - else - { - _self.value_nonleaf.high = static_cast(right_node)->value_nonleaf.high; - } - } - else - { - _self.value_nonleaf.high = left_node->is_leaf - ? static_cast(left_node)->value_leaf.key - : static_cast(left_node)->value_nonleaf.high; - } - } - }; - -#ifdef MDDS_UNIT_TEST - struct to_string_handler - { - std::string operator()(const node& _self) const + bool operator==(const nonleaf_value_type& r) const { - std::ostringstream os; - os << "[" << _self.value_leaf.key << "] "; - return os.str(); + return data_chain == r.data_chain; } - std::string operator()(const __st::nonleaf_node& _self) const - { - std::ostringstream os; - os << "[" << _self.value_nonleaf.low << "-" << _self.value_nonleaf.high << ")"; - if (_self.value_nonleaf.data_chain) - { - os << " { "; - typename data_chain_type::const_iterator itr, itr_beg = _self.value_nonleaf.data_chain->begin(), - itr_end = _self.value_nonleaf.data_chain->end(); - for (itr = itr_beg; itr != itr_end; ++itr) - { - if (itr != itr_beg) - os << ", "; - os << (*itr)->name; - } - os << " }"; - } - os << " "; - return os.str(); - } + ~nonleaf_value_type() + {} }; -#endif - struct init_handler + struct leaf_value_type { - void operator()(node& _self) - { - _self.value_leaf.data_chain = nullptr; - } + std::unique_ptr data_chain; - void operator()(__st::nonleaf_node& _self) + leaf_value_type() + {} + leaf_value_type(const leaf_value_type& r) { - _self.value_nonleaf.data_chain = nullptr; + if (r.data_chain) + data_chain = std::make_unique(*r.data_chain); } - }; - struct dispose_handler - { - void operator()(node& _self) + bool operator==(const leaf_value_type& r) const { - delete _self.value_leaf.data_chain; + return data_chain == r.data_chain; } - void operator()(__st::nonleaf_node& _self) - { - delete _self.value_nonleaf.data_chain; - } + ~leaf_value_type() + {} }; -#ifdef MDDS_UNIT_TEST - struct node_printer - { - void operator()(const __st::node_base* p) const - { - if (p->is_leaf) - std::cout << static_cast(p)->to_string() << " "; - else - std::cout << static_cast(p)->to_string() << " "; - } - }; -#endif +public: + using node = st::detail::node; + using node_ptr = typename node::node_ptr; + using nonleaf_node = typename st::detail::nonleaf_node; private: + class search_result_inserter; + /** * This base class takes care of collecting data chain pointers during * tree descend for search. */ class search_results_base { + friend class search_result_inserter; + public: - typedef std::vector res_chains_type; + typedef std::vector res_chains_type; typedef std::shared_ptr res_chains_ptr; - public: - search_results_base() : mp_res_chains(static_cast(nullptr)) + protected: + search_results_base(const segment_store_type& segment_store) : m_segment_store(&segment_store) {} - search_results_base(const search_results_base& r) : mp_res_chains(r.mp_res_chains) + search_results_base(const search_results_base& r) + : m_segment_store(r.m_segment_store), mp_res_chains(r.mp_res_chains) {} - size_t size() const - { - size_t combined = 0; - if (!mp_res_chains) - return combined; + bool empty() const; - typename res_chains_type::const_iterator itr = mp_res_chains->begin(), itr_end = mp_res_chains->end(); - for (; itr != itr_end; ++itr) - combined += (*itr)->size(); - return combined; - } + size_type size() const; - void push_back_chain(data_chain_type* chain) - { - if (!chain || chain->empty()) - return; + void push_back_chain(value_chain_type* chain); - if (!mp_res_chains) - mp_res_chains.reset(new res_chains_type); - mp_res_chains->push_back(chain); + const segment_store_type* get_segment_store() const + { + return m_segment_store; } - res_chains_ptr& get_res_chains() + const res_chains_ptr& get_res_chains() const { return mp_res_chains; } private: + const segment_store_type* m_segment_store = nullptr; res_chains_ptr mp_res_chains; }; - class iterator_base + class const_iterator_base { + friend class segment_tree; + protected: typedef typename search_results_base::res_chains_type res_chains_type; typedef typename search_results_base::res_chains_ptr res_chains_ptr; - iterator_base(const res_chains_ptr& p) : mp_res_chains(p), m_end_pos(true) + const_iterator_base(const segment_store_type* segment_store, const res_chains_ptr& p) + : m_segment_store(segment_store), mp_res_chains(p), m_end_pos(true) {} public: - typedef ::std::bidirectional_iterator_tag iterator_category; - typedef typename data_chain_type::value_type value_type; - typedef typename data_chain_type::pointer pointer; - typedef typename data_chain_type::reference reference; - typedef typename data_chain_type::difference_type difference_type; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = const segment_tree::segment_type; + using pointer = value_type*; + using reference = value_type&; + using difference_type = std::ptrdiff_t; - iterator_base() : mp_res_chains(static_cast(nullptr)), m_end_pos(true) - {} + const_iterator_base() = default; + const_iterator_base(const const_iterator_base& r) = default; + const_iterator_base& operator=(const const_iterator_base& r) = default; - iterator_base(const iterator_base& r) - : mp_res_chains(r.mp_res_chains), m_cur_chain(r.m_cur_chain), m_cur_pos_in_chain(r.m_cur_pos_in_chain), - m_end_pos(r.m_end_pos) - {} + value_type* operator++(); + value_type* operator--(); - iterator_base& operator=(const iterator_base& r) - { - mp_res_chains = r.mp_res_chains; - m_cur_chain = r.m_cur_chain; - m_cur_pos_in_chain = r.m_cur_pos_in_chain; - m_end_pos = r.m_end_pos; - return *this; - } + bool operator==(const const_iterator_base& r) const; + bool operator!=(const const_iterator_base& r) const; - typename data_chain_type::value_type* operator++() + value_type& operator*() { - // We don't check for end position flag for performance reasons. - // The caller is responsible for making sure not to increment past - // end position. - - // When reaching the end position, the internal iterators still - // need to be pointing at the last item before the end position. - // This is why we need to make copies of the iterators, and copy - // them back once done. - - typename data_chain_type::iterator cur_pos_in_chain = m_cur_pos_in_chain; - - if (++cur_pos_in_chain == (*m_cur_chain)->end()) - { - // End of current chain. Inspect the next chain if exists. - typename res_chains_type::iterator cur_chain = m_cur_chain; - ++cur_chain; - if (cur_chain == mp_res_chains->end()) - { - m_end_pos = true; - return nullptr; - } - m_cur_chain = cur_chain; - m_cur_pos_in_chain = (*m_cur_chain)->begin(); - } - else - ++m_cur_pos_in_chain; - - return operator->(); + return cur_value(); } - typename data_chain_type::value_type* operator--() + const value_type* operator->() { - if (!mp_res_chains) - return nullptr; - - if (m_end_pos) - { - m_end_pos = false; - return &(*m_cur_pos_in_chain); - } - - if (m_cur_pos_in_chain == (*m_cur_chain)->begin()) - { - if (m_cur_chain == mp_res_chains->begin()) - { - // Already at the first data chain. Don't move the iterator position. - return nullptr; - } - --m_cur_chain; - m_cur_pos_in_chain = (*m_cur_chain)->end(); - } - --m_cur_pos_in_chain; - return operator->(); + return &cur_value(); } - bool operator==(const iterator_base& r) const - { - if (mp_res_chains.get()) - { - // non-empty result set. - return mp_res_chains.get() == r.mp_res_chains.get() && m_cur_chain == r.m_cur_chain && - m_cur_pos_in_chain == r.m_cur_pos_in_chain && m_end_pos == r.m_end_pos; - } - - // empty result set. - if (r.mp_res_chains.get()) - return false; - return m_end_pos == r.m_end_pos; - } + protected: + void move_to_front(); + void move_to_end(); - bool operator!=(const iterator_base& r) const + private: + value_type& cur_value() { - return !operator==(r); + auto pos = *m_cur_pos_in_chain; + return (*m_segment_store)[pos]; } - typename data_chain_type::value_type& operator*() + size_type cur_pos() const { return *m_cur_pos_in_chain; } - typename data_chain_type::value_type* operator->() - { - return &(*m_cur_pos_in_chain); - } + const segment_store_type* m_segment_store = nullptr; + res_chains_ptr mp_res_chains; + typename res_chains_type::const_iterator m_cur_chain; + typename value_chain_type::const_iterator m_cur_pos_in_chain; + bool m_end_pos = true; + }; - protected: - void move_to_front() + class search_result_inserter + { + public: + search_result_inserter(search_results_base& results) : m_results(results) + {} + void operator()(value_chain_type* node_data) { - if (!mp_res_chains) - { - // Empty data set. - m_end_pos = true; - return; - } - - // We assume that there is at least one chain list, and no - // empty chain list exists. So, skip the check. - m_cur_chain = mp_res_chains->begin(); - m_cur_pos_in_chain = (*m_cur_chain)->begin(); - m_end_pos = false; - } - - void move_to_end() - { - m_end_pos = true; - if (!mp_res_chains) - // Empty data set. + if (!node_data) return; - m_cur_chain = mp_res_chains->end(); - --m_cur_chain; - m_cur_pos_in_chain = (*m_cur_chain)->end(); - --m_cur_pos_in_chain; + m_results.push_back_chain(node_data); } private: - res_chains_ptr mp_res_chains; - typename res_chains_type::iterator m_cur_chain; - typename data_chain_type::iterator m_cur_pos_in_chain; - bool m_end_pos : 1; + search_results_base& m_results; }; public: class search_results : public search_results_base { + friend class segment_tree; + typedef typename search_results_base::res_chains_type res_chains_type; typedef typename search_results_base::res_chains_ptr res_chains_ptr; + search_results(const segment_store_type& segment_tree) : search_results_base(segment_tree) + {} + public: - class iterator : public iterator_base + class const_iterator : public const_iterator_base { - friend class segment_tree<_Key, _Value>::search_results; + friend class segment_tree::search_results; private: - iterator(const res_chains_ptr& p) : iterator_base(p) + const_iterator(const segment_store_type* segment_store, const res_chains_ptr& p) + : const_iterator_base(segment_store, p) {} public: - iterator() : iterator_base() + const_iterator() : const_iterator_base() {} + + const_iterator(const const_iterator& r) : const_iterator_base(r) + {} + + const_iterator& operator=(const const_iterator& r) + { + const_iterator_base::operator=(r); + return *this; + } }; - typename search_results::iterator begin() + /** + * Check if this results pool is empty or not. + * + * @return true if this results pool is empty, otherwise false. + */ + bool empty() const { - typename search_results::iterator itr(search_results_base::get_res_chains()); - itr.move_to_front(); - return itr; + return search_results_base::empty(); } - typename search_results::iterator end() + /** + * Count the number of results in this results pool. + * + * @return number of results in this results pool. + */ + size_type size() const { - typename search_results::iterator itr(search_results_base::get_res_chains()); - itr.move_to_end(); - return itr; + return search_results_base::size(); } - }; - class search_result_vector_inserter - { - public: - search_result_vector_inserter(search_results_type& result) : m_result(result) - {} - void operator()(data_chain_type* node_data) + typename search_results::const_iterator begin() const { - if (!node_data) - return; - - typename data_chain_type::const_iterator itr = node_data->begin(), itr_end = node_data->end(); - for (; itr != itr_end; ++itr) - m_result.push_back(*itr); + typename search_results::const_iterator it( + search_results_base::get_segment_store(), search_results_base::get_res_chains()); + it.move_to_front(); + return it; } - private: - search_results_type& m_result; - }; - - class search_result_inserter - { - public: - search_result_inserter(search_results_base& result) : m_result(result) - {} - void operator()(data_chain_type* node_data) + typename search_results::const_iterator end() const { - if (!node_data) - return; - - m_result.push_back_chain(node_data); + typename search_results::const_iterator it( + search_results_base::get_segment_store(), search_results_base::get_res_chains()); + it.move_to_end(); + return it; } - - private: - search_results_base& m_result; }; segment_tree(); segment_tree(const segment_tree& r); + segment_tree(segment_tree&& r); ~segment_tree(); + segment_tree& operator=(const segment_tree& r); + segment_tree& operator=(segment_tree&& r); + /** - * Equality between two segment_tree instances is evaluated by comparing - * the segments that they store. The trees are not compared. + * Check equality with another instance. + * + * @note Equality between two segment_tree instances is evaluated + * by comparing the logically stored segments only; the tree parts of the + * structures are not compared. */ bool operator==(const segment_tree& r) const; - bool operator!=(const segment_tree& r) const - { - return !operator==(r); - } + bool operator!=(const segment_tree& r) const; /** * Check whether or not the internal tree is in a valid state. The tree @@ -540,64 +363,86 @@ * * @return true if the tree is valid, false otherwise. */ - bool is_tree_valid() const + bool valid_tree() const noexcept { return m_valid_tree; } /** - * Build or re-build tree based on the current set of segments. + * Build or re-build a tree based on the current set of segments. + * + * @note Building a tree with no logical stored segments will not result in + * a valid tree. */ void build_tree(); /** - * Insert a new segment. + * Insert a new segment. Duplicate segments are allowed. * - * @param begin_key begin point of the segment. The value is inclusive. - * @param end_key end point of the segment. The value is non-inclusive. - * @param pdata pointer to the data instance associated with this segment. - * Note that the caller must manage the life cycle of the - * data instance. + * @param start_key start key of a segment. The value is inclusive. + * @param end_key end key of a segment. The value is non-inclusive. + * It must be greater than the start key. + * @param value value to associate with this segment. */ - bool insert(key_type begin_key, key_type end_key, value_type pdata); + void insert(key_type start_key, key_type end_key, value_type value); /** - * Search the tree and collect all segments that include a specified - * point. + * Search the tree to find all the segments that contain a specified point. + * + * @param point A point to search the tree with. + * + * @return Results object containing the segments that contain the specified + * point. * - * @param point specified point value - * @param result doubly-linked list of data instances associated with - * the segments that include the specified point. - * Note that the search result gets appended to the - * list; the list will not get emptied on each - * search. It is caller's responsibility to empty - * the list before passing it to this method in case the - * caller so desires. + * @note You need to have a valid tree prior to calling this method. Call + * build_tree() to build one. To check if you have a valid tree, call + * valid_tree() and see if it returns true. * - * @return true if the search is performed successfully, false if the - * search has ended prematurely due to error conditions. + * @note A point value can be any value allowed by the key_type. + * If the point is outside of the range of the tree, empty results + * will be returned. */ - bool search(key_type point, search_results_type& result) const; + search_results search(const key_type& point) const; /** - * Search the tree and collect all segments that include a specified - * point. + * Remove a segment referenced by an iterator. Calling this method will + * not invalidate the tree; however, you might want to re-build the + * tree to compact its size if you have removed a large number of segments. * - * @param point specified point value + * @param pos Position that references the segment to be removed. + */ + void erase(const typename search_results::const_iterator& pos); + + /** + * Remove all segments that satisfy a predicate. * - * @return object containing the result of the search, which can be - * accessed via iterator. + * The predicate must take three parameters that are a start position, end + * position and a value of a segment in this order. The first two + * parameters are of the same type as the key_type while the last parameter + * is of the same type as the value_type. + * + * @code{.cpp} + * // Given int as key_type and std::string as value_type, this predicate removes + * // all the segments that 1) contain 5 and 2) store a value of "A". + * auto pred = [](int start, int end, const std::string& value) { + * return start <= 5 && 5 < end && value == "A"; + * }; + * @endcode + * + * @param pred Predicate that tests each segment. A segment that evaluates + * true by the predicate gets removed. + * + * @return Number of erased elements. */ - search_results search(key_type point) const; + template + size_type erase_if(Pred pred); /** - * Remove a segment that matches by the value. This will not - * invalidate the tree; however, if you have removed lots of segments, you - * might want to re-build the tree to shrink its size. + * Exchange the content of the tree with that of another. * - * @param value value to remove a segment by. + * @param r Another tree instance to swap the contents with. */ - void remove(value_type value); + void swap(segment_tree& r) noexcept; /** * Remove all segments data. @@ -607,7 +452,7 @@ /** * Return the number of segments currently stored in this container. */ - size_t size() const; + size_type size() const; /** * Return whether or not the container stores any segments or none at all. @@ -619,41 +464,38 @@ * * @return number of leaf nodes. */ - size_t leaf_size() const; - -#ifdef MDDS_UNIT_TEST - void dump_tree() const; - void dump_leaf_nodes() const; - void dump_segment_data() const; - bool verify_node_lists() const; - - struct leaf_node_check - { - key_type key; - data_chain_type data_chain; - }; - - bool verify_leaf_nodes(const ::std::vector& checks) const; + size_type leaf_size() const; /** - * Verify the validity of the segment data array. + * Create a string representation of the internal state of a tree. * - * @param checks null-terminated array of expected values. The last item - * must have a nullptr pdata value to terminate the array. + * @return String representation of the internal state of a tree. */ - bool verify_segment_data(const segment_map_type& checks) const; -#endif + std::string to_string() const; -private: /** - * To be called from rectangle_set. + * Create a sorted sequence of unique boundary keys. A boundary key is a + * key that is either the start or the end key of a stored segment. + * + * @return A sorted sequence of unique boundary keys. */ - void search(key_type point, search_results_base& result) const; + std::vector boundary_keys() const; + + struct integrity_check_properties + { + struct leaf_node + { + key_type key = {}; + std::vector value_chain; + }; + + std::vector leaf_nodes; + }; - typedef std::vector<__st::node_base*> node_list_type; - typedef std::map> data_node_map_type; + void check_integrity(const integrity_check_properties& props) const; - static void create_leaf_node_instances(const ::std::vector& keys, node_ptr& left, node_ptr& right); +private: + static void create_leaf_node_instances(std::vector keys, node_ptr& left, node_ptr& right); /** * Descend the tree from the root node, and mark appropriate nodes, both @@ -661,7 +503,8 @@ * record their positions as a list of node pointers. */ void descend_tree_and_mark( - __st::node_base* pnode, value_type pdata, key_type begin_key, key_type end_key, node_list_type* plist); + st::detail::node_base* pnode, value_pos_type value, const key_type& start_key, const key_type& end_key, + node_chain_type& nodelist); void build_leaf_nodes(); @@ -669,32 +512,49 @@ * Go through the list of nodes, and remove the specified data pointer * value from the nodes. */ - void remove_data_from_nodes(node_list_type* plist, const value_type pdata); - void remove_data_from_chain(data_chain_type& chain, const value_type pdata); + void remove_data_from_nodes(node_chain_type& nodelist, value_pos_type value); + void remove_data_from_chain(value_chain_type& chain, value_pos_type value); + void remove_value_pos(size_type pos); void clear_all_nodes(); -#ifdef MDDS_UNIT_TEST - static bool has_data_pointer(const node_list_type& node_list, const value_type pdata); - static void print_leaf_value(const leaf_value_type& v); -#endif - private: + struct tree_dumper_traits + { + using leaf_type = node; + using nonleaf_type = nonleaf_node; + using tree_type = segment_tree; + + struct to_string + { + const tree_type& tree; + + to_string(const tree_type& _tree); + std::string operator()(const leaf_type& leaf) const; + std::string operator()(const nonleaf_type& nonleaf) const; + }; + }; + std::vector m_nonleaf_node_pool; - segment_map_type m_segment_data; + /** + * Storage for inserted segments. Note that real values are only stored + * here. The rest of the structure only stores indices into this storage to + * find the values when needed. + */ + segment_store_type m_segment_store; /** - * For each data pointer, it keeps track of all nodes, leaf or non-leaf, - * that stores the data pointer label. This data is used when removing - * segments by the data pointer value. + * For each segment index, it keeps track of all nodes, leaf or non-leaf, + * that are marked with that index. This is used for removing segments by + * value. */ - data_node_map_type m_tagged_node_map; + value_to_nodes_type m_tagged_nodes_map; nonleaf_node* m_root_node; node_ptr m_left_leaf; node_ptr m_right_leaf; - bool m_valid_tree : 1; + bool m_valid_tree; }; } // namespace mdds diff -Nru mdds-2.1.1/include/mdds/segment_tree_def.inl mdds-3.1.0/include/mdds/segment_tree_def.inl --- mdds-2.1.1/include/mdds/segment_tree_def.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/include/mdds/segment_tree_def.inl 2024-04-11 01:43:55.000000000 +0000 @@ -26,40 +26,37 @@ ************************************************************************/ #include +#include +#include +#include namespace mdds { -namespace __st { +namespace st { namespace detail { -template -void descend_tree_for_search(typename T::key_type point, const __st::node_base* pnode, _Inserter& result) +template +void descend_tree_for_search(typename T::key_type point, const st::detail::node_base* pnode, InserterT& result) { + assert(pnode); + typedef typename T::node leaf_node; typedef typename T::nonleaf_node nonleaf_node; - typedef typename T::nonleaf_value_type nonleaf_value_type; - typedef typename T::leaf_value_type leaf_value_type; - - if (!pnode) - // This should never happen, but just in case. - return; - if (pnode->is_leaf) { - result(static_cast(pnode)->value_leaf.data_chain); + result(static_cast(pnode)->value_leaf.data_chain.get()); return; } const nonleaf_node* pnonleaf = static_cast(pnode); - const nonleaf_value_type& v = pnonleaf->value_nonleaf; - if (point < v.low || v.high <= point) + if (point < pnonleaf->low || pnonleaf->high <= point) // Query point is out-of-range. return; - result(v.data_chain); + result(pnonleaf->value_nonleaf.data_chain.get()); // Check the left child node first, then the right one. - __st::node_base* pchild = pnonleaf->left; + st::detail::node_base* pchild = pnonleaf->left; if (!pchild) return; @@ -68,8 +65,7 @@ if (pchild->is_leaf) { // The child node are leaf nodes. - const leaf_value_type& vleft = static_cast(pchild)->value_leaf; - if (point < vleft.key) + if (point < static_cast(pchild)->key) { // Out-of-range. Nothing more to do. return; @@ -78,8 +74,7 @@ if (pnonleaf->right) { assert(pnonleaf->right->is_leaf); - const leaf_value_type& vright = static_cast(pnonleaf->right)->value_leaf; - if (vright.key <= point) + if (static_cast(pnonleaf->right)->key <= point) // Follow the right node. pchild = pnonleaf->right; } @@ -88,111 +83,365 @@ { // This child nodes are non-leaf nodes. - const nonleaf_value_type& vleft = static_cast(pchild)->value_nonleaf; + const auto* pleaf_left = static_cast(pchild); - if (point < vleft.low) + if (point < pleaf_left->low) { // Out-of-range. Nothing more to do. return; } - if (vleft.high <= point && pnonleaf->right) + if (pleaf_left->high <= point && pnonleaf->right) // Follow the right child. pchild = pnonleaf->right; assert( - static_cast(pchild)->value_nonleaf.low <= point && - point < static_cast(pchild)->value_nonleaf.high); + static_cast(pchild)->low <= point && + point < static_cast(pchild)->high); + } + + descend_tree_for_search(point, pchild, result); +} + +template +void erase_deleted_segments(SegStoreT& segments) +{ + using segment_type = typename SegStoreT::value_type; + + SegStoreT compacted; + for (auto&& v : segments) + { + if (v == segment_type{}) + continue; + + compacted.push_back(std::move(v)); + } + + segments.swap(compacted); +} + +}} // namespace st::detail + +template +segment_tree::segment_type::segment_type() : start{}, end{}, value{} +{} + +template +segment_tree::segment_type::segment_type(key_type _start, key_type _end, value_type _value) + : start(std::move(_start)), end(std::move(_end)), value(std::move(_value)) +{} + +template +bool segment_tree::segment_type::operator<(const segment_type& r) const +{ + if (start != r.start) + return start < r.start; + + if (end != r.end) + return end < r.end; + + return value < r.value; +} + +template +bool segment_tree::segment_type::operator==(const segment_type& r) const +{ + if (start != r.start) + return false; + + if (end != r.end) + return false; + + return value == r.value; +} + +template +bool segment_tree::segment_type::operator!=(const segment_type& r) const +{ + return !operator==(r); +} + +template +bool segment_tree::search_results_base::empty() const +{ + if (!mp_res_chains) + return true; + + // mp_res_chains only contains non-empty chain, that is, if it's not + // empty, it does contain one or more results. + return mp_res_chains->empty(); +} + +template +typename segment_tree::size_type segment_tree::search_results_base::size() const +{ + size_type combined = 0; + if (!mp_res_chains) + return combined; + + for (const value_chain_type* p : *mp_res_chains) + combined += p->size(); + return combined; +} + +template +void segment_tree::search_results_base::push_back_chain(value_chain_type* chain) +{ + if (!chain || chain->empty()) + return; + + if (!mp_res_chains) + mp_res_chains.reset(new res_chains_type); + mp_res_chains->push_back(chain); +} + +template +auto segment_tree::const_iterator_base::operator++() -> value_type* +{ + // We don't check for end position flag for performance reasons. + // The caller is responsible for making sure not to increment past + // end position. + + // When reaching the end position, the internal iterators still + // need to be pointing at the last item before the end position. + // This is why we need to make copies of the iterators, and copy + // them back once done. + + auto cur_pos_in_chain = m_cur_pos_in_chain; + + if (++cur_pos_in_chain == (*m_cur_chain)->end()) + { + // End of current chain. Inspect the next chain if exists. + auto cur_chain = m_cur_chain; + ++cur_chain; + if (cur_chain == mp_res_chains->end()) + { + m_end_pos = true; + return nullptr; + } + m_cur_chain = cur_chain; + m_cur_pos_in_chain = (*m_cur_chain)->begin(); + } + else + ++m_cur_pos_in_chain; + + return operator->(); +} + +template +auto segment_tree::const_iterator_base::operator--() -> value_type* +{ + if (!mp_res_chains) + return nullptr; + + if (m_end_pos) + { + m_end_pos = false; + return &cur_value(); + } + + if (m_cur_pos_in_chain == (*m_cur_chain)->begin()) + { + if (m_cur_chain == mp_res_chains->begin()) + { + // Already at the first data chain. Don't move the iterator position. + return nullptr; + } + --m_cur_chain; + m_cur_pos_in_chain = (*m_cur_chain)->end(); + } + --m_cur_pos_in_chain; + return operator->(); +} + +template +bool segment_tree::const_iterator_base::operator==(const const_iterator_base& r) const +{ + if (mp_res_chains.get()) + { + // non-empty result set. + return mp_res_chains.get() == r.mp_res_chains.get() && m_cur_chain == r.m_cur_chain && + m_cur_pos_in_chain == r.m_cur_pos_in_chain && m_end_pos == r.m_end_pos; + } + + // empty result set. + if (r.mp_res_chains.get()) + return false; + return m_end_pos == r.m_end_pos; +} + +template +bool segment_tree::const_iterator_base::operator!=(const const_iterator_base& r) const +{ + return !operator==(r); +} + +template +void segment_tree::const_iterator_base::move_to_front() +{ + if (!mp_res_chains) + { + // Empty data set. + m_end_pos = true; + return; } - descend_tree_for_search(point, pchild, result); + // We assume that there is at least one chain list, and no + // empty chain list exists. So, skip the check. + m_cur_chain = mp_res_chains->begin(); + m_cur_pos_in_chain = (*m_cur_chain)->begin(); + m_end_pos = false; } -} // namespace __st +template +void segment_tree::const_iterator_base::move_to_end() +{ + m_end_pos = true; + if (!mp_res_chains) + // Empty data set. + return; + + m_cur_chain = mp_res_chains->end(); + --m_cur_chain; + m_cur_pos_in_chain = (*m_cur_chain)->end(); + --m_cur_pos_in_chain; +} -template -segment_tree<_Key, _Value>::segment_tree() : m_root_node(nullptr), m_valid_tree(false) +template +segment_tree::segment_tree() : m_root_node(nullptr), m_valid_tree(false) {} -template -segment_tree<_Key, _Value>::segment_tree(const segment_tree& r) - : m_segment_data(r.m_segment_data), m_root_node(nullptr), m_valid_tree(r.m_valid_tree) +template +segment_tree::segment_tree(const segment_tree& r) + : m_segment_store(r.m_segment_store), m_root_node(nullptr), m_valid_tree(r.m_valid_tree) { if (m_valid_tree) build_tree(); } -template -segment_tree<_Key, _Value>::~segment_tree() +template +segment_tree::segment_tree(segment_tree&& r) + : m_nonleaf_node_pool(std::move(r.m_nonleaf_node_pool)), m_segment_store(std::move(r.m_segment_store)), + m_tagged_nodes_map(std::move(r.m_tagged_nodes_map)), m_root_node(r.m_root_node), + m_left_leaf(std::move(r.m_left_leaf)), m_right_leaf(std::move(r.m_right_leaf)), m_valid_tree(r.m_valid_tree) +{ + r.m_root_node = nullptr; + r.m_valid_tree = false; +} + +template +segment_tree::~segment_tree() { clear_all_nodes(); } -template -bool segment_tree<_Key, _Value>::operator==(const segment_tree& r) const +template +segment_tree& segment_tree::operator=(const segment_tree& r) +{ + segment_tree tmp(r); + swap(tmp); + return *this; +} + +template +segment_tree& segment_tree::operator=(segment_tree&& r) +{ + segment_tree tmp(std::move(r)); + swap(tmp); + return *this; +} + +template +bool segment_tree::operator==(const segment_tree& r) const { if (m_valid_tree != r.m_valid_tree) return false; - // Sort the data by key values first. - sorted_segment_map_type seg1(m_segment_data.begin(), m_segment_data.end()); - sorted_segment_map_type seg2(r.m_segment_data.begin(), r.m_segment_data.end()); - typename sorted_segment_map_type::const_iterator itr1 = seg1.begin(), itr1_end = seg1.end(); - typename sorted_segment_map_type::const_iterator itr2 = seg2.begin(), itr2_end = seg2.end(); + std::unordered_set rhs; - for (; itr1 != itr1_end; ++itr1, ++itr2) + for (const segment_type& seg : r.m_segment_store) { - if (itr2 == itr2_end) - return false; + if (seg == segment_type{}) + continue; + + rhs.insert(&seg); + } + + std::size_t n_lhs = 0; + + for (const segment_type& seg : m_segment_store) + { + if (seg == segment_type{}) + continue; + + ++n_lhs; + const auto* src = &seg; - if (*itr1 != *itr2) + auto it = std::find_if(rhs.begin(), rhs.end(), [src](const segment_type* p) { return *src == *p; }); + + if (it == rhs.end()) return false; } - if (itr2 != itr2_end) - return false; - return true; + return n_lhs == rhs.size(); } -template -void segment_tree<_Key, _Value>::build_tree() +template +bool segment_tree::operator!=(const segment_tree& r) const { + return !operator==(r); +} + +template +void segment_tree::build_tree() +{ + m_valid_tree = false; + + // Remove deleted entries first + st::detail::erase_deleted_segments(m_segment_store); + build_leaf_nodes(); m_nonleaf_node_pool.clear(); + m_root_node = nullptr; + + if (!m_left_leaf) + { + assert(!m_right_leaf); + return; + } // Count the number of leaf nodes. - size_t leaf_count = __st::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); + size_t leaf_count = st::detail::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); // Determine the total number of non-leaf nodes needed to build the whole tree. - size_t nonleaf_count = __st::count_needed_nonleaf_nodes(leaf_count); + size_t nonleaf_count = st::detail::count_needed_nonleaf_nodes(leaf_count); m_nonleaf_node_pool.resize(nonleaf_count); - mdds::__st::tree_builder builder(m_nonleaf_node_pool); + mdds::st::detail::tree_builder builder(m_nonleaf_node_pool); m_root_node = builder.build(m_left_leaf); // Start "inserting" all segments from the root. - typename segment_map_type::const_iterator itr, itr_beg = m_segment_data.begin(), itr_end = m_segment_data.end(); - data_node_map_type tagged_node_map; - for (itr = itr_beg; itr != itr_end; ++itr) - { - value_type pdata = itr->first; - auto r = - tagged_node_map.insert(typename data_node_map_type::value_type(pdata, std::make_unique())); + value_to_nodes_type tagged_node_map; - node_list_type* plist = r.first->second.get(); - plist->reserve(10); + for (value_pos_type i = 0; i < m_segment_store.size(); ++i) + { + const auto& v = m_segment_store[i]; + auto r = tagged_node_map.emplace(std::make_pair(i, node_chain_type{})); + assert(r.second); - descend_tree_and_mark(m_root_node, pdata, itr->second.first, itr->second.second, plist); + node_chain_type& nodelist = r.first->second; + descend_tree_and_mark(m_root_node, i, v.start, v.end, nodelist); } - m_tagged_node_map.swap(tagged_node_map); + m_tagged_nodes_map.swap(tagged_node_map); m_valid_tree = true; } -template -void segment_tree<_Key, _Value>::descend_tree_and_mark( - __st::node_base* pnode, value_type pdata, key_type begin_key, key_type end_key, node_list_type* plist) +template +void segment_tree::descend_tree_and_mark( + st::detail::node_base* pnode, value_pos_type value, const key_type& start_key, const key_type& end_key, + node_chain_type& nodelist) { if (!pnode) return; @@ -201,73 +450,76 @@ { // This is a leaf node. node* pleaf = static_cast(pnode); - if (begin_key <= pleaf->value_leaf.key && pleaf->value_leaf.key < end_key) + if (start_key <= pleaf->key && pleaf->key < end_key) { leaf_value_type& v = pleaf->value_leaf; if (!v.data_chain) - v.data_chain = new data_chain_type; - v.data_chain->push_back(pdata); - plist->push_back(pnode); + v.data_chain = std::make_unique(); + v.data_chain->push_back(value); + nodelist.push_back(pnode); } return; } nonleaf_node* pnonleaf = static_cast(pnode); - if (end_key < pnonleaf->value_nonleaf.low || pnonleaf->value_nonleaf.high <= begin_key) + if (end_key < pnonleaf->low || pnonleaf->high <= start_key) return; - nonleaf_value_type& v = pnonleaf->value_nonleaf; - if (begin_key <= v.low && v.high < end_key) + if (start_key <= pnonleaf->low && pnonleaf->high < end_key) { // mark this non-leaf node and stop. + nonleaf_value_type& v = pnonleaf->value_nonleaf; + if (!v.data_chain) - v.data_chain = new data_chain_type; - v.data_chain->push_back(pdata); - plist->push_back(pnode); + v.data_chain = std::make_unique(); + v.data_chain->push_back(value); + nodelist.push_back(pnode); return; } - descend_tree_and_mark(pnonleaf->left, pdata, begin_key, end_key, plist); - descend_tree_and_mark(pnonleaf->right, pdata, begin_key, end_key, plist); + descend_tree_and_mark(pnonleaf->left, value, start_key, end_key, nodelist); + descend_tree_and_mark(pnonleaf->right, value, start_key, end_key, nodelist); } -template -void segment_tree<_Key, _Value>::build_leaf_nodes() +template +void segment_tree::build_leaf_nodes() { - using namespace std; + // NB: m_segment_store must not contain deleted segments! disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); - // In 1st pass, collect unique end-point values and sort them. - vector keys_uniq; - keys_uniq.reserve(m_segment_data.size() * 2); - typename segment_map_type::const_iterator itr, itr_beg = m_segment_data.begin(), itr_end = m_segment_data.end(); - for (itr = itr_beg; itr != itr_end; ++itr) + // Collect all boundary keys. + std::vector keys; + keys.reserve(m_segment_store.size() * 2); + + for (const auto& v : m_segment_store) { - keys_uniq.push_back(itr->second.first); - keys_uniq.push_back(itr->second.second); + keys.push_back(v.start); + keys.push_back(v.end); } - // sort and remove duplicates. - sort(keys_uniq.begin(), keys_uniq.end()); - keys_uniq.erase(unique(keys_uniq.begin(), keys_uniq.end()), keys_uniq.end()); - - create_leaf_node_instances(keys_uniq, m_left_leaf, m_right_leaf); + create_leaf_node_instances(std::move(keys), m_left_leaf, m_right_leaf); } -template -void segment_tree<_Key, _Value>::create_leaf_node_instances( - const ::std::vector& keys, node_ptr& left, node_ptr& right) +template +void segment_tree::create_leaf_node_instances(std::vector keys, node_ptr& left, node_ptr& right) { + left.reset(); + right.reset(); + if (keys.empty() || keys.size() < 2) // We need at least two keys in order to build tree. return; - typename ::std::vector::const_iterator itr = keys.begin(), itr_end = keys.end(); + // sort and remove duplicates. + std::sort(keys.begin(), keys.end()); + keys.erase(std::unique(keys.begin(), keys.end()), keys.end()); + + auto it = keys.cbegin(); // left-most node left.reset(new node); - left->value_leaf.key = *itr; + left->key = *it; // move on to next. left->next.reset(new node); @@ -275,9 +527,9 @@ node_ptr cur_node = left->next; cur_node->prev = prev_node; - for (++itr; itr != itr_end; ++itr) + for (++it; it != keys.cend(); ++it) { - cur_node->value_leaf.key = *itr; + cur_node->key = *it; // move on to next cur_node->next.reset(new node); @@ -291,151 +543,159 @@ right = prev_node; } -template -bool segment_tree<_Key, _Value>::insert(key_type begin_key, key_type end_key, value_type pdata) +template +void segment_tree::insert(key_type start_key, key_type end_key, value_type value) { - if (begin_key >= end_key) - return false; - - if (m_segment_data.find(pdata) != m_segment_data.end()) - // Insertion of duplicate data is not allowed. - return false; - - ::std::pair range; - range.first = begin_key; - range.second = end_key; - m_segment_data.insert(typename segment_map_type::value_type(pdata, range)); + if (start_key >= end_key) + throw std::invalid_argument("start key cannot be greater than or equal to the end key"); + m_segment_store.emplace_back(std::move(start_key), std::move(end_key), std::move(value)); m_valid_tree = false; - return true; -} - -template -bool segment_tree<_Key, _Value>::search(key_type point, search_results_type& result) const -{ - if (!m_valid_tree) - // Tree is invalidated. - return false; - - if (!m_root_node) - // Tree doesn't exist. Since the tree is flagged valid, this means no - // segments have been inserted. - return true; - - search_result_vector_inserter result_inserter(result); - typedef segment_tree<_Key, _Value> tree_type; - __st::descend_tree_for_search(point, m_root_node, result_inserter); - return true; } -template -typename segment_tree<_Key, _Value>::search_results segment_tree<_Key, _Value>::search(key_type point) const +template +typename segment_tree::search_results segment_tree::search(const key_type& point) const { - search_results result; + search_results result(m_segment_store); if (!m_valid_tree || !m_root_node) return result; search_result_inserter result_inserter(result); - typedef segment_tree<_Key, _Value> tree_type; - __st::descend_tree_for_search(point, m_root_node, result_inserter); + typedef segment_tree tree_type; + st::detail::descend_tree_for_search(point, m_root_node, result_inserter); return result; } -template -void segment_tree<_Key, _Value>::search(key_type point, search_results_base& result) const +template +void segment_tree::erase(const typename search_results::const_iterator& pos) { - if (!m_valid_tree || !m_root_node) - return; - - search_result_inserter result_inserter(result); - typedef segment_tree<_Key, _Value> tree_type; - __st::descend_tree_for_search(point, m_root_node, result_inserter); + remove_value_pos(pos.cur_pos()); } -template -void segment_tree<_Key, _Value>::remove(value_type value) +template +template +typename segment_tree::size_type segment_tree::erase_if(Pred pred) { - using namespace std; + size_type n_erased = 0; - typename data_node_map_type::iterator itr = m_tagged_node_map.find(value); - if (itr != m_tagged_node_map.end()) + for (size_type pos = 0; pos < m_segment_store.size(); ++pos) { - // Tagged node list found. Remove all the tags from the tree nodes. - node_list_type* plist = itr->second.get(); - if (!plist) - return; + const auto& seg = m_segment_store[pos]; + if (seg == segment_type()) + continue; // skip deleted segments - remove_data_from_nodes(plist, value); + if (!pred(seg.start, seg.end, seg.value)) + continue; - // Remove the tags associated with this pointer from the data set. - m_tagged_node_map.erase(itr); + remove_value_pos(pos); + ++n_erased; } - // Remove from the segment data array. - m_segment_data.erase(value); + return n_erased; +} + +template +void segment_tree::swap(segment_tree& r) noexcept +{ + m_nonleaf_node_pool.swap(r.m_nonleaf_node_pool); + m_segment_store.swap(r.m_segment_store); + m_tagged_nodes_map.swap(r.m_tagged_nodes_map); + std::swap(m_root_node, r.m_root_node); + m_left_leaf.swap(r.m_left_leaf); + m_right_leaf.swap(r.m_right_leaf); + std::swap(m_valid_tree, r.m_valid_tree); } -template -void segment_tree<_Key, _Value>::clear() +template +void segment_tree::clear() { - m_tagged_node_map.clear(); - m_segment_data.clear(); + m_tagged_nodes_map.clear(); + m_segment_store.clear(); clear_all_nodes(); m_valid_tree = false; } -template -size_t segment_tree<_Key, _Value>::size() const +template +typename segment_tree::size_type segment_tree::size() const { - return m_segment_data.size(); + return std::count_if( + m_segment_store.cbegin(), m_segment_store.cend(), [](const auto& v) { return v != segment_type(); }); } -template -bool segment_tree<_Key, _Value>::empty() const +template +bool segment_tree::empty() const { - return m_segment_data.empty(); + if (m_segment_store.empty()) + return true; + + // NB: take deleted segments into account + return size() == 0; } -template -size_t segment_tree<_Key, _Value>::leaf_size() const +template +typename segment_tree::size_type segment_tree::leaf_size() const { - return __st::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); + return st::detail::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); } -template -void segment_tree<_Key, _Value>::remove_data_from_nodes(node_list_type* plist, const value_type pdata) +template +void segment_tree::remove_data_from_nodes(node_chain_type& nodelist, value_pos_type value) { - typename node_list_type::iterator itr = plist->begin(), itr_end = plist->end(); - for (; itr != itr_end; ++itr) + for (st::detail::node_base* p : nodelist) { - data_chain_type* chain = nullptr; - __st::node_base* p = *itr; + value_chain_type* chain = nullptr; if (p->is_leaf) - chain = static_cast(p)->value_leaf.data_chain; + chain = static_cast(p)->value_leaf.data_chain.get(); else - chain = static_cast(p)->value_nonleaf.data_chain; + chain = static_cast(p)->value_nonleaf.data_chain.get(); if (!chain) continue; - remove_data_from_chain(*chain, pdata); + remove_data_from_chain(*chain, value); } } -template -void segment_tree<_Key, _Value>::remove_data_from_chain(data_chain_type& chain, const value_type pdata) +template +void segment_tree::remove_data_from_chain(value_chain_type& chain, value_pos_type value) { - typename data_chain_type::iterator itr = ::std::find(chain.begin(), chain.end(), pdata); - if (itr != chain.end()) + if (auto it = std::find(chain.begin(), chain.end(), value); it != chain.end()) { - *itr = chain.back(); + *it = chain.back(); chain.pop_back(); } } +template +void segment_tree::remove_value_pos(size_type pos) +{ +#ifdef MDDS_SEGMENT_TREE_DEBUG + if (pos >= m_segment_store.size()) + { + std::ostringstream os; + os << "specified segment position is out-of-bound: (pos=" << pos + << "; segment-store-count=" << m_segment_store.size() << ")"; + throw std::runtime_error(os.str()); + } +#endif + + m_segment_store[pos] = segment_type(); + + if (!m_valid_tree) + return; + + if (auto it = m_tagged_nodes_map.find(pos); it != m_tagged_nodes_map.end()) + { + // Tagged node list found. Remove all the tags from the tree nodes. + remove_data_from_nodes(it->second, pos); + + // Remove the tags associated with this pointer from the data set. + m_tagged_nodes_map.erase(it); + } +} -template -void segment_tree<_Key, _Value>::clear_all_nodes() +template +void segment_tree::clear_all_nodes() { disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); m_nonleaf_node_pool.clear(); @@ -444,120 +704,183 @@ m_root_node = nullptr; } -#ifdef MDDS_UNIT_TEST -template -void segment_tree<_Key, _Value>::dump_tree() const -{ - using ::std::cout; - using ::std::endl; +template +segment_tree::tree_dumper_traits::to_string::to_string(const tree_type& _tree) : tree(_tree) +{} - if (!m_valid_tree) - assert(!"attempted to dump an invalid tree!"); +template +std::string segment_tree::tree_dumper_traits::to_string::operator()(const leaf_type& leaf) const +{ + std::ostringstream os; + os << leaf.to_string(); - cout << "dump tree ------------------------------------------------------" << endl; - size_t node_count = mdds::__st::tree_dumper::dump(m_root_node); - size_t node_instance_count = node::get_instance_count(); + if (leaf.value_leaf.data_chain) + { + os << ":{"; + for (const auto pos : *leaf.value_leaf.data_chain) + os << tree.m_segment_store[pos].value << ','; + os << '}'; + } + else + os << ":{}"; - cout << "tree node count = " << node_count << " node instance count = " << node_instance_count << endl; + return os.str(); } -template -void segment_tree<_Key, _Value>::dump_leaf_nodes() const +template +std::string segment_tree::tree_dumper_traits::to_string::operator()(const nonleaf_type& nonleaf) const { - using ::std::cout; - using ::std::endl; + std::ostringstream os; + os << nonleaf.to_string(); - cout << "dump leaf nodes ------------------------------------------------" << endl; - - node* p = m_left_leaf.get(); - while (p) + if (nonleaf.value_nonleaf.data_chain) { - print_leaf_value(p->value_leaf); - p = p->next.get(); + os << ":{"; + for (const auto pos : *nonleaf.value_nonleaf.data_chain) + os << tree.m_segment_store[pos].value << ','; + os << '}'; } - cout << " node instance count = " << node::get_instance_count() << endl; + else + os << ":{}"; + + return os.str(); } -template -void segment_tree<_Key, _Value>::dump_segment_data() const +template +std::string segment_tree::to_string() const { - using namespace std; - cout << "dump segment data ----------------------------------------------" << endl; + std::ostringstream os; + + os << "valid tree: " << (m_valid_tree ? "true" : "false") << std::endl; + os << "stored segments:" << std::endl; + + for (const segment_type& v : m_segment_store) + { + if (v == segment_type()) + // skip deleted segment + continue; + + os << " - range: '[" << v.start << '-' << v.end << ")'" << std::endl; + os << " value: " << v.value << std::endl; + } + + if (!m_valid_tree) + return os.str(); - segment_map_printer func; - for_each(m_segment_data.begin(), m_segment_data.end(), func); + std::size_t node_count = mdds::st::detail::tree_dumper::dump(os, *this, m_root_node); + os << "tree node count: " << node_count; + + return os.str(); } -template -bool segment_tree<_Key, _Value>::verify_node_lists() const +template +auto segment_tree::boundary_keys() const -> std::vector { - using namespace std; + std::vector keys; - typename data_node_map_type::const_iterator itr = m_tagged_node_map.begin(), itr_end = m_tagged_node_map.end(); - for (; itr != itr_end; ++itr) + for (const auto& seg : m_segment_store) { - // Print stored nodes. - cout << "node list " << itr->first->name << ": "; - const node_list_type* plist = itr->second.get(); - assert(plist); - node_printer func; - for_each(plist->begin(), plist->end(), func); - cout << endl; + if (seg == segment_type{}) + continue; - // Verify that all of these nodes have the data pointer. - if (!has_data_pointer(*plist, itr->first)) - return false; + keys.push_back(seg.start); + keys.push_back(seg.end); } - return true; + + std::sort(keys.begin(), keys.end()); + auto last = std::unique(keys.begin(), keys.end()); + keys.erase(last, keys.end()); + + return keys; } -template -bool segment_tree<_Key, _Value>::verify_leaf_nodes(const ::std::vector& checks) const +template +void segment_tree::check_integrity(const integrity_check_properties& props) const { - using namespace std; - node* cur_node = m_left_leaf.get(); - typename ::std::vector::const_iterator itr = checks.begin(), itr_end = checks.end(); - for (; itr != itr_end; ++itr) - { - if (!cur_node) - // Position past the right-mode node. Invalid. + + const auto& segstore = m_segment_store; + auto to_string = [&segstore](const value_chain_type& chain) -> std::string { + std::ostringstream os; + for (auto pos : chain) + os << segstore[pos].value << ", "; + return os.str(); + }; + + auto has_value_index = [](const st::detail::node_base* pnode, value_pos_type value_index) { + const value_chain_type* chain = nullptr; + + if (pnode->is_leaf) + chain = static_cast(pnode)->value_leaf.data_chain.get(); + else + chain = static_cast(pnode)->value_nonleaf.data_chain.get(); + + if (!chain) return false; - if (cur_node->value_leaf.key != itr->key) - // Key values differ. + if (std::find(chain->begin(), chain->end(), value_index) == chain->end()) return false; - if (itr->data_chain.empty()) + return true; + }; + + // Check the integrity of the leaf nodes first. + + for (const auto& node_check : props.leaf_nodes) + { + value_chain_type chain_expected; + + for (const auto& v : node_check.value_chain) + { + auto it = std::find_if( + m_segment_store.cbegin(), m_segment_store.cend(), [&v](const auto& seg) { return seg.value == v; }); + + if (it == m_segment_store.cend()) + { + std::ostringstream os; + os << "value '" << v << "' is not stored in this instance"; + throw std::invalid_argument(os.str()); + } + + chain_expected.push_back(std::distance(m_segment_store.cbegin(), it)); + } + + assert(chain_expected.size() == node_check.value_chain.size()); + + if (!cur_node) + throw integrity_error("current node position is past the right-most node which is unexpected"); + + if (cur_node->key != node_check.key) + { + std::ostringstream os; + os << "key values differ: expected='" << node_check.key << "'; actual='" << cur_node->key << "'"; + throw integrity_error(os.str()); + } + + if (chain_expected.empty()) { if (cur_node->value_leaf.data_chain) - // The data chain should be empty (i.e. the pointer should be nullptr). - return false; + throw integrity_error("data chain should be empty i.e. its pointer value should be nullptr"); } else { if (!cur_node->value_leaf.data_chain) - // This node should have data pointers! - return false; + throw integrity_error("node has empty data chain but it should have a non-empty data chain"); - data_chain_type chain1 = itr->data_chain; - data_chain_type chain2 = *cur_node->value_leaf.data_chain; - - if (chain1.size() != chain2.size()) - return false; - - ::std::vector test1, test2; - test1.reserve(chain1.size()); - test2.reserve(chain2.size()); - copy(chain1.begin(), chain1.end(), back_inserter(test1)); - copy(chain2.begin(), chain2.end(), back_inserter(test2)); + value_chain_type chain_actual = *cur_node->value_leaf.data_chain; // copy // Sort both arrays before comparing them. - sort(test1.begin(), test1.end()); - sort(test2.begin(), test2.end()); + std::sort(chain_expected.begin(), chain_expected.end()); + std::sort(chain_actual.begin(), chain_actual.end()); - if (test1 != test2) - return false; + if (chain_expected != chain_actual) + { + std::ostringstream os; + os << "data chain of leaf node with key '" << cur_node->key << "' is not as expected:" << std::endl; + os << " expected: " << to_string(chain_expected) << std::endl; + os << " actual: " << to_string(chain_actual); + throw integrity_error(os.str()); + } } cur_node = cur_node->next.get(); @@ -566,79 +889,23 @@ if (cur_node) // At this point, we expect the current node to be at the position // past the right-most node, which is nullptr. - return false; - - return true; -} + throw integrity_error("current node position was expected to be past the right-most node but it isn't"); -template -bool segment_tree<_Key, _Value>::verify_segment_data(const segment_map_type& checks) const -{ - // Sort the data by key values first. - sorted_segment_map_type seg1(checks.begin(), checks.end()); - sorted_segment_map_type seg2(m_segment_data.begin(), m_segment_data.end()); + // Check the integrity of the tagged-node map. - typename sorted_segment_map_type::const_iterator itr1 = seg1.begin(), itr1_end = seg1.end(); - typename sorted_segment_map_type::const_iterator itr2 = seg2.begin(), itr2_end = seg2.end(); - for (; itr1 != itr1_end; ++itr1, ++itr2) + for (const auto& [value_index, nodes] : m_tagged_nodes_map) { - if (itr2 == itr2_end) - return false; - - if (*itr1 != *itr2) - return false; - } - if (itr2 != itr2_end) - return false; - - return true; -} - -template -bool segment_tree<_Key, _Value>::has_data_pointer(const node_list_type& node_list, const value_type pdata) -{ - using namespace std; - - typename node_list_type::const_iterator itr = node_list.begin(), itr_end = node_list.end(); - - for (; itr != itr_end; ++itr) - { - // Check each node, and make sure each node has the pdata pointer - // listed. - const __st::node_base* pnode = *itr; - const data_chain_type* chain = nullptr; - if (pnode->is_leaf) - chain = static_cast(pnode)->value_leaf.data_chain; - else - chain = static_cast(pnode)->value_nonleaf.data_chain; - - if (!chain) - return false; - - if (find(chain->begin(), chain->end(), pdata) == chain->end()) - return false; - } - return true; -} - -template -void segment_tree<_Key, _Value>::print_leaf_value(const leaf_value_type& v) -{ - using namespace std; - cout << v.key << ": { "; - if (v.data_chain) - { - const data_chain_type* pchain = v.data_chain; - typename data_chain_type::const_iterator itr, itr_beg = pchain->begin(), itr_end = pchain->end(); - for (itr = itr_beg; itr != itr_end; ++itr) + for (const st::detail::node_base* this_node : nodes) { - if (itr != itr_beg) - cout << ", "; - cout << (*itr)->name; + if (!has_value_index(this_node, value_index)) + { + std::ostringstream os; + os << "invalid tagged node map: node (" << this_node << ") does not contain a value index of " + << value_index; + throw integrity_error(os.str()); + } } } - cout << " }" << endl; } -#endif } // namespace mdds diff -Nru mdds-2.1.1/include/mdds/sorted_string_map.hpp mdds-3.1.0/include/mdds/sorted_string_map.hpp --- mdds-2.1.1/include/mdds/sorted_string_map.hpp 2022-08-21 03:01:39.000000000 +0000 +++ mdds-3.1.0/include/mdds/sorted_string_map.hpp 2024-01-10 23:45:35.000000000 +0000 @@ -28,47 +28,99 @@ #pragma once -#include +#include "./cref_wrapper.hpp" + #include +#include namespace mdds { +namespace ssmap { +namespace detail { + +template +struct map_entry +{ + std::string_view key; + ValueT value; +}; + +} // namespace detail + /** - * Single key-value entry. Caller must provide at compile time a static array - * of these entries. - * - * @param key memory address of the first character of the char buffer that - * stores the key. - * @param key_length length of the char buffer. - * @param value value associated with the key. + * Function object that iterates through the key-value entries linearly until + * it finds one that contains the target value. */ -template -struct chars_map_entry +template +class linear_key_finder { - const char* key; - SizeT key_length; - ValueT value; + using value_type = ValueT; + using size_type = typename std::string_view::size_type; + using entry_type = detail::map_entry; + + const entry_type* m_entries; + const entry_type* m_entries_end; + +public: + linear_key_finder(const entry_type* entries, const entry_type* entries_end); + + std::string_view operator()(const value_type& v) const; }; -template -struct string_view_map_entry +/** + * Function object that builds a hash map of values to keys during its + * construction, and uses it during the lookup of the keys. + */ +template +class hash_key_finder { - std::string_view key; - ValueT value; + using value_type = ValueT; + using size_type = typename std::string_view::size_type; + using entry_type = detail::map_entry; + using keystore_type = std::unordered_map< + mdds::detail::cref_wrapper, size_type, typename mdds::detail::cref_wrapper::hash>; + + const entry_type* m_entries; + keystore_type m_keys; + +public: + hash_key_finder(const entry_type* entries, const entry_type* entries_end); + + std::string_view operator()(const value_type& v) const; }; +} // namespace ssmap + /** - * 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. + * sorted_string_map is an immutable associative container that provides an + * efficient way to map string keys to values of a user-specified type. + * The keys must be known at compile time and must be sorted in ascending + * order. + * + * Besides the minimal amount of memory required to store the size and memory + * address of the caller-provided key-value entries and a few extra data, + * it does not allocate any additional memory; it simply re-uses the + * caller-provided key-value entries in all of its operations. + * + * @tparam ValueT Type of the values associated with the string keys. + * This type must be either movable or copyable. + * @tparam KeyFinderT Function object type for performing reverse-lookup of + * keys from values. This is used in the find_key() method. */ -template class EntryT = chars_map_entry> +template class KeyFinderT = ssmap::linear_key_finder> class sorted_string_map { + using func_find_key_type = KeyFinderT; + public: using value_type = ValueT; - using size_type = std::size_t; - using entry = EntryT; + using size_type = typename std::string_view::size_type; + + /** + * Single key-value entry type. Caller must provide at compile time a + * static array of these entries. + */ + using entry_type = ssmap::detail::map_entry; /** * Constructor. @@ -78,7 +130,7 @@ * @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); + sorted_string_map(const entry_type* entries, size_type entry_size, value_type null_value); /** * Find a value associated with a specified string key. @@ -90,7 +142,7 @@ * @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; + const value_type& find(const char* input, size_type len) const; /** * Find a value associated with a specified string key. @@ -100,7 +152,21 @@ * @return value associated with the key, or the null value in case the * key is not found. */ - value_type find(std::string_view input) const; + const value_type& find(std::string_view input) const; + + /** + * Find a key associated with a specified value. + * + * @warning When multiple keys are associated with one value, this method + * only returns one of the keys. Which key gets returned for that + * value is undefined. + * + * @param v Value to find the associated key of. + * + * @return Key associated with the value, or an empty string if no key is + * found. + */ + std::string_view find_key(const value_type& v) const; /** * Return the number of entries in the map. Since the number of entries @@ -112,10 +178,12 @@ size_type size() const; private: - const entry* m_entries; - value_type m_null_value; - size_type m_entry_size; - const entry* m_entry_end; + const entry_type* m_entries; + const value_type m_null_value; + const size_type m_entry_size; + const entry_type* m_entries_end; + + func_find_key_type m_func_find_key; }; } // namespace mdds diff -Nru mdds-2.1.1/include/mdds/sorted_string_map_def.inl mdds-3.1.0/include/mdds/sorted_string_map_def.inl --- mdds-2.1.1/include/mdds/sorted_string_map_def.inl 2022-09-13 02:21:43.000000000 +0000 +++ mdds-3.1.0/include/mdds/sorted_string_map_def.inl 2024-01-10 23:45:35.000000000 +0000 @@ -29,135 +29,116 @@ #include "./global.hpp" #include +#include #include namespace mdds { +namespace ssmap { namespace detail { -template class EntryT> -struct entry_funcs; - -template -struct entry_funcs +template +struct compare { - using entry = chars_map_entry; - using size_type = SizeT; + using entry_type = map_entry; - static bool compare(const entry& entry1, const entry& entry2) + bool operator()(const entry_type& entry1, const entry_type& entry2) const { - if (entry1.key_length != entry2.key_length) - { - std::size_t key_length = std::min(entry1.key_length, entry2.key_length); - int ret = std::memcmp(entry1.key, entry2.key, key_length); - if (ret == 0) - return entry1.key_length < entry2.key_length; - - return ret < 0; - } - else - { - return std::memcmp(entry1.key, entry2.key, entry1.key_length) < 0; - } - } - - static entry to_entry(const char* input, std::size_t len) - { - return entry{input, len, ValueT{}}; - } + if (entry1.key.size() == entry2.key.size()) + return std::memcmp(entry1.key.data(), entry2.key.data(), entry1.key.size()) < 0; - static const char* get_key_ptr(const entry& e) - { - return e.key; - } + std::size_t key_length = std::min(entry1.key.size(), entry2.key.size()); + int ret = std::memcmp(entry1.key.data(), entry2.key.data(), key_length); + if (ret == 0) + return entry1.key.size() < entry2.key.size(); - static size_type get_key_size(const entry& e) - { - return e.key_length; + return ret < 0; } }; -template -struct entry_funcs -{ - using entry = string_view_map_entry; - using size_type = SizeT; +} // namespace detail - static bool compare(const entry& entry1, const entry& entry2) - { - if (entry1.key.size() != entry2.key.size()) - { - std::size_t key_length = std::min(entry1.key.size(), entry2.key.size()); - int ret = std::memcmp(entry1.key.data(), entry2.key.data(), key_length); - if (ret == 0) - return entry1.key.size() < entry2.key.size(); - - return ret < 0; - } - else - { - return std::memcmp(entry1.key.data(), entry2.key.data(), entry1.key.size()) < 0; - } - } +template +linear_key_finder::linear_key_finder(const entry_type* entries, const entry_type* entries_end) + : m_entries(entries), m_entries_end(entries_end) +{} + +template +std::string_view linear_key_finder::operator()(const value_type& v) const +{ + auto it = std::find_if(m_entries, m_entries_end, [&v](const auto& e) { return e.value == v; }); + if (it == m_entries_end) + return {}; - static entry to_entry(const char* input, std::size_t len) - { - return entry{{input, len}, ValueT{}}; - } + return it->key; +} - static const char* get_key_ptr(const entry& e) - { - return e.key.data(); - } +template +hash_key_finder::hash_key_finder(const entry_type* entries, const entry_type* entries_end) : m_entries(entries) +{ + size_type pos = 0u; + for (const auto* e = entries; e != entries_end; ++e, ++pos) + m_keys.insert_or_assign(e->value, pos); - static size_type get_key_size(const entry& e) - { - return e.key.size(); - } -}; + assert(pos == static_cast(entries_end - entries)); +} -} // namespace detail +template +std::string_view hash_key_finder::operator()(const value_type& v) const +{ + auto it = m_keys.find(v); + if (it == m_keys.cend()) + return {}; -template class EntryT> -sorted_string_map::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) + const auto* entry = m_entries + it->second; + return entry->key; +} + +} // namespace ssmap + +template class KeyFinderT> +sorted_string_map::sorted_string_map( + const entry_type* entries, size_type entry_size, value_type null_value) + : m_entries(entries), m_null_value(std::move(null_value)), m_entry_size(entry_size), + m_entries_end(m_entries + m_entry_size), m_func_find_key(m_entries, m_entries_end) { #ifdef MDDS_SORTED_STRING_MAP_DEBUG - using entry_funcs = detail::entry_funcs; - - if (!std::is_sorted(m_entries, m_entry_end, entry_funcs::compare)) + if (!std::is_sorted(m_entries, m_entries_end, ssmap::detail::compare{})) throw invalid_arg_error("mapped entries are not sorted"); #endif } -template class EntryT> -typename sorted_string_map::value_type sorted_string_map::find( +template class KeyFinderT> +const typename sorted_string_map::value_type& sorted_string_map::find( const char* input, size_type len) const { if (m_entry_size == 0) return m_null_value; - using entry_funcs = detail::entry_funcs; - entry ent = entry_funcs::to_entry(input, len); + const entry_type* val = std::lower_bound( + m_entries, m_entries_end, entry_type{{input, len}, value_type{}}, ssmap::detail::compare{}); - const entry* val = std::lower_bound(m_entries, m_entry_end, ent, entry_funcs::compare); - - if (val == m_entry_end || entry_funcs::get_key_size(*val) != len || - std::memcmp(entry_funcs::get_key_ptr(*val), input, len)) + if (val == m_entries_end || val->key.size() != len || std::memcmp(val->key.data(), input, len)) return m_null_value; return val->value; } -template class EntryT> -typename sorted_string_map::value_type sorted_string_map::find( +template class KeyFinderT> +const typename sorted_string_map::value_type& sorted_string_map::find( std::string_view input) const { return find(input.data(), input.size()); } -template class EntryT> -typename sorted_string_map::size_type sorted_string_map::size() const +template class KeyFinderT> +std::string_view sorted_string_map::find_key(const value_type& v) const +{ + return m_func_find_key(v); +} + +template class KeyFinderT> +typename sorted_string_map::size_type sorted_string_map::size() const { return m_entry_size; } diff -Nru mdds-2.1.1/include/mdds/trie_map.hpp mdds-3.1.0/include/mdds/trie_map.hpp --- mdds-2.1.1/include/mdds/trie_map.hpp 2023-04-21 02:32:52.000000000 +0000 +++ mdds-3.1.0/include/mdds/trie_map.hpp 2025-02-08 04:41:45.000000000 +0000 @@ -36,110 +36,27 @@ #include #include #include +#include +#include namespace mdds { namespace trie { -/** - * Template for a key type implemented using a typical STL container type. - */ -template -struct std_container_traits -{ - /** type used to store a key value. */ - using key_type = ContainerT; - - /** - * type used to build an intermediate key value, from which a final key - * value is to be created. It is expected to be an array structure whose - * content is contiguous in memory. Its elements must be of - * key_unit_type. - */ - using key_buffer_type = key_type; - - /** - * type that represents a single character inside a key or a key buffer - * object. A key object is expected to store a series of elements of this - * type. - */ - using key_unit_type = typename key_type::value_type; - - /** - * Function called to create and initialize a buffer object from a given - * initial key value. - * - * @param str pointer to the first character of the key value. - * @param length length of the key value. - * - * @return buffer object containing the specified key value. - */ - static key_buffer_type to_key_buffer(const key_unit_type* str, size_t length) - { - return key_buffer_type(str, length); - } +namespace detail { - /** - * Function called to create and initialize a buffer object from a given - * initial key value. - * - * @param key key value - * - * @return buffer object containing the specified key value. - */ - static key_buffer_type to_key_buffer(const key_type& key) - { - return key_buffer_type(key); - } - - static const key_unit_type* buffer_data(const key_buffer_type& buf) - { - return buf.data(); - } - - static size_t buffer_size(const key_buffer_type& buf) - { - return buf.size(); - } - - /** - * Function called to append a single character to the end of a key - * buffer. - * - * @param buffer buffer object to append character to. - * @param c character to append to the buffer. - */ - static void push_back(key_buffer_type& buffer, key_unit_type c) - { - buffer.push_back(c); - } - - /** - * Function called to remove a single character from the tail of an - * existing key buffer. - * - * @param buffer buffer object to remove character from. - */ - static void pop_back(key_buffer_type& buffer) - { - buffer.pop_back(); - } +struct copy_to_pack +{ +}; - /** - * Function called to create a final string object from an existing - * buffer. - * - * @param buf buffer object to create a final string object from. - * - * @return string object whose content is created from the buffer object. - */ - static key_type to_key(const key_buffer_type& buf) - { - return buf; - } +struct move_to_pack +{ }; -using std_string_traits = std_container_traits; +template +struct dump_packed_buffer; + +} // namespace detail /** Serializer for numeric data types. */ template @@ -204,9 +121,40 @@ { }; +struct default_traits +{ + /** + * Unit value type of a buffer used in packed_trie_map to store its content. + * It must be an unsigned integral type. + * + * @note Maximum number of key-value pairs that can be stored in the + * packed_trie_map variant is the maximum value that can be expressed + * by this type minus one. For instance, if the size of this type is + * 8-bits, only up to 255 key-value pairs can be stored. + */ + using pack_value_type = uintptr_t; +}; + +/** + * Specifies the type of human-readable output to dump. + */ +enum class dump_structure_type +{ + /** + * Dump the in-memory buffer that stores the trie content in a linear + * fashion. + */ + packed_buffer, + + /** + * Dump the traversal result of the trie in depth-first order. + */ + trie_traversal, +}; + } // namespace trie -template +template class packed_trie_map; /** @@ -215,10 +163,10 @@ * are stored in an ordered tree structure known as trie, or sometimes * referred to as prefix tree. */ -template +template class trie_map { - friend class packed_trie_map; + friend class packed_trie_map; friend class trie::detail::iterator_base; friend class trie::detail::iterator_base; friend class trie::detail::const_iterator; @@ -228,14 +176,12 @@ friend trie::detail::get_node_stack_type; public: - typedef packed_trie_map packed_type; - typedef KeyTraits key_traits_type; - typedef typename key_traits_type::key_type key_type; - typedef typename key_traits_type::key_buffer_type key_buffer_type; - typedef typename key_traits_type::key_unit_type key_unit_type; + using traits_type = TraitsT; + typedef packed_trie_map packed_type; + typedef KeyT key_type; + typedef typename key_type::value_type key_unit_type; typedef ValueT value_type; typedef size_t size_type; - typedef std::pair key_value_type; using const_iterator = trie::detail::const_iterator; using iterator = trie::detail::iterator; @@ -289,6 +235,69 @@ public: /** + * Represents an individual node of a trie. + */ + class const_node_type + { + friend class trie_map; + + const trie_node* m_ref_node = nullptr; + + const_node_type(const trie_node* ref_node); + + public: + const_node_type(); + const_node_type(const const_node_type& other); + + const_node_type& operator=(const const_node_type& other); + + /** + * Query whether or not the node references an existing node in a tree. + * + * @return True if the node references an existing node in a tree, + * or false if the node does not reference any node in any tree. + */ + bool valid() const; + + /** + * Query whether or not the node has at least one child node. + * + * @return True if the node has at least one child node, or false if the + * node has no child nodes at all. + */ + bool has_child() const; + + /** + * Query whether or not the node has a value associated with it. + * + * @return True if the node has a value, otherwise false. + */ + bool has_value() const; + + /** + * Access the value associated with the node. + * + * @return Reference to the value associated with the node. + * + * @warning The caller must ensure that the node has a value via + * has_value() before calling this method to access it. + * Calling this method on a node without a value is undefined. + */ + const value_type& value() const; + + /** + * Move to a child node by a unit key. + * + * @param c A unit key associated with a child node relative to the + * current node. + * + * @return A valid node if a child node exists for the unit key passed + * to this method, otherwise an invalid node is returned. + */ + const_node_type child(key_unit_type c) const; + }; + + /** * Default constructor. */ trie_map(); @@ -307,15 +316,25 @@ trie_map& operator=(trie_map other); + bool operator==(const trie_map& other) const; + bool operator!=(const trie_map& other) const; + void swap(trie_map& other); /** + * Obtain a root node of the trie to traverse it node-by-node. + * + * @return Root node of the trie. + */ + const_node_type root_node() const; + + /** * Insert a new key-value pair. * * @param key key value. * @param value value to associate with the key. */ - void insert(const key_type& key, const value_type& value); + void insert(const key_type& key, value_type value); /** * Insert a new key-value pair. @@ -325,7 +344,7 @@ * @param len length of the character array storing the key. * @param value value to associate with the key. */ - void insert(const key_unit_type* key, size_type len, const value_type& value); + void insert(const key_unit_type* key, size_type len, value_type value); /** * Erase a key and the value associated with it. @@ -427,13 +446,23 @@ * provides better search performance and requires much less memory * footprint. * - * @return an instance of mdds::packed_trie_map with the same content. + * @note Calling this method will move all stored values into the packed + * variant. You should make a copy of the instance first if you need + * to preserve the original. + * + * @return an instance of mdds::packed_trie_map with the same content, + * with all the values stored in the original instance moved into + * the returned instance. + * + * @throws mdds::size_error When the number of entries exceeds maximum + * allowed number of key-value pairs. + * See trie::default_traits::pack_value_type for more + * detailed explanation. */ - packed_type pack() const; + packed_type pack(); private: - void insert_into_tree( - trie_node& node, const key_unit_type* key, const key_unit_type* key_end, const value_type& value); + void insert_into_tree(trie_node& node, const key_unit_type* key, const key_unit_type* key_end, value_type value); const trie_node* find_prefix_node( const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const; @@ -444,10 +473,12 @@ const key_unit_type* prefix, const key_unit_type* prefix_end) const; template - key_buffer_type build_key_buffer_from_node_stack(const std::vector>& node_stack) const; + key_type build_key_buffer_from_node_stack(const std::vector>& node_stack) const; void count_values(size_type& n, const trie_node& node) const; + bool descend_for_equality(const trie_node& left, const trie_node& right) const; + private: trie_node m_root; }; @@ -462,20 +493,23 @@ * Note that, since this container is immutable, the content of the * container cannot be modified once constructed. */ -template +template class packed_trie_map { + using pack_value_type = typename TraitsT::pack_value_type; + using packed_type = std::vector; + friend class trie::detail::packed_iterator_base; friend class trie::detail::packed_search_results; + friend class trie_map; + friend struct trie::detail::dump_packed_buffer; public: - typedef KeyTraits key_traits_type; - typedef typename key_traits_type::key_type key_type; - typedef typename key_traits_type::key_buffer_type key_buffer_type; - typedef typename key_traits_type::key_unit_type key_unit_type; + using traits_type = TraitsT; + typedef KeyT key_type; + typedef typename key_type::value_type key_unit_type; typedef ValueT value_type; typedef size_t size_type; - typedef std::pair key_value_type; typedef trie::detail::packed_iterator_base const_iterator; typedef trie::detail::packed_search_results search_results; @@ -495,6 +529,13 @@ }; private: + using value_store_type = std::deque; + + /** Special value representing a value-not-set. */ + static constexpr auto null_value = std::numeric_limits::max(); + /** Maximum allowed index for value. */ + static constexpr auto max_value_pos = null_value - 1u; + struct trie_node { key_unit_type key; @@ -508,17 +549,22 @@ struct stack_item { - const uintptr_t* node_pos; - const uintptr_t* child_pos; - const uintptr_t* child_end; + const value_store_type* value_store = nullptr; - stack_item(const uintptr_t* _node_pos, const uintptr_t* _child_pos, const uintptr_t* _child_end) - : node_pos(_node_pos), child_pos(_child_pos), child_end(_child_end) + const pack_value_type* node_pos = nullptr; + const pack_value_type* child_pos = nullptr; + const pack_value_type* child_end = nullptr; + + stack_item( + const value_store_type* _value_store, const pack_value_type* _node_pos, const pack_value_type* _child_pos, + const pack_value_type* _child_end) + : value_store(_value_store), node_pos(_node_pos), child_pos(_child_pos), child_end(_child_end) {} bool operator==(const stack_item& other) const { - return node_pos == other.node_pos && child_pos == other.child_pos; + return value_store == other.value_store && node_pos == other.node_pos && child_pos == other.child_pos && + child_end == other.child_end; } bool operator!=(const stack_item& other) const @@ -528,24 +574,87 @@ bool has_value() const { - const value_type* pv = reinterpret_cast(*node_pos); - return pv; + return *node_pos != null_value; } - const value_type* get_value() const + pack_value_type get_value_pos() const { - return reinterpret_cast(*node_pos); + return *node_pos; } }; typedef std::vector node_stack_type; - typedef std::deque node_pool_type; - typedef std::vector packed_type; - typedef std::deque value_store_type; typedef std::vector> child_offsets_type; + packed_trie_map(trie::detail::move_to_pack, trie_map& from); + public: + /** + * Represents an individual node of a trie. + */ + class const_node_type + { + friend class packed_trie_map; + + const packed_type* m_packed = nullptr; + const value_store_type* m_value_store = nullptr; + const pack_value_type* m_pos = nullptr; + + const_node_type(const packed_type* packed, const value_store_type* value_store, const pack_value_type* p); + + public: + const_node_type() = default; + const_node_type(const const_node_type& other) = default; + + const_node_type& operator=(const const_node_type& other); + + /** + * Query whether or not the node references an existing node in a tree. + * + * @return True if the node references an existing node in a tree, + * or false if the node does not reference any node in any tree. + */ + bool valid() const; + + /** + * Query whether or not the node has at least one child node. + * + * @return True if the node has at least one child node, or false if the + * node has no child nodes at all. + */ + bool has_child() const; + + /** + * Query whether or not the node has a value associated with it. + * + * @return True if the node has a value, otherwise false. + */ + bool has_value() const; + + /** + * Access the value associated with the node. + * + * @return Reference to the value associated with the node. + * + * @warning The caller must ensure that the node has a value via + * has_value() before calling this method to access it. + * Calling this method on a node without a value is undefined. + */ + const value_type& value() const; + + /** + * Move to a child node by a unit key. + * + * @param c A unit key associated with a child node relative to the + * current node. + * + * @return A valid node if a child node exists for the unit key passed + * to this method, otherwise an invalid node is returned. + */ + const_node_type child(key_unit_type c) const; + }; + packed_trie_map(); /** @@ -555,6 +664,11 @@ * * @param entries pointer to the array of key-value entries. * @param entry_size size of the key-value entry array. + * + * @throws mdds::size_error When the number of entries exceeds + * maximum allowed number of key-value pairs. See + * trie::default_traits::pack_value_type for more detailed + * explanation. */ packed_trie_map(const entry* entries, size_type entry_size); @@ -563,8 +677,13 @@ * mdds::trie_map instance. * * @param other mdds::trie_map instance to build content from. + * + * @throws mdds::size_error When the number of entries exceeds + * maximum allowed number of key-value pairs. See + * trie::default_traits::pack_value_type for more detailed + * explanation. */ - packed_trie_map(const trie_map& other); + packed_trie_map(const trie_map& other); packed_trie_map(const packed_trie_map& other); @@ -643,6 +762,13 @@ void swap(packed_trie_map& other); /** + * Obtain a root node of the trie to traverse it node-by-node. + * + * @return Root node of the trie. + */ + const_node_type root_node() const; + + /** * Save the state of the instance of this class to an external buffer. * * @param os output stream to write the state to. @@ -660,45 +786,42 @@ void load_state(std::istream& is); /** - * Dump the structure of the trie content for debugging. You must define - * MDDS_TRIE_MAP_DEBUG in order for this method to generate - * output. + * Dump the structure of the trie content in a specified human-readable + * textural format. + * + * @param type Output format type. */ - void dump_structure() const; + std::string dump_structure(trie::dump_structure_type type) const; private: + void dump_trie_traversal(std::ostream& os) const; + node_stack_type get_root_stack() const; void traverse_range( trie_node& root, node_pool_type& node_pool, const entry* start, const entry* end, size_type pos); size_type compact_node(const trie_node& node); - size_type compact_node(const typename trie_map::trie_node& node); + + template + size_type compact_node(ModeT, NodeT& node); + + void check_value_size_or_throw() const; + + size_type push_value_to_store(trie::detail::copy_to_pack, const value_type& value); + size_type push_value_to_store(trie::detail::move_to_pack, value_type& value); void push_child_offsets(size_type offset, const child_offsets_type& child_offsets); + void init_pack(); void compact(const trie_node& root); - void compact(const typename trie_map::trie_node& root); - - const uintptr_t* find_prefix_node( - const uintptr_t* p, const key_unit_type* prefix, const key_unit_type* prefix_end) const; - void find_prefix_node_with_stack( - node_stack_type& node_stack, const uintptr_t* p, const key_unit_type* prefix, - const key_unit_type* prefix_end) const; + template + void compact(ModeT, NodeT& root); template void traverse_tree(_Handler hdl) const; - template - void traverse_buffer(_Handler hdl) const; - -#ifdef MDDS_TRIE_MAP_DEBUG - void dump_node(key_buffer_type& buffer, const trie_node& node) const; - void dump_trie(const trie_node& root) const; - void dump_packed_trie() const; -#endif - private: value_store_type m_value_store; packed_type m_packed; diff -Nru mdds-2.1.1/include/mdds/trie_map_def.inl mdds-3.1.0/include/mdds/trie_map_def.inl --- mdds-2.1.1/include/mdds/trie_map_def.inl 2023-04-21 02:32:52.000000000 +0000 +++ mdds-3.1.0/include/mdds/trie_map_def.inl 2024-03-26 01:55:58.000000000 +0000 @@ -29,22 +29,309 @@ #include "mdds/global.hpp" #include +#include +#include #include -#include #include +#include +#include +#include #include #include +#include -#ifdef MDDS_TRIE_MAP_DEBUG -#include -#include -using std::cout; -using std::endl; -#endif +#define HAS_STATIC_CONSTEXPR_MEMBER(MEMBER) \ + template \ + class has_##MEMBER \ + { \ + using y_type = char; \ + using n_type = long; \ +\ + template \ + static y_type test(decltype(U::MEMBER)); \ + template \ + static n_type test(...); \ +\ + public: \ + static constexpr bool value = sizeof(test(0)) == sizeof(y_type); \ + }; namespace mdds { -namespace detail { namespace trie { +namespace trie { namespace detail { + +HAS_STATIC_CONSTEXPR_MEMBER(dump_packed_construction_state) + +template +struct traverse_packed_buffer +{ + using packed_type = PackedT; + + void operator()(const packed_type& packed, HandlerT hdl) const + { + size_t n = packed.size(); + size_t i = 0; + hdl.root_offset(i, packed[i]); + ++i; + + while (i < n) + { + hdl.node_value(i, packed[i]); + ++i; + + hdl.node_index_size(i, packed[i]); + size_t index_size = packed[i]; + ++i; + index_size /= 2; + + for (size_t j = 0; j < index_size; ++j) + { + hdl.node_child_key(i, packed[i]); + ++i; + hdl.node_child_offset(i, packed[i]); + ++i; + } + } + } +}; + +template +struct dump_packed_buffer +{ + using packed_type = PackedT; + using key_type = typename TrieT::key_type; + using key_unit_type = typename key_type::value_type; + using value_type = typename TrieT::value_type; + using pack_value_type = typename TrieT::traits_type::pack_value_type; + + static constexpr auto null_value = TrieT::null_value; + + void operator()(std::ostream& os, const packed_type& packed) + { + os << std::setfill('0') << "---\n" + << "# packed buffer layout\n" + << "buffer size: " << packed.size() << "\n" + << "layout:" << std::endl; + + int width = std::floor(std::log10(packed.size())) + 1; + + struct _handler + { + std::ostream& m_os; + const int m_width = 0; + std::size_t m_this_node_offset = 0; + + _handler(std::ostream& _os, int width) : m_os(_os), m_width(width) + {} + + /** first element in the buffer. */ + void root_offset(size_t i, pack_value_type v) const + { + m_os << " " << std::setw(m_width) << i << ": root node offset (" << v << ")" << std::endl; + } + + /** first element in each node section. */ + void node_value(size_t i, pack_value_type v) + { + m_this_node_offset = i; + m_os << " " << std::setw(m_width) << i << ": node value pos ("; + + if (v == null_value) + m_os << "null"; + else + m_os << +v; + + m_os << ")" << std::endl; + } + + /** + * second element in each node section that stores the size of + * the child data sub-section. + */ + void node_index_size(size_t i, pack_value_type v) const + { + m_os << " " << std::setw(m_width) << i << ": index size (" << size_t(v) << ")" << std::endl; + } + + /** element that stores the key value for child node. */ + void node_child_key(size_t i, pack_value_type v) const + { + key_unit_type key = v; + m_os << " " << std::setw(m_width) << i << ": key (" << key << ")" << std::endl; + } + + /** element that stores the relative offset of the child node. */ + void node_child_offset(size_t i, pack_value_type v) const + { + size_t offset = v; + m_os << " " << std::setw(m_width) << i << ": offset (rel=" << offset + << "; abs=" << (m_this_node_offset - offset) << ")" << std::endl; + } + + } handler(os, width); + + traverse_packed_buffer{}(packed, handler); + } +}; + +template +struct dump_packed_construction_state +{ + void operator()(std::ostream&, const PackedT&, const NodeT&) + {} +}; + +template +struct dump_packed_construction_state< + TrieT, PackedT, NodeT, + typename std::enable_if_t::value>> +{ + using trie_node = NodeT; + + void operator()(std::ostream& os, const PackedT& packed, const NodeT& root) + { + if constexpr (!TrieT::traits_type::dump_packed_construction_state) + return; + + os << "---\n" + << "# input entries" << std::endl; + + typename TrieT::key_type buffer; + traverse_node(os, buffer, root); + + dump_packed_buffer{}(os, packed); + } + +private: + void traverse_node(std::ostream& os, typename TrieT::key_type& buffer, const NodeT& node) + { + if (node.value) + { + // This node has value. + os << "- key: " << buffer << "\n" + << " value: " << *node.value << std::endl; + } + + for (const trie_node* p : node.children) + { + const trie_node& this_node = *p; + buffer.push_back(this_node.key); + traverse_node(os, buffer, this_node); + buffer.pop_back(); + } + } +}; + +template +void verify_packed_position(const PackedT& packed, const typename PackedT::value_type* pos) +{ + const auto* end_pos = packed.data() + packed.size(); + + if (packed.data() <= pos && pos < end_pos) + return; + + std::ostringstream os; + os << "stored position is outside the valid data region (pos=" << pos << "; packed-begin=" << packed.data() + << "; packed-end=" << end_pos; + throw integrity_error(os.str()); +} + +template +const PackValueT* find_child_pos(const PackValueT* first_child, SizeT n_child_nodes, KeyUnitT c) +{ + using size_type = SizeT; + using key_unit_type = KeyUnitT; + + for (size_type low = 0, high = n_child_nodes - 1; low <= high;) + { + size_type i = (low + high) / 2; // take the mid position + + // each slot contains the key for the child and offset to its index position + const auto* child_pos = first_child + i * 2; + const key_unit_type node_key = *child_pos; + + if (c == node_key) + { + // Match found! + return child_pos; + } + + if (low == high) + // No more child node key to test. Bail out. + break; + + if (high - low == 1) + { + // Only two more child keys left. + if (i == low) + low = high; + else + { + assert(i == high); + high = low; + } + } + else if (c < node_key) + // Move on to the lower sub-group. + high = i; + else + // Move on to the higher sub-group. + low = i; + } + + // no match found + return nullptr; +} + +template +const PackValueT* find_prefix_node( + const PackValueT* p, const KeyUnitT* prefix, const KeyUnitT* prefix_end, + std::function node_func) +{ + using size_type = SizeT; + + if (prefix == prefix_end) + { + // target node found! + size_t index_size = *(p + 1); + const auto* child_pos = p + 2; + const auto* child_end = child_pos + index_size; + node_func(p, child_pos, child_end); + return p; + } + + const auto* p0 = p; // store the head offset position of this node. + + // Find the child node with a matching key character. + + ++p; + size_type index_size = *p; + size_type n = index_size / 2; // number of child nodes + ++p; + + if (!n) + { + // This is a leaf node - no more child nodes to test + node_func(nullptr, nullptr, nullptr); + return nullptr; + } + + const auto* child_end = p + index_size; + + if (const auto* child_pos = find_child_pos(p, n, *prefix); child_pos) + { + // Match found! + size_type offset = *(child_pos + 1); + node_func(p0, child_pos, child_end); + const auto* p_child = p0 - offset; + ++prefix; + return find_prefix_node(p_child, prefix, prefix_end, std::move(node_func)); + } + + // no matching node found - search failed + node_func(nullptr, nullptr, nullptr); + return nullptr; +} inline const char* value_type_size_name(bool variable_size) { @@ -65,12 +352,10 @@ template struct write_variable_size_values_to_ostream { - value_addrs_type operator()(std::ostream& os, const std::deque& value_store) const + void operator()(std::ostream& os, const std::deque& value_store) const { bin_value bv; - value_addrs_type value_addrs; - size_t pos = 0; for (const ValueT& v : value_store) { @@ -89,20 +374,17 @@ os.write(bv.buffer, 4); os.seekp(sp_end); - value_addrs.insert({&v, pos++}); + ++pos; } - - return value_addrs; } }; template struct write_fixed_size_values_to_ostream { - value_addrs_type operator()(std::ostream& os, const std::deque& value_store) const + void operator()(std::ostream& os, const std::deque& value_store) const { bin_value bv; - value_addrs_type value_addrs; // Write the size of constant-size values. bv.ui32 = FuncT::value_size; @@ -124,10 +406,8 @@ throw size_error(msg.str()); } - value_addrs.insert({&v, pos++}); + ++pos; } - - return value_addrs; } }; @@ -213,7 +493,7 @@ { }; -}} // namespace detail::trie +}} // namespace trie::detail namespace trie { @@ -308,49 +588,112 @@ } // namespace trie -template -trie_map::trie_map::trie_node::trie_node() : value(value_type()), has_value(false) +template +trie_map::trie_map::trie_node::trie_node() : value{}, has_value(false) {} -template -trie_map::trie_map::trie_node::trie_node(const trie_node& other) +template +trie_map::trie_map::trie_node::trie_node(const trie_node& other) : children(other.children), value(other.value), has_value(other.has_value) {} -template -trie_map::trie_map::trie_node::trie_node(trie_node&& other) +template +trie_map::trie_map::trie_node::trie_node(trie_node&& other) : children(std::move(other.children)), value(std::move(other.value)), has_value(std::move(other.has_value)) {} -template -void trie_map::trie_map::trie_node::swap(trie_node& other) +template +void trie_map::trie_map::trie_node::swap(trie_node& other) { children.swap(other.children); std::swap(value, other.value); std::swap(has_value, other.has_value); } -template -trie_map::trie_map() +template +trie_map::const_node_type::const_node_type(const trie_node* ref_node) : m_ref_node(ref_node) +{} + +template +trie_map::const_node_type::const_node_type() +{} + +template +trie_map::const_node_type::const_node_type(const const_node_type& other) + : m_ref_node(other.m_ref_node) +{} + +template +auto trie_map::const_node_type::operator=(const const_node_type& other) -> const_node_type& +{ + m_ref_node = other.m_ref_node; + return *this; +} + +template +bool trie_map::const_node_type::valid() const +{ + return m_ref_node != nullptr; +} + +template +bool trie_map::const_node_type::has_child() const +{ + if (!m_ref_node) + return false; + + return !m_ref_node->children.empty(); +} + +template +bool trie_map::const_node_type::has_value() const +{ + if (!m_ref_node) + return false; + + return m_ref_node->has_value; +} + +template +auto trie_map::const_node_type::value() const -> const value_type& +{ + return m_ref_node->value; +} + +template +auto trie_map::const_node_type::child(key_unit_type c) const -> const_node_type +{ + if (!m_ref_node) + return const_node_type(); + + auto it = m_ref_node->children.find(c); + if (it == m_ref_node->children.end()) + return const_node_type(); + + return const_node_type(&it->second); +} + +template +trie_map::trie_map() {} -template -trie_map::trie_map(const trie_map& other) : m_root(other.m_root) +template +trie_map::trie_map(const trie_map& other) : m_root(other.m_root) {} -template -trie_map::trie_map(trie_map&& other) : m_root(std::move(other.m_root)) +template +trie_map::trie_map(trie_map&& other) : m_root(std::move(other.m_root)) {} -template -typename trie_map::const_iterator trie_map::begin() const +template +typename trie_map::const_iterator trie_map::begin() const { if (m_root.children.empty()) // empty container return end(); // Push the root node. - key_buffer_type buf; + key_type buf; const_node_stack_type node_stack; node_stack.emplace_back(&m_root, m_root.children.begin()); @@ -370,15 +713,15 @@ return const_iterator(std::move(node_stack), std::move(buf), trie::detail::iterator_type::normal); } -template -typename trie_map::iterator trie_map::begin() +template +typename trie_map::iterator trie_map::begin() { if (m_root.children.empty()) // empty container return end(); // Push the root node. - key_buffer_type buf; + key_type buf; node_stack_type node_stack; node_stack.emplace_back(&m_root, m_root.children.begin()); @@ -398,57 +741,72 @@ return iterator(std::move(node_stack), std::move(buf), trie::detail::iterator_type::normal); } -template -typename trie_map::const_iterator trie_map::end() const +template +typename trie_map::const_iterator trie_map::end() const { const_node_stack_type node_stack; node_stack.emplace_back(&m_root, m_root.children.end()); - return const_iterator(std::move(node_stack), key_buffer_type(), trie::detail::iterator_type::end); + return const_iterator(std::move(node_stack), key_type(), trie::detail::iterator_type::end); } -template -typename trie_map::iterator trie_map::end() +template +typename trie_map::iterator trie_map::end() { node_stack_type node_stack; node_stack.emplace_back(&m_root, m_root.children.end()); - return iterator(std::move(node_stack), key_buffer_type(), trie::detail::iterator_type::end); + return iterator(std::move(node_stack), key_type(), trie::detail::iterator_type::end); } -template -trie_map& trie_map::operator=(trie_map other) +template +trie_map& trie_map::operator=(trie_map other) { trie_map tmp(std::move(other)); tmp.swap(*this); return *this; } -template -void trie_map::swap(trie_map& other) +template +bool trie_map::operator==(const trie_map& other) const +{ + return descend_for_equality(m_root, other.m_root); +} + +template +bool trie_map::operator!=(const trie_map& other) const +{ + return !operator==(other); +} + +template +void trie_map::swap(trie_map& other) { m_root.swap(other.m_root); } -template -void trie_map::insert(const key_type& key, const value_type& value) +template +auto trie_map::root_node() const -> const_node_type { - using ktt = key_traits_type; + return const_node_type(&m_root); +} - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); +template +void trie_map::insert(const key_type& key, value_type value) +{ + const key_unit_type* p = key.data(); + size_t n = key.size(); const key_unit_type* p_end = p + n; - insert_into_tree(m_root, p, p_end, value); + insert_into_tree(m_root, p, p_end, std::move(value)); } -template -void trie_map::insert(const key_unit_type* key, size_type len, const value_type& value) +template +void trie_map::insert(const key_unit_type* key, size_type len, value_type value) { const key_unit_type* key_end = key + len; - insert_into_tree(m_root, key, key_end, value); + insert_into_tree(m_root, key, key_end, std::move(value)); } -template -bool trie_map::erase(const key_unit_type* key, size_type len) +template +bool trie_map::erase(const key_unit_type* key, size_type len) { const key_unit_type* key_end = key + len; @@ -478,13 +836,13 @@ return true; } -template -void trie_map::insert_into_tree( - trie_node& node, const key_unit_type* key, const key_unit_type* key_end, const value_type& value) +template +void trie_map::insert_into_tree( + trie_node& node, const key_unit_type* key, const key_unit_type* key_end, value_type value) { if (key == key_end) { - node.value = value; + node.value = std::move(value); node.has_value = true; return; } @@ -499,11 +857,11 @@ } ++key; - insert_into_tree(it->second, key, key_end, value); + insert_into_tree(it->second, key, key_end, std::move(value)); } -template -const typename trie_map::trie_node* trie_map::find_prefix_node( +template +const typename trie_map::trie_node* trie_map::find_prefix_node( const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const { if (prefix == prefix_end) @@ -518,9 +876,9 @@ return find_prefix_node(it->second, prefix, prefix_end); } -template +template template -void trie_map::find_prefix_node_with_stack( +void trie_map::find_prefix_node_with_stack( std::vector>& node_stack, mdds::detail::const_t& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const { @@ -541,25 +899,22 @@ find_prefix_node_with_stack(node_stack, it->second, prefix, prefix_end); } -template +template template -typename trie_map::key_buffer_type trie_map::build_key_buffer_from_node_stack( +typename trie_map::key_type trie_map::build_key_buffer_from_node_stack( const std::vector>& node_stack) const { // Build the key value from the stack. - key_buffer_type buf; + key_type buf; auto end = node_stack.end(); --end; // Skip the node with value which doesn't store a key element. - std::for_each(node_stack.begin(), end, [&](const stack_item& si) { - using ktt = key_traits_type; - ktt::push_back(buf, si.child_pos->first); - }); + std::for_each(node_stack.begin(), end, [&](const stack_item& si) { buf.push_back(si.child_pos->first); }); return buf; } -template -void trie_map::count_values(size_type& n, const trie_node& node) const +template +void trie_map::count_values(size_type& n, const trie_node& node) const { if (node.has_value) ++n; @@ -569,19 +924,41 @@ [&](const typename trie_node::children_type::value_type& v) { count_values(n, v.second); }); } -template -typename trie_map::const_iterator trie_map::find(const key_type& key) const +template +bool trie_map::descend_for_equality(const trie_node& left, const trie_node& right) const { - using ktt = key_traits_type; - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); + if (left.has_value != right.has_value) + return false; - return find(p, n); + if (left.has_value && left.value != right.value) + return false; + + if (left.children.size() != right.children.size()) + return false; + + auto it_lhs = left.children.cbegin(); + auto it_rhs = right.children.cbegin(); + for (; it_lhs != left.children.cend(); ++it_lhs, ++it_rhs) + { + if (it_lhs->first != it_rhs->first) + return false; + + if (!descend_for_equality(it_lhs->second, it_rhs->second)) + return false; + } + + return true; +} + +template +typename trie_map::const_iterator trie_map::find( + const key_type& key) const +{ + return find(key.data(), key.size()); } -template -typename trie_map::const_iterator trie_map::find( +template +typename trie_map::const_iterator trie_map::find( const key_unit_type* input, size_type len) const { const key_unit_type* input_end = input + len; @@ -591,24 +968,19 @@ // Specified key doesn't exist. return end(); - key_buffer_type buf = build_key_buffer_from_node_stack(node_stack); + key_type buf = build_key_buffer_from_node_stack(node_stack); return const_iterator(std::move(node_stack), std::move(buf), trie::detail::iterator_type::normal); } -template -typename trie_map::iterator trie_map::find(const key_type& key) +template +typename trie_map::iterator trie_map::find(const key_type& key) { - using ktt = key_traits_type; - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); - - return find(p, n); + return find(key.data(), key.size()); } -template -typename trie_map::iterator trie_map::find( +template +typename trie_map::iterator trie_map::find( const key_unit_type* input, size_type len) { const key_unit_type* input_end = input + len; @@ -618,151 +990,58 @@ // Specified key doesn't exist. return end(); - key_buffer_type buf = build_key_buffer_from_node_stack(node_stack); + key_type buf = build_key_buffer_from_node_stack(node_stack); return iterator(std::move(node_stack), std::move(buf), trie::detail::iterator_type::normal); } -template -typename trie_map::search_results trie_map::prefix_search( +template +typename trie_map::search_results trie_map::prefix_search( const key_type& key) const { - using ktt = key_traits_type; - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); - - return prefix_search(p, n); + return prefix_search(key.data(), key.size()); } -template -typename trie_map::search_results trie_map::prefix_search( +template +typename trie_map::search_results trie_map::prefix_search( const key_unit_type* prefix, size_type len) const { - using ktt = key_traits_type; - const key_unit_type* prefix_end = prefix + len; - std::vector matches; - const trie_node* node = find_prefix_node(m_root, prefix, prefix_end); - return search_results(node, ktt::to_key_buffer(prefix, len)); + return search_results(node, key_type(prefix, len)); } -template -typename trie_map::size_type trie_map::size() const +template +typename trie_map::size_type trie_map::size() const { size_type n = 0; count_values(n, m_root); return n; } -template -bool trie_map::empty() const noexcept +template +bool trie_map::empty() const noexcept { return m_root.children.empty() && !m_root.has_value; } -template -void trie_map::clear() +template +void trie_map::clear() { m_root.children.clear(); m_root.has_value = false; } -template -typename trie_map::packed_type trie_map::pack() const +template +typename trie_map::packed_type trie_map::pack() { - return packed_type(*this); + return packed_type(trie::detail::move_to_pack{}, *this); } -#ifdef MDDS_TRIE_MAP_DEBUG - -template -void packed_trie_map::dump_node(key_buffer_type& buffer, const trie_node& node) const -{ - using namespace std; - - using ktt = key_traits_type; - - if (node.value) - { - // This node has value. - cout << buffer << ":" << *static_cast(node.value) << endl; - } - - std::for_each(node.children.begin(), node.children.end(), [&](const trie_node* p) { - const trie_node& this_node = *p; - ktt::push_back(buffer, this_node.key); - dump_node(buffer, this_node); - ktt::pop_back(buffer); - }); -} - -template -void packed_trie_map::dump_trie(const trie_node& root) const -{ - key_buffer_type buffer; - dump_node(buffer, root); -} - -template -void packed_trie_map::dump_packed_trie() const -{ - cout << "packed size: " << m_packed.size() << endl; - - struct _handler - { - size_t this_node_offset = 0; - - /** first element in the buffer. */ - void root_offset(size_t i, const uintptr_t& v) const - { - cout << std::setw(4) << i << ": root node offset: " << v << endl; - } - - /** first element in each node section. */ - void node_value(size_t i, const uintptr_t& v) - { - this_node_offset = i; - const value_type* value = reinterpret_cast(v); - cout << std::setw(4) << i << ": node value pointer: " << value << endl; - } - - /** - * second element in each node section that stores the size of - * the child data sub-section. - */ - void node_index_size(size_t i, const uintptr_t& v) const - { - cout << std::setw(4) << i << ": index size: " << size_t(v) << endl; - } - - /** element that stores the key value for child node. */ - void node_child_key(size_t i, const uintptr_t& v) const - { - key_unit_type key = v; - cout << std::setw(4) << i << ": key: " << key << endl; - } - - /** element that stores the relative offset of the child node. */ - void node_child_offset(size_t i, const uintptr_t& v) const - { - size_t offset = v; - cout << std::setw(4) << i << ": offset: " << offset << " (abs: " << (this_node_offset - offset) << ")" - << endl; - } - - } handler; - - traverse_buffer(handler); -} - -#endif - -template -void packed_trie_map::traverse_range( - trie_node& root, node_pool_type& node_pool, const typename packed_trie_map::entry* start, - const typename packed_trie_map::entry* end, size_type pos) +template +void packed_trie_map::traverse_range( + trie_node& root, node_pool_type& node_pool, const typename packed_trie_map::entry* start, + const typename packed_trie_map::entry* end, size_type pos) { const entry* p = start; const entry* range_start = start; @@ -810,8 +1089,8 @@ } } -template -typename packed_trie_map::size_type packed_trie_map::compact_node( +template +typename packed_trie_map::size_type packed_trie_map::compact_node( const trie_node& node) { std::vector> child_offsets; @@ -828,52 +1107,80 @@ size_type offset = m_packed.size(); if (node.value) { - m_value_store.push_back(*node.value); // copy the value object. - m_packed.push_back(uintptr_t(&m_value_store.back())); + auto pos = push_value_to_store(trie::detail::copy_to_pack{}, *node.value); + m_packed.push_back(pack_value_type(pos)); } else - m_packed.push_back(uintptr_t(0)); + m_packed.push_back(null_value); push_child_offsets(offset, child_offsets); return offset; } -template -typename packed_trie_map::size_type packed_trie_map::compact_node( - const typename trie_map::trie_node& node) +template +template +auto packed_trie_map::compact_node(ModeT, NodeT& node) -> size_type { - using node_type = typename trie_map::trie_node; - std::vector> child_offsets; child_offsets.reserve(node.children.size()); // Process child nodes first. - std::for_each( - node.children.begin(), node.children.end(), [&](const typename node_type::children_type::value_type& v) { - key_unit_type key = v.first; - const node_type& child_node = v.second; - size_type child_offset = compact_node(child_node); - child_offsets.emplace_back(child_offset, key); - }); + std::for_each(node.children.begin(), node.children.end(), [&](auto& v) { + key_unit_type key = v.first; + size_type child_offset = compact_node(ModeT{}, v.second); + child_offsets.emplace_back(child_offset, key); + }); // Process this node. size_type offset = m_packed.size(); if (node.has_value) { - m_value_store.push_back(node.value); // copy the value object. - m_packed.push_back(uintptr_t(&m_value_store.back())); + auto pos = push_value_to_store(ModeT{}, node.value); + m_packed.push_back(pack_value_type(pos)); } else - m_packed.push_back(uintptr_t(0)); + m_packed.push_back(null_value); push_child_offsets(offset, child_offsets); return offset; } -template -void packed_trie_map::push_child_offsets(size_type offset, const child_offsets_type& child_offsets) +template +void packed_trie_map::check_value_size_or_throw() const { - m_packed.push_back(uintptr_t(child_offsets.size() * 2)); + if (m_value_store.size() >= max_value_pos) + { + std::ostringstream os; + os << "maximum allowed number of values (" << (max_value_pos + 1) << ") exceeded"; + throw size_error(os.str()); + } +} + +template +auto packed_trie_map::push_value_to_store(trie::detail::copy_to_pack, const value_type& value) + -> size_type +{ + check_value_size_or_throw(); + auto pos = m_value_store.size(); + m_value_store.push_back(value); // copy the value object + return pos; +} + +template +auto packed_trie_map::push_value_to_store(trie::detail::move_to_pack, value_type& value) + -> size_type +{ + check_value_size_or_throw(); + auto pos = m_value_store.size(); + m_value_store.emplace_back(std::move(value)); // move the value object + return pos; +} + +template +void packed_trie_map::push_child_offsets( + size_type offset, const child_offsets_type& child_offsets) +{ + m_packed.push_back(pack_value_type(child_offsets.size() * 2)); std::for_each(child_offsets.begin(), child_offsets.end(), [&](const std::tuple& v) { key_unit_type key = std::get<1>(v); @@ -883,37 +1190,140 @@ }); } -template -void packed_trie_map::compact(const trie_node& root) +template +void packed_trie_map::init_pack() { - packed_type init(size_t(1), uintptr_t(0)); + packed_type init(size_t(1), pack_value_type(0)); m_packed.swap(init); assert(m_packed.size() == 1); +} +template +void packed_trie_map::compact(const trie_node& root) +{ + init_pack(); size_t root_offset = compact_node(root); m_packed[0] = root_offset; } -template -void packed_trie_map::compact(const typename trie_map::trie_node& root) +template +template +void packed_trie_map::compact(ModeT, NodeT& root) { - packed_type init(size_t(1), uintptr_t(0)); - m_packed.swap(init); - assert(m_packed.size() == 1); - - size_t root_offset = compact_node(root); + init_pack(); + size_t root_offset = compact_node(ModeT{}, root); m_packed[0] = root_offset; } -template -packed_trie_map::packed_trie_map() : m_packed(3, 0u) +template +packed_trie_map::const_node_type::const_node_type( + const packed_type* packed, const value_store_type* value_store, const pack_value_type* pos) + : m_packed(packed), m_value_store(value_store), m_pos(pos) +{} + +template +auto packed_trie_map::const_node_type::operator=(const const_node_type& other) + -> const_node_type& +{ + m_packed = other.m_packed; + m_value_store = other.m_value_store; + m_pos = other.m_pos; + return *this; +} + +template +bool packed_trie_map::const_node_type::valid() const +{ + return m_pos != nullptr; +} + +template +bool packed_trie_map::const_node_type::has_child() const +{ + if (!m_pos) + return false; + +#ifdef MDDS_TRIE_MAP_DEBUG + trie::detail::verify_packed_position(*m_packed, m_pos); +#endif + + size_type index_size = *(m_pos + 1); + return index_size > 0u; +} + +template +bool packed_trie_map::const_node_type::has_value() const { + if (!m_pos) + return false; + +#ifdef MDDS_TRIE_MAP_DEBUG + trie::detail::verify_packed_position(*m_packed, m_pos); +#endif + + return *m_pos != null_value; +} + +template +auto packed_trie_map::const_node_type::value() const -> const value_type& +{ +#ifdef MDDS_TRIE_MAP_DEBUG + trie::detail::verify_packed_position(*m_packed, m_pos); +#endif + + assert(m_value_store); + assert(*m_pos < m_value_store->size()); + return (*m_value_store)[*m_pos]; +} + +template +auto packed_trie_map::const_node_type::child(key_unit_type c) const -> const_node_type +{ + if (!m_pos) + return const_node_type(); + +#ifdef MDDS_TRIE_MAP_DEBUG + trie::detail::verify_packed_position(*m_packed, m_pos); +#endif + + size_type index_size = *(m_pos + 1); + if (!index_size) + // no more child nodes + return const_node_type(); + + size_type n = index_size / 2; + const pack_value_type* p = m_pos + 2; + + if (const auto* child_pos = trie::detail::find_child_pos(p, n, c); child_pos) + { + // Match found! + size_type offset = *(child_pos + 1); + const auto* p_child = m_pos - offset; + return const_node_type(m_packed, m_value_store, p_child); + } + + return const_node_type(); +} + +template +packed_trie_map::packed_trie_map( + trie::detail::move_to_pack, trie_map& from) +{ + compact(trie::detail::move_to_pack{}, from.m_root); +} + +template +packed_trie_map::packed_trie_map() : m_packed(3, 0u) +{ + static_assert(!std::is_signed_v); + static_assert(std::is_integral_v); + // root offset (0), root value (1), and root child count (2). m_packed[0] = 1; } -template -packed_trie_map::packed_trie_map(const entry* entries, size_type entry_size) +template +packed_trie_map::packed_trie_map(const entry* entries, size_type entry_size) { const entry* p = entries; const entry* p_end = p + entry_size; @@ -938,45 +1348,46 @@ trie_node root(0); node_pool_type node_pool; traverse_range(root, node_pool, p, p_end, 0); -#if defined(MDDS_TRIE_MAP_DEBUG) && defined(MDDS_TRIE_MAP_DEBUG_DUMP_TRIE) - dump_trie(root); -#endif // Compact the trie into a packed array. compact(root); -#if defined(MDDS_TRIE_MAP_DEBUG) && defined(MDDS_TRIE_MAP_DEBUG_DUMP_PACKED) - dump_packed_trie(); -#endif + + trie::detail::dump_packed_construction_state{}(std::cout, m_packed, root); } -template -packed_trie_map::packed_trie_map(const trie_map& other) +template +packed_trie_map::packed_trie_map(const trie_map& other) { - compact(other.m_root); + compact(trie::detail::copy_to_pack{}, other.m_root); } -template -packed_trie_map::packed_trie_map(const packed_trie_map& other) : m_packed(other.m_packed) +template +packed_trie_map::packed_trie_map(const packed_trie_map& other) : m_packed(other.m_packed) { struct _handler { packed_trie_map& m_parent; + const packed_trie_map& m_other; - void node(const uintptr_t* node_pos, key_unit_type /*c*/, size_t /*depth*/, size_t /*index_size*/) + void node(const pack_value_type* node_pos, const key_unit_type*, size_type, size_type) { - uintptr_t value_ptr = *node_pos; + pack_value_type other_value_pos = *node_pos; - if (value_ptr) + if (other_value_pos != null_value) { - auto p = reinterpret_cast(value_ptr); - m_parent.m_value_store.push_back(*p); // copy the value object. - const uintptr_t* head = m_parent.m_packed.data(); + assert(other_value_pos < m_other.m_value_store.size()); + pack_value_type pos = m_parent.m_value_store.size(); + m_parent.m_value_store.push_back(m_other.m_value_store[other_value_pos]); // copy the value object. + const auto* head = m_parent.m_packed.data(); size_t offset = std::distance(head, node_pos); - m_parent.m_packed[offset] = uintptr_t(&m_parent.m_value_store.back()); + m_parent.m_packed[offset] = pos; } } - void move_up(const uintptr_t*, const uintptr_t*, const uintptr_t*) + void move_up(const pack_value_type*, const pack_value_type*, const pack_value_type*) + {} + + void move_down() {} void next_child() @@ -985,16 +1396,16 @@ void end() {} - _handler(packed_trie_map& parent) : m_parent(parent) + _handler(packed_trie_map& parent, const packed_trie_map& other) : m_parent(parent), m_other(other) {} - } handler(*this); + } handler(*this, other); traverse_tree(handler); } -template -packed_trie_map::packed_trie_map(packed_trie_map&& other) +template +packed_trie_map::packed_trie_map(packed_trie_map&& other) : m_value_store(std::move(other.m_value_store)), m_packed(std::move(other.m_packed)) { // Even the empty structure needs to have the root offset and the empty root record. @@ -1002,16 +1413,16 @@ other.m_packed[0] = 1; } -template -packed_trie_map& packed_trie_map::operator=(packed_trie_map other) +template +packed_trie_map& packed_trie_map::operator=(packed_trie_map other) { packed_trie_map tmp(std::move(other)); tmp.swap(*this); return *this; } -template -bool packed_trie_map::operator==(const packed_trie_map& other) const +template +bool packed_trie_map::operator==(const packed_trie_map& other) const { if (m_value_store.size() != other.m_value_store.size()) return false; @@ -1029,200 +1440,201 @@ return true; } -template -bool packed_trie_map::operator!=(const packed_trie_map& other) const +template +bool packed_trie_map::operator!=(const packed_trie_map& other) const { return !operator==(other); } -template -typename packed_trie_map::const_iterator packed_trie_map::begin() const +template +typename packed_trie_map::const_iterator packed_trie_map::begin() const { return cbegin(); } -template -typename packed_trie_map::const_iterator packed_trie_map::end() const +template +typename packed_trie_map::const_iterator packed_trie_map::end() const { return cend(); } -template -typename packed_trie_map::const_iterator packed_trie_map::cbegin() const +template +typename packed_trie_map::const_iterator packed_trie_map::cbegin() const { - using ktt = key_traits_type; - node_stack_type node_stack = get_root_stack(); const stack_item* si = &node_stack.back(); if (si->child_pos == si->child_end) // empty container. - return const_iterator(std::move(node_stack), key_buffer_type()); + return const_iterator(&m_value_store, std::move(node_stack), key_type()); - const uintptr_t* node_pos = si->node_pos; - const uintptr_t* child_pos = si->child_pos; - const uintptr_t* child_end = si->child_end; - const uintptr_t* p = child_pos; + const auto* node_pos = si->node_pos; + const auto* child_pos = si->child_pos; + const auto* child_end = si->child_end; + const auto* p = child_pos; // Follow the root node's left-most child. - key_buffer_type buf; + key_type buf; key_unit_type c = *p; - ktt::push_back(buf, c); + buf.push_back(c); ++p; - size_t offset = *p; + size_type offset = *p; node_pos -= offset; // jump to the child node. p = node_pos; ++p; - size_t index_size = *p; + size_type index_size = *p; ++p; child_pos = p; child_end = child_pos + index_size; // Push this child node onto the stack. - node_stack.emplace_back(node_pos, child_pos, child_end); + node_stack.emplace_back(&m_value_store, node_pos, child_pos, child_end); - const value_type* pv = reinterpret_cast(*node_pos); - while (!pv) + pack_value_type pos = *node_pos; + while (pos == null_value) { // Keep following the left child node until we reach a node with value. - const_iterator::push_child_node_to_stack(node_stack, buf, node_stack.back().child_pos); - pv = reinterpret_cast(*node_stack.back().node_pos); + const_iterator::push_child_node_to_stack(&m_value_store, node_stack, buf, node_stack.back().child_pos); + pos = *node_stack.back().node_pos; } - return const_iterator(std::move(node_stack), std::move(buf), *pv); + return const_iterator(&m_value_store, std::move(node_stack), std::move(buf), pos); } -template -typename packed_trie_map::const_iterator packed_trie_map::cend() const +template +typename packed_trie_map::const_iterator packed_trie_map::cend() const { node_stack_type node_stack = get_root_stack(); node_stack.back().child_pos = node_stack.back().child_end; - return const_iterator(std::move(node_stack), key_buffer_type()); + return const_iterator(&m_value_store, std::move(node_stack), key_type()); } -template -typename packed_trie_map::node_stack_type packed_trie_map::get_root_stack() const +template +typename packed_trie_map::node_stack_type packed_trie_map< + KeyT, ValueT, TraitsT>::get_root_stack() const { assert(!m_packed.empty()); - size_t root_offset = m_packed[0]; + size_type root_offset = m_packed[0]; assert(root_offset < m_packed.size()); - const uintptr_t* p = m_packed.data() + root_offset; - const uintptr_t* node_pos = p; + const auto* p = m_packed.data() + root_offset; + const auto* node_pos = p; ++p; size_t index_size = *p; ++p; - const uintptr_t* child_pos = p; - const uintptr_t* child_end = child_pos + index_size; + const auto* child_pos = p; + const auto* child_end = child_pos + index_size; node_stack_type node_stack; - node_stack.emplace_back(node_pos, child_pos, child_end); + node_stack.emplace_back(&m_value_store, node_pos, child_pos, child_end); return node_stack; } -template -typename packed_trie_map::const_iterator packed_trie_map::find( +template +typename packed_trie_map::const_iterator packed_trie_map::find( const key_type& key) const { - using ktt = key_traits_type; - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); - - return find(p, n); + return find(key.data(), key.size()); } -template -typename packed_trie_map::const_iterator packed_trie_map::find( +template +typename packed_trie_map::const_iterator packed_trie_map::find( const key_unit_type* input, size_type len) const { if (m_value_store.empty()) return end(); const key_unit_type* key_end = input + len; - size_t root_offset = m_packed[0]; + size_type root_offset = m_packed[0]; assert(root_offset < m_packed.size()); - const uintptr_t* root = m_packed.data() + root_offset; + const auto* root = m_packed.data() + root_offset; node_stack_type node_stack; - find_prefix_node_with_stack(node_stack, root, input, key_end); + const auto* vs = &m_value_store; + + trie::detail::find_prefix_node( + root, input, key_end, + [&node_stack, + vs](const pack_value_type* node_pos, const pack_value_type* child_pos, const pack_value_type* child_end) { + node_stack.emplace_back(vs, node_pos, child_pos, child_end); + }); + if (node_stack.empty() || !node_stack.back().node_pos) return end(); const stack_item& si = node_stack.back(); - const value_type* pv = reinterpret_cast(*si.node_pos); - if (!pv) + pack_value_type v = *si.node_pos; + if (v == null_value) return end(); // Build the key value from the stack. - key_buffer_type buf; + key_type buf; auto end = node_stack.end(); --end; // Skip the node with value which doesn't store a key element. - std::for_each(node_stack.begin(), end, [&](const stack_item& this_si) { - using ktt = key_traits_type; - ktt::push_back(buf, *this_si.child_pos); - }); + std::for_each(node_stack.begin(), end, [&](const stack_item& this_si) { buf.push_back(*this_si.child_pos); }); - return const_iterator(std::move(node_stack), std::move(buf), *pv); + return const_iterator(&m_value_store, std::move(node_stack), std::move(buf), v); } -template -typename packed_trie_map::search_results packed_trie_map::prefix_search( +template +typename packed_trie_map::search_results packed_trie_map::prefix_search( const key_type& key) const { - using ktt = key_traits_type; - key_buffer_type buf = ktt::to_key_buffer(key); - const key_unit_type* p = ktt::buffer_data(buf); - size_t n = ktt::buffer_size(buf); - - return prefix_search(p, n); + return prefix_search(key.data(), key.size()); } -template -typename packed_trie_map::search_results packed_trie_map::prefix_search( +template +typename packed_trie_map::search_results packed_trie_map::prefix_search( const key_unit_type* prefix, size_type len) const { - using ktt = key_traits_type; - if (m_value_store.empty()) - return search_results(nullptr, key_buffer_type()); + return search_results(&m_value_store, nullptr, key_type()); const key_unit_type* prefix_end = prefix + len; - size_t root_offset = m_packed[0]; + size_type root_offset = m_packed[0]; assert(root_offset < m_packed.size()); - const uintptr_t* root = m_packed.data() + root_offset; + const auto* root = m_packed.data() + root_offset; + + const auto* node = trie::detail::find_prefix_node( + root, prefix, prefix_end, [](const pack_value_type*, const pack_value_type*, const pack_value_type*) {}); - const uintptr_t* node = find_prefix_node(root, prefix, prefix_end); - key_buffer_type buf = ktt::to_key_buffer(prefix, len); - return search_results(node, std::move(buf)); + return search_results(&m_value_store, node, key_type(prefix, len)); } -template -typename packed_trie_map::size_type packed_trie_map::size() const noexcept +template +typename packed_trie_map::size_type packed_trie_map::size() const noexcept { return m_value_store.size(); } -template -bool packed_trie_map::empty() const noexcept +template +bool packed_trie_map::empty() const noexcept { return m_value_store.empty(); } -template -void packed_trie_map::swap(packed_trie_map& other) +template +void packed_trie_map::swap(packed_trie_map& other) { m_value_store.swap(other.m_value_store); m_packed.swap(other.m_packed); } -template +template +auto packed_trie_map::root_node() const -> const_node_type +{ + assert(m_packed.size() >= 3u); + std::size_t root_offset = m_packed[0]; + return const_node_type(&m_packed, &m_value_store, m_packed.data() + root_offset); +} + +template template -void packed_trie_map::save_state(std::ostream& os) const +void packed_trie_map::save_state(std::ostream& os) const { - detail::trie::bin_value bv; + trie::detail::bin_value bv; bv.ui16 = 0x0000; // write 2-byte flags bv.ui16 |= (0x0001 & FuncT::variable_size); @@ -1232,21 +1644,18 @@ bv.ui32 = m_value_store.size(); os.write(bv.buffer, 4); - using value_addrs_type = std::map; - value_addrs_type value_addrs; - // Dump the stored values first. using value_size_type = std::bool_constant; - detail::trie::write_values_to_ostream func; - value_addrs = func(os, m_value_store); + trie::detail::write_values_to_ostream func; + func(os, m_value_store); // Write 0xFF to signify the end of the value section. bv.ui8 = 0xFF; os.write(bv.buffer, 1); - // Write the size of uintptr_t. It must be either 4 or 8. - bv.ui8 = sizeof(uintptr_t); + // Write the size of pack_value_type. + bv.ui8 = sizeof(pack_value_type); os.write(bv.buffer, 1); // Write the size of the packed blob. @@ -1255,86 +1664,65 @@ struct _handler { - size_t const m_elem_size = sizeof(uintptr_t); + const std::size_t m_elem_size = sizeof(pack_value_type); std::ostream& m_os; - const value_addrs_type& m_value_addrs; - const packed_trie_map& m_parent; - inline void write(uintptr_t v) const + inline void write(pack_value_type v) const { const char* p = reinterpret_cast(&v); m_os.write(p, m_elem_size); } /** first element in the buffer. */ - void root_offset(size_t /*i*/, const uintptr_t& v) const + void root_offset(size_t /*i*/, pack_value_type v) const { write(v); } /** first element in each node section. */ - void node_value(size_t /*i*/, const uintptr_t& v) const + void node_value(size_t /*i*/, pack_value_type v) const { - const value_type* p = reinterpret_cast(v); - if (p) - { - // Replace the pointer of the value with its index into the value store. - auto it = m_value_addrs.find(p); - assert(it != m_value_addrs.cend()); - uintptr_t index = it->second; - - write(index); - } - else - { - // Use the numeric value with all bits set, to encode 0. - // Because the index of the value is 0-based, we can't just - // leave it as zero. - uintptr_t max_bits = 0; - max_bits = ~max_bits; - write(max_bits); - } + write(v); } /** * second element in each node section that stores the size of * the child data sub-section. */ - void node_index_size(size_t /*i*/, const uintptr_t& v) const + void node_index_size(size_t /*i*/, pack_value_type v) const { write(v); } /** element that stores the key value for child node. */ - void node_child_key(size_t /*i*/, const uintptr_t& v) const + void node_child_key(size_t /*i*/, pack_value_type v) const { write(v); } /** element that stores the relative offset of the child node. */ - void node_child_offset(size_t /*i*/, const uintptr_t& v) const + void node_child_offset(size_t /*i*/, pack_value_type v) const { write(v); } - _handler(std::ostream& os, const value_addrs_type& value_addrs, const packed_trie_map& parent) - : m_os(os), m_value_addrs(value_addrs), m_parent(parent) + _handler(std::ostream& os) : m_os(os) {} - } handler(os, value_addrs, *this); + } handler(os); - traverse_buffer(handler); + trie::detail::traverse_packed_buffer{}(m_packed, handler); // Write 0xFF to signify the end of the packed blob. bv.ui8 = 0xFF; os.write(bv.buffer, 1); } -template +template template -void packed_trie_map::load_state(std::istream& is) +void packed_trie_map::load_state(std::istream& is) { - detail::trie::bin_value bv; + trie::detail::bin_value bv; is.read(bv.buffer, 2); uint16_t flags = bv.ui16; @@ -1343,8 +1731,8 @@ if (variable_size != FuncT::variable_size) { std::ostringstream os; - os << "This stream is meant for a value type of " << detail::trie::value_type_size_name(variable_size) - << ", but the actual value type is of " << detail::trie::value_type_size_name(FuncT::variable_size) << "."; + os << "This stream is meant for a value type of " << trie::detail::value_type_size_name(variable_size) + << ", but the actual value type is of " << trie::detail::value_type_size_name(FuncT::variable_size) << "."; throw std::invalid_argument(os.str()); } @@ -1353,7 +1741,7 @@ uint32_t value_count = bv.ui32; using value_size_type = std::bool_constant; - detail::trie::read_values_from_istream func; + trie::detail::read_values_from_istream func; m_value_store = func(is, value_count); // There should be a check byte of 0xFF. @@ -1361,12 +1749,12 @@ if (bv.ui8 != 0xFF) throw std::invalid_argument("failed to find the check byte at the end of the value section."); - // Size of uintptr_t + // Size of pack_value_type is.read(bv.buffer, 1); - size_t ptr_size = bv.ui8; + size_type pvt_size = bv.ui8; - if (ptr_size != sizeof(uintptr_t)) - throw std::invalid_argument("size of uintptr_t is different."); + if (pvt_size != sizeof(pack_value_type)) + throw std::invalid_argument("size of pack_value_type is different."); // Size of the packed blob. is.read(bv.buffer, 8); @@ -1377,8 +1765,8 @@ for (size_t i = 0; i < n; ++i) { - is.read(bv.buffer, sizeof(uintptr_t)); - const uintptr_t* p = reinterpret_cast(bv.buffer); + is.read(bv.buffer, pvt_size); + const auto* p = reinterpret_cast(bv.buffer); packed.push_back(*p); } @@ -1391,280 +1779,176 @@ struct _handler { - uintptr_t m_max_value; packed_trie_map& m_parent; - void root_offset(size_t /*i*/, const uintptr_t& /*v*/) const + void root_offset(size_t /*i*/, pack_value_type /*v*/) const {} - void node_value(size_t i, const uintptr_t& v) const + void node_value(size_t i, pack_value_type v) const { - if (v == m_max_value) - m_parent.m_packed[i] = 0; - else - { - // Replace the value index with its memory address. - const value_type& val = m_parent.m_value_store[v]; - const uintptr_t addr = reinterpret_cast(&val); - m_parent.m_packed[i] = addr; - } + m_parent.m_packed[i] = v; } - void node_index_size(size_t /*i*/, const uintptr_t& /*v*/) const + void node_index_size(size_t /*i*/, pack_value_type /*v*/) const {} - void node_child_key(size_t /*i*/, const uintptr_t& /*v*/) const + void node_child_key(size_t /*i*/, pack_value_type /*v*/) const {} - void node_child_offset(size_t /*i*/, const uintptr_t& /*v*/) const + void node_child_offset(size_t /*i*/, pack_value_type /*v*/) const {} - _handler(packed_trie_map& parent) : m_max_value(0), m_parent(parent) - { - m_max_value = ~m_max_value; - } + _handler(packed_trie_map& parent) : m_parent(parent) + {} } handler(*this); - traverse_buffer(handler); + trie::detail::traverse_packed_buffer{}(m_packed, handler); } -template -void packed_trie_map::dump_structure() const +template +std::string packed_trie_map::dump_structure(trie::dump_structure_type type) const { -#ifdef MDDS_TRIE_MAP_DEBUG - dump_packed_trie(); - - cout << "--" << endl; - cout << "entry size: " << m_value_store.size() << endl; - cout << "memory size: " << m_packed.size() << endl; + std::ostringstream os; - const uintptr_t* head = m_packed.data(); - - struct _handler + switch (type) { - const uintptr_t* m_head; - - _handler(const uintptr_t* head) : m_head(head) - {} - - void node(const uintptr_t* node_pos, key_unit_type c, size_t depth, size_t index_size) - { - uintptr_t value_ptr = *node_pos; - size_t offset = std::distance(m_head, node_pos); - - cout << " --" << endl; - cout << " offset: " << offset << endl; - cout << " key: " << c << endl; - cout << " depth: " << depth << endl; - cout << " child count: " << (index_size / 2) << endl; - cout << " value address: " << value_ptr; - - if (value_ptr) - { - auto p = reinterpret_cast(value_ptr); - cout << "; value: " << *p; - } - - cout << endl; - } - - void move_up(const uintptr_t* node_pos, const uintptr_t* child_pos, const uintptr_t* child_end) + case trie::dump_structure_type::packed_buffer: { - size_t offset = std::distance(m_head, node_pos); - size_t child_size = std::distance(child_pos, child_end) / 2; - cout << " --" << endl; - cout << " move up: (offset: " << offset << "; child count: " << child_size << ")" << endl; + trie::detail::dump_packed_buffer{}(os, m_packed); + break; } - - void next_child() + case trie::dump_structure_type::trie_traversal: { - cout << " next child" << endl; + dump_trie_traversal(os); + break; } + } - void end() - {} - - } handler(head); - - traverse_tree(handler); -#endif + return os.str(); } -template -const uintptr_t* packed_trie_map::find_prefix_node( - const uintptr_t* p, const key_unit_type* prefix, const key_unit_type* prefix_end) const +template +void packed_trie_map::dump_trie_traversal(std::ostream& os) const { - if (prefix == prefix_end) - return p; + os << "---\n" + << "# trie traversal (depth first)\n" + << "value entries: " << m_value_store.size() << "\n" + << "packed buffer size: " << m_packed.size() << "\n" + << "traversal:\n"; - const uintptr_t* p0 = p; // store the head offset position of this node. + const auto* head = m_packed.data(); - // Find the child node with a matching key character. - - ++p; - size_t index_size = *p; - size_t n = index_size / 2; - ++p; - - if (!n) - // This is a leaf node. - return nullptr; - - for (size_type low = 0, high = n - 1; low <= high;) + struct _handler { - size_type i = (low + high) / 2; + const value_store_type& m_value_store; + std::ostream& m_os; + const pack_value_type* m_head = nullptr; - const uintptr_t* p_this = p + i * 2; - key_unit_type node_key = *p_this; - size_t offset = *(p_this + 1); + _handler(const value_store_type& value_store, std::ostream& os, const pack_value_type* head) + : m_value_store(value_store), m_os(os), m_head(head) + {} - if (*prefix == node_key) + void node(const pack_value_type* node_pos, const key_unit_type* c, size_type depth, size_type index_size) { - // Match found! - const uintptr_t* p_child = p0 - offset; - ++prefix; - return find_prefix_node(p_child, prefix, prefix_end); - } - - if (low == high) - // No more child node key to test. Bail out. - break; + auto value_pos = *node_pos; + size_type offset = std::distance(m_head, node_pos); - if (high - low == 1) - { - // Only two more child keys left. - if (i == low) - low = high; + m_os << " - node:\n" + << " offset: " << offset << " (abs)\n" + << " key: "; + if (c) + m_os << *c; else - { - assert(i == high); - high = low; - } - } - else if (*prefix < node_key) - // Move on to the lower sub-group. - high = i; - else - // Move on to the higher sub-group. - low = i; - } + m_os << ""; - return nullptr; -} + m_os << "\n" + << " depth: " << depth << "\n" + << " child count: " << (index_size / 2) << "\n" + << " value position: "; -template -void packed_trie_map::find_prefix_node_with_stack( - node_stack_type& node_stack, const uintptr_t* p, const key_unit_type* prefix, const key_unit_type* prefix_end) const -{ - if (prefix == prefix_end) - { - size_t index_size = *(p + 1); - const uintptr_t* child_pos = p + 2; - const uintptr_t* child_end = child_pos + index_size; - node_stack.emplace_back(p, child_pos, child_end); - return; - } - - const uintptr_t* p0 = p; // store the head offset position of this node. - - // Find the child node with a matching key character. - - ++p; - size_t index_size = *p; - size_t n = index_size / 2; - ++p; - - if (!n) - { - // This is a leaf node. - node_stack.emplace_back(nullptr, nullptr, nullptr); - return; - } - - const uintptr_t* child_end = p + index_size; + if (value_pos == null_value) + m_os << "(null)"; + else + m_os << value_pos << " (value=" << m_value_store[value_pos] << ")"; - for (size_type low = 0, high = n - 1; low <= high;) - { - size_type i = (low + high) / 2; + m_os << std::endl; + } - const uintptr_t* child_pos = p + i * 2; - key_unit_type node_key = *child_pos; - size_t offset = *(child_pos + 1); + void move_up( + const pack_value_type* node_pos, const pack_value_type* child_pos, const pack_value_type* child_end) + { + size_type offset = std::distance(m_head, node_pos); + size_type child_size = std::distance(child_pos, child_end) / 2; + m_os << " - move up:\n" + << " offset: " << offset << " (abs)\n" + << " remaining child count: " << child_size << std::endl; + } - if (*prefix == node_key) + void move_down() { - // Match found! - node_stack.emplace_back(p0, child_pos, child_end); - const uintptr_t* p_child = p0 - offset; - ++prefix; - find_prefix_node_with_stack(node_stack, p_child, prefix, prefix_end); - return; + m_os << " - move down" << std::endl; } - if (low == high) - // No more child node key to test. Bail out. - break; + void next_child() + { + m_os << " - next child" << std::endl; + } - if (high - low == 1) + void end() { - // Only two more child keys left. - if (i == low) - low = high; - else - { - assert(i == high); - high = low; - } + m_os << " - end of traversal" << std::endl; } - else if (*prefix < node_key) - // Move on to the lower sub-group. - high = i; - else - // Move on to the higher sub-group. - low = i; - } - node_stack.emplace_back(nullptr, nullptr, nullptr); + } handler(m_value_store, os, head); + + traverse_tree(handler); } -template +template template -void packed_trie_map::traverse_tree(_Handler hdl) const +void packed_trie_map::traverse_tree(_Handler hdl) const { node_stack_type node_stack = get_root_stack(); stack_item* si = &node_stack.back(); + + size_type index_size = std::distance(si->child_pos, si->child_end); + size_type depth = 0; + hdl.node(si->node_pos, nullptr, depth, index_size); + if (si->child_pos == si->child_end) // empty container return; - const uintptr_t* node_pos = si->node_pos; - const uintptr_t* child_pos = si->child_pos; - const uintptr_t* child_end = si->child_end; - const uintptr_t* p = child_pos; + const auto* node_pos = si->node_pos; + const auto* child_pos = si->child_pos; + const auto* child_end = si->child_end; + + const auto* p = child_pos; for (bool in_tree = true; in_tree;) { // Descend until the leaf node is reached by following the left-most child nodes. while (true) { - auto key = *p; - size_t depth = node_stack.size(); + key_unit_type key = *p; + depth = node_stack.size(); ++p; - size_t offset = *p; + size_type offset = *p; // jump down to the child node. + hdl.move_down(); node_pos -= offset; p = node_pos; ++p; - size_t index_size = *p; // size of the buffer that stores child nodes' keys and offsets. + index_size = *p; // size of the buffer that stores child nodes' keys and offsets. - hdl.node(node_pos, key, depth, index_size); + hdl.node(node_pos, &key, depth, index_size); ++p; child_pos = p; child_end = child_pos + index_size; // Push this child node onto the stack. - node_stack.emplace_back(node_pos, child_pos, child_end); + node_stack.emplace_back(&m_value_store, node_pos, child_pos, child_end); if (!index_size) // no child nodes i.e. leaf node. Bail out of the loop. @@ -1678,8 +1962,10 @@ // move up. node_stack.pop_back(); si = &node_stack.back(); - hdl.move_up(si->node_pos, si->child_pos, si->child_end); std::advance(si->child_pos, 2); // move to the next child node slot. + + hdl.move_up(si->node_pos, si->child_pos, si->child_end); + if (si->child_pos != si->child_end) { // This is an unvisited child node. Bail out of the loop. @@ -1701,35 +1987,6 @@ hdl.end(); } -template -template -void packed_trie_map::traverse_buffer(_Handler hdl) const -{ - size_t n = m_packed.size(); - size_t i = 0; - hdl.root_offset(i, m_packed[i]); - ++i; - - while (i < n) - { - hdl.node_value(i, m_packed[i]); - ++i; - - hdl.node_index_size(i, m_packed[i]); - size_t index_size = m_packed[i]; - ++i; - index_size /= 2; - - for (size_t j = 0; j < index_size; ++j) - { - hdl.node_child_key(i, m_packed[i]); - ++i; - hdl.node_child_offset(i, m_packed[i]); - ++i; - } - } -} - } // namespace mdds /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/include/mdds/trie_map_itr.hpp mdds-3.1.0/include/mdds/trie_map_itr.hpp --- mdds-2.1.1/include/mdds/trie_map_itr.hpp 2023-04-21 02:32:52.000000000 +0000 +++ mdds-3.1.0/include/mdds/trie_map_itr.hpp 2024-03-23 01:06:48.000000000 +0000 @@ -100,9 +100,7 @@ using trie_node_child_pos_type = typename mdds::detail::get_iterator_type< typename std::remove_const::type::children_type, _is_const>::type; - using key_traits_type = typename trie_type::key_traits_type; - using key_type = typename key_traits_type::key_type; - using key_buffer_type = typename key_traits_type::key_buffer_type; + using key_type = typename trie_type::key_type; using trie_value_type = typename mdds::detail::const_or_not::type; public: @@ -115,18 +113,16 @@ protected: node_stack_type m_node_stack; - key_buffer_type m_buffer; + key_type m_buffer; key_type m_current_key; trie_value_type* m_current_value_ptr; iterator_type m_type; static trie_node_type* push_child_node_to_stack( - node_stack_type& node_stack, key_buffer_type& buf, trie_node_child_pos_type& child_pos) + node_stack_type& node_stack, key_type& buf, trie_node_child_pos_type& child_pos) { - using ktt = key_traits_type; - trie_node_type* node = &child_pos->second; - ktt::push_back(buf, child_pos->first); + buf.push_back(child_pos->first); node_stack.emplace_back(node, node->children.begin()); return node; @@ -136,10 +132,8 @@ * From the current node, move to its previous child node and descend all * the way to the leaf node. */ - static trie_node_type* descend_to_previus_leaf_node(node_stack_type& node_stack, key_buffer_type& buf) + static trie_node_type* descend_to_previus_leaf_node(node_stack_type& node_stack, key_type& buf) { - using ktt = key_traits_type; - trie_node_type* cur_node = nullptr; do @@ -150,7 +144,7 @@ auto& si = node_stack.back(); --si.child_pos; - ktt::push_back(buf, si.child_pos->first); + buf.push_back(si.child_pos->first); cur_node = &si.child_pos->second; node_stack.emplace_back(cur_node, cur_node->children.end()); } while (!cur_node->children.empty()); @@ -165,10 +159,9 @@ iterator_base() : m_current_value_ptr(nullptr), m_type(iterator_type::normal) {} - iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf, iterator_type type) - : m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), - m_current_key(key_traits_type::to_key(m_buffer)), m_current_value_ptr(&m_node_stack.back().node->value), - m_type(type) + iterator_base(node_stack_type&& node_stack, key_type&& buf, iterator_type type) + : m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), m_current_key(m_buffer), + m_current_value_ptr(&m_node_stack.back().node->value), m_type(type) {} bool operator==(const iterator_base& other) const @@ -199,8 +192,6 @@ iterator_base& operator++() { - using ktt = key_traits_type; - trie_node_type* cur_node = m_node_stack.back().node; do @@ -228,7 +219,7 @@ } // Move up one parent and see if it has an unvisited child node. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); auto& si = m_node_stack.back(); ++si.child_pos; @@ -249,7 +240,7 @@ } } while (!cur_node->has_value); - m_current_key = ktt::to_key(m_buffer); + m_current_key = m_buffer; m_current_value_ptr = &cur_node->value; return *this; } @@ -263,7 +254,6 @@ iterator_base& operator--() { - using ktt = key_traits_type; trie_node_type* cur_node = m_node_stack.back().node; if (m_type == iterator_type::end && cur_node->has_value) @@ -290,7 +280,7 @@ { // Go up one node. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); auto& si = m_node_stack.back(); cur_node = si.node; @@ -314,7 +304,7 @@ do { // Go up. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); auto& si = m_node_stack.back(); cur_node = si.node; @@ -329,7 +319,7 @@ } assert(cur_node->has_value); - m_current_key = ktt::to_key(m_buffer); + m_current_key = m_buffer; m_current_value_ptr = &cur_node->value; return *this; } @@ -356,7 +346,7 @@ using base_type = iterator_base; using node_stack_type = typename base_type::node_stack_type; - using key_buffer_type = typename base_type::key_buffer_type; + using key_type = typename base_type::key_type; iterator(empty_iterator_type t) : base_type(t) {} @@ -365,7 +355,7 @@ iterator() : base_type() {} - iterator(node_stack_type&& node_stack, key_buffer_type&& buf, iterator_type type) + iterator(node_stack_type&& node_stack, key_type&& buf, iterator_type type) : base_type(std::move(node_stack), std::move(buf), type) {} }; @@ -380,7 +370,7 @@ using base_type = iterator_base; using node_stack_type = typename base_type::node_stack_type; - using key_buffer_type = typename base_type::key_buffer_type; + using key_type = typename base_type::key_type; using base_type::m_buffer; using base_type::m_current_key; @@ -395,7 +385,7 @@ const_iterator() : base_type() {} - const_iterator(node_stack_type&& node_stack, key_buffer_type&& buf, iterator_type type) + const_iterator(node_stack_type&& node_stack, key_type&& buf, iterator_type type) : base_type(std::move(node_stack), std::move(buf), type) {} @@ -443,16 +433,14 @@ using node_stack_type = typename trie_type::const_node_stack_type; using trie_node = typename trie_type::trie_node; - using key_traits_type = typename trie_type::key_traits_type; - using key_type = typename key_traits_type::key_type; - using key_buffer_type = typename key_traits_type::key_buffer_type; - using key_unit_type = typename key_traits_type::key_unit_type; + using key_type = typename trie_type::key_type; + using key_unit_type = typename key_type::value_type; const trie_node* m_node; - key_buffer_type m_buffer; + key_type m_buffer; node_stack_type m_node_stack; - search_results(const trie_node* node, key_buffer_type&& buf) : m_node(node), m_buffer(buf) + search_results(const trie_node* node, key_type&& buf) : m_node(node), m_buffer(buf) {} public: @@ -465,7 +453,7 @@ return const_iterator(empty_iterator); // Push the root node. - key_buffer_type buf(m_buffer); + key_type buf(m_buffer); node_stack_type node_stack; node_stack.emplace_back(m_node, m_node->children.begin()); @@ -489,73 +477,75 @@ node_stack_type node_stack; node_stack.emplace_back(m_node, m_node->children.end()); - return const_iterator(std::move(node_stack), key_buffer_type(m_buffer), iterator_type::end); + return const_iterator(std::move(node_stack), key_type(m_buffer), iterator_type::end); } }; template class packed_search_results; -template +template class packed_iterator_base { - using trie_type = _TrieType; + using trie_type = TrieT; friend trie_type; friend packed_search_results; using stack_item = typename trie_type::stack_item; using node_stack_type = typename trie_type::node_stack_type; - using key_traits_type = typename trie_type::key_traits_type; - using key_type = typename key_traits_type::key_type; - using key_buffer_type = typename key_traits_type::key_buffer_type; - using key_unit_type = typename key_traits_type::key_unit_type; + using key_type = typename trie_type::key_type; + using size_type = typename trie_type::size_type; + using trie_value_type = typename trie_type::value_type; + using value_store_type = typename trie_type::value_store_type; + using pack_value_type = typename trie_type::pack_value_type; + using key_unit_type = typename key_type::value_type; public: // iterator traits - using value_type = typename trie_type::key_value_type; + using value_type = mdds::detail::ref_pair, std::add_const_t>; using pointer = value_type*; using reference = value_type&; using difference_type = std::ptrdiff_t; using iterator_category = std::bidirectional_iterator_tag; private: + const value_store_type* m_value_store = nullptr; node_stack_type m_node_stack; - key_buffer_type m_buffer; - value_type m_current_value; + key_type m_buffer; + pack_value_type m_current_value = trie_type::null_value; iterator_type m_type; /** * Given a child offset position (child_pos), jump to the actual child * node position and push that onto the stack as stack_item. */ - static void push_child_node_to_stack(node_stack_type& node_stack, key_buffer_type& buf, const uintptr_t* child_pos) + static void push_child_node_to_stack( + const value_store_type* value_store, node_stack_type& node_stack, key_type& buf, + const pack_value_type* child_pos) { - using ktt = key_traits_type; - - const uintptr_t* node_pos = node_stack.back().node_pos; + assert(value_store); + const auto* node_pos = node_stack.back().node_pos; key_unit_type c = static_cast(*child_pos); - ktt::push_back(buf, c); + buf.push_back(c); ++child_pos; - size_t offset = static_cast(*child_pos); + auto offset = static_cast(*child_pos); node_pos -= offset; // Jump to the head of the child node. - const uintptr_t* p = node_pos; + const auto* p = node_pos; ++p; - size_t index_size = *p; + size_type index_size = *p; ++p; child_pos = p; - const uintptr_t* child_end = child_pos + index_size; + const auto* child_end = child_pos + index_size; // Push it onto the stack. - node_stack.emplace_back(node_pos, child_pos, child_end); + node_stack.emplace_back(value_store, node_pos, child_pos, child_end); } - static const void descend_to_previus_leaf_node(node_stack_type& node_stack, key_buffer_type& buf) + static const void descend_to_previous_leaf_node(node_stack_type& node_stack, key_type& buf) { - using ktt = key_traits_type; - - const uintptr_t* node_pos = nullptr; + const pack_value_type* node_pos = nullptr; size_t index_size = 0; do @@ -570,15 +560,15 @@ --si->child_pos; key_unit_type c = *si->child_pos; node_pos -= offset; // Jump to the head of the child node. - ktt::push_back(buf, c); + buf.push_back(c); - const uintptr_t* p = node_pos; + const auto* p = node_pos; ++p; index_size = *p; ++p; - const uintptr_t* child_pos = p; - const uintptr_t* child_end = child_pos + index_size; - node_stack.emplace_back(node_pos, child_end, child_end); + const auto* child_pos = p; + const auto* child_end = child_pos + index_size; + node_stack.emplace_back(node_stack.back().value_store, node_pos, child_end, child_end); } while (index_size); } @@ -589,13 +579,15 @@ packed_iterator_base() : m_type(iterator_type::normal) {} - packed_iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf, const typename trie_type::value_type& v) - : m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), - m_current_value(key_traits_type::to_key(m_buffer), v), m_type(iterator_type::normal) + packed_iterator_base( + const value_store_type* value_store, node_stack_type&& node_stack, key_type&& buf, pack_value_type pos) + : m_value_store(value_store), m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), + m_current_value(pos), m_type(iterator_type::normal) {} - packed_iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf) - : m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), m_type(iterator_type::end) + packed_iterator_base(const value_store_type* value_store, node_stack_type&& node_stack, key_type&& buf) + : m_value_store(value_store), m_node_stack(std::move(node_stack)), m_buffer(std::move(buf)), + m_type(iterator_type::end) {} bool operator==(const packed_iterator_base& other) const @@ -614,22 +606,24 @@ return !operator==(other); } - const value_type& operator*() + value_type operator*() { - return m_current_value; + assert(m_value_store); + assert(m_current_value != trie_type::null_value); + return value_type(m_buffer, (*m_value_store)[m_current_value]); } - const value_type* operator->() + value_type operator->() { - return &m_current_value; + assert(m_value_store); + assert(m_current_value != trie_type::null_value); + return value_type(m_buffer, (*m_value_store)[m_current_value]); } packed_iterator_base& operator++() { - using ktt = key_traits_type; - stack_item* si = &m_node_stack.back(); - const typename trie_type::value_type* pv = nullptr; + pack_value_type v = trie_type::null_value; size_t index_size = *(si->node_pos + 1); do @@ -657,7 +651,7 @@ } // Move up one parent and see if it has an unvisited child node. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); si = &m_node_stack.back(); std::advance(si->child_pos, 2); @@ -665,7 +659,7 @@ if (si->child_pos != si->child_end) { // Move down to this unvisited child node. - push_child_node_to_stack(m_node_stack, m_buffer, si->child_pos); + push_child_node_to_stack(m_value_store, m_node_stack, m_buffer, si->child_pos); break; } } @@ -673,16 +667,16 @@ else { // Current node has child nodes. Follow the first child node. - push_child_node_to_stack(m_node_stack, m_buffer, si->child_pos); + push_child_node_to_stack(m_value_store, m_node_stack, m_buffer, si->child_pos); } si = &m_node_stack.back(); - pv = reinterpret_cast(*si->node_pos); + v = *si->node_pos; index_size = *(si->node_pos + 1); - } while (!pv); + } while (v == trie_type::null_value); - assert(pv); - m_current_value = value_type(ktt::to_key(m_buffer), *pv); + assert(v != trie_type::null_value); + m_current_value = v; return *this; } @@ -696,14 +690,11 @@ packed_iterator_base& operator--() { - using ktt = key_traits_type; - stack_item* si = &m_node_stack.back(); - const typename trie_type::value_type* pv = - reinterpret_cast(*si->node_pos); + pack_value_type v = *si->node_pos; size_t index_size = *(si->node_pos + 1); // index size for child nodes. - if (m_type == iterator_type::end && pv) + if (m_type == iterator_type::end && v != trie_type::null_value) { assert(m_node_stack.size() == 1); m_type = iterator_type::normal; @@ -713,9 +704,9 @@ // This is the end position aka root node. Move down to the // right-most leaf node. assert(si->child_pos == si->child_end); - descend_to_previus_leaf_node(m_node_stack, m_buffer); + descend_to_previous_leaf_node(m_node_stack, m_buffer); si = &m_node_stack.back(); - pv = reinterpret_cast(*si->node_pos); + v = *si->node_pos; m_type = iterator_type::normal; } else if (!index_size) @@ -728,26 +719,26 @@ { // Go up one node. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); si = &m_node_stack.back(); - const uintptr_t* p = si->node_pos; - pv = reinterpret_cast(*p); + const auto* p = si->node_pos; + v = *p; ++p; index_size = *p; ++p; - const uintptr_t* first_child = p; + const auto* first_child = p; if (si->child_pos != first_child) { // Left and down. - descend_to_previus_leaf_node(m_node_stack, m_buffer); + descend_to_previous_leaf_node(m_node_stack, m_buffer); si = &m_node_stack.back(); p = si->node_pos; - pv = reinterpret_cast(*p); - assert(pv); + v = *p; + assert(v != trie_type::null_value); } - } while (!pv); + } while (v == trie_type::null_value); } else { @@ -760,24 +751,24 @@ do { // Go up. - ktt::pop_back(m_buffer); + m_buffer.pop_back(); m_node_stack.pop_back(); si = &m_node_stack.back(); - pv = reinterpret_cast(*si->node_pos); + v = *si->node_pos; if (m_node_stack.size() == 1) { // Root node reached. - descend_to_previus_leaf_node(m_node_stack, m_buffer); + descend_to_previous_leaf_node(m_node_stack, m_buffer); si = &m_node_stack.back(); - pv = reinterpret_cast(*si->node_pos); - assert(pv); + v = *si->node_pos; + assert(v != trie_type::null_value); } - } while (!pv); + } while (v == trie_type::null_value); } - assert(pv); - m_current_value = value_type(ktt::to_key(m_buffer), *pv); + assert(v != trie_type::null_value); + m_current_value = v; return *this; } @@ -796,30 +787,34 @@ using trie_type = _TrieType; friend trie_type; using node_stack_type = typename trie_type::node_stack_type; + using value_store_type = typename trie_type::value_store_type; + using pack_value_type = typename trie_type::pack_value_type; - using key_traits_type = typename trie_type::key_traits_type; - using key_type = typename key_traits_type::key_type; - using key_buffer_type = typename key_traits_type::key_buffer_type; - using key_unit_type = typename key_traits_type::key_unit_type; + using key_type = typename trie_type::key_type; + using key_unit_type = typename key_type::value_type; - const uintptr_t* m_node; - key_buffer_type m_buffer; + const value_store_type* m_value_store = nullptr; + const pack_value_type* m_node = nullptr; + key_type m_buffer; - packed_search_results(const uintptr_t* node, key_buffer_type&& buf) : m_node(node), m_buffer(std::move(buf)) - {} + packed_search_results(const value_store_type* value_store, const pack_value_type* node, key_type&& buf) + : m_value_store(value_store), m_node(node), m_buffer(std::move(buf)) + { + assert(m_value_store); + } node_stack_type get_root_node() const { - const uintptr_t* p = m_node; + const auto* p = m_node; ++p; size_t index_size = *p; ++p; - const uintptr_t* child_pos = p; - const uintptr_t* child_end = child_pos + index_size; + const auto* child_pos = p; + const auto* child_end = child_pos + index_size; // Push this child node onto the stack. node_stack_type node_stack; - node_stack.emplace_back(m_node, child_pos, child_end); + node_stack.emplace_back(m_value_store, m_node, child_pos, child_end); return node_stack; } @@ -857,7 +852,7 @@ return const_iterator(empty_iterator); // Push the root node. - key_buffer_type buf(m_buffer); + key_type buf(m_buffer); node_stack_type node_stack = get_root_node(); while (!node_stack.back().has_value()) @@ -865,10 +860,10 @@ // There should always be at least one value node along the // left-most branch. - const_iterator::push_child_node_to_stack(node_stack, buf, node_stack.back().child_pos); + const_iterator::push_child_node_to_stack(m_value_store, node_stack, buf, node_stack.back().child_pos); } - return const_iterator(std::move(node_stack), std::move(buf), *node_stack.back().get_value()); + return const_iterator(m_value_store, std::move(node_stack), std::move(buf), node_stack.back().get_value_pos()); } const_iterator end() const @@ -880,7 +875,7 @@ node_stack_type node_stack = get_root_node(); auto& si = node_stack.back(); si.child_pos = si.child_end; - return const_iterator(std::move(node_stack), key_buffer_type(m_buffer)); + return const_iterator(m_value_store, std::move(node_stack), key_type(m_buffer)); } }; diff -Nru mdds-2.1.1/m4/ax_cxx_compile_stdcxx.m4 mdds-3.1.0/m4/ax_cxx_compile_stdcxx.m4 --- mdds-2.1.1/m4/ax_cxx_compile_stdcxx.m4 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/m4/ax_cxx_compile_stdcxx.m4 2025-01-16 01:49:38.000000000 +0000 @@ -10,13 +10,13 @@ # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). +# CXXCPP to enable support. VERSION may be '11', '14', '17', '20', or +# '23' for the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. +# preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is @@ -35,13 +35,16 @@ # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp +# Copyright (c) 2015, 2022, 2023, 2024 Olly Betts # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 11 +#serial 23 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). @@ -50,6 +53,8 @@ m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [$1], [23], [ax_cxx_compile_alternatives="23"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -62,7 +67,17 @@ AC_LANG_PUSH([C++])dnl ac_success=no - m4_if([$2], [noext], [], [dnl + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" @@ -86,14 +101,23 @@ done fi]) - m4_if([$2], [ext], [], [dnl + m4_if([$2], [ext], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" @@ -137,23 +161,44 @@ dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11] ) - dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14] ) +dnl Test body for checking C++17 support + m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17] +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20] +) + +dnl Test body for checking C++23 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_23 ) + dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ @@ -165,7 +210,21 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201103L +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" @@ -456,7 +515,7 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201402L +#elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" @@ -580,7 +639,7 @@ #error "This is not a C++ compiler" -#elif __cplusplus < 201703L +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L #error "This is not a C++17 compiler" @@ -946,6 +1005,66 @@ } // namespace cxx17 -#endif // __cplusplus < 201703L +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +]]) + + +dnl Tests for new features in C++23 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +#error "This is not a C++23 compiler" + +#else + +#include + +namespace cxx23 +{ + +// As C++23 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx23 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L ]]) diff -Nru mdds-2.1.1/misc/sorted_string_data.dat mdds-3.1.0/misc/sorted_string_data.dat --- mdds-2.1.1/misc/sorted_string_data.dat 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/misc/sorted_string_data.dat 2022-04-22 00:12:40.000000000 +0000 @@ -0,0 +1,10000 @@ +01nWuuudoV +01qIl5SAd8 +02cvSsQ0dZ +02gPdv3iUG +03DGo2cwip +03tlFSYAbV +0449taw482 +04FryceLtS +04bD0LT70Q +04eg1UyQen +04kUaFXBdR +05UGBwgW3K +05WTj3MwH3 +060yYwUQ4k +06GFvtDdHn +06y5DPqvWB +07Mmp5ja5a +07aBLn0MQO +07bd7hS9RX +07mBRzyxoN +089IoYnlf8 +08yCnYflUu +09AG8qoRHB +0Ap7S5kL9y +0BQA3nxXS6 +0BYSLUH5h0 +0Br8QgefJd +0CCJxY50vU +0CiArnBTDQ +0Ckj1e4rK5 +0DK4sz3PB4 +0DRrv2NMoF +0DwCOOfI0C +0E2x1W3w0L +0EAFMKtulI +0F85EyYGfE +0G8v6lkQbS +0GNisi8mow +0GUtCRS41K +0HMLWxBTPe +0Hy5JwQ8Fi +0I3xiKwjMX +0JWlvOKWKs +0Jv2LaMZEH +0KCLo5fHH2 +0KWbbBe7FZ +0KkFqQIp4M +0KvvqIu5fm +0MntZc5lVI +0MoOB6FGq4 +0MwD5csYSN +0N88FApeIR +0OBBmhQYYz +0OgUgbuj5V +0PC6HgOwvX +0QCvw8TJyD +0QSmo4wX2V +0QXhAkxN0f +0QdWWfn2Wm +0QynlO4vTd +0R7RFLIIVP +0RPtufqzks +0RgRVNJu60 +0TwqMX6tPH +0UBW23PGhR +0VS7TmpDIY +0VkWy3Chea +0WJc4FY3rf +0WYItNlbNN +0WxsbYe7AD +0XbZjZpmej +0XpJdTkKZz +0YEsQv5n8e +0YUduWNuUQ +0YteZw7Ikx +0ZVZWufTMO +0ZZkYq6p4i +0Zk6dD9bQB +0aIb5btjda +0amPrU5eq5 +0apakrDjDJ +0aukoMDd1r +0bMhqcyXKr +0clN82aKFM +0cmGZhtcTn +0cuFWcJkTw +0d4v3BidZY +0d5qavrXOj +0dCCdnjLRy +0dlybugK9p +0dsUPO3CzS +0eOGkAlCyk +0efmGHXaJW +0eokxVfCiD +0fJQIqfi4c +0fLL5oBNg8 +0gKBJ4zmdp +0hAnSfe82H +0hFm81Qfgl +0hP7ZOdon0 +0hpUJBptbO +0hqk8tYs8T +0ijnRb8kAR +0jdKKvCIhB +0lH04743uf +0lSPYzrxxV +0lfyPj7p2I +0lvs4TKKJ6 +0mbWSe8fqZ +0mlpUAvQuU +0neNT4wDyS +0nqwYb223G +0oNu5jWdMj +0p41GuOjNI +0pDF0kH6M9 +0rXVozswMM +0rcmwFwxx9 +0s67jkaIgt +0sCNRzHu1f +0sQteMkjc0 +0tsaBf7Oh5 +0uGrKiu7Ey +0uLOT4StrA +0uYvHz1oyp +0ump86Yd2N +0uwBtSzwkq +0vJboPCWjy +0vLcKQQ0xi +0vbAEkN6GV +0vlVMWTDDN +0w6xTPEVN3 +0wHPCk4ueJ +0wIkXCewVc +0wJ9GOm1XF +0wUQDcPAae +0wjFBt42B1 +0xBLnELeyT +0xWJxdjfma +0xbcY9Oyza +0yZvNTMz4p +0zYWTZ8xxq +0zeqsYjpev +0zjglqBEtF +0zr0RWNo1S +0zvgEuFmCx +10Kyw5zFHM +10SpuVNkJi +10kuRJIEW5 +10pA5hGV7D +1144dOZ0hV +119Kh7UxW9 +11r6vrd0ct +120PJYao5D +125cZRlVo9 +12FDHLW9gI +12QhpxybFI +12vO2fKYRf +1406qbLSWR +14AjLKY1Xr +14K1emRAml +14XmNmbGPw +14kmLiEe2b +14u9q0rE2K +15iZKnLSbV +15t32zcfjt +17qnfPqxKF +186xdNIP7U +18AssSIPUW +18jG0MwkFD +18r5KRFKnX +19YYrc7Aej +19h9J2BIk3 +1A36sWwQ4n +1AHeSd7KYK +1ArL1kHeKt +1ArSRu2KiN +1ByPA8ba04 +1CLvQqRCMN +1COFer1w6k +1CkLH5BhIx +1DRFjpb0C8 +1DomFN8i3V +1DzlqABOar +1EBYlSUPRD +1EX9VmqcOs +1Ge1hj0Hf9 +1GmZ4BuF9I +1HLei5A9yi +1HNOttGgI7 +1IOwglik3R +1JKWWgG5DT +1JOtqapD4m +1JyJgQ2kiY +1KFhuAKX5S +1KkE0znzz9 +1LF4wWBgXg +1LG6diGlgm +1M0lByvmhF +1MWiduMeIS +1Mv5mCKNQx +1NFMO5mUU2 +1O1lwkhM3w +1O3ap1PfPw +1O7JXsPQa3 +1OVLr7rlwk +1OYlHFSLs2 +1Oe1Kqn80S +1Ow3WHQ2ag +1OzssII4qw +1P9OBLODET +1PRGyw203z +1PahXD8RBK +1PiM89xMGJ +1RKeRJJMVe +1RSYIe9oZw +1SQIbJtN0a +1SX2ubJBVv +1Sk4pJldSl +1Sm2x6Lo6t +1TE5nGzLiM +1TFJg9n2j8 +1U98Fje3Iy +1USG8oGbDM +1UiyMhUFyu +1VHvnpCpuA +1Vo3J2ywDf +1VqTPYBxJf +1W0bNgBnbM +1WNqMQtODz +1WRbsQihNd +1Wonign3Ub +1XwMtoRzll +1YfI5963IM +1YyyAXtEeS +1ZAK8j8uBg +1ZXz0uAkmE +1aLc7YX6Yz +1avLAzjYLc +1bc1u7zO1a +1cG1ESjUCi +1cOlUVoCZg +1ceOMSQiqD +1csAJYrCtI +1dBgzI2LCf +1dSqv21QlF +1deP3SVyXw +1dqzdVOMh3 +1eFKOP8Kzl +1f4Q3bjde0 +1fZTvRkT3w +1gJhr7EFID +1gXlDU0a25 +1gkapi3x9s +1h1SqWQUFf +1h2L3jOVy4 +1hX94Hqkwi +1ha7spgD4y +1hwHUrUOlW +1iP6aq7AYC +1ikGFsB1Ub +1inUckVJtt +1ioDmbjL7h +1iqOOUDqGw +1j3bs6PC7J +1jr6Z0uu5h +1kuBTVzfhq +1l6vgnuJyT +1l78MpfDfL +1lTUlYz0R3 +1lWHiMpxTV +1m21VzDTve +1mqyoOtdd1 +1n2sjiFgVr +1n7KuYpT0p +1nDmu1JYra +1oTLyef2lI +1qNZ7OTjLL +1qYGucvNGu +1qoxLNolIb +1qwGuVkXE7 +1rMYKxnpAa +1rPSkYLJIi +1rjuMtcH5Y +1rkIUlVDDC +1s1XgH4dj5 +1shHFKcDZR +1smQsQ10x0 +1t6U5kPtKP +1tVt8agJnH +1tXycGJbyr +1tp1tMMkie +1u26CPKSUm +1ukiVMAY7t +1uuio0r6VH +1vPsUBcEgY +1wIyJJ1wc3 +1wMTqT27RF +1wNx2o8puq +1wQMwSiDWR +1wv67Itf0Z +1x16VskpY4 +1xsK46xwlW +1y2nUJeWbP +1ygdI3msn3 +1yobipR0Xg +1z70PfWlpM +1zpJJon045 +20RMyDPzFe +20u3S8kuoG +20y78ucqZO +215M2HAYdP +21pJPMSIVd +22nK2D5Q6u +23AGc2SlOX +23CJ64cZJ7 +24YoM1cTIH +25I6eJ29z5 +25RMACQj1H +25V65a3vEh +25zP0ayDTD +26PtnqeCcY +26zac7RZNs +27IiKqJgQe +27WlEFLEFB +27Z18e3yjb +27fzDrYqnj +27kJqsuivJ +27uXsL04PA +2828Sl6MiO +283BAkfM8Q +28aeI5PMt8 +28i4C94NcQ +2ABJr4VjjJ +2B2CzbtFmp +2BCqgXNhqL +2BIvQAi2TB +2BL1oOcArC +2Bnov3RIFv +2BpUTevg3a +2BzOrOyQLp +2C9DGDMxYL +2CgQomAkb0 +2D7VqWfGNL +2DCfchDm9f +2DJbjpuyGb +2DxM4OhxfL +2DxzrJHNPc +2DyxqvlXTI +2E0mGp7cMl +2E9p73XzqH +2EYPK69Zeb +2EmEz3qqQz +2EvLAPJ4Y8 +2FrHt8wXgz +2FzScGpxJa +2GDrsZ0teI +2GLpc2pnEw +2H2vQqCm7p +2HTP6y1geg +2IEoxsaVJG +2J1IlMu2nM +2J2a0qYwmP +2J5XIXJKz8 +2JADKYw7HU +2JB7g457fs +2K7KixiQL8 +2KBvw79jn7 +2KFauLjuhs +2L87yQP0qL +2LY8nE22Ou +2LkJrSIgrA +2MLDOfhSzk +2Mki8dMemj +2Mn8ARE6Hj +2Ms09kUWiW +2N7ATa5U5r +2NmK1VzgfS +2NsWyPb1ZN +2OCafOqwGI +2OMYYORTU5 +2OPkuwetKW +2OYIQjZRrn +2P5CfsLTaO +2QNowh4kQR +2RCgfx2y3t +2RYTJJVSZN +2SXuh4jpRI +2Sk2AaT6sk +2TMhojKrN6 +2Tni3KJ1Ep +2U89tgkCBw +2V15Ov7T7v +2VRge2y5Fl +2W5DbzazpI +2WiF2VHNgQ +2X7TRhQ9KQ +2XXjU7aag5 +2XqEyUYbaf +2XzE7GeFnK +2YFHMBFCpD +2YxaZndkxH +2ZFeRW10Fn +2aFCXAKxMM +2aJsi9JtnQ +2aMcIjPXEh +2am1Iv7psL +2atnwpu9O1 +2b6RzYuzkw +2bUH5hXVHS +2bUJvzcO9l +2bWbwjwbpC +2cLiixfjcC +2cM1m15nEm +2d8gjkbJb5 +2e0NFxnvF9 +2e4InJOpMW +2evBS3KscZ +2eyqtG96pA +2foGrfkH6Z +2g4JWPlRWN +2g7V9oDdKV +2g9LZu6KRN +2gb4y1Ju6i +2gtPOSDPmD +2hb7abRPHa +2hnWb7Nvxt +2hoyadZmOR +2inOmgSKWx +2jEnxlcqUI +2jX807nzA4 +2kSdWOQasq +2lBMRWEUy4 +2lGnMdDuJS +2lkMKrv62R +2lwKaLIxIB +2mCCTeeQUs +2mTXBRpm0h +2mUnZVqXMw +2mUwtN1oUQ +2mvq8f5DtJ +2nCIQ07am8 +2nedYaF2fX +2oxYtqSZp7 +2pp1ifMJ1L +2q6XQkFFvl +2qG7tw0QMc +2qnzkSUFmw +2qpKvPESwO +2r77d28xpp +2rDcaIeuMQ +2s4XRyfHHP +2swbt3bBTm +2tCAvsf3i5 +2u6hV78GES +2uZA1TwG9g +2utZEqOv0W +2vIvkrRcSJ +2vwR7emzIa +2w81Q0PLd9 +2wBgXE8ghG +2wR1GWDlHH +2wlXB7mlQw +2wwrlH76AH +2x5qNTqtQh +2x8WIe2Sa2 +2xLpgYOcup +2xNW3hWU1O +2xdpTMNpzi +2yTS3VqcWy +2yYbx480qI +2yt6CgbJ4Q +2z9SwXZqyA +2z9hk6cbuM +2zC5XV7FDT +2zhGczQrj0 +306BbhAnJb +30B6e4TRH0 +30BPvQjisy +30gcnJ1wNy +30uzls3UpI +315q1IHigC +31CAjA0GLt +31QQRFOmsp +31kTmwCbmg +31kdmWgx5C +32U601vPxr +33TBOKA2o5 +33ZEVuoesC +33d6gbMPQF +34Gll5yoax +34OO2PrfGA +34RappSVSc +34vW7wQJEJ +354iOVksEF +35VPUNhpWl +365NDJIo7L +36IiWmtiLZ +36JsPAXYEs +36OfmflH1U +37b7uLktiF +37v1x9mJQu +381PakOs8t +387OkiF3VJ +38BJUiXMm7 +38lWXq2LIl +38zZ5PFPNT +3927vIlZWc +39fo1tCnTb +3AbUjDFjnJ +3BQfLBHKbm +3BpFWkmUF6 +3C9FVDGjIV +3Cf0kueVRh +3D7bHYcZnM +3D87cRWILO +3DBMVeyCJB +3DseaZCHii +3Dzvd7KXfp +3EkCO0nFyJ +3Eyqp6vQEj +3F3nttuYng +3FBysoRzmG +3FXXg1Vjbv +3FkXToNIHl +3G11WxL2n5 +3G6DEscne7 +3GJJuNzRYp +3GVdzW0g8N +3HlFXh7R2m +3I29i5TiMw +3IaKI2rh9o +3J5M1QUY6w +3JoJyHnZ7G +3JxhXQIFiR +3KKnBTUYle +3KVuRmVzUu +3N11c6P6m5 +3Neu6me2Bg +3PCnmPH0eU +3PXwDMQ4pl +3PZHf1drqS +3PlQ8Wv3e4 +3Q4AUzZCQq +3RGygMiyky +3RJCy7BTrT +3RUjrSuA7P +3SLdZnHHkT +3SNQA0rpTh +3SVhx1u2F1 +3SWtfIXt6k +3SeQgWTCQS +3Sh5SiaCnJ +3SoWjht8AL +3SuwNHJOq2 +3T0CKvkFGW +3TF6Mce938 +3UMEIhk1NT +3UcZQH7WaC +3VfKLh5zHY +3VsH0t9UOp +3VunmKYDGH +3Wv4WolFKA +3X03RTSae6 +3XmN3SNrxH +3YCIXQ1Y0A +3YFvP0hJBy +3ZqL8xKpNS +3a0eUrL0xo +3aCVbg5B2b +3aKFBx4GgI +3aqI7q4yG5 +3b7JxATpHW +3bEtVWzEOg +3bNTPeKmY2 +3cK4aOKOEN +3cRbcepMuQ +3d6C9iUuV4 +3dRVX3qAX8 +3dT5vrfwGc +3dgh5hrpBC +3duVVqCpxi +3dxGI9gYcO +3dzncEHbWd +3eDaK4HKQs +3eFsfaoWC4 +3emPEX7o6I +3ev8noAIko +3ewqmUXDe9 +3fBYbDuidU +3fMxnvZRLf +3ffb4FlJMn +3gMV2OSArH +3gMh96SAoS +3gWDjpaIXP +3h1DFRgNSS +3h1hzeB2Gg +3hfQNOozgg +3iRvlm1mQs +3ipfltRzE2 +3jSOXYNrZl +3jw0GetiBQ +3k3UR5ltxc +3kJFMxJbw6 +3mGqrIULMM +3mURpmsoMD +3oHRHjhjqy +3ood2fV8QS +3opUW4alWY +3p5TrMt3Lp +3pQcsCxUTG +3q4y7737pe +3qpyIZm2oP +3rc8SyI83W +3rfxdGuA3D +3rgU9FzMlx +3sVf0XHoeF +3slmiBoWqF +3tFEgAkdrX +3tXDkvHZaJ +3u32jKCY30 +3uPFexpsSF +3uwy8uv6Gi +3wB8g9xzke +3wulrJhQM6 +3xWKtPAdVW +3xjkstNlAg +3xzwHh2ThQ +3ybNEyvzI3 +3z9YetVmM1 +3zACZPhYk6 +3zXesaFd4F +3zafdBrvPI +3zcL0IktHj +40BCiQNuJH +40Mm7vJ2nu +40NTLgQzAD +40PokWcufK +40Ynn9NOCB +40ZU3nsyrn +40yJgkp2se +419tgSgmK6 +41hvMgayzX +41oHeSXON4 +421KPp3M1a +42AyK4xq01 +42D7aPdG4s +42GzhQN9fS +42cXVfekRp +42dWijiKJC +43DtKNpGRs +44OCdVAD09 +454kOVWXXN +456Dqyxz44 +45EfMDwVaJ +45G1JOyd9s +45Y1XXRXyF +45bjSuyxTT +46BjzrIHWV +46OD0yVKuL +46e10gzxAX +48u30by96t +49QeMAF9EZ +4ASEu78PgF +4AhWsSo2Ma +4AyolleHt9 +4AzNRMGatF +4B1aSt9Fxg +4BCD0qQHlT +4BXwgWF1dF +4BwR8y7sMQ +4C4LOclQAa +4CKsQCIPlJ +4D4eOxn0ls +4Dv4jXCDEo +4E3LqPyXr9 +4F7nNKEcmf +4FGx6MtbMO +4FU9zFWx68 +4FWe6TjrVp +4G7AY36I5D +4GdhxBxwDt +4HinCJwFg9 +4JrwddyITq +4Ka9Wk640l +4L3t8uGHYZ +4L86fMuQ6K +4LMwxy3mCc +4Nxb5ljlWy +4O456YQ9Vb +4OikoHCmYT +4PBAzT9SEr +4PWCEdHzTl +4PY5gQaeen +4PjkcMoA2u +4QONwxXELK +4ROPSKrad2 +4RWTsDBDKs +4RdwH3Q31G +4RfLPZCLRd +4Rvwnn5xvD +4RylsxyDmP +4SunKOOcjm +4TIi6AgDpI +4TZ1TdcdIF +4TerH7RVnJ +4UIBtAsHXn +4UwXpdCAyO +4UxvSAOCXy +4V753OWsAq +4WNzeM1mTm +4WbmdHssJ0 +4XCY73eJnS +4Xi0AgDayM +4XvZg4YPjF +4Y0O0Lv8qg +4YQGfV1VHF +4ZCoMy227e +4ZLSXIkYmk +4ZaLoyXyJu +4Zwb5H1s69 +4aDuGDjR2q +4ahvVUHfcC +4aj9U6D30e +4alLkMq2fL +4avNQhOutK +4bl2A7fmu1 +4cThzkizNg +4cUREM3beK +4cdzMabOtx +4dFRfo0aXd +4dKPrbmRKD +4dfYG0OuWy +4eQzpgLQvZ +4eV3pr2gzE +4eYHqvQtNq +4f3oQskBKL +4fNaSDE3o3 +4fTP7byWB9 +4fVlMdpR5v +4fZpMGfLn7 +4g7Uno9TXG +4gCsqCEwj6 +4hvgptr7PO +4iZ7Vo1I1e +4icinRX8fb +4iejIGsR4I +4j5PhIZKIc +4jHtRsnG1z +4jI4j8tjJo +4jdBTbn4Ce +4jinimlQyJ +4jqnlmXBKL +4kb2710l41 +4ldNJ6JGp9 +4lgNlJLqBp +4lsB3lwx6S +4mRwwLbNjW +4mloR3xKN1 +4mpnIneNeI +4mws6UKXiM +4o1X6mR6JO +4o6g9L0NpY +4pAX42aZyf +4pfUMPYbla +4q1oFchoMk +4qD5KQMRGy +4s7eMdLDig +4sGQh5H2lP +4sl8wsl4Kc +4t6m5cqPLu +4t8IOj2100 +4tQsrfaCyr +4tazCQy5By +4tg411ISoh +4tsdiOyZPi +4txSMEEToG +4u7477M1T3 +4uQ0Qj8eBh +4uRviFinJC +4udkmgdQ2N +4unAaL2G1q +4vZdlcs7cU +4w7jVZQJjV +4x49MTDzsV +4xoTutnlXs +4y2qwrPys4 +4zZfoVs6hu +4zhKxJ9XBL +50bGr2jjKi +50kGt4V4yT +50p0DBtc21 +514LiejkUt +516E4jJjFO +51rriLMzNf +51zq4YQLQB +52FSjtQjNB +52uWJsJTyr +52zmVLlBBb +53ZpMgrW0O +53mKGOW2vm +53nAvClpXZ +5443gwmWW1 +54bMiANtcI +54vA3RFT0e +55IpvFlB9C +55XfD66YAs +55p6Uu3AO6 +56X6Y5Qpkh +56YsZBJkFU +57k9enrmL5 +5811hTqbyf +588HFSmDY5 +58M8NlpMJF +58qOmHaJeC +58uE4XdXmS +59KVyzZxx2 +5A61u6ulOR +5AIH1Yrdi5 +5Aha1CRfy0 +5B4gUPybMO +5B6e97Xbpk +5CDOslphkt +5CPYgDEemS +5Ccvm10k45 +5ChjNL3n3N +5CuorHwNbR +5D2AgyKhJk +5D8UigYEPZ +5D9KvI96k0 +5DQG28Dpbw +5DhlPl1T5S +5DyM7qWR5V +5E4BHJ50B7 +5F8m8WNq03 +5FJjmInUk2 +5GiyeBt2vg +5HyPbK0kFR +5IglWdm4he +5Iq81FExT9 +5JIwfnScAf +5JXe1b44fo +5Jsh8M9CF9 +5K1YI9UDDU +5KvtIbZVfe +5LKDJ9ib1J +5LnqcqthEx +5M6NMaRDkp +5Mm8p8uqDT +5OpR8UKTN3 +5PNgsZQWry +5PR0IJxksI +5PUaBVdW9o +5PZ5f0dJnJ +5QzWgHJZzq +5S2ZaeYBIr +5SLJzB6Ze3 +5SlaNxdXdZ +5SsMd9opRv +5TAOYhpZ1Z +5TO1U9imHB +5TlY6vef83 +5TmVQCRCww +5TwjkcSGgO +5Uza4RZ7wq +5VU1MUjGiR +5W7XLGuvn4 +5WQCnr9yp5 +5X4vCJ20Dl +5XE9617Lao +5XjzOwWWrp +5XzpRrwwaj +5YmLjYe01y +5YnWMOlpxM +5Z0QYiQo3k +5Z5FkKuzjL +5ZKOHzKTKO +5ZusDkg02Q +5adOop7uvK +5awtLU1yTd +5awuRTGQnA +5bLyV6rTO1 +5bQ5Iag6yy +5bVHUvLTRB +5cKnQB7gaH +5caAf2kD6h +5ccGnlHx1g +5dZDCr19gk +5ddnmGbZOQ +5e9Rbme3Qi +5eB2jRZ8zP +5efQ6P7Rd4 +5f2andeSPR +5fej3Lddnt +5fngG2Th2V +5gLiJwXEFO +5gjPBrj4SY +5hfTBpGOVQ +5iuhiyF2Be +5j8QC3zzGQ +5jLHx6XPq5 +5l1DOxaOAQ +5l7rOrFkYS +5lAhwXf72B +5lCGS7WVkr +5lVn2JhR8i +5levXsnUF8 +5mDr0xJx9W +5mTrFFS0bk +5mVHsOh11H +5mrcx3jEVN +5mvftyJiP7 +5nHo8ZZqN4 +5nKCrkfBcF +5nWMw2TBuP +5nWhqULPME +5ncgpqSAdt +5o5cw8NC8W +5oC7dIHTmr +5ocG4UxrDG +5oy5T4GHiF +5p7PoMziAT +5qAn9Jzjzu +5qJHidz55j +5qMdGcktF8 +5qlAAjxAfC +5qxefu5tq6 +5r0izobonu +5rZk2UcswT +5rooeLZmTc +5sJ19GUgIE +5t81cTYP1W +5tgeEyaU3H +5u8oL3YX4u +5uF428VjAN +5uX4KIkuTs +5uqrPIZuvR +5v3wl3iM7S +5vqqUvY2Eg +5wlECaZNpH +5wlGnKzNJ8 +5xUI0hGqGq +5yD1TZKL3B +5yH3Qg14lK +5yRxso46sX +60bwGRhk6U +613PaSTmZa +613gwHF2Cj +617qjsB8yC +61HicZIPMy +61MCnPCtP8 +61hwEqqp3u +62VIcrX1fe +636OHBGd73 +637jOQMlRa +63eCGfCsiI +63eJx38SHL +64R8jIff0u +64higmC2XJ +64mV7KbA7n +64mn5epa3k +65DwwRPFRk +65OC9iHNdK +65emjchsBQ +66baFIWva1 +66nVfcb1QV +67RQ2Jn9dz +67ZHyiH7oK +68jv1S5LsG +6A4wgoOOaC +6A9jqcpvLb +6Aqo5cK6mb +6Avu2e4gOt +6BB6dUPjxC +6Dzedpo4DZ +6EPGJOAlEZ +6ES0UVy9Wm +6FEjX41tqi +6GcBU1LKym +6GkGgBdbhG +6HA07ylWO9 +6IDMuegASw +6IDdKTGxjb +6Ju82chDTH +6K3uLLJMgz +6KRKtJl49u +6KRojSWw1w +6MeFrgJ1U8 +6MeIc5Xdtm +6MqqEQCmLi +6NdDzzw3RA +6OBIFkcuKH +6Ofvrmwbgf +6PU9Uf1I7A +6PW2l6DZPT +6PslHfroJ4 +6PwT9El0Oj +6QYUocOCA2 +6Rioi4sCsJ +6Rkz2ygp3H +6RpeDpZ4MO +6S5cprhaBy +6SZ2wxyr8p +6SljgLBtFF +6T5gAz70gM +6TXN2hXPII +6TXREmcawg +6TuPBMG4gx +6U3gQ4hRQw +6UWG7E9RFj +6Umhznv1HD +6Uz4qr5Wll +6V85FuEn29 +6V9v65ZOPt +6VV8fuQJiO +6W8hVq3FTt +6WQXvF69k9 +6WjYepChhd +6X4h1wAp7a +6X4j9Jl89P +6XCbZxjQSE +6YW2wcNJ4Q +6YqSkmk6LT +6ZCYCIeNHb +6ZQLPzy5TD +6ZVWzbaC9W +6Zg5yWNjjV +6a4vyQs5uG +6a9bjcFtj6 +6aS5tTRxzG +6aYcWUmEGL +6anz0ucdnQ +6b8WtT2aEF +6bAClriQKh +6bYQOHD7qw +6bcoosAtIy +6beeIr055F +6bonaDOpMd +6cUnOQSgPD +6cgFhXDexi +6d2BORuGyH +6dD62u6spA +6dY1H7hfrr +6dkDJchWtC +6fRDEWUhy9 +6fb3TsekDA +6fyX4cAA0R +6gDILkloLE +6gb1kKIA1f +6gl5nerhQR +6hBmT1olv1 +6hmdkokOME +6i1c5JQwt4 +6iFtUphxmD +6iMr3yVkoi +6iPscnRcKt +6ixUR7bI1s +6j24OMYRzg +6j25RiuG7L +6jBMFPPLUS +6jZQ2psO1h +6jrRleNVCQ +6kMmSGiiJU +6lBs5YOCY5 +6lCdpEO4nV +6lPNWoVuKX +6lUBbT6pHD +6ldUzY652Q +6ldhzcojMN +6ltAhfFPnQ +6luG0eIlfC +6mVIjVjc7U +6nNvH0nx1v +6nQ4wUOffc +6nZEtYXa0S +6neMA35LkH +6ngbPojV9F +6oAkj3GRCF +6oB89y6aBd +6oFeRNzpJN +6oHaUj1YY7 +6oJeycrVF4 +6oJk1xRgKT +6qKvtcJnCW +6qRdvbQJBM +6qfKJ4Qdlb +6qgm87ArsK +6r1trj7TXa +6rDL92Rrw1 +6rNsQQUJur +6sGO6k7Tk6 +6sLZbSB1JV +6saOzp42nh +6sxljOulub +6t9EztfnrC +6tJ005pIYa +6uPHSywzip +6vYUJwT5qq +6wx2NP3nSw +6x3zyv005g +6xGZkHXFia +6xSUoCKiAO +6xa5nNQZOf +6xcMGXOYAq +6xgqWQBbeH +6y1204NElh +6yHvDvAWWk +6yLcPw3M3D +6ySKfoJ5bG +6yrMaIGYI8 +6yv5kSIbXh +6z9a70g3Mi +6zkdEXATDr +70ok2QPYpl +70vtTJhQG6 +71AygzBvWi +71DZWZNEak +71wOAWgOHb +72OoHmpjze +72YEGVQEOB +72rDoVkTme +73TQp4qpEW +74X6Q8BYG6 +74cYyGkCpY +74wwPF7Z2V +75olAYaRYc +76WSXIaOmN +76apgjf4pw +77Lm2WZYhY +77fNbtKOlW +77yHzD8NC1 +78kg6o2FoD +7A0GEdQle0 +7ABwQjIpbB +7AE1bayIMM +7AYUUzIy7d +7Ap8luUIMh +7B9Mcfczed +7C7lIUvzqq +7CdfkiBRia +7DH5pqEqGJ +7DIU1JQCVa +7DLloVDlCp +7F6JzgT0oV +7FCCpWJM3n +7FDJgc3Dzx +7Ffb670Fh2 +7FlaxB70pS +7FwqqPDb74 +7FyChWYypw +7GU4htEoMC +7GfWP4FCS3 +7GjoLTl83N +7GyjrrZltZ +7H8nOBeJ3R +7HOQLsniza +7HknR8HvTt +7HsZj7gJzu +7I173I9UN0 +7IU3WImG8a +7IpdkUM2BC +7IyjxH6tLV +7JKMIh9QKB +7Jxvk0nww2 +7KZ5xoEJI2 +7LtUrhqMAd +7M4cXQ1XAa +7MLtwBVxRs +7MwiLbyICS +7NEWfjWdUE +7O1t0OXRp9 +7ObR9x8gMH +7OjBgD3Cmc +7PLnJUOizY +7POU5rgqx2 +7Pai62GEaO +7QpOUaQS0c +7RdWGjps3E +7TfOiNh34t +7U6QA0q1Ys +7Ua7cRupVZ +7UmOJwD8nC +7UtTzWKYPE +7VAPLdfuVQ +7VG85f053i +7Vgb7f8u9F +7VsWIKsEcz +7VyVF6KLt1 +7WAHoXJv8Y +7WxadCJwa0 +7Y4fz5qp3n +7YD0QNJYSB +7YhvNEN2dO +7YrzMMCHJX +7ZB4FWJyDX +7ZkNQDI0So +7aADllCDnw +7afqRXkZXR +7axY47S4ak +7bUuIraM4w +7bW4FC4OBi +7bgkgIyvIN +7bwT3dsS5r +7c4b78eNwP +7cCYAWvfmq +7cTHiiPFIE +7cXRweQgxX +7copcBGJWQ +7d3LEqAJgN +7d8asYhyhC +7dG9h6YXAO +7eIS8n16Hq +7eJ8bGcFE1 +7fmzx5ze5F +7fuNeFoWi0 +7gULmQpRsY +7ggVXyP63p +7hkcENhZCU +7hrWfeH3pX +7i4xk1LHzU +7i9iAiovl6 +7inm8QlkFK +7jCJX46pYS +7kEasE64jS +7kxOdL9WDB +7lW8Aje5yL +7lWwFBPFeE +7lb6FTmGLt +7m1EET75Ja +7mCmV7smja +7mTNDhigYx +7n15gs50xZ +7n6QzPV4cK +7n8xpfIwEp +7nCLYKaO4f +7nHYLAwu0g +7nMDUGeTjd +7nNAX1jRI0 +7nbQbuRFHF +7noKpWSdxA +7oTjpQghBU +7ofFnaRaWC +7oqA4fKNDG +7pgSmMxFdQ +7piGGwBCvW +7puC0q8FIX +7pxDDnsMRE +7q6l3tvonQ +7qRgol2tQG +7qajB40kAl +7qwwt2UExJ +7r5ZI16FkR +7rNQadkhMT +7raMyQASwv +7rjf1mEHdH +7ryE02fLlS +7s5PlDhluR +7s8GeZOitX +7sbp60lEwk +7t6jxBCUZP +7tq1ME6E5I +7uIZuHeQPQ +7uPDhFf5uS +7uvtWgc6aT +7v4iPKMYYC +7vVOqQQ9wk +7xQBwQQEXY +7xi4uENJxV +7xnoSw1Ayb +7xrRmshmq7 +7y5pNc9BJF +7z1MVWkgkv +7zKeWX3JNr +7zfUpvDpql +800S9ybUCu +810nQyZWLf +81A4h6VLIb +81YavgFS5L +81bUiC32K5 +81diCZ3eHc +824bie5gnO +82HHG0sEGz +82bMWeTclg +82x7PWTslS +83M4KKaHFi +83iQn7MIvH +83zQo59gug +84YqeSDxpl +84njuT51SA +85BnD7Dkag +85koTMYekY +85l9Yk4Zhp +85q6uoK5im +8787BavJSg +87DJzWtHxt +87PYj5rGfn +87TyWdmUjB +87Ugwp39VY +8826jKPojz +885KRepKIS +88OXoYAu4i +88cpEWm2ry +88eZpuDjkG +88pcPPsKe2 +88xUep5ItY +89ReubIfWJ +89hHFU0Il5 +89wU1W1M4R +8BGrUmk1Xr +8BYz4XStez +8BdwpmctcK +8Bw7xu23yJ +8CHFyqYDRV +8CNFduUWFo +8CgWllt3jJ +8CnNtUl9XV +8DaCTDkCBU +8FZ1ekGOX2 +8GOSPlfpaP +8GmIKU9RhJ +8J9t7pJ6Tb +8JUBYg0nRP +8JZwNxaqqE +8KeOvQM4Yv +8LBBPynSJ0 +8La7Bwr2n1 +8MM7oyQXdb +8MbZQ0rJvq +8NSrhD5ePP +8NYBqww9o6 +8NzWbcOz4u +8OXbsbJxOo +8OZC7Yw0WI +8OhaNN71lJ +8PKjhYPwvp +8QMqEnDixp +8QyEcJokUS +8R3I82Ys15 +8RJQFTorYv +8SSXJwxVO5 +8TExNWdLUi +8THP2JmYIr +8Tyk5EtqMl +8WIkTKyv9V +8Wg3DUMf6i +8XIgCnCgzi +8XLfLKqyOx +8XiOUju5Bh +8XpRV6VTFP +8XxuEOUljd +8XywRC1cJm +8Y3T5Hhb49 +8YGU5Zsjwd +8YJ6LisnMG +8YiFyoGatY +8ZLBDzH93n +8ZO9LcQICY +8aZOQwnhXn +8bB9PEvhVS +8bPbjEEaYF +8bwy7HWDh3 +8cbfvyCyBh +8dbUoOEcpj +8dwtUG2gbz +8eW6oJMzUm +8ebUo5HzjS +8ej96Swtm5 +8fCiOkEi2X +8fN8NFAb4A +8fT7PgDv1c +8fYcqu7To9 +8ffDM1C0P6 +8fmwLBY1t0 +8g4Krfoe90 +8gUTlaOTq8 +8gdu4wfo0u +8gswaPGWJG +8hLEKzY8GP +8hc4BVE0y9 +8hmEc2IN7P +8hvgPVFp1m +8i0EElJcFi +8i8yBUTjBU +8iUKG9T1Ac +8ijlWpUqj9 +8jSAv57Cpp +8jSiy62oDx +8jgUU8VLyu +8jhKMb210B +8kbh61HDwb +8khv0In412 +8kvJIagtiE +8kvLokjb7Q +8lliF6gZgY +8lyrZqF7We +8m5eou2m7e +8mHP3cEBRO +8mJ3yD2qOd +8nID5gJmPM +8oNODjRRNK +8onCQDh6nh +8pFdG5RV95 +8pSvMgbGlc +8pXXJUELSQ +8rCQ1qo0Dn +8rcb5GhwIw +8rqPk7o4yg +8s2ZkLrDaR +8t7rOT6eUd +8tcB69gvGk +8vpUZ33jgJ +8vz5t0hY5p +8w5fMaw5sG +8wLlfbNORo +8wkig0mUgb +8wupb1vREi +8yASkEX5gG +8yBpJjblkP +8ySvPWvnrb +8yTWoMqAZm +8ygMkM8MIH +8zQoFI0FEk +90Prt3qJjD +90QoREvM4b +90YEsSWm4t +90pxicttLy +91KkWsiuOF +91VyReli40 +91jpzgGj5s +91mO6oixFI +92AHa3Ihdu +92Bux6c3Ui +92eMbZmtDI +92iZOD0Ljk +92tLNxvpks +93CEy8sG7J +93JSrkVfip +93R1pqAXdc +93dRZgGL3a +93tb6iLVPO +94oNdJoJ36 +94ztUCpABV +95Rm3DDUG6 +95Si7Cf1kY +95mtkybRDa +95vLjXz7GY +96RnT1Pec8 +96w7P7eYZg +97SZBIrrc3 +98Jy13RFkD +992A86HkUa +994tn0Zfxr +99u1LkN7bV +99zsUGZRX6 +9AZLSTwIAS +9Auaio2Xco +9BGlVEFVuG +9BSIuRK8C0 +9Crow59EeX +9DTVZ0l9LY +9DpgJ6bmFx +9G9R9lx73i +9GsdNZK5Bs +9H1c4AlQa7 +9H6RVSjLy3 +9Hbup54l46 +9Hfdpc4qcs +9I5BXClEGj +9I7PajX4sQ +9JFLK2C8nr +9JWIV3wD5s +9KK0zIUZ7C +9Ki1BzkjlL +9LEWGN7prJ +9LHximBcU9 +9LUIwKZv1O +9Lc4IyoLBS +9LptQdz2gt +9M1ZAcFJzr +9MZ2XIXwXo +9Mdr1Pt0RB +9MwdZdRuFV +9NiDBPgj7C +9OCdUP3aDG +9OFd72APwY +9OgJMgIDFp +9OnL3UpaW4 +9P0qogIosS +9Pssgbv8pA +9Q75TfVe94 +9QFENlSTBg +9QIBRTEDrn +9QNXm6hS6G +9QUUdcmARP +9QVLIOKm2V +9RDhlLR0nq +9RR5Ix5FNy +9RsXuduDZG +9T9fkwQcQD +9TUJ5s52Hh +9TsW9Cp0zi +9UHELduAtF +9UI7HU6Wwv +9USKc9mnYD +9UYJLzNU4W +9VNCNuBqzR +9Vmtp0dZ6G +9VxEaQqpUo +9Y2d6hYdgc +9YDxNYQaTy +9ZBFh1IiIe +9Za80WXpZU +9ZjmibQK0E +9Zk3V8QyVG +9Zs3r7Sa4y +9aUhmdFIgV +9ag6opR5zT +9bRq8YvTIp +9bqGY8eWZc +9c5QQCNPp2 +9cNw0tlaoN +9cc8cEuYZG +9cu8GiSMAQ +9dLTFLoiau +9dSarNGEDI +9dSnhWyUNW +9eUIRNHkze +9eaRB8j9KH +9fDAlHkpuG +9fIJqrAiIZ +9fK2sG9J1p +9fvfoLHM9n +9gVZGI9ij4 +9gqmaLnTGy +9h4XvE3zI8 +9izVZxmY7J +9j841vfulW +9jFhBGGgzn +9jX0h77nWc +9jxkgGVfmv +9k2E2K2jEW +9k746YX5Qk +9kTbysDXfk +9kVE2PCTJ9 +9kxneZeVJs +9lMfAOhA3P +9lVrYtPn8w +9mcWnAB1I5 +9njAi79mBW +9nsqsedC2C +9p5kyUmOOJ +9p6J0AMekj +9pKeYSAYKp +9qHLbTcJHh +9qHigDS7t2 +9qicjVhjp3 +9rMfWhcMLE +9rrnMDHHuq +9s9lKzEyEv +9sYmY1YcC0 +9skTKN5Ag7 +9tDYAkiMd9 +9tm7dQyOe6 +9uTlg2bAa9 +9uo0lRvuqB +9v8HJnGMYL +9vAOgWuNYK +9vLNHiYcAE +9vU0Z484dT +9xErVMMa3G +9yoB1yt8Z1 +9zI9UvfOeX +9zIwhHhw8W +9zLA4KQpOt +9zLipu1HO6 +9zOq3Jr0eY +9zWkfx029n +9zik8Ss2jJ +9zjsrp9cmf +9zuPvzSfy5 +A09X8syjqV +A0bSApNcIm +A161BAsYOZ +A1TXczFZWq +A1YL1l3edN +A20KYxOcKq +A2acP1lVUm +A2cYKlimhA +A2dgL85D14 +A2poRj5Bbh +A4BWVDihN4 +A4C3EqGP5Q +A4FID02y1z +A4JAlYTul1 +A4TsumjSjF +A4ryAVptbi +A5HdWIXYNr +A5QxhybNIR +A5clccjLJj +A5tlhJf5Ff +A5zcj0ZIqQ +A6OTV0BGxd +A7oCnoKq8R +A7rpR2YTMa +A7ujkglUCg +A80lx1WyTe +A8ig2htlML +A9naDIeNUY +A9rn1e29nh +AA0V0BU5Ih +AAYZ8mgtCU +AAbCr1m9IL +ACnQMF7no3 +AEKTZSv2YJ +AEOlGfWgJe +AFNBefGXnP +AG0DC3EYe2 +AGQQIhWvqK +AGgnkMZFpu +AHoAmChU6E +AHxQJJViAv +AIeWtlVz5W +AJGMHI04wd +AK03GY7kjc +AKBMi1ZXHN +AKfyISFyhX +AKr9Adve0n +ALFo2rlX77 +ALTWRiCo4R +ALX8uOFibM +ALfvzdqcD5 +ALgSDtL6oI +AM4pn4lM1Z +AMeimoHhdr +AMroatkkHT +AN3XlcstsH +AO6jN3sUtR +AOuDMBUEhL +APES4QRDTB +APM14ZKTNl +APt6jG81Mb +AQ7JUXvzUd +AQD8vnizcL +AQQ68VPUkG +AQZG9d1GC7 +ARS7MHxZQW +ARYcjjg4hx +ARzGD3yJrR +ASZI4zEJcX +ASaGiGp9gO +ASbxEmFk9F +AT2BGyP1SY +ATNAoll3Vl +ATUsIP64Nx +ATZsgLDD6Q +ATbDC8xW63 +ATeUnqfpLV +ATwjgE8IZg +AUXWjxmfMu +AVfkkC9zAm +AVfpoVSRMq +AVtXDlek4L +AW3WO7BGOr +AXLgfcbwmT +AYa7NbMTKl +AZCQvo4sLj +AZCbry33oC +AZdWf41tuT +AaZZJ5sEPG +AaouRaugpm +AbGrPnVp75 +AbLbw5buwS +AbU2GrVG6M +AbZuhdzW8p +AbnP9GDGRl +AcBb1ueiUk +AcUeyzm5gE +Acx0G2rqX6 +AdRdJPRsSx +AdTcNsszyx +AemwmcTu80 +Af3Dud9vZw +AfPl5pwZwO +AfjbwFtnmP +AfshB7QA4X +AgLQi1YlQC +AhyEpXSX4M +AifTqBZLPY +Aj7reZ6sa8 +AjX332ZTAN +AjmSwAQTmP +Ajr6bv8PDZ +AjyPPRGKwN +Ak64H7BH9g +AkHszWv76P +Akds8tORlX +Al61g3qTrT +AlBy5b7JST +AlYlFhfreR +AlZJglPPIc +AlcUisox9c +Algzn6XAaV +AmkLBJUvgQ +Aow5c8Kt7w +ApnQaB2hvD +AqOxy2Z8AU +AqbWSryiSw +Ar3W44RewU +Ar6ICFP1R5 +ArbI7mvfII +AsHRgxB51U +AsPHSAdeHK +AsTRYMPP1O +Asxn7g8tru +AtMH7HwpTq +AuNLZ0BfR6 +Av2Qc0AtbS +AvKZSe7rVv +AvN3HsOhyY +AvoU6iVHpI +AwYzE7o7dR +AwbmHmEDaj +Ax8fvZm8XI +Ay9XEMo2rl +AyEg1eIxye +Az0eUI24bO +Az1YYqMX1q +Azt5xUQR2v +B029tVm7mv +B0cSqRSK1s +B0qjeFiW6n +B0xCeETk3V +B1fjhxp5Bg +B1p6tusHhO +B2Bq59P9tw +B2KK9WsNOQ +B3YuZ96wTv +B3gESdXvSo +B4NMH9o7rz +B4gLYKICWV +B4xHWnjZ5L +B57jEWPM2e +B67HJfUGBR +B6CT91VTEF +B6jmf4Id8E +B6yGmmmLuM +B7qkVti56I +B8HJz38ml6 +B8XOwmMlAI +B8tIBf6h2n +B98yRf4BUj +BA8z9IeQwg +BAC3M1CDEG +BAR05nxY4m +BAhFSE5wHH +BB8bmU4BrZ +BBr8F7nHfZ +BCtiGD9wl6 +BCxL4fqISB +BDDV0TqagM +BDw0Ejb35i +BEGepD0YVO +BF1ZZIMgCQ +BF557ur65X +BGbChCI0Z1 +BH06ZZwMXf +BHKXIDOS8V +BHKsWRM7YE +BHpbVitZtw +BHy2yfy0Qr +BIpyd6eQ0Y +BIu25e7jSC +BJ2Uw0HDDZ +BJPdznu3Bw +BKLePOTJ4g +BKgc2oTlCs +BNnQ2frCcu +BO8bac90KN +BOdg5JSXVx +BP27WEfQ6o +BPY9OvvibL +BPhOCPYEA7 +BPtENJwShI +BQ9GiRqb6F +BQ9UZO4li5 +BR8vc1aqek +BRcnKqBnbD +BRuOr1OHN1 +BSWuFNxBvS +BTFxrhPoMk +BTUmWOXiKf +BTdVMJIzwk +BUKgcys5oH +BUM5MMacb8 +BUMOKD5Efh +BUY5cWNQ5R +BUhSacRtr1 +BUr1guQDf1 +BVGHbUVlEO +BVM7NujjnO +BVZJ3h6TaA +BVgM3LbMK6 +BWWxsTwl4y +BWePTEmKCO +BWyyMDGvii +BXXnbH9OUt +BY5esTnFbE +BagenfXxww +BcGMJ8NjSi +BcTu08AJ9Q +BcnBAKaEVs +BcrNoAVmxY +BdC3zyEPHy +BdSRuxPEfV +Bdmmm81ORT +Be5AW1m09o +BeFaxJWLTG +BeZtd8v3oz +BeaMpPvTdh +BfFjFLJDJQ +BfLllvSHt4 +Bfewe0XeQl +BfiLSiPKse +BfwzSAUFds +Bg9raurLbT +BgG4Ts4iFh +BgO3O2qnos +BgVtVGLCWr +BgaLvSpWGv +Bgelrq68Qo +BgvWv016IU +BgxUuT0lMo +BiZKYOgJ1Z +Bj2sII7c6i +Bj86zMEnrx +BjNPxh7dFb +BkFkOv21rN +BkjXoiEj8N +BlPIqH3R1T +BllDKEMCJq +Bm5f7UeYG8 +BmMNSFv7Dq +BmNt7s3fTr +BmnlfY7GP5 +BmvLnaLhrY +BnaEcUAyvp +BneVUeG5XR +Bnh0YbkhYT +BnmYoSrmsA +BoLX6JpwAI +Bp54TC63uY +BpPNRfHaCf +BpcgnpK3rV +Bq2EJlQzFc +Bqa3BrmvDM +BrMLmnpXL2 +BrSSvywKpq +BrUQfmDze4 +Brw8Y3NNO2 +Bsk61r1ObM +Bt3HdxRCKb +BtCQsqp6g6 +BtL5SmFj6e +BtLwUQr35o +BtiJOZ4qc0 +BtkiPMkkcG +BtnKjnYGSE +BuQRB2qFc5 +BumDwVyWDU +BvQzguscPA +BvXsPjnf15 +BvcDyfPIsm +Bw7VLKZi0d +BwEfBut8Ha +BwOFcELX0e +BwzBrqDjmc +Bx2Vx3NHtE +Bxs1iabqea +By1jUr3nYe +ByPkATlPa3 +BykRvXlD4o +BzHbMBPkQA +C07pel10NI +C0Sov2h8QV +C1K0uNwtz9 +C1jOh27n8X +C3LG5bOLbn +C3mbbKKVcN +C3oJTnaiUJ +C4TXnsMaD6 +C4Xd9QTIve +C5LPinF81s +C5mOrhNM6N +C5rUk4D5px +C6KSAxK0yF +C6YOELzjkT +C7U0N8aOXz +C7dsFv5qsO +C7hfQfkSZL +C8I4rjwC8p +C8V8tTRf0f +CBCoyTryxC +CBS4Xxy6Tr +CBuOomm450 +CCCvb4bTCZ +CDnjMimzSi +CDogkggfvw +CG5INSPEtA +CHFfuuDnTY +CHPzV6eqHy +CHs00wvASe +CI1uNFg7RB +CLGe14kbTN +CLT1ofpTeq +CMUdWfRnT5 +CMUvOk7Fyy +CMXm6H7cun +CMYp5EG87L +CMo5gYWdjj +CMxkmRVu7R +CNDHlw3r5L +CNcTqEinZX +CNhoXHep1v +CNq2oJgZVJ +COVNoNanoN +COoFesOwli +COteMrRRcL +CPfAev3Rpt +CPoztHsbA0 +CQ3RodRC7Q +CQxOGucMvc +CRAyitHMOL +CRIVb48tml +CRMROfWDsx +CRhPBpRQXD +CRqJV0VdWX +CTcfBwKoUX +CTfvjQZFJr +CUEwkZ6DmC +CVHzhiq0w0 +CVK2WK5uOf +CVRxGp5vei +CVY4hBYRan +CW1hnHCwu5 +CWFyQMIFCV +CWLaAyc4vE +CX0OkZhiqV +CX5xSZX7nw +CXB9GZqstm +CZ87hMMdWQ +CZJ4vmwXWY +CZpK3twxpE +Ca5qqHAuUp +CaAt8YSPe0 +Cb91UWHGWZ +CbzeYNn0Zn +Cc17eQLtkI +CcGaRpo0Xc +CcnqkqvVBX +CdqS5hGoZV +CeKF8hTHuf +CeMTdWZmKB +CeXLpM2J2s +CebbroxNHk +CfCPELJcVf +CfwFLGmTz7 +CgTksDNf3a +CgxilZRKfl +Ch5DFd6DQz +ChW6czArQl +ChuZZBnMqV +CildYwurRd +CjGUDcQXRh +CjYzSiZEun +CjrIFgRRYI +CkbYsOUUtN +CkgxvVc2yS +CkmVyz7oMb +Ckvp5wh1gJ +Cl9wJmKxLD +CmH8erhdk6 +CmIu7ctKCg +CmjpB6C11e +CnBxKvTdLk +CnWXPi0q3U +CnkDtWLz0W +CoF26HcTKv +Com6vI0wkp +Cpwcv1Sdl5 +CqECJ6mh4f +CqPi0VmDrA +CqkZi6au5r +CqmxeWl3Gm +CqnKgw7ezz +CsNalpc1AK +CsmNqbnMSz +CtFZc9ySZ4 +CtqOyrSRWm +Ctz24PY0Wv +CukXic6ZwE +Cus3vgOPKI +CvUCi9WXMk +Cvd0Wxd49C +CwPkv8U1i4 +Cx9wF4Ab7f +CxBH0sO5ad +CxFWZYyboN +Cy3lDGmWo8 +CyRwnIVR3M +Cyl9Iy9D4c +Cym3s1gyCW +CzWPgKwuNx +CzccvkOBLT +CzhFj15k51 +D00EbpRtYn +D0NHOP7uR8 +D0etBgPa3U +D0q9MJrd1y +D0xUyEjutk +D1eU93a55T +D2FYpuMRsZ +D2QBbirP0T +D2QVCTcYVf +D2d0xCygsg +D2g12vSVyd +D2qITVzCtR +D3sikY3E4M +D4JOQwCb1T +D4kROSQUxu +D52eI75sCo +D5IRtcX5vZ +D5yeeh7mD3 +D6Sq3ycMVs +D6YwUDxHYt +D6jOhKR22v +D6t6wcsKoP +D7QOzOwByM +D7dBbiwKPl +D7qawFZPDA +D8FEDV3mqN +D8Jwc0tc5q +D8i6ikUDO9 +D9259Ns674 +D9M6i0qu4s +D9PLoyJwLE +DA8q6wEPQA +DA9rXHI8tR +DAKaTVuvvY +DAYSta3eX3 +DAtk70fg6B +DB7RJdaaAG +DBOwbItkuV +DBQMe3TyuL +DBfCdBI6EO +DBuCT6eHQu +DCKrzUmL8f +DCa8Slaaao +DD7qCnxa9I +DDCLJRERD0 +DDEEvtoEMl +DE4h0IT7d4 +DESNjEezmd +DEnDRdtuqT +DFUV5Salum +DFcmp2TTjX +DFpAmCoHsV +DG2Ms2Vh10 +DGGSXoDHRT +DGi6yJ65c4 +DHTK6rxWLI +DHTNF8KsEb +DHe8TNQYLe +DHpQ7kVLOf +DI15Z7V9Ap +DI6G2gsP1H +DIDaL26onD +DIoKwuEj8i +DIpSt9sWgc +DJ8RSTDyIg +DJlcRY7siA +DJvZcSehDI +DKIqdXUiqj +DKLNvC1pwG +DKRRyHpSbC +DKU8izeas1 +DKitHCx2cQ +DLyI2P43ol +DM2MNBsYGw +DMR1i7RKNM +DMeze4fDmd +DNScU7o6qi +DNo2k98eKv +DOFmQKaq7h +DPGpwmDW5A +DPKgCYbUBP +DPRaMvrrho +DPW6kBBPab +DQcrYWC4Kz +DQj1WVorhZ +DQuia7PylV +DRG0Bqpzxl +DRhbwxpzdt +DRn70nO1Xp +DTS10eAF1B +DUOmBmRJrl +DVVj8fAvBt +DVZ8psctMa +DXIdff71Dq +DXIpVcvMCd +DXSGl9do9Z +DZDDIh3bXa +DZXZg14PCo +DZp5wMiGTo +DZpX9SeHpV +DZuQoDbFWa +DZzVXxnkVB +Dao5TTTJDf +DarKl6fl3r +DazIPpbbDq +DbKdvH4lNJ +Dcd9kKlMSD +Dd0Bv5qcbz +DdMDmOPr3a +DdWm3KYLHk +DdYxLvAwbN +DdmSqY4f11 +DfsIlUzHQ3 +DgJX6Djrnu +DgjcrSDGAI +Dh3ZhTmowB +DhQxmMNJYu +DhTXtvUMs7 +DhUWtef2Ce +DiEvzfmZI4 +DiKCrCmTDM +DiLUE4w5Dd +DiMzJYC3t7 +DiNLWLg1u2 +Dk3UVXs1hh +Dk50x523Nx +Dkcu2x0Tpp +Dkz8dzaQzE +Dl0HclBVNM +Dl7fuEhEI0 +DlWpkTRLFP +Dm95wBzu0u +DmA1FN8u2I +DmTXWWK428 +DmYNaM05oy +Dmib85CDbY +DmtThqqhXK +Dn52pSQ2ba +DnbnpAWHhq +DngORyD1g1 +Dnjy1JlgEN +Do3fQGWwcr +DoCAZgTPhb +DobJwBx65T +Dp8ZaI40SV +DphtxhgGMX +Dq4N5HRbQZ +DqFw4zaVR0 +DqSZK05SGM +DqTrqPymKe +DqoQEAt2z8 +DsQnroHKNx +DsX7eIWrlh +Dsdf4Qix8h +Dst3nFgffR +Dt3W6IK5nb +Dt9IL1SXEy +DtJl7m8JZF +DtegZrYukK +DuTjxPFOC2 +DuwoY8Amnf +Dv7DvDDxUA +DvArnAYRkL +DvNp9LRHhh +Dw9n2v3Uzh +DwY4bloSEV +DwkeLC3art +Dws7AI8Gqv +DxiwWy9OcH +DxuJGe3Cd5 +DzswLwLR5r +E0SfFaxWmo +E154sDUhtt +E1Yj9tfjj7 +E3IfDZdMQJ +E3RoqAuXQB +E4IXrAtxmQ +E4R2RTcRlo +E58HedjFuu +E5CSSEzvwa +E5EwIhnk71 +E5FXDOQxcb +E5fXVGLNgP +E5jaSQLbnI +E6AMVOkprg +E73BEdbNdp +E7V7EVTcII +E7iXymCQ1O +E8YskeHzJ6 +E8cX23DYa3 +E8g2cLmRsW +E8jdFK0jft +E8rRgD5kOy +E8x9Zb3QUY +E90hi2EFX5 +EA377QTqbn +EAEOc1Ecag +EAw1DWkVhP +EAz6l8BZcD +EBO6mmBLJt +EBUOZjSp4Y +EBuTjkHYGJ +EBx8JeyYGu +ED4MR1qIlw +EDTDMK448R +EDpDhlH4r2 +EE0E55RqBJ +EEPHWMAoVF +EEbuyfuyaZ +EFNYIV4UyN +EFPqAhGSQY +EFtkAu4kfr +EGDllw32lO +EGLI36HWLF +EGZDJlwEJF +EGhoCW76DU +EHVJbmiZ44 +EHrXytVeZu +EI0oYRYyCP +EIKF23eH2s +EJKIegsiDt +EJTRkJodFE +EJXxoDQeh9 +EJlKn1VDRn +EKNxRyyI7s +EKnF5OSnF1 +ELafyJHDp9 +EMBYHWhL6u +EMenCYuqjc +ENS0zgIeEQ +ENiuRndLSC +ENtBvIbUMq +EOyBsdSc0g +EQfXtMCrYn +ER1WGeTP2p +ERTSSe9tPl +ERhZAIBfjh +ES11JbFAH8 +ESLICxokf5 +EScGhPgVS4 +ET0hqM5reU +ET8gL2Bfax +ET99Uzd0PU +ETGdN3aS22 +ETbs0HzEsu +ETlKNsrrYp +EVcw5BPrvg +EW2kETGDWj +EWQh3QX4Yo +EWYgBYNAde +EWk80Xjr0P +EWyXDuk3pp +EXBS0IHSYQ +EY2HhWom2f +EY6ZVE4UJt +EYEJUBSYtd +EYPx8W22jL +EYf93gIf0a +EYheh6u9il +EYqqUKjT0b +EZBlhrIZc4 +EZHY3JCa8j +EZNWlu16Fj +EZiNvbICgo +EZjFiOm60L +EZpf4maJNp +EblVvrUoda +Ec8jCZjeVV +EcD1YYWyPP +EcKdWJgS9l +EcOydS1rBn +Ed0EESjp6G +Ed8lrkTSqo +EdQiLF85MX +EdSw4SHgRg +EdU1g3GzWC +Eddezv5Oyg +EeOpqQ0kVB +EeTSol0LuZ +EeimzijFpx +EfR4jiavzP +Eg6rgOgqPW +EgG8BduIhJ +EgwxA1820I +EhCgRQOW3v +EhtWD9YC1g +EiJ34VLfyj +Eijbbb5t1W +EjxNiLAeEQ +EkiDLKZ4IU +ElGfn0Ucp0 +ElTwF8HfCo +Elain5kYtg +ElxT8QPbkj +Em51Bckwxx +EmBl2hS93f +EmICqJWfca +EmcpYn7SFn +Emm3l9GGfT +EoDjkCde2R +Ep8g95ASeq +EpAdkGyWP4 +EpNdJ0VIHG +EpNrvrQxIy +EpOww66fKj +EpeoLQ8CNj +EqgKF7a0yt +Eqiuuahkga +ErG682r4Wm +ErRV64MCzV +ErcGF0D3Ky +ErxUJotOIh +EsIvDFxdCy +EsN3zVOo0a +EsVuSAnUyE +EsrBtEMdg4 +EtEkptmikE +EuAz4icvjH +EuDBWRU2IH +EuJoLGjyuq +EuorveFHYJ +Ex2oRFDOS8 +Exht4Ugumd +ExmISEH3Vx +Ey68T18n03 +EyF3NnctMW +EyGqU5ZIzS +EyvBJt0fSR +EyzpZ5ckz2 +EzC2leTHPb +EzGDueQuyO +EzmuS5gHbC +EzzcBN3hzr +F03lFSntQg +F1hjY5XwUg +F21vRqpAmX +F224QvTXIP +F31XyulcoI +F3QwtycUS1 +F3sQIP0BmQ +F4hWi3On86 +F4zfDw5j0L +F5JuKi2mOw +F5R4sQ1DxH +F5Rner6IsW +F5c8Rseur6 +F5xQDgjCik +F6BnrjWttj +F6PBgNNyn8 +F6QJl4kDO1 +F711Ci7wv7 +F76PEDfcNY +F7FZtMve9N +F7S4Fodpk1 +F7WbNwq2KB +F7Ylg93w9Q +F98RIelXi0 +F9LqCdXv3X +FChXEzw0Gp +FCo0czu6xV +FCztu519aX +FCzyjcFpGp +FDDuM6wx1t +FE2WwHJply +FE3EvnqDJX +FE57WJsLYn +FE89xSaA6A +FEEJbM8qzt +FFU5LuY9XO +FFUpyJx8Oq +FFsC8bOvt8 +FFzBV9Rlcm +FGP2QKeFtV +FGSmOwDQju +FGmVRoRR3x +FGtVryBZyt +FH4LpkYTTo +FHIdwiccvp +FHLkQVuRvu +FIFEK2uOUJ +FIRjsm3XdN +FIvlpIz8SH +FIzpRkWJlm +FJGk001GXi +FJhFTBJl5Z +FJv7w1CbV7 +FKBwHarBTW +FL5riuMkuI +FLF6tuTINF +FLczMCwxGG +FLiuOofRrh +FLqwOZN8Zv +FM8ZoB733d +FMDmhdNEPJ +FMG6KCrhSi +FMKIBHhK4v +FMY27JBrQq +FNFIIpxmjw +FNTVeEgY4s +FNVgxdC7kD +FNeh5NaNBd +FNtUJ603wQ +FOE4z8QK2F +FOTpnhU2UF +FPIiru9oBc +FPhEYTTQt2 +FQsCGvvi69 +FR8sL87FFZ +FRYPcPb5ZP +FRcRQhILwv +FS3x79vr6r +FSXM5vg1QV +FSZD3MhhRO +FSe8enqIV4 +FTfQGTo8gS +FTqxUhbOZF +FUMRDLzkoZ +FUXnp0Q8JH +FUe2lNEohI +FVatpm3sdQ +FVdCsoMEyd +FVmcJws87m +FWSDiocbUM +FXJuFdNWKv +FZDG1iZDao +FZE54SQ0VD +FZfRQeckcO +FaAoZo9aig +FaazHWov7D +FajmFOsQna +FazOL0cNXA +FbGqORYU7v +Fbem5c7b1q +FchgO54ANk +FctyOEMJEy +Fd3odMJeiZ +Fdu5A6r593 +FejN94pdUJ +FfH3UKG8Mn +FfK5AJwq4m +FfWOt6tkp8 +FfoUxQMTfg +Ffr61JWkBg +Fh3dRBoBMg +FhQHuqflT0 +Fhu9XJ4C7K +FiTOhsePxr +FiXHEXSuUq +FiaHAewPws +Fimswph5xu +FiprBbz85h +FjGtedIuFU +FjtsiEmG28 +FjyZ6eGA9e +Fk9xwbMaJX +FkJPUs0T6w +FksUao4HnY +Fl91cUPgcp +FlOQAP7CJG +FmK3oG7RPR +FmKa4SntP9 +Fn9qjJ1nAX +FnGvrgCDRM +FnhGdBSpTr +FnmjHhPu7B +FnwnGpHOXu +FoYwQX6Gqb +Focvtiu0Ke +FoeErSsDa4 +FpD100HVgb +FpJGB4nSDL +FpMoUUCx3w +FpNWtmFzAs +Fq1qux8Zn6 +FqAjhYi8G9 +FqmFSLPrFi +FqyJSSmyHC +Fr0OUTBtGY +FrySfodmGT +FsPdhhCr7Y +Ft86Tc67ja +FtQJpdJBig +Fu5mRrguLS +FuKdP5hcCx +Fv9AzrMMu4 +FwING2N8RQ +Fx5Lwhl8v8 +FxBm7IcKIG +FxJSNmbQmE +FxaVYG5sqU +Fy5tQ6Bo57 +Fz0a5MHhFU +Fz4dS58FMl +G0MTYayKIP +G18DR1Ab9F +G1J3kM7LwC +G2v9EGDRMD +G36Ronu75W +G38y6gcl4J +G3CH5t80YY +G3r8B15KJA +G3utMk5DsJ +G4XIfwBZht +G4fKXGANL6 +G4nOjPvxIP +G4pxVELdiV +G5Uw1sg2Fv +G5xGYsskLj +G6AB0XNiJc +G6ddx2UA1T +G73PE6SmZj +G8JSFVaUmm +G8tRhiOTZZ +G93HgYEhjb +G9Jj6q0kZF +G9ReK22ntK +G9VpsKP9xy +G9XU3a0Nik +G9n5FvsghN +G9r8a1450s +GA3d5arTHV +GACFZ1WkqG +GAOQExOcUw +GAlru3DBSX +GAp0tVjKwo +GB8jWTtuEZ +GBEdvyvEZl +GBaW086Gyp +GBgrum6DVZ +GBqDUgScwT +GBqDcybPIW +GCFz7yoKBA +GCO1fQ5Pmd +GCyxy0iMzK +GDCfmyilh8 +GDIS8ZJkd2 +GDOoyKCozH +GDYBV6aNma +GELibPMqv4 +GFkMUT9UYV +GG5vLlrvBc +GGgi8qOedN +GHFF9DTY3k +GHeLFZISKg +GHwOZ0SeDh +GIkByMjOmN +GJ0dXeV0nq +GJIipQkjNA +GK2qeM98cG +GKCcqKSrVB +GKPu6DTy10 +GKmXBt1jF6 +GLMpsk7iDq +GLukKvmPgh +GLxQbR1K87 +GM4Y96gund +GM9r22pXUz +GMQkvZDITK +GMZGe1YQPO +GMxMopFoit +GMyF7YGkei +GN6ykPUV85 +GOsVAp7FBh +GP5cC2SeSF +GPYakA3fW6 +GQTDaBIYXi +GR7WuPt8BR +GRz8xcvmVG +GS08Gs7z5J +GSQK9dbRph +GSavwbE4Ap +GT0sgu6beD +GTL85ZiKWl +GTlz7go82V +GUY5J6aQxU +GUqGrfEjuk +GV4Uzs8yfF +GV8dsfWZps +GVfgIZ3V5H +GVkI25ImR1 +GW7d1utGwT +GWPbsdMWPF +GXGkVaSm44 +GXR6TJmHpA +GXSeZvD2Bs +GXo2wUzY8Q +GXzEStSFou +GYeGud4uEM +GYrVoQKcJ7 +GZ61Zn36PV +GZFmSYkrFe +GZb2aXo4pH +GaMBY9Uc3Z +Gao1uts1oo +Gb7ZpcCb83 +GbaNFqCbZF +Gbk4wZo1ez +GbzhSEBAze +Gcqn550bZ1 +GdJXvYBRZa +GdKpJnwLBT +GdVS2uWAhP +GdlffAADpn +GeOAgXrn3k +GeS9CZN4P9 +Gen1ieEu27 +GerV5o7bwu +GevZx7t8tG +GfzTvRK4Ot +Gg0BFBSDNR +GgGeTdeAc5 +GgL9Ezcv2Z +GgcAEcOLzv +GhkcjaMoRQ +GhvjATMmKG +GiYX6ma3v4 +GimYCKM9Z5 +GjzrGafpO9 +Gk7BM1kiH2 +GkDlO5BuGh +GlX3msoFm7 +Glm0TKo3Zb +GlwZmqedWF +GmXGzAnOVI +Gmbpagpl2A +Gmy5uPHZ0M +Gmz0d8kIUr +GnkAqPazNa +Gnpb2NqWQR +GoGCJwtB29 +GoH1n9DbvE +GoOXsUU013 +GoyDhXgEPZ +GpcHqWyCZP +GqMDpmiNTN +GqfHDp3GaL +GrHjSCb96l +GrML7opole +Grv3wC9smc +Gs0PvHmgy8 +GsKpOztFxM +Gsoqz7Bi8N +GuZwMG3Cof +GugNjwGaEF +GulJvOHIMo +GvGtuAfLbi +GvbcvDji4a +Gw3QrYWUqK +GwTI4QTuY5 +GwrPDWpm5P +GwwZIcVXpU +GxaoJluPv2 +GxiUccSTzK +Gy5pNrhpBz +GyM3i1kY1Q +GyWzalHjDK +GyiJRnjSyO +GyiJxq8OnO +GynYgLCTAN +GyoPLG0JJP +Gz3Kd8sGon +GzzNZo1qTk +H0I61DQsvc +H0NWzfFgVa +H0dOZ34w7Y +H1QLS1YWXA +H1ht0ZeXPY +H2tQA3SaQ5 +H2uKb9V2Eh +H36B8ye8BY +H4NY9hfOPS +H5iguQ0FWp +H5jJHZ5jGd +H5njwy42GP +H5x144BBvy +H69PijI3Bw +H6i4RMmHyI +H6nOhaav9e +H7U18kFwPk +H7jA57XZgT +H81bD7dI5R +H88Gr6AiZ0 +H8GjxfKSAg +H8gpFYi4Ki +H91ArUd6pZ +H99cGmlSCW +H9NleBT6mE +H9XMYZukCH +HBYd0B42bD +HBzJHfyDaX +HCHHU7fN6v +HCOvPbfjFt +HDQNNOpjHl +HE2wlNSKtJ +HECERVt6a4 +HELENRV4Ix +HEMkJnK3O9 +HERD5LcBpL +HFAOt3tefy +HFCKUlHu1s +HFFcZiuzxw +HFtswkrVZS +HG5L6JQ4qg +HG8aItzgXg +HGDxGqJM47 +HGpA99t361 +HHJMN4ov0K +HHQAP3JDfB +HHVjPmmuOz +HHWSCZcvpw +HHYKtGtHM7 +HHZIzw3iAR +HHiKh8DhAF +HI5oWjvcMf +HIh35b832E +HJtrypXHgu +HJvaUtImcp +HKd0bu8dPM +HL2UZUDLrN +HL4mK3PDRR +HLPTmrVk3q +HLPWRSE9u5 +HM8oI2zCbk +HMTzBR79c3 +HN70u7NYYH +HNkiRmArEE +HNnPvu1iY2 +HNyKbOcUoF +HO4AOUCAAw +HOI4J2GjFs +HOLDcPMbrc +HOXZGNJWrt +HOlampzQtq +HP3DVequAl +HPHfw99ena +HPJjRDRdWe +HQ2QU5rL5u +HQ6GvnXOKf +HQr5nz3IZJ +HR8dE2KCbo +HRadSkQBNp +HRlEfQdEUE +HSJwQd9xIU +HTfCL8YhXH +HTgVKxM7AE +HTwpmNL4gu +HUIAnczWeT +HW98ZM0doZ +HWY6DQsckH +HWYs2jWZJv +HXT7PrCLlC +HY5p0wQa5X +HYJeuP2NEC +HYbiUmaBzw +HZ5kV06EHU +Ha6HoypVsI +Haezyf1y8q +Hb6moALMgr +HbXs4PaTCn +HbgdHReFcs +HbnUyyndJX +HbqIwjjAOo +HcPSYND2Lt +HdBwV9KrFV +Hdga8YBOSC +HduXhn5ctC +He2msv9mWY +HeW84b7Sg0 +Heuoskg8TO +HeuzY5r8Dr +HfDxLDfeDK +HfUGizHkMw +HfVbT3yUsH +HfeaWex7hA +HfrPu6rrc3 +HgQ4DI0RE4 +HgSyvw0Wbn +HgpcUdWH1O +Hgq5JCLbfF +Hgvvq62q1c +HhlBeY7rZ4 +HiFEuAAYxH +HjbclQluff +HjqQMK8tHx +HkVKUB9yKl +HlZhDWtMxt +Hlolo3PHyc +HmDRQcP2mb +HmfhPaC37f +HmgshUQPPR +HoUmPAzoU3 +HoXipMeGaB +HpA9aRmo4c +HpPSM2qTiZ +HpzgMEhNNu +HqreWckDhO +HrQnO0TD3B +HrQt8DZQru +HsAz59GavM +HsaaQ3BAw6 +HsgwrLIwiu +HtJZ5T1flE +HtvyZK7RN2 +Htyb3O77WZ +HuPMZzWboX +HuPVDLFtmC +HvBuIRACVO +HwTjut23US +HwdIpYC5cd +HwjvqqOK8u +Hwk7yen4JZ +Hwm4Xx3auN +HwqvPl4tiA +HySqJKo5uC +HyllLm3fnq +HzAwtNzGTu +HzZsRV4kzH +I0XiDMU89f +I0yVRmsZqx +I1QnJ6zl13 +I1mFl0E2Lf +I3CGP93sMD +I3IpROjnRc +I3sWG0s25K +I4077EYxEG +I4J3iWnbbk +I4krK1RYTs +I5XzjatV5a +I5d2WLO9G2 +I7sirWcYKe +I7vblAzibQ +I86Oml5YX0 +I8hs2KfvJa +I9Fuvj3ssR +I9TAiMPTe4 +I9lEAe8J8c +I9q56o3eer +IAQMKLXJ45 +IAaLziOQBp +IAgqifMahT +IB3it3TD76 +ICKhVAlzRg +ICeO98oiYH +ICqLLb0Rnz +ID26eWoPdw +IDSeZY1Ctw +IDgXAIIu7a +IE9OXO0VR9 +IEYpXbp9fa +IEeGVTjC1s +IFCWV7rgrg +IFwi1NeNzj +IGCO8RMiLv +IGMHjdaSaE +IGMS0pXtbH +IGtKdQU18N +IGvTubr0hH +IGvyLzCKwl +IH6Q4R08N5 +IHMyOWNCef +IIBKrnGtoI +IIE9PqbgeL +IIRBWe2usK +IIuw7qq6L8 +IJIUGbBIqu +IJLC6Bbu7n +IJzImt3kqu +IKVdz6kEH3 +IKv7ndV9uI +ILK5nxA6tF +ILVKUmv1gQ +ILZ4rK56w4 +ILagAdICyw +IMD1aBvOCF +IMKGpayLRa +IMRRhMnhWp +IMhjr5yPzg +IMlDru511c +IMo7RAn1PR +IO5qqM0cZY +IO91dPlZ7B +IOLY4wZgD5 +IOa5LN39Tn +IOdp01esh5 +IOeXE9jedW +IOkn9EKuBP +IPCJEkZx4F +IPCYIB2opQ +IPVwfWlEkN +IPv3NqOIGL +IQ7ad03u3y +IR4TORkutZ +IRG2ZBb0z2 +IRPAyfWNL7 +ISNKmCJVpK +ISagKZndry +ISkz30rv4w +ISpsd9I6eN +ISqfVP4B1Q +ITJz11hd1m +IUe0ifdRLC +IUkGaw9BSF +IVJe9JFBwY +IVbwrFSFq9 +IVlgoMG2vW +IVlvVOkcpu +IVoeXqJqb7 +IX62XACQWn +IYKigqmWG2 +IYNB16WBRs +IYYx1Qqfe5 +IYgDJp5ITT +IYtolE0k27 +IZ4O8Q7qeo +IZYdgCQA8K +IZewQAA5WO +IZf8ohChF3 +IZtLTKRYFY +IZv68NrGrI +IaE7zKx6NJ +IaNTiElBHc +IaeM0rEeFr +IahRnzVsMG +Ib8HGpsPRJ +IbCLDxpHij +IbIVmEkSwF +Ic0ipTum1B +Ic63gLZDQL +IcNSDN8Kon +IcRLLYpTmr +IdDbB5uuai +IdDl9QjVtc +IeCuZIRyyb +IearEwvKQV +IeeZU4Do3V +IelaleMCZx +If49PWHowH +IgBqzSFSir +IgTQ02Hkje +IhAkeSpSVz +IhEOq6MFRw +IhRC1Bp0ci +Iht0HADCoN +Ii17iCXLZq +Ii680Yg3Fp +IipaXiN4jh +IjCAytfl21 +Ijgtn05lKp +Ik4WqYWJ1j +Ik9UmiPXQM +IkRPn16NQ4 +Il5lQM1ZRS +Il9UW3F4bz +IlX4d4DPGI +IlhobrVNXU +ImruVYPN4c +ImxIaKsADb +In80pifpbh +In8Ic0Bzvb +InEbW6hXjq +InZ7SYyx6L +InmaQYnhJP +InnTyIsNeo +Io0ENZmRTe +Ipz2zB5feT +IqOeYnsvXf +IrZJaZR3Yr +IrlBwVKiZY +IryjlAMXeg +It6JEfk0hZ +ItLFTKjfgO +IuY9kj27M4 +IulJ7lZZlV +IvLGgtDZpA +IvXjIvl8WZ +IvYTLTh8d7 +IwemqfILPv +IxdoCfc22t +IzIBtGcWib +IzQO2ZRBCl +J0T0cm8Kek +J0YoNItArD +J0xnVLMIxF +J0ygw2FYOh +J1KmDA6Dk8 +J1aN0OLXyC +J2HmeypBsE +J2JJ0nH9IN +J2mT6LbI5X +J3guPsA4fF +J48Qtqn2Mj +J4cuWN0eN6 +J4pd40Z6Tq +J4sgdOEBUB +J5hE7Iio4y +J6h1ygrJsX +J7NnwPVTud +J7SN3t9j6Y +J7exPXR8pR +J7fZrbhXWh +J7q6kBKGVK +J8I9PaWOjL +J8NHPWSog3 +J97vv8irdE +J9iWqgBFzo +JARnYeZA3r +JAjxC6z18c +JAldWnk7Hn +JAxNHb0QQy +JB2iTYT5bk +JB8NoUcHYl +JBCNCE1ChQ +JBHi8Uz4MD +JBJSV7DAYN +JCDrTV5Sjs +JCT46txtvg +JCfjSZu4zP +JD5HyXdfGt +JDGSaT2uYy +JDIFjizXn1 +JDZFeAlozC +JEatxXu4Zd +JEg5BDxC7l +JElYWSbM7q +JEqoExA4qt +JFZnjiDwEy +JFa0q15V1r +JFivg9l5rs +JFvMP29uTJ +JGReSX64PL +JH9eKO6OMB +JHHjlMmQFO +JHVSrNmKJ8 +JI8Vb028ub +JIg9O69G2u +JJ57vObUDn +JKWABsHF9i +JLNCKGha9C +JLQiSTSuJn +JLSgn3AhtL +JMZYoKQk5x +JMgWxcoS5I +JMofa8zKFj +JN2UM85uft +JNP8BOhoMg +JNdIilvnQv +JOIcpcYWJB +JOzVa4uwto +JPF1Inri3H +JPm0wfbPeI +JPpzLufUoJ +JQlTwrahhx +JQrymLUNQx +JR0uX6pR8Z +JRflwyCnRy +JTZ6g5uTtp +JUN6AVWjMN +JUnaK8tDD4 +JUpORZmvMA +JVMBc2yuhH +JVOFgpa4um +JVZ2LxxAsI +JWMJw3SylP +JWYCvI8Zf9 +JWeHWkZeYk +JWhzx7ti4L +JWvZVZBzJv +JXMGSYxmRk +JXnECnFq4I +JYJSE40SMq +JZ73qVDzFh +JZMB26Wdp2 +JZRnEytWcT +JZf8mXIrh7 +JakuzzZw0Y +JbF1i3TurA +JbRrp45EWv +JbaFMB98V2 +JbmNxm0JGM +JcerkgJgib +JcoCr1oJEI +JcwtOYdJZX +JdcsSrd7py +JdnEffFYaE +JeQ4MpobVr +Jec2wYeHa8 +Jf86Zs6m3l +JfMFdKouzN +JfVVRyjfT1 +Jfk2BTlMzz +JgEhVQtSZ0 +JgLkC454mM +JgkMGjsoek +JgvpID2hsk +JhH4S9TXkA +JhOdJp7Inr +JhRKN0UfTL +JhSHX5kDTU +JhmnnfAeXE +JiJJnDB41j +JiM56yTNWW +JiXeHmGbvn +JicNzQxGYs +JjZNAJjVzW +JjgfcYdv64 +JkNHXiP1Q9 +JkV6zb4rYA +JlyvVov07D +JmN23IMi2P +Jmq0GRp1xn +JnIpWbWu5f +JnNh6s0VMA +JntaqZxmWK +JoFmKrjAUy +JowPi4hNt2 +JowXg30Tbv +JpPyJ7pILN +JpX3Q70nAn +JppGpounc7 +JqD0xxETMl +JqtmWrRibw +Jrqn785ypW +JrxHFzQ4ER +JsRcA1w5Xk +JscjNZV39C +JswuFegAG4 +JtS4xoxFbM +JuI29MRHUu +JusaJuOHoB +Juzi3cMYE1 +JwWgBLe0N7 +JwcyWALyKt +JwwwjB2WlV +JxI7S0gFaj +JzP10aVqY1 +JzeeQFfcE2 +JzhjBgEIlT +JzzDyluuum +K04O72JMR7 +K0IC5wdWMU +K0pISBuGAr +K0wAtHoWES +K1SHLZY9HV +K1p6a8qGSC +K2OhlWG0fO +K3Tuz59rGi +K3UilSmgiE +K47qORJoSD +K4w6pXjevQ +K57BO5a6ph +K5o8BBX1Z8 +K6cpgUqtn1 +K6v5MzG3FF +K7omdFLBM1 +K8Pb7w9g1m +K8Pdn7HIiM +K8VR4PycAY +K8cHTUGI8V +K99rUkY8dC +K9Uyjcawf6 +K9pWX0B7bu +K9pWiuHx2H +KAqz57nlUe +KBWyv0ri02 +KBufVlicx1 +KC1mtpdKb0 +KCsuC11uGd +KDQY87V3Fq +KDf2G3dNzd +KEMVSCTFX5 +KETi8aQn67 +KFMQeZJgVi +KGUesj3VUq +KGgt6ihEhY +KGs1omcOaa +KGssbQFZKS +KGwkTCquCi +KH1eqUQlMC +KIxzPideOW +KJ7rTnhNBN +KJcdHfId47 +KJgDyNq11h +KKxCckyhdK +KL5DLCFVwd +KLI9BJuuXz +KLcWZIYJCb +KLvNeVCSrB +KLvtmuSj7s +KM4OnIfvfq +KM7K5OoHtO +KMdgqyOehq +KMea079UXU +KMvzkkZ8ro +KNLKAFGvLI +KOSoacR63G +KOTYSIlgLG +KPM1KQhO8Z +KPxXdz80MB +KQKG1gXRYI +KQbfQ1flES +KRMqrlYVqI +KRh7x6cKAK +KSfZbwi1yg +KT5BuMd1zl +KT6WjEAtaM +KTShKWObys +KUEKGnAfI6 +KUkbO8wo20 +KUmz7J1H3P +KUvEtmpzzz +KV1pxmaytB +KV5nEQeatN +KV6YAMDeeq +KVlAjfuxOg +KWkenD0brH +KXZTLnPaAx +KYlDDsMN79 +KZ8lZCnEXw +KZJ5yVhsZP +KaO7hiSYaq +KaOLriJJ0W +KaPYF0gLSA +KawFU70eTS +Kbf1Ja889b +Kbn3vK2ZjF +KbsnMUhkkj +KcYBrex7wm +KcchtIQtgd +KcdZ41CeqC +KcpD7hDvDh +Kcv5NyAdZu +KdrWOAdZ8J +KeQNSf6xqr +KfIM8OPXqT +Kg2EmUzvqk +Kg551UOiyf +KgIcgdm0IU +KgQHBDFEve +KhA0itNFSZ +KhhURKTX78 +Kho9uFXcWM +Khuj069wfT +KiNZ0aIZIf +KijDxK5eam +KinuE8IhVE +Kj1jKWVSpb +KjnksUL4hG +KjwZEmHjUB +KkvyCHvU1t +Kl1TgFTHPl +KlFzqExOED +KlL3YaEcdY +KmJ7j0Srpm +KmajAY5oLH +Kn07gD0wCs +KnTGMS0EN7 +KnZB3TIDYW +KneiHnX0nD +KnzCRKJxnR +Ko5iJd8iZ6 +KoO2erwphq +KoVMsT47lW +Kp8UUVtR90 +KpC6H1rQ8M +KpPekLZilX +KpmEOBJwHf +Kq3SMrCTRn +KqCb95WZH5 +KrE9iHDN59 +KrG3H430Z6 +KryEVDwBkS +Ks4Bl4ycH4 +KsK6bQAFZE +KtArxtRI6a +KtGhVVb2ur +KtLTfYzTRe +KtzRN0pBkB +KtzgMuhchi +Ku40ibrK1c +KuQnziGi2o +KuRDuuKtvy +KujpvaVHrH +KutHO32Qpt +Kvv2NfWkgG +KwA6NO6Ini +KwdiWZwyks +Kwno7sZmaX +KxAdmqPDxu +KxDaXFkdN8 +KxMQjQhrqw +KxPFO1pi1i +KxcGBXp3Fx +KxfTVNdd6Y +KynVD08Ot5 +Kzdf5l49jk +L04RBzlG5v +L118hHhpfO +L1ukn7mCjI +L2AT7YT2gL +L2cSTRx7k0 +L2rQ7Y9YJN +L4GCF8ZFNY +L4HwXF6pML +L4iH9p4VdL +L4iMhSWEyK +L4zZbyd5Ky +L5H8Oqtwdz +L5nP4wTZa2 +L6NsdAe70w +L6XXWAptbm +L6wkVHOlPz +L7CAMDx2nL +L8dB6H9klI +L8lpRCCAYm +L911bHQBvs +L9PxXlv9Yv +L9Xd1NeOKk +L9kA71FGtR +L9uEXv2NQh +LAESsHG4E9 +LAHrcCfzLw +LANx8ylzTR +LAwBtxGJMD +LB0kQE96So +LB6WvEo7K5 +LB70EJJZ6U +LBGhewMw0s +LBfy028hr2 +LBl911nWp6 +LBqemAkmlg +LC0zkqYgU3 +LCDTF8qKb2 +LCQme8Xcvt +LCknSxHgp2 +LDL0K1MviQ +LDWVKj3sMq +LE0EFuyRgJ +LEfNEXa6Hn +LEzTHMKPGP +LG0p7ZyP7E +LGHXNWghU7 +LHBPHiyJLZ +LHel9wLana +LHtjNVh67i +LI7KLVQF8U +LIfe0WHKkv +LIp3yxxgwI +LJenEg8TZG +LJoWO6y8YD +LK4NCNoJh6 +LK6728nu7q +LKm3MHeqR2 +LKn0wn8gPt +LLG4wqfdvn +LLJtIvokfN +LM4dl84LM5 +LMNJER0YJS +LMbfFMEIfE +LMwnLXLJxO +LN4xVXCA2l +LNGZZopPJY +LNU43Y8dkG +LNY7LdP34s +LOdONWXZbH +LOqwpU4r5l +LOuBuDNl5F +LPIKtEcoEt +LPkHBvfU6x +LPynT36GF3 +LQru0NCtdd +LRYabjk4DV +LRkKXv1sJI +LSIUkr6aIp +LTfLelTGXg +LTftmLTFE0 +LUIhk5CJGV +LUWd7uELCC +LVXa15J77R +LVlu878K5O +LVrY34HUgD +LWSxLe9Uwg +LWnEW54YdP +LXQgI8zWoB +LXeJyRSfaq +LXf1JT1TaK +LY15fPeWt1 +LYfeBfr2ZA +LZFUalyZom +LZjZ4da7iV +La1XWUHlHZ +LaAEt4ts9C +LaDJNuECBH +LafCxyXIgz +LdHCMcx4xS +LdZm2NS3rx +Ldz2u0sDSG +LeL9jLQ583 +LesXQH3v6e +LfBbbhi2oZ +LfLm3ZHkDR +LfShvkCEWt +LfTFQC5wXu +Lffg5PP44u +Lg9aoJ3GoW +LgFegMHPP0 +LgbuPPrO0o +LgeKSjwv1v +Lgf8JpEHWd +LgpttbaL6y +Lgsk0zwqah +LhQ7kjFN3K +LhSk3ZOPhk +LhiWBpaXmx +LiKvVS3Uiw +LipoHhZuDM +Lit2qv1vDh +LiuUWxSTXL +LjGPjT34BN +LjfS0NaIHk +LjnSDmTVJB +LjpYHL1Wbq +LkYPuzvTlS +Llc5EeCN7q +LlfbMNxv9y +LmC3jZHyZ1 +LmbKlgeUg7 +Lmj5WJzfYx +LmpEDbC1mp +Ln8T1mR2k5 +LnBLVLAoWU +LnFPOLOPZd +LnUp8PjOMz +LncMCLNS18 +LoPROFxBJ9 +LodOMSFwze +LoyziLAUxt +LpN7jSHutI +Lr1s6XRX3u +Ls3dwo56U6 +Ls4B1cXQKk +LsNxGxvw8n +Lsi2Dsz7en +LtVXfyuZNQ +LtVn6zJrWm +Ltoan6BXFx +Lu4sWURVqS +Lu9L6IyycJ +LuEGXcFvP2 +LuMePGSA8m +LuVPL08iQV +LuetQUBS3g +LvqltY5zbG +LvuZGjgPBm +LvzWPHsqXT +LwlUlg09KP +Lx0a77Yalo +LxnMJKPyVR +LxnwFysvif +LxrOm1HMnx +LyH9Yh6C6l +LyKEX5lyNi +LyMiUZSyrM +LzJQG5VGEj +LzWzDdfflF +LzchjBqpf5 +LzlrYsX1Q1 +LzyGWVv3BD +M0J5IAVPyR +M1kaXXC32Q +M2WEMuRVff +M2r3dbmTOp +M3xPbt7kmv +M3yaydQiQw +M5D2vDgsI9 +M5FzfnrC4U +M5VhgWqOfb +M63mLOU6N5 +M6avj4ZEpD +M6njGHH8Vw +M72usvtEeo +M73EHRax7V +M7pTy785Gu +M8E7Bgof6J +M8XR6LUk9e +M9M3nmLpbX +M9a1ktfkhc +M9sIr1wCwR +M9sstvwmtR +M9t2J17TCM +MA7GUDzEqq +MAF4ABTwwE +MAKswVwXWs +MAQNPEFiqV +MAUVTCEHun +MBMgs2Staa +MCJm11dpov +MCuTZws3BA +MD0lbCTV5b +MD8sDc2DVt +MDXA8qL3uU +MDatGNtcvW +MEdvIdi4Di +MFEAowW6pc +MFW2whU80s +MFqr6PToQG +MGpwzMoZO1 +MGu9pMhvsV +MGz3HpHgRf +MHiz0GmGi1 +MHlmqvXNHG +MHpet0RGr8 +MIvBAvDCxb +MJ9HXosnOL +MJdJ1aY1OJ +MJfhZiiGaD +MJoOsMPEoD +MK4A4HiTCU +MK6zgN4jvA +MKAjBFqdEG +MLIV4ydyGT +MLWz5naRkz +MLlSVhibc9 +MNFXx4ytqX +MNIiCbVZTc +MO3M8xKzef +MO4XI14sam +MOWyxsynQm +MOhoSOkvYO +MP15zmoofF +MP2kUmypVm +MPSbUM5kx1 +MPYY539bOT +MPbL75MNxy +MQ8WKWNAle +MQDFXg0jb3 +MQTNIHU6Jf +MQrECabRGL +MQxIB5SamC +MQzl07XC6I +MRK5UG0RLE +MRTQds6FV1 +MSA70RjWPD +MSAl0478Vw +MSJtAogsXY +MSUNKGdwUl +MTFSHHUJR1 +MTJ13yH7hI +MTMUr3jHLJ +MTwW9JCD9B +MU1wfTgQug +MU2GhcswqN +MUf8w7jhLn +MUkEubSZaH +MVR3Drk5kr +MVtvla7InQ +MWDVNPPlsc +MWPlHD7QZC +MWQ2NnfsC4 +MWUFAF4OOc +MWXcc4U0kA +MWtNENb1Iv +MWx3Cbq1Z4 +MXcSg1fHJb +MXxVclyKBf +MYAxfX4LzZ +MYcScoCslw +MYnnLGJkZa +MZ2XtnWuIw +MZEpkHZvHZ +MZNhABQhFj +MaBbUnkVIx +MaSTZYkgik +Mb75TxRvTb +MbQShMFZ8J +MbbDgwvutC +Mc2k3uJgzU +Mc6AykkbhM +Me6WqZdIe6 +MeCivDOcg8 +MeYCtuXsTL +Mf6cHmINdq +MfGyk8wnAi +MfKwZEtn60 +MfYKdeDfgO +Mfi3wMlinQ +MfoWE3sQyg +MginzLLWkm +MhAHuQjCge +MhcwYI2dv8 +MheFYFT4FP +Mhwfb1AS0o +Mi2VhsL8b1 +Mi6Vpggkw4 +Mi9Q5BeTbU +MiI3A7IFgh +Mj4FabnAAu +MjA3vd4oRk +MjsiillZ83 +Mk3WEYbF38 +Mk5HM37PSq +MkKVCDKaNX +MkWHWK4yfB +MlgMBt13Qi +MlhSnw1pOx +Mm2I3wd8qY +MmCGI2Zu2m +MmPPTSYzB6 +MmYnVkZhMW +Mn015E0xqc +MnGM7j8OFl +Mnh51flnwy +MnjfGNnABg +Mpca3uaQu8 +MpfGL5QlkU +MqCqqCzmlS +MqrIObz0tz +MrVb772t10 +MrZ6smdUIX +Msfm0VPWph +MsrcmdCUff +MtXozPVEEY +MtdFIVpcUV +MuSddZlHdV +MuogHD6LWT +Mv7I6FMVtD +MwOgfEh1LT +MwjMeBKnqg +Mx7Q4Zy6R9 +MxNVYBThvQ +MxrkUtJmfU +Myvqn81E7d +Mz4pubTKbF +MzLZs82sRb +MzRRWxAapb +N1LtfLwQBQ +N1Z5DLapZv +N29nxyjyI9 +N2ERSVIkjF +N3VaVlMnH9 +N3qpAsFpxg +N5ccgd9QLP +N67vURExUw +N6YK6t3Rq5 +N79FUaRoKC +N79q7XTfZz +N7AsWQlGvm +N7MbbLJgWo +N7kCotfLQa +N7zKaiCC7n +N85jSAKYl3 +N87aCMZdgj +N8I5uRXw2J +N8VQzrV7tI +N8oAym2y2R +N8vSy1hmI8 +N95mDGVgmc +N9kQfIb6on +N9t7aPZVgl +NA5FekkhFS +NB0cKqaqfl +NB4gX8CJeA +NB8PJxLiXN +NB95EJgQLQ +NBNUAl3oWB +NC60Z5WMgS +NCLSZ4OZh8 +NDHNfgr4XA +NDqo1aVSds +NF36T79F21 +NFAWCNiaIF +NFJkftMaVX +NFReabJMQ1 +NFg2sttIBr +NGuvU8isJ0 +NHALclvl2l +NHHo5iIjhB +NHSix3UBYx +NIrO53rNfp +NIuFprFSSL +NJKYJa8Dkf +NK2LokvnMg +NK7qZ6VEOM +NKbwYchQTe +NKgfVDh3lA +NKnWXPfLQk +NLJKQNjBch +NLJx3oQdXB +NLvw2LNK6A +NLyMmkRz7R +NM7lMW8jmw +NMPpUj4NEp +NMWa1UAbkJ +NMxlJJcyh8 +NNc8JOSCQU +NO79759avA +NOQfCF83vd +NOU8oeZ4aa +NOkP2t0hxZ +NPD5Xka3ak +NPZD1sNRNV +NRCxTslmsU +NRz84MsiLl +NSMfByiazD +NSSnVMjPna +NSmiyjEWkv +NSoHaN3wVz +NSreXi6GQU +NTB0NnTwhP +NTJdVep7o6 +NTRqsxiF95 +NTVEaSIz7M +NTWJ1hco9v +NTghBmVcUK +NTqCAIPVBe +NTtri0alur +NUMPzyt64F +NUOQ1nKuvJ +NUXQvWiGIF +NVBawXDZ3Z +NVbF9j6DUP +NX6NaTTCN2 +NXkspCX9NO +NYjWeNow2P +NZ0p7Ea4NM +NZ7Db3jgnL +NZ8ZDA9GhH +Na53eqzUCY +NaScfzA5E1 +NaqPspF5Kf +NbVFYogfwq +NbaQ9BuW1w +NcC5JWRgvv +NcIjic7kqA +NcNglkun9g +NcYIjVDl4C +NdJVDmLyFw +NdMCas1po9 +NdplnOFArc +Ndv3keG1Iw +NeAjzR8GNR +NeWD5CZBjz +Nfcm9GvPN9 +NfetgVkcJH +NfkoMMCWjU +NgC5szqBDz +NgINx9Dx0f +NgKKc7mUyM +NgcdeIpfJr +NggOf2cXkf +NghlOz0LYO +NgkG0vxXF4 +Ngt0zwWBJV +NgvSmqTD7j +Nhwqib7pmp +NjCgh4CGLp +NktSJEQMNo +NkuLhzCz9D +NkzIMZLn4T +NmFrjPiHXE +NmcmPTxi4f +NoEyJCdneu +Noj6CirZdI +NozteuGIuV +NpI9jx4HHu +NplsC7hNxA +NqDSWkwzo7 +NqZsobRYFz +NrWQ4r1k6p +NrbrZvzfwe +NsQEwtaiWf +NsayuKQbaL +Nsr7lxpcRw +Nsz2w03BB3 +NthTNhTDA9 +NuYwfkif6C +NvH5uA1krk +NvNFOS9Y9B +NvdaLuTZp0 +NvmxGPin0p +NwRdXRZjm1 +NwiEeTSamq +NwiGlhvNCB +NwrKwo8iuB +NxqXBPhUp8 +NxsXgEg15Y +NyDzD4Dexk +Nz3VjUiqNK +NzSYNji3W5 +O0ARozX1rI +O0EGYC2L1m +O0ZWBg1j1m +O1awqkiUDJ +O25dXok8oV +O33h2MSEeN +O3KzM6Adhu +O4A63hROO5 +O4Bcb30OUp +O4qvlsZNoR +O57mRyZBCC +O5XVOcJ7TI +O5nl3eXFUt +O6QCyd0TXt +O6SsMnyfuy +O6jgo9e0ra +O74aYTyb3B +O7TU6DSvT5 +O7kELjGlY8 +O8smLKY7RI +O9AaXumux8 +O9GLiRJmUn +O9dRcvBKLd +O9i3GqXsj2 +OAMEpKucjt +OAsUERGUlM +OB1k78IK2k +OB2LomIMlB +OB2XKKj1Fn +OCIApFxQyS +OCZb5uWDsh +ODcakv9SzU +ODnblwAX1l +ODv240rG8W +OE8WtYYk1E +OEiTCMkSVE +OEilUpD0Da +OF4S7ZhsxJ +OGiroRoCWr +OHBEHW7y4u +OIt3ezkm1h +OIz5Pfrst2 +OJ0xrLYGTn +OJMeeSXoTD +OKd5REO6o1 +OLK8hQncd7 +OLStzCu8Ib +OLU5Q9tCeF +OLmWII2Uin +OM54fK2bNq +OMBEbL6sZZ +OMLiQ2DP6p +OMlV8sOOVr +ONCy62h9xG +ONQ2d3RIde +ONjJoeg8s8 +OOTLk4uvsr +OOVjp289W6 +OOXgIMkVqB +OOYm9mVFuH +OPJaDDDS3Q +OPX0U68zF5 +OQ4w7f6kcL +OQ7a5PsOAU +OR46cuKF0q +OR9o5sptAq +ORjSfPd6XO +OSEEz2Dmlw +OTP343q4yy +OVDAGJoA3q +OVNru0o5RJ +OVoAVjm04N +OW9Ka79Gq6 +OWGgudJKid +OX23u5HPsT +OX4UYamcrg +OXJR57zXIs +OXSAORKOfX +OXUrJfYqN2 +OXsHavLHh5 +OXuRkTRkop +OYa9P4UuBI +OZ63EC2gsa +OZuB0Tmx9b +Oa267ignKn +Oa6I7kAKG9 +OaCcgHUNiU +OaGP5nyg8A +OaORdJWUAh +ObLpcRmb5g +ObZeJBV3kO +OblKBcKuhb +OcUUXsobme +OcX3SgHQ6M +Od1HxIDn4J +OdLH7bEsAl +Oe9Nmv7tbQ +OeNTvCQ1jh +Oea9M8XO3w +OejbrPtua9 +OfKVQixOgx +OfQSKBZiOY +OfZjUsffWw +OfoIzWL8Z6 +OgvqRXMcyP +OgwilHnF45 +Ogz3pN88nc +Oh05djuLN1 +OhR8UQNxol +OhvsfhZHxm +OhwYA76OyK +OiCXaRylnV +OiPpvzGkTH +OizRYF05R9 +OjR6lqJOaD +OjWaZRVluM +OjzmihbeCK +Ok1FaLm8w2 +Ok7L0iDoZd +OkE7EZfqUi +OkRET7zHxy +OlJUx7jtnR +OlQtcVRfZE +OlSeGqxnQE +OmZEZtsaGj +OmcWCgYnhn +Omk7H5cPrz +OmoXw8d5xc +OnHGj79kQN +OnUEmO6XfB +OnXoWMMsLW +Onf4sSCM5y +Oo6bWJQPuA +OoaACal4lP +OpmbjYXjPl +Oq64uIpI1R +OqB4qVQXE0 +Oqd5sWIwlC +OqpJxZ6ww9 +OrKrDrl95z +OrL9YmgJPj +OrYkWEY4hz +Oryy723lRU +OsI3l8Dqz5 +OtEx0Y6ZbO +OtIbyAn56j +OtIngxGlXL +OtKZZJP1lr +Ou2tiy9S4j +OudAMrZbVc +OuhAgtqx6C +OupOxYmM0g +OwE0McG759 +OwNEouJKoM +OwYKrnMvpV +Oxg62Yh8gj +Oxo6bNm9sD +Oy7raWjbu3 +OyHI8amq08 +OyKs8TjNNg +OyY0cDRe9X +OyZWk0euya +P01xwKYQ2S +P02CiQI96J +P0ScnVDVvY +P0XW845vrc +P0eoQwwxwI +P1HVi20WTv +P1KYmcJMLD +P1pJc61d1U +P2zTdAcd67 +P3WEdCTwJ4 +P3c1fXtz2j +P3iYzEJEUy +P40kgfBDbG +P40x3iU9dJ +P46JJa1slb +P4lnco97Ge +P4tCAxIxMD +P5ozr1z7ms +P65ASh95Ga +P6O38Sbp60 +P6Qv92BUU2 +P7a7NYYV6a +P7v3t1NFl3 +P7xO9vP1ay +P8Ea0Qar1y +P8T0OUqkW0 +P8fmzIVdL4 +P8ixBAJOs1 +P8tjjpK5UJ +P8vAYEmpYx +PAH6yvmZvG +PAIA5Iph8r +PAhuTBhzcf +PB7G8ahAJe +PBVhYwEaTw +PCNUOgmfW0 +PChXMlvbQr +PCixZDfdhQ +PCvmqOFNbK +PCw1MKMGVm +PDE3cGTB5h +PDr0VvAUcf +PEOarx4H4E +PFkD2U5WgB +PGNnUl9ktL +PGSCVwNZkQ +PGrMMMkqvP +PGwbluCYoq +PHLDPfHZ8G +PHUhEwnJvF +PHoXLdJlCh +PIGSoTv9mG +PIiRliUj9T +PIstmVCs2e +PJ93VmZSli +PJkgeGKWl3 +PJzRn9jmj4 +PKPIQm0sZh +PKrgY5xtBz +PLNALg8nUs +PLiVS5ApH0 +PLnLyNWB2O +PNJ3ZbQVnw +PNeSguhGTP +PNkiPUdUdD +POVPjsgly9 +POfz5Og7GH +POg55fMk4E +PPe15jkt8g +PPxDn4f0zf +PSX65zqUGN +PSpKkUoWF7 +PSrOEKITj3 +PT2EDnTNow +PTDTJolZXp +PTFTdz7ryA +PUM2GXl3QW +PUZHRWehhz +PUm0WTZvnc +PVbqY5OahV +PVsSDsMdwk +PWBRcHwpad +PXO10sPfkA +PXZWK1Ivsx +PYotSpHxRX +PZ97xDHFaa +PZnZmU1yaE +PaDVXF4Djq +PaDfyAyxTD +PaOVRHs6Rd +PaRL21Nv2p +Paw3Vqw3oL +PbR715uraM +Pbdkj8omyj +PbqodZOpPh +Pbzr6tToat +PdFvyhQCuW +PdH0Fkks2K +PdVVmUqsnE +PdhnuGdI4k +PeUWouAAIQ +PehyhvQQed +PfA9BpT6Vt +Pfz5J8zggP +PgN0sJJsoz +PgNDLAbZzK +PgmVRaXkFd +PhZxnOIKdb +Pha8KjedWn +Pi8Uwm1SMf +PiCvoxcfkl +Pjd16f19AZ +PjzKgqqC5X +PkhwyScsF6 +PkvyCdZpAl +Pl7Z78Fegb +PlYgf7e1Ee +PlqueenFuT +PlyWj0wWT3 +PmBjQozNn7 +PmNB9zzkYM +Pn8EenrMty +PoDIWs8W4e +PoGn5LjanG +PoRGGsRvoh +PpLlRxjL2I +PpahaxLyfC +PqB4WmcVpT +Pqd9M6CD8B +PqlE9DPB97 +Prn9YBTh2E +Ps1fi7ghwC +PsDg0h1kJC +PsjbbIqdSP +PskFTjsZAH +PtRLScaQZ9 +PtbAlEjAU9 +PtvhZYLXAq +Pu3BRp3g58 +PuRKJYAlGw +PuklhZh3Zl +Pun6pq3NwH +Pv2bmi4BUx +Pv8rSCGJXT +PxWVzNVurn +Py0uvsf1k6 +PyGkXHHEAf +PywrzHeH1m +PzGCN3n8Vd +Pza7r95Mqs +Q00d0auNjZ +Q0ukKIohMo +Q1IRrlMfI5 +Q1nKhg3vIP +Q2j5bDgR2f +Q2kNQfZjQX +Q2mKxYJmBX +Q33b5L4kOE +Q3R64W11n0 +Q3eIAw5GwP +Q3yKXqJw0P +Q475phMbZr +Q4Cd0wZ4Do +Q4Qtlxp2xD +Q4XNIciCU6 +Q4YqBtCNtA +Q7SR3OQS0f +Q7u8zAHOSZ +Q85NzEM9LV +Q8DMrjgYeY +Q8HwZ9Wx3h +Q8Qla8B9bu +Q8Tjo6jwdA +Q8dD0RUTqr +Q8gliQ1uLg +Q93zDTiurv +Q9aB13Vmvf +Q9hv64BGGF +QACC3Yjzlm +QAHyZCOVSc +QASZ0nCD21 +QAdSGU3b0z +QAeiiPL9Bl +QAf0vCzMQ7 +QAy9FBsy7Z +QB8sZ7nRWW +QBq987Jt0Z +QC74oxJxRg +QCNO8qavIR +QCPMgVWEU4 +QCukabgQMO +QCzECECnkI +QD8Bc4eYgm +QDAYN3U83D +QF4wFsyjXN +QFE07CZwuZ +QFzg8nKbJZ +QG1HtDqnp0 +QGGtFRBUCc +QGhZhXYu9l +QGlxDywLlN +QHMLjwTMh7 +QHOgPQZFwv +QHj00pALDm +QHrwG04hIy +QI10M7nUEm +QIHQWQPQKe +QIPv0zN4en +QIpAwgC1n2 +QIv19PcuxD +QJ0rlck3Kc +QJ3ysIzK0k +QJ6ay0cqbT +QJ9jaLCqxg +QJNO8OUCQA +QJTXo9KCyF +QJgAsa4n23 +QJkXItMq7H +QJrCuDxfaH +QKPA6xbHgx +QKyHHVvrDE +QL0E64MsQj +QLNRpNtRFA +QLVI1etQ0Z +QLWVRPK3EY +QLXilgAfOY +QLwTUBHTAC +QMh6vribOy +QN8rbdD0KK +QNq0aNY2Aq +QO2hYMnuTm +QOEhSVWh1d +QOSfHQwzGi +QPb70za2pL +QPf0CaJfP5 +QPfNBeYMaZ +QPj1ZLoj64 +QPqxK0ymBR +QQ1BgAVc9m +QQBXhJSnKC +QQizxJpHcf +QQma66GmqX +QQw3cjqy7z +QR5ON3WrUK +QRbHRCYtPL +QSMluvzvqH +QScrU4ognU +QSthCJAOCg +QTfqtEEuM3 +QTmYNtMWtP +QTqQjK1VAV +QUkTBejKKm +QV4D9TxrtS +QV8sq46tiQ +QVIhUhfHcX +QVJRb0nbcB +QVMqK5nlBj +QWPrJoumsA +QWT9YwCSgF +QWYS0Ew3LY +QXLfcq5if3 +QY0oPZRjef +QYPqYHJ5ow +QYSfKdNaxu +QYV2s3A7uo +QYvJKvKXeE +QZcSTzEvBs +QZp9NCBZWf +Qa1OFycT09 +Qa5Xpea14T +QaQlRpg1Yj +QaSsUVLfsz +QaX4nPrwXj +QbHgUWQHbN +QbL8tEZYES +QbLa8X3j8f +QbhkEyrvH1 +QcCG2RgAMi +QcaMy4lBko +QdJDBX3DNB +QdbAgDDZA2 +QdpL0M8BCm +QeefZot5V5 +QeuwTqwc1d +QfVMPA7OYs +Qfluvm571m +QfrX2GPjks +QgccDJeSBd +Qgt6agb952 +QhDnSZoDl1 +QhIffoDswO +QhY6Cd7E1S +QhYxqEXeV0 +QhxGU1ZIRW +QiCynm72ve +Qiot9u93O3 +QjQQq7cAA0 +QjnqxAH9Fu +QkXhAGSx5U +QlANjcljOt +QlQx7z1pGI +QlSCdiLrFC +Qlh6HFvJGj +QlkwAkcyvb +QlwLBqNP0H +Qm4GCdDdic +Qm4j9ZdRa4 +QmUANBKU3a +QmbFtHEnmi +QngRo5PMib +QnlynClxZe +QoiGKwYcMo +Qopidvi9C4 +QovPAxCSe8 +QpdMaW8U2v +QplqrEqvTI +QqB2hjDVLb +QqCvihSXMH +QrawdSphMy +QsKHYYkZZ0 +QsclAgYuu1 +Qt3rUdSzmF +QtZeaYxvfP +QtZzY9ahwU +QtseaBO6Yx +QuFSkAwEb1 +QuN1qo5L57 +QucDUCFu4F +Qv8brHQMc7 +QvJ2dragye +QwOcpKfZoZ +QwoQODyPML +Qx7m0pDZSY +Qx8i48DmfC +Qx9kCy6TOd +QxFKyljdBJ +QxVSSqsLaY +QxbUSXEFtu +QyG9hNJNOh +QyGmsZ8g03 +QyLr8FvJNA +QyZts8wJHF +QzFSf2TSaP +QzZLJC7epj +QzkO9Eyf5N +R0Gr7K2cWD +R11ZLjtY6j +R1DRiEIRPT +R1cuiiwL80 +R1gZbIMIw1 +R1nr6Q1Oll +R23u9T5lhD +R2ONjJnuEm +R2SQOlWrRt +R2cd0kHkBK +R39GnxPo3z +R3b1a3NJTI +R3dOV12gqh +R43LlgYXDV +R4W2ZOxrfd +R4YZscOeIi +R4a9uaiRuU +R5YiBDEcHA +R64jwQ2NzL +R6BUkhG1TH +R6liJNMUIm +R6ol65Z9Ti +R6ssC83ft6 +R7FVbY1jsa +R7fU7sgljy +R7ykbdJlB0 +R80B73oej7 +R85RAtdfsQ +R8k95BFs42 +R8xCBiI8Va +R9bskVCSAJ +RAAyONBkMP +RAN0y4yifl +RAgBo27SRs +RApeMxMFMW +RBAp9Cstlk +RBly2p9zTj +RC06C95gdG +RCU6kPOP5x +RCkZmLvrr1 +REUXQdoZtS +REWid6lOIS +REdGH45QPU +REf3MniSiP +RFABCprfGE +RFCVG2EzDO +RFnPPBsRDo +RG0OHHUuK1 +RG2QHbU4pQ +RG6fbWTIwA +RGE38DQT8e +RGS3P1DnLK +RGuPkxYiS5 +RH75866VUe +RHso28ixOQ +RIxYQYQR3b +RJVuS8t6ip +RJovXbNbIS +RKCaq4YChm +RKYUkussLG +RKYp9o4p8d +RLILeRNUEY +RLRaomyeQI +RLwMLCFh1b +RMu1im2611 +RNflzpmWoq +RNr8OclgrD +ROaxQNY4vJ +ROwj687GsX +RP1G5TBVKa +RPD5cKQU5X +RPbCWHEi6P +RPfdUF3TQt +RPrgz79Cyr +RPsydHGwFX +RPw3v2mYw2 +RR3HqZO2yC +RR4CgOUWwp +RRrCeA03ek +RRrzcDZaRH +RSVpmOZFTn +RSaR8paNGf +RTGl2BjG86 +RTKHnbbavW +RUS11FIz0N +RVBqdFcgeJ +RXN2XJ6BqG +RXuwdO1xbx +RYDh3zRb3T +RYWpLlT4WX +RYYiK9tJqW +RYjcc79qSY +RZ4ehv0QIE +RZFbAOIVAB +RZKiN83cvY +RaNUnIKIF9 +RaohGsv76k +RaxkttI1Hq +RbM0PBuExb +RbeT3zMjpR +Rc70PHfSqu +RcAivPPxJC +RcTpmwa3eS +RcmYTXefKc +Rd11UDRxiK +Rd30tA9i6f +RdITRVPPdZ +RdtvEFT93G +Rec6uQx0O1 +Rep39IIyv7 +RfFTPmbc08 +RfGlgWko9K +RfMIbN8SG9 +RfQ3SkQXkN +Rfx3aSodLh +RgUbBBsfVh +RgXbgwrmbe +RghvwpGy68 +RiVseIGMT7 +RicnQ2hQiE +Rj6s3gOO3d +Rj8uVZaxo0 +RjAFOgVXgL +RjQRibqRea +RjVddn1tlV +RjmliEQe83 +Rk2QXLb06j +Rk4ByqmXy4 +Rk74ZGLubN +RkG82XjrtR +RkPARqQ712 +RlZ0hY7b8v +Rm6hUFVuwb +RmybN1PjQs +RoEZbi0zDw +RoWt3hmTZf +RomWwhTqTl +RpMvmgNfoK +Rpjxd9KnKr +Rq39lGGueY +RqVKxCAzBc +RqlW6Xr7q5 +RrDXsUQhrx +RrrbBZaePu +RscTdiWvCN +RscYbbC2rr +RtETvmX6fv +RtvdBEZTe0 +RtwYqZHJ6u +RuSGbJQFCX +RuTLfIQLoj +RvAYZ9XQNB +RvPhvOpIwE +RvuSnHKrEj +Rvzn6Wpv4F +Rwe5QMfthy +Rx3s4FFDOh +Rx7aBNJIaf +RxF5vtBgGh +RxfwvKM6jn +Rxgop4Gbe2 +RxhziuQRwv +RxnSqLkUiP +RxvpANEPBY +RyKjxiB7Za +RyxWFZzSh2 +RyyE0QSVi7 +S01BkpbZNv +S0GvBM9sck +S0W9q7Pzw8 +S0qdqenzna +S0u1PKdwrP +S1DIGNhL7p +S207ACuzt2 +S2Lytsclb4 +S2MvUKnfXW +S2PMmexCkH +S2sL75Fi90 +S2yLmIkwDx +S32ahx1MRr +S36rQJHopN +S3Gfdn9yf5 +S3Js2LvVQH +S3eSWWdxd7 +S43HUD8VMv +S4r40aWRwc +S4zFtwnZTN +S52L6QgTaG +S65jbQXsYA +S6TEMvYBME +S6bS7vMY6C +S7rZQiKCKO +S89zn2cJdt +S8MY3qmJRi +S8eASJ4pa3 +S9HekDkIe0 +S9IOV53G1X +S9WWscohwK +S9kpwzIN78 +SA8kYREpsL +SA9nWNAP7O +SAQxUQeCHi +SAkMnOVoUm +SAnd59EnTk +SAz842DKud +SBslZX194p +SBxBy3papT +SCGCsmilPO +SCX7OVsM9o +SD42COWi7m +SDSGalCQaZ +SDUGAi4Pct +SDVslv6L5g +SEJBbJdf3h +SEbZpabckm +SEhBaXbnBR +SEqR7OcsEO +SFSMKBOkjg +SFTjU5wztX +SFkANcwJsF +SHJfiTd3Tq +SHaHAqXQKJ +SJe4BXfHtC +SJolnQErST +SKvP0N9cKs +SL0X1aXyol +SL2grgRS9J +SLZrINlWkP +SLaOKPQUSV +SLj5GcdrtT +SM7cGhPr5i +SMRH3OwyzQ +SMpwZMU0lf +SNhKHP6jJf +SO3mg30M3u +SOPWskKxyV +SOXlX1JbDn +SOgxp5waIW +SQYKuqIgHH +SQySii7ImJ +SR3tICTl3o +SR689pbtGl +SRKFOI63AD +SRwmACcqiZ +SSQnJ45L8f +SSn91PuBRC +SSym5AR3pk +STAaFzwyBa +STFocqUl0x +STNrGBcEhF +SUGqfzjfhb +SVJNRrgtFj +SVRFoCSMCg +SVdxYGRNW0 +SVk2oDSAA1 +SW4r1GIjax +SXwiKYcIW4 +SY0Z4Y2BnJ +SY1uK9X36U +SY7iESsII1 +SYi1gjY1ok +SYp7PaYjOp +SZm7fE2gdN +Sa49RvQDvs +Sa7mWCcxtG +SaUgiCXUbj +Sab86e92sN +SaepVcd5Jx +SayMdtxaxa +SbKxJAOFPA +ScEbm8QtNT +ScLH2BNE0B +ScgWkMAN7W +ScxPEuufcZ +Sd04JKnMYD +Sd6oSWPakD +SfCMWk2zii +SgALoPCDMo +SgZ8dX8Nkm +SgbQOYPwF6 +SguqZByJl2 +ShQMP30XnO +ShiNBSLyg3 +ShxUH5jDl5 +Si8xSPCvsF +SiWORa9VPk +SiYmsmnkBR +SiZF62DzTB +SjKRBsDj5d +SjPo1oDXi8 +SjXLQ9V9hq +SjraV8DUKL +SjsgjxPcfR +SjztLpTmdG +SkQ4smKrx1 +SkgOm7qfk1 +Skm3KjEGNL +SkpcdXMaAp +SkxGYD1h8x +Sl90h7bD62 +SlCUELXHoS +SlQyzdqXRx +Sls3KgLbow +SltGWOmu8F +SmQ6gqaUHI +Smt0UAJNxr +SnSbCzoPi5 +SnkJN052Oj +So21aHC0wV +SoCKIqzXB7 +SoPiEfxs7D +SoV5grQg49 +SoVBkSQFAt +Soof6T7cas +Sopm6rgAPk +SozfAvtlxE +SpDWUqSGoH +SpRnLYMH3q +SpqhvRhsaO +SrRVTPfhbY +SrgvgQztZm +Ss85b55GFC +SsUGqGRFCY +SsryYHTiXM +SswrMmLIMv +St1MfvLc5b +StUzklfUi2 +StxNofHVG9 +SuZbVCY0Om +SutsQjJ8wF +SuwLp317ks +SvHN5s0tL3 +SvJ1FfCZSC +SvN8s6nEPJ +SvhMnnYHbG +SwSfr4pnpU +SxLwibcV5V +SxNOng2QdU +SxX2AVIQrU +SxghVwvQNx +SybFVdLnto +SyvZtAm2zx +Sz4MtOmuUV +SzQKxKCLmE +T0As1rIHbB +T110mmWDMi +T1CocOgOaS +T1QlTaCJai +T1a3NPkfj6 +T1eKzeXy1K +T26dhBGXwT +T3ZVfA6Y8x +T3vIA1F8Wt +T4RP2NNHww +T4aT8IzHS9 +T4cWLpRzYu +T4fDywByS8 +T5FUrhaD54 +T5Udv7Y6TI +T5rCBwAqD5 +T6zIvqPFyj +T7N3YFUd65 +T7lztiDWaV +T9ZkBb3HJW +T9blmb529A +TAnuqvTEyk +TAoTVhzeds +TAoVYgHAQy +TArDUaJMba +TBwmKxunNG +TCACEwRqm6 +TCldkKRUII +TDKcAVECiZ +TDR8LnTbcA +TDSsduxByW +TDlhtLyuxG +TEDN1RZ2bK +TEMIfpmuXS +TESImM9MyP +TEgzJFYWOK +TEpgksAsa5 +TFT4mteZH4 +TFZk6VHnyx +TH8PO4yZJ0 +THBXaeqKw2 +THqeWiHz9i +THyrUSP1FX +TIL8MMCl3Z +TIUDG482uC +TIx7S1LGKK +TJshLFby24 +TKwFRfDhHk +TLX8c2K2HL +TMFrkbGubA +TMoHtcs2s3 +TN00qDJXPO +TN3nZsami3 +TNKyLnukac +TNL5i3z6SZ +TNqcuoGsUl +TOCA4H50uF +TOJbXhGBMf +TOTXDhIAFZ +TOZQ4tFXYJ +TQsauQu7Au +TSGm31EokO +TSIV6MxtC1 +TTHzwumnYw +TTNaDNWK8g +TVAvIqPcHM +TVjQMKnoWt +TVmuO9iHnH +TVpxZLtKyU +TWJYUgh1vc +TWOnhXgbEg +TWXYTH1PC5 +TWc2Kwbafx +TWwCbjIcMZ +TX736Ey4eG +TX8jVawCR1 +TXgaIdPCFd +TXkf3ku888 +TXw2n8KK4t +TY7SOL9YFV +TYAMkZLYdE +TZ9jumKTMX +TZY1QE0k56 +TZyh9grnwG +TZyhSryjkp +TaRR5hXVjm +TajTWBUxl1 +TakT1paNt4 +TblNa7tS0q +TcQ9tNWri0 +TctkzJPrQ3 +TcuAff7yl4 +TdY72lQZmi +Te9GnTtUkY +TeFZ50w4Dq +TeXlH4T5rX +ThNTSxTWNY +ThrqSDYmhs +Ti6IY3csST +TiMcMEwexm +TiWhZN5Ibf +TiXnbTCe2C +Tio1ekPyj4 +Tj2ane0uye +TjCZLOLbqp +TjbHOZFsXK +TjwtP8Pml0 +TjzTHRb2op +TlJ3FVys26 +TmISWEEWQu +TmOosW4rFg +Tml1gFBqGr +TmyJpjifn5 +TnsiP92K0y +ToKyf2JhyS +ToMJKZfxLX +Tp6EhEYTjR +TpiP6We7hn +Tpkcl3ZZqd +TprlkdtwS3 +TpuIigLTyS +TqFUPhEWsM +TrRD5AZXqH +TrSGUwqLDp +TsDRqPw4Rv +TsQg6w7swy +TtAtExyv3z +TtB1UQ5UIR +Ttvk2RpJg5 +TuFAgGBirR +TuJ4mtImt2 +TuNRoxSEk1 +TucA2l1uff +Tvw8HO77S2 +TwPmT32OvK +TwQyySA5QM +TxKO8GVDDx +TxYwuPys0j +TxZseBkAOG +TxyJ5ft9e2 +Ty3PclV0HX +TyKEgIDRSv +TyKW925VQz +TyKlljR4SS +TykavsxKMU +TzackTuIvM +TzjL4Iy5uz +Tzme5wIEtg +TzomtMIaXI +U05VRENBLj +U09rjb8a9j +U0Qctcx3uv +U0Sh97xmtX +U0UL7mwE9n +U138Ajihxf +U15SdAJDom +U1mxqtGtSE +U26fNDTkNX +U2GIyMjaax +U2JSqITAS6 +U2L69a4Dcf +U2W0TNb3RE +U2XR8BoxjH +U2fvHTddV9 +U2ivu8V9DF +U3A6cVt1xq +U3xkYpnDbD +U4E4pHosdQ +U4IQVlATKo +U4gV2QMYjx +U4iPGCIdIr +U63OhBO42F +U67c05dSEk +U6Tgfdwkgr +U74vSXYt9I +U7dMh3w4Vd +U7un8kfVmC +U8B9S1Hcf8 +U8CTdaC0jL +U8ueOtDZjL +U8zri8oFb1 +U9LFWrfFuy +UA2Uqy9AkQ +UACpzHsNOv +UAbcht5QEd +UB0Khm2Vpg +UB7YKJLSae +UBqUxqfCym +UCnJhRWvPP +UCrMxPOJWO +UCzXWmNwGM +UD9Tbgx8QK +UDbQ1z35y8 +UDwHAYFueL +UDwRsBGXNV +UE2i2hlQuk +UEg1gE0edv +UEq1Qmz9Qw +UEyLTMUsfS +UFgRL9NZ9c +UFnYAgFdbg +UFulH9j8Fi +UFzHoRH9dQ +UG0wbwkytr +UGXaESu09D +UGkbjEmmBd +UHJ0uOF51M +UHmyxha54R +UI41ZAwzTB +UI9GfgRzHm +UJDPYcDxvV +UJzqAtrLA7 +UKVqX6FTcb +UKZAeVbjNw +UKyZ6feruR +UL7zzyUicL +ULY9cEk9bM +ULZR3OwLVD +ULb4X4GaAH +UM5Kaw6vgJ +UMfAK1oELA +UMyoo8IdpU +UNGdf7sf0X +UNM68UImip +UNNNRBj5vt +UORFNpqvRz +UOZ3Z32DF2 +UPwBunAl5C +UQJu3oZtGT +UQsEnLF0bz +URLxHoCSsC +URWaUbTWrA +URyHjeeyPx +UTHqGYsPcU +UTl6BxksQS +UTpQfBOAiR +UTr26RUMlX +UUZTpqXXu6 +UUkwB9Zmd6 +UUne3SFnvT +UVGgvVTS8l +UVTaPLRoMH +UVYsLBbRLY +UVinMQUTw2 +UW7ssuyDde +UWqOvsjsfN +UXl6wK0Z2q +UXlSDfg5uC +UXrzjTNNXX +UY0jTZAjUt +UYOVY95pOy +UYgoEilcrT +UZUAZcESJR +UZUgtH9feD +UZXgvvDy8D +Ua9i8aXfp4 +UaAIr16rIm +UahiBdf361 +UazmuQbtQx +UbTLoX8nzA +UbxoIreik8 +UcAhLOoQ03 +UcMVAfnub8 +UcPC4TQIFf +UcTXcnAGrR +UcZ02kkgZi +UdJVbUP95M +UdPW6mELVD +UdQr8os0mJ +UezhdcZHRu +Uf3saAFRwc +UfGiGGLB0s +UfIvZ0kH4I +UfMKuVvDnu +UfmTi84Wyp +Ufzh05C2lX +UgQGpfhiT3 +UgXDYqfaYx +UgrenEToqs +UgvdN1dDhc +UhY3vdWZew +UhwffsjLAD +Ui3xijEmJg +UiQECUcAdr +UijkX5RoMI +UjDwpLfZpi +Ujrbqw1i3C +UkD6OratBc +UkImQThavW +UkQAprTbG0 +UkpyXu96wA +Ul6WnP0jtv +Ulc84A4JAo +Ulktg8HFSB +Uma7sGBpwm +Umg3IfHOBS +Uo8DDSI7u0 +UoaUyznvpm +UojPjHN57A +UoqVwzTHvE +Uotx6kdJ9v +UpNXVhzKlU +UpSr2mSduc +UpjPriJSAX +UqDPnglSeZ +UqWOPy3DU1 +UrPSCn9FfW +UsFWEyBfD0 +UsTjiYSmSV +Ut4MQ4GWY9 +UtDm1uBTGl +UtIxR0Ppy6 +Uu7qEMa3sZ +UuLByiMeCu +UuRSMwGI70 +Uv8Ns0MTiB +Uvp7ECB1Zm +UwPindsJ8F +UwgBPOn9Ts +Uws5PzMyUx +UxLpHXgVgI +UxX7RJkiov +Uxbg5tVZbX +UyBSUIUp0H +UyBoz2Swcd +UyFsuV6HLX +UyQXNRu23V +UzEuzl8CTt +UzKkwL5nxD +V0RYBVAmjH +V0cMpRv4Go +V1dI1I4LNd +V1jeuoi4tG +V2cE9JMYNs +V2ku1fcaxr +V3zrnL0l2s +V47Tev9TUQ +V4B2D7rIV4 +V4k7red0mZ +V5DgZ9SzVn +V5Ttk18krs +V5Ubf8bTLu +V6aTWp5LdH +V6wlgWKHh4 +V7cyjBoHPy +V7fswBcJY3 +V86cQmOF96 +V8AeomUHF3 +V8CeNDJsD1 +V8FymQnEoe +V8nBrZQMhA +V8vfdXwgYY +VA7kFEQrC6 +VAC9rKLaKa +VAbIQmAh1n +VAbsGto7MF +VBDvqzA3cv +VBpZNfo1a3 +VCqVEo5mWA +VD0XW7ctoF +VD9dVeiMpX +VDh9Q0aWQI +VDlFCE1kRI +VEShxOieBg +VEgAjhn5Yy +VF2Dt4GNrq +VG0GnOmHFq +VGaQsmovdS +VGhS4yJOHK +VHgWwuqreh +VHgy4ZatCm +VHrSH9SUkc +VHwPIiN6n2 +VI2vIK33uD +VIk47C4Kzs +VJiiyZG9Ur +VKBQ6TdtRb +VKmbnxdHLL +VL5X7LLq2j +VLbd3kqnS0 +VLinkolVVM +VMMbyE95Dm +VMPsW43LFl +VMRjsXaw5o +VMkTglk8aB +VN6hbRdBHW +VNcw6BGdrp +VNkiOFYyYv +VOTpGvpwwO +VOYwKC1LwS +VOYzh9vJFa +VPRb1l2D3x +VPTp1o3q0T +VPbPQ20jkz +VQ2LR0bjzU +VQHHhhAyqS +VQcEclOHyV +VR5lC4XlDK +VRIFNE4WBP +VRTLXBNKf6 +VRpJZACS5v +VSTMhC9HQ9 +VTPOANyeK7 +VTrfEmNNN6 +VUSlH6hGsQ +VUjvaS5JUK +VUtFoZVvjT +VUwPssSv4k +VWQvG0COIi +VWYI56G9aW +VXksGMHsxR +VYWJTspOh4 +VYb5lYsVII +VZHREqlE90 +VZVd5IA0lc +Va5bJK5Ak9 +Vao3qWk9Ky +Vawt3Zr9Fs +Vay8DU7Go3 +VbTVO3mEyu +VcOSs4Gbkp +VcXpkuSglV +VcwkBRAuNt +Vd3bSGPJjR +VdV6ik0PL3 +VdVfnHVQMN +Ve48rpBpgX +VeHsrR3Euy +VflGlFFYUw +Vfq6phvkZO +VgF8fxTByN +VgMHkLL5hB +VgXbDXnQyK +VgYngaKStZ +VgppUbCYGs +Vi0Eo9Glxl +Vi7K52r9lG +Vi8yZyzu9g +ViHQW0ORhJ +ViX5QrPxan +ViZrcuOAYy +Viha6RXnHs +ViiAkhSdWR +Vj7IWa5FlR +VjPSTGtNpY +Vjx7R9x0kA +VkL9ym7C9n +VkZRdureKD +Vkpjz3v9OX +Vl1bIs5MEu +Vl3blmyDmh +VlSXPvhkCT +VlW8ONFZjV +VlZuly4M3k +VmO3zJTC6P +VmXxO6FkRd +VmhNsJ5svC +VmyV88Qkv2 +VnPmtjEQPa +Vns1UvMZZ4 +VntL0kduAW +VoAnen7m5a +Vonkx2nqxC +VoxtQdBypB +Vp8eISpFWC +VpNpc2oOtt +VpuYIFujLJ +VqBU5Plrjs +VqcOoAOi2o +VrI6MC5e0u +Vrbq9PJVJD +VsASwS4fhk +VsNiSq4Cy0 +VsV3TBQs4e +Vt4Blty9J2 +Vt9PLavkCd +VtMkelIpaq +VtcPVyRU7c +VtoFxDTxWO +VuNt07UVSS +VujrnH8uiG +Vurs2Vm7xS +VutuIcVBdW +VvJqQJGhfF +VwHJx6nWKt +VwczX2vhKf +Vx9Nt1dzRs +VyTcQwPRGt +VybSYidZMZ +VyltTDMZei +VzrrqiEjqy +VzvPZBG2gH +W09wPGvKMC +W0ffzg7uwA +W0lfuDGIwz +W0wb5DUXxg +W1ZXrUIlkm +W1tX5aFPRj +W3coIlVKLY +W3h0GlZ7GZ +W5H8U5WI6y +W5WYCneWLG +W60WwVu6G4 +W6W3YYKUMc +W6Xk8HIaS7 +W7zQnBeA4s +W83lV7Ygcv +W8B8uz5RDs +W8JgRTttNi +W8a8whi9NY +W8prIymtTu +W8zxgshCIY +W94AlUvNrm +W97Yx5fBDt +W9BlJQfdaS +W9RZdtfamu +W9fTn24LDs +W9nCyqroLd +W9pv67lvEE +WAP6oSQGKH +WAWrG4v6uv +WAXQ35B5Sq +WAlEbchowd +WBBVXNlygR +WDdWAK8GIL +WEkA4B5Fow +WF8DZuVdpa +WG7rzLDKuQ +WGSeaAOehC +WGm5FVY8hy +WHCyG8bFgv +WHI3CCdaaZ +WHs64zD8uB +WHzNYFB8Qp +WI7FoKSrN5 +WJSVPkDc3q +WJmAdLKEyo +WKSf2nipty +WKe8WGumOm +WKiTgM76OQ +WL6UKy1var +WLnimRGRxZ +WMNfmEzgCI +WMWjdN33DD +WN20Pdq7LD +WNKBwX2Oii +WNfMcGNExL +WOMcMngrem +WOhBg0HWx4 +WOob0hlToj +WOvMQX78JH +WPLyqUKpTF +WPTa9MBw4J +WPUzb5Cxxe +WPox2IO0SX +WQ4r9J7O0L +WQEWPe4Dgj +WQTvR1dE8R +WQVY5dOlHi +WQomcGyLGG +WR3dvagAGF +WSHu41NiKN +WSRzKo2MZm +WSTAfFUKyw +WSkJbMh7YD +WTOD1trb5b +WTryXPRyys +WU4CaEwTom +WUiAKKllyS +WUyKZXyLRL +WWFgJ0n3S4 +WWfJLBxVuJ +WWfYbIsnpr +WWjrw5LLJ9 +WXdJ2LMjC9 +WXdpIuZmwC +WXy9EcZt0G +WY5kTdixu0 +WY7tt1BBjn +WYnpqGOPco +WZ9BVpNVA2 +WZjfa6SUsK +WZwVYGSNJ1 +WaCbglQEpC +WaPdqGohsY +Wb2PScyGHp +WbKKBZcg4H +WbaL8YFCJF +Wc1AD2MZi1 +WcHhkkDIYD +WcJvsSiKUb +Wcsf3GNtrN +WeZSQ6KKbC +Wea0Q6FFun +Wei3hGJRrG +WezVnywg3E +Wg09ZvuqcK +WgJb4jClmr +WgPFAvrdFp +WgS8y4dmrs +Wh1Ggb6eXJ +WhEOb06DE7 +WiEBPOgVZj +WiSXyAsKPX +WjPjhP9SdO +WjU3HFFqZ3 +Wjzf7dTgaE +Wl2wwIHdIT +WlG9bvUGRu +WlHbQVlzMg +WlXvukxQTD +WliV9kR2pX +WmOJjRY419 +WmibF8lwPo +WmpOzeiXZm +WnWWa8DSBS +WomUaj2mU3 +WoykQjCrlg +WpbtvHN16E +Wq5aVoztL4 +WqiMEqoxL3 +WqzO7U6Vys +Wr2I22xRT8 +Wr4faMAAgX +WrisdIaX2Q +WrkPANedEM +WsHWftXWYT +WscTWjJ377 +WstiKTFoUX +WtuyHF7NrL +WvGTg4IhnJ +WwFEF6tLpF +WwHXVZNVEf +WwS2YOtAsH +WwfX04aLuB +WwiUcE2O2k +Wwm4KQxPM3 +WypAmIf124 +WzkdmCewAb +Wzph0b0NEL +X0bkRtJksj +X1Uq9sV4lk +X1Z9BxuKrI +X1hJ9pZ8tp +X1uxXullRF +X21YrDrBVu +X2JM1Drffb +X2S7kyC1aZ +X2VaylT2Vj +X2ppQvR4pg +X3aS8nWgaW +X3wscjw2Zo +X4CV5C1bQ3 +X68MUWjNOB +X6HEV2bgnH +X6L8pWTzGN +X6X1WbZo4I +X7U2x6LlvG +X7esnaNgnK +X7ptjqjNt5 +X8IS0ibc0i +X9eUVHGJ0A +XAKLfmpvLH +XAW4ssDQL0 +XAmB9biLrZ +XBBL9pi98F +XBe9v66IW7 +XBf4eCWJxR +XBs87OIIKQ +XBy7hFSkZh +XC5T2n05l8 +XCskzoi6pA +XDQHrLOz1j +XDUYpwvPrT +XDfikm46kS +XDtWHUd7Gt +XENeGoSOrP +XGEOOmHhP6 +XGJzDkieLj +XGyVIZE7mz +XHCSMu2zDx +XHIRBTTvnV +XHg5hadheD +XHmxMUvj7P +XItkMjWYjm +XJPWD6M4sR +XJo38IvzGL +XK1ymKH1SE +XKGkgLx003 +XLE7RQlRLx +XLFInYqrQl +XLLK2OY5ma +XLMavJFJYJ +XM7mjcYPts +XMC52TKPS7 +XMjCiZJDQr +XNSs3BXCQw +XNlZk2sEk7 +XO1U0AWPZY +XODIvxQTkV +XONXvSEVa1 +XOoJWpkB7k +XPVkTGv739 +XPZsomx0sL +XPo5IxTOx3 +XQ3cmuqSTr +XQstTlnifR +XR9M4PT7px +XRrtGH4so1 +XSdT7SXHyN +XSlzCuVzsI +XTLdw2l2QT +XTVsWkO3uL +XTv7yDCAX7 +XU03Ai2QD0 +XUA2vzjZVA +XV8MfudAh4 +XVwQbj0VRB +XWH6T4w8iO +XWqKtg9bwu +XX8VMDK4s9 +XXeFojpnfI +XY1JdhPSX5 +XYTBkqL3gL +XYvTvzElRn +XZ3easoyfl +XZoqIWx2Fa +XZzTZVqGYX +XaBsJhIE7g +XaPVZNmnF1 +Xay0gQwra7 +Xb1yWK4oOl +Xbe0I6ldry +XbqHwYMZU0 +Xbzx3BDGXK +Xc7iILKKX1 +Xc88OOamkG +Xd2mISiSfZ +XdA3my9beN +XdZBK5Vg3x +XeuxRmPe7i +XfNMlDzvKA +XfPINjS2Mh +XfsjsW7gM7 +XgmSQdUAql +XgqOgyZoqS +XgqyNqAFgp +XhPrgdzpDf +XiWaEwPjOv +XiXLKtHUHo +Xit2OrLw6N +XiuQDEys0I +XiytlTrpb9 +Xj5VX3V04s +XjAQst8qQe +XkJelKn3Y5 +XksBbrwNjc +XktLMqCTzz +XlBJQ08qst +Xld15zj6nS +Xm9s3qHRaP +XmF5IxQfxi +XmqLArYOCd +XmuQOjd44S +XnQCjVMOGx +XnXEIVLFs5 +XogvYVAKuT +XpCPgVxJZK +XpIBYYDNG7 +XpdeNc5xSq +XqHJkg6OnH +XqOXC1EktH +Xqh4zIMd2f +XqxNplGk2U +XrFnnUPZOf +XrbyNaga4o +XrvKwQw6Xu +Xry1s8VEld +XryBQ2XeOC +Xs2Usaxgzb +XsXjMaFahz +XsqM9TuPrA +XsvCE2znLF +Xtbp3RmCh4 +XuTBBLDgRe +XuTh8clfpY +XvAhrbCYYt +XvUGHDEL5E +XvqHM4zqFH +XwEwUguztY +XwLml1BjGF +XwkQlrj4dv +XwqSn5VFMr +XwuCgxdiuc +Xx6roPYCm7 +XxZsv4T2EN +XxcxcTl6jr +XxszCTRBPq +XxypYzoJSo +Xz8SPb7neB +XzBnSzwTje +XzCTkd3bbI +XzHUzDgJKv +Xzh9XTJhMl +Xzv7M4hDpQ +XzvX5Jk4cM +Y01eFGwHeX +Y041HGTaFp +Y0gxtq8ZMM +Y13nybGmfy +Y1IcORQFgt +Y1MzlvoqwJ +Y1te1ldQ2e +Y20pBaokSo +Y2H0Rf6iJC +Y2nAtT7AAR +Y3Y0jx0V93 +Y4GvReFZNJ +Y568pJKDN1 +Y5ARgRSAWi +Y5C6X7x7mC +Y5G170xrEV +Y5ZH8hTRIJ +Y5yUTYd32b +Y615rIpP70 +Y69ufxknzf +Y6NdwjlQae +Y6VQLMkggD +Y6WTAeATOI +Y6mUw0pb5n +Y7TviSnBcj +Y7WXROhhc5 +Y84y7JPiLc +Y8CCKS03ga +Y8FbXWjmkW +Y9AHTIhU1G +Y9EmWhgMHC +YAHnmjV3OW +YAd7IwAJq9 +YAfa9CjnGl +YB8UvnZnoU +YBBQRETqIt +YBTd0xyZah +YBk3BS3ApZ +YCBu3OCeAs +YCEZ89j8lH +YCHRzcJwIN +YDQKwywXzW +YDkeqBQPlR +YDrBuYdoU6 +YEHjzNu4yT +YG2xYGtpFR +YGAVdwFqZe +YGk1QfPJdb +YH1Q9JEqXI +YHnynfLzPu +YI9vm9x5qk +YIfw4HTJSB +YIv59yTlIj +YJFASvChYl +YK4ao3aBDo +YKClpFPNJq +YKpwVNgKf0 +YL7HdcvG3S +YLEVJ0BeKd +YLiUK9tTrv +YMSIw1x820 +YMZYwaHsjo +YMefJoZxCN +YMf77CIKBT +YNJywFkqh6 +YNegXHXi12 +YO3ZY9FhLe +YOglMQWyID +YP5kTDQIBA +YPHiVodbiR +YQfKnfhvUg +YQo0Ko66o5 +YQyQw4saXG +YR3zkAR2p3 +YRGHvcfZ69 +YRpjhY8cpk +YS3SPoisdY +YSrU5VVEXE +YSrckDv0fA +YSzXjAlRHb +YTc7ML8YAN +YTqpqPrz2P +YTwHL4Oi30 +YVTL2ohq62 +YW6bgvDp7x +YXVb2ba1sV +YXZx9qvx0u +YXuDY0PaV1 +YXxpO4nDha +YZ9CxkcXqv +YZQYYVnGYx +YZb0XqZr6y +YZrV5f6spp +YZvMAFdoNL +YaCQtkN5SX +YaKe8B9M4k +YadPRAuov8 +YahkwzwQgY +YcC0Qj4By4 +YcNeKtMshe +YcdxHGduoU +YckPpo32Cf +YcnzgbkB54 +Ycvt1vqQA7 +Yd7xzZ8NqA +YeZiOjUh78 +YezzIZiEtC +Yf1xEXNby8 +YfIRSmRsi1 +YfezAPbJ5K +Yfz9oEpxgu +YgkBHmXefM +YgxlMrxah6 +Yh8rp21FOH +YhNDpVhlPs +Yhnk7jTCRS +YiG26ChbdG +YibLLjh2c5 +YjY1MGActR +YjbXeBUuFX +YkPDr9EDIn +YkcAgZBz9Q +YlFp5XAdyW +YltOEveiSu +Ym8SwviRMX +YmLlUWEX00 +Ymh8YYLyuu +YmwrfpTSM5 +Ymxt6dzcFS +YnJnaUCypF +YnRhnQu6PT +YngyeU0vIk +YoXy77MQGC +YogwR7Bukx +Yqmi7uxj5Q +YrU2AiEY2p +Yrj7iPypiB +YsFBJpc9ra +YsjJLn5MLC +YsoH9B1Wk3 +YtPGJdcWbc +YtR70VUR5Y +YtfyYiNvrP +YuuolV0np7 +YvU9riGqei +YvvmCiSYF5 +YwC1OufF5W +YwKogPVl4K +YwinBR0K9x +YwjfZLPY2m +Yxe6BRNHNO +Yy4D86mGju +Yy5ZmVQuSh +YyMFrj9x76 +YyMKMALyKC +Yyevf4ksAU +Yz9LSGs3Ux +YzDspEPC3a +YzRZZxzeH9 +Z0gJeY4ZTW +Z12BjHkHDq +Z1BAGeaL7f +Z1RbDKrQj6 +Z2JdQhLfCz +Z2rDwjXeAq +Z2v21IkhDs +Z2v8Vwpjq1 +Z31XhXTuwn +Z3HAKF6LL4 +Z3pCrocq2Z +Z3smn0whXp +Z3wz0GRj0P +Z4qcp72iFU +Z5VW7NkggL +Z5YQHHO45j +Z5bo8wUUSa +Z5e0lU354X +Z5y25OKobt +Z6ZMmB1FEC +Z6bLFdLCi1 +Z6dVVz54dh +Z6eJEvYa8s +Z6js0RZC3J +Z6zMFsJvxB +Z74x6UUR5V +Z7GrHGdX6d +Z7SxbADDZX +Z7U4qdKCui +Z7YyU1atXz +Z7gIjMWqdp +Z7m4IxHy6K +Z820WKGli6 +Z82O88D6Bp +Z8Vvfly3dO +Z8tqHwbrKS +Z9oGRmAhRZ +ZA4n3g4CPW +ZAGDc33JKm +ZAtkKiAtA4 +ZB3g2YXj5g +ZB76uigklm +ZB9YCMWAxV +ZBTH111DOC +ZBboDslfNC +ZCq2ZqkGNB +ZD66bTXNZh +ZECGvQk5dz +ZEUBZnn3tI +ZEdyTgmeQ8 +ZEhNEMH1rC +ZEkrPAIZjl +ZEqqbgsfrJ +ZEtAkLXpHU +ZFTiL2DyVM +ZFeuqCxHdQ +ZFyrFc7nYs +ZGYjAYzIGO +ZGiDc3A15w +ZHVTpgj08l +ZIQe0k9gap +ZIR9CeIyeW +ZIzjIQVC0C +ZJNw9oblvj +ZJWmtlhu3J +ZJu1wRchAv +ZKDaXYTYeC +ZKIYtA5Gk3 +ZKRqOWnr4S +ZKT63PMSUs +ZKd7559wDN +ZKirHG2fMW +ZKlApy1X8e +ZLASNee1en +ZLMcitau4l +ZLNYkuVV9p +ZLTT81kB6J +ZLcyuuVSPJ +ZLvsjitPdC +ZLytzc1l9J +ZMDL5iDe4M +ZN1KrDQXjE +ZN1zlcrGNR +ZN2FcvtVfQ +ZN81uqElpD +ZNwMTd8XmS +ZOaRiiHNNd +ZOiwpRP6SB +ZPDjXqNzjD +ZPO0anD7co +ZQpLtAMg87 +ZQwLa8NiyO +ZR25pvVh1S +ZROnSmla8h +ZRcVVdYWvM +ZRluRNd1wd +ZRyQDlBZe5 +ZS6w7GyHrC +ZS8dt2PMMn +ZSSZe69ieF +ZSv3klX2oN +ZTK0NldGbN +ZTtOPhFYkJ +ZU3JXktoXW +ZU6uYwnylr +ZUIyMkEl39 +ZUyXdOElOo +ZVZc1dpOcm +ZW615JgaDo +ZWVnwi8gKB +ZWlHCAPloA +ZX1UyeX16f +ZXFtPdtM7A +ZY0lYKutSL +ZYGofvJW1u +ZYJjDBgkIw +ZYQt6tbZPd +ZYT2ZY6bp1 +ZYkDx681I8 +ZYvLRqKDip +ZYvoC9BiRo +ZZKTfpdkoc +ZZQDIN5YN0 +ZZf7cUwT75 +ZZiQuGk5AW +ZapkWQahZo +Zb6o4rUIcH +ZbOJig568K +Zbh1xKTU5i +Zbs4fQY6ro +ZbsqNgRvv7 +ZcKOYOkTAI +ZchaKADIqK +Zd4TfvUqAd +ZdHWPrPITt +Zdkdzc5Igt +ZeJlvnBBt8 +ZeLfxivMT3 +ZetnsFN7oq +ZfB7DUjFIl +ZfbZVdYomk +ZfiC6gWqmB +ZfqhPDmRQN +ZfsIYYCURw +ZfwCvP4Fs7 +ZgArJ4nwln +ZggjgwGtfd +ZhjBoxAPQC +Zht7VpAqPu +Zi8IYuwDqA +Zij5c1W1Ik +ZitzMUzTbs +Ziw7FgqEPJ +Zj3I7qw8FO +ZjDWDn5vWx +ZjGYCKFyHn +Zja7xzdc7u +ZjoXXh0OWi +Zjpabii4CB +Zk4NoBEHXC +ZklOPkEpZZ +ZlYSbn4a2X +Zlbwfr24vu +Zm5OIDH7cu +ZmEqoZr2Rw +ZmYF7cGX65 +Zmq8qToZa5 +Zmr8u4JBUa +ZmttJxBuMY +Zn2Mwn0jbA +Zn7vNWhQMq +Zn94HCCuiC +ZnAJBMLnmq +ZnURMlIxMH +ZntMpC6kEK +ZnuC84NDZH +Zo5Bm1UkpE +ZoB5aUr6Bk +ZoKRLRU6Vg +ZoTJSjkr7s +ZobAV5IMKD +ZodGIY6GD3 +ZourPES0ou +ZqEKlDWYq8 +ZqNCbcz56K +ZqNo7MhH3s +ZqQ75HEqOI +ZqiOqMkFEq +Zqrh1DFKdM +Zqz1uDgTpG +Zs10vIsuvL +ZsAZgUKhHb +ZsLpe4OZNE +Zt4JP1KLc4 +Ztxa9fUAUs +ZuG9H7Mptf +ZuOsLh2RN5 +ZunNH4W2xl +ZvBw7Rboid +ZvG8OjQNSC +ZvHP66ZHAz +ZvNNhgKR8k +ZvdDKgdIXH +ZvmMj1gaSW +ZvyRTmXvcX +Zw5m7rbHaV +ZwKVEyf0hD +Zy7qkg660S +ZyOEv9tDlr +ZzkDij43La +Zzm6DxM9ji +a0OnM9BPQQ +a0suGtse8u +a1BOV3xnWp +a1RQDvLRcu +a2gozAENli +a2xM7ssAkA +a38Gz3d7gr +a3NFqSQQbr +a47hkrsJQN +a4Dk80gjAC +a4JqAq6r6N +a4QIUgshfp +a4QY97JL4M +a4ujUAdTVN +a4ytnTEfxx +a52NqfYYvE +a58WI2C1G4 +a5FCFjZxdY +a5VFjTqEXK +a5fkmPPNZQ +a6DMPSnOUv +a6GPSPMy5U +a6LZDqjxb3 +a6gOCS9WdV +a6i3EJzgHv +a6s7uDSvDE +a7CQ6TioEV +a7FKPxiofI +a7zYMMzIwI +a8QqoJ43sS +a8ge92Btot +a8hSeQyQvy +a976KzOaK8 +a9PuIIvH4y +a9nyRY2ZRm +a9xSKVVd3z +aB7bz70ByK +aBiBSYip6P +aBtQFAvqCZ +aBzCjgsMNJ +aCHPFNjy3O +aCtBjEHmV2 +aCw6UsKP3P +aCxlCVWIFP +aD9JJsRYr9 +aDiX686STN +aDqSEKo3l6 +aDvJH1Mg77 +aE3USlmAVU +aEl9zsv8F4 +aFROY4y22B +aFdb8cztB0 +aFkmvVn3Ro +aFnfPyOQ7S +aFvjLXdaFC +aG41hVH3KL +aGZimkUku6 +aGi4wrfwIJ +aHPKRj1RdE +aI0ulIEOZd +aI2FCGl0sv +aI2ZXDJ9sW +aI4n90El5C +aJjcnXpIsW +aJrLeTZncC +aL49Y64UoJ +aLYzYNQy4I +aLyi1FydxE +aM24xpHhjx +aMHi8al2aP +aMrgqV1xSp +aN2yx71Lsy +aN3gWSSm40 +aNFe6wQLMA +aNZgNyBBZd +aPrjLkOGQk +aQJi0geAhj +aQPAKuCabM +aRBWTCLtZP +aRUhEhfIRX +aRaidZWS6a +aRoa2Pzzk9 +aRp6yJZPGQ +aS0nhxd24Z +aSPKbmtcqh +aTXTlasVGW +aUGJjwWNL6 +aW6nk5YE8I +aWGXU8pdra +aY7POGkw9n +aYhOvfKed9 +aYjPUhv1cx +aYz7L15Eky +aZCOir67hN +aZCq8scpGT +aZaCqVjV1K +aZelcIpSA8 +aa6jHbjg7Y +aaih0z0nG3 +aauNmaBU6a +ab8vDycozM +abQ6IbD8Hd +abnhEMK556 +ac1tLgBRy1 +aczL7HRRwD +adY9560Q55 +adf6Bd9qTV +adu4FTsfDX +ae9syAb0SM +aeL1CwW7dI +afJztxp1EB +afTbsmB6IA +afkR33mvWJ +afo1frS8Z9 +ag0DS7MewN +agovOMGLNT +ahGIbb9lgT +ahSxeGUcFY +ai5UgLZfyr +ai7pxBoiOw +aiS5ygEBVk +aiVPCtR1KI +aictkKHvPk +aig6dtsvao +aigFOguuUt +aioQkQ7PnE +aje0G9pyny +ak6UDKHW30 +akSzsGJUE4 +akZ6GXrDDB +akj1L4OfdU +akripqXgWD +akujuSeXeG +akv9f9Afk7 +akxd5HXSVc +akxs7i3O0g +al2yqLkZVa +alVBsAVNeg +alo8IcHFrg +alrFcN1UKW +am8ULVbHLx +amzAJcZICD +an3qWNrjbm +an5Yx04SRI +anQbXupf7n +anj3v5MqPL +aoGgqljSUF +aoX0TLgWfM +ap64sOMvk3 +ap73kevjwH +apRDasIRRD +aplUiIQ9Zx +apotiuG4tm +aqCsuLx7iP +aqWZEctZBn +arER9GJcf5 +arUYZjdcVf +asYxoR78eo +aszRQkcrw3 +ati9GQ8Fvs +au2sFsU9Hp +auEbVwT6In +aunFgRPBdC +avAnJbTCeG +avjuXVBw2R +awELVPSEnr +axTFRZEvV6 +ay7R7xXrhw +aya2tu8jeB +ayrdSN1Y4n +ayw5a5E7DQ +az3Zu9lvK4 +azQo0m0M7J +b0Qj55wsMK +b0fGSDtWmP +b0yjjAJG24 +b16bONMWhg +b185viqODw +b1BWI9SQXC +b1FPJ0VKKe +b1QspvbsVt +b23W5C9KDS +b2RBG8vyYU +b3ozos4gK9 +b46yY5dbnx +b4TQjeW5Zh +b5EIHWrgyq +b5RfhMmqAe +b6YmGOY0kP +b6vhJavJdZ +b72Dz7wyHe +b76cdmzSac +b7GWfS4gKu +b7Gqibfly5 +b7hEdI652Z +b7ks36eEKR +b7nCHhoILP +b7p2YFjxSx +b8Fr8QYxgK +b8i8B1d6Fz +b9APNVCRHR +b9i5HNS7Cy +bAINYi7p9P +bAJnPsdst7 +bAlLNEP6KA +bBJGXqWH5O +bBqi18QSKx +bCUchnxV8H +bD0UsdMcjl +bDOHqWttly +bDsGzsFWQG +bF9GQqbscQ +bFNnZWR5GP +bFPHstUpTv +bFPwi1S5M8 +bFcE65QJlI +bGCAbUQzCg +bGI81M2Njj +bHV3fxrt4e +bHmTEnvrEl +bIDKQJqjbZ +bIDPDBLJpZ +bJAEycup71 +bJBuNQjE2t +bJUv6r9G2K +bKam1CzISz +bKvAQqn3zk +bLDWJgLct5 +bLSINwiwNB +bMUDnSFwyq +bMWrSm6Thj +bMrOWDdMBA +bMyl5lYbI2 +bN2N3HF2bA +bNCTq520lp +bOh0oXxWa7 +bPGFpGKtCu +bPLOgwyor5 +bQEvirlYsL +bQUL0uEVX6 +bQweS4iwfN +bQx8kIYDW3 +bRJXSE2OMx +bRPOntUPq1 +bRwBsXoCVf +bS6qSEq6yn +bSfqfg84GB +bSn7kEKbJM +bTVPz4ltgm +bTZNx1BPj4 +bTnQ0HorVT +bWTWL28Q6d +bWo2YrENM6 +bWyu9L2pzl +bXeapVhUJj +bXwhMUpD6Z +bYItlAZxu2 +bYOCNoFMVA +bYTw4yJZEM +bYzUkAO5CM +bZ1YUkVdyM +bZ7BjzLFeS +bZhBGwKuLy +baKTBaCCaS +baVOxY96Jj +baWU4mwp0d +baWxjxrT9u +barIweMsl5 +bbZI679hrV +bcCs5F2uxK +bckf1B6f32 +bcmy5kg7xh +bcypTKVSwv +beJL412ai9 +beRbI2w3tC +beuIV7tsRr +bf5ZgXVXUK +bf6J5ahVjD +bfUsNLXk2o +bfzVUydt1A +bg3w01ixOE +bgSrVmfQag +bgsUqLeQqo +bgupGnCaCv +bgutPmTwQQ +biWyHY3m4m +bilk1Spjnb +binIFXp3Yv +bjpF5L48oP +bjtCgFsgY3 +bk7NngS7Jc +bk7iRtmCkD +bkP7cTV1gj +bkR7PIGzDo +bl5wXHsk55 +blX9usPC1j +bld6kvGsZV +blpQMkmkS6 +bmEKTtvonu +bmt6frEgHZ +bn2wvCtCpB +bnDPYZs5aY +boKFDYw5He +boauDS5z5v +boweKtEizu +bpjumYyTTz +bqIYQky2ZL +bqa6OYEKZt +bqxiwzwjXW +bs9xg1yp1n +bsGHIgLqmI +bsyRGRobJI +bszDamHmC3 +btDGzqYyjj +btUhVZZrQA +btfIdE5gsy +btnaI4A4TT +bumvXRciUJ +buoMUiQq0f +buuJbenXse +bvpvxnzgMK +bwM6fEKB1O +bwTT6BxmBj +bwbK2eVb2g +bxWNUtHpQL +bxvlWJ2fUn +byBA1gBZFP +byXz9h6T4J +byxACskxX3 +byxNxLYv59 +bzBCjzxDII +bzFDDn5tlE +bzLlwYwXCG +bzlQxGz0QK +bzntuz1r82 +bzsTI1bUop +c0fPVR3kxE +c126cwSYgo +c1AY9jsJan +c1Qkp4GIYd +c1QzB3T5zm +c1TvNPoSGW +c1qfFUSvHm +c1rlShlQy7 +c1s0wURAza +c2E9OyFujB +c2Z2tUnHhL +c3Q86f8QWX +c3yOoLGDqI +c42vrWvbIS +c4kHjSCcHx +c4vKcQiqFb +c5TyV86SbF +c5cTRnmpcN +c5wEsXLkZV +c6LDpE3zXj +c7CAKEO68O +c7KEF9APSf +c7r1kOPKSE +c9wgaXGp8S +cA0ZWTMClB +cBflBmzzM4 +cCAhu8Lt8c +cCOMxA0kxb +cCU5ALkRiz +cCZUK6k5JN +cCaQlr5rgu +cCxjqftEDz +cDOtYleMl4 +cDSIBWfihQ +cDilnWxZwd +cDpyFT47ow +cEOMeHrLhh +cEXVsZcicp +cEb3hWrSpq +cEdJEresTb +cEluVtQhII +cFHALiRtpQ +cFM8pHk0tB +cFO49lxSFC +cFof1cbmQa +cFzQCJvKRz +cG5mCf9Nje +cGf3VDjNaU +cGk6qE8Lfx +cGz2qVxLiT +cIDoTYpAsi +cIQEgeSvFj +cIWNWWC42X +cJ01KIzH7b +cJJiDCuCz1 +cJT2xbVSFI +cJZxiN45Qy +cKuLvqcKCF +cLHN0HM6nL +cLys8R2gKb +cMDLurFQMY +cNGgbixdpX +cNOpVS48Fm +cNTwC7nulA +cNnofyiKhK +cOfW0RlTwr +cP3MdqAhdL +cPO5JDx5UH +cRcIznY4Aq +cRpiLQerJb +cS8kbmJI5H +cSKHA3S6um +cSQ2p4uk0w +cSiNm3GusI +cWKrCm0Oe6 +cWPXgi6rgW +cWT5qz7fm4 +cWoiD8A42a +cXGZVGhxJM +cXmyskWOUo +cXwhzP1Mkg +cY0QelHo5J +cY83UCQbjE +cYZvomFEFj +cYnuxj73PX +cYwt9Fla2P +cZJbk6ZKlP +caRrC9nW7b +cbN4zfnKTy +cbRM79QY0j +cbZ4Ss7P11 +cbdTnTEoDi +cbwCkaiNyS +cc21Rueg1b +ccNIypcA8u +ccoKZ9dtoe +ccw4FWr1m2 +cd6kbizbXE +cdLbW6rnZn +cdRywBN4KN +cdk0vxQmAP +cdyeVTNme3 +ce8M5krVTG +ceRSQ5VGKG +cezLhgcIdJ +cf9Ts6hIAV +cfEroKqDqg +cfFMLE053o +cg35KK1GfL +cgEdVgeCOj +cgi6iyKa2H +cgnLBELMqX +cgrHC98Qav +ch1d5myTwy +ch2aJgxW24 +chQ176i8LB +chZrDbdP9f +chxhB7Q7BB +ciU8dh717R +ciufdS8Y0b +cjUcAIEUoA +ck7wqhXSIG +ckCXAjF3eN +ckJtsqV8ae +ckktM8kA42 +clLYLaAAC4 +cm2Cg8h8tm +cmZ4zSzsvV +cmab5LlOMp +cnVOUMVNZG +cnlT2RzItZ +coDyyAq7Zv +coqwVa2bCk +cpBuZC53t5 +cpFqiNoS8e +cpXxSFCrMq +cpx3zvodwk +cqhmjcFz3Y +crHmTnnQDu +crPmQSjuFD +crXKsD9Naz +crqUyPbTsX +ctEWHkDBt0 +ctFKYA8KCK +ctFTG73JN3 +ctNeASTaGU +cu7C2p9ke6 +cubJP2fxwz +cuqEit6ZMz +curt7rwqu4 +cuwnoQ8r0i +cv9t055yi4 +cvLzecZVzJ +cvTOwHKvJK +cvmrGH6oA5 +cvy1lIoZVy +cwAWpAV2Xa +cwcd9XV0JM +cwdmDIWkbQ +cwicTHGLOM +cx2mVGKIaS +cx6QqKk5tS +cxN6c8Mhnv +cxdSalk4tR +cxgq48dd2m +cz1HyQP5Ry +czLscTC3tJ +d0IzLFNVZV +d0fSvqM3be +d0inyxkZbC +d0vRSrHZQ3 +d23rHsWdiO +d2CuvhD1k3 +d38KBsnjVf +d3N62u813c +d3pIewkZoO +d3yAp7Na9C +d4bg2pKKyU +d4gSdCdCxi +d4xoe39rJi +d5tZ6gBR4Q +d5yNrbplMG +d6B2ho29yk +d6DwCPyQ1Q +d6nDwPVMMr +d715rUtPT1 +d7EO0Zp0wR +d7Gtsd7gRv +d7ipK2VOaO +d8GmOfnfiz +d8KGqIe0kC +d8hzzKUN7L +d99NePvedE +d9D3gidZXw +d9akhiuQqn +dA2hkjShRE +dAQyaUHyG7 +dAiBg1Uh0j +dBn8DYKMTt +dC6bZDl7Ve +dCJoeROZw2 +dDSSwGdwKu +dEVDSxPPOy +dEiNAQavCd +dFzn68NBdq +dG9XKE0emB +dGMD2Vdy4u +dGbu0PSXAH +dH2zfPzl7d +dH52R91COj +dH7OnBF1aL +dHckmW6AnL +dHnzfvQScY +dHsxqSoNhr +dIT7GtdnaV +dITNtNWtlv +dKJNyFZVWc +dKK9W275E8 +dKgDMs15Vm +dL7wHIEoyG +dLJ98NK0kp +dLSH7WbX74 +dLYqMEehkD +dMlzVFseZM +dNH2eUnXnx +dO8DJr1esi +dOGqmCudim +dOKhqWaU7t +dOcrfv3W6f +dP4wg2KGOa +dQCjTLEOOf +dQDvBlJUjf +dQFX3ndIwn +dQPGJmtUAe +dQU0qrdEKM +dQbYLBFJnZ +dRsHT9sWha +dRwDP3fckC +dSIUk2P9fr +dSRTrZ4QlZ +dSTCsNkzya +dTkQIvS59y +dU2jUudFJC +dUEKJI8Vc6 +dUwK4Ehrue +dVCmNiZyPz +dVKNkBpsRn +dVVQX6o5VT +dWP8PiAXGj +dWgPdrP1CK +dXEhhw6PkT +dXc0OUUkKe +dXdUqb8uXK +dXrL45QZU4 +dY2dtXy2LQ +dYneSakxGe +dYuYj1TY4E +dYzd6GTuek +dZcPe8ERoE +dZdEwgrQNS +daRNMbpc8J +db8IoW5ReS +dbMUgEQ9eX +dbPSwi3UfV +dbUUxls9rw +dbtRpl4lno +dbwnwV7ML0 +dc2PkDAl5r +dc6Zyk7o7X +dcPxbCbMMQ +dceFN3S4Bc +dcsAvFjFWu +dd3ZSnoBF0 +ddbOe0WFrJ +de0LNMUF10 +dg8J5rlb7b +dg9GL9Inm6 +dgDkn4aCXQ +dgQFUjxceq +dgWloDd6q9 +dgbvGXfDPu +dhKXr5Dhm0 +dhXsCHrt5i +di5tTOJh86 +diL6EVzdDU +dio3mvVvDM +diwKXlCjin +djDY0PjNYU +djQy5IRMYo +djgy93J2DO +djtMJHNtf4 +dmHZnyI6vj +dn98hbBDOz +dnbfn0mXR9 +dngee5wkxf +dnxYjrAQHE +dokezw8940 +dpbAxfkVKU +dqPPvLmzKt +dqXfSgZUic +dqhmQ1Zvx0 +drqjAui97C +ds8nVKake9 +dsCFBuh9ZK +dtIXZtY0FW +duSArmGkoh +duScLsTl4X +duUw8IiKoc +duV4zdapBE +duXNGAefV2 +dv7E3u5FHC +dvBZ5K5W5g +dw19q963su +dwGUCEm8KL +dwPvm0b7wY +dwvuZLWX8v +dxVrhUthM1 +dxWb6ciLyS +dxyjek8R7A +dyOFyzbrsS +dyoHpZuMP2 +dz02huXEKy +dzaaY12StP +e0ZK1OMsUe +e1VUjlb8cl +e1gdziWbU6 +e1n0S79Wbm +e20tsLqZKY +e2NeRj0xet +e2PCpMQlGd +e2QoYFvG7w +e2gg11fKl2 +e2jjgri9Sn +e2zyu36fdP +e3lSJFUbtl +e3lfHxODtX +e4BdCoT8w2 +e4OJ6ZpXwZ +e4TF78dr2d +e4ydAGX1ie +e5fb7IlpWE +e5i9HnsWol +e5mTrK51B2 +e5qAxxP25G +e5xA2ofGgc +e5xfz2IvmG +e69aC5XSyc +e6KcaTihYZ +e6RNN9YbzF +e6aa7XChul +e7yK0uGRPS +e8dOQ78eSx +e9h4gnyNNA +eAAd9QGoj2 +eAGCm21LCG +eALXnRiGYn +eAV13gPW4t +eCFbwGsJp1 +eD9eusopub +eDDb7vJ51Z +eDEUQk2ge4 +eEhvmCLXU0 +eEkjEuMVcW +eElwKv2B3K +eFD8bRlsbB +eFoPtVdy3G +eFqf3Wuhib +eFtUR6ffd2 +eFxZ2VjjPl +eGTNRGTR4u +eH1YObxvss +eH5WcZq56R +eH6gBXX8A6 +eIQ7tQSGUS +eInY9vo7X5 +eJdmS3bhPv +eKwXQ2YUdU +eLdcVlEheY +eLsliLJPZ1 +eLwGPUd0OK +eMtaPCk5MB +eNEilPYv6W +eNbkiZlSXp +eOuwTMeBq6 +ePTVfxm2eI +ePl39UvoPL +ePm06G1Doy +eQ14KT66EA +eQR7ed0NAP +eRSfrrm1tb +eRqKO73xfV +eRwGyeBmLF +eS0F04oQSP +eS7L5W1X0F +eSm7sRDgmT +eTzk3v71oV +eUDkq7lZWU +eUJRlk9W4J +eUyqNHZD4x +eVWcqP6qUo +eVjbw3sPpw +eVnuN93efR +eWZxnMchzQ +eWhM0M5Wtf +eXApclwT8W +eY6eLLJ1Cp +eYDtsPWEXZ +eYFEbceqKw +eZX7IUse5O +eZqvZjpNrf +ea2oS2dVD9 +ea99ttyaDD +eaHHmq9ttl +eaJ1Dp8UaZ +eanK5re8ZH +ebdhLTZwRU +ebeCZTiWvl +ebtiEsl8S9 +ebvqrSc4zX +ecXIGfnHgQ +ectnKwFR47 +edBXvNRbrg +eeTQtKy3SQ +eewfaPH9mu +efE5wajL2l +efJzc1tpaR +efNjEzosJj +efnBD6quuM +egEc4acibX +egjQkKHCks +egjmFay49s +ehcxNH3mdN +ehfKfr5bET +ehrPbUDTKi +ejtK5Ww9Lu +ejzMWoj3bn +ek6WCCLvZa +ekH5pmfLL8 +ekHkvPC6QL +ekYrYlbl9M +elLTo7HYcE +elqx9O55Mv +elvkdIhSXZ +elwk2ZVU51 +em5kau1DF2 +emjmQRWeml +enDkrA2ncu +enMMElixuW +enYsHILGue +eoo62qgtyh +eoyCkBz4QS +ep46INChZT +epBuKu34r2 +eptr1HbtNc +eqHkZ8haeV +eqhuqfhear +erO3BhrEMF +ervNy6yo4U +esJHhiNM6o +et4ji5MRbQ +etNJoOdKJq +etXIcdYAWy +etsIWXtetS +etvuBGoyIT +ev37VMp7dH +evf36GNrU6 +evqviRyy9m +evxc7d0aU7 +ew2O2rKDUW +ewNqVbFVly +exLfIAYqTm +exPheppZXC +exWwkrGzZ2 +exdGuwcPbh +ey8KvQXWXF +eyAbUkKNwZ +ezywzk1a3E +f0YwBB0ucy +f0lMsb26uA +f151TyuCCG +f1BlOYtI1P +f1DH51bB4L +f1JLaaAryM +f1oWWhiyOx +f2LamSDiF2 +f2ZS0M3rLW +f2eLuKl9fZ +f3hJ3JRuSO +f44SO5b3Ju +f4bvi6g89W +f4oQP8xPOR +f4xrk3wjxG +f5ESoTq5OA +f5vZL4FO9F +f6K6GIQHoP +f6NM3x0IhB +f6SmPLxHDl +f6lUpY7k9c +f6y8GZ1mu8 +f7QWAr1KiV +f7pfxJWI5T +f8Zwpx6LbV +f8hgjZpuNM +f9JbDVTKRI +f9OYz7G0th +f9eWW2fba0 +fA7SEuHzCd +fADsLqE1Hr +fAatsHoYbJ +fAhxVOI2qL +fAqMn8zax0 +fBCuz40J6J +fBYKqLMgh0 +fCIRnLR8N9 +fCWDhjzV72 +fCWPvqg6c9 +fCb0okWdlU +fCsBGTi0oR +fCu1tKcCSj +fDBApClWGI +fDOXaSkw2D +fE67XD8Iac +fELFOHgRHo +fEOS4Id1cP +fEXquSnMrr +fEf9yJWktq +fEm1fdadnj +fF3Lawurlb +fF6YPOqvX9 +fFOyiX5AaP +fFPPIS5EZZ +fFz529NCiG +fG4E0tpHvE +fGPVBd4D8v +fGUPvCF13V +fGglKta8oy +fH41l54rBs +fHAd7S2Mbv +fI3jPJPTPA +fITq6cGkP2 +fIep2fSFXb +fIqteVBBQS +fJK4q3NXCB +fKFV9M1PNU +fKR74zch2D +fKhrRLYxFc +fL3iIN5jbe +fLTVwQfop7 +fLuL2w7yKa +fLvphZzVj2 +fLyoaqnlgi +fMKgpYAuAb +fMemyS44jV +fNLmDFKpqp +fNM8sDwHS5 +fNaBzG6OF9 +fNvrg1w5Hw +fOoo9GcySq +fP8qTFR0Wt +fPQMl0kFw9 +fQIDd5nSZQ +fQNHBdvUWa +fROdqt87CD +fRvCSwbzf5 +fSYW2AhtDT +fT2yNhyrig +fTKQaW7pel +fTSmFHY61x +fTvj9Ud5Ep +fUCpee0WGU +fUFsJRg1xD +fULmujTD0t +fUYEZY4LVO +fUd1aMFiMW +fUdbZt1wFP +fV11zWYbRZ +fVAKCpKPME +fVyZtyXn0s +fWAQM1A32n +fWEhNj2wwC +fWVltwlIgM +fYHDxpKG3Q +fYtQXMj0mT +fZ018Q2tBt +fa2UsR5oaV +faGZXrZ2cr +fahIwtydEe +fbeYPsCPcc +fbrhmqkPmf +fbvVeqwFn5 +fcUgHa0jZe +fdZSwaEsEk +fdjFZZkWyL +fe99pREMAQ +feFPMTHZhp +feVmEYKSIU +ffFfVLoRsT +fg2JCZDLsS +fgLgcUlt0t +fgTuAwCMB4 +fhofzyVl4w +fiMvNaufLc +fjVKPNzFOB +fkWQzmNTQZ +fkjwoi6UUF +fkwpSXpNid +fltAtimjmC +fmLcNLyhgI +fmaleE0ulz +fmuEnRi5ya +fnHIF3UpzX +fnTKZjHMSU +foPbbXUc3l +foalk6FAfG +fpNbQaOyvs +fqVdvelOsf +fqmQzAN6HP +fqmY8sUdAV +fr25uYzHDI +frDvDu5TGo +frUEHvvlzY +ft8qw9ls9A +ftZZto28jL +fu7b9rVUhu +fuU3PkbGGO +fvwCaDpRNV +fwYGbUcZx7 +fwa3SHIwKg +fy3Kg27U1M +fyc5xReI0S +fz5c4OOeDT +g0T5Z3IEPj +g0X0QHvMW7 +g0xp0QMfDm +g11NK4Md9F +g15FfquZUg +g1dMSXkac6 +g1tpF85ufp +g3BXjV0Y2C +g3g37k8CGW +g3gqDmxyF2 +g3yubjhf5T +g4xtJPQINX +g59uX4msog +g5cZt946Qa +g5qzjUP7Pc +g5writpoRT +g67W3XnV6s +g69LtziewZ +g69V6GEbnc +g7DIuziDVU +g7KXyRUf4v +g7mHxFDbN1 +g86q2Rp5WX +g92QRQX5Hp +g96KwuAwUO +g9DpMEYT9C +g9ZRjHJyH2 +gAiXDDHqp7 +gAk0DlnB3T +gAxbamXXTD +gCZaALm5TB +gCh0wZ2mDo +gCr3bO2tcb +gCtbkcjTrg +gDB0wx9yAS +gDJQ38TNu2 +gECTyPOlSd +gEHJBZDw5W +gEZl6yGe6v +gFMiyfj2Xf +gFO5mK3Eht +gFTewIc3yi +gFzJD6iRTN +gGiAVbX6a3 +gGkssAuyaZ +gHCLZAoLAT +gHkGotWT26 +gHyeGp4r7A +gIVJe8dY3K +gItrv5odmB +gJUCPR16IX +gJWAuMRyI1 +gK8wiWInt3 +gKHxZZtjiI +gKf2BGe2JM +gLPTs4FNvD +gN1WVOhd4J +gNA3bjLrlD +gNpBXXSrtm +gNvCM4z4br +gOljPjltoC +gQAYmNQlgt +gQNYQsJKmf +gQRv5ySRkT +gQX49XPGQV +gRWZiZW7n6 +gRdcN0VWHe +gSJ9p754un +gSa297MoHJ +gTB3gJzIWv +gTTjZXEORf +gTXpRqi1sm +gTioYf3qw6 +gU7Ei7ZWh5 +gUMZzMdA0y +gV524KeO29 +gVXEw88N9R +gVeAPQLRMP +gVeSvGRz84 +gWC8zPgIea +gWVVhzua9q +gWwTkbamHU +gXNW9WYhQD +gXtm2irvCG +gXxfjAgVIN +gYokf17Bx2 +gYv1BPvBA6 +gYz7TwvJfI +gZFdcV6IPN +gZI2xld5RV +gZYXrXwcSS +gZhdvQuziH +gaXXw5Ss2j +gas8KOU6WT +gbQx7abm2R +gbdu2VPPQH +gbgqhIcmc0 +gc1GSA0puv +gc58p0IaiW +gcQeLsTfbE +gclEVX9w3m +gcnLsdGAmL +gd4tebtPPw +gd7a9hkkTl +gdkyTNipi2 +gdmHH1Be9r +geWxaS10jc +geme7ZXggX +gfofCbJkvY +ggdO5Dads9 +ggiBN4FrK8 +ggwuK7eeJR +gh86yot5VN +ghMOHntiob +gi3xcCxXs2 +gi4g26jPmV +gieiFROaDd +gikIyLpYwP +gjBlDIFdWv +gjDh2kd7VV +gjO0bywWL1 +gjQ0s6beO2 +gjeEU9IU9e +gk41WeU3ka +gkKLGzTw3X +gllDxa0D8h +glmXeXbp6o +gma4wzCTtP +gmntwk5mKS +gn3JQdOgoN +gnX5DIWVXR +go2Fk9xRMM +goA6ZTq5xN +gpAHxGseQd +gpjtgFd0F4 +gq1ry79Fp5 +gq393GIDxs +gqtwVwX0Ut +grb4OIZ92L +grwedV6IqY +gs5fIBIP78 +gsVqiKXlNb +gt165Kmd3F +gtd09SaTjJ +gtzUqTYiHz +gu6BjZyMRX +gv5jSGok4h +gvdTKciHbO +gvdkdBBIgY +gvww1ePEFP +gwBaYkIUKI +gwQB44G8Kr +gwcMXDTHkD +gx9XdiLk0q +gxIZMjHPJS +gyyDJLRKwL +gznTsJeqW2 +h02s8GZrV0 +h06lBT4LvH +h0BygAslXp +h0cPOzNI0j +h0n8qy58z2 +h0skRoSWDw +h1ATDgVQzk +h2Hi24ZcfV +h2ZnKgDW2o +h2z2xQzmwV +h3529WHzCh +h3BZEje3nX +h3Vq5RK8dr +h4PUATzS1x +h4WsM1Hbvl +h4kjDBr8rC +h4uGBfz8c2 +h4uiWxy1gW +h5WPb41vo6 +h5X572OccG +h5ZA7MUqYN +h5fBOEbS6c +h5kXdL9Hwj +h61pz9S9GK +h6AlRXkpoE +h6Ld4Jk3Xt +h7jQXtkvK0 +h8dzKeOsoC +h8gKOzcQSW +h92a9haKUk +h9QBHlxSFf +hA101zGN6M +hA1zsqjGF7 +hAuFGHq0mG +hBRFKi3s0z +hBXWAQPrBa +hCDYjRMMzx +hCem1lUAA8 +hDnKZaGLsp +hE2EH0rgMv +hEVYjFRHg3 +hEvQ3XSRQN +hGFcz7oEGI +hGWn18FMhR +hGaQ8tNiqg +hGb3mopSx0 +hGjBb3LhVc +hGvscYRXaH +hHDaT9FT1l +hHRizpPdRk +hI4epViCj1 +hI6QDi6orN +hI9Hdh2okI +hILl9qAm2T +hISBWW38VT +hJN7VgiOV3 +hJOhoGB0nD +hJgAfSfJow +hKClM2dOPB +hKjM9bFJNU +hKyon9en4Y +hLAp2AGupx +hMPnFDywUb +hNE7ca2AIU +hNMQUQXXGk +hNryYjG0UR +hODoMuG7x8 +hOd0wLwk79 +hOqDtiwBAx +hPAwf3ESnL +hQEqMF8TRu +hQRL6ExEQe +hQzG3oBakz +hRQMMXUiXw +hS2qM6IGqe +hSlPQ905xR +hT4o3XCa3q +hTIHwb3xfV +hTosMa7CvK +hTxpWQQUtM +hUHQv8m61b +hUX4PA5IV2 +hVgk9R3mif +hVnAQ5SSqW +hWAfIvWNFR +hWXPT3PC6K +hWpB2GhRRf +hWvnzEdtx3 +hXNSoxXGWL +hYACXO5nje +hYibQ9AtLB +hYnIxIKsEY +hZ70Y37Okm +ha2HSiJ504 +hb8YBYL37f +hdRQt3xnHq +he0MgXSloF +heBZuKsx9y +heYMGneRvO +hfMXk13mFM +hfTXbF6qYS +hfeOg0bPdO +hgFQnvz8dX +hgX9k2LqQG +hhOons80U7 +hhPolWWHSQ +hhVhv0sEu7 +hhg0sKayhU +hhpHGmvHud +hiRqGbPg0H +hiYnY7bgNW +hikVp54L6t +hiwHuIYOcg +hjDCVNon5r +hjKJYKdzhH +hjiutcyf8s +hjveRMa0o0 +hkdrT6ITEt +hkepHgacHN +hkydrEVc3a +hl292o6MrC +hlgzWcytBK +hmxvriITyr +hnbu8gPB5p +ho8SK6S6sV +hoGAsvcbuS +hpK3d6I2fz +hpYIy2BeuK +hpYuBD8uyd +hpka9Dutrh +hqQFQrfTFC +hrRIeEbDRn +hrb0jSniWJ +hrhLdVOjkv +hrjUc9nJNK +hsNJkk6rcJ +hsnm2g8oRz +hsnndDUPtr +ht2fTwcNLb +htFM1ieOVj +htaAan3hA6 +htrI60sS8A +htuqU1W1qk +huAmNMJ5Ya +hv5lCWjXh2 +hvObhZw0lf +hvhwUwISVz +hw2ZG4hDOM +hw7wYIKNpP +hwrkNtwshb +hwwgcrtFcw +hxTfHmxYNT +hyVPaMpJTs +hzi10Fdi3U +hzmoVSmEai +i0JARW1QkO +i0JHexrtDZ +i29TIj4KYr +i2EA96TXAA +i2pCvqGKtc +i2xOljLlmK +i3YTCCvj9D +i3b42hlAxy +i3bsMUFyLw +i3nOG0MOXs +i3qd6SgKZd +i3qrTWxex2 +i55sqHD5V1 +i6C9jRuqCS +i6IXY3Y338 +i6q4iegAvD +i7ApvrBIRg +i7kT8TYhQT +i7qHltnuZ7 +i9NHoxFCG7 +iAHUHS5c4X +iALdB7UW2E +iAUDw3IdIn +iBDRrfEY3c +iBLjaXrLCh +iBhfxXys2Y +iCORmUTs0I +iCfMidnSy6 +iDBw9hjmOL +iDZUrbpKF8 +iDcZZKii04 +iDpSwkCViP +iEP9n7G3rc +iFbytaPBO7 +iFvt6otfDl +iGjpmhoozo +iH0nWz9mtL +iH7goN6Tth +iHBtE0pG9c +iHa9wHO4xm +iIMj9k8YAv +iKS9gDxhB9 +iKlW2nb69S +iL0HY2UeW4 +iLHA2vDfrk +iLYNEn1LDC +iLu7Ia23GJ +iM5ajw6vtJ +iMCLFSd2Vt +iMY4DfAL2r +iN6MMIGz3j +iNhBhtHBYj +iO9G0ABU9W +iO9Yq9GU75 +iOgbxvQjub +iOsiAXuvoC +iP6AKBC7gY +iPToOdxqi9 +iR2KKvfz6Z +iR5t7KmIde +iRSVQx0yiu +iRcPfMfyrF +iRgNBb04Hc +iRtAo1LZF1 +iSyuTzLL8g +iT1WEEcH07 +iTWQDjWEDA +iTffEjbrI7 +iUBqyjENTG +iUCjQAxF4t +iUK3yJPj48 +iUuVw2tjGS +iUumGZSTy1 +iUvmLQ9PZU +iV43EpV4EJ +iVDVon7LAa +iVmmTI4GJ6 +iW1b70ZvQ8 +iWIsLaRqHN +iWgNYXtZtW +iX5lGn92fq +iXCTHkamgn +iXHlra7X7a +iY9JmiheLB +iaQN2NCYfJ +iaRLs4z9fG +iaiMKXHg10 +ibO8zesTkK +ibQIakOlsL +ibUz4Zts1U +ibo2F26YRm +ic7zofu5yY +icFmdT8CU7 +idGA1XPiCl +ieM7LPjRfU +ieVwN9YvWA +ielUs5YZy0 +ieosUwtRZa +ifHHV9U44k +ifQQW0BYDS +ifwRJo3RFl +ig0jSTbFhr +ig2zKJLdRA +igMYVfGErS +igqRMAu4Uc +igvHhfHj63 +ihOEfUXdQB +iiPE80rn5X +iiPYLIiY0k +ijovL8eXmW +ikSBLPYe1j +il5Tk9NVWr +ilkHjJgn53 +ilw8DFGdeq +imUcqfSyOh +imlTNVP5i0 +in7dIaOBaA +inoprsmHgu +ioDPAShpUC +ip4TP1MGXM +ipfdsSNtmQ +iq4N2pgs8z +iq6HbpCGtR +iqZIL3V91Y +irCP2VnfX4 +irGNXAlBtb +is6PoU733M +isNHDzl0ay +isijley6Oo +iu6zMbgMIU +iuCupgDGLe +iuQiAWnFSL +iw5mstovFA +iwoaZhPNuh +ix6GcUrLDW +ixgx8B36iq +iyh9O6pxuT +izgc8suCaR +izh78qBBVD +izt5K3xB4J +j0E1hdi3aK +j0RtEtCNom +j0d4EsPAVL +j0i9gKZK5N +j11vThCpIH +j1MAuTflSK +j1Td74gxwa +j1wUNsNrBU +j2VR5kuC8g +j2lXfHRLCB +j3oDG412jZ +j4AVLW2mWJ +j4ltqKLgcE +j5bLkSakDT +j5oca2ttcM +j5rwGkWh9L +j6RSEevXsB +j6o17YsbdA +j7EZIOlcPa +j7d3HUow5m +j7uxNKI90R +j8ttiA13dx +j8wJkdLWc4 +j8zSVIrQtx +j9fvBk5vLM +j9vOwV4R83 +jAJhvumNTw +jAMwRuCUnO +jAk27QsLkJ +jB1wLqygi9 +jB8bHgdc2v +jBIsrLUPWf +jBuf9ahJeI +jBwKuBLSfH +jBxMJ5jF6m +jD83rGcsQ4 +jDmVQrytB0 +jDr87UvI8F +jDyWHdAEMD +jEIVKpHvcK +jEJMZeqJF0 +jEPYa6cFxe +jEWY8flGzh +jEYWM5flV7 +jFLwWED77g +jFSDnyvwI0 +jH0Ii2mqIK +jHmVfPSGTo +jI31sH4tDt +jIWD1Hlh5D +jIbja98ct9 +jJAIdDPraY +jJDohW9Tys +jJECwQuPtV +jJFVb4pskp +jJG2aH3nm9 +jKP7iLOjId +jLBQYXvire +jLPOFseY8o +jLSCO0srd1 +jLSEg6Wzbg +jMMFuSFOcJ +jMj7vkM1Iw +jMyrqayi7Z +jNlpgCYxxg +jNolNiUGOu +jOLcxctrrA +jOLsaH2E8V +jOboGIXIe4 +jOcFfJABYz +jOcYREm32k +jOrPttdR0x +jQAsb1O7yj +jQvK0GQu73 +jR4QB2eRjK +jRGWnLQOhd +jRy64RkcZW +jS7aJi0yOQ +jSSIXToOZg +jThUqTKDGq +jUXbPokNuk +jUvrAOpLF4 +jV8DXiOxZz +jW0RKtLyPF +jWTxxleIfA +jWaZs9HeWl +jXDTV0qpkL +jXWUu8CXi4 +jXxnSrOHvo +jY5g2E6hra +jZ6TqGTxfX +jZB7LJujUh +jZaU4Ios4d +jZeluM6s8G +jaeeaaZRcZ +jai3oqEVCk +jalnmvDKA5 +jaoUnm5T81 +jb1WrAc4ni +jbOFRyJZ2w +jbSpoA7N8D +jcxIR4e7mQ +jdKj4jXrrs +jenisL4wMZ +jfHnO6BtYi +jgt4Tsn2cn +jgukeJLKeN +jh6GgEQgAS +jiCjTqT0w1 +jj1XHKBlXn +jj5oMS4o9M +jj7IHsfKNh +jj7lxIDLHD +jjSytt4x3N +jk3w3MOBTJ +jk9co5ICFr +jl3GoSJOTA +jlH1bL6oxx +jmiEOqRmIO +jnPD4WpXf1 +jovuh8QUvt +jp0nBKzOs5 +jp0rA0cGyQ +jpCmAY10yU +jpO36hw8Nt +jpuktdlSuO +jqvDSPxBAs +jr8S5Otm9x +jrGCJ0D5sb +jrUEeEJG9p +jrWmkPrxGi +jrYpsrOFjp +jraXRTWPPJ +js9XxdjdWf +jsHOOYmY4D +jsf2QshsM0 +jtHkcT42ij +jtRFXqdyLw +jtXS2BcBYz +jtr8rtaCKK +ju3Af5ZCwm +juZ9aPuMno +juaFUFpOpv +juhHnLF025 +juklHNF5Gg +jun8QD0nez +juwnqACc77 +jvCPPcGhmi +jvGDPxi98S +jvW2i0QRRD +jvwbsIrHx1 +jw63Ss5js2 +jwNi2Bel8b +jxNQ11E3Lk +jxTAImlruf +jxa97cKwRK +jyS6e8hP3b +jylXRE1Zgc +jz9IjAfG2e +jzEoRPDbuj +jznrFCesO4 +k0JoAi9geS +k0UZx1hHzf +k0WYMrgyLV +k0plgLYr1B +k1h2V1Oy6a +k2CX21VQ1V +k2toDhEak6 +k36cJKWWSI +k3BEubHka3 +k3JoNnCTh5 +k3kGqTCvjp +k3zz5XNJrc +k4MmirlVNi +k4RjpOxnB4 +k5494LfFgG +k5VXVpLCFY +k5k62blk69 +k5tW4mxfa8 +k5wzOcG3NE +k60vCWuAP3 +k66ocQzfqA +k6C7VILVvF +k6JC1HNhyW +k6Z1sNTKOy +k72kLVrzYe +k82uTHS2GP +k8khe1YVnm +k9NRMnYi6K +k9SJKvXSZy +kBiwuQ8HiE +kBtZc4J8Ps +kCM0S0kCf2 +kCSoo22JPS +kD4dSIosrs +kD6pnKauez +kDO0jwk4EP +kDVdTyWgRa +kDruIzPWPH +kE01l8Cofi +kEdOoqs0H8 +kFMZOBo0BL +kGJYmRdxG2 +kGgdkz55k7 +kGoPkSS0yq +kHFAcpcjDh +kHI4u9vQkH +kHWu1DIAHV +kIW3Djj8Dl +kJjbzYQSyF +kKm3Pqe04b +kLNkacwogH +kMuLmDYoyI +kO6SDVapBU +kOLKiUl9dL +kORt4Vr3Qk +kOaMq2JDdb +kPGxVLKCsQ +kPZbuhWPzg +kPbXF2I62N +kQDlwCyhM5 +kQGJziXdGl +kQOZqMh27B +kQcaDfRpwK +kQjkDJZI7U +kQlJRGFCuN +kQq4rqIs1q +kREevvkiSg +kRxbXQhRBD +kS7RV1AeLO +kSUTTerH0j +kSrVwFekDp +kTIWpj6Ued +kUfGJwtwX6 +kUmk9B0ofR +kUz5mWXoh1 +kVerOw549r +kVzcPvNIqM +kXSKHxbUBI +kXjUPIJDc6 +kZ1oollkBi +kZLqqPJLXH +kZRimuT1NV +kZRuDRy1mp +kZUEvQucdX +kZaxOr6wAg +kZraDH2dsn +ka0lLiQzyB +ka5OvVKDwf +kaNfUPKSt4 +kaTfEUrzHB +kavkf29SMI +kb4luSGTwh +kbJHANB9ig +kbKfoo1oyq +kbmTjJYody +kc8hhg50JV +kcEBUXHWqK +kcbAJLFzcQ +kdIJ6QtBGu +kdu9DuRnQc +ke6Mpn0C9T +kebtXYixun +kewzFn0bOE +kf9IAFA9kI +kfjzxTXT3n +khUjL8Z5ZI +kihbGWl8vy +kjkx8nfTV4 +kjlnRJFJwv +kk23S3NYsy +kkcArnaX99 +klBjTw7BNc +klFAD8xMe5 +kloRYjiaVj +km36QY5uQ3 +kmI53k169B +kmRSyXo6Dc +kn7ivnDMio +knAwL4A5mh +kob03eTHjy +kp435y589w +kpIVGrbwaR +kq6jWr2cVp +kqLL6uTBBe +kqh1Il1c8k +kqigEV6Nck +kqw4GRPQOQ +kr5G7GS8yh +krcEfjLez7 +krlkoMtQzC +ktpnCFtt5l +ktrDAK1SxL +ku09lrrjwQ +kuGyCBjLv9 +kuUg1CJ2rM +kv1v0L6tEp +kv8rLynAew +kvEBv7JnzL +kvX1vZV5Rg +kvtVetecRK +kvxwmMWGY4 +kwLijrgSiT +kwVwDXox2N +kwbbxoX34D +kwk4yREO3w +kxxZaShGbw +kz81bvNdh8 +kzALq0jFY9 +kzssnhIdeD +l07ZkbJIcn +l0AinNxQss +l1dWCHVPCY +l26oCL8k9t +l2UvK3KVQv +l3SzlHDfSV +l3VVJYWQXK +l3XQu98Rg8 +l438PnhaDy +l44JATdvF2 +l4TEHqLeso +l4lh6nvEca +l59VfNHpnr +l5W5GTka05 +l5f0QqkiDI +l5jjvBoP59 +l66KQUbt8A +l6BlbEXRbZ +l6Boeh6efe +l6GG4kYzzi +l6VCrZxQGZ +l6W9uAY8cP +l6xifKWK1G +l7wy26yZZ5 +l8dFTVB0KH +l8zARCj6GY +l9KdXAYvCU +l9euIoIQOV +l9gHN0RWEh +lAK88Wl419 +lAh4tJI3XK +lB3e7JW1RZ +lBP5YP4tOO +lBSUj5qLfi +lC2prk2rFs +lC5JIwbClY +lCPSqVTE3Z +lCkXv4a2zy +lCxB0RcfJo +lD36A4PPAc +lDJZJIgsRh +lE6j71uycx +lEFcti5uKu +lEmQQcNPfl +lFS8AMr2WO +lFbfCh2SrU +lFk7muaPZE +lFomxV0xz4 +lFqVHeujpx +lFvtl8ExiT +lGVetbVjQk +lGk407VQ5X +lHV4hNUh4c +lIGmW97qf8 +lIJOsUlNR1 +lIjSASgrIP +lJ4R1q9qPf +lJ6bJw3omX +lJ9jMWtw7w +lJhJgO3ECA +lK1pMJWdgc +lKn70GDDQC +lKs0h59uzP +lKtG6CoTY0 +lNPQ5YhxnL +lNeBSbSffn +lNj6ltCgxx +lNlHC742Br +lNtoM7RpW8 +lOGXjAqJjG +lOM9CE6DwC +lQLciPI5q0 +lQMi99bgvV +lQSACFEPAz +lREG4NB5e4 +lRJKw2Fd27 +lRN7cYA4zw +lSnmbVNttZ +lSoygG0RmK +lT5lg13Op6 +lTyZp3zP70 +lURWvL02az +lURxoMjyxf +lUkjdtmzgM +lUrY6EUdlu +lUw1MRN47p +lV2uT2fZzd +lW2SU7nN91 +lW5cSfIgw9 +lWAikqu1gh +lX6raxrBQb +lXE1QRUlUY +lXFUQiiGj1 +lXOHwFSs9e +lXYVqdmvWv +lYCZuojLmu +lYFmw4jK87 +lZA6T0ax34 +lZGd7zwSOG +lZqKCbuuHz +lZwmOceBOw +layNtXKAJ1 +lbJOHZ9wKU +lc4oAATbzC +lcDgMZPywE +lcdYSoZuff +ldDp0nZyOr +leEAObSZLz +leFsEJQfit +lehZ23l9Oo +lf4X2ajWpY +lfokbrMDgd +lgT6qWzThg +lhAM5jdkKH +lhGXxvbcWo +lhS2nGGZ8b +lhugvTQZMc +liKNQwmvex +lj1FKxrc3z +ljA9GdZqrC +ljAwYqnkf9 +ljNgGYF8Qt +ljYAegb1zm +lkK2UEwocN +lkXm7uJyif +lln7EGIgC6 +lmQ8mE6621 +lmVtO6Nib2 +lmlQXxUJP8 +lmqKiu7wFR +lnHY88WvsB +lnlwCPVNDW +lpXmmAW5Bf +lplVxvwd36 +lq1sWYjjBv +lq2VcXYboR +lqf4HUvWce +lqpJvhwpME +lr1r2PZg8S +lsBjZ4tigY +lslOXF6GBK +lt8k1jNNek +ltOgW3Wgk4 +ltaP2ruNPu +ltpXGZpHIR +luOu0bP49a +lulFomDiMu +luwTz7cq4F +lv1kkKFq41 +lweNpzSe0s +lweVqagO8v +lwhjKucduX +lx76izAJfT +lxIpNnBOkt +lxOEeUjhWf +lxyKFOy5y6 +ly3qMEA6jy +lyeJ3rbUpa +lytYi53B1r +lzJIsyeEx5 +lzt7wrG0uC +m0xXYy1lds +m1CZNYIrb5 +m1D4EbmHsS +m1F3gfz9i2 +m2NePSI5yv +m2VkpftEEk +m3haKWogaz +m3iw5rELEs +m3nX68loC4 +m44fY2VQma +m4alNexQyF +m4zeJvKvLq +m51luB08un +m5BmyeVT5T +m5DBGpWtFv +m5LjSrLTPC +m5TVPiIcgJ +m6FKsK8axW +m6rBJbxaQJ +m74mI0kVoG +m83r7YRpZ8 +m8AKCBYWTx +m8M7ZTPt8S +m9ggwabgzA +m9oBjbls4r +m9qsT4BLVb +m9unPs8GyX +mABFNuckvS +mAFHh8N7xt +mAJL3H0Udv +mAOacXGuL4 +mAQX22mniu +mBABc0neKN +mC18PiQAq2 +mCHfaAS26S +mCa21Kbsg4 +mDBmIii7br +mDhu7jhFhx +mE7BLY9yLC +mEIBHS6WVv +mEJ0r3sSbE +mFC6TKKaD3 +mFRqjKEZS2 +mGHCkHchDm +mGaL5s8NKr +mHG6onHSiF +mHVgj4NlF2 +mHeeAirnjw +mHfCCD80QU +mHkzbVLYuf +mHtTlRWJoQ +mIVf3ofnGB +mIYROUpB5b +mJ6Qfs9Ct8 +mKv799ITJ1 +mKxaiVF7pu +mLGyZd0SGr +mLo3n0S1Jg +mLt8nMAdSm +mM7uR9aXVO +mMg0QrkduT +mNfsoHgzkL +mNzLcKrbnn +mP1OXmQoX0 +mP2unUNvg4 +mPpUgwVTFx +mPxNGdTKPt +mQho2GtwVG +mQrr0oeRf6 +mR0FLq1C9v +mRHwM4NgVS +mRdU0E9TkX +mS0pKH4WTF +mTv7t6Agmx +mUEhUDFRA3 +mUxjLabZVS +mVOVUXubU9 +mVsfBGEXKu +mVwSmzQB0a +mW55EKPsmA +mW911KH3GP +mWT9Zn97tW +mWeTyB5kwj +mWh7klFtTk +mWoGu6sDI5 +mXHq1a4cUb +mY0YaCCeEJ +mY9gPpwpjF +mYFPKslLeS +mYshSaLEfv +mYtOOWFHzB +mYwxpKDC8x +mZnZIhzMor +ma1ekgodhb +maGPeADyg9 +mb4LLmZg6t +mbPTaMuvCf +mbaOrQ9J3N +mbcyS8FVTn +mcT0vdSW7a +mdNTQKHKiZ +mdRXNmUCcm +me50HrcaYG +me6rshz6mp +meR7shVKwn +meiRQaV6ru +mexfgCW7cs +mf3N8tNzzZ +mfM1qBZLeC +mfWkKQiz4J +mfiXjfotd2 +mg4YiMgrOH +mgCUWOtTyU +mhKEPOjRtu +mhnyO49j5r +mhtii7nlvt +mhxRQLGsXR +miPq9J3pgk +miT2lCAG4c +mibg00VuPz +mjY3CM81xO +mkVzQyMiJ8 +mkt0GOL7iv +mkuL1bfrBD +mlbA8uCJjx +mmA2MLndxE +mmClaflsFZ +mmUyU0sX0X +mnROXXivS9 +mnbiA185aP +mnckGEcOol +mndEdRsg85 +moLRZ69uM6 +moQqNo8rIg +mp5kC1bw6Y +mpDfXm1SA3 +mpO09QUHWI +mpc5MG1BfY +mqAdKsTt4s +mqSwpJ9Tim +mqevvr6pW0 +mqr9gSIfpM +mrFM7LMeth +mrFwsvtzU6 +msMfjePg0U +msu0Nfo20S +mtHxWRHJoX +mtwpiFHYwF +muMqqD42tY +mus765Fkm0 +mvYfYX5PFV +mw4LKUHZpw +mwESEVKHQa +mwXqjmYKk2 +mwpMutVSAX +mwqarnAg2c +mx6jHjaUTv +mxP2MPY89y +mycYfB6Z5r +myulezc4QB +mz0365ASr4 +mz38lV9hRN +mzBbU8uG96 +mznMzUfzxj +n0d9PB0OUD +n208cZgWw8 +n2NVYjwl6p +n36jfdQVfk +n3SyTgQKIK +n3WPHniA7o +n3ZqlpCmOU +n4B2pKgJql +n4H9893f3R +n4b5jOu5uJ +n4oUYS4lWp +n4rCmqRaer +n5FFpODr7C +n5Is6HN4K9 +n5KtwEvrE0 +n5PI0eGfib +n5RbbGCdwF +n6bHKVh2dp +n7QQJCaEu1 +n7xgLWUTL9 +n8dGc87weX +n9VA8Rasgn +nABLG6WIFJ +nB8SGVK8o4 +nBKm0b8P5u +nBWRQZqxHE +nBWWDKrKVf +nBwptHyNW2 +nC1GBHcjMJ +nCiSTuid52 +nCqO5E3BCN +nCxS4RwAAH +nD87mSmR6x +nDQMlwcr7L +nEn956jIbm +nErTHRDwGF +nFLwOYobsV +nFS8TPWq1J +nFZpOsHShZ +nFcaUBHz21 +nFnSfeeCCc +nH7hUErotU +nHNjLEcY8x +nHooHRTRlI +nHyvtAqCXf +nIUsvbkFyS +nIuILEIxja +nIzmtts4GT +nJIslwcXr4 +nJL3zs4Luk +nJW05ya8rj +nJqkbVTd08 +nK2nRdmv2m +nKDY3401UN +nKJ4kasMKF +nKVBiKMnTv +nM0MQK5GbV +nMC6Ltc25D +nMDbvQxpSi +nMdmDEJjuE +nN63reZyqk +nN7MBlvjQp +nNBNnxRGpC +nNhhw8tRV0 +nNqBMW1IM4 +nOl8l7JNqo +nOumQRv4wj +nOxbsEO3i2 +nPaeOBuIt8 +nPeFelPknC +nPpQu76YUe +nQ9AB8LpVS +nQA3HZ6MRs +nQl1qLa1vB +nRA9vIURAJ +nSB5ReDaPP +nSaWKo2AU0 +nSkcv1GH0u +nSoLicmRSd +nT84euBHBS +nTwu8yeBXT +nUFEGmmPMs +nUuUxWSEjz +nVAlAYnHOk +nVHAydkqXu +nVPftsTqDU +nVUD9Ge4Gp +nVn3o2BnfG +nWc206cerp +nX3Jcp1qif +nXUqoiumGb +nXWodmbfXo +nY88zoCvqJ +nY9i0ameit +nYEdKCoEi7 +nYIP2uQgBy +nYXFPI8BOJ +nYyXITUUad +nZ9tWxYi01 +nZOj4sKd78 +nZpUkh7x2N +nbgBdCn63z +ncDsREOs0M +ncd7uNNDJ7 +nd2X7wZMJv +neCdwfJMxf +neLNM9UnOQ +neyMl2PIEU +nfCnz5SxZX +nfKqTqD22L +nfrag340DO +ng4bJbpXXN +ngb3zpYOvs +ngkBZHVrzd +nhGkkaTvab +nhR1Ms65bi +niPyogM4k6 +niSXsd8IxU +niaGYqYKw3 +niy4LBTBss +njDBDJljP7 +nkAD4OVKm2 +nkTAQITB0h +nkYvEHvKaU +nkdwHDjyRF +nkexbutdRs +nlJtUhDyEB +nlYoPWt6gJ +nlaibjjbib +nlcQo63qea +nmTB4JSK6d +nn9McC6jvI +nn9TUY0NmR +nnuorN6HPy +nnv9Uz0xu0 +nnvd9JQyyU +nogTfC1qgO +novIxw3eBY +nq2fFSo41Z +nqo0rj48C9 +nqxrcN8zmX +nr3nvFB96c +nrGUrEFZPU +ns4Ea6PSzz +nsDTxTqH3K +nsGxKaBjUB +nsienNx6aG +ntuNsE0oYI +nu904JjWC2 +nuM03izwub +nuMPwfmvlm +nuVpaOs5oe +nuzYAy1iGm +nvM2GCXnsy +nwh3WHLyN6 +nx093iHk13 +ny13foSrEq +nz7okIKfuD +nzOpPAtZ2r +o0nRky24cZ +o1YkCfo3Lj +o1mMncLiEC +o2LaaYqbul +o2ccb0h247 +o2r9hBCYSb +o3LHU7lghm +o3SRZaf58j +o4KKGYggNW +o4zUHYZJZs +o52ag33CRp +o6B7j7M7Cu +o6H0w5bOs5 +o77Gdx35kj +o7VL5a0hDP +o7meAj6sVo +o7pIUA5Tea +o8SD3C7cNU +o8p740vWfJ +o8ynLHOMtM +o9CsE6EMvQ +o9PZjE0wz6 +o9T8thNy3K +o9UxW9czia +o9V2L9YfP5 +o9ZI47ZEdX +o9sRpB9vqp +oASV9kHWet +oBYiXH3ae3 +oBpXq2FE1i +oC6CkRIA7k +oCgtzFNHMq +oCm5ElUc7J +oCmKAyQSl6 +oDQBm9wgAk +oDpihwJJKb +oEDGcpe16i +oEcPPvbM2r +oEnsUyFW18 +oFLLBHc210 +oFPD4hxAiT +oFdaak69tm +oFfqHtPeeQ +oG5HPnJrVw +oGUsAhcNwh +oGf3aTrFZB +oGnoOrpFw9 +oGonQXhfVY +oGyJibu8n7 +oH6iQMiYg8 +oHRT6juIXQ +oHzk73hLfi +oIMNIa5EQz +oIRMNLnbye +oJWRnjOISi +oJZQPQUd5j +oJxd9AV4jB +oKMCwDmT9y +oLdxIcb0WF +oLehRfZrhh +oMBueLZ09V +oMGVnEHhMV +oMhBZPgsKK +oMxnDbA2FT +oNZnaGgnrB +oO4rvKJZMm +oOAZieKXEU +oOE6VeLp8M +oOXXb0UVHh +oPuVhXyFk0 +oQX5X1paJA +oR8xZsmize +oRGmRrRwok +oRZrnHPSXN +oRg4LwwsNR +oRntFfZTpE +oRsmHxVJj7 +oS41xW6ycg +oSEOA9J7dZ +oSmzQaVOqM +oSvpvl66Vk +oTi8pO4337 +oUEeKA9n1l +oVB172Wwoi +oVkvIQnona +oVxBZZOAvd +oW8na0M5eX +oWMa7yR2CL +oWV6l8Rjs2 +oXTdsNNqd0 +oXU9h9JqTw +oXihWW9fTN +oYEWScqcza +oYXboTcS63 +oZ2zTKcTsa +oZT3qgJZB8 +oZTF2JPTDY +oa2C4ZhS9T +oaevJ0EvCU +obkI8EdEZk +obkah8lLsq +oc2G40iCqy +ocXGgN4h0T +ocotnhxRYQ +odF9wgrhSb +odHDh8nsE6 +odJDodnqTH +odQcI2Tvt3 +oeCFtuEaBP +oesdnZENvV +ofOIKSKi2m +ofW2Xn3WNs +ofg4REq8Jl +ofzSL45WHC +ogU8mFJpGb +ogyXJOcFwc +ohZFGiKzx1 +ohhTcZOUSa +ohhyv5KC7n +oiQzAkV4up +ojImglnKOB +ojz7e5BQ3e +okqfjCfcLi +okr5bupTyE +okwF6Y509S +ol6bLhUGxN +olR6O2LYnZ +olTeexI9WZ +olXEIcMnbJ +olYoeEFWZ4 +onFbabfj5i +onPlz4mpqK +onTHzb18be +onUQYG2fhu +ooEWAy3vH0 +ooIILSt88E +oodV1GdivL +oof9phTZqx +oomMovSFh6 +oorxo8XVZ9 +opeU2rQDhP +opioKsBWvc +oqIyMlmyEr +oqwAB2AGSt +orEqqQqX7n +orNiMO7u36 +ori6njk7Td +oslDOTeXca +otA0Wz32aT +otCfVRqCHI +otcB9jlYeN +otew6Cscon +otuGWvt1wt +ovJetjffGH +ovebXimGmi +ovfTnxP0ao +ovoxEzCNtu +ow1PHaBRPL +owLZzWWlVZ +owNRvnedW6 +owXzuNhkk6 +oxS9rM479D +oyGT6fFVFG +ozPULKvTW5 +ozQYMy1SiR +ozYC5aC0D8 +ozzCzJeIDa +p0SUvY0Ore +p0dlZ0XNgx +p1EjkK2Arc +p1p6rOJYJy +p2TWha1Y2O +p2kKlP0u2d +p39uxTcRjc +p3VmLhgg8P +p4IE9AN6HB +p4XUH4fshH +p4aHbFqczo +p4yw8l4OjY +p53g4NDZri +p57EHuSFdx +p5JwJa79R7 +p5s8poHG0j +p62mn58x3g +p66RBHyCj8 +p6wP8CmZ2Q +p8WMCeJuaZ +p9BlBZeTd6 +p9Jk7j2g5k +p9ptcyhbHU +pACQ18PZx1 +pAHEuYZwIe +pAgUg8leJM +pAiywPiIs5 +pB1VtHSYc4 +pB6kdyQAae +pBU7NQhFwN +pC1VmSntJP +pCAnJEaJgo +pCczymAnb2 +pCrfAOg7Ut +pDw3W0v0vM +pE6MZndcin +pETSzcaoGs +pEUOP65vCP +pEZFY81xeC +pFIW3wK5D0 +pFgQ5NyCVL +pFhs27aT2F +pFll0UFeCB +pGLy2gGb0d +pGMhYMaTTN +pGkzjpUeDe +pGqaiWPKM6 +pH4T7IVqNP +pHlg5GpBmk +pHwnhplRLj +pI8V9DSISV +pIOsk7jVxH +pIYAeKIfIO +pIpfRIEUHy +pJq061MjQQ +pJvxsy2nae +pJzigwpLbb +pKRUfUBHp1 +pKWNKJMsmr +pKgIPwAm9y +pLHWWb2ZnI +pMJLhRn2uk +pMdkTfLypg +pMdmuUfERM +pMe8PFn1wv +pNCkJZjvOw +pNbdALl2Lo +pNqEMQWxdB +pOkoHOa8Up +pOwG86VbUt +pPMRp9rSGv +pPoPRiGpgr +pQ0zxuSwFf +pQBWvFceoi +pQKUbUEVjR +pQfGhPw5bc +pQtFGQSe4m +pR3oT9f6qH +pRGBNm3wX1 +pRI4gAkYCl +pRtiVW2xZf +pS0y5Vjcu3 +pSC8TMVX4x +pSS3LrMzS3 +pSXs8CuQVi +pSgSiao8Co +pSkKKHpDVG +pTBJFz1Vru +pTlH2H9nnd +pTpW7uECVH +pUOIKXRCd9 +pUXn7dPCjl +pUc6cciEym +pVD8GW6Bx4 +pVENHum5wM +pVEUZaU0Zh +pVINFpovta +pVp65sj5L3 +pWCEnupsar +pWkgt1hyhp +pWmv3X8kNT +pXD8Q6uu9c +pXkj5enT0Q +pXrrbyRiEB +pY4lqVahyZ +pY73lLbQUh +pYJBybNYu6 +pYQ8EXTVqd +pYaowygDSG +pYzbs4cuzG +pZ6p3LdBUr +pZAuZS2mL8 +pZj7973f81 +pZp2Q4HFnn +pZs4qMXXg9 +pbBulvZaRI +pbU5zje0ZZ +pbtLEe1tjf +pbu92SuhPM +pdJjRH2Biu +pdJw3Z6EKL +pdSvDFOLOe +pe4QVtMXr0 +pepGKk1beQ +pewU7EPnUP +pf2ZDht3bD +pfECWg8zzX +pfHNoL0YXG +pfTC30SqBE +pffjBvKJot +pg1HUBX2xQ +pgRPU2MYAG +pgWvCXwd0Y +pgq8LJxX91 +pgrzJ9lAnM +phXSnNFfJN +phyaiSXlrI +pi0HtJ468q +pi54KcmMKt +piKT9aK3Oq +piMMtFrQbj +pimFzoADym +pitz2xD2Kt +pjDPAVRmFa +pjVj0tMYdD +pjt9SdIfUU +pkBbB6stWu +pkKSlXm1Yj +pke5oIal2Y +pkgkpdqyqy +pkiOBWMRsx +plOryC6lN6 +pljiCvkXVP +pm4E2yviCk +pmMOi1cfY3 +pmPmEiorBj +pmWl7kwv9j +pmhApWlw6e +po0xT9EvWE +porPa5EvLL +pp2bxgHBzZ +ppHjI5Qi9Q +ppk1UKevQi +ppt4qz19UY +ppvm96YiWr +pqlFoixp4B +pqldciu3Ym +prGvt01bIJ +prQETUKCal +psPYV11Bt2 +ptYp7laV0v +pteVaAWiZk +ptpWrOeFHA +puIGAiPjVV +puQWZrsR3A +purul2kHDI +pvDqKdCI4T +pvYk260cRC +pvaywzHzK0 +pvhfCaufUS +pvjQbNiK5Q +pvq47LCBlS +pwONhSILgY +pwPMlYwDap +pwVDZAFad6 +pwVHUHeol8 +pwYoPYkcih +px4tY5QSB5 +px9sc0thLy +pxI212dAVX +pxzNA08Gpn +py7In9mRxC +pyWZljfOzI +pyXXlMgnbM +pzA4qp7nNE +pzDGhv3Kmk +pzGnB1GtZi +pzVAQLcQJA +q1I8mtqROH +q1OoAaKK3Y +q1mdYKOLUi +q24G3L42a0 +q25DNfHQvR +q2BEaqH0BK +q3Rp6lKs3M +q3wSayEIMK +q4X63d0KXM +q4ZfdzGk9E +q4sPULczg8 +q4uNjY2mL6 +q5JbHf0WG2 +q5V9zzkxPN +q5fpebSlJA +q6rich1VdG +q7dIx03QP3 +q8IyMka6hI +q8lk3n56Wo +q8qquj4rMu +q9knHIPEQl +qAEG1PLVgL +qAQ19q3tls +qARnkro1eZ +qAeGpXCdKE +qAqkAsNvsC +qBNfHUi3h6 +qCUOpp76PM +qCepXYGvhB +qD7XTEwDiA +qDMqqcF5ae +qDyUWSrvio +qE6m2re0Xt +qETFGa2DS9 +qEUyxOIv60 +qEkkkjk86k +qErKlyKRu0 +qF29F3bXyQ +qFMLW9XvTd +qGVHlmfExb +qH5BMcPS69 +qH5RHvqrFX +qHi4CcxdIM +qHjQI3tEFX +qHuZ1zlvbg +qIElO6xTQJ +qIUKfjUKx6 +qJHttNQqAL +qKusarfu4L +qL1jisqQ6t +qLZk2HWdJF +qLtzyuOX58 +qMTiEY239K +qMXbUieGaZ +qMdoRmdXjV +qMjcak9Xxv +qNGlqWNoRZ +qNILDjV9rt +qNJw7IDC5A +qNzY8A9x9Q +qOL5n6c0nJ +qOoxf0KgLh +qOprZGGYT8 +qP6hhDBP5h +qPE6xnk72I +qPQLLm4UuL +qPmmTaTd1J +qQAMa8j1Fr +qQJqbGKvoe +qQLthdSRH7 +qQNCFLzpAC +qQRyrvvGoY +qRaedjaePB +qS4HzqiZnO +qTSzhQLma6 +qTp3aZQdtm +qTw7GvSaNx +qU8NT9A6Bh +qUTFqyOL2A +qUoqiFn2Mp +qW8ATl07Hv +qWBKTTraNE +qWpfr63jKl +qX1ma2kpAD +qX53smLIs6 +qXdony8EnG +qY9Ve0UOWz +qYKMyX8DVL +qYhqLlwnHn +qYivbFLWTg +qZ5Om8iL6J +qZpEvXjFUv +qZqpZvkSzd +qZsmRaNsk3 +qaTdBkJqwS +qarVjBiSzc +qbwqBy61mG +qbz2V2vNFc +qcYXxNtzwc +qcceQ26uvA +qczr1hgsiM +qdBSgesuTN +qdC2iDuw9d +qdF5HPpPnd +qdZXP1o3WV +qdhh4wU92G +qdrUJXe7k9 +qdtH7542mW +qdtQ8zhRYc +qe2LyXbuX2 +qe465Sqrfg +qet2fGPf2o +qg2EuEWTU9 +qhU10ybIIV +qhVUG0pdH3 +qiAmAbghEN +qj1CRKYH06 +qj3FPhSpPk +qj9sqZdOb0 +qjWLgsBUzq +qjcqmPmRN2 +qjsVqndlYz +qkROOIZfRU +qkhmXVFqmB +qkpWmEdBfd +qlIQMnOQcD +qoG8KJc1a1 +qod46HONo7 +qosBvlo1Lb +qoupae5P0q +qpaJfEWsGc +qpoPvwshAx +qqBHbLe0nv +qqaU2Mx5lB +qqffSnGJRh +qsETBEnGOr +qss5Ptbv3W +qt5i4bwlBi +qtE7Tyx33x +qtPSCxfBci +qtQsFurFt0 +qti3PllZ8z +qtri6YkHKy +qufoDaX9oK +qvPr6xO0gR +qvUO6iG2iR +qvn4uxFIvb +qx2UMoRpvC +qx2owrZKcU +qxD0oZS8tJ +qxDx5eY6vU +qxUAPfQM97 +qxiN9PrjdR +qxpnd80GzT +qy6RXDmoDS +qy9MiwpVoq +qyB44DVRan +qyJLBOq8fS +qyR16vFC4R +qylIcIBtwq +qyodjBo4a7 +r0oPRbOnTl +r10vMLTLBU +r19RTLAVvt +r28Glmncho +r2c6ISZiLu +r2eLUKUuUo +r2urX1YnFD +r31fkXumK9 +r3tc9CPgQ7 +r59nutZ9X0 +r5N4p2KJRZ +r5Y8WL57CX +r5lqcTTdY8 +r6B0w52DkG +r6axWzn09F +r6juwlDf9b +r6qIsMkuSB +r8TMT6SEts +r8dxHZL9Lh +r8lsgN9aKf +r8o0sspFdp +r9wHAHNCk3 +rAqnSmh1Kp +rAvGqQLWg7 +rAvSkyTcQ9 +rBAlT2V1ec +rBen8IKQrA +rC5IP9gts8 +rCdEXMhmp2 +rCrhTzAp7K +rCzfWPqxqZ +rE2eS6Z1hM +rFA0MeBGxk +rFPHwBUKWF +rFiyjalVQc +rGNK6dgcYt +rGkjFdOE98 +rHYdggFOAe +rIGB1P2O3d +rInHefkhLJ +rMH0MnjCjw +rMcwl8NGPz +rMyJZWv4m0 +rMykTqxeob +rN2UHk3H0s +rNZ9CycPKh +rNZPqZxzhU +rNv7175cG6 +rOasLWUSNJ +rPJ9nEdLCg +rQ34KJUwgd +rR729EOsrt +rR8nGDbDHU +rRBfEKLwl7 +rRU2WzLh7E +rRmug8RiMf +rSODPvIqYp +rSwYbbx4Ht +rU5v4RZxBE +rUECVMh0jR +rUGlWz1MwD +rUnWs2JgNs +rUp1a0QICm +rVytlSWVv1 +rWTaje27O1 +rWq1LDumXw +rX8gfnO15o +rXmkgapQ5N +rY5CHHHVHU +rYm7U3Ek7J +rZerFf4Cbh +raLmkw7Xmf +rb5rPlWz69 +rbMfHMzPLN +rcBJkzPXGV +rcEipqVy1w +rdE2jNgpvt +rdQSeetKnf +re6ymUeuPZ +reWl5pbjma +recahN6xEn +rewl4EQUvV +rf4r6Moehr +rgGU9h5gAh +rhHpDyosfW +rhRWsKmlfR +rheMVIBP2A +rhhPQtDyXi +ri1KkrGNpp +ri8VECsfYL +riEpaA3SJe +riNwQBRLxW +rj6tPFkAm1 +rk27UcXSVD +rl6Ied5y5R +rlJSTTwfyN +rlj4CefxbR +rlpiVQ7RBy +rltU63ir6I +rmD20NevEA +rmEzLoE96Q +rmcH8oDgxj +rmfi0gwxlp +rnu1d63VWw +rnzaNEgOrB +rolpM25DXA +rou5LkzGmd +rp8C6Yjvww +rpMcDQbo5S +rpQGAxhQnl +rqXr23ToPQ +rqhws5z3kN +rqzCPTcPGw +rqzIK2EXW9 +rrAIJn6vg5 +rrFmMwLtAY +rsDehgKvG5 +rt0AT79TdR +rt0Wqeqagw +rt9tytj1bP +rtbZHnlqcC +rtzXKaTiH8 +ru0TxvIUd5 +ruA9rKCdzq +ruNxEw8SdM +ruOZqJvbBa +rvX10zmvVJ +rvZu7GX5fT +rvtP2VIBjA +rwiqghYfvm +rx84Q0C5m7 +rxfQJbY3Hs +rxkI7sxvGa +rxxTZi0ySP +ry0FH0CnxR +ryS1UBZYNE +ryTx9J9AEs +rzRsu21hkZ +rzYvMcarGq +s0R9Nc3wpn +s0S0mkwxK2 +s0U4nm9fgt +s0ibW91BNn +s1ZzNGcb2c +s1df8QHMZT +s2vUffF4kc +s3V1PiOMzb +s3iJNsyV2E +s4Z3YX283Q +s4xZQqQo0Z +s5KrDyn8iB +s5RqXcrnWE +s5kDBF64Be +s5rZKE5zW3 +s5xzSmzrdQ +s6IkwsGdTQ +s6uEzPOooP +s7FPGRjKra +s7SX5Qy17N +s7qhXW6KNl +s7tvT6uxKK +s82eUNaAJa +s84eNBMpFz +s8D259bU7z +s8LdMgEKKw +s8WmaN100d +s9ks25pK8f +sAEbGOQnrH +sAXMaYCwKt +sAc3VIJJbY +sBRQ9FYztF +sBcb4CTI3i +sDRaFuu8CT +sDhRWhKs1y +sDohKffZdy +sEV2SRo7R8 +sFILlKiVUc +sFK2GChngc +sFda72g1ut +sG1zmfdIOa +sG304kQeaw +sG8iQCE6XV +sGWGLkkcNl +sHiMIobLjP +sI27IbSBza +sI3CaVyXdF +sI4u8Z7PGQ +sIb2JvC13j +sIcvlu43gp +sIqGdNkyns +sIqSBN1idV +sIzOFE4i7o +sJ9cApWEhv +sJpn3nszsG +sKEdicO17d +sKj59X6Jnc +sKpQ1Hz4nN +sLEadk9SVB +sLElZIOv9R +sLHXw7sXFn +sLa8sLp0k0 +sLy3Pxw8Jj +sMdBPlU60i +sMeIRcjfHB +sMggaZm6Lz +sNBoRdhzeC +sNCR3ptOUH +sNFkNqlNEA +sOFT2VpZV1 +sOaZngoS18 +sP543Y3SA2 +sP9Dzg7dQW +sPVEGxlWwe +sPu6kZNcbl +sQELR9Umyl +sRKJUNcfCB +sRVRam0MM4 +sRf5NtD8q2 +sS7RTO52Z6 +sSfVSI0NCc +sTL0nxWqfF +sTUsvn7LJG +sTX2F49Idf +sTe9GMkdnf +sUE4nzpjbC +sUGDKVqMNP +sUqAs9p43W +sV0cU4sk3w +sV4UaR5y6G +sWXqFsr69e +sWqvXsWj3w +sY5Wym6128 +sYFJTr8q0L +sYnb7rapqO +sYuZOAI6D6 +sZKkZMGhOn +sal2aJTxBL +sb1DKPT5sz +sbLazma6n3 +sbPBKirgny +sbeLNdTUzn +sbxwctrRQz +scp6wyGbsq +sdFEemztMx +sdSmY44EVg +sdiHcBDBzJ +se1HX0fjBO +se61a5Gf8C +seGjo45AmK +sehMhFtmCg +sffpN4Oxnt +sfgPPLrSgJ +sgUEJMdBW4 +sgjBzMrRXO +sgjNPK3lXR +sgrgRPNO0y +she7iWLRMx +shuhJtHLBp +siTOoa1qer +siYNFzUTbf +sinFsv4QaF +sjBjtRcITQ +sjXgi0vZj8 +sjceVdouII +sjmZP7Eczx +sjuFK4mEcA +skZRNmV8ZH +skf5ML5dNA +slD0euBjBJ +sm7wiIUMir +sn2GrWttu7 +snS0IHKc3u +soPwLeckQD +sobbFigJdY +sohFB4e3ij +spPrLBTUJr +spRZHUubND +sqM7DTsXSw +sqh1HhN797 +srQoQeBKyn +srUYVh8sAR +ss8FcmnjHx +ssOaxrBG8Q +stR1KMVXfL +stSfdtac82 +suV0Yc5TtC +sutb9damps +sviegS0qoV +swq3s74LqT +swsEccHGpy +swz91TESSL +sx466qjkPs +sxxYQVWAWk +syHmRGmXd2 +syK9f8gxza +syiQrqPlYk +sykOLEcEYe +sz94sa4A34 +szJbsIrqxM +szsgMsyiB8 +t0JrySURK6 +t0cCKjx29F +t1jrGUE2DU +t2Jl8bJ6Ja +t2SidYVijn +t2XFXATFuG +t2cSscTMuO +t2xLHmeNwc +t3NKqukRJP +t3abXWWI2f +t3l067Ndyx +t3qFj6XMh1 +t3zELzWxAO +t4QrNuewEE +t4ebm1zVPJ +t4j88S0sgB +t4wkamlgjz +t6EbveIJYC +t6gWjLqgL9 +t78RWwxRhM +t78jxQaZYv +t897FB6oPi +t8miXuoPwf +t8s7l3atFp +t9D3zDrXNA +t9U0lcSH8z +t9YOybFJcb +t9v0ZflxfC +tAPQwIK2vl +tAdMLt3UMn +tAkY5VSMDC +tBChb5XlT5 +tBOR510xTc +tBd22Cnubf +tBeVirjZgW +tBiQBKNd7n +tCEJmRSstz +tCSCEP6mn4 +tD4G6TyaAa +tDa4n0UtKB +tEECICEsj0 +tEOi3g8vPT +tEX0icoHXd +tEz6SWr47G +tF3KQxAwjt +tFTN1lHVWe +tGCEKWDaxD +tGkm74Dyaw +tGsQhBp4Y7 +tGxItzU8o9 +tHUBAcaTVn +tHYZfyjId1 +tHZUfJVupC +tHxCWfPJh9 +tI9oygxWkG +tI9xbIxrQA +tICw5hSAuY +tIxFrtqxMG +tJNIi1GbUe +tJThtwMn4r +tKAFWk9cFY +tKkYJvPxnZ +tL4FG289o5 +tLdYau3Wpl +tNLkFeq2dn +tNMdpqXZpe +tNZaTMtUYJ +tNbmqQO4Gj +tOB1JXqZO2 +tOFLQ4SIYS +tPOPucczDL +tQ2zlofQT5 +tQ92iMf7vh +tR8AQZlKzB +tRbY6wuv5I +tRdTjvHEkY +tRpdqSePBx +tRqqMeRBiq +tRvu76DFFg +tSOFZAPY4X +tT52OaMCss +tTBIQQlxMy +tTXAFYe6Ia +tTlIBXdhZv +tUn1ZAfzVm +tUy0lqclXH +tV10IBbPib +tVGPhJMaHF +tWL3ONtMDA +tWrbDAhGOo +tX0PslqC57 +tX8eCexzIT +tXfaoRsPiM +tY9vDfXmyc +tZ1K7Pfuzl +tZkRdJrBtx +tZvtHyz6sY +taP3kGktJZ +tamBf9uw9M +tb0BGc0WZK +tb3ERtvobj +tbcmCLpSx8 +tc21yu5kcM +tdv4MxmETF +tevNNqMVq2 +texfq0u2hU +tf7JAl6Ho7 +tfLyGHetMe +tfi7iU1y3p +tfzMVz13bD +tfzfcldC9j +tgVgO47Nvw +th1EelAoXN +thXblSzzsi +ti18twqvd3 +ti24quoFwQ +tiKbSv545N +tiSYzAzNW7 +tj3hrPyTgu +tkb2MDMbb7 +tkfYe3B7yL +tl0dJKq0HC +tl8rbiwwqE +tlCyjd1gpq +tlQtOzNakH +tlSllDJEau +tlkuN9rgO7 +tlnPoYLmQQ +tmxkpuUVVT +tnBi6HDINx +tnU1035ZHW +tndhSfSTQj +toEbUUXa75 +toaUW6O7YW +tolYLHgm5q +tp20GbB9ll +tplabAgllk +tqX3aFYOO1 +tqjpCb0ALC +tr9VQ4Gmul +trZDKbMGNf +trnpv3kQJa +tsVWbCcu91 +tscTToULa0 +tsd6kFSaZ9 +tstHgCuELA +tt0PoUenzX +ttPTk5O1m9 +ttemjuu9gF +tuRshsvOFw +tugO51RShl +tvKYdBKZ1Y +tw3cPjoUa3 +twLiq0G5Ya +tws0dQzesM +tx9ZxDxXO7 +txmOxoAWbC +ty4q6iUMg1 +tyULDdByFp +tyV5zuiQQk +tyYMM4zLDP +tymRQpDZND +tyw91QQRDj +tz2vZcioJS +u02mYALC6n +u0Kjk4e4GB +u0MTvxkiVI +u0RXalMPe0 +u0XKSxJxRz +u0yH7R9Bq1 +u17SIWjKPy +u1gV7AqXXj +u1lvVlJWzn +u1pvcoOYEL +u2BIXg8cNl +u2f5aURJgu +u2oE5mJK4T +u377CElAxG +u3BAAGHMij +u3pCabhNNO +u40FhczlOz +u4EY6pw93i +u4wOsIHUye +u5GuXwwX5X +u5bEq9TiNm +u6zU1OL1eP +u7e4ZuILAk +u7i2JNSdmI +u7tz7j1IvD +u7xuPe3j4v +u7ytfcKYM5 +u840s3nI7T +u9Tuhpgs14 +u9gi4V31Rs +u9x63tKJYc +uAjDCMXiYu +uAvmOnTm3X +uBStQRTH3h +uBYvgdouNL +uBgj3WGBsQ +uByr8XjkGf +uC6tXmcAkN +uCViZvIm1t +uDCQw7DZK7 +uECl44nBMj +uETtMZR5xt +uFwoUCYpvT +uG1H5rtWRI +uGU75Zif04 +uGUN6uAXBi +uH7DTIE0CB +uHHHu9hv2E +uHdj0ka4jL +uIYdb1d76Y +uIwM0oswT6 +uJ0OkTOhBi +uJ7VkOYGU4 +uJD7hSXLvA +uJEdjbDLd8 +uLb0CXejOd +uLnsLjSTDl +uM8L8XBFin +uMgEHWCVm6 +uNAU9yRsBp +uNghwAESOi +uO9FscX7Dx +uOBb1Q3mv4 +uOKN9K2tvZ +uOR1OKTTQG +uOVSumJEx5 +uOkjchVGNz +uOy7Qh2Q2k +uPKwmY6QwZ +uPehD3Sw0Z +uR4lRPxP51 +uRBLr8AUte +uSoPXXkXWd +uTYYrHwoRb +uTt1BmGt8x +uUFcJvcxVL +uUI76eW9Yn +uUdWSJkr9a +uVoawUJMC3 +uWPNprwAWN +uWVMe7OIzK +uWj9ljf2pK +uWtjjsX8n2 +uXJgAX2VNh +uXkV39eLR2 +uY7O3BfuT7 +uYCWGRfM5P +uYMcsZYbtq +uYoBSqNP5F +uZR1yhkwGm +uZS3bBHpUc +uaXEoVpe3e +ubJDxsWpI0 +ubKK4CKR1l +ubieWlvQOE +uc4zUALKrI +ucZIYGiYXI +ucsmxzBmJt +ud1XAZwOmc +ud1glkfuoq +udBNmXjU64 +udEJlczey8 +udJbLq5CI0 +udyWlmMlAA +ueVryQ5GcE +uelBgngFW7 +uer0nVkcTB +uf28Rra1YU +ufT655WCHp +ufTuHLkwN7 +ugPQp8EA6Z +uggQLtKXFn +ugnREvLuwZ +uhaSxFGH9N +uiCdPWuxZj +ujKsMLy0GQ +um7HHD1BN5 +umAYUCnaJW +umG8YiTu7T +umMhCH4hh9 +un45fwxLiE +unBqX6Awrh +uncOngmsZO +uoATAQ0Y7i +uoexwNsDw9 +uowi9seWsf +up85sSyD2F +up8pFfaE1E +uqnOd0AWoh +uqqYN9Ri5z +urIrSATuKJ +usIKrsz2vi +usLfXHy1pp +usQULZKfeV +utRnf5DBGP +utlQjTKh7H +uvWFvm2WFo +uw3sKycK7W +uwQBjHX1rm +uwRmtU81tb +uxEkaar3eK +uxhAZrhTql +uy3G2Ra3tm +uyJ7eHV1E3 +uz8eWmqbyt +uzTLkpGjpA +uzjTJnKAoy +uztCY4kqLe +v0BtWUi0Aa +v0K0WKRpQg +v0rTbtxmGv +v11o1TXbUB +v127WsapYf +v1muOEeuvS +v2XM4j2CP9 +v2YbsUbhty +v3BUkhi0cl +v3cQ7ANLNI +v40DkIqyb0 +v4CEucTZJC +v4JAWWRLE6 +v4Jgeyy7AN +v5SQdtwR1w +v5ZhP7D09Y +v5yVlkgURu +v6hGPJhTGC +v7TKlQFJHK +v7b3TTrg4b +v8K7d28U82 +v8YXh2K2zN +v8tKF9Vo3i +v9OjIt4OdG +vAAJ7mhzrV +vABK7c5kZJ +vB14PeYeh8 +vCJxNAZarV +vCNCAcnV9V +vCOXoeLNYV +vCVsvY4vld +vCZPOwN6RI +vCq2bKoepx +vDEBvuuqy7 +vDaAF4RkWI +vDcXZyjnGr +vEKm1n4W7m +vEY9ZBacgh +vEZK8etmdV +vEawT8gOZs +vEovcDYtxD +vEtvBX1XRK +vF9kU1XIiD +vFCpKOEGw1 +vFDanAhzsX +vFMUZSiciA +vFeFoKvU0N +vGA0zJlMAZ +vGjRmIzx4q +vHDPpuLCkX +vHopn9hNxJ +vHrODxUWW1 +vHxlN6Eorp +vIIPSqoFVo +vJlK1RwQ6V +vKKd8ggDlz +vKtxBZG2Qk +vNILFlG3O1 +vNLx6nzATJ +vNPgL7ucqW +vNYXvQxZBK +vNtDDKQFtz +vO8gWSHPds +vOUm2cgqxR +vOtuDJz8q6 +vOzbgtITjM +vPXHNsTXmY +vPaTg2stRm +vPdv6O6E0S +vPhlMC9mXH +vPmItnsWZZ +vPmSdcI3Pb +vPyQhTOtym +vQ02wUJ69g +vQCZYpchx8 +vQDQROeclq +vQrH8Udth8 +vQz6mnKONS +vSQZDlFi1j +vSoNyHcKBG +vSoSh6osW4 +vT762r2J97 +vTlF3ZF2wh +vUUFgb9XWM +vUViEOrWm0 +vUsvW1k9iw +vUzLYp8PIY +vV6yOphAIL +vV8y4oxFpB +vVaN18VOgQ +vVeT9vWnRv +vVhP4N5Kn1 +vVsIUu68C4 +vVsQJoRmLL +vWO6JE3QT2 +vWYXss13mw +vX25pZaULg +vX4us4dn1y +vXuMa2vX74 +vY7SSuMnhy +vYZv8fWV9f +vYp5WBRmur +vZVN8PuTHC +vZc4JxRo97 +vZk0SM3iaK +vZuQe3ZrCa +va3Ou4Uumd +vaFavvC18N +vb87rAQenl +vcFN9hOeQi +vcL7V4TGzW +vcoTYhEJ7W +vdFnuf2iRl +vdHeExPEt0 +vdIKU6w0tk +vdrjXyytDn +ve78H2kxJQ +veO4IoZSHa +veuOQsCiMZ +vfGAqi3giY +vg6salBg4U +vg7tubnKd1 +vgADiWVHKJ +vgj9ZIhkfG +vhS2gGAMkW +vhv59Ssmkf +viJWQgBQpL +viM5yB1Uab +viT0q12Tup +vicb11gI3X +vijw0Sjxcz +vjHHx4qIyJ +vjSjIkUwW6 +vk5YgAExOq +vkOZwaEYHH +vkjvgjAm10 +vl0dqRzfb0 +vlLj3US07z +vlgEv6qaBW +vmTbA7p28R +vmqC8ZlPQ7 +vmwRq0J5Tg +vmyK0dVx4x +vn9eggyGSW +vnBFzegeCO +vnXIj7Mz17 +vpU4JQZ5Hm +vqMpTZu2lO +vqOmb6S4P1 +vqieCE6dug +vqpmCHJBkw +vr4momQrHT +vrI7TqDYaQ +vrZGtnlTBs +vrxP5ZYUF5 +vsY2xQuGuX +vsdamMJOcc +vskJ2f8YLK +vsuR234V9k +vt4MXAC3nY +vtOAty2dQB +vumRkxvLQK +vv7iTtcO4Z +vvWixuiwoo +vvwROfnAXl +vvz9mE6Gr0 +vw87vmV7CS +vwgSwXd5IT +vxZTWwPos7 +vxbW2BK2F5 +vxi8bo3agV +vxrOLoTss0 +vy1gYF0oxR +vyQSgfPYQL +vzr4D2IBHx +w0pNSBMaoB +w0r3cCCGgQ +w10DkTnNsH +w1gF4dKqXM +w20SS1BCQV +w25uKwxX8B +w2bck7JZid +w2f77vxR7l +w2wHtDtwR1 +w3M7W08eQ8 +w4Pa8bmFLG +w4bqXrnKsV +w4kjwU7xwD +w4xDMn4lpU +w55aA0VP60 +w5liKk7Kse +w6GR0aISy5 +w6T6LmAwnc +w7DKl1BcJs +w7iJz5DXpC +w8WfCb1jPH +w8nb0f6e60 +wA4j3qt4B1 +wAvfDWPswT +wBiOIXHI8i +wBySsyvjco +wC5Dc8zaJ5 +wCY1BEFeqi +wCYm6VdsxG +wCySkvgdRF +wDXqm9EFtf +wDlng4d5zd +wDpbI0kdVU +wDxviTjIHi +wEKoPH8Pvz +wEagHp37Ir +wFNgiIvCjI +wFVfHgZc9C +wFbDU6muaY +wFcsLgOS6M +wFdu4KG9fQ +wFfyj5F33s +wFtrwlIAur +wGxP6RxZqa +wIkR3GFv0u +wJ6AKIj7Ts +wJjWw8LcUD +wJvjYQfkGT +wK25S3HVUE +wLUe6NsTfJ +wLj5hhXavn +wLnzPduh5d +wLqVT7Nlgd +wMTWn61Jjv +wMcVb0GTOF +wNOZtlcRzw +wO3XqVcxIf +wOzuyvKo2X +wPd2mkXbRJ +wPfyDGVOdf +wQBW9vWkBp +wQFUw2McSB +wQaCMfoaku +wQgrxaWRLp +wQs4YqW8xV +wQzD5iJtl8 +wRGNWcy7Xa +wRlMPbBXA5 +wRymnucJsv +wS1XSiVmys +wSJmKYRthu +wSijD6wgBS +wUbkXueRhX +wUth0jWOKY +wVBGljNKG4 +wVXTJIDdO6 +wVw1uXlPC8 +wWeXMJ8Wn2 +wWjb91dZY1 +wX4HKJ1SIh +wXK65mc1hI +wXflPE0fSX +wY6LOnodcu +wYUdL7uhsh +wZ9WLdokbJ +wZNQ1Azri9 +wZQ7Nz0vI3 +wZV4Y3RCGD +wZp6YcAhO2 +wZvJFGbERK +wacEMdcPey +waiOB5prpy +wausiazbQ9 +wbVkuAvaQj +wbXIHYbHMm +wc9DZ8MQDl +wcTns15cJm +wcjTE1Zfoa +wcoM30N26C +wcriotVE88 +wcx46PzcAM +wdvGUhIdjM +we9yIgrJ8F +wfFJ43D8Yn +wfjBkDYcSs +wg9jS1kPQM +whNUIgmdeJ +wiEsinwnVZ +wj6aR3Em3r +wjEy4ru4YF +wjTuz1hBi5 +wk3LBuoRiI +wk99j5cJhB +wkT8pjmUZo +wkfMnF9bg6 +wlOl2BCVVZ +wlXOikk0Mu +wlnl9nPUkJ +wm1uaRVCXe +wm9hUGlnWm +wmv8nLIQyi +wnTIGc68y6 +woivdwBvLN +wpH3uWBobY +wpktkjMMdz +wq4lOTL7xP +wqcBEbO7RP +wqdUZNodYI +wrUTfcMqom +wsOhUYix54 +wsThkZzDBM +wsbmBPlcXH +wtNPn9sq6A +wtNTe21hvT +wteXxO66jq +wuRmfOZTZB +wugIjXpM4N +wv3GFde3qZ +wvM8Ra9zpX +wvYLey1wqC +ww6VsKOrcl +wwFxl1vW47 +wwNaWR1QLp +wwW4Uk4cMX +wwisWSfw3q +wxpalrf5mW +wy7E69UEn9 +wyKGajcox3 +wyhRktVUEi +wz61C0Q9lk +wz8UQHnHOA +wzsTwTQVVz +wzsXcbPVIT +x04K88dbQi +x0s59LRxuM +x19VZrKWpD +x2KiG0zyRG +x2QExkR0MD +x3IBZTungH +x4zIvmfuCA +x56aIhLS07 +x5CstObqjG +x5P14SZ2XT +x5XdSQBSo4 +x5e1vumCfc +x6EyB7rsTP +x6doXYWRdE +x6fDHF58nc +x6mxxMnbep +x7HZJWOMq6 +x7RzCQmrBn +x7yNzpEVSr +x86Jrr6D3G +x912CaZrv9 +x98q7w1bq8 +x9DdvEDi7f +x9PUHbIEcZ +x9Pxe4cDj0 +x9U0pkBCsb +x9oSiI3Bdf +xALJ3cwb1f +xARv2Qm6Tj +xAvtdqut06 +xBELXqZvHs +xBSXyCmLCD +xBpkmMpt8l +xCdMIJMem5 +xDaGLBcPri +xDahKBnCDZ +xDnuTL0OCw +xE5npJV9FU +xEgtHeDgGP +xEm9gODzTL +xFXXf0bW9Y +xFYBd4H4Yy +xFa0ie23WK +xGAESdl0mX +xGLAunR33c +xGLer2bhBh +xGX2aogtul +xGberHXYOy +xGuygUVghQ +xH11DevcNi +xHBUJnLP05 +xHbCiLetan +xHf3KiL1za +xHfVB2mWOC +xHr8HUKXFU +xHwnPZ40uR +xIGJXb2DCo +xIbd2fDeiq +xIvfSp09kz +xJ8ap6KEoK +xJHQxdb7PE +xJWOSsTCVl +xJxFGMLnc4 +xKZlGQVb7S +xKxPWb7s80 +xLqHuyytDm +xMvQWK9L4e +xNMLOdqxOC +xNOufUg896 +xNQmCODffB +xNYSxvNJQl +xNiEPOyFDt +xNvMDCFQw6 +xOS4JN6yYI +xPFk8e319L +xQT5khjArh +xQUPVfZNQx +xR8ojMRZgY +xRvM9Y1x3a +xSE2VgDaQz +xSFl5CjcUo +xSpxtZLUY5 +xTRRlYiJpO +xUGm0uUKiw +xUTwMC6fan +xUWzvNvvtN +xUZdFrl1OD +xUl8FZckZ4 +xUwjP9mSwz +xVDnj55tQ2 +xVSZYDYJaw +xVhNQuTbsm +xVnYrzE9jp +xW7a1bT0Js +xWDjAgDVt2 +xWd4nuuGty +xWecS5csPF +xX2C7xJQW3 +xX6HjIEns7 +xXA1XX5sRT +xXdn4i2o46 +xXkxIRFgIs +xXuESOj6l8 +xYHrA8xmUA +xZ78NG3b40 +xZSHIDx0YX +xZtaG4Wo8L +xa0xu5ltaP +xa1iJsEGLu +xaNfLXuzls +xaRMy6SP5j +xbR02Rt24U +xbhSsZxbNa +xc2xwXYbGp +xcNMRFY1tm +xcNcObokNc +xcXXEjVdHg +xd2oYI0u03 +xe0OWDDKIs +xe3a8aAKP9 +xeHWIeFXbs +xeypxrFghF +xfQQytCXhq +xh18puJ3AQ +xhCvvvXhaW +xhhSYxT0hc +xhrvvBaEto +xik6XSbvAJ +xjJTDecsn4 +xk3aYC9fci +xkIYAQFzWM +xkes55FjD4 +xkk3mScmCY +xl2GFgBioA +xlWu7hGoaU +xm9kSCk9Z9 +xmLLmasIOl +xmkbg4E4g9 +xmydjd9CG7 +xnXhsUFuLs +xoLVwyaVrj +xoV3cGeC9F +xoc5tIQm9H +xph4clpxjM +xpiyDuJ3gb +xqO6Je1qJU +xqcoWhmnQE +xrTK5dKLjF +xrUFllBw3X +xsT3rj1Tz6 +xt1VzLreMF +xt57NOp73O +xu1VqIlwEz +xuCAtwEXKc +xuFzPeWnJ1 +xuuCH99cE5 +xv1Y96kdaG +xvgKUsUVuA +xwpbXLyuCo +xx2Grl8FP7 +xx7PlhJGWS +xxDm5cc9Fv +xxRqZy6esY +xxWAG3Iiie +xy85d38GQp +xyINOfSuFK +xz4EcdX8YP +xzETh026ra +xzI4nnooMd +xznUEhaf56 +y0Q220ibuB +y0g1tJqF9k +y0s9AVegPF +y0wT8omTSi +y10AkhO5QA +y1ZwO5lIgt +y2A6f0lnTE +y2AumuesBh +y2aj2MKV79 +y3B1j5zWjY +y3E8NoA1gv +y3ZYX9mQSW +y3auDBj28m +y41BaueVCQ +y4hyyI7EBA +y5ITfNu606 +y5XEeGadzI +y5XTJk67AT +y5z4t135IC +y7CXbZCtUa +y7ES0WDqCU +y84OmuapuW +y890ZtMgh7 +y8C4EHOpud +y8kAJQcEJx +y985doxWAr +y98EGKU7nd +y9L9zOuMtH +yAPn3aEXeG +yAU8wsbdNL +yBZjXph3gF +yBlrwCHe8a +yBwh2hnn0P +yCcTyMEA3j +yCiq1zzfmF +yDNXKG1shb +yF3FofjQLE +yFUeMWC092 +yGQYvWbthy +yGjj3JE31N +yGn8PZ2SVu +yHSlWIC1pP +yI0u65hzqq +yI5aPlGZvq +yIblCs5W2y +yId6pCCWZi +yIo7XTM3DW +yJwTksEMfm +yK60MaZn2u +yKkJmEZb5c +yLMgQZpFSR +yMNTDA1BdC +yMUzKU801o +yMWkIYc82O +yMiQvOsk4T +yN2kRxohVF +yPhrxrBose +yQhEQQ0CQt +yR3Iud2nQ1 +yRW1vkelsz +yRXNEgflcv +ySC9Oo1xTb +ySEwMiWhjG +ySgvU3aYC8 +ySskYsXBM1 +yTQJdev3rJ +yTfDPVKAyo +yTr0nG7eX4 +yU1SaGkRXH +yU2XL2oQgg +yUA3RUx7gK +yUOhGwz2xZ +yUbxaEDQtP +yUqIlJdTKm +yUyTylKB5o +yVBDs3EB84 +yWOzgEyvOU +yWRUmD0lqI +yWZwEL6u8R +yWfU0QjXrB +yWgt7PSTUP +yWoy1w9Ru8 +yXoebrDPp1 +yYoreDBVMF +yZ754hJzBY +yZ7jhsye0a +yZEcAhUlku +yZFPwvC0Ug +yZQEAITZNv +yZbagdncwt +yZmQzSLzHP +yaWXD5l6L9 +ybKmewO9LS +ybRJY7IOqA +yc3jsXacaI +ycKkrde753 +yd1QRiw23x +yd1gMsERig +ydMRDz7owD +ydimy0panT +yeBDimhEqs +yeHz30FVi0 +yenSYFkiMH +yfMRKoMHg2 +yfbwfzUejK +yflbfu5LHh +ygT2sEtb6m +yh0hvrq6ol +yhHklKDn24 +yhu6Y6MzvW +yjl8VVp2Sl +yjqeB4lvrX +ykDRXeftIc +ykQSms9mWJ +yl0yJzzp9l +ylhtXGl6PP +ylnQREf6Ik +ymp0vEFcTN +yntvcY1Vn3 +yoVwfaRrmT +ypAzocimts +ypSiI9JX25 +ypiN1DilX8 +yq8M8748Ms +yqOq5183ml +yqlP1qxCFr +yrsXAxsfj6 +ysFSvdWkcv +ysbFR6tExw +ytBNO3MJ5J +ytRvi6SHp7 +ytf9FpYZ4T +yuS5eRyC19 +yv0q8p1NU5 +yvngfFshQs +yvsNeU68vY +yyDIQXDMGi +yyJN49ixsx +yyfCOQS8cI +yz7SSfeqcM +z09cdnsvjk +z1AMpsWMdq +z1MMWDn2f2 +z1lOyRKTkw +z1vCn0gOpG +z2KOLBojVk +z2vAbyiNk5 +z2wEGmks3U +z32BWyo3vz +z4aNNZyPfq +z4djUFQvVe +z4ldR1gndx +z5nLiQ0DA2 +z5rVOcNuIV +z5xzhZOa13 +z64co1fRZ2 +z6Xmou2ile +z7AKweiKFS +z7GwiIoFrd +z7awAKkj6J +z7jJfFQmBb +z7vKdGuAcH +z82paGvSKN +z85WcOgMFb +z8LH1tqkek +z8SMtrWivj +z8SawLFKZJ +z9Yqe461Is +z9uHQpc2Pf +zA0VCVDKNH +zA1A5qCpIc +zA6FaMKLAo +zAr0v4cmA4 +zBBLmKCYBk +zBUIfBrv0Z +zBaj38LpNA +zBhpFVa0nT +zBjH8YV40K +zBlWoj5S7M +zBmob3iWKS +zBu3tBkqol +zC4WAIPEv9 +zCwQBRd9Jg +zDRwwVruS5 +zDhsJGIx5h +zDq1SJNv2r +zEUA9nNjTW +zEb1da8m9S +zEfEDsKaod +zEz76KFfrb +zFADrWnOr9 +zFnRW4dc00 +zFz8tCQFoC +zGOYkZPKEa +zGXsrc4Lyc +zGf3WUP03g +zGqu342otm +zGx9qlUL8Y +zHQaxyCvf3 +zHdOPQLCdK +zHfzqDa0oY +zHmDpbSRrk +zJ4uaCbK4V +zJHn7DpVhn +zK6P1d0XU2 +zK9JbA5m9y +zKcrYHZPAe +zKoDHvcBRq +zL4MZLicDa +zM7UmfPSfY +zMiHWgLwRn +zNIO2SdDWV +zNPd21HMNl +zNVcSjrYgT +zNapzPIADK +zNlPU1Y39w +zOAewRydx5 +zOUKTUevbg +zOjX9vzo3T +zP1IvGa7Yz +zPXi6R7mxs +zQ8AsSAXTC +zQFNxAOUyu +zQhnN1O0VU +zR2Te8pPiw +zRLUWacMSC +zRNndDmYwH +zRSu7Cv8cC +zRTHUoxNFN +zS1OhkBSfn +zSJe54FcWF +zSxr89SDq4 +zTM021vOZ1 +zTctYMYTMj +zUWXc3wg4W +zUg9iCvyw8 +zUyulTwKD5 +zV25NrhMfj +zVdncbQu8p +zWXsEGFN6W +zWkr7XdS8m +zXIrgE7IsV +zYQwHuwx6L +zYakZuXk0o +zYhISRAy6q +zYpgkRb4Y0 +zYsFA0hnTG +zYuCARnQdQ +zYvv1GcdaR +zZ9zpLPHqz +zZJ1Xe5YLR +zaBeBwzE2a +zaCYoZG1Zl +zaFVtjvJ4Q +zb1BmttIAT +zbqmgVPbVj +zcFFe85Lwp +zcFyOpfst3 +zd3T3S9rCq +zdExy49xEi +zdaQWE74un +ze3vx2n4gJ +ze7dCLh3sy +zeGWi95ASg +zeLEKkfuIk +zeloWzgmx6 +zfLcYkcz5G +zftKguGpkz +zgEkUZq7wZ +zgVIgQW1K4 +zgum5DmgeD +zgzL3qj9Sr +zhRJNpoxBx +zhsNwcFVj1 +ziBSboVdz9 +zjCe74le7b +zjPjll8Pki +zjVAMYtvv7 +zjlzTN1AWm +zkTyIhMV60 +zkWzDB83gP +zkvbikovaE +zlMZM3lMfn +zliV2vm4sD +zlsjC0livn +zlub8Ub4fm +zm0ZcVglDe +zn2hxIhs7L +znJ188PV9m +znqb1gOBFX +zoRejFqtLr +zpQCV1AbWP +zpip9dr3Eo +zqeSA5GB2R +zqhkX5rvir +zqxl3nebQj +zrAF7vG0eV +zruAECPWIt +zrzlaHisfv +zs0m3RWi4w +zsPL8OLiyF +zsY9SnxlnW +zsZdKq8UFg +ztHxCNXKJi +ztb0GboSM5 +ztufXiUMbm +ztvqNVwXin +zuUiLoEnpB +zuiTYQ5Mvc +zv5N2VmNNm +zvKRi7cWbp +zvSxLts9Mn +zvhapzgIbl +zvnPz3gKrI +zwQIhkrA6y +zwU8pjlcAM +zy7BZKdXww +zyJgwDRegx +zyK0qWaGKD +zyRv5hmbKL +zyjkEHpXfx +zzCDxO3hNA +zzqKqwneZI diff -Nru mdds-2.1.1/quickcheck/flat_segment_tree.cpp mdds-3.1.0/quickcheck/flat_segment_tree.cpp --- mdds-2.1.1/quickcheck/flat_segment_tree.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/quickcheck/flat_segment_tree.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,512 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ - -using quickcheck::Property; - -using std::ostream; -using std::pair; -using std::string; - -typedef mdds::flat_segment_tree fst_type; -typedef fst_type::key_type key_type; -typedef fst_type::value_type value_type; - -class fst_wrapper -{ -public: - fst_type* get() const - { - return m_pimpl.get(); - } - fst_type& operator*() const - { - assert(initialized()); - return *get(); - } - fst_type* operator->() const - { - assert(initialized()); - return get(); - } - - bool initialized() const - { - return m_pimpl.get(); - } - - void initialize(key_type low_, key_type high_, value_type value_) - { - assert(!initialized()); - m_pimpl.reset(new fst_type(low_, high_, value_)); - } - -private: - std::shared_ptr m_pimpl; -}; - -template -ostream& -operator<<(ostream& out_, mdds::flat_segment_tree const& fst_) -{ - out_ << "["; - bool first(true); - typedef typename mdds::flat_segment_tree::const_iterator - iterator_type; - iterator_type cur(fst_.begin()); - for (iterator_type end(fst_.end()); cur != end; ++cur) - { - if (first) - first = false; - else - out_ << ", "; - out_ << cur->first << ": " << cur->second; - } - out_ << ", " << cur->first << "), default = " << fst_.default_value(); - return out_; -} - -ostream& operator<<(ostream& out_, fst_wrapper const& fst_) -{ - return fst_.initialized() ? out_ << *fst_ : out_; -} - -template -struct generator -{ - generator(size_t n_) - : m_n(n_) - { - } - - T operator()() const - { - using quickcheck::generate; - T val; - generate(m_n, val); - return val; - } - -private: - size_t m_n; -}; - -void generate(size_t n_, fst_wrapper& fst_) -{ - using quickcheck::generate; - value_type default_value; - generate(n_, default_value); - - // generate a number of segments - size_t segments(0); - generate(n_, segments); - segments = std::max(segments, 1); - - using std::set; - set points; - { - size_t count(segments + 1); - while (count > 0) - { - generator gen(n_); - if (points.insert(gen()).second) - --count; - } - } - - using std::vector; - vector values; - values.reserve(segments); - std::generate_n( - std::back_inserter(values), segments, generator(n_)); - - fst_.initialize(*points.begin(), *points.rbegin(), default_value); - - // insert segments - if (segments >= 2) - { - assert(points.size() == values.size() + 1); - - typedef set::const_iterator points_iterator; - points_iterator last(points.begin()); - points_iterator cur(points.begin()); - points_iterator end(points.end()); - typedef vector::const_iterator values_iterator; - values_iterator cur_val(values.begin()); - values_iterator end_val(values.end()); - ++cur; - while (cur != end && cur_val != end_val) - { - fst_->insert_back(*last, *cur, *cur_val); - last = cur; - ++cur; - ++cur_val; - } - } -} - -bool is_valid_key(fst_type const& fst_, key_type const& key_) -{ - return key_ >= fst_.begin()->first && key_ < fst_.rbegin()->first; -} - -bool is_valid_range(fst_type const& fst_, key_type const& low_, key_type const& high_) -{ - return low_ < high_ && is_valid_key(fst_, low_) && is_valid_key(fst_, high_); -} - -bool is_empty_tree(fst_type const& fst_) -{ - return fst_.rbegin()->first - fst_.begin()->first == 1; -} - -bool is_single_segment(fst_type const& fst_) -{ - fst_type::const_iterator begin(fst_.begin()); - ++begin; - return begin == fst_.end(); -} - -class FlatSegmentTreeInsertProperty - : public Property -{ -public: - typedef fst_type::const_iterator const_iterator; - - virtual bool - accepts( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const&) - { - return is_valid_range(*fst_, low_, high_); - } -}; - -class FlatSegmentTreeChangeProperty - : public FlatSegmentTreeInsertProperty -{ -public: - virtual bool - isTrivialFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const&) - { - return is_empty_tree(*fst_); - } -}; - -class PInsertFrontIsSameAsInsertBack : public FlatSegmentTreeChangeProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type insert_front(*fst_); - fst_type insert_back(*fst_); - insert_front.insert_front(low_, high_, value_); - insert_back.insert_back(low_, high_, value_); - return insert_front == insert_back; - } -}; - -class PInsertIsSameAsInsertBack : public FlatSegmentTreeChangeProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type insert(*fst_); - fst_type insert_back(*fst_); - insert.insert(insert.begin(), low_, high_, value_); - insert_back.insert_back(low_, high_, value_); - return insert == insert_back; - } -}; - -class PRepeatedInsertDoesNothing : public FlatSegmentTreeChangeProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type fst(*fst_); - const_iterator const pos(fst.insert_front(low_, high_, value_).first); - fst_type orig(fst); - fst.build_tree(); - pair result(fst.insert(pos, low_, high_, value_)); - return !result.second && result.first == pos && fst == orig; - } -}; - -class PKeyInLimitsIsFound : public FlatSegmentTreeInsertProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type fst(*fst_); - value_type dummy; - pair result(fst.search(low_, dummy)); - - return result.second && result.first != fst.end() && - result.first->first <= low_; - } -}; - -class PKeyInInsertedSegmentIsFound : public FlatSegmentTreeChangeProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type fst(*fst_); - pair - insert(fst.insert_front(low_, high_, value_)); - value_type value; - pair search(fst.search(insert.first, low_, value)); - return search.second && search.first == insert.first && value == value_; - } -}; - -class PSearchTreeIsSameAsSearch : public Property -{ - virtual bool holdsFor(fst_wrapper const& fst_, key_type const& key_) - { - fst_type fst(*fst_); - value_type value; - key_type low; - key_type high; - pair search(fst.search(key_, value, &low, &high)); - - if (!fst.is_tree_valid()) - fst.build_tree(); - value_type value_tree; - key_type low_tree; - key_type high_tree; - bool const search_tree(fst.search_tree(key_, value_tree, &low_tree, &high_tree)); - return search.second == search_tree && low == low_tree - && high == high_tree && value == value_tree; - } - - virtual bool accepts(fst_wrapper const& fst_, key_type const& key_) - { - return is_valid_key(*fst_, key_); - } -}; - -class PSearchDoesNotChangeTree : public Property -{ - virtual bool holdsFor(fst_wrapper const& fst_, key_type const& key_) - { - fst_type& orig(*fst_); - fst_type fst(orig); - value_type dummy; - fst.search(key_, dummy); - return fst == orig; - } - - virtual bool accepts(fst_wrapper const& fst_, key_type const& key_) - { - return is_valid_key(*fst_, key_); - } -}; - -class PBuildTreeDoesNotChangeTree : public Property -{ - virtual bool holdsFor(fst_wrapper const& fst_) - { - fst_type& orig(*fst_); - fst_type& fst(orig); - fst.build_tree(); - return fst == orig; - } - - virtual bool isTrivialFor(fst_wrapper const& fst_) - { - return fst_->is_tree_valid(); - } -}; - -class PShiftLeftRemovesSomething : public Property -{ - virtual bool - holdsFor(fst_wrapper const& fst_, key_type const& low_, key_type const& high_) - { - fst_type& orig(*fst_); - fst_type fst(orig); - fst.shift_left(low_, high_); - return fst != orig; - } - - virtual bool - accepts(fst_wrapper const& fst_, key_type const& low_, key_type const& high_) - { - return is_valid_range(*fst_, low_, high_) && !is_single_segment(*fst_); - } -}; - -class PShiftRightWorks : public Property -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& key_, key_type const& size_, - bool const& skip_start_) - { - fst_type& orig(*fst_); - fst_type fst(orig); - fst.shift_right(key_, size_, skip_start_); - return isTrivialFor(fst_, key_, size_, skip_start_) ? fst == orig : fst != orig; - } - - virtual bool - accepts( - fst_wrapper const& fst_, key_type const& key_, key_type const& size_, - bool const&) - { - return is_valid_key(*fst_, key_); - } - - virtual bool - isTrivialFor( - fst_wrapper const& fst_, key_type const& key_, key_type const& size_, - bool const& skip_start_) - { - return - (is_single_segment(*fst_) && fst_->begin()->second == fst_->default_value()) - || size_ == 0 - || (skip_start_ && key_ == fst_->max_key() - 1); - } -}; - -bool keys_ordered(fst_type const& fst_) -{ - fst_type::const_iterator cur(fst_.begin()); - fst_type::const_iterator end(fst_.end()); - fst_type::const_iterator last(cur); - ++cur; - while (cur != end) - { - if (last->first >= cur->first) - return false; - ++cur; - } - return last->first < cur->first; -} - -class PKeysOrderedAfterInsert : public FlatSegmentTreeInsertProperty -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type fst(*fst_); - fst.insert_front(low_, high_, value_); - return keys_ordered(fst); - } - - virtual bool - isTrivialFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - value_type const& value_) - { - fst_type fst(*fst_); - return !fst.insert_front(low_, high_, value_).second; - } -}; - -class PKeysOrderedAfterShiftLeft : public Property -{ - virtual bool - holdsFor(fst_wrapper const& fst_, key_type const& low_, key_type const& high_) - { - fst_type fst(*fst_); - fst.shift_left(low_, high_); - return keys_ordered(fst); - } - - virtual bool - accepts(fst_wrapper const& fst_, key_type const& low_, key_type const& high_) - { - return is_valid_range(*fst_, low_, high_); - } - - virtual bool - isTrivialFor(fst_wrapper const& fst_, key_type const& low_, key_type const& high_) - { - fst_type& fst(*fst_); - return is_single_segment(fst) && fst.begin()->second == fst.default_value(); - } -}; - -class PKeysOrderedAfterShiftRight : public Property -{ - virtual bool - holdsFor( - fst_wrapper const& fst_, key_type const& key_, key_type const& size_, - bool const& skip_start_) - { - fst_type fst(*fst_); - fst.shift_right(key_, size_, skip_start_); - return keys_ordered(fst); - } - - virtual bool - accepts( - fst_wrapper const& fst_, key_type const& key_, key_type const& size_, - bool const&) - { - return is_valid_key(*fst_, key_); - } - - virtual bool - isTrivialFor( - fst_wrapper const& fst_, key_type const& low_, key_type const& high_, - bool const&) - { - fst_type& fst(*fst_); - return is_single_segment(fst) && fst.begin()->second == fst.default_value(); - } -}; - -} - -int main() -{ - size_t const tests(200); - using quickcheck::check; - check( - "insert_front is the same as insert_back", tests); - check("insert is same as insert_back", tests); - check("repeated insert does nothing", tests); - check("key in tree limits is found", tests); - check( - "key in just inserted segment is found at the right pos", tests); - check("search_tree is the same as search", tests); - check("search does not change tree", tests); - check("build_tree does not change tree", tests); - check("shift_left removes something", tests); - // check("shift_right works", tests); - check("keys remain ordered after insert", tests); - check("keys remain ordered after shift_left", tests); - check("keys remain ordered after shift_right", tests); -} - -// vim: set ts=4 sw=4 et: diff -Nru mdds-2.1.1/test/Makefile.in mdds-3.1.0/test/Makefile.in --- mdds-2.1.1/test/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -470,7 +470,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/flat_segment_tree/Makefile.in mdds-3.1.0/test/flat_segment_tree/Makefile.in --- mdds-2.1.1/test/flat_segment_tree/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/flat_segment_tree/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -430,7 +430,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/flat_segment_tree/test_main.cpp mdds-3.1.0/test/flat_segment_tree/test_main.cpp --- mdds-2.1.1/test/flat_segment_tree/test_main.cpp 2023-04-19 19:28:17.000000000 +0000 +++ mdds-3.1.0/test/flat_segment_tree/test_main.cpp 2025-07-05 20:22:32.000000000 +0000 @@ -142,10 +142,10 @@ db.insert_back(4, 6, "4-6"); db_type::const_iterator it = db.search(-1); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.search(8); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); struct check { @@ -164,36 +164,36 @@ for (const auto& c : checks) { it = db.search(c.key); - assert(it != db.end()); - assert(it->first == c.start); - assert(it->second == c.value); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->first == c.start); + TEST_ASSERT(it->second == c.value); auto sit = it.to_segment(); - assert(sit->start == c.start); - assert(sit->end == c.end); - assert(sit->value == c.value); + TEST_ASSERT(sit->start == c.start); + TEST_ASSERT(sit->end == c.end); + TEST_ASSERT(sit->value == c.value); } // variant of search() with a position hint it = db.search(db.begin(), -1); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.search(db.begin(), 8); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.begin(); for (const auto& c : checks) { it = db.search(it, c.key); - assert(it != db.end()); - assert(it->first == c.start); - assert(it->second == c.value); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->first == c.start); + TEST_ASSERT(it->second == c.value); auto sit = it.to_segment(); - assert(sit->start == c.start); - assert(sit->end == c.end); - assert(sit->value == c.value); + TEST_ASSERT(sit->start == c.start); + TEST_ASSERT(sit->end == c.end); + TEST_ASSERT(sit->value == c.value); } } @@ -318,32 +318,32 @@ typedef std::pair ret_type; ret_type ret = db.search_tree(0, val, &start, &end); - assert(ret.second); - assert(start == 0 && end == 5 && val == 0); - assert(ret.first == db.begin()); + TEST_ASSERT(ret.second); + TEST_ASSERT(start == 0 && end == 5 && val == 0); + TEST_ASSERT(ret.first == db.begin()); ret = db.search_tree(6, val, &start, &end); - assert(ret.second); - assert(start == 5 && end == 10 && val == 2); + TEST_ASSERT(ret.second); + TEST_ASSERT(start == 5 && end == 10 && val == 2); fst_type::const_iterator check = db.begin(); ++check; // 5-10 is the 2nd segment from the top. - assert(ret.first == check); + TEST_ASSERT(ret.first == check); ret = db.search_tree(17, val, &start, &end); - assert(ret.second); - assert(start == 15 && end == 18 && val == 3); + TEST_ASSERT(ret.second); + TEST_ASSERT(start == 15 && end == 18 && val == 3); std::advance(check, 2); - assert(ret.first == check); + TEST_ASSERT(ret.first == check); ret = db.search_tree(55, val, &start, &end); - assert(ret.second); - assert(start == 28 && end == upper && val == 0); + TEST_ASSERT(ret.second); + TEST_ASSERT(start == 28 && end == upper && val == 0); std::advance(check, 3); - assert(ret.first == check); + TEST_ASSERT(ret.first == check); ret = db.search_tree(upper + 10, val, &start, &end); - assert(!ret.second); // This search should fail. - assert(ret.first == db.end()); + TEST_ASSERT(!ret.second); // This search should fail. + TEST_ASSERT(ret.first == db.end()); } void fst_test_tree_search_2() @@ -358,10 +358,10 @@ db.build_tree(); db_type::const_iterator it = db.search_tree(-1); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.search_tree(8); // out-of-bound - assert(it == db.end()); + TEST_ASSERT(it == db.end()); struct check { @@ -380,14 +380,14 @@ for (const auto& c : checks) { it = db.search_tree(c.key); - assert(it != db.end()); - assert(it->first == c.start); - assert(it->second == c.value); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->first == c.start); + TEST_ASSERT(it->second == c.value); auto sit = it.to_segment(); - assert(sit->start == c.start); - assert(sit->end == c.end); - assert(sit->value == c.value); + TEST_ASSERT(sit->start == c.start); + TEST_ASSERT(sit->end == c.end); + TEST_ASSERT(sit->value == c.value); } } @@ -395,9 +395,9 @@ { int r_val, r_start, r_end; if (db.search_tree(key, r_val, &r_start, &r_end).second) - assert(r_val == val && r_start == start && r_end == end); + TEST_ASSERT(r_val == val && r_start == start && r_end == end); else - assert(!"tree search failed!"); + TEST_ASSERT(!"tree search failed!"); } template @@ -440,7 +440,7 @@ const typename flat_segment_tree::const_iterator& end, const key_type* keys, const value_type* values, size_t key_size) { - assert(key_size > 1); + TEST_ASSERT(key_size > 1); typedef flat_segment_tree container; typename container::const_iterator itr; @@ -495,7 +495,7 @@ const typename flat_segment_tree::const_reverse_iterator& end, const key_type* keys, const value_type* values, size_t key_size) { - assert(key_size > 1); + TEST_ASSERT(key_size > 1); typedef flat_segment_tree container; typename container::const_reverse_iterator itr; @@ -552,61 +552,61 @@ db_type db(0, 100, 0); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 0, 0, 0, 100); test_single_tree_search(db, 99, 0, 0, 100); db.insert_front(0, 10, 1); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 0, 1, 0, 10); test_single_tree_search(db, 5, 1, 0, 10); test_single_tree_search(db, 9, 1, 0, 10); test_single_tree_search(db, 10, 0, 10, 100); db.insert_front(0, 100, 0); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 0, 0, 0, 100); test_single_tree_search(db, 99, 0, 0, 100); db.insert_front(10, 20, 5); db.insert_front(30, 40, 5); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 10, 5, 10, 20); test_single_tree_search(db, 20, 0, 20, 30); test_single_tree_search(db, 30, 5, 30, 40); test_single_tree_search(db, 40, 0, 40, 100); db.insert_front(18, 22, 6); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 18, 6, 18, 22); test_single_tree_search(db, 22, 0, 22, 30); test_single_tree_search(db, 30, 5, 30, 40); db.insert_front(19, 30, 5); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 19, 5, 19, 40); db.insert_front(-100, 500, 999); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.is_tree_valid()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db.valid_tree()); test_single_tree_search(db, 30, 999, 0, 100); } @@ -624,23 +624,23 @@ // invalid segment ranges -- these should not modify the state of the // tree, hence the tree should remain valid. db.shift_left(5, 0); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_left(95, 120); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_left(105, 120); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_left(-10, -5); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_left(-10, 5); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); // shift without removing nodes (including the lower bound). db.shift_left(0, 5); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { std::vector key_checks; @@ -652,12 +652,12 @@ key_checks.push_back(65); key_checks.push_back(75); key_checks.push_back(100); - assert(db.verify_keys(key_checks)); + TEST_ASSERT(db.verify_keys(key_checks)); } // shift without removing nodes (not including the lower bound). db.shift_left(1, 6); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { std::vector key_checks; @@ -669,13 +669,13 @@ key_checks.push_back(60); key_checks.push_back(70); key_checks.push_back(100); - assert(db.verify_keys(key_checks)); + TEST_ASSERT(db.verify_keys(key_checks)); } // shift without removing nodes (the upper bound of the removed segment // coincides with a node). db.shift_left(5, 10); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { std::vector key_checks; @@ -687,76 +687,76 @@ key_checks.push_back(55); key_checks.push_back(65); key_checks.push_back(100); - assert(db.verify_keys(key_checks)); + TEST_ASSERT(db.verify_keys(key_checks)); } // shift with one overlapping node. db.shift_left(1, 11); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 15, 25, 35, 45, 55, 100}; int vals[] = {0, 5, 0, 10, 0, 15, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // shift with two overlapping nodes. db.shift_left(2, 30); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 2, 7, 17, 27, 100}; int vals[] = {0, 5, 10, 0, 15, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // shift with both ends at existing nodes, but no nodes in between. db.shift_left(0, 1); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 6, 16, 26, 100}; int vals[] = {5, 10, 0, 15, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // shift with both ends at existing nodes, no nodes in between, and // removing the segment results in two consecutive segments with identical // value. The segments should get combined into one. db.shift_left(16, 26); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 6, 100}; int vals[] = {5, 10, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // insert two new segments for the next test.... db.insert_front(10, 20, 400); db.insert_front(30, 40, 400); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 6, 10, 20, 30, 40, 100}; int vals[] = {5, 10, 0, 400, 0, 400, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // same test as the previous one, but the value of the combined segment // differs from the value of the rightmost leaf node. db.shift_left(20, 30); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 1, 6, 10, 30, 100}; int vals[] = {5, 10, 0, 400, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // remove all. db.shift_left(0, 100); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); } @@ -773,7 +773,7 @@ { int keys[] = {0, 100}; bool vals[] = {false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } db.insert_front(20, 100, true); @@ -781,47 +781,47 @@ { int keys[] = {0, 20, 100}; bool vals[] = {false, true}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // This should insert a new segment at the end with the initial base value. db.shift_left(80, 100); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 20, 80, 100}; bool vals[] = {false, true, false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // This should not modify the tree since the removed segment already has // the initial base value. db.shift_left(85, 100); - assert(db.is_tree_valid()); // tree must still be valid. + TEST_ASSERT(db.valid_tree()); // tree must still be valid. build_and_dump(db); { int keys[] = {0, 20, 80, 100}; bool vals[] = {false, true, false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Insert a new segment at the end with the value 'true' again... db.insert_front(85, 100, true); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 20, 80, 85, 100}; bool vals[] = {false, true, false, true}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } db.shift_left(90, 95); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 20, 80, 85, 95, 100}; bool vals[] = {false, true, false, true, false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } } @@ -831,21 +831,21 @@ flat_segment_tree db(0, 100, false); db.insert_front(0, 100, true); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 100}; bool vals[] = {true}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } db.shift_left(10, 20); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 90, 100}; bool vals[] = {true, false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } db.insert_front(0, 10, true); @@ -853,21 +853,21 @@ db.insert_front(20, 60, true); db.insert_front(60, 80, false); db.insert_front(80, 100, true); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 10, 20, 60, 80, 100}; bool vals[] = {true, false, true, false, true}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } db.shift_left(0, 70); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 10, 30, 100}; bool vals[] = {false, true, false}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } } @@ -885,114 +885,114 @@ db.insert_front(60, 70, 6); db.insert_front(70, 80, 7); db.insert_front(80, 90, 8); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); // shifting position is at the lower bound. The leftmost segment has a // non-zero value which needs to be preserved after the shift by adding a // new node. db.shift_right(0, 5, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 100}; int vals[] = {0, 15, 1, 2, 3, 4, 5, 6, 7, 8, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // shifting position is at the lower bound, and after the shift, the upper // bound of the last non-zero segment (10) becomes the upper bound of the // global range. db.shift_right(0, 5, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; int vals[] = {0, 15, 1, 2, 3, 4, 5, 6, 7, 8}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Shift by some odd number. db.shift_right(0, 49, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 59, 69, 79, 89, 99, 100}; int vals[] = {0, 15, 1, 2, 3, 4}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Shift so that the 2nd node from the right-most node becomes the new // right-most node. db.shift_right(0, 11, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 70, 80, 90, 100}; int vals[] = {0, 15, 1, 2}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // This should remove all segments. db.shift_right(0, 30, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 100}; int vals[] = {0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Insert a few new segments for the next series of tests... db.insert_front(5, 10, 5); db.insert_front(20, 30, 5); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 5, 10, 20, 30, 100}; int vals[] = {0, 5, 0, 5, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Inserting at a non-node position. This should simply extend that // segment and shift all the others. db.shift_right(6, 20, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 5, 30, 40, 50, 100}; int vals[] = {0, 5, 0, 5, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Inserting at a node position. db.shift_right(5, 20, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 25, 50, 60, 70, 100}; int vals[] = {0, 5, 0, 5, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Inserting at a non-node position, pushing a node out-of-bound. db.shift_right(65, 40, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 25, 50, 60, 100}; int vals[] = {0, 5, 0, 5}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } // Inserting at a node position, pushing a node out-of-bound. db.shift_right(50, 40, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int keys[] = {0, 25, 90, 100}; int vals[] = {0, 5, 0}; - assert(check_leaf_nodes(db, keys, vals, std::size(keys))); + TEST_ASSERT(check_leaf_nodes(db, keys, vals, std::size(keys))); } } @@ -1003,44 +1003,44 @@ // Initialize the tree with a default value of 999. flat_segment_tree db(0, 100, 999); db.insert_front(0, 10, 0); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int k[] = {0, 10, 100}; int v[] = {0, 999}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // This should only extend the first segment. db.shift_right(1, 10, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int k[] = {0, 20, 100}; int v[] = {0, 999}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // Inserting at the leftmost node position should create a new segment // with a default value of 999. db.shift_right(0, 10, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { int k[] = {0, 10, 30, 100}; int v[] = {999, 0, 999}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // Invalid shifts -- these should not invalidate the tree. db.shift_right(-10, 10, false); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_right(100, 10, false); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); db.shift_right(0, 0, false); - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); } void fst_test_shift_right_bool() @@ -1049,21 +1049,21 @@ flat_segment_tree db(0, 1048576, false); db.insert_front(3, 7, true); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { long k[] = {0, 3, 7, 1048576}; bool v[] = {false, true, false}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.shift_right(1, 1, false); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { long k[] = {0, 4, 8, 1048576}; bool v[] = {false, true, false}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } } @@ -1073,31 +1073,31 @@ flat_segment_tree db(0, 1048576, 0); db.insert_front(3, 7, 5); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { long k[] = {0, 3, 7, 1048576}; short v[] = {0, 5, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.shift_right(3, 2, true); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { long k[] = {0, 3, 9, 1048576}; short v[] = {0, 5, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // shift_right from the leftmost node should not change its value db.insert_front(0, 4, 2); - assert(!db.is_tree_valid()); + TEST_ASSERT(!db.valid_tree()); build_and_dump(db); { long k[] = {0, 4, 9, 1048576}; short v[] = {2, 5, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.shift_right(0, 2, true); @@ -1105,7 +1105,7 @@ { long k[] = {0, 6, 11, 1048576}; short v[] = {2, 5, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } } @@ -1123,7 +1123,7 @@ { unsigned k[] = {0, 10}; unsigned v[] = {0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(0, 8, 2); @@ -1131,7 +1131,7 @@ { unsigned k[] = {0, 8, 10}; unsigned v[] = {2, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // Shift all nodes out of range. After this, there should be only the @@ -1141,17 +1141,10 @@ { unsigned k[] = {0, 10}; unsigned v[] = {0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } } -template -struct leaf_node_functor -{ - void operator()(const std::pair&) const - {} -}; - void fst_test_const_iterator() { MDDS_TEST_FUNC_SCOPE; @@ -1168,7 +1161,7 @@ { unsigned int k[] = {0, 1000}; unsigned short v[] = {max_value}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_front(10, 20, 10); @@ -1178,20 +1171,21 @@ { unsigned int k[] = {0, 10, 20, 50, 100, 300, 1000}; unsigned short v[] = {max_value, 10, 20, max_value, 55, max_value}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); fprintf(stdout, "fst_test_const_iterator: leaf nodes valid\n"); // Check the forward iterator's integrity. - assert(is_iterator_valid(db.begin(), db.end(), k, v, std::size(k))); + TEST_ASSERT(is_iterator_valid(db.begin(), db.end(), k, v, std::size(k))); fprintf(stdout, "fst_test_const_iterator: forward iterator valid\n"); // Check the reverse iterator's integrity. - assert(is_iterator_valid(db.rbegin(), db.rend(), k, v, std::size(k))); + TEST_ASSERT(is_iterator_valid(db.rbegin(), db.rend(), k, v, std::size(k))); fprintf(stdout, "fst_test_const_iterator: reverse iterator valid\n"); } // Make sure it works with for_each. - std::for_each(db.begin(), db.end(), leaf_node_functor()); + auto func = [](const auto& v) { (void)v; }; + std::for_each(db.begin(), db.end(), func); } { @@ -1204,36 +1198,36 @@ container_type::const_iterator it = db.begin(), it_end = db.end(); // 0 -> 50 -> 100 -> end cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 0); - assert(it->second == false); + TEST_ASSERT(it->first == 0); + TEST_ASSERT(it->second == false); ++it; cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 50); - assert(it->second == true); + TEST_ASSERT(it->first == 50); + TEST_ASSERT(it->second == true); ++it; cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 100); - assert(it != it_end); + TEST_ASSERT(it->first == 100); + TEST_ASSERT(it != it_end); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } { cout << "-- reverse" << endl; container_type::const_reverse_iterator it = db.rbegin(), it_end = db.rend(); // 100 -> 50 -> 0 -> end cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 100); + TEST_ASSERT(it->first == 100); ++it; cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 50); - assert(it->second == true); + TEST_ASSERT(it->first == 50); + TEST_ASSERT(it->second == true); ++it; cout << "key: " << it->first << " value: " << it->second << endl; - assert(it->first == 0); - assert(it->second == false); - assert(it != it_end); + TEST_ASSERT(it->first == 0); + TEST_ASSERT(it->second == false); + TEST_ASSERT(it != it_end); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } } } @@ -1254,8 +1248,8 @@ for (key_type i = start_key; i < end_key - 10; ++i) { itr_type itr = db_front.insert_front(i, i + 1, val).first; - assert(itr->first == i); - assert(itr->second == val); + TEST_ASSERT(itr->first == i); + TEST_ASSERT(itr->second == val); if (++val > 10) val = 0; } @@ -1266,8 +1260,8 @@ for (key_type i = start_key; i < end_key - 10; ++i) { itr_type itr = db_back.insert_back(i, i + 1, val).first; - assert(itr->first == i); - assert(itr->second == val); + TEST_ASSERT(itr->first == i); + TEST_ASSERT(itr->second == val); if (++val > 10) val = 0; } @@ -1280,7 +1274,7 @@ db_back.dump_leaf_nodes(); cout << "start_key = " << start_key << " end_key = " << end_key << " default_value = " << default_value << endl; - assert(!"Contents of the two containers are not identical!"); + TEST_ASSERT(!"Contents of the two containers are not identical!"); } } @@ -1330,43 +1324,43 @@ { // Original node. fst::node_ptr node1(new fst::node); - node1->value_leaf.key = 10; + node1->key = 10; node1->value_leaf.value = 500; - assert(node1->is_leaf); - assert(!node1->parent); - assert(!node1->prev); - assert(!node1->next); + TEST_ASSERT(node1->is_leaf); + TEST_ASSERT(!node1->parent); + TEST_ASSERT(!node1->prev); + TEST_ASSERT(!node1->next); // Copy it to new node. fst::node_ptr node2(new fst::node(*node1)); - assert(node2->is_leaf); - assert(!node2->parent); - assert(!node2->prev); - assert(!node2->next); - assert(node2->value_leaf.key == 10); - assert(node2->value_leaf.value == 500); + TEST_ASSERT(node2->is_leaf); + TEST_ASSERT(!node2->parent); + TEST_ASSERT(!node2->prev); + TEST_ASSERT(!node2->next); + TEST_ASSERT(node2->key == 10); + TEST_ASSERT(node2->value_leaf.value == 500); // Changing the values of the original should not modify the second node. - node1->value_leaf.key = 35; + node1->key = 35; node1->value_leaf.value = 200; - assert(node2->value_leaf.key == 10); - assert(node2->value_leaf.value == 500); + TEST_ASSERT(node2->key == 10); + TEST_ASSERT(node2->value_leaf.value == 500); } { // Test non-leaf node objects. fst::nonleaf_node node1; - node1.value_nonleaf.low = 123; - node1.value_nonleaf.high = 789; + node1.low = 123; + node1.high = 789; // Test the copying of non-leaf values. fst::nonleaf_node node2(node1); - assert(!node2.is_leaf); - assert(!node2.parent); - assert(!node2.left); - assert(!node2.right); - assert(node2.value_nonleaf.low == 123); - assert(node2.value_nonleaf.high == 789); + TEST_ASSERT(!node2.is_leaf); + TEST_ASSERT(!node2.parent); + TEST_ASSERT(!node2.left); + TEST_ASSERT(!node2.right); + TEST_ASSERT(node2.low == 123); + TEST_ASSERT(node2.high == 789); } // Now, test the copy construction of the flat_segment_tree. @@ -1374,48 +1368,48 @@ // Simple copying by copy construction. fst db(0, 100, 5); fst db_copied(db); - assert(db == db_copied); + TEST_ASSERT(db == db_copied); { key_type k[] = {0, 100}; value_type v[] = {5}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // Inserting the same segment value to both instances. They should still // be equal. db.insert_front(5, 10, 0); db_copied.insert_front(5, 10, 0); - assert(db == db_copied); + TEST_ASSERT(db == db_copied); { key_type k[] = {0, 5, 10, 100}; value_type v[] = {5, 0, 5}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } // Inserting a new segment only to the 2nd instance. They should differ. db_copied.insert_front(15, 20, 35); - assert(db != db_copied); + TEST_ASSERT(db != db_copied); { key_type k[] = {0, 5, 10, 15, 20, 100}; value_type v[] = {5, 0, 5, 35, 5}; - assert(check_leaf_nodes(db_copied, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db_copied, k, v, std::size(k))); } // Make sure that copying will leave the tree invalid. - assert(!db_copied.is_tree_valid()); + TEST_ASSERT(!db_copied.valid_tree()); db_copied.build_tree(); - assert(db_copied.is_tree_valid()); + TEST_ASSERT(db_copied.valid_tree()); fst db_copied_again(db_copied); - assert(db_copied == db_copied_again); - assert(!db_copied_again.is_tree_valid()); - assert(!db_copied_again.get_root_node()); + TEST_ASSERT(db_copied == db_copied_again); + TEST_ASSERT(!db_copied_again.valid_tree()); + TEST_ASSERT(!db_copied_again.get_root_node()); // Make sure we can still perform tree search correctly. value_type answer = 0; db_copied_again.build_tree(); db_copied_again.search_tree(18, answer); - assert(db_copied_again.is_tree_valid()); - assert(answer == 35); + TEST_ASSERT(db_copied_again.valid_tree()); + TEST_ASSERT(answer == 35); } void fst_test_move_ctor() @@ -1431,39 +1425,39 @@ auto src_root = src.get_root_node(); container_type moved(std::move(src)); - assert(moved.min_key() == -50); - assert(moved.max_key() == 50); - assert(moved.default_value() == "none"); - assert(moved.leaf_size() == 2); - assert(!moved.is_tree_valid()); - assert(moved.get_root_node() == src_root); + TEST_ASSERT(moved.min_key() == -50); + TEST_ASSERT(moved.max_key() == 50); + TEST_ASSERT(moved.default_value() == "none"); + TEST_ASSERT(moved.leaf_size() == 2); + TEST_ASSERT(!moved.valid_tree()); + TEST_ASSERT(moved.get_root_node() == src_root); moved.build_tree(); - assert(moved.is_tree_valid()); + TEST_ASSERT(moved.valid_tree()); { // Make sure search_tree() won't access invalid memory std::string v; moved.search_tree(0, v); - assert(v == "none"); + TEST_ASSERT(v == "none"); } src_root = moved.get_root_node(); // move again with valid tree container_type moved2(std::move(moved)); - assert(moved2.min_key() == -50); - assert(moved2.max_key() == 50); - assert(moved2.default_value() == "none"); - assert(moved2.leaf_size() == 2); - assert(moved2.is_tree_valid()); - assert(src_root == moved2.get_root_node()); + TEST_ASSERT(moved2.min_key() == -50); + TEST_ASSERT(moved2.max_key() == 50); + TEST_ASSERT(moved2.default_value() == "none"); + TEST_ASSERT(moved2.leaf_size() == 2); + TEST_ASSERT(moved2.valid_tree()); + TEST_ASSERT(src_root == moved2.get_root_node()); { // Make sure search_tree() won't access invalid memory std::string v; moved2.search_tree(0, v); - assert(v == "none"); + TEST_ASSERT(v == "none"); } } @@ -1477,45 +1471,45 @@ auto src_root = src.get_root_node(); container_type moved(std::move(src)); - assert(moved.min_key() == -50); - assert(moved.max_key() == 50); - assert(moved.default_value() == "none"); - assert(moved.leaf_size() == 4); - assert(!moved.is_tree_valid()); - assert(moved.get_root_node() == src_root); + TEST_ASSERT(moved.min_key() == -50); + TEST_ASSERT(moved.max_key() == 50); + TEST_ASSERT(moved.default_value() == "none"); + TEST_ASSERT(moved.leaf_size() == 4); + TEST_ASSERT(!moved.valid_tree()); + TEST_ASSERT(moved.get_root_node() == src_root); moved.build_tree(); - assert(moved.is_tree_valid()); + TEST_ASSERT(moved.valid_tree()); { // Make sure search_tree() won't access invalid memory std::string v; moved.search_tree(-40, v); - assert(v == "none"); + TEST_ASSERT(v == "none"); moved.search_tree(0, v); - assert(v == "middle"); + TEST_ASSERT(v == "middle"); } src_root = moved.get_root_node(); // move again with valid tree container_type moved2(std::move(moved)); - assert(moved2.min_key() == -50); - assert(moved2.max_key() == 50); - assert(moved2.default_value() == "none"); - assert(moved2.leaf_size() == 4); - assert(moved2.is_tree_valid()); - assert(src_root == moved2.get_root_node()); + TEST_ASSERT(moved2.min_key() == -50); + TEST_ASSERT(moved2.max_key() == 50); + TEST_ASSERT(moved2.default_value() == "none"); + TEST_ASSERT(moved2.leaf_size() == 4); + TEST_ASSERT(moved2.valid_tree()); + TEST_ASSERT(src_root == moved2.get_root_node()); { // Make sure search_tree() won't access invalid memory std::string v; moved2.search_tree(-40, v); - assert(v == "none"); + TEST_ASSERT(v == "none"); moved2.search_tree(0, v); - assert(v == "middle"); + TEST_ASSERT(v == "middle"); } } } @@ -1530,34 +1524,34 @@ container_type db1(0, 100, 0); container_type db2(0, 100, 0); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.insert_front(0, 1, 1); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db2.insert_front(0, 1, 1); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); // Same node count, but with different value. db2.insert_front(0, 1, 2); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); // Set the value back. db2.insert_front(0, 1, 1); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.insert_front(4, 10, 10); db1.insert_front(4, 10, 0); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.insert_front(20, 40, 5); db1.insert_front(30, 35, 6); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db2.insert_front(20, 30, 5); db2.insert_front(30, 35, 6); db2.insert_front(35, 40, 5); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); } void fst_test_back_insert() @@ -1572,56 +1566,56 @@ { unsigned int k[] = {0, 1, 2, 100}; unsigned short v[] = {0, 1, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(3, 4, 2); { unsigned int k[] = {0, 1, 2, 3, 4, 100}; unsigned short v[] = {0, 1, 0, 2, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(4, 5, 2); { unsigned int k[] = {0, 1, 2, 3, 5, 100}; unsigned short v[] = {0, 1, 0, 2, 0}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(90, 120, 10); { unsigned int k[] = {0, 1, 2, 3, 5, 90, 100}; unsigned short v[] = {0, 1, 0, 2, 0, 10}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(0, 10, 20); { unsigned int k[] = {0, 10, 90, 100}; unsigned short v[] = {20, 0, 10}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(5, 20, 20); { unsigned int k[] = {0, 20, 90, 100}; unsigned short v[] = {20, 0, 10}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(15, 30, 5); { unsigned int k[] = {0, 15, 30, 90, 100}; unsigned short v[] = {20, 5, 0, 10}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.insert_back(0, 1, 2); { unsigned int k[] = {0, 1, 15, 30, 90, 100}; unsigned short v[] = {2, 20, 5, 0, 10}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } db.dump_leaf_nodes(); @@ -1645,55 +1639,55 @@ db_type::const_iterator itr; itr = db.insert_front(0, 5, 4).first; - assert(itr->first == 0); - assert(itr->second == 4); + TEST_ASSERT(itr->first == 0); + TEST_ASSERT(itr->second == 4); print_iterator(itr); itr = db.insert_front(3, 10, 100).first; - assert(itr->first == 3); - assert(itr->second == 100); + TEST_ASSERT(itr->first == 3); + TEST_ASSERT(itr->second == 100); print_iterator(itr); itr = db.insert_front(5, 8, 100).first; - assert(itr->first == 3); - assert(itr->second == 100); + TEST_ASSERT(itr->first == 3); + TEST_ASSERT(itr->second == 100); print_iterator(itr); itr = db.insert_front(5, 8, 50).first; - assert(itr->first == 5); - assert(itr->second == 50); + TEST_ASSERT(itr->first == 5); + TEST_ASSERT(itr->second == 50); print_iterator(itr); itr = db.insert_front(6, 9, 50).first; - assert(itr->first == 5); - assert(itr->second == 50); + TEST_ASSERT(itr->first == 5); + TEST_ASSERT(itr->second == 50); print_iterator(itr); itr = db.insert_front(9, 20, 24).first; - assert(itr->first == 9); - assert(itr->second == 24); + TEST_ASSERT(itr->first == 9); + TEST_ASSERT(itr->second == 24); print_iterator(itr); itr = db.insert_front(19, 24, 34).first; - assert(itr->first == 19); - assert(itr->second == 34); + TEST_ASSERT(itr->first == 19); + TEST_ASSERT(itr->second == 34); print_iterator(itr); itr = db.insert_front(24, 26, 0).first; - assert(itr->first == 24); - assert(itr->second == 0); + TEST_ASSERT(itr->first == 24); + TEST_ASSERT(itr->second == 0); print_iterator(itr); itr = db.insert_front(30, 50, 2).first; - assert(itr->first == 30); - assert(itr->second == 2); + TEST_ASSERT(itr->first == 30); + TEST_ASSERT(itr->second == 2); print_iterator(itr); itr = db.insert_front(120, 140, 34).first; - assert(itr == db.end()); + TEST_ASSERT(itr == db.end()); itr = db.insert_front(-20, -10, 20).first; - assert(itr == db.end()); + TEST_ASSERT(itr == db.end()); } void fst_test_insert_state_changed() @@ -1710,88 +1704,88 @@ // Inserting a segment with the default value. This should not change the // state. ret_type r = db.insert_front(10, 15, 0); - assert(!r.second); + TEST_ASSERT(!r.second); // New segment with a different value. r = db.insert_front(0, 10, 1); - assert(r.second); + TEST_ASSERT(r.second); // Inserting the same segment should not change the state. r = db.insert_front(0, 10, 1); - assert(!r.second); + TEST_ASSERT(!r.second); r = db.insert_front(0, 1, 1); - assert(!r.second); + TEST_ASSERT(!r.second); r = db.insert_front(8, 10, 1); - assert(!r.second); + TEST_ASSERT(!r.second); // This extends the segment, therefore the state should change. r = db.insert_front(8, 11, 1); - assert(r.second); + TEST_ASSERT(r.second); r = db.insert_front(11, 15, 0); - assert(!r.second); + TEST_ASSERT(!r.second); // This extends the segment. At this point, 0 - 15 should have a value of 1. r = db.insert_front(11, 15, 1); - assert(r.second); + TEST_ASSERT(r.second); { db_type::const_iterator itr = r.first; - assert(itr->first == 0); - assert(itr->second == 1); + TEST_ASSERT(itr->first == 0); + TEST_ASSERT(itr->second == 1); ++itr; - assert(itr->first == 15); + TEST_ASSERT(itr->first == 15); } r = db.insert_front(2, 4, 1); - assert(!r.second); + TEST_ASSERT(!r.second); // Different value segment. This should change the state. r = db.insert_front(2, 4, 0); - assert(r.second); + TEST_ASSERT(r.second); // Ditto. r = db.insert_front(2, 4, 1); - assert(r.second); + TEST_ASSERT(r.second); r = db.insert_front(1, 8, 1); - assert(!r.second); + TEST_ASSERT(!r.second); // Different value segment. r = db.insert_front(1, 8, 2); - assert(r.second); + TEST_ASSERT(r.second); r = db.insert_front(8, 20, 2); - assert(r.second); + TEST_ASSERT(r.second); // The 0-1 segment should still have a value of 1. So this won't change // the state. r = db.insert_front(0, 1, 1); - assert(!r.second); + TEST_ASSERT(!r.second); // Partially out-of-bound segment, but this should modify the value of 0-2. r = db.insert_front(-50, 2, 10); - assert(r.second); + TEST_ASSERT(r.second); { db_type::const_iterator itr = r.first; - assert(itr->first == 0); - assert(itr->second == 10); + TEST_ASSERT(itr->first == 0); + TEST_ASSERT(itr->second == 10); ++itr; - assert(itr->first == 2); + TEST_ASSERT(itr->first == 2); } // Entirely out-of-bound. r = db.insert_front(-50, -2, 20); - assert(!r.second); + TEST_ASSERT(!r.second); // Likewise, partially out-of-bound at the higher end. r = db.insert_front(800, 1200, 20); - assert(r.second); + TEST_ASSERT(r.second); // Entirely out-of-bound. r = db.insert_front(1300, 1400, 25); - assert(!r.second); + TEST_ASSERT(!r.second); } void fst_perf_test_insert_position() @@ -1876,7 +1870,7 @@ { bool val2; ret_type ret = db.search(i, val2); - assert(ret.second); + TEST_ASSERT(ret.second); } } @@ -1887,7 +1881,7 @@ { bool val2; ret_type ret = db.search(itr, i, val2); - assert(ret.second); + TEST_ASSERT(ret.second); itr = ret.first; } } @@ -1948,30 +1942,30 @@ // empty iterator - should fall back to normal search. success = check_pos_search_result( db, itr, j, params[i].start_range, params[i].end_range, params[i].value_expected); - assert(success); + TEST_ASSERT(success); // iterator returned from the previous search. success = check_pos_search_result( db, itr, j, params[i].start_range, params[i].end_range, params[i].value_expected); - assert(success); + TEST_ASSERT(success); // begin iterator. itr = db.begin(); success = check_pos_search_result( db, itr, j, params[i].start_range, params[i].end_range, params[i].value_expected); - assert(success); + TEST_ASSERT(success); // end iterator. itr = db.end(); success = check_pos_search_result( db, itr, j, params[i].start_range, params[i].end_range, params[i].value_expected); - assert(success); + TEST_ASSERT(success); // iterator from another container - should fall back to normal search. itr = db2.begin(); success = check_pos_search_result( db, itr, j, params[i].start_range, params[i].end_range, params[i].value_expected); - assert(success); + TEST_ASSERT(success); } } @@ -1983,10 +1977,10 @@ for (size_t i = 0; i < n; ++i) { ret_type r = db.search(itr, end, val, &start, &end); - assert(start == params[i].start_range); - assert(end == params[i].end_range); - assert(val == params[i].value_expected); - assert(r.second); + TEST_ASSERT(start == params[i].start_range); + TEST_ASSERT(end == params[i].end_range); + TEST_ASSERT(val == params[i].value_expected); + TEST_ASSERT(r.second); itr = r.first; } } @@ -1997,9 +1991,9 @@ typedef flat_segment_tree db_type; db_type db(0, 100, 2); - assert(db.min_key() == 0); - assert(db.max_key() == 100); - assert(db.default_value() == 2); + TEST_ASSERT(db.min_key() == 0); + TEST_ASSERT(db.max_key() == 100); + TEST_ASSERT(db.default_value() == 2); } void fst_test_swap() @@ -2018,12 +2012,12 @@ { db_type::key_type k[] = {0, 20, 30, 40, 50, 200}; db_type::value_type v[] = {20, 1, 2, 3, 20}; - assert(check_leaf_nodes(db1, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db1, k, v, std::size(k))); } - assert(db1.min_key() == 0); - assert(db1.max_key() == 200); - assert(db1.default_value() == 20); - assert(db1.is_tree_valid()); + TEST_ASSERT(db1.min_key() == 0); + TEST_ASSERT(db1.max_key() == 200); + TEST_ASSERT(db1.default_value() == 20); + TEST_ASSERT(db1.valid_tree()); db1.swap(db2); @@ -2031,17 +2025,17 @@ { db_type::key_type k[] = {0, 20, 30, 40, 50, 200}; db_type::value_type v[] = {20, 1, 2, 3, 20}; - assert(check_leaf_nodes(db2, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db2, k, v, std::size(k))); } - assert(db2.min_key() == 0); - assert(db2.max_key() == 200); - assert(db2.default_value() == 20); - assert(db2.is_tree_valid()); + TEST_ASSERT(db2.min_key() == 0); + TEST_ASSERT(db2.max_key() == 200); + TEST_ASSERT(db2.default_value() == 20); + TEST_ASSERT(db2.valid_tree()); // Tree search should work on db2. db_type::value_type val = 0; - assert(db2.search_tree(35, val).second); - assert(val == 2); + TEST_ASSERT(db2.search_tree(35, val).second); + TEST_ASSERT(val == 2); } void fst_test_swap_tree_memory() @@ -2054,7 +2048,7 @@ db1->build_tree(); int value = -1; db1->search_tree(20, value); - assert(value == 999); + TEST_ASSERT(value == 999); db_type db2(-10, 10, -99); db2.swap(*db1); @@ -2062,10 +2056,10 @@ db1.reset(); // Make sure that the tree is valid, and you can still search through the tree. - assert(db2.is_tree_valid()); + TEST_ASSERT(db2.valid_tree()); value = -1; db2.search_tree(20, value); - assert(value == 999); + TEST_ASSERT(value == 999); } void fst_test_clear() @@ -2082,24 +2076,24 @@ { db_type::key_type k[] = {0, 10, 20, 30, 100}; db_type::value_type v[] = {0, 1, 2, 42}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } - assert(db.min_key() == 0); - assert(db.max_key() == 100); - assert(db.default_value() == 42); - assert(db.is_tree_valid()); + TEST_ASSERT(db.min_key() == 0); + TEST_ASSERT(db.max_key() == 100); + TEST_ASSERT(db.default_value() == 42); + TEST_ASSERT(db.valid_tree()); db.clear(); { db_type::key_type k[] = {0, 100}; db_type::value_type v[] = {42}; - assert(check_leaf_nodes(db, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db, k, v, std::size(k))); } - assert(db.min_key() == 0); - assert(db.max_key() == 100); - assert(db.default_value() == 42); - assert(!db.is_tree_valid()); + TEST_ASSERT(db.min_key() == 0); + TEST_ASSERT(db.max_key() == 100); + TEST_ASSERT(db.default_value() == 42); + TEST_ASSERT(!db.valid_tree()); } void fst_test_assignment() @@ -2116,12 +2110,12 @@ { db_type::key_type k[] = {0, 10, 20, 30, 100}; db_type::value_type v[] = {0, 1, 2, 42}; - assert(check_leaf_nodes(db1, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db1, k, v, std::size(k))); } - assert(db1.min_key() == 0); - assert(db1.max_key() == 100); - assert(db1.default_value() == 42); - assert(db1.is_tree_valid()); + TEST_ASSERT(db1.min_key() == 0); + TEST_ASSERT(db1.max_key() == 100); + TEST_ASSERT(db1.default_value() == 42); + TEST_ASSERT(db1.valid_tree()); db_type db2(20, 40, 0); db2.insert_back(20, 30, 8); @@ -2130,12 +2124,12 @@ { db_type::key_type k[] = {20, 30, 40}; db_type::value_type v[] = {8, 0}; - assert(check_leaf_nodes(db2, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db2, k, v, std::size(k))); } - assert(db2.min_key() == 20); - assert(db2.max_key() == 40); - assert(db2.default_value() == 0); - assert(db2.is_tree_valid()); + TEST_ASSERT(db2.min_key() == 20); + TEST_ASSERT(db2.max_key() == 40); + TEST_ASSERT(db2.default_value() == 0); + TEST_ASSERT(db2.valid_tree()); db_type db3(10, 80, 4); db3.build_tree(); @@ -2143,44 +2137,44 @@ { db_type::key_type k[] = {10, 80}; db_type::value_type v[] = {4}; - assert(check_leaf_nodes(db3, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db3, k, v, std::size(k))); } - assert(db3.min_key() == 10); - assert(db3.max_key() == 80); - assert(db3.default_value() == 4); - assert(db3.is_tree_valid()); + TEST_ASSERT(db3.min_key() == 10); + TEST_ASSERT(db3.max_key() == 80); + TEST_ASSERT(db3.default_value() == 4); + TEST_ASSERT(db3.valid_tree()); db3 = db2 = db1; { db_type::key_type k[] = {0, 10, 20, 30, 100}; db_type::value_type v[] = {0, 1, 2, 42}; - assert(check_leaf_nodes(db1, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db1, k, v, std::size(k))); } - assert(db1.min_key() == 0); - assert(db1.max_key() == 100); - assert(db1.default_value() == 42); - assert(db1.is_tree_valid()); + TEST_ASSERT(db1.min_key() == 0); + TEST_ASSERT(db1.max_key() == 100); + TEST_ASSERT(db1.default_value() == 42); + TEST_ASSERT(db1.valid_tree()); { db_type::key_type k[] = {0, 10, 20, 30, 100}; db_type::value_type v[] = {0, 1, 2, 42}; - assert(check_leaf_nodes(db2, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db2, k, v, std::size(k))); } - assert(db2.min_key() == 0); - assert(db2.max_key() == 100); - assert(db2.default_value() == 42); - assert(!db2.is_tree_valid()); + TEST_ASSERT(db2.min_key() == 0); + TEST_ASSERT(db2.max_key() == 100); + TEST_ASSERT(db2.default_value() == 42); + TEST_ASSERT(!db2.valid_tree()); { db_type::key_type k[] = {0, 10, 20, 30, 100}; db_type::value_type v[] = {0, 1, 2, 42}; - assert(check_leaf_nodes(db3, k, v, std::size(k))); + TEST_ASSERT(check_leaf_nodes(db3, k, v, std::size(k))); } - assert(db3.min_key() == 0); - assert(db3.max_key() == 100); - assert(db3.default_value() == 42); - assert(!db3.is_tree_valid()); + TEST_ASSERT(db3.min_key() == 0); + TEST_ASSERT(db3.max_key() == 100); + TEST_ASSERT(db3.default_value() == 42); + TEST_ASSERT(!db3.valid_tree()); } void fst_test_move_assignment() @@ -2192,33 +2186,33 @@ container_type moved{10, 200, "base2"}; moved = std::move(src); - assert(moved.min_key() == 0); - assert(moved.max_key() == 100); - assert(moved.default_value() == "base"); - assert(moved.leaf_size() == 2); - assert(!moved.is_tree_valid()); + TEST_ASSERT(moved.min_key() == 0); + TEST_ASSERT(moved.max_key() == 100); + TEST_ASSERT(moved.default_value() == "base"); + TEST_ASSERT(moved.leaf_size() == 2); + TEST_ASSERT(!moved.valid_tree()); moved.insert_back(10, 25, "10-25"); moved.build_tree(); - assert(moved.is_tree_valid()); - assert(moved.leaf_size() == 4); + TEST_ASSERT(moved.valid_tree()); + TEST_ASSERT(moved.leaf_size() == 4); container_type moved2{30, 450, "base3"}; moved2 = std::move(moved); - assert(moved2.min_key() == 0); - assert(moved2.max_key() == 100); - assert(moved2.default_value() == "base"); - assert(moved2.leaf_size() == 4); - assert(moved2.is_tree_valid()); + TEST_ASSERT(moved2.min_key() == 0); + TEST_ASSERT(moved2.max_key() == 100); + TEST_ASSERT(moved2.default_value() == "base"); + TEST_ASSERT(moved2.leaf_size() == 4); + TEST_ASSERT(moved2.valid_tree()); // Make sure we can perform tree search. std::string v; uint32_t key1, key2; auto res = moved2.search_tree(20, v, &key1, &key2); - assert(res.second); - assert(v == "10-25"); - assert(key1 == 10); - assert(key2 == 25); + TEST_ASSERT(res.second); + TEST_ASSERT(v == "10-25"); + TEST_ASSERT(key1 == 10); + TEST_ASSERT(key2 == 25); } void fst_test_non_numeric_value() @@ -2229,16 +2223,16 @@ db_type db(0, 4, "42"); db.insert_back(1, 2, "hello world"); - assert(db.default_value() == "42"); + TEST_ASSERT(db.default_value() == "42"); std::string result; db.search(1, result); - assert(result == "hello world"); + TEST_ASSERT(result == "hello world"); db_type db2(db); - assert(db == db2); + TEST_ASSERT(db == db2); } void fst_test_insert_out_of_bound() @@ -2254,28 +2248,28 @@ // ranges that are entirely out-of-bound. auto ret = db.insert_front(-10, -8, false); - assert(!ret.second); + TEST_ASSERT(!ret.second); db.insert_back(12, 13, false); - assert(!ret.second); + TEST_ASSERT(!ret.second); db_type::const_iterator pos = db.end(); ret = db.insert(pos, -10, -8, false); - assert(!ret.second); + TEST_ASSERT(!ret.second); pos = ret.first; ret = db.insert(pos, 12, 13, false); - assert(!ret.second); + TEST_ASSERT(!ret.second); pos = ret.first; // partial overflows. ret = db.insert(pos, -2, 2, true); - assert(ret.second); // content modified + TEST_ASSERT(ret.second); // content modified pos = ret.first; ret = db.insert(pos, 8, 20, true); - assert(ret.second); // content modified + TEST_ASSERT(ret.second); // content modified pos = ret.first; } @@ -2291,8 +2285,8 @@ auto ret = db.insert_back(256, 1024, true); // Insertion never took place. - assert(ret.first == db.end()); - assert(!ret.second); + TEST_ASSERT(ret.first == db.end()); + TEST_ASSERT(!ret.second); } void fst_test_segment_iterator() @@ -2305,74 +2299,74 @@ db_type::const_segment_iterator it = db.begin_segment(); db_type::const_segment_iterator ite = db.end_segment(); - assert(it != ite); - assert(it->start == 0); - assert(it->end == 100); - assert(it->value == false); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->start == 0); + TEST_ASSERT(it->end == 100); + TEST_ASSERT(it->value == false); const auto& v = *it; - assert(v.start == 0); - assert(v.end == 100); - assert(v.value == false); + TEST_ASSERT(v.start == 0); + TEST_ASSERT(v.end == 100); + TEST_ASSERT(v.value == false); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); --it; - assert(it != ite); - assert(it->start == 0); - assert(it->end == 100); - assert(it->value == false); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->start == 0); + TEST_ASSERT(it->end == 100); + TEST_ASSERT(it->value == false); db_type::const_segment_iterator it2; // default constructor it2 = it; // assignment operator - assert(it2 == it); - assert(it2->start == 0); - assert(it2->end == 100); - assert(it2->value == false); + TEST_ASSERT(it2 == it); + TEST_ASSERT(it2->start == 0); + TEST_ASSERT(it2->end == 100); + TEST_ASSERT(it2->value == false); auto it3(it2); // copy constructor - assert(it3 == it2); - assert(it3->start == 0); - assert(it3->end == 100); - assert(it3->value == false); + TEST_ASSERT(it3 == it2); + TEST_ASSERT(it3->start == 0); + TEST_ASSERT(it3->end == 100); + TEST_ASSERT(it3->value == false); db.insert_back(20, 50, true); // this invalidates the iterators. it = db.begin_segment(); ite = db.end_segment(); - assert(it->start == 0); - assert(it->end == 20); - assert(it->value == false); + TEST_ASSERT(it->start == 0); + TEST_ASSERT(it->end == 20); + TEST_ASSERT(it->value == false); it2 = it++; // post-increment - assert(it2->start == 0); - assert(it2->end == 20); - assert(it2->value == false); - - assert(it->start == 20); - assert(it->end == 50); - assert(it->value == true); + TEST_ASSERT(it2->start == 0); + TEST_ASSERT(it2->end == 20); + TEST_ASSERT(it2->value == false); + + TEST_ASSERT(it->start == 20); + TEST_ASSERT(it->end == 50); + TEST_ASSERT(it->value == true); ++it; - assert(it->start == 50); - assert(it->end == 100); - assert(it->value == false); + TEST_ASSERT(it->start == 50); + TEST_ASSERT(it->end == 100); + TEST_ASSERT(it->value == false); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); it2 = it--; // post-decrement. - assert(it2 == ite); + TEST_ASSERT(it2 == ite); it = db.begin_segment(); auto it_moved{std::move(it)}; // move construction - assert(it_moved->start == 0); - assert(it_moved->end == 20); - assert(it_moved->value == false); + TEST_ASSERT(it_moved->start == 0); + TEST_ASSERT(it_moved->end == 20); + TEST_ASSERT(it_moved->value == false); } void fst_test_segment_range() @@ -2398,7 +2392,7 @@ actual.push_back(v); } - assert(expected == actual); + TEST_ASSERT(expected == actual); } { @@ -2420,7 +2414,7 @@ actual.push_back(v); } - assert(expected == actual); + TEST_ASSERT(expected == actual); // Use it with structured binding std::cout << "--" << std::endl; @@ -2431,7 +2425,7 @@ actual.emplace_back(start, end, value); } - assert(expected == actual); + TEST_ASSERT(expected == actual); } } @@ -2500,7 +2494,7 @@ for (const node_type& v : db.segment_range()) actual.push_back(v); - assert(expected == actual); + TEST_ASSERT(expected == actual); } int main(int argc, char** argv) diff -Nru mdds-2.1.1/test/gdb/Makefile.in mdds-3.1.0/test/gdb/Makefile.in --- mdds-2.1.1/test/gdb/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/gdb/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -242,7 +242,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/gdb/src/Makefile.in mdds-3.1.0/test/gdb/src/Makefile.in --- mdds-2.1.1/test/gdb/src/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/gdb/src/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -235,7 +235,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/gdb/src/sorted_string_map.cpp mdds-3.1.0/test/gdb/src/sorted_string_map.cpp --- mdds-2.1.1/test/gdb/src/sorted_string_map.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/gdb/src/sorted_string_map.cpp 2024-01-10 23:45:35.000000000 +0000 @@ -15,7 +15,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include #include void stop(); @@ -26,14 +25,13 @@ { sorted_string_map empty_ssmap(nullptr, 0, 0); - sorted_string_map::entry entries[] = { - {MDDS_ASCII("aaaa"), 1}, - {MDDS_ASCII("bbb"), 2}, - {MDDS_ASCII("cc"), 3}, - {MDDS_ASCII("d"), 4}, + sorted_string_map::entry_type entries[] = { + {"aaaa", 1}, + {"bbb", 2}, + {"cc", 3}, + {"d", 4}, }; - size_t entry_count = sizeof(entries) / sizeof(entries[0]); - sorted_string_map ssmap_int(entries, entry_count, 0); + sorted_string_map ssmap_int(entries, std::size(entries), 0); stop(); } diff -Nru mdds-2.1.1/test/gdb/src/trie_map.cpp mdds-3.1.0/test/gdb/src/trie_map.cpp --- mdds-2.1.1/test/gdb/src/trie_map.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/gdb/src/trie_map.cpp 2024-02-07 03:12:37.000000000 +0000 @@ -27,15 +27,15 @@ void test_trie_map() { - trie_map empty_tm; + trie_map empty_tm; - trie_map tm_int; + trie_map tm_int; tm_int.insert("a", 13); tm_int.insert("aa", 10); tm_int.insert("ab", 3); tm_int.insert("b", 7); - trie_map tm_str; + trie_map tm_str; tm_str.insert("a", "13"); tm_str.insert("aa", "10"); tm_str.insert("ab", "3"); @@ -51,21 +51,21 @@ auto tm_search_iter_end = tm_search_one.end(); auto tm_search_iter_empty = tm_search_empty.begin(); - packed_trie_map::entry entries_int[] = { + packed_trie_map::entry entries_int[] = { {MDDS_ASCII("a"), 13}, {MDDS_ASCII("aa"), 10}, {MDDS_ASCII("ab"), 3}, {MDDS_ASCII("b"), 7}, }; - packed_trie_map empty_ptm(entries_int, 0); - packed_trie_map ptm_int(entries_int, MDDS_N_ELEMENTS(entries_int)); - packed_trie_map::entry entries_str[] = { + packed_trie_map empty_ptm(entries_int, 0); + packed_trie_map ptm_int(entries_int, MDDS_N_ELEMENTS(entries_int)); + packed_trie_map::entry entries_str[] = { {MDDS_ASCII("a"), "13"}, {MDDS_ASCII("aa"), "10"}, {MDDS_ASCII("ab"), "3"}, {MDDS_ASCII("b"), "7"}, }; - packed_trie_map ptm_str(entries_str, MDDS_N_ELEMENTS(entries_str)); + packed_trie_map ptm_str(entries_str, MDDS_N_ELEMENTS(entries_str)); auto ptm_search_empty = ptm_int.prefix_search("foo"); auto ptm_search_one = ptm_int.prefix_search("b"); diff -Nru mdds-2.1.1/test/include/Makefile.in mdds-3.1.0/test/include/Makefile.in --- mdds-2.1.1/test/include/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/include/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -182,7 +182,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/include/test_global.hpp mdds-3.1.0/test/include/test_global.hpp --- mdds-2.1.1/test/include/test_global.hpp 2023-03-14 23:45:11.000000000 +0000 +++ mdds-3.1.0/test/include/test_global.hpp 2025-07-03 16:15:17.000000000 +0000 @@ -25,8 +25,7 @@ * ************************************************************************/ -#ifndef INCLUDED_TEST_GLOBAL_HPP -#define INCLUDED_TEST_GLOBAL_HPP +#pragma once #ifdef NDEBUG // release build @@ -44,6 +43,17 @@ #include #include +#define TEST_ASSERT(condition) \ + do \ + { \ + if (!(condition)) \ + { \ + std::cerr << "Assertion failed: " << #condition << ", file " << __FILE__ << ", line " << __LINE__ \ + << std::endl; \ + std::abort(); \ + } \ + } while (false) + struct cmd_options { bool test_func; @@ -94,4 +104,7 @@ __sp_os__ << __func__ << ' ' << stream; \ stack_printer __sp__(__sp_os__.str()) -#endif +#define MDDS_TEST_FUNC_SCOPE_NS(stream) \ + std::ostringstream __sp_os__; \ + __sp_os__ << stream << "::" << __func__; \ + stack_printer __sp__(__sp_os__.str()) diff -Nru mdds-2.1.1/test/multi_type_matrix/Makefile.in mdds-3.1.0/test/multi_type_matrix/Makefile.in --- mdds-2.1.1/test/multi_type_matrix/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_matrix/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -434,7 +434,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_matrix/test_main.cpp mdds-3.1.0/test/multi_type_matrix/test_main.cpp --- mdds-2.1.1/test/multi_type_matrix/test_main.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_matrix/test_main.cpp 2025-07-05 20:40:36.000000000 +0000 @@ -34,7 +34,6 @@ #include using namespace mdds; -using namespace std; // Standard matrix that uses std::string as its string type. typedef multi_type_matrix mtx_type; @@ -43,16 +42,16 @@ class custom_string { - string m_val; + std::string m_val; public: custom_string() {} - custom_string(const string& val) : m_val(val) + custom_string(const std::string& val) : m_val(val) {} custom_string(const custom_string& r) : m_val(r.m_val) {} - const string& get() const + const std::string& get() const { return m_val; } @@ -66,7 +65,7 @@ } }; -ostream& operator<<(ostream& os, const custom_string& str) +std::ostream& operator<<(std::ostream& os, const custom_string& str) { os << str.get(); return os; @@ -92,13 +91,13 @@ { mtx.set(row, col, val); _T test = mtx.get<_T>(row, col); - assert(test == val); + TEST_ASSERT(test == val); } bool check_copy(const mtx_type& mx1, const mtx_type& mx2) { - size_t row_count = min(mx1.size().row, mx2.size().row); - size_t col_count = min(mx1.size().column, mx2.size().column); + size_t row_count = std::min(mx1.size().row, mx2.size().row); + size_t col_count = std::min(mx1.size().column, mx2.size().column); for (size_t i = 0; i < row_count; ++i) { for (size_t j = 0; j < col_count; ++j) @@ -129,7 +128,8 @@ case mtm::element_string: if (mx1.get(i, j) != mx2.get(i, j)) { - cout << "check_copy: (row=" << i << ",column=" << j << ") different string values." << endl; + std::cout << "check_copy: (row=" << i << ",column=" << j << ") different string values." + << std::endl; return false; } break; @@ -145,145 +145,147 @@ void mtm_test_construction() { - stack_printer __stack_printer__("::mtm_test_construction"); + MDDS_TEST_FUNC_SCOPE; + { // default constructor. mtx_type mtx; mtx_type::size_pair_type sz = mtx.size(); - assert(sz.row == 0 && sz.column == 0); + TEST_ASSERT(sz.row == 0 && sz.column == 0); } { // construction to a specific size. mtx_type mtx(2, 5); mtx_type::size_pair_type sz = mtx.size(); - assert(sz.row == 2 && sz.column == 5); + TEST_ASSERT(sz.row == 2 && sz.column == 5); } { // construction to a specific size with default value. - mtx_type mtx(2, 5, string("foo")); + mtx_type mtx(2, 5, std::string("foo")); mtx_type::size_pair_type sz = mtx.size(); - assert(sz.row == 2 && sz.column == 5); - assert(mtx.get_type(0, 0) == mtm::element_string); - assert(mtx.get_string(0, 0) == "foo"); - assert(mtx.get_type(1, 4) == mtm::element_string); - assert(mtx.get_string(1, 4) == "foo"); + TEST_ASSERT(sz.row == 2 && sz.column == 5); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_string); + TEST_ASSERT(mtx.get_string(0, 0) == "foo"); + TEST_ASSERT(mtx.get_type(1, 4) == mtm::element_string); + TEST_ASSERT(mtx.get_string(1, 4) == "foo"); } { // construct with an array of data. - vector vals; + std::vector vals; vals.push_back(1.1); vals.push_back(1.2); vals.push_back(1.3); vals.push_back(1.4); mtx_type mtx(2, 2, vals.begin(), vals.end()); mtx_type::size_pair_type sz = mtx.size(); - assert(sz.row == 2 && sz.column == 2); - assert(mtx.get_numeric(0, 0) == 1.1); - assert(mtx.get_numeric(1, 0) == 1.2); - assert(mtx.get_numeric(0, 1) == 1.3); - assert(mtx.get_numeric(1, 1) == 1.4); + TEST_ASSERT(sz.row == 2 && sz.column == 2); + TEST_ASSERT(mtx.get_numeric(0, 0) == 1.1); + TEST_ASSERT(mtx.get_numeric(1, 0) == 1.2); + TEST_ASSERT(mtx.get_numeric(0, 1) == 1.3); + TEST_ASSERT(mtx.get_numeric(1, 1) == 1.4); try { mtx_type mtx2(3, 2, vals.begin(), vals.end()); - assert(!"Construction of this matrix should have failed!"); + TEST_ASSERT(!"Construction of this matrix should have failed!"); } catch (const invalid_arg_error& e) { // Good. - cout << "exception caught (as expected) which says: " << e.what() << endl; + std::cout << "exception caught (as expected) which says: " << e.what() << std::endl; } try { // Trying to initialize a matrix with array of unsupported data // type should end with an exception thrown. - vector vals_ptr(4, 22); + std::vector vals_ptr(4, 22); mtx_type mtx3(2, 2, vals_ptr.begin(), vals_ptr.end()); - assert(!"Construction of this matrix should have failed!"); + TEST_ASSERT(!"Construction of this matrix should have failed!"); } - catch (const exception& e) + catch (const std::exception& e) { - cout << "exception caught (as expected) which says: " << e.what() << endl; + std::cout << "exception caught (as expected) which says: " << e.what() << std::endl; } } { // Construct with an array of custom string type. - vector vals; + std::vector vals; vals.push_back(custom_string("A")); vals.push_back(custom_string("B")); vals.push_back(custom_string("C")); vals.push_back(custom_string("D")); mtx_custom_type mtx(1, 4, vals.begin(), vals.end()); - assert(mtx.get_string(0, 0).get() == "A"); - assert(mtx.get_string(0, 1).get() == "B"); - assert(mtx.get_string(0, 2).get() == "C"); - assert(mtx.get_string(0, 3).get() == "D"); - assert(mtx.get_type(0, 0) == mtm::element_string); - assert(mtx.get_type(0, 1) == mtm::element_string); - assert(mtx.get_type(0, 2) == mtm::element_string); - assert(mtx.get_type(0, 3) == mtm::element_string); + TEST_ASSERT(mtx.get_string(0, 0).get() == "A"); + TEST_ASSERT(mtx.get_string(0, 1).get() == "B"); + TEST_ASSERT(mtx.get_string(0, 2).get() == "C"); + TEST_ASSERT(mtx.get_string(0, 3).get() == "D"); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_string); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(0, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(0, 3) == mtm::element_string); } { // Construct size_pair_type from initializer list. mtx_type::size_pair_type sz({3, 4}); - assert(sz.row == 3); - assert(sz.column == 4); + TEST_ASSERT(sz.row == 3); + TEST_ASSERT(sz.column == 4); } } void mtm_test_data_insertion() { - stack_printer __stack_printer__("::mtm_test_data_insertion"); + MDDS_TEST_FUNC_SCOPE; { // Create with empty elements. mtx_type mtx(3, 4); mtx_type::size_pair_type sz = mtx.size(); - assert(sz.row == 3 && sz.column == 4); - assert(!mtx.empty()); - assert(mtx.get_type(0, 0) == mtm::element_empty); - assert(mtx.get_type(2, 3) == mtm::element_empty); + TEST_ASSERT(sz.row == 3 && sz.column == 4); + TEST_ASSERT(!mtx.empty()); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 3) == mtm::element_empty); check_value(mtx, 1, 1, 1.2); check_value(mtx, 2, 1, true); check_value(mtx, 3, 1, false); - check_value(mtx, 0, 2, string("foo")); + check_value(mtx, 0, 2, std::string("foo")); check_value(mtx, 1, 2, 23.4); // Overwrite - assert(mtx.get_type(1, 1) == mtm::element_numeric); - check_value(mtx, 1, 1, string("baa")); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_numeric); + check_value(mtx, 1, 1, std::string("baa")); // Setting empty. - assert(mtx.get_type(1, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_string); mtx.set_empty(1, 1); - assert(mtx.get_type(1, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_empty); mtx.clear(); - assert(mtx.size().row == 0); - assert(mtx.size().column == 0); - assert(mtx.empty()); + TEST_ASSERT(mtx.size().row == 0); + TEST_ASSERT(mtx.size().column == 0); + TEST_ASSERT(mtx.empty()); } } void mtm_test_data_insertion_multiple() { - stack_printer __stack_printer__("::mtm_test_data_insertion_multiple"); + MDDS_TEST_FUNC_SCOPE; + { mtx_type mtx(3, 5); // data shorter than column length - vector vals; + std::vector vals; vals.push_back(1.1); vals.push_back(1.2); mtx.set_column(2, vals.begin(), vals.end()); - assert(mtx.get_numeric(0, 2) == 1.1); - assert(mtx.get_numeric(1, 2) == 1.2); - assert(mtx.get_type(2, 2) == mtm::element_empty); + TEST_ASSERT(mtx.get_numeric(0, 2) == 1.1); + TEST_ASSERT(mtx.get_numeric(1, 2) == 1.2); + TEST_ASSERT(mtx.get_type(2, 2) == mtm::element_empty); // data exatly at column length vals.clear(); @@ -291,10 +293,10 @@ vals.push_back(2.2); vals.push_back(2.3); mtx.set_column(2, vals.begin(), vals.end()); - assert(mtx.get_numeric(0, 2) == 2.1); - assert(mtx.get_numeric(1, 2) == 2.2); - assert(mtx.get_numeric(2, 2) == 2.3); - assert(mtx.get_type(0, 3) == mtm::element_empty); + TEST_ASSERT(mtx.get_numeric(0, 2) == 2.1); + TEST_ASSERT(mtx.get_numeric(1, 2) == 2.2); + TEST_ASSERT(mtx.get_numeric(2, 2) == 2.3); + TEST_ASSERT(mtx.get_type(0, 3) == mtm::element_empty); // data longer than column length. The excess data should be ignored. vals.clear(); @@ -303,16 +305,16 @@ vals.push_back(3.3); vals.push_back(3.4); mtx.set_column(2, vals.begin(), vals.end()); - assert(mtx.get_numeric(0, 2) == 3.1); - assert(mtx.get_numeric(1, 2) == 3.2); - assert(mtx.get_numeric(2, 2) == 3.3); - assert(mtx.get_type(0, 3) == mtm::element_empty); + TEST_ASSERT(mtx.get_numeric(0, 2) == 3.1); + TEST_ASSERT(mtx.get_numeric(1, 2) == 3.2); + TEST_ASSERT(mtx.get_numeric(2, 2) == 3.3); + TEST_ASSERT(mtx.get_type(0, 3) == mtm::element_empty); } } void mtm_test_data_insertion_integer() { - stack_printer __stack_printer__("::mtm_test_data_insertion_integer"); + MDDS_TEST_FUNC_SCOPE; // +--------+--------+ // | int | double | @@ -326,34 +328,34 @@ mtx.set(0, 1, double(10)); mtx.set(1, 0, double(22)); - assert(mtx.get_type(0, 0) == mtm::element_integer); - assert(mtx.get_type(1, 1) == mtm::element_integer); - assert(mtx.get_type(0, 1) == mtm::element_numeric); - assert(mtx.get_type(1, 0) == mtm::element_numeric); - - assert(mtx.get_integer(0, 0) == 0); - assert(mtx.get_integer(1, 1) == 22); - assert(mtx.get_integer(0, 1) == 10); - assert(mtx.get_integer(1, 0) == 22); - - assert(mtx.get_numeric(0, 0) == 0.0); - assert(mtx.get_numeric(1, 1) == 22.0); - assert(mtx.get_numeric(0, 1) == 10.0); - assert(mtx.get_numeric(1, 0) == 22.0); - - assert(mtx.get_boolean(0, 0) == false); - assert(mtx.get_boolean(1, 1) == true); - assert(mtx.get_boolean(0, 1) == true); - assert(mtx.get_boolean(1, 0) == true); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_integer); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_integer); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_numeric); + TEST_ASSERT(mtx.get_type(1, 0) == mtm::element_numeric); + + TEST_ASSERT(mtx.get_integer(0, 0) == 0); + TEST_ASSERT(mtx.get_integer(1, 1) == 22); + TEST_ASSERT(mtx.get_integer(0, 1) == 10); + TEST_ASSERT(mtx.get_integer(1, 0) == 22); + + TEST_ASSERT(mtx.get_numeric(0, 0) == 0.0); + TEST_ASSERT(mtx.get_numeric(1, 1) == 22.0); + TEST_ASSERT(mtx.get_numeric(0, 1) == 10.0); + TEST_ASSERT(mtx.get_numeric(1, 0) == 22.0); + + TEST_ASSERT(mtx.get_boolean(0, 0) == false); + TEST_ASSERT(mtx.get_boolean(1, 1) == true); + TEST_ASSERT(mtx.get_boolean(0, 1) == true); + TEST_ASSERT(mtx.get_boolean(1, 0) == true); - assert(mtx.numeric()); // integers are considered numeric. + TEST_ASSERT(mtx.numeric()); // integers are considered numeric. - assert(mtx.get(0, 0) == 0); - assert(mtx.get(1, 1) == 22); + TEST_ASSERT(mtx.get(0, 0) == 0); + TEST_ASSERT(mtx.get(1, 1) == 22); mtx_type::position_type pos = mtx.position(0, 1); mtx.set(pos, int(987)); - assert(mtx.get(0, 1) == 987); + TEST_ASSERT(mtx.get(0, 1) == 987); // +--------+--------+ // | int | int | @@ -361,49 +363,50 @@ // | double | int | // +--------+--------+ - vector nodes; + std::vector nodes; std::function f = [&nodes](const mtx_type::element_block_node_type& node) { nodes.push_back(node); }; mtx.walk(f); - assert(nodes.size() == 3); - assert(nodes[0].type == mtm::element_integer); - assert(nodes[0].size == 1); - assert(nodes[1].type == mtm::element_numeric); - assert(nodes[1].size == 1); - assert(nodes[2].type == mtm::element_integer); - assert(nodes[2].size == 2); + TEST_ASSERT(nodes.size() == 3); + TEST_ASSERT(nodes[0].type == mtm::element_integer); + TEST_ASSERT(nodes[0].size == 1); + TEST_ASSERT(nodes[1].type == mtm::element_numeric); + TEST_ASSERT(nodes[1].size == 1); + TEST_ASSERT(nodes[2].type == mtm::element_integer); + TEST_ASSERT(nodes[2].size == 2); { auto it = nodes[2].begin(); auto ite = nodes[2].end(); - assert(*it == 987); + TEST_ASSERT(*it == 987); ++it; - assert(*it == 22); + TEST_ASSERT(*it == 22); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); } } void mtm_test_set_empty() { - stack_printer __stack_printer__("::mtm_test_set_empty"); + MDDS_TEST_FUNC_SCOPE; + { // set whole column empty. mtx_type mtx(3, 5, 1.2); cout << "setting whole column 2 empty..." << endl; mtx.set_column_empty(2); - assert(mtx.get_type(0, 1) != mtm::element_empty); - assert(mtx.get_type(1, 1) != mtm::element_empty); - assert(mtx.get_type(2, 1) != mtm::element_empty); - assert(mtx.get_type(0, 2) == mtm::element_empty); - assert(mtx.get_type(1, 2) == mtm::element_empty); - assert(mtx.get_type(2, 2) == mtm::element_empty); - assert(mtx.get_type(0, 3) != mtm::element_empty); - assert(mtx.get_type(1, 3) != mtm::element_empty); - assert(mtx.get_type(2, 3) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 1) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 1) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 1) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 2) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 2) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 2) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 3) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 3) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 3) != mtm::element_empty); } { @@ -411,48 +414,48 @@ mtx_type mtx(3, 5, 1.2); cout << "setting whole row 1 empty..." << endl; mtx.set_row_empty(1); - assert(mtx.get_type(0, 0) != mtm::element_empty); - assert(mtx.get_type(0, 1) != mtm::element_empty); - assert(mtx.get_type(0, 2) != mtm::element_empty); - assert(mtx.get_type(0, 3) != mtm::element_empty); - assert(mtx.get_type(0, 4) != mtm::element_empty); - assert(mtx.get_type(1, 0) == mtm::element_empty); - assert(mtx.get_type(1, 1) == mtm::element_empty); - assert(mtx.get_type(1, 2) == mtm::element_empty); - assert(mtx.get_type(1, 3) == mtm::element_empty); - assert(mtx.get_type(1, 4) == mtm::element_empty); - assert(mtx.get_type(2, 0) != mtm::element_empty); - assert(mtx.get_type(2, 1) != mtm::element_empty); - assert(mtx.get_type(2, 2) != mtm::element_empty); - assert(mtx.get_type(2, 3) != mtm::element_empty); - assert(mtx.get_type(2, 4) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 0) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 1) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 2) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 3) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 4) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 2) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 3) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 4) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 0) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 1) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 2) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 3) != mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 4) != mtm::element_empty); } { // Set a range of elements empty. - mtx_type mtx(5, 3, string("A")); + mtx_type mtx(5, 3, std::string("A")); cout << "setting element (0,1) to (1,2) empty..." << endl; mtx.set_empty(1, 0, 6); // rows 1-4 in column 0 and rows 0-1 in column 1. - assert(mtx.get_type(0, 0) == mtm::element_string); - assert(mtx.get_type(1, 0) == mtm::element_empty); - assert(mtx.get_type(2, 0) == mtm::element_empty); - assert(mtx.get_type(3, 0) == mtm::element_empty); - assert(mtx.get_type(4, 0) == mtm::element_empty); - assert(mtx.get_type(0, 1) == mtm::element_empty); - assert(mtx.get_type(1, 1) == mtm::element_empty); - assert(mtx.get_type(2, 1) == mtm::element_string); - assert(mtx.get_type(3, 1) == mtm::element_string); - assert(mtx.get_type(4, 1) == mtm::element_string); - assert(mtx.get_type(0, 2) == mtm::element_string); - assert(mtx.get_type(1, 2) == mtm::element_string); - assert(mtx.get_type(2, 2) == mtm::element_string); - assert(mtx.get_type(3, 2) == mtm::element_string); - assert(mtx.get_type(4, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_string); + TEST_ASSERT(mtx.get_type(1, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(3, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(4, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(2, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(3, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(4, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(0, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(1, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(2, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(3, 2) == mtm::element_string); + TEST_ASSERT(mtx.get_type(4, 2) == mtm::element_string); try { mtx.set_empty(2, 2, 0); - assert(false); + TEST_ASSERT(false); } catch (const std::exception&) { @@ -463,7 +466,8 @@ void mtm_test_swap() { - stack_printer __stack_printer__("::mtm_test_swap"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx1(3, 6), mtx2(7, 2); mtx1.set(0, 0, 1.1); mtx1.set(2, 5, 1.9); @@ -471,161 +475,163 @@ mtx2.set(6, 1, 2.9); mtx1.swap(mtx2); - assert(mtx1.size().row == 7); - assert(mtx1.size().column == 2); - assert(mtx1.get(0, 0) == 2.1); - assert(mtx1.get(6, 1) == 2.9); - - assert(mtx2.size().row == 3); - assert(mtx2.size().column == 6); - assert(mtx2.get(0, 0) == 1.1); - assert(mtx2.get(2, 5) == 1.9); + TEST_ASSERT(mtx1.size().row == 7); + TEST_ASSERT(mtx1.size().column == 2); + TEST_ASSERT(mtx1.get(0, 0) == 2.1); + TEST_ASSERT(mtx1.get(6, 1) == 2.9); + + TEST_ASSERT(mtx2.size().row == 3); + TEST_ASSERT(mtx2.size().column == 6); + TEST_ASSERT(mtx2.get(0, 0) == 1.1); + TEST_ASSERT(mtx2.get(2, 5) == 1.9); } void mtm_test_transpose() { - stack_printer __stack_printer__("::mtm_test_transpose"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx(3, 6); mtx.set(0, 0, 1.1); mtx.set(1, 0, 1.2); mtx.set(2, 0, 1.3); - mtx.set(1, 5, string("foo")); + mtx.set(1, 5, std::string("foo")); mtx.set(2, 3, true); mtx.transpose(); - assert(mtx.size().row == 6); - assert(mtx.size().column == 3); - assert(mtx.get(0, 0) == 1.1); - assert(mtx.get(0, 1) == 1.2); - assert(mtx.get(0, 2) == 1.3); - assert(mtx.get(5, 1) == "foo"); - assert(mtx.get(3, 2) == true); + TEST_ASSERT(mtx.size().row == 6); + TEST_ASSERT(mtx.size().column == 3); + TEST_ASSERT(mtx.get(0, 0) == 1.1); + TEST_ASSERT(mtx.get(0, 1) == 1.2); + TEST_ASSERT(mtx.get(0, 2) == 1.3); + TEST_ASSERT(mtx.get(5, 1) == "foo"); + TEST_ASSERT(mtx.get(3, 2) == true); } void mtm_test_resize() { - stack_printer __stack_printer__("::mtm_test_resize"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx(0, 0); - assert(mtx.size().row == 0); - assert(mtx.size().column == 0); - assert(mtx.empty()); + TEST_ASSERT(mtx.size().row == 0); + TEST_ASSERT(mtx.size().column == 0); + TEST_ASSERT(mtx.empty()); mtx.resize(1, 3); - assert(mtx.size().row == 1); - assert(mtx.size().column == 3); - assert(!mtx.empty()); - assert(mtx.get_type(0, 0) == mtm::element_empty); - assert(mtx.get_type(0, 1) == mtm::element_empty); - assert(mtx.get_type(0, 2) == mtm::element_empty); + TEST_ASSERT(mtx.size().row == 1); + TEST_ASSERT(mtx.size().column == 3); + TEST_ASSERT(!mtx.empty()); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 2) == mtm::element_empty); mtx.set(0, 0, 1.1); - mtx.set(0, 1, string("foo")); + mtx.set(0, 1, std::string("foo")); mtx.set(0, 2, true); - assert(mtx.get(0, 0) == 1.1); - assert(mtx.get(0, 1) == "foo"); - assert(mtx.get(0, 2) == true); + TEST_ASSERT(mtx.get(0, 0) == 1.1); + TEST_ASSERT(mtx.get(0, 1) == "foo"); + TEST_ASSERT(mtx.get(0, 2) == true); // This shouldn't alter the original content. mtx.resize(2, 4); - assert(mtx.size().row == 2); - assert(mtx.size().column == 4); - assert(mtx.get(0, 0) == 1.1); - assert(mtx.get(0, 1) == "foo"); - assert(mtx.get(0, 2) == true); - assert(mtx.get_type(1, 3) == mtm::element_empty); + TEST_ASSERT(mtx.size().row == 2); + TEST_ASSERT(mtx.size().column == 4); + TEST_ASSERT(mtx.get(0, 0) == 1.1); + TEST_ASSERT(mtx.get(0, 1) == "foo"); + TEST_ASSERT(mtx.get(0, 2) == true); + TEST_ASSERT(mtx.get_type(1, 3) == mtm::element_empty); mtx.resize(2, 2); - assert(mtx.size().row == 2); - assert(mtx.size().column == 2); - assert(mtx.get(0, 0) == 1.1); - assert(mtx.get(0, 1) == "foo"); - assert(mtx.get_type(1, 0) == mtm::element_empty); - assert(mtx.get_type(1, 1) == mtm::element_empty); + TEST_ASSERT(mtx.size().row == 2); + TEST_ASSERT(mtx.size().column == 2); + TEST_ASSERT(mtx.get(0, 0) == 1.1); + TEST_ASSERT(mtx.get(0, 1) == "foo"); + TEST_ASSERT(mtx.get_type(1, 0) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_empty); // Three ways to resize to empty matrix. mtx.resize(2, 0); - assert(mtx.size().row == 0); - assert(mtx.size().column == 0); + TEST_ASSERT(mtx.size().row == 0); + TEST_ASSERT(mtx.size().column == 0); mtx.resize(2, 2); mtx.resize(0, 2); - assert(mtx.size().row == 0); - assert(mtx.size().column == 0); + TEST_ASSERT(mtx.size().row == 0); + TEST_ASSERT(mtx.size().column == 0); mtx.resize(2, 2); mtx.resize(0, 0); - assert(mtx.size().row == 0); - assert(mtx.size().column == 0); + TEST_ASSERT(mtx.size().row == 0); + TEST_ASSERT(mtx.size().column == 0); // Resize with initial value when the matrix becomes larger. mtx.resize(3, 2, 12.5); - assert(mtx.size().row == 3); - assert(mtx.size().column == 2); - assert(mtx.get(2, 1) == 12.5); - assert(mtx.get(2, 0) == 12.5); - assert(mtx.get(0, 0) == 12.5); - assert(mtx.get(0, 1) == 12.5); + TEST_ASSERT(mtx.size().row == 3); + TEST_ASSERT(mtx.size().column == 2); + TEST_ASSERT(mtx.get(2, 1) == 12.5); + TEST_ASSERT(mtx.get(2, 0) == 12.5); + TEST_ASSERT(mtx.get(0, 0) == 12.5); + TEST_ASSERT(mtx.get(0, 1) == 12.5); // The initial value should be ignored when shrinking. mtx.resize(2, 1, true); - assert(mtx.size().row == 2); - assert(mtx.size().column == 1); - assert(mtx.get(1, 0) == 12.5); + TEST_ASSERT(mtx.size().row == 2); + TEST_ASSERT(mtx.size().column == 1); + TEST_ASSERT(mtx.get(1, 0) == 12.5); // Resize again with initial value of different type. - mtx.resize(3, 2, string("extra")); - assert(mtx.size().row == 3); - assert(mtx.size().column == 2); - assert(mtx.get(0, 0) == 12.5); - assert(mtx.get(1, 0) == 12.5); - assert(mtx.get(2, 1) == "extra"); - assert(mtx.get(2, 0) == "extra"); - assert(mtx.get(1, 1) == "extra"); - assert(mtx.get(0, 1) == "extra"); + mtx.resize(3, 2, std::string("extra")); + TEST_ASSERT(mtx.size().row == 3); + TEST_ASSERT(mtx.size().column == 2); + TEST_ASSERT(mtx.get(0, 0) == 12.5); + TEST_ASSERT(mtx.get(1, 0) == 12.5); + TEST_ASSERT(mtx.get(2, 1) == "extra"); + TEST_ASSERT(mtx.get(2, 0) == "extra"); + TEST_ASSERT(mtx.get(1, 1) == "extra"); + TEST_ASSERT(mtx.get(0, 1) == "extra"); } void mtm_test_copy() { - stack_printer __stack_printer__("::mtm_test_copy"); + MDDS_TEST_FUNC_SCOPE; // Assigning from a smaller matrix to a bigger one. mtx_type mx1(5, 5), mx2(2, 2); mx2.set(0, 0, 1.2); mx2.set(1, 1, true); - mx2.set(0, 1, string("test")); - mx2.set(1, 0, string("foo")); + mx2.set(0, 1, std::string("test")); + mx2.set(1, 0, std::string("foo")); mx1.copy(mx2); bool success = check_copy(mx1, mx2); - assert(success); + TEST_ASSERT(success); mx2.resize(8, 8); mx2.copy(mx1); success = check_copy(mx1, mx2); - assert(success); + TEST_ASSERT(success); // from a larger matrix to a smaller one. - mx1.set(0, 0, string("test1")); - mx2.set(0, 0, string("test2")); + mx1.set(0, 0, std::string("test1")); + mx2.set(0, 0, std::string("test2")); mx2.set(4, 4, true); mx2.set(7, 7, false); mx1.copy(mx2); success = check_copy(mx1, mx2); - assert(success); + TEST_ASSERT(success); // self assignment (should be no-op). mx1.copy(mx1); success = check_copy(mx1, mx1); - assert(success); + TEST_ASSERT(success); mx2.copy(mx2); success = check_copy(mx2, mx2); - assert(success); + TEST_ASSERT(success); } void mtm_test_copy_empty_destination() { - stack_printer __stack_printer__("::mtm_test_copy_empty_destination"); + MDDS_TEST_FUNC_SCOPE; mtx_type mx1, mx2(1, 1); mx1.copy(mx2); // This should not throw. @@ -635,9 +641,9 @@ void mtm_test_copy_from_array() { - stack_printer __stack_printer__("::mtm_test_copy_from_array"); + MDDS_TEST_FUNC_SCOPE; - vector src; + std::vector src; src.reserve(9); for (size_t i = 0; i < 9; ++i) src.push_back(double(i)); @@ -645,25 +651,25 @@ mtx_type mx(4, 4); mx.copy(3, 3, src.begin(), src.end()); - assert(mx.get(0, 0) == 0.0); - assert(mx.get(1, 0) == 1.0); - assert(mx.get(2, 0) == 2.0); - assert(mx.get(0, 1) == 3.0); - assert(mx.get(1, 1) == 4.0); - assert(mx.get(2, 1) == 5.0); - assert(mx.get(0, 2) == 6.0); - assert(mx.get(1, 2) == 7.0); - assert(mx.get(2, 2) == 8.0); - assert(mx.get_type(3, 0) == mtm::element_empty); - assert(mx.get_type(3, 1) == mtm::element_empty); - assert(mx.get_type(3, 2) == mtm::element_empty); - assert(mx.get_type(3, 3) == mtm::element_empty); - assert(mx.get_type(0, 3) == mtm::element_empty); - assert(mx.get_type(1, 3) == mtm::element_empty); - assert(mx.get_type(2, 3) == mtm::element_empty); - assert(mx.get_type(3, 3) == mtm::element_empty); + TEST_ASSERT(mx.get(0, 0) == 0.0); + TEST_ASSERT(mx.get(1, 0) == 1.0); + TEST_ASSERT(mx.get(2, 0) == 2.0); + TEST_ASSERT(mx.get(0, 1) == 3.0); + TEST_ASSERT(mx.get(1, 1) == 4.0); + TEST_ASSERT(mx.get(2, 1) == 5.0); + TEST_ASSERT(mx.get(0, 2) == 6.0); + TEST_ASSERT(mx.get(1, 2) == 7.0); + TEST_ASSERT(mx.get(2, 2) == 8.0); + TEST_ASSERT(mx.get_type(3, 0) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 1) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 2) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(0, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(1, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(2, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 3) == mtm::element_empty); - vector src2; + std::vector src2; src2.reserve(4); src2.push_back("A"); src2.push_back("B"); @@ -672,45 +678,45 @@ mx.copy(2, 2, src2.begin(), src2.end()); - assert(mx.get(0, 0) == "A"); - assert(mx.get(1, 0) == "B"); - assert(mx.get(0, 1) == "C"); - assert(mx.get(1, 1) == "D"); - assert(mx.get(2, 0) == 2.0); - assert(mx.get(2, 1) == 5.0); - assert(mx.get(0, 2) == 6.0); - assert(mx.get(1, 2) == 7.0); - assert(mx.get(2, 2) == 8.0); - assert(mx.get_type(3, 0) == mtm::element_empty); - assert(mx.get_type(3, 1) == mtm::element_empty); - assert(mx.get_type(3, 2) == mtm::element_empty); - assert(mx.get_type(3, 3) == mtm::element_empty); - assert(mx.get_type(0, 3) == mtm::element_empty); - assert(mx.get_type(1, 3) == mtm::element_empty); - assert(mx.get_type(2, 3) == mtm::element_empty); - assert(mx.get_type(3, 3) == mtm::element_empty); + TEST_ASSERT(mx.get(0, 0) == "A"); + TEST_ASSERT(mx.get(1, 0) == "B"); + TEST_ASSERT(mx.get(0, 1) == "C"); + TEST_ASSERT(mx.get(1, 1) == "D"); + TEST_ASSERT(mx.get(2, 0) == 2.0); + TEST_ASSERT(mx.get(2, 1) == 5.0); + TEST_ASSERT(mx.get(0, 2) == 6.0); + TEST_ASSERT(mx.get(1, 2) == 7.0); + TEST_ASSERT(mx.get(2, 2) == 8.0); + TEST_ASSERT(mx.get_type(3, 0) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 1) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 2) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(0, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(1, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(2, 3) == mtm::element_empty); + TEST_ASSERT(mx.get_type(3, 3) == mtm::element_empty); - vector src3; + std::vector src3; src3.push_back(true); src3.push_back(false); src3.push_back(true); src3.push_back(false); mx.copy(4, 1, src3.begin(), src3.end()); - assert(mx.get(0, 0) == true); - assert(mx.get(1, 0) == false); - assert(mx.get(2, 0) == true); - assert(mx.get(3, 0) == false); + TEST_ASSERT(mx.get(0, 0) == true); + TEST_ASSERT(mx.get(1, 0) == false); + TEST_ASSERT(mx.get(2, 0) == true); + TEST_ASSERT(mx.get(3, 0) == false); // Try to copy from an array of invalid type. - vector src_invalid; + std::vector src_invalid; src_invalid.push_back('a'); src_invalid.push_back('b'); try { mx.copy(2, 1, src_invalid.begin(), src_invalid.end()); - assert(!"type_error did not get thrown."); + TEST_ASSERT(!"type_error did not get thrown."); } catch (const mdds::type_error& e) { @@ -720,167 +726,173 @@ void mtm_test_assignment() { - stack_printer __stack_printer__("::mtm_test_assignment"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mx_orig(5, 5, 1.2); mtx_type mx_copied = mx_orig; - assert(mx_orig == mx_copied); + TEST_ASSERT(mx_orig == mx_copied); mx_copied = mx_copied; // self assignment. - assert(mx_orig == mx_copied); + TEST_ASSERT(mx_orig == mx_copied); mx_orig.set(2, 3, true); - mx_orig.set(1, 1, string("foo")); + mx_orig.set(1, 1, std::string("foo")); mx_copied = mx_orig; - assert(mx_orig == mx_copied); + TEST_ASSERT(mx_orig == mx_copied); } void mtm_test_numeric() { + MDDS_TEST_FUNC_SCOPE; + // Numeric elements only matrix is numeric. mtx_type mtx(2, 2, 1.1); - assert(mtx.numeric()); + TEST_ASSERT(mtx.numeric()); // Boolean element is numeric. mtx.set(0, 0, true); - assert(mtx.numeric()); + TEST_ASSERT(mtx.numeric()); // String element is not. - mtx.set(1, 0, string("foo")); - assert(!mtx.numeric()); + mtx.set(1, 0, std::string("foo")); + TEST_ASSERT(!mtx.numeric()); mtx.set(1, 0, 1.3); - assert(mtx.numeric()); + TEST_ASSERT(mtx.numeric()); // Empty element is not numeric. mtx.set_empty(1, 1); - assert(!mtx.numeric()); + TEST_ASSERT(!mtx.numeric()); // Empty matrix is not numeric. mtx.clear(); - assert(!mtx.numeric()); + TEST_ASSERT(!mtx.numeric()); } void mtm_test_custom_string() { - stack_printer __stack_printer__("::mtm_test_custom_string"); + MDDS_TEST_FUNC_SCOPE; + mtx_custom_type mtx(2, 2); mtx.set(0, 0, custom_string("foo")); - assert(mtx.get_type(0, 0) == mtm::element_string); - assert(mtx.get(0, 0) == custom_string("foo")); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_string); + TEST_ASSERT(mtx.get(0, 0) == custom_string("foo")); mtx.set(1, 1, 12.3); - assert(mtx.get(1, 1) == 12.3); + TEST_ASSERT(mtx.get(1, 1) == 12.3); } void mtm_test_position() { - stack_printer __stack_printer__("::mtm_test_position"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx(3, 2); mtx.set(0, 0, 1.0); - mtx.set(0, 1, string("foo")); + mtx.set(0, 1, std::string("foo")); mtx.set(1, 0, 2.0); mtx.set(1, 1, 2.1); mtx.set(2, 0, true); mtx.set(2, 1, false); - assert(mtx.get_type(0, 0) == mtm::element_numeric); - assert(mtx.get_type(0, 1) == mtm::element_string); - assert(mtx.get_type(1, 0) == mtm::element_numeric); - assert(mtx.get_type(1, 1) == mtm::element_numeric); - assert(mtx.get_type(2, 0) == mtm::element_boolean); - assert(mtx.get_type(2, 1) == mtm::element_boolean); + TEST_ASSERT(mtx.get_type(0, 0) == mtm::element_numeric); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_type(1, 0) == mtm::element_numeric); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_numeric); + TEST_ASSERT(mtx.get_type(2, 0) == mtm::element_boolean); + TEST_ASSERT(mtx.get_type(2, 1) == mtm::element_boolean); mtx_type::position_type pos = mtx.position(1, 1); - assert(mtx.get_type(pos) == mtm::element_numeric); - assert(mtx.get_numeric(pos) == 2.1); + TEST_ASSERT(mtx.get_type(pos) == mtm::element_numeric); + TEST_ASSERT(mtx.get_numeric(pos) == 2.1); pos = mtx.position(2, 0); - assert(mtx.get_type(pos) == mtm::element_boolean); - assert(mtx.get_boolean(pos) == true); + TEST_ASSERT(mtx.get_type(pos) == mtm::element_boolean); + TEST_ASSERT(mtx.get_boolean(pos) == true); pos = mtx.position(0, 1); - assert(mtx.get_type(pos) == mtm::element_string); - assert(mtx.get_string(pos) == "foo"); + TEST_ASSERT(mtx.get_type(pos) == mtm::element_string); + TEST_ASSERT(mtx.get_string(pos) == "foo"); mtx.set_empty(pos); - assert(mtx.get_type(0, 1) == mtm::element_empty); + TEST_ASSERT(mtx.get_type(0, 1) == mtm::element_empty); pos = mtx.position(1, 1); mtx.set(pos, false); - assert(mtx.get_type(1, 1) == mtm::element_boolean); - assert(mtx.get_boolean(1, 1) == false); + TEST_ASSERT(mtx.get_type(1, 1) == mtm::element_boolean); + TEST_ASSERT(mtx.get_boolean(1, 1) == false); pos = mtx.position(2, 0); mtx.set(pos, 12.3); - assert(mtx.get_type(2, 0) == mtm::element_numeric); - assert(mtx.get_numeric(2, 0) == 12.3); + TEST_ASSERT(mtx.get_type(2, 0) == mtm::element_numeric); + TEST_ASSERT(mtx.get_numeric(2, 0) == 12.3); pos = mtx.position(2, 1); - mtx.set(pos, string("ABC")); - assert(mtx.get_type(2, 1) == mtm::element_string); - assert(mtx.get_string(2, 1) == "ABC"); + mtx.set(pos, std::string("ABC")); + TEST_ASSERT(mtx.get_type(2, 1) == mtm::element_string); + TEST_ASSERT(mtx.get_string(2, 1) == "ABC"); // Start over, and test the traversal of position object. pos = mtx.position(0, 0); mtx_type::size_pair_type mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 0); - assert(mtx_pos.row == 0); + TEST_ASSERT(mtx_pos.column == 0); + TEST_ASSERT(mtx_pos.row == 0); pos = mtx_type::next_position(pos); mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 0); - assert(mtx_pos.row == 1); + TEST_ASSERT(mtx_pos.column == 0); + TEST_ASSERT(mtx_pos.row == 1); pos = mtx_type::next_position(pos); mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 0); - assert(mtx_pos.row == 2); + TEST_ASSERT(mtx_pos.column == 0); + TEST_ASSERT(mtx_pos.row == 2); pos = mtx_type::next_position(pos); mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 1); - assert(mtx_pos.row == 0); + TEST_ASSERT(mtx_pos.column == 1); + TEST_ASSERT(mtx_pos.row == 0); pos = mtx_type::next_position(pos); mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 1); - assert(mtx_pos.row == 1); + TEST_ASSERT(mtx_pos.column == 1); + TEST_ASSERT(mtx_pos.row == 1); pos = mtx_type::next_position(pos); mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.column == 1); - assert(mtx_pos.row == 2); + TEST_ASSERT(mtx_pos.column == 1); + TEST_ASSERT(mtx_pos.row == 2); pos = mtx_type::next_position(pos); - assert(pos == mtx.end_position()); + TEST_ASSERT(pos == mtx.end_position()); } void mtm_test_set_data_via_position() { - stack_printer __stack_printer__("::mtm_test_set_data_via_position"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx(5, 4); mtx_type::position_type pos = mtx.position(0, 1); - vector data; + std::vector data; data.push_back(1.1); data.push_back(1.2); data.push_back(1.3); data.push_back(1.4); data.push_back(1.5); pos = mtx.set(pos, data.begin(), data.end()); - assert(mtx.get(0, 1) == 1.1); - assert(mtx.get(1, 1) == 1.2); - assert(mtx.get(2, 1) == 1.3); - assert(mtx.get(3, 1) == 1.4); - assert(mtx.get(4, 1) == 1.5); + TEST_ASSERT(mtx.get(0, 1) == 1.1); + TEST_ASSERT(mtx.get(1, 1) == 1.2); + TEST_ASSERT(mtx.get(2, 1) == 1.3); + TEST_ASSERT(mtx.get(3, 1) == 1.4); + TEST_ASSERT(mtx.get(4, 1) == 1.5); mtx_type::size_pair_type mtx_pos = mtx.matrix_position(pos); - assert(mtx_pos.row == 0); - assert(mtx_pos.column == 1); + TEST_ASSERT(mtx_pos.row == 0); + TEST_ASSERT(mtx_pos.column == 1); pos = mtx.position(pos, 0, 2); - pos = mtx.set(pos, string("test")); + pos = mtx.set(pos, std::string("test")); pos = mtx_type::next_position(pos); pos = mtx.set(pos, true); - assert(mtx.get(0, 2) == "test"); - assert(mtx.get(1, 2) == true); + TEST_ASSERT(mtx.get(0, 2) == "test"); + TEST_ASSERT(mtx.get(1, 2) == true); } /** @@ -935,7 +947,7 @@ mtx_type mx(rowsize, colsize, 0.0); for (size_t col = 0; col < colsize; ++col) { - vector vals; + std::vector vals; vals.reserve(rowsize); for (size_t row = 0; row < rowsize; ++row) vals.push_back(1.0); @@ -949,7 +961,7 @@ for (size_t colsize = 1; colsize <= 5; ++colsize) { // Fill the data array before insertion. - vector vals; + std::vector vals; vals.reserve(rowsize); for (size_t row = 0; row < rowsize; ++row) vals.push_back(1.0); @@ -973,7 +985,7 @@ mtx_type mx(rowsize, colsize); for (size_t col = 0; col < colsize; ++col) { - vector vals; + std::vector vals; vals.reserve(rowsize); for (size_t row = 0; row < rowsize; ++row) vals.push_back(1.0); @@ -987,7 +999,7 @@ for (size_t colsize = 1; colsize <= 5; ++colsize) { // Fill the data array before insertion. - vector vals; + std::vector vals; vals.reserve(rowsize); for (size_t row = 0; row < rowsize; ++row) vals.push_back(1.0); diff -Nru mdds-2.1.1/test/multi_type_matrix/test_walk.cpp mdds-3.1.0/test/multi_type_matrix/test_walk.cpp --- mdds-2.1.1/test/multi_type_matrix/test_walk.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_matrix/test_walk.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -34,7 +34,6 @@ #include using namespace mdds; -using namespace std; // Standard matrix that uses std::string as its string type. typedef multi_type_matrix mtx_type; @@ -50,7 +49,7 @@ { void operator()(const _T& v) const { - cout << v << endl; + std::cout << v << std::endl; } }; @@ -91,7 +90,7 @@ } break; case mtm::element_empty: - cout << "- empty block -" << endl; + std::cout << "- empty block -" << std::endl; break; default:; } @@ -138,63 +137,66 @@ void mtm_test_walk() { - stack_printer __stack_printer__("::mtm_test_walk"); + MDDS_TEST_FUNC_SCOPE; + mtx_type mtx(12, 1); // single column matrix to make it easier. mtx.set(2, 0, 1.1); mtx.set(3, 0, 1.2); mtx.set(4, 0, 1.3); mtx.set(5, 0, 1.4); - mtx.set(7, 0, string("A")); - mtx.set(8, 0, string("B")); - mtx.set(9, 0, string("C")); + mtx.set(7, 0, std::string("A")); + mtx.set(8, 0, std::string("B")); + mtx.set(9, 0, std::string("C")); mtx.set(10, 0, false); mtx.set(11, 0, true); walk_element_block func; func = mtx.walk(func); - assert(func.get_node_count() == 5); + TEST_ASSERT(func.get_node_count() == 5); walk_element_block_move_only func_mo; func_mo = mtx.walk(std::move(func_mo)); - assert(func_mo.get_node_count() == 5); + TEST_ASSERT(func_mo.get_node_count() == 5); } void mtm_test_walk_subset() { { - stack_printer __stack_printer__("::mtm_test_walk_subset test1"); + MDDS_TEST_FUNC_SCOPE_MSG("test1"); + mtx_type mtx(4, 4); mtx.set(1, 1, 1.1); mtx.set(2, 1, 1.2); mtx.set(3, 1, 1.3); - mtx.set(0, 2, string("A1")); - mtx.set(1, 2, string("A2")); + mtx.set(0, 2, std::string("A1")); + mtx.set(1, 2, std::string("A2")); mtx.set(2, 2, false); walk_element_block func; func = mtx.walk(func, mtx_type::size_pair_type(1, 1), mtx_type::size_pair_type(2, 2)); - assert(func.get_node_count() == 3); + TEST_ASSERT(func.get_node_count() == 3); } { - stack_printer __stack_printer__("::mtm_test_walk_subset test2"); + MDDS_TEST_FUNC_SCOPE_MSG("test2"); + mtx_type mtx(4, 4); mtx.set(0, 1, 1.0); mtx.set(1, 1, 1.1); - mtx.set(0, 2, string("A1")); - mtx.set(1, 2, string("A2")); - mtx.set(2, 2, string("A3")); - mtx.set(3, 2, string("A4")); + mtx.set(0, 2, std::string("A1")); + mtx.set(1, 2, std::string("A2")); + mtx.set(2, 2, std::string("A3")); + mtx.set(3, 2, std::string("A4")); walk_element_block func; func = mtx.walk(func, mtx_type::size_pair_type(1, 1), mtx_type::size_pair_type(2, 2)); - assert(func.get_node_count() == 3); + TEST_ASSERT(func.get_node_count() == 3); } } template -void push_to_buffer(const mtx_type::element_block_node_type& node, std::vector& buf) +void push_to_buffer(const mtx_type::element_block_node_type& node, std::vector& buf) { auto it = node.begin<_Blk>(); auto ite = node.end<_Blk>(); std::for_each(it, ite, [&](const typename _Blk::value_type& v) { - ostringstream os; + std::ostringstream os; os << v; buf.push_back(os.str()); }); @@ -202,13 +204,13 @@ template<> void push_to_buffer( - const mtx_type::element_block_node_type& node, std::vector& buf) + const mtx_type::element_block_node_type& node, std::vector& buf) { using blk_type = mtx_type::boolean_block_type; auto it = node.begin(); auto ite = node.end(); std::for_each(it, ite, [&](bool v) { - ostringstream os; + std::ostringstream os; os << (v ? "true" : "false"); buf.push_back(os.str()); }); @@ -216,7 +218,7 @@ class parallel_walk_element_block { - using strlist_type = std::vector; + using strlist_type = std::vector; std::string m_name; std::shared_ptr m_ls; @@ -268,9 +270,9 @@ void operator()(const mtx_type::element_block_node_type& left, const mtx_type::element_block_node_type& right) { - cout << "--" << endl; - cout << "l: " << left << endl; - cout << "r: " << right << endl; + std::cout << "--" << std::endl; + std::cout << "l: " << left << std::endl; + std::cout << "r: " << right << std::endl; process_node(left, *m_ls); process_node(right, *m_rs); } @@ -278,12 +280,12 @@ strlist_type get_concat_buffer() const { strlist_type buf; - assert(m_ls->size() == m_rs->size()); + TEST_ASSERT(m_ls->size() == m_rs->size()); auto it = m_ls->begin(), it2 = m_rs->begin(); auto ite = m_ls->end(); for (; it != ite; ++it, ++it2) { - ostringstream os; + std::ostringstream os; os << *it << ":" << *it2; buf.push_back(os.str()); } @@ -308,7 +310,7 @@ } }; -bool check_concat_buffer(std::vector concat, const char* expected[], size_t expected_size) +bool check_concat_buffer(std::vector concat, const char* expected[], size_t expected_size) { if (concat.size() != expected_size) { @@ -330,22 +332,22 @@ void mtm_test_parallel_walk() { - stack_printer __stack_printer__("::mtm_test_parallel_walk"); + MDDS_TEST_FUNC_SCOPE; parallel_walk_element_block func("test0"); - mtx_type left(10, 1), right(10, 1, string("'+'")); + mtx_type left(10, 1), right(10, 1, std::string("'+'")); right.set(2, 0, 1.2); right.set(8, 0, false); right.set(9, 0, true); left.set(0, 0, 122.0); - left.set(4, 0, string("A12")); - left.set(5, 0, string("A25")); + left.set(4, 0, std::string("A12")); + left.set(5, 0, std::string("A25")); { func = left.walk(func, right); - assert(func.get_name() == "test0"); + TEST_ASSERT(func.get_name() == "test0"); const char* expected[] = { "122:'+'", "' ':'+'", "' ':1.2", "' ':'+'", "A12:'+'", @@ -353,7 +355,7 @@ }; size_t n = std::size(expected); - assert(check_concat_buffer(func.get_concat_buffer(), expected, n)); + TEST_ASSERT(check_concat_buffer(func.get_concat_buffer(), expected, n)); } func.clear(); @@ -361,14 +363,14 @@ { func.set_name("test0-2"); func = left.walk(func, right, mtx_type::size_pair_type(2, 0), mtx_type::size_pair_type(8, 0)); - assert(func.get_name() == "test0-2"); + TEST_ASSERT(func.get_name() == "test0-2"); const char* expected[] = { "' ':1.2", "' ':'+'", "A12:'+'", "A25:'+'", "' ':'+'", "' ':'+'", "' ':false", }; size_t n = std::size(expected); - assert(check_concat_buffer(func.get_concat_buffer(), expected, n)); + TEST_ASSERT(check_concat_buffer(func.get_concat_buffer(), expected, n)); } func.clear(); @@ -377,20 +379,20 @@ // Only one row. func.set_name("test0-3"); func = left.walk(func, right, mtx_type::size_pair_type(4, 0), mtx_type::size_pair_type(4, 0)); - assert(func.get_name() == "test0-3"); + TEST_ASSERT(func.get_name() == "test0-3"); const char* expected[] = { "A12:'+'", }; size_t n = std::size(expected); - assert(check_concat_buffer(func.get_concat_buffer(), expected, n)); + TEST_ASSERT(check_concat_buffer(func.get_concat_buffer(), expected, n)); } } void mtm_test_parallel_walk_non_equal_size() { - stack_printer __stack_printer__("::mtm_test_parallel_walk_non_equal_size"); + MDDS_TEST_FUNC_SCOPE; mtx_type left(3, 3), right(2, 2); @@ -404,16 +406,16 @@ left.set(1, 2, 80.0); left.set(2, 2, 90.0); - right.set(0, 0, string("A")); - right.set(1, 0, string("B")); - right.set(0, 1, string("C")); - right.set(1, 1, string("D")); + right.set(0, 0, std::string("A")); + right.set(1, 0, std::string("B")); + right.set(0, 1, std::string("C")); + right.set(1, 1, std::string("D")); { // Only walk the top-left 2x2 range. parallel_walk_element_block func("test1"); func = left.walk(func, right, mtx_type::size_pair_type(0, 0), mtx_type::size_pair_type(1, 1)); - assert(func.get_name() == "test1"); + TEST_ASSERT(func.get_name() == "test1"); const char* expected[] = { "10:A", @@ -423,7 +425,7 @@ }; size_t n = std::size(expected); - assert(check_concat_buffer(func.get_concat_buffer(), expected, n)); + TEST_ASSERT(check_concat_buffer(func.get_concat_buffer(), expected, n)); } // Break up the blocks a little. @@ -436,7 +438,7 @@ // Only walk the top-left 2x2 range. parallel_walk_element_block func("test2"); func = left.walk(func, right, mtx_type::size_pair_type(0, 0), mtx_type::size_pair_type(1, 1)); - assert(func.get_name() == "test2"); + TEST_ASSERT(func.get_name() == "test2"); const char* expected[] = { "10:-99", @@ -446,7 +448,7 @@ }; size_t n = std::size(expected); - assert(check_concat_buffer(func.get_concat_buffer(), expected, n)); + TEST_ASSERT(check_concat_buffer(func.get_concat_buffer(), expected, n)); } } @@ -455,14 +457,15 @@ */ void mtm_test_walk_with_lambda() { - stack_printer __stack_printer__("::mtm_test_walk_with_lambda"); - vector values = {1.1, 1.2, 1.3, 1.4}; + MDDS_TEST_FUNC_SCOPE; + + std::vector values = {1.1, 1.2, 1.3, 1.4}; mtx_type mtx(2, 2, values.begin(), values.end()); mtx.walk([](const mtx_type::element_block_node_type& node) { - assert(node.type == mdds::mtm::element_numeric); - assert(node.offset == 0); - assert(node.size == 4); + TEST_ASSERT(node.type == mdds::mtm::element_numeric); + TEST_ASSERT(node.offset == 0); + TEST_ASSERT(node.size == 4); }); struct section @@ -494,14 +497,14 @@ {0, 0}, {0, 1} // (row=0, column=0) to (row=0, column=1) ); - assert(expected == actual); + TEST_ASSERT(expected == actual); } void mtm_test_parallel_walk_with_lambda() { - stack_printer __stack_printer__("::mtm_test_parallel_walk_with_lambda"); + MDDS_TEST_FUNC_SCOPE; - vector values = {1.1, 1.2, 1.3, 1.4}; + std::vector values = {1.1, 1.2, 1.3, 1.4}; mtx_type mtx1(2, 2, values.begin(), values.end()); mtx_type mtx2(2, 2); @@ -540,11 +543,11 @@ std::vector actual; - cout << "--" << endl; + std::cout << "--" << std::endl; mtx1.walk( [&](const mtx_type::element_block_node_type& l, const mtx_type::element_block_node_type& r) { - cout << "left: " << l << "; right: " << r << endl; + std::cout << "left: " << l << "; right: " << r << std::endl; actual.emplace_back(); actual.back().left.type = l.type; actual.back().left.offset = l.offset; @@ -555,7 +558,7 @@ }, mtx2); - assert(expected == actual); + TEST_ASSERT(expected == actual); mtx_type mtx3(4, 4, 1.0), mtx4(4, 4, std::string("A")); mtx3.set(2, 0, true); @@ -581,11 +584,11 @@ actual.clear(); - cout << "--" << endl; + std::cout << "--" << std::endl; mtx3.walk( [&](const mtx_type::element_block_node_type& l, const mtx_type::element_block_node_type& r) { - cout << "left: " << l << "; right: " << r << endl; + std::cout << "left: " << l << "; right: " << r << std::endl; actual.emplace_back(); actual.back().left.type = l.type; actual.back().left.offset = l.offset; @@ -596,14 +599,14 @@ }, mtx4, {0, 0}, {2, 2}); - assert(expected.size() == actual.size()); - assert(expected[0] == actual[0]); - assert(expected[1] == actual[1]); - assert(expected[2] == actual[2]); - assert(expected[3] == actual[3]); - assert(expected[4] == actual[4]); - assert(expected[5] == actual[5]); - assert(expected[6] == actual[6]); + TEST_ASSERT(expected.size() == actual.size()); + TEST_ASSERT(expected[0] == actual[0]); + TEST_ASSERT(expected[1] == actual[1]); + TEST_ASSERT(expected[2] == actual[2]); + TEST_ASSERT(expected[3] == actual[3]); + TEST_ASSERT(expected[4] == actual[4]); + TEST_ASSERT(expected[5] == actual[5]); + TEST_ASSERT(expected[6] == actual[6]); } int main(int argc, char** argv) @@ -635,6 +638,6 @@ return EXIT_FAILURE; } - cout << "Test finished successfully!" << endl; + std::cout << "Test finished successfully!" << std::endl; return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/test/multi_type_vector/Makefile.am mdds-3.1.0/test/multi_type_vector/Makefile.am --- mdds-2.1.1/test/multi_type_vector/Makefile.am 2022-10-28 01:42:14.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/Makefile.am 2025-06-13 02:56:24.000000000 +0000 @@ -1 +1,10 @@ -SUBDIRS = collection custom custom-trait debug-util default element-blocks event perf +SUBDIRS = \ + collection \ + custom \ + custom-trait \ + debug-util \ + default \ + element-blocks \ + event \ + perf \ + push-emplace-back diff -Nru mdds-2.1.1/test/multi_type_vector/Makefile.in mdds-3.1.0/test/multi_type_vector/Makefile.in --- mdds-2.1.1/test/multi_type_vector/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -295,7 +294,17 @@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ -SUBDIRS = collection custom custom-trait debug-util default element-blocks event perf +SUBDIRS = \ + collection \ + custom \ + custom-trait \ + debug-util \ + default \ + element-blocks \ + event \ + perf \ + push-emplace-back + all: all-recursive .SUFFIXES: diff -Nru mdds-2.1.1/test/multi_type_vector/collection/Makefile.in mdds-3.1.0/test/multi_type_vector/collection/Makefile.in --- mdds-2.1.1/test/multi_type_vector/collection/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/collection/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/collection/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/collection/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/collection/aos/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/collection/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -435,7 +435,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/collection/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/collection/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/collection/soa/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/collection/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -435,7 +435,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/collection/tc/Makefile.in mdds-3.1.0/test/multi_type_vector/collection/tc/Makefile.in --- mdds-2.1.1/test/multi_type_vector/collection/tc/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/collection/tc/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -182,7 +182,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/collection/tc/all.inl mdds-3.1.0/test/multi_type_vector/collection/tc/all.inl --- mdds-2.1.1/test/multi_type_vector/collection/tc/all.inl 2022-05-11 00:33:24.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/collection/tc/all.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,14 +28,15 @@ void mtv_test_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + cols_type empty; - assert(empty.begin() == empty.end()); + TEST_ASSERT(empty.begin() == empty.end()); } void mtv_test_pointer_size1() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // Two vectors of size 1, both of which are totally empty. @@ -47,21 +48,21 @@ cols_type::const_iterator it, ite; it = collection.begin(); ite = collection.end(); - assert(it->type == mdds::mtv::element_type_empty); - assert((it++)->index == 0); - assert(it != ite); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT((it++)->index == 0); + TEST_ASSERT(it != ite); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->index == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->index == 1); - assert(++it == ite); + TEST_ASSERT(++it == ite); for_each(vectors.begin(), vectors.end(), [](const mtv_type* p) { delete p; }); } void mtv_test_unique_pointer_size1() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // Two vector of size 1, with empty and numeric values. @@ -73,59 +74,59 @@ cols_type collection(vectors.begin(), vectors.end()); cols_type::const_iterator it = collection.begin(), ite = collection.end(); - assert((*it).type == mdds::mtv::element_type_empty); - assert((*it).index == 0); + TEST_ASSERT((*it).type == mdds::mtv::element_type_empty); + TEST_ASSERT((*it).index == 0); ++it; - assert((*it).type == mdds::mtv::element_type_double); - assert((*it).index == 1); - assert(it->get() == 1.1); + TEST_ASSERT((*it).type == mdds::mtv::element_type_double); + TEST_ASSERT((*it).index == 1); + TEST_ASSERT(it->get() == 1.1); - assert(++it == ite); + TEST_ASSERT(++it == ite); } void mtv_test_shared_pointer_size2() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::vector> vectors; vectors.push_back(std::make_shared(2, 2.3)); vectors.push_back(std::make_shared(2, std::string("test"))); cols_type collection(vectors.begin(), vectors.end()); - assert(collection.size() == 2); + TEST_ASSERT(collection.size() == 2); cols_type::const_iterator it = collection.begin(); - assert(it->type == mdds::mtv::element_type_double); - assert(it->index == 0); - assert(it->position == 0); - assert(it->get() == 2.3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->get() == 2.3); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->index == 1); - assert(it->position == 0); - assert(it->get() == "test"); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->get() == "test"); ++it; - assert(it->type == mdds::mtv::element_type_double); - assert(it->index == 0); - assert(it->position == 1); - assert(it->get() == 2.3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->get() == 2.3); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->index == 1); - assert(it->position == 1); - assert(it->get() == "test"); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->get() == "test"); - assert(++it == collection.end()); + TEST_ASSERT(++it == collection.end()); } void mtv_test_non_pointer_size1() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // Test 1 by 1 grid. @@ -134,20 +135,20 @@ vectors.emplace_back(1, int8_t('c')); cols_type collection(vectors.begin(), vectors.end()); - assert(collection.size() == 1); + TEST_ASSERT(collection.size() == 1); auto it = collection.begin(); - assert(it->type == mdds::mtv::element_type_int8); - assert(it->index == 0); - assert(it->position == 0); - assert(it->get() == 'c'); + TEST_ASSERT(it->type == mdds::mtv::element_type_int8); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->get() == 'c'); - assert(++it == collection.end()); + TEST_ASSERT(++it == collection.end()); } void mtv_test_invalid_collection() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::vector vectors; vectors.reserve(2); @@ -158,7 +159,7 @@ { // Grouping vectors of different lengths is not allowed. cols_type collection(vectors.begin(), vectors.end()); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -171,7 +172,7 @@ { // Grouping of empty vectors is not allowed. cols_type collection(vectors.begin(), vectors.end()); - assert(false); + TEST_ASSERT(false); } catch (const mdds::invalid_arg_error&) { @@ -181,7 +182,7 @@ void mtv_test_sub_element_ranges() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::deque vectors; vectors.emplace_back(0); @@ -216,80 +217,80 @@ collection.set_element_range(1, 2); cols_type::const_iterator it = collection.begin(); - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 1); - assert(it->index == 0); - assert(it->position == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 1); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 4); - assert(it->index == 1); - assert(it->position == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 4); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 7); - assert(it->index == 2); - assert(it->position == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 7); + TEST_ASSERT(it->index == 2); + TEST_ASSERT(it->position == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 2); - assert(it->index == 0); - assert(it->position == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 2); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 2); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 5); - assert(it->index == 1); - assert(it->position == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 5); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 2); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 8); - assert(it->index == 2); - assert(it->position == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 8); + TEST_ASSERT(it->index == 2); + TEST_ASSERT(it->position == 2); - assert(++it == collection.end()); + TEST_ASSERT(++it == collection.end()); // Limit the collection range. collection.set_collection_range(1, 1); it = collection.begin(); - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 4); - assert(it->index == 1); - assert(it->position == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 4); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 5); - assert(it->index == 1); - assert(it->position == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 5); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 2); - assert(++it == collection.end()); + TEST_ASSERT(++it == collection.end()); // Swap and try again. cols_type swapped; collection.swap(swapped); it = swapped.begin(); - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 4); - assert(it->index == 1); - assert(it->position == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 4); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->get() == 5); - assert(it->index == 1); - assert(it->position == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->get() == 5); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 2); - assert(++it == swapped.end()); + TEST_ASSERT(++it == swapped.end()); } void mtv_test_sub_element_ranges_invalid() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::deque vectors; vectors.emplace_back(5); @@ -301,7 +302,7 @@ { // Empty size. collection.set_element_range(0, 0); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -310,7 +311,7 @@ { // out-of-range start position. collection.set_element_range(5, 1); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -319,7 +320,7 @@ { // out-of-range end position. collection.set_element_range(0, 6); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -327,7 +328,7 @@ void mtv_test_sub_collection_ranges_invalid() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::deque vectors; vectors.emplace_back(1); @@ -341,7 +342,7 @@ { // Empty size. collection.set_collection_range(0, 0); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -350,7 +351,7 @@ { // out-of-range start position. collection.set_collection_range(5, 1); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -359,7 +360,7 @@ { // out-of-range end position. collection.set_collection_range(0, 6); - assert(!"invalid_arg_error is expected to be thrown"); + TEST_ASSERT(!"invalid_arg_error is expected to be thrown"); } catch (const mdds::invalid_arg_error&) {} @@ -367,7 +368,7 @@ void mtv_test_boolean_block() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; std::vector vectors; vectors.reserve(2); @@ -377,18 +378,18 @@ cols_type collection(vectors.begin(), vectors.end()); auto it = collection.begin(); - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->index == 0); - assert(it->position == 0); - assert(it->get() == true); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->index == 0); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->get() == true); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->index == 1); - assert(it->position == 0); - assert(it->get() == false); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->index == 1); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->get() == false); - assert(++it == collection.end()); + TEST_ASSERT(++it == collection.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/Makefile.in mdds-3.1.0/test/multi_type_vector/custom/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/custom/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom/aos/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -444,7 +444,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/custom/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom/soa/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -444,7 +444,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/Makefile.in mdds-3.1.0/test/multi_type_vector/custom/tc/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom/tc/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -182,7 +182,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/basic.inl mdds-3.1.0/test/multi_type_vector/custom/tc/basic.inl --- mdds-2.1.1/test/multi_type_vector/custom/tc/basic.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/basic.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,7 @@ void mtv_test_basic() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // mdds::multi_type_vector does not manage the life cycle of individual cells; // the client code needs to manage them when storing pointers. @@ -45,12 +45,12 @@ db.set(2, p); user_cell* p2 = db.get(0); - assert(p->value == p2->value); + TEST_ASSERT(p->value == p2->value); p = pool.construct(3.4); db.set(0, p); p2 = db.get(0); - assert(p->value == p2->value); + TEST_ASSERT(p->value == p2->value); pool.clear(); } @@ -69,11 +69,11 @@ user_cell* ptest; ptest = db.get(0); - assert(ptest && ptest->value == 1.1); + TEST_ASSERT(ptest && ptest->value == 1.1); ptest = db.get(1); - assert(ptest && ptest->value == 2.2); + TEST_ASSERT(ptest && ptest->value == 2.2); ptest = db.get(2); - assert(ptest && ptest->value == 3.3); + TEST_ASSERT(ptest && ptest->value == 3.3); db.resize(6); user_cell* p4 = pool.construct(11); @@ -86,64 +86,64 @@ db.set(3, vals.begin(), vals.end()); ptest = db.get(0); - assert(ptest && ptest->value == 1.1); + TEST_ASSERT(ptest && ptest->value == 1.1); ptest = db.get(1); - assert(ptest && ptest->value == 2.2); + TEST_ASSERT(ptest && ptest->value == 2.2); ptest = db.get(2); - assert(ptest && ptest->value == 3.3); + TEST_ASSERT(ptest && ptest->value == 3.3); ptest = db.get(3); - assert(ptest && ptest->value == 11); + TEST_ASSERT(ptest && ptest->value == 11); ptest = db.get(4); - assert(ptest && ptest->value == 22); + TEST_ASSERT(ptest && ptest->value == 22); ptest = db.get(5); - assert(ptest && ptest->value == 33); + TEST_ASSERT(ptest && ptest->value == 33); // Shrink the block to erase the bottom 3 cells. db.resize(3); - assert(db.size() == 3); + TEST_ASSERT(db.size() == 3); ptest = db.get(2); - assert(ptest && ptest->value == 3.3); + TEST_ASSERT(ptest && ptest->value == 3.3); // Re-insert the values at the front. db.insert(0, vals.begin(), vals.end()); - assert(db.size() == 6); + TEST_ASSERT(db.size() == 6); ptest = db.get(0); - assert(ptest && ptest->value == 11); + TEST_ASSERT(ptest && ptest->value == 11); ptest = db.get(1); - assert(ptest && ptest->value == 22); + TEST_ASSERT(ptest && ptest->value == 22); ptest = db.get(2); - assert(ptest && ptest->value == 33); + TEST_ASSERT(ptest && ptest->value == 33); ptest = db.get(3); - assert(ptest && ptest->value == 1.1); + TEST_ASSERT(ptest && ptest->value == 1.1); ptest = db.get(4); - assert(ptest && ptest->value == 2.2); + TEST_ASSERT(ptest && ptest->value == 2.2); ptest = db.get(5); - assert(ptest && ptest->value == 3.3); + TEST_ASSERT(ptest && ptest->value == 3.3); // set_empty(), is_empty(). db.set_empty(2, 4); - assert(db.block_size() == 3); - assert(db.get(1)->value == 22); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.get(5)->value == 3.3); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.get(1)->value == 22); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.get(5)->value == 3.3); // erase() db.erase(3, 5); - assert(db.size() == 3); - assert(db.get(1)->value == 22); - assert(db.is_empty(2)); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.get(1)->value == 22); + TEST_ASSERT(db.is_empty(2)); // insert_empty(). db.insert_empty(1, 2); - assert(db.size() == 5); - assert(db.get(0)->value == 11); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.get(3)->value == 22); - assert(db.is_empty(4)); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0)->value == 11); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.get(3)->value == 22); + TEST_ASSERT(db.is_empty(4)); pool.clear(); } @@ -171,10 +171,10 @@ vals.push_back(pool.construct(2.3)); vals.push_back(pool.construct(2.4)); db.set(1, vals.begin(), vals.end()); - assert(db.is_empty(0)); - assert(db.get(1)->value == 2.3); - assert(db.get(2)->value == 2.4); - assert(db.get(3)->value == 1.1); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.get(1)->value == 2.3); + TEST_ASSERT(db.get(2)->value == 2.4); + TEST_ASSERT(db.get(3)->value == 1.1); pool.clear(); } @@ -183,34 +183,34 @@ // Get empty value. mtv_type db(1); user_cell* p = db.get(0); - assert(p == nullptr); + TEST_ASSERT(p == nullptr); } } void mtv_test_basic_equality() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; user_cell_pool pool; mtv_type db1(3); mtv_type db2 = db1; - assert(db2 == db1); + TEST_ASSERT(db2 == db1); user_cell* p0 = pool.construct(1.1); db1.set(0, p0); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db2.set(0, p0); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.set(2, std::string("foo")); db2.set(2, std::string("foo")); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); // same value but different memory addresses. user_cell* p1 = pool.construct(1.2); user_cell* p2 = pool.construct(1.2); db1.set(1, p1); db2.set(1, p2); - assert(db1 != db2); // equality is by the pointer value. + TEST_ASSERT(db1 != db2); // equality is by the pointer value. } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/managed_block.inl mdds-3.1.0/test/multi_type_vector/custom/tc/managed_block.inl --- mdds-2.1.1/test/multi_type_vector/custom/tc/managed_block.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/managed_block.inl 2025-07-03 16:15:17.000000000 +0000 @@ -31,15 +31,15 @@ */ void mtv_test_managed_block() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { mtv_type db(1); db.set(0, new muser_cell(1.0)); const muser_cell* p = db.get(0); - assert(p->value == 1.0); + TEST_ASSERT(p->value == 1.0); db.set(0, new muser_cell(2.0)); // overwrite. p = db.get(0); - assert(p->value == 2.0); + TEST_ASSERT(p->value == 2.0); } { @@ -109,29 +109,29 @@ // swap mtv_type db2; db2.swap(db); - assert(db.empty()); - assert(db2.get(0)->value == 1.0); - assert(db2.get(1)->value == 2.0); - assert(db2.get(2)->value == 3.0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db2.get(0)->value == 1.0); + TEST_ASSERT(db2.get(1)->value == 2.0); + TEST_ASSERT(db2.get(2)->value == 3.0); db.swap(db2); - assert(db2.empty()); - assert(db.get(0)->value == 1.0); - assert(db.get(1)->value == 2.0); - assert(db.get(2)->value == 3.0); + TEST_ASSERT(db2.empty()); + TEST_ASSERT(db.get(0)->value == 1.0); + TEST_ASSERT(db.get(1)->value == 2.0); + TEST_ASSERT(db.get(2)->value == 3.0); // copy constructor mtv_type db_copied(db); - assert(db_copied.size() == 3); - assert(db_copied.get(0)->value == 1.0); - assert(db_copied.get(1)->value == 2.0); - assert(db_copied.get(2)->value == 3.0); + TEST_ASSERT(db_copied.size() == 3); + TEST_ASSERT(db_copied.get(0)->value == 1.0); + TEST_ASSERT(db_copied.get(1)->value == 2.0); + TEST_ASSERT(db_copied.get(2)->value == 3.0); // Assignment. mtv_type db_assigned = db; - assert(db_assigned.size() == 3); - assert(db_assigned.get(0)->value == 1.0); - assert(db_assigned.get(1)->value == 2.0); - assert(db_assigned.get(2)->value == 3.0); + TEST_ASSERT(db_assigned.size() == 3); + TEST_ASSERT(db_assigned.get(0)->value == 1.0); + TEST_ASSERT(db_assigned.get(1)->value == 2.0); + TEST_ASSERT(db_assigned.get(2)->value == 3.0); } { @@ -141,7 +141,7 @@ db.set(1, new muser_cell(2.0)); db.set(2, new muser_cell(3.0)); db.resize(1); - assert(db.get(0)->value == 1.0); + TEST_ASSERT(db.get(0)->value == 1.0); db.clear(); } @@ -164,7 +164,7 @@ db.set(1, new muser_cell(2.0)); db.set(2, new muser_cell(3.0)); db.erase(0, 2); - assert(db.empty()); + TEST_ASSERT(db.empty()); // Erase top. db.resize(3); @@ -172,21 +172,21 @@ db.set(1, new muser_cell(2.0)); db.set(2, new muser_cell(3.0)); db.erase(0, 1); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); // Erase bottom. db.resize(3); db.set(1, new muser_cell(4.0)); db.set(2, new muser_cell(5.0)); db.erase(1, 2); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); // Erase middle. db.resize(3); db.set(1, new muser_cell(4.0)); db.set(2, new muser_cell(5.0)); db.erase(1, 1); - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); } { @@ -199,7 +199,7 @@ db.set(2, new muser_cell(2.0)); db.set(3, new muser_cell(3.0)); db.erase(1, 3); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); // Erase top. db.resize(4); @@ -207,21 +207,21 @@ db.set(2, new muser_cell(2.0)); db.set(3, new muser_cell(3.0)); db.erase(1, 2); - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); // Erase bottom. db.resize(4); db.set(2, new muser_cell(4.0)); db.set(3, new muser_cell(5.0)); db.erase(2, 3); - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); // Erase middle. db.resize(4); db.set(2, new muser_cell(4.0)); db.set(3, new muser_cell(5.0)); db.erase(2, 2); - assert(db.size() == 3); + TEST_ASSERT(db.size() == 3); } { @@ -267,9 +267,9 @@ db.set(0, new muser_cell(1.0)); db.set(1, new muser_cell(2.0)); db.insert_empty(1, 2); - assert(db.size() == 4); - assert(db.get(0)->value == 1.0); - assert(db.get(3)->value == 2.0); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.get(0)->value == 1.0); + TEST_ASSERT(db.get(3)->value == 2.0); } { @@ -282,8 +282,8 @@ vals.push_back(new muser_cell(3.0)); vals.push_back(new muser_cell(4.0)); db.set(0, vals.begin(), vals.end()); - assert(db.get(0)->value == 3.0); - assert(db.get(1)->value == 4.0); + TEST_ASSERT(db.get(0)->value == 3.0); + TEST_ASSERT(db.get(1)->value == 4.0); } { @@ -294,8 +294,8 @@ double vals[] = {3.0}; const double* p = &vals[0]; db.set(0, p, p + 1); - assert(db.get(0) == 3.0); - assert(db.get(1)->value == 2.0); + TEST_ASSERT(db.get(0) == 3.0); + TEST_ASSERT(db.get(1)->value == 2.0); } { @@ -306,8 +306,8 @@ double vals[] = {3.0}; const double* p = &vals[0]; db.set(1, p, p + 1); - assert(db.get(0)->value == 1.0); - assert(db.get(1) == 3.0); + TEST_ASSERT(db.get(0)->value == 1.0); + TEST_ASSERT(db.get(1) == 3.0); } { @@ -320,9 +320,9 @@ double vals[] = {4.0}; const double* p = &vals[0]; db.set(2, p, p + 1); - assert(db.get(1)->value == 1.0); - assert(db.get(2) == 4.0); - assert(db.get(3)->value == 3.0); + TEST_ASSERT(db.get(1)->value == 1.0); + TEST_ASSERT(db.get(2) == 4.0); + TEST_ASSERT(db.get(3)->value == 3.0); } { // insert_empty() to split the block into two. @@ -331,9 +331,9 @@ db.set(1, new muser_cell(1.0)); db.set(2, new muser_cell(2.0)); db.insert_empty(2, 2); - assert(db.size() == 5); - assert(db.get(1)->value == 1.0); - assert(db.get(4)->value == 2.0); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(1)->value == 1.0); + TEST_ASSERT(db.get(4)->value == 2.0); } { @@ -343,15 +343,15 @@ db.set(1, new muser_cell(1.0)); db.set(2, static_cast(2)); db.set(3, new muser_cell(3.0)); - assert(db.block_size() == 4); - assert(db.size() == 4); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.size() == 4); db.erase(2, 2); - assert(db.block_size() == 2); - assert(db.size() == 3); - assert(db.get(0) == 1.1); - assert(db.get(1)->value == 1.0); - assert(db.get(2)->value == 3.0); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1)->value == 1.0); + TEST_ASSERT(db.get(2)->value == 3.0); } { @@ -376,14 +376,14 @@ db.set(3, 1.2); db.set(4, new muser_cell(3.0)); db.set(5, new muser_cell(4.0)); - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); std::vector vals; vals.push_back(new muser_cell(5.0)); vals.push_back(new muser_cell(6.0)); vals.push_back(new muser_cell(7.0)); db.set(2, vals.begin(), vals.end()); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); } { @@ -395,22 +395,22 @@ db.set(3, 1.2); db.set(4, new muser_cell(3.0)); db.set(5, new muser_cell(4.0)); - assert(db.block_size() == 4); - assert(db.get(0) == 12); - assert(db.get(1)->value == 1.0); - assert(db.get(2)->value == 2.0); - assert(db.get(3) == 1.2); - assert(db.get(4)->value == 3.0); - assert(db.get(5)->value == 4.0); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.get(0) == 12); + TEST_ASSERT(db.get(1)->value == 1.0); + TEST_ASSERT(db.get(2)->value == 2.0); + TEST_ASSERT(db.get(3) == 1.2); + TEST_ASSERT(db.get(4)->value == 3.0); + TEST_ASSERT(db.get(5)->value == 4.0); db.set(3, new muser_cell(5.0)); // merge blocks. - assert(db.block_size() == 2); - assert(db.get(0) == 12); - assert(db.get(1)->value == 1.0); - assert(db.get(2)->value == 2.0); - assert(db.get(3)->value == 5.0); - assert(db.get(4)->value == 3.0); - assert(db.get(5)->value == 4.0); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == 12); + TEST_ASSERT(db.get(1)->value == 1.0); + TEST_ASSERT(db.get(2)->value == 2.0); + TEST_ASSERT(db.get(3)->value == 5.0); + TEST_ASSERT(db.get(4)->value == 3.0); + TEST_ASSERT(db.get(5)->value == 4.0); } { @@ -421,10 +421,10 @@ db.set(2, new muser_cell(3.1)); db.set(0, new muser_cell(4.2)); // merge - assert(db.block_size() == 1); - assert(db.get(0)->value == 4.2); - assert(db.get(1)->value == 2.1); - assert(db.get(2)->value == 3.1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0)->value == 4.2); + TEST_ASSERT(db.get(1)->value == 2.1); + TEST_ASSERT(db.get(2)->value == 3.1); } { @@ -446,21 +446,21 @@ db.set(3, 1.2); db.set(4, new muser_cell(2.2)); db.set(5, new muser_cell(2.3)); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); std::vector vals; vals.push_back(new muser_cell(2.4)); vals.push_back(new muser_cell(2.5)); vals.push_back(new muser_cell(2.6)); db.set(1, vals.begin(), vals.end()); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); - assert(db.get(0) == "foo"); - assert(db.get(1)->value == 2.4); - assert(db.get(2)->value == 2.5); - assert(db.get(3)->value == 2.6); - assert(db.get(4)->value == 2.2); - assert(db.get(5)->value == 2.3); + TEST_ASSERT(db.get(0) == "foo"); + TEST_ASSERT(db.get(1)->value == 2.4); + TEST_ASSERT(db.get(2)->value == 2.5); + TEST_ASSERT(db.get(3)->value == 2.6); + TEST_ASSERT(db.get(4)->value == 2.2); + TEST_ASSERT(db.get(5)->value == 2.3); } { @@ -478,14 +478,14 @@ vals.push_back(new muser_cell(2.5)); vals.push_back(new muser_cell(2.6)); db.set(1, vals.begin(), vals.end()); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); - assert(db.get(0) == "foo"); - assert(db.get(1)->value == 2.4); - assert(db.get(2)->value == 2.5); - assert(db.get(3)->value == 2.6); - assert(db.get(4)->value == 2.2); - assert(db.get(5)->value == 2.3); + TEST_ASSERT(db.get(0) == "foo"); + TEST_ASSERT(db.get(1)->value == 2.4); + TEST_ASSERT(db.get(2)->value == 2.5); + TEST_ASSERT(db.get(3)->value == 2.6); + TEST_ASSERT(db.get(4)->value == 2.2); + TEST_ASSERT(db.get(5)->value == 2.3); } { @@ -493,7 +493,7 @@ db.set(0, new muser_cell(1.0)); db.set(2, new muser_cell(1.0)); db.set(1, new muser_cell(1.0)); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); } { @@ -503,24 +503,24 @@ std::vector doubles(3, 2.2); db.set(3, doubles.begin(), doubles.end()); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); std::vector cells; cells.push_back(new muser_cell(2.1)); cells.push_back(new muser_cell(2.2)); cells.push_back(new muser_cell(2.3)); db.set(3, cells.begin(), cells.end()); - assert(db.block_size() == 1); - assert(db.get(0)->value == 1.1); - assert(db.get(1)->value == 1.1); - assert(db.get(2)->value == 1.1); - assert(db.get(3)->value == 2.1); - assert(db.get(4)->value == 2.2); - assert(db.get(5)->value == 2.3); - assert(db.get(6)->value == 1.1); - assert(db.get(7)->value == 1.1); - assert(db.get(8)->value == 1.1); - assert(db.get(9)->value == 1.1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0)->value == 1.1); + TEST_ASSERT(db.get(1)->value == 1.1); + TEST_ASSERT(db.get(2)->value == 1.1); + TEST_ASSERT(db.get(3)->value == 2.1); + TEST_ASSERT(db.get(4)->value == 2.2); + TEST_ASSERT(db.get(5)->value == 2.3); + TEST_ASSERT(db.get(6)->value == 1.1); + TEST_ASSERT(db.get(7)->value == 1.1); + TEST_ASSERT(db.get(8)->value == 1.1); + TEST_ASSERT(db.get(9)->value == 1.1); } { @@ -529,18 +529,18 @@ db.set(1, new muser_cell(2.0)); db.set(2, new muser_cell(3.0)); db.set_empty(1, 1); - assert(db.block_size() == 3); - assert(db.get(0)->value == 1.0); - assert(db.is_empty(1)); - assert(db.get(2)->value == 3.0); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.get(0)->value == 1.0); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.get(2)->value == 3.0); } { mtv_type db(3); db.set(1, new muser_cell(3.3)); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); db.set_empty(1, 1); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); } { @@ -549,18 +549,18 @@ muser_cell* p1 = new muser_cell(4.5); db.set(0, p1); muser_cell* p2 = db.release(0); - assert(p1 == p2); - assert(p2->value == 4.5); - assert(db.is_empty(0)); + TEST_ASSERT(p1 == p2); + TEST_ASSERT(p2->value == 4.5); + TEST_ASSERT(db.is_empty(0)); delete p2; db = mtv_type(2); db.set(0, new muser_cell(23.3)); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); p2 = db.release(0); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.block_size() == 1); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.block_size() == 1); delete p2; db = mtv_type(2); @@ -568,16 +568,16 @@ db.set(1, new muser_cell(1.3)); p2 = db.release(0); - assert(db.is_empty(0)); - assert(!db.is_empty(1)); - assert(p2->value == 1.2); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(!db.is_empty(1)); + TEST_ASSERT(p2->value == 1.2); delete p2; db.set(0, new muser_cell(1.4)); p2 = db.release(1); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(p2->value == 1.3); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(p2->value == 1.3); delete p2; db = mtv_type(3); @@ -586,10 +586,10 @@ db.set(2, new muser_cell(2.3)); p2 = db.release(1); - assert(p2->value == 2.2); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); + TEST_ASSERT(p2->value == 2.2); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); delete p2; @@ -606,17 +606,17 @@ db.set(3, new muser_cell(5.1)); mtv_type::iterator pos = db.release(0, p1); - assert(pos == db.begin()); + TEST_ASSERT(pos == db.begin()); pos = db.release(pos, 3, p2); ++pos; - assert(pos == db.end()); - assert(p1->value == 4.5); - assert(p2->value == 5.1); - assert(db.block_size() == 3); - assert(db.is_empty(0)); - assert(db.get(1)->value == 4.6); - assert(db.is_empty(2)); - assert(db.is_empty(3)); + TEST_ASSERT(pos == db.end()); + TEST_ASSERT(p1->value == 4.5); + TEST_ASSERT(p2->value == 5.1); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.get(1)->value == 4.6); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); delete p1; delete p2; } diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/misc.inl mdds-3.1.0/test/multi_type_vector/custom/tc/misc.inl --- mdds-2.1.1/test/multi_type_vector/custom/tc/misc.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/misc.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,64 +28,67 @@ void mtv_test_misc_types() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mdds::mtv::element_t ct; // Basic types ct = mtv_type::get_element_type(double(12.3)); - assert(ct == mdds::mtv::element_type_double); + TEST_ASSERT(ct == mdds::mtv::element_type_double); ct = mtv_type::get_element_type(std::string()); - assert(ct == mdds::mtv::element_type_string); + TEST_ASSERT(ct == mdds::mtv::element_type_string); ct = mtv_type::get_element_type(static_cast(12)); - assert(ct == mdds::mtv::element_type_uint64); + TEST_ASSERT(ct == mdds::mtv::element_type_uint64); ct = mtv_type::get_element_type(true); - assert(ct == mdds::mtv::element_type_boolean); + TEST_ASSERT(ct == mdds::mtv::element_type_boolean); ct = mtv_type::get_element_type(false); - assert(ct == mdds::mtv::element_type_boolean); + TEST_ASSERT(ct == mdds::mtv::element_type_boolean); // Custom cell type user_cell* p = nullptr; ct = mtv_type::get_element_type(p); - assert(ct == element_type_user_block && ct >= mdds::mtv::element_type_user_start); + TEST_ASSERT(ct == element_type_user_block && ct >= mdds::mtv::element_type_user_start); ct = mtv_type::get_element_type(static_cast(nullptr)); - assert(ct == element_type_muser_block && ct >= mdds::mtv::element_type_user_start); + TEST_ASSERT(ct == element_type_muser_block && ct >= mdds::mtv::element_type_user_start); ct = mtv_fruit_type::get_element_type(unknown_fruit); - assert(ct == element_type_fruit_block && ct >= mdds::mtv::element_type_user_start); + TEST_ASSERT(ct == element_type_fruit_block && ct >= mdds::mtv::element_type_user_start); } void mtv_test_misc_block_identifier() { - stack_printer __stack_printer__(__FUNCTION__); - assert(user_cell_block::block_type == element_type_user_block); - assert(muser_cell_block::block_type == element_type_muser_block); - assert(fruit_block::block_type == element_type_fruit_block); - assert(date_block::block_type == element_type_date_block); + MDDS_TEST_FUNC_SCOPE; + + TEST_ASSERT(user_cell_block::block_type == element_type_user_block); + TEST_ASSERT(muser_cell_block::block_type == element_type_muser_block); + TEST_ASSERT(fruit_block::block_type == element_type_fruit_block); + TEST_ASSERT(date_block::block_type == element_type_date_block); } void mtv_test_misc_custom_block_func1() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_fruit_type db(10); db.set(0, apple); db.set(1, orange); db.set(2, mango); db.set(3, peach); - assert(db.block_size() == 2); - assert(db.get_type(0) == element_type_fruit_block); - assert(db.get(0) == apple); - assert(db.get(1) == orange); - assert(db.get(2) == mango); - assert(db.get(3) == peach); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get_type(0) == element_type_fruit_block); + TEST_ASSERT(db.get(0) == apple); + TEST_ASSERT(db.get(1) == orange); + TEST_ASSERT(db.get(2) == mango); + TEST_ASSERT(db.get(3) == peach); db.set(1, 234); - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); db.set(1, apple); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); } void mtv_test_misc_custom_block_func3() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv3_type db(10); // Insert custom elements. @@ -93,28 +96,29 @@ db.set(1, apple); db.set(2, date(1989, 12, 13)); db.set(3, date(2011, 8, 7)); - assert(db.get_type(0) == element_type_muser_block); - assert(db.get_type(1) == element_type_fruit_block); - assert(db.get_type(2) == element_type_date_block); - assert(db.get_type(3) == element_type_date_block); - assert(db.get(0)->value == 12.3); - assert(db.get(1) == apple); - assert(db.get(2).year == 1989); - assert(db.get(2).month == 12); - assert(db.get(2).day == 13); - assert(db.get(3).year == 2011); - assert(db.get(3).month == 8); - assert(db.get(3).day == 7); - assert(db.block_size() == 4); + TEST_ASSERT(db.get_type(0) == element_type_muser_block); + TEST_ASSERT(db.get_type(1) == element_type_fruit_block); + TEST_ASSERT(db.get_type(2) == element_type_date_block); + TEST_ASSERT(db.get_type(3) == element_type_date_block); + TEST_ASSERT(db.get(0)->value == 12.3); + TEST_ASSERT(db.get(1) == apple); + TEST_ASSERT(db.get(2).year == 1989); + TEST_ASSERT(db.get(2).month == 12); + TEST_ASSERT(db.get(2).day == 13); + TEST_ASSERT(db.get(3).year == 2011); + TEST_ASSERT(db.get(3).month == 8); + TEST_ASSERT(db.get(3).day == 7); + TEST_ASSERT(db.block_size() == 4); // We should still support the primitive types. db.set(8, 34.56); - assert(db.get(8) == 34.56); + TEST_ASSERT(db.get(8) == 34.56); } void mtv_test_misc_release() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(3); muser_cell c1(1.2), c2(1.3); // allocated on the stack. db.set(0, &c1); @@ -122,52 +126,52 @@ 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()); + TEST_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); + TEST_ASSERT(db.size() == 4); + TEST_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 == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); mtv_type::iterator check = it; --check; - assert(check == db.begin()); + TEST_ASSERT(check == db.begin()); check = it; ++check; ++check; - assert(check == db.end()); + TEST_ASSERT(check == db.end()); db.push_back(new muser_cell(10.2)); - assert(db.size() == 5); + TEST_ASSERT(db.size() == 5); muser_cell* p1 = db.get(3); muser_cell* p2 = db.get(4); - assert(p1->value == 10.1); - assert(p2->value == 10.2); + TEST_ASSERT(p1->value == 10.1); + TEST_ASSERT(p2->value == 10.2); // Pass iterator as a position hint. it = db.release_range(it, 3, 4); - assert(db.block_size() == 2); + TEST_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 == mdds::mtv::element_type_empty); - assert(it->size == 4); + TEST_ASSERT(check == db.begin()); + TEST_ASSERT(check->type == element_type_muser_block); + TEST_ASSERT(check->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // It should be safe to delete these instances now that they've been released. delete p1; @@ -176,7 +180,7 @@ void mtv_test_misc_construction_with_array() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { std::vector vals; vals.push_back(new muser_cell(2.1)); @@ -185,11 +189,11 @@ mtv_type db(vals.size(), vals.begin(), vals.end()); db.set(1, 10.2); // overwrite. - assert(db.size() == 3); - assert(db.block_size() == 3); - assert(db.get(0)->value == 2.1); - assert(db.get(1) == 10.2); - assert(db.get(2)->value == 2.3); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.get(0)->value == 2.1); + TEST_ASSERT(db.get(1) == 10.2); + TEST_ASSERT(db.get(2)->value == 2.3); // Now those heap objects are owned by the container. Clearing the // array shouldn't leak. diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/swap.inl mdds-3.1.0/test/multi_type_vector/custom/tc/swap.inl --- mdds-2.1.1/test/multi_type_vector/custom/tc/swap.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/swap.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_swap() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv3_type db1(5), db2(2); db1.set(0, new muser_cell(1.1)); db1.set(1, new muser_cell(1.2)); @@ -58,26 +59,26 @@ 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(3)->value == 3.1); - assert(db1.get(4)->value == 3.2); - assert(db1.get(5)->value == 3.3); - assert(db2.get(3) == 2.1); - assert(db2.get(4) == 2.2); - assert(db2.get(5) == 2.3); + TEST_ASSERT(db1.size() == 10); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db2.size() == 10); + TEST_ASSERT(db2.block_size() == 3); + + TEST_ASSERT(db1.get(3)->value == 3.1); + TEST_ASSERT(db1.get(4)->value == 3.2); + TEST_ASSERT(db1.get(5)->value == 3.3); + TEST_ASSERT(db2.get(3) == 2.1); + TEST_ASSERT(db2.get(4) == 2.2); + TEST_ASSERT(db2.get(5) == 2.3); db2.swap(3, 5, db1, 3); - assert(db1.get(3) == 2.1); - assert(db1.get(4) == 2.2); - assert(db1.get(5) == 2.3); - assert(db2.get(3)->value == 3.1); - assert(db2.get(4)->value == 3.2); - assert(db2.get(5)->value == 3.3); + TEST_ASSERT(db1.get(3) == 2.1); + TEST_ASSERT(db1.get(4) == 2.2); + TEST_ASSERT(db1.get(5) == 2.3); + TEST_ASSERT(db2.get(3)->value == 3.1); + TEST_ASSERT(db2.get(4)->value == 3.2); + TEST_ASSERT(db2.get(5)->value == 3.3); // Same as above, except that the source segment splits the block into 2. @@ -110,23 +111,23 @@ db2.set(4, 6.2); db2.set(5, 6.3); - assert(db1.get(2)->value == 4.1); - assert(db1.get(3) == 4.2); - assert(db1.get(4)->value == 4.3); - - assert(db2.get(3)->value == 6.1); - assert(db2.get(4) == 6.2); - assert(db2.get(5) == 6.3); + TEST_ASSERT(db1.get(2)->value == 4.1); + TEST_ASSERT(db1.get(3) == 4.2); + TEST_ASSERT(db1.get(4)->value == 4.3); + + TEST_ASSERT(db2.get(3)->value == 6.1); + TEST_ASSERT(db2.get(4) == 6.2); + TEST_ASSERT(db2.get(5) == 6.3); db2.swap(4, 4, db1, 4); - assert(db1.get(2)->value == 4.1); - assert(db1.get(3) == 4.2); - assert(db1.get(4) == 6.2); - - assert(db2.get(3)->value == 6.1); - assert(db2.get(4)->value == 4.3); - assert(db2.get(5) == 6.3); + TEST_ASSERT(db1.get(2)->value == 4.1); + TEST_ASSERT(db1.get(3) == 4.2); + TEST_ASSERT(db1.get(4) == 6.2); + + TEST_ASSERT(db2.get(3)->value == 6.1); + TEST_ASSERT(db2.get(4)->value == 4.3); + TEST_ASSERT(db2.get(5) == 6.3); // One more on double deletion... @@ -146,19 +147,20 @@ db1.swap(2, 2, db2, 3); - assert(db1.get(0) == 2.1); - assert(db1.get(1) == 2.2); - assert(db1.get(2)->value == 3.2); - assert(db1.get(3)->value == 4.5); - - assert(db2.get(2)->value == 3.1); - assert(db2.get(3) == 2.3); - assert(db2.get(4)->value == 3.3); + TEST_ASSERT(db1.get(0) == 2.1); + TEST_ASSERT(db1.get(1) == 2.2); + TEST_ASSERT(db1.get(2)->value == 3.2); + TEST_ASSERT(db1.get(3)->value == 4.5); + + TEST_ASSERT(db2.get(2)->value == 3.1); + TEST_ASSERT(db2.get(3) == 2.3); + TEST_ASSERT(db2.get(4)->value == 3.3); } void mtv_test_swap_2() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv3_type db1(3), db2(3); db1.set(0, new muser_cell(1.1)); @@ -169,16 +171,16 @@ // Repeat the same swap twice. db1.swap(0, 1, db2, 0); - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 1.2); - assert(db1.get(0) == 1.2); - assert(db1.get(1) == "foo"); + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 1.2); + TEST_ASSERT(db1.get(0) == 1.2); + TEST_ASSERT(db1.get(1) == "foo"); db1.swap(0, 1, db2, 0); - assert(db1.get(0)->value == 1.1); - assert(db1.get(1)->value == 1.2); - assert(db2.get(0) == 1.2); - assert(db2.get(1) == "foo"); + TEST_ASSERT(db1.get(0)->value == 1.1); + TEST_ASSERT(db1.get(1)->value == 1.2); + TEST_ASSERT(db2.get(0) == 1.2); + TEST_ASSERT(db2.get(1) == "foo"); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/custom/tc/transfer.inl mdds-3.1.0/test/multi_type_vector/custom/tc/transfer.inl --- mdds-2.1.1/test/multi_type_vector/custom/tc/transfer.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom/tc/transfer.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,17 +28,18 @@ void mtv_test_transfer() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db1(3), db2(4); // db2 is larger than db1. db1.set(0, new muser_cell(1.1)); db1.set(1, new muser_cell(1.2)); db1.set(2, new muser_cell(1.3)); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); try { db1.transfer(0, 1, db1, 0); - assert(!"Exception should have been thrown"); + TEST_ASSERT(!"Exception should have been thrown"); } catch (const mdds::invalid_arg_error&) { @@ -49,91 +50,91 @@ db1.transfer(0, 2, db2, 0); // Now db1 should be totally empty. - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); mtv_type::iterator check = db1.begin(); - assert(check != db1.end()); - assert(check->type == mdds::mtv::element_type_empty); - assert(check->size == 3); - - assert(db2.block_size() == 2); - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 1.2); - assert(db2.get(2)->value == 1.3); - assert(db2.is_empty(3)); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check->size == 3); + + TEST_ASSERT(db2.block_size() == 2); + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 1.2); + TEST_ASSERT(db2.get(2)->value == 1.3); + TEST_ASSERT(db2.is_empty(3)); // Transfer back to db1. This should make db2 to be totally empty again. db2.transfer(0, 2, db1, 0); - assert(db2.block_size() == 1); + TEST_ASSERT(db2.block_size() == 1); check = db2.begin(); - assert(check != db2.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); - - assert(db1.block_size() == 1); - assert(db1.get(0)->value == 1.1); - assert(db1.get(1)->value == 1.2); - assert(db1.get(2)->value == 1.3); + TEST_ASSERT(check != db2.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + + TEST_ASSERT(db1.block_size() == 1); + TEST_ASSERT(db1.get(0)->value == 1.1); + TEST_ASSERT(db1.get(1)->value == 1.2); + TEST_ASSERT(db1.get(2)->value == 1.3); // Now, transfer only the top 2 elements. db1.transfer(0, 1, db2, 0); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.get(2)->value == 1.3); - - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 1.2); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.get(2)->value == 1.3); + + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 1.2); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); // .. and back. db2.transfer(0, 1, db1, 0); - assert(db1.block_size() == 1); - assert(db1.get(0)->value == 1.1); - assert(db1.get(1)->value == 1.2); - assert(db1.get(2)->value == 1.3); + TEST_ASSERT(db1.block_size() == 1); + TEST_ASSERT(db1.get(0)->value == 1.1); + TEST_ASSERT(db1.get(1)->value == 1.2); + TEST_ASSERT(db1.get(2)->value == 1.3); - assert(db2.block_size() == 1); + TEST_ASSERT(db2.block_size() == 1); check = db2.begin(); - assert(check != db2.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check != db2.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); db1 = mtv_type(4); db2 = mtv_type(4); db2.set(1, new muser_cell(2.1)); db2.set(2, new muser_cell(2.2)); - assert(db2.block_size() == 3); + TEST_ASSERT(db2.block_size() == 3); db1.transfer(0, 1, db2, 1); // This causes db2's 3 blocks to merge into one. - assert(db2.block_size() == 1); + TEST_ASSERT(db2.block_size() == 1); check = db2.begin(); - assert(check != db2.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); - assert(db1.block_size() == 1); + TEST_ASSERT(check != db2.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); db2.set(0, new muser_cell(3.1)); - assert(db2.block_size() == 2); + TEST_ASSERT(db2.block_size() == 2); db1.set(1, new muser_cell(3.2)); db1.set(2, new muser_cell(3.3)); db1.set(3, new muser_cell(3.4)); - assert(db1.block_size() == 2); + TEST_ASSERT(db1.block_size() == 2); db1.transfer(1, 2, db2, 1); - assert(db1.block_size() == 2); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.get(3)->value == 3.4); - assert(db2.block_size() == 2); - assert(db2.get(0)->value == 3.1); - assert(db2.get(1)->value == 3.2); - assert(db2.get(2)->value == 3.3); - assert(db2.is_empty(3)); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.get(3)->value == 3.4); + TEST_ASSERT(db2.block_size() == 2); + TEST_ASSERT(db2.get(0)->value == 3.1); + TEST_ASSERT(db2.get(1)->value == 3.2); + TEST_ASSERT(db2.get(2)->value == 3.3); + TEST_ASSERT(db2.is_empty(3)); db1 = mtv_type(3); db2 = mtv_type(3); @@ -142,44 +143,44 @@ db2.set(2, new muser_cell(4.3)); db1.transfer(1, 1, db2, 1); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 3); - assert(check->type == mdds::mtv::element_type_empty); - assert(db2.block_size() == 1); - assert(db2.get(0)->value == 4.1); - assert(db2.get(1)->value == 4.2); - assert(db2.get(2)->value == 4.3); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 3); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db2.block_size() == 1); + TEST_ASSERT(db2.get(0)->value == 4.1); + TEST_ASSERT(db2.get(1)->value == 4.2); + TEST_ASSERT(db2.get(2)->value == 4.3); // Transfer to middle of block. db1 = mtv_type(3); db2 = mtv_type(3); db1.set(0, new muser_cell(5.2)); - assert(db1.block_size() == 2); + TEST_ASSERT(db1.block_size() == 2); db1.transfer(0, 0, db2, 1); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 3); - assert(check->type == mdds::mtv::element_type_empty); - assert(db2.block_size() == 3); - assert(db2.is_empty(0)); - assert(db2.get(1)->value == 5.2); - assert(db2.is_empty(2)); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 3); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db2.block_size() == 3); + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1)->value == 5.2); + TEST_ASSERT(db2.is_empty(2)); db1 = mtv_type(2); db2 = mtv_type(3); db1.set(0, new muser_cell(11.1)); db1.set(1, new muser_cell(11.2)); db1.transfer(1, 1, db2, 1); - assert(db1.block_size() == 2); - assert(db1.get(0)->value == 11.1); - assert(db1.is_empty(1)); - assert(db2.block_size() == 3); - assert(db2.is_empty(0)); - assert(db2.get(1)->value == 11.2); - assert(db2.is_empty(2)); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db1.get(0)->value == 11.1); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db2.block_size() == 3); + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1)->value == 11.2); + TEST_ASSERT(db2.is_empty(2)); // Transfer to bottom of block. db1 = mtv_type(4); @@ -187,17 +188,17 @@ db1.set(0, new muser_cell(6.1)); db1.set(1, new muser_cell(6.2)); db1.transfer(0, 1, db2, 3); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); - assert(db2.block_size() == 2); - assert(db2.is_empty(0)); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.get(3)->value == 6.1); - assert(db2.get(4)->value == 6.2); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db2.block_size() == 2); + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.get(3)->value == 6.1); + TEST_ASSERT(db2.get(4)->value == 6.2); // Transfer multiple blocks. Very simple use case. db1 = mtv_type(4); @@ -207,16 +208,16 @@ db1.transfer(1, 3, db2, 0); // db1 should be completely empty. - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 4); - assert(check->type == mdds::mtv::element_type_empty); - - assert(db2.block_size() == 3); - assert(db2.get(0)->value == 10.1); - assert(db2.is_empty(1)); - assert(db2.get(2)->value == 10.2); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 4); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + + TEST_ASSERT(db2.block_size() == 3); + TEST_ASSERT(db2.get(0)->value == 10.1); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.get(2)->value == 10.2); // Multiple-block transfer that involves merging. db1 = mtv_type(5); @@ -230,43 +231,43 @@ db2.set(4, new muser_cell(1.2)); mtv_type::iterator it = db1.transfer(1, 3, db2, 1); - assert(db1.block_size() == 3); - assert(db1.get(0)->value == 0.1); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.get(4)->value == 0.4); - - assert(db2.block_size() == 3); - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 0.2); - assert(db2.is_empty(2)); - assert(db2.get(3)->value == 0.3); - assert(db2.get(4)->value == 1.2); - - assert(it != db1.end()); - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db1.get(0)->value == 0.1); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.get(4)->value == 0.4); + + TEST_ASSERT(db2.block_size() == 3); + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 0.2); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.get(3)->value == 0.3); + TEST_ASSERT(db2.get(4)->value == 1.2); + + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); it = db1.transfer(it, 4, 4, db2, 2); // Transfer single element at 4. - assert(db1.block_size() == 2); - assert(db1.get(0)->value == 0.1); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.block_size() == 1); - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 0.2); - assert(db2.get(2)->value == 0.4); - assert(db2.get(3)->value == 0.3); - assert(db2.get(4)->value == 1.2); - - assert(it != db1.end()); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db1.get(0)->value == 0.1); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.block_size() == 1); + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 0.2); + TEST_ASSERT(db2.get(2)->value == 0.4); + TEST_ASSERT(db2.get(3)->value == 0.3); + TEST_ASSERT(db2.get(4)->value == 1.2); + + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db1.end()); + TEST_ASSERT(it == db1.end()); // Multi-block transfer to the top part of destination block. db1 = mtv_type(5); @@ -280,24 +281,24 @@ db2.set(2, false); db2.set(3, true); it = db1.transfer(2, 3, db2, 2); - assert(it != db1.end()); - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); std::advance(it, 2); - assert(it == db1.end()); - assert(db1.block_size() == 3); - assert(db1.get(0)->value == -1.1); - assert(db1.get(1)->value == -2.1); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.get(4)->value == -5.1); - - assert(db2.block_size() == 5); - assert(db2.is_empty(0)); - assert(db2.get(1) == true); - assert(db2.get(2)->value == -3.1); - assert(db2.get(3) == "foo"); - assert(db2.is_empty(4)); + TEST_ASSERT(it == db1.end()); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db1.get(0)->value == -1.1); + TEST_ASSERT(db1.get(1)->value == -2.1); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.get(4)->value == -5.1); + + TEST_ASSERT(db2.block_size() == 5); + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1) == true); + TEST_ASSERT(db2.get(2)->value == -3.1); + TEST_ASSERT(db2.get(3) == "foo"); + TEST_ASSERT(db2.is_empty(4)); // Multi-block transfer to the bottom part of destination block. db1 = mtv_type(10); @@ -310,33 +311,33 @@ db2.set(1, false); it = db1.transfer(0, 2, db2, 7); - assert(it != db1.end()); - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it != db1.end()); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_int8); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int8); ++it; - assert(it != db1.end()); - assert(it->size == 6); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db1.end()); - assert(db1.block_size() == 3); - assert(db1.get(3) == 'b'); - - assert(db2.block_size() == 4); - assert(db2.get(0) == true); - assert(db2.get(1) == false); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); - assert(db2.is_empty(6)); - assert(db2.get(7)->value == 2.1); - assert(db2.get(8)->value == 2.2); - assert(db2.get(9) == 'a'); + TEST_ASSERT(it == db1.end()); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db1.get(3) == 'b'); + + TEST_ASSERT(db2.block_size() == 4); + TEST_ASSERT(db2.get(0) == true); + TEST_ASSERT(db2.get(1) == false); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); + TEST_ASSERT(db2.is_empty(6)); + TEST_ASSERT(db2.get(7)->value == 2.1); + TEST_ASSERT(db2.get(8)->value == 2.2); + TEST_ASSERT(db2.get(9) == 'a'); // Multi-block transfer to the middle part of destination block. db1 = mtv_type(10); @@ -350,63 +351,63 @@ db1.set(7, new muser_cell(2.7)); db1.set(8, true); it = db1.transfer(3, 6, db2, 2); - assert(it != db1.end()); - assert(it->size == 7); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 7); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it != db1.end()); - assert(it->size == 1); - assert(it->type == element_type_muser_block); + TEST_ASSERT(it != db1.end()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == element_type_muser_block); ++it; - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db1.end()); + TEST_ASSERT(it == db1.end()); - assert(db1.block_size() == 4); - assert(db1.is_empty(6)); - assert(db1.get(7)->value == 2.7); - assert(db1.get(8) == true); - assert(db1.is_empty(9)); - - assert(db2.block_size() == 7); - assert(db2.get(0) == true); - assert(db2.is_empty(1)); - assert(db2.get(2)->value == 2.4); - assert(db2.get(3)->value == 2.5); - assert(db2.get(4) == "abc"); - assert(db2.get(5)->value == 2.6); - assert(db2.is_empty(6)); - assert(db2.is_empty(7)); - assert(db2.is_empty(8)); - assert(db2.get(9) == true); + TEST_ASSERT(db1.block_size() == 4); + TEST_ASSERT(db1.is_empty(6)); + TEST_ASSERT(db1.get(7)->value == 2.7); + TEST_ASSERT(db1.get(8) == true); + TEST_ASSERT(db1.is_empty(9)); + + TEST_ASSERT(db2.block_size() == 7); + TEST_ASSERT(db2.get(0) == true); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.get(2)->value == 2.4); + TEST_ASSERT(db2.get(3)->value == 2.5); + TEST_ASSERT(db2.get(4) == "abc"); + TEST_ASSERT(db2.get(5)->value == 2.6); + TEST_ASSERT(db2.is_empty(6)); + TEST_ASSERT(db2.is_empty(7)); + TEST_ASSERT(db2.is_empty(8)); + TEST_ASSERT(db2.get(9) == true); db1 = mtv_type(10); db2 = mtv_type(10); db1.set(3, true); db2.set(3, std::string("test")); db1.transfer(0, 6, db2, 0); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); check = db1.begin(); - assert(check != db1.end()); - assert(check->size == 10); - assert(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check != db1.end()); + TEST_ASSERT(check->size == 10); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); ++check; - assert(check == db1.end()); - assert(db2.block_size() == 3); - assert(db2.is_empty(0)); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.get(3) == true); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); - assert(db2.is_empty(6)); - assert(db2.is_empty(7)); - assert(db2.is_empty(8)); - assert(db2.is_empty(9)); + TEST_ASSERT(check == db1.end()); + TEST_ASSERT(db2.block_size() == 3); + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.get(3) == true); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); + TEST_ASSERT(db2.is_empty(6)); + TEST_ASSERT(db2.is_empty(7)); + TEST_ASSERT(db2.is_empty(8)); + TEST_ASSERT(db2.is_empty(9)); // Make sure that transfer will overwrite cells in managed blocks. db1 = mtv_type(3); @@ -417,12 +418,12 @@ db2.set(1, new muser_cell(2.1)); // This element will be overwritten. db1.transfer(0, 2, db2, 0); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db2.get(0)->value == 1.1); - assert(db2.get(1)->value == 1.2); - assert(db2.get(2)->value == 1.3); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db2.get(0)->value == 1.1); + TEST_ASSERT(db2.get(1)->value == 1.2); + TEST_ASSERT(db2.get(2)->value == 1.3); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/custom-trait/Makefile.in mdds-3.1.0/test/multi_type_vector/custom-trait/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom-trait/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom-trait/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom-trait/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/custom-trait/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom-trait/aos/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom-trait/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -442,7 +442,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom-trait/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/custom-trait/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/custom-trait/soa/Makefile.in 2023-04-29 13:08:04.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom-trait/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -445,7 +445,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/custom-trait/soa/test_loop_unrolling_simd.cpp mdds-3.1.0/test/multi_type_vector/custom-trait/soa/test_loop_unrolling_simd.cpp --- mdds-2.1.1/test/multi_type_vector/custom-trait/soa/test_loop_unrolling_simd.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom-trait/soa/test_loop_unrolling_simd.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -66,28 +66,28 @@ void mtv_test_loop_unrolling_sse2_x64() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } void mtv_test_loop_unrolling_sse2_x64_4() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } void mtv_test_loop_unrolling_sse2_x64_8() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } void mtv_test_loop_unrolling_sse2_x64_16() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } @@ -109,28 +109,28 @@ void mtv_test_loop_unrolling_sse2_x64() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_sse2(); } void mtv_test_loop_unrolling_sse2_x64_4() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_sse2(); } void mtv_test_loop_unrolling_sse2_x64_8() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_sse2(); } void mtv_test_loop_unrolling_sse2_x64_16() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_sse2(); } @@ -141,21 +141,21 @@ void mtv_test_loop_unrolling_avx2_x64() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } void mtv_test_loop_unrolling_avx2_x64_4() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } void mtv_test_loop_unrolling_avx2_x64_8() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; run_test(); } @@ -177,21 +177,21 @@ void mtv_test_loop_unrolling_avx2_x64() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_avx2(); } void mtv_test_loop_unrolling_avx2_x64_4() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_avx2(); } void mtv_test_loop_unrolling_avx2_x64_8() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; print_disabled_reasons_avx2(); } diff -Nru mdds-2.1.1/test/multi_type_vector/custom-trait/tc/loop_unrolling.inl mdds-3.1.0/test/multi_type_vector/custom-trait/tc/loop_unrolling.inl --- mdds-2.1.1/test/multi_type_vector/custom-trait/tc/loop_unrolling.inl 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/custom-trait/tc/loop_unrolling.inl 2025-07-03 16:15:17.000000000 +0000 @@ -62,35 +62,35 @@ void mtv_test_loop_unrolling_0() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_test_loop_unrolling(); } void mtv_test_loop_unrolling_4() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_test_loop_unrolling(); } void mtv_test_loop_unrolling_8() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_test_loop_unrolling(); } void mtv_test_loop_unrolling_16() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_test_loop_unrolling(); } void mtv_test_loop_unrolling_32() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_test_loop_unrolling(); } diff -Nru mdds-2.1.1/test/multi_type_vector/debug-util/Makefile.in mdds-3.1.0/test/multi_type_vector/debug-util/Makefile.in --- mdds-2.1.1/test/multi_type_vector/debug-util/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/debug-util/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/debug-util/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/debug-util/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/debug-util/soa/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/debug-util/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -430,7 +430,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/debug-util/soa/test_trace.cpp mdds-3.1.0/test/multi_type_vector/debug-util/soa/test_trace.cpp --- mdds-2.1.1/test/multi_type_vector/debug-util/soa/test_trace.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/debug-util/soa/test_trace.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -90,7 +90,7 @@ if (!std::equal(m_expected.cbegin(), m_expected.cend(), m_observed.cbegin(), compare)) { std::cerr << "test failed (line=" << m_line_number << ")" << std::endl; - assert(false); + TEST_ASSERT(false); } m_observed.clear(); } @@ -439,11 +439,11 @@ observed.clear(); db = db2; // copy checked_method_props expected{&db, "operator=", trace_method_t::mutator}; - assert(compare(observed.at(0), expected)); + TEST_ASSERT(compare(observed.at(0), expected)); observed.clear(); db = std::move(db2); // move - assert(compare(observed.at(0), expected)); + TEST_ASSERT(compare(observed.at(0), expected)); observed.clear(); } diff -Nru mdds-2.1.1/test/multi_type_vector/default/Makefile.in mdds-3.1.0/test/multi_type_vector/default/Makefile.in --- mdds-2.1.1/test/multi_type_vector/default/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/default/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/default/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/default/aos/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -463,7 +463,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/default/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/default/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/default/soa/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -463,7 +463,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/Makefile.in mdds-3.1.0/test/multi_type_vector/default/tc/Makefile.in --- mdds-2.1.1/test/multi_type_vector/default/tc/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -182,7 +182,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/basic.inl mdds-3.1.0/test/multi_type_vector/default/tc/basic.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/basic.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/basic.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,7 @@ void mtv_test_basic() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; bool res; { @@ -39,11 +39,11 @@ // Empty cell has a numeric value of 0.0. col_db.get(0, test); - assert(test == 0.0); + TEST_ASSERT(test == 0.0); // Basic value setting and retrieval. res = test_cell_insertion(col_db, 0, 2.0); - assert(res); + TEST_ASSERT(res); } { @@ -53,30 +53,30 @@ // Test empty cell values. col_db.get(0, test); - assert(test == 0.0); + TEST_ASSERT(test == 0.0); test = 1.0; col_db.get(1, test); - assert(test == 0.0); + TEST_ASSERT(test == 0.0); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); col_db.get(1, test); - assert(test == 0.0); // should be empty. + TEST_ASSERT(test == 0.0); // should be empty. // Insert a new value to an empty row right below a non-empty one. res = test_cell_insertion(col_db, 1, 7.5); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 0, 4.5); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 5.1); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 2, 34.2); - assert(res); + TEST_ASSERT(res); } { @@ -84,31 +84,31 @@ mtv_type col_db(3); res = test_cell_insertion(col_db, 2, 5.0); // Insert into the last row. - assert(res); + TEST_ASSERT(res); double test = 9; col_db.get(1, test); - assert(test == 0.0); // should be empty. + TEST_ASSERT(test == 0.0); // should be empty. res = test_cell_insertion(col_db, 0, 2.5); - assert(res); + TEST_ASSERT(res); col_db.get(1, test); - assert(test == 0.0); // should be empty. + TEST_ASSERT(test == 0.0); // should be empty. res = test_cell_insertion(col_db, 1, 1.2); - assert(res); + TEST_ASSERT(res); } { // This time insert from bottom up one by one. mtv_type col_db(3); res = test_cell_insertion(col_db, 2, 1.2); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 0.2); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 0, 23.1); - assert(res); + TEST_ASSERT(res); } { @@ -118,7 +118,7 @@ for (size_t i = 0; i < 4; ++i, ++val) { res = test_cell_insertion(col_db, order[i], val); - assert(res); + TEST_ASSERT(res); } } @@ -129,7 +129,7 @@ for (size_t i = 0; i < 4; ++i, ++val) { res = test_cell_insertion(col_db, order[i], val); - assert(res); + TEST_ASSERT(res); } } @@ -140,7 +140,7 @@ for (size_t i = 0; i < 4; ++i, ++val) { res = test_cell_insertion(col_db, order[i], val); - assert(res); + TEST_ASSERT(res); } } @@ -151,7 +151,7 @@ for (size_t i = 0; i < 5; ++i, ++val) { res = test_cell_insertion(col_db, order[i], val); - assert(res); + TEST_ASSERT(res); } } @@ -159,139 +159,139 @@ // Insert first value into a middle row. mtv_type col_db(10); res = test_cell_insertion(col_db, 5, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "test"; res = test_cell_insertion(col_db, 4, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "test"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 2.0); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(2); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "test"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "test"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); str = "foo"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 2, 2.0); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); str = "test"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(4); res = test_cell_insertion(col_db, 0, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 3, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 2, 2.0); - assert(res); + TEST_ASSERT(res); std::string test; col_db.get(3, test); // Check the cell below. - assert(test == "foo"); + TEST_ASSERT(test == "foo"); res = test_cell_insertion(col_db, 1, -2.0); - assert(res); + TEST_ASSERT(res); test = "hmm"; col_db.get(3, test); - assert(test == "foo"); + TEST_ASSERT(test == "foo"); res = test_cell_insertion(col_db, 0, 7.5); // overwrite. - assert(res); + TEST_ASSERT(res); str = "bah"; res = test_cell_insertion(col_db, 0, str); // overwrite with different type. - assert(res); + TEST_ASSERT(res); double val = -999; col_db.get(1, val); // Check the cell below. - assert(val == -2.0); + TEST_ASSERT(val == -2.0); str = "alpha"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); col_db.get(2, val); // Check the cell below. - assert(val == 2.0); + TEST_ASSERT(val == 2.0); col_db.get(3, test); - assert(test == "foo"); + TEST_ASSERT(test == "foo"); str = "beta"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(1); res = test_cell_insertion(col_db, 0, 2.0); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 0, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 0, 3.0); - assert(res); + TEST_ASSERT(res); } { mtv_type col_db(2); res = test_cell_insertion(col_db, 0, 2.0); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 0, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 0, 3.0); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); str = "alpha"; res = test_cell_insertion(col_db, 0, str); - assert(res); + TEST_ASSERT(res); std::string test; col_db.get(1, test); - assert(test == "foo"); + TEST_ASSERT(test == "foo"); } { @@ -299,71 +299,71 @@ std::string str = "alpha"; col_db.set(2, str); res = test_cell_insertion(col_db, 2, 5.0); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 0, 1.0); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 2.0); - assert(res); + TEST_ASSERT(res); // At this point it contains one numeric block with 3 values. str = "beta"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 2, 3.0); - assert(res); + TEST_ASSERT(res); double test; col_db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); col_db.get(1, test); - assert(test == 2.0); + TEST_ASSERT(test == 2.0); col_db.get(2, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); } { mtv_type col_db(3); res = test_cell_insertion(col_db, 1, 5.0); - assert(res); + TEST_ASSERT(res); std::string str = "alpha"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 0, 4.0); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 3.0); - assert(res); + TEST_ASSERT(res); double test; col_db.get(0, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); // The top 2 cells are numeric and the bottom cell is still empty. str = "beta"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); col_db.get(0, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); res = test_cell_insertion(col_db, 1, 6.5); - assert(res); + TEST_ASSERT(res); col_db.get(0, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); str = "gamma"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); col_db.get(0, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); col_db.get(1, test); - assert(test == 6.5); + TEST_ASSERT(test == 6.5); // The top 2 cells are numeric and the bottom cell is std::string. str = "delta"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); } { @@ -375,10 +375,10 @@ col_db.set(3, 4.0); res = test_cell_insertion(col_db, 2, 3.0); - assert(res); + TEST_ASSERT(res); double test; col_db.get(3, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); } { @@ -390,7 +390,7 @@ col_db.set(3, str); res = test_cell_insertion(col_db, 3, 3.0); - assert(res); + TEST_ASSERT(res); } { @@ -401,15 +401,15 @@ col_db.set(2, str); res = test_cell_insertion(col_db, 2, 3.0); - assert(res); + TEST_ASSERT(res); // Next cell should still be empty. double test_val; col_db.get(3, test_val); - assert(test_val == 0.0); + TEST_ASSERT(test_val == 0.0); std::string test_str; col_db.get(3, test_str); - assert(test_str.empty()); + TEST_ASSERT(test_str.empty()); } { @@ -420,7 +420,7 @@ col_db.set(3, 1.0); std::string str = "alpha"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); } { @@ -440,39 +440,39 @@ col_db.set(2, str); str = "bah"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 2.0); - assert(res); + TEST_ASSERT(res); uint64_t index = 2; res = test_cell_insertion(col_db, 1, index); - assert(res); + TEST_ASSERT(res); std::string test; col_db.get(2, test); - assert(test == "foo"); + TEST_ASSERT(test == "foo"); str = "alpha"; res = test_cell_insertion(col_db, 0, str); - assert(res); + TEST_ASSERT(res); double val = 3.5; res = test_cell_insertion(col_db, 1, val); - assert(res); + TEST_ASSERT(res); index = 3; res = test_cell_insertion(col_db, 2, index); - assert(res); + TEST_ASSERT(res); // At this point cells 1, 2, 3 all contain different data types. str = "beta"; res = test_cell_insertion(col_db, 1, str); - assert(res); + TEST_ASSERT(res); // Reset. val = 4.5; res = test_cell_insertion(col_db, 1, val); - assert(res); + TEST_ASSERT(res); index = 4; res = test_cell_insertion(col_db, 1, index); - assert(res); + TEST_ASSERT(res); } { @@ -484,10 +484,10 @@ col_db.set(2, str); uint64_t index = 1; res = test_cell_insertion(col_db, 1, index); - assert(res); + TEST_ASSERT(res); std::string test; col_db.get(2, test); - assert(test == "beta"); + TEST_ASSERT(test == "beta"); } { @@ -495,17 +495,17 @@ // Insert 3 cells of 3 different types. res = test_cell_insertion(col_db, 0, true); - assert(res); + TEST_ASSERT(res); res = test_cell_insertion(col_db, 1, 1.2); - assert(res); + TEST_ASSERT(res); std::string str = "foo"; res = test_cell_insertion(col_db, 2, str); - assert(res); + TEST_ASSERT(res); // Now, insert a cell of the 4th type to the middle spot. uint64_t index = 2; res = test_cell_insertion(col_db, 1, index); - assert(res); + TEST_ASSERT(res); } { @@ -517,22 +517,22 @@ db.set(3, std::string("foo")); db.set(4, 3.0); db.set(5, 4.0); - assert(db.block_size() == 4); - assert(db.get(0) == 12); - assert(db.get(1) == 1.0); - assert(db.get(2) == 2.0); - assert(db.get(3) == "foo"); - assert(db.get(4) == 3.0); - assert(db.get(5) == 4.0); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.get(0) == 12); + TEST_ASSERT(db.get(1) == 1.0); + TEST_ASSERT(db.get(2) == 2.0); + TEST_ASSERT(db.get(3) == "foo"); + TEST_ASSERT(db.get(4) == 3.0); + TEST_ASSERT(db.get(5) == 4.0); db.set(3, 5.0); // merge blocks. - assert(db.block_size() == 2); - assert(db.get(0) == 12); - assert(db.get(1) == 1.0); - assert(db.get(2) == 2.0); - assert(db.get(3) == 5.0); - assert(db.get(4) == 3.0); - assert(db.get(5) == 4.0); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == 12); + TEST_ASSERT(db.get(1) == 1.0); + TEST_ASSERT(db.get(2) == 2.0); + TEST_ASSERT(db.get(3) == 5.0); + TEST_ASSERT(db.get(4) == 3.0); + TEST_ASSERT(db.get(5) == 4.0); } { @@ -541,10 +541,10 @@ db.set(5, std::string("test")); db.set(1, std::string("foo")); db.set(6, true); - assert(db.get(0) == 1.2); - assert(db.get(5) == "test"); - assert(db.get(1) == "foo"); - assert(db.get(6) == true); + TEST_ASSERT(db.get(0) == 1.2); + TEST_ASSERT(db.get(5) == "test"); + TEST_ASSERT(db.get(1) == "foo"); + TEST_ASSERT(db.get(6) == true); } { @@ -557,14 +557,14 @@ db.set(4, static_cast(-10)); db.set(5, static_cast(10)); db.set(6, true); - assert(db.block_size() == 7); - assert(db.get_type(0) == mdds::mtv::element_type_int64); - assert(db.get_type(1) == mdds::mtv::element_type_uint64); - assert(db.get_type(2) == mdds::mtv::element_type_int32); - assert(db.get_type(3) == mdds::mtv::element_type_uint32); - assert(db.get_type(4) == mdds::mtv::element_type_int16); - assert(db.get_type(5) == mdds::mtv::element_type_uint16); - assert(db.get_type(6) == mdds::mtv::element_type_boolean); + TEST_ASSERT(db.block_size() == 7); + TEST_ASSERT(db.get_type(0) == mdds::mtv::element_type_int64); + TEST_ASSERT(db.get_type(1) == mdds::mtv::element_type_uint64); + TEST_ASSERT(db.get_type(2) == mdds::mtv::element_type_int32); + TEST_ASSERT(db.get_type(3) == mdds::mtv::element_type_uint32); + TEST_ASSERT(db.get_type(4) == mdds::mtv::element_type_int16); + TEST_ASSERT(db.get_type(5) == mdds::mtv::element_type_uint16); + TEST_ASSERT(db.get_type(6) == mdds::mtv::element_type_boolean); } { @@ -576,9 +576,9 @@ db.set(8, std::string("A")); db.set(9, std::string("B")); db.set(7, 2.1); - assert(db.block_size() == 5); - assert(db.get_type(7) == mdds::mtv::element_type_double); - assert(db.get(7) == 2.1); + TEST_ASSERT(db.block_size() == 5); + TEST_ASSERT(db.get_type(7) == mdds::mtv::element_type_double); + TEST_ASSERT(db.get(7) == 2.1); } { @@ -586,14 +586,14 @@ std::vector vals(3, 1.2); db.set(4, vals.begin(), vals.end()); db.set(3, 4.1); - assert(db.get(0) == true); - assert(db.get(1) == true); - assert(db.get(2) == true); - assert(db.get(3) == 4.1); - assert(db.get(4) == 1.2); - assert(db.get(5) == 1.2); - assert(db.get(6) == 1.2); - assert(db.get(7) == true); + TEST_ASSERT(db.get(0) == true); + TEST_ASSERT(db.get(1) == true); + TEST_ASSERT(db.get(2) == true); + TEST_ASSERT(db.get(3) == 4.1); + TEST_ASSERT(db.get(4) == 1.2); + TEST_ASSERT(db.get(5) == 1.2); + TEST_ASSERT(db.get(6) == 1.2); + TEST_ASSERT(db.get(7) == true); } { @@ -606,33 +606,33 @@ db.set(4, 'e'); db.set(5, 'f'); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); db.set(0, 'r'); // overwrite. db.set(5, 'z'); // overwrite - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); mtv_type::const_iterator it = db.begin(); - assert(it != db.end()); - assert(it->type == mdds::mtv::element_type_int8); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->type == mdds::mtv::element_type_int8); { const int8_t* p = &mdds::mtv::int8_element_block::at(*it->data, 0); - assert(*p == 'r'); + TEST_ASSERT(*p == 'r'); ++p; - assert(*p == 'b'); + TEST_ASSERT(*p == 'b'); ++p; - assert(*p == 'c'); + TEST_ASSERT(*p == 'c'); } ++it; - assert(it != db.end()); - assert(it->type == mdds::mtv::element_type_uint8); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->type == mdds::mtv::element_type_uint8); { const uint8_t* p = mdds::mtv::uint8_element_block::data(*it->data); - assert(*p == 'd'); + TEST_ASSERT(*p == 'd'); ++p; - assert(*p == 'e'); + TEST_ASSERT(*p == 'e'); ++p; - assert(*p == 'z'); + TEST_ASSERT(*p == 'z'); } } } @@ -642,7 +642,7 @@ */ void mtv_test_basic_numeric() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db; @@ -650,20 +650,20 @@ db.push_back(1.0); db.push_back(2.0); - assert(db.size() == 3); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 1); db.set(1, 4.0f); - assert(db.size() == 3); - assert(db.block_size() == 3); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 3); db.set(0, 3.5f); - assert(db.size() == 3); - assert(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); db.set(2, 4.5f); - assert(db.size() == 3); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 1); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/construction.inl mdds-3.1.0/test/multi_type_vector/default/tc/construction.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/construction.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/construction.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,38 +28,38 @@ void mtv_test_construction() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { mtv_type db; // default constructor. - assert(db.size() == 0); - assert(db.empty()); - assert(db.block_size() == 0); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db.block_size() == 0); } { // Create an empty segment of size 7. mtv_type db(7); - assert(db.size() == 7); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 7); + TEST_ASSERT(db.block_size() == 1); } { // Create with initial value and size. mtv_type db(10, 1.0); - assert(db.size() == 10); - assert(db.block_size() == 1); - assert(db.get(0) == 1.0); - assert(db.get(9) == 1.0); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == 1.0); + TEST_ASSERT(db.get(9) == 1.0); } { // Create with initial value and size. mtv_type db(10, std::string("foo")); - assert(db.size() == 10); - assert(db.block_size() == 1); - assert(db.get(0) == "foo"); - assert(db.get(9) == "foo"); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == "foo"); + TEST_ASSERT(db.get(9) == "foo"); } { @@ -69,27 +69,27 @@ vals.push_back(1.2); vals.push_back(1.3); mtv_type db(vals.size(), vals.begin(), vals.end()); - assert(db.size() == 3); - assert(db.block_size() == 1); - assert(db.get(0) == 1.1); - assert(db.get(1) == 1.2); - assert(db.get(2) == 1.3); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 1.2); + TEST_ASSERT(db.get(2) == 1.3); } { std::vector vals; mtv_type db_empty(0, vals.begin(), vals.end()); - assert(db_empty.size() == 0); - assert(db_empty.block_size() == 0); + TEST_ASSERT(db_empty.size() == 0); + TEST_ASSERT(db_empty.block_size() == 0); vals.push_back("Andy"); vals.push_back("Bruce"); mtv_type db(2, vals.begin(), vals.end()); - assert(db.size() == 2); - assert(db.block_size() == 1); - assert(db.get(0) == "Andy"); - assert(db.get(1) == "Bruce"); + TEST_ASSERT(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == "Andy"); + TEST_ASSERT(db.get(1) == "Bruce"); } { @@ -97,7 +97,7 @@ try { mtv_type db(20, vals.begin(), vals.end()); - assert(!"This construction should have failed due to incorrect initial array size."); + TEST_ASSERT(!"This construction should have failed due to incorrect initial array size."); } catch (const mdds::invalid_arg_error&) { diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/empty_cells.inl mdds-3.1.0/test/multi_type_vector/default/tc/empty_cells.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/empty_cells.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/empty_cells.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,13 +28,13 @@ void mtv_test_empty_cells() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { mtv_type db(3); - assert(db.is_empty(0)); - assert(db.is_empty(2)); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(2)); // These won't change the state of the container since it's already empty. db.set_empty(0, 0); @@ -44,12 +44,12 @@ db.set(0, 1.0); db.set(2, 5.0); - assert(!db.is_empty(0)); - assert(!db.is_empty(2)); - assert(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(!db.is_empty(2)); + TEST_ASSERT(db.is_empty(1)); db.set(1, 2.3); - assert(!db.is_empty(1)); + TEST_ASSERT(!db.is_empty(1)); // Container contains a single block of numeric cells at this point. @@ -63,13 +63,13 @@ // Set the upper part of the block empty. db.set_empty(0, 1); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); double test; db.get(2, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); // Reset. db.set(0, 5.0); @@ -78,12 +78,12 @@ // Set the lower part of the block empty. db.set_empty(1, 2); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); db.get(0, test); - assert(test == 5.0); + TEST_ASSERT(test == 5.0); // Reset. db.set(0, 3.0); @@ -92,16 +92,16 @@ // Set the middle part of the block empty. db.set_empty(1, 1); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); db.get(0, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); db.get(2, test); - assert(test == 3.2); + TEST_ASSERT(test == 3.2); bool res = test_cell_insertion(db, 1, 4.3); - assert(res); + TEST_ASSERT(res); } { @@ -112,20 +112,20 @@ for (size_t i = 0; i < 4; ++i) { - assert(!db.is_empty(i)); + TEST_ASSERT(!db.is_empty(i)); } db.set_empty(1, 2); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(!db.is_empty(3)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); double test; db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); db.get(3, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); } { @@ -133,12 +133,12 @@ mtv_type db(2); db.set(0, 1.0); db.set(1, std::string("foo")); - assert(!db.is_empty(0)); - assert(!db.is_empty(1)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(!db.is_empty(1)); db.set_empty(0, 1); - assert(db.is_empty(0)); - assert(db.is_empty(1)); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); } { @@ -155,18 +155,18 @@ db.set(5, index); db.set_empty(1, 4); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(!db.is_empty(5)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(!db.is_empty(5)); double val; db.get(0, val); - assert(val == 1.0); + TEST_ASSERT(val == 1.0); uint64_t index_test; db.get(5, index_test); - assert(index_test == 100); + TEST_ASSERT(index_test == 100); } { @@ -183,15 +183,15 @@ db.set(5, index); db.set_empty(0, 4); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(!db.is_empty(5)); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(!db.is_empty(5)); uint64_t test; db.get(5, test); - assert(test == 50); + TEST_ASSERT(test == 50); } { @@ -207,15 +207,15 @@ db.set(5, index); db.set_empty(1, 5); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.is_empty(5)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); double test; db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); } { @@ -227,25 +227,25 @@ db.set(4, str); str = "baa"; db.set(5, str); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); - assert(!db.is_empty(3)); - assert(!db.is_empty(4)); - assert(!db.is_empty(5)); - assert(db.block_size() == 3); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(!db.is_empty(4)); + TEST_ASSERT(!db.is_empty(5)); + TEST_ASSERT(db.block_size() == 3); db.set_empty(1, 4); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(!db.is_empty(5)); - assert(db.block_size() == 2); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(!db.is_empty(5)); + TEST_ASSERT(db.block_size() == 2); std::string test; db.get(5, test); - assert(test == "baa"); + TEST_ASSERT(test == "baa"); } { @@ -255,24 +255,24 @@ db.set(1, 2.0); db.set(2, std::string("foo")); db.set(3, std::string("baa")); - assert(!db.is_empty(0)); - assert(!db.is_empty(1)); - assert(!db.is_empty(2)); - assert(!db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.is_empty(5)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(!db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); db.set_empty(1, 4); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.is_empty(5)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); double test; db.get(0, test); - assert(test == 1.0); - assert(db.block_size() == 2); + TEST_ASSERT(test == 1.0); + TEST_ASSERT(db.block_size() == 2); } { @@ -280,23 +280,23 @@ mtv_type db(6); db.set(2, 1.0); db.set(3, std::string("foo")); - assert(db.block_size() == 4); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); - assert(!db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.is_empty(5)); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); // This should set the whole range empty. db.set_empty(1, 4); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.is_empty(5)); - assert(db.block_size() == 1); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); + TEST_ASSERT(db.block_size() == 1); } { @@ -310,19 +310,19 @@ db.set(4, static_cast(4)); db.set_empty(2, 4); - assert(!db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); + TEST_ASSERT(!db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); db.set(2, static_cast(5)); db.set(3, static_cast(6)); db.set(4, static_cast(7)); db.set_empty(1, 2); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(!db.is_empty(3)); - assert(!db.is_empty(4)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(!db.is_empty(4)); db.set(3, static_cast(8)); db.set(4, static_cast(9)); @@ -343,77 +343,77 @@ db.set_empty(10, 10); cout << "setting 12 empty..." << endl; db.set_empty(12, 12); - assert(!db.is_empty(0)); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); - assert(!db.is_empty(3)); - assert(db.is_empty(4)); - assert(!db.is_empty(5)); - assert(!db.is_empty(6)); - assert(db.is_empty(7)); - assert(!db.is_empty(8)); - assert(!db.is_empty(9)); - assert(db.is_empty(10)); - assert(!db.is_empty(11)); - assert(db.is_empty(12)); - assert(!db.is_empty(13)); - assert(!db.is_empty(14)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(!db.is_empty(5)); + TEST_ASSERT(!db.is_empty(6)); + TEST_ASSERT(db.is_empty(7)); + TEST_ASSERT(!db.is_empty(8)); + TEST_ASSERT(!db.is_empty(9)); + TEST_ASSERT(db.is_empty(10)); + TEST_ASSERT(!db.is_empty(11)); + TEST_ASSERT(db.is_empty(12)); + TEST_ASSERT(!db.is_empty(13)); + TEST_ASSERT(!db.is_empty(14)); } { mtv_type db(3, true); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); db.set_empty(1, 1); - assert(db.get(0) == true); - assert(db.is_empty(1)); - assert(db.get(2) == true); - assert(db.block_size() == 3); + TEST_ASSERT(db.get(0) == true); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.get(2) == true); + TEST_ASSERT(db.block_size() == 3); } { mtv_type db(10); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); int16_t val = 12; db.set(3, val); - assert(db.block_size() == 3); - assert(db.is_empty(2)); - assert(!db.is_empty(3)); - assert(db.is_empty(4)); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); db.set_empty(3, 3); // This should merge the top, middle and bottom blocks into one. - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); db.set(9, val); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); db.set_empty(9, 9); // Merge the block with the top one. - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); db = mtv_type(10, true); db.set(3, 1.1); db.set(4, 1.2); db.set(5, 1.3); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); db.set_empty(3, 5); // No merging. - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); } { mtv_type db(10); db.set(0, 1.1); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); db.set(1, 1.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); db.set_empty(1, 1); // Merge with the next block. - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); db.set(1, 1.3); db = mtv_type(5); db.set(3, 2.1); db.set(4, 2.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); db.set_empty(3, 3); // Merge with the previous block. - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); } { @@ -423,26 +423,26 @@ db.set(4, true); db.set(5, static_cast(22)); db.set(6, std::string("foo")); - assert(db.block_size() == 7); + TEST_ASSERT(db.block_size() == 7); db.set_empty(2, 4); // Merge with the previous block. - assert(db.block_size() == 4); - assert(db.get(0) == 1.2); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.is_empty(4)); - assert(db.get(5) == 22); - assert(db.get(6) == "foo"); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.get(0) == 1.2); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); + TEST_ASSERT(db.get(5) == 22); + TEST_ASSERT(db.get(6) == "foo"); } { mtv_type db(4); db.set(0, true); db.set(2, true); - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); db.set_empty(0, 2); // Merge with the next block. cout << "block size: " << db.block_size() << endl; - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); } } diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/erase.inl mdds-3.1.0/test/multi_type_vector/default/tc/erase.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/erase.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/erase.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,15 +28,15 @@ void mtv_test_erase() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { // Single empty block. mtv_type db(5); db.erase(0, 2); // erase rows 0-2. - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); db.erase(0, 1); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); } { @@ -45,9 +45,9 @@ db.push_back(-234); db.erase(0, 2); // erase rows 0-2. - assert(db.size() == 3); + TEST_ASSERT(db.size() == 3); db.erase(0, 1); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); } { @@ -56,20 +56,20 @@ for (long i = 0; i < 5; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 1); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); db.erase(0, 2); // erase rows 0-2 - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); double test; db.get(0, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); db.get(1, test); - assert(test == 5.0); + TEST_ASSERT(test == 5.0); db.erase(0, 1); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); } { @@ -78,27 +78,27 @@ for (long i = 0; i < 4; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 2); - assert(db.size() == 8); - assert(!db.is_empty(3)); - assert(db.is_empty(4)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 8); + TEST_ASSERT(!db.is_empty(3)); + TEST_ASSERT(db.is_empty(4)); // Erase across two blocks. db.erase(3, 6); // 4 cells - assert(db.block_size() == 2); - assert(db.size() == 4); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 4); // Check the integrity of the data. double test; db.get(2, test); - assert(test == 3.0); - assert(db.is_empty(3)); + TEST_ASSERT(test == 3.0); + TEST_ASSERT(db.is_empty(3)); // Empty it. db.erase(0, 3); - assert(db.block_size() == 0); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.block_size() == 0); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); } { @@ -110,28 +110,28 @@ for (long i = 4; i < 8; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 2); - assert(db.size() == 8); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 8); // Erase across two blocks. db.erase(3, 6); // 4 cells - assert(db.block_size() == 2); - assert(db.size() == 4); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 4); // Check the integrity of the data. double test; db.get(2, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); uint64_t test2; db.get(3, test2); - assert(test2 == 8); + TEST_ASSERT(test2 == 8); // Empty it. db.erase(0, 3); - assert(db.block_size() == 0); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.block_size() == 0); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); } { @@ -150,31 +150,31 @@ db.set(i, os.str()); } - assert(db.block_size() == 3); - assert(db.size() == 9); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 9); db.erase(2, 7); - assert(db.block_size() == 2); - assert(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); // Check the integrity of the data. double test1; db.get(1, test1); - assert(test1 == 2.0); + TEST_ASSERT(test1 == 2.0); std::string test2; db.get(2, test2); - assert(test2 == "9"); + TEST_ASSERT(test2 == "9"); db.erase(2, 2); // Erase only one-block. - assert(db.block_size() == 1); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 2); test1 = -1.0; db.get(1, test1); - assert(test1 == 2.0); + TEST_ASSERT(test1 == 2.0); db.erase(0, 1); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); } { @@ -184,28 +184,28 @@ db.set(1, std::string("foo")); db.set(2, static_cast(2)); db.set(3, std::string("baa")); - assert(db.block_size() == 4); - assert(db.size() == 4); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.size() == 4); db.erase(2, 2); - assert(db.block_size() == 2); - assert(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); // Try again, but this time merge two empty blocks. db.resize(4); db.set_empty(1, 3); db.set(2, static_cast(10)); - assert(db.get(0) == 1.1); - assert(db.is_empty(1)); - assert(db.get(2) == 10); - assert(db.is_empty(3)); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.get(2) == 10); + TEST_ASSERT(db.is_empty(3)); db.erase(2, 2); - assert(db.block_size() == 2); - assert(db.size() == 3); - assert(db.get(0) == 1.1); - assert(db.is_empty(1)); - assert(db.is_empty(2)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); } { @@ -216,19 +216,19 @@ db.set(3, std::string("B")); db.set(4, 5.0); db.set(5, 6.0); - assert(db.block_size() == 3); - assert(db.size() == 6); - assert(db.get(0) == 1.0); - assert(db.get(1) == 2.0); - assert(db.get(2) == "A"); - assert(db.get(3) == "B"); - assert(db.get(4) == 5.0); - assert(db.get(5) == 6.0); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(db.get(0) == 1.0); + TEST_ASSERT(db.get(1) == 2.0); + TEST_ASSERT(db.get(2) == "A"); + TEST_ASSERT(db.get(3) == "B"); + TEST_ASSERT(db.get(4) == 5.0); + TEST_ASSERT(db.get(5) == 6.0); db.erase(1, 4); - assert(db.block_size() == 1); - assert(db.size() == 2); - assert(db.get(0) == 1.0); - assert(db.get(1) == 6.0); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 2); + TEST_ASSERT(db.get(0) == 1.0); + TEST_ASSERT(db.get(1) == 6.0); } { @@ -252,8 +252,8 @@ db.push_back(9); db.erase(1, 3); - assert(db.block_size() == 3); - assert(db.size() == 6); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 6); } { @@ -272,8 +272,8 @@ db.push_back(9); db.erase(1, 5); - assert(db.block_size() == 2); - assert(db.size() == 7); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 7); } { @@ -292,8 +292,8 @@ db.push_back(9); db.erase(3, 5); - assert(db.block_size() == 2); - assert(db.size() == 9); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 9); } { @@ -312,8 +312,8 @@ db.push_back(9); db.erase(3, 5); - assert(db.block_size() == 3); - assert(db.size() == 9); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 9); } { @@ -332,8 +332,8 @@ db.push_back(9); db.erase(3, 5); - assert(db.block_size() == 3); - assert(db.size() == 9); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 9); } { @@ -352,8 +352,8 @@ db.push_back(9); db.erase(3, 5); - assert(db.block_size() == 2); - assert(db.size() == 9); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 9); } } diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/hints.inl mdds-3.1.0/test/multi_type_vector/default/tc/hints.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/hints.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/hints.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,35 +28,37 @@ void mtv_test_hints_set() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(3); db.set(db.begin(), 0, 23.4); - assert(db.get(0) == 23.4); + TEST_ASSERT(db.get(0) == 23.4); db.set(db.end(), 0, std::string("test")); // passing end position should have no impact. - assert(db.get(0) == "test"); + TEST_ASSERT(db.get(0) == "test"); mtv_type::iterator pos_hint = db.set(0, 1.2); pos_hint = db.set(pos_hint, 1, 1.3); pos_hint = db.set(pos_hint, 2, 1.4); - assert(db.get(0) == 1.2); - assert(db.get(1) == 1.3); - assert(db.get(2) == 1.4); + TEST_ASSERT(db.get(0) == 1.2); + TEST_ASSERT(db.get(1) == 1.3); + TEST_ASSERT(db.get(2) == 1.4); pos_hint = db.begin(); pos_hint = db.set(pos_hint, 0, false); pos_hint = db.set(pos_hint, 1, std::string("foo")); pos_hint = db.set(pos_hint, 2, 34.5); - assert(db.get(0) == false); - assert(db.get(1) == "foo"); - assert(db.get(2) == 34.5); + TEST_ASSERT(db.get(0) == false); + TEST_ASSERT(db.get(1) == "foo"); + TEST_ASSERT(db.get(2) == 34.5); db.set(pos_hint, 0, int32_t(444)); // position hint does not precede the insertion position. - assert(db.get(0) == 444); // it should still work. + TEST_ASSERT(db.get(0) == 444); // it should still work. } void mtv_test_hints_set_cells() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(9); std::vector ints; @@ -79,22 +81,22 @@ pos_hint = db.set(pos_hint, 3, doubles.begin(), doubles.end()); pos_hint = db.set(pos_hint, 6, strings.begin(), strings.end()); - assert(db.get(0) == 1); - assert(db.get(1) == 2); - assert(db.get(2) == 3); - - assert(db.get(3) == 1.1); - assert(db.get(4) == 1.2); - assert(db.get(5) == 1.3); - - assert(db.get(6) == "A"); - assert(db.get(7) == "B"); - assert(db.get(8) == "C"); + TEST_ASSERT(db.get(0) == 1); + TEST_ASSERT(db.get(1) == 2); + TEST_ASSERT(db.get(2) == 3); + + TEST_ASSERT(db.get(3) == 1.1); + TEST_ASSERT(db.get(4) == 1.2); + TEST_ASSERT(db.get(5) == 1.3); + + TEST_ASSERT(db.get(6) == "A"); + TEST_ASSERT(db.get(7) == "B"); + TEST_ASSERT(db.get(8) == "C"); } void mtv_test_hints_insert_cells() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db(1, true); // We need to have at least one element to be able to insert. @@ -114,34 +116,35 @@ strings.push_back(std::string("David")); mtv_type::iterator pos_hint = db.insert(0, ints.begin(), ints.end()); - assert(db.get(0) == 11); - assert(db.get(1) == 22); - assert(db.get(2) == true); + TEST_ASSERT(db.get(0) == 11); + TEST_ASSERT(db.get(1) == 22); + TEST_ASSERT(db.get(2) == true); pos_hint = db.insert(pos_hint, 2, doubles.begin(), doubles.end()); - assert(db.get(0) == 11); - assert(db.get(1) == 22); - assert(db.get(2) == 2.1); - assert(db.get(3) == 3.2); - assert(db.get(4) == 4.3); - assert(db.get(5) == true); + TEST_ASSERT(db.get(0) == 11); + TEST_ASSERT(db.get(1) == 22); + TEST_ASSERT(db.get(2) == 2.1); + TEST_ASSERT(db.get(3) == 3.2); + TEST_ASSERT(db.get(4) == 4.3); + TEST_ASSERT(db.get(5) == true); pos_hint = db.insert(pos_hint, 4, strings.begin(), strings.end()); - assert(db.get(0) == 11); - assert(db.get(1) == 22); - assert(db.get(2) == 2.1); - assert(db.get(3) == 3.2); - assert(db.get(4) == "Andy"); - assert(db.get(5) == "Bruce"); - assert(db.get(6) == "Charlie"); - assert(db.get(7) == "David"); - assert(db.get(8) == 4.3); - assert(db.get(9) == true); + TEST_ASSERT(db.get(0) == 11); + TEST_ASSERT(db.get(1) == 22); + TEST_ASSERT(db.get(2) == 2.1); + TEST_ASSERT(db.get(3) == 3.2); + TEST_ASSERT(db.get(4) == "Andy"); + TEST_ASSERT(db.get(5) == "Bruce"); + TEST_ASSERT(db.get(6) == "Charlie"); + TEST_ASSERT(db.get(7) == "David"); + TEST_ASSERT(db.get(8) == 4.3); + TEST_ASSERT(db.get(9) == true); } void mtv_test_hints_set_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(20, true); mtv_type::iterator pos_hint = db.set_empty(db.begin(), 2, 3); pos_hint = db.set_empty(pos_hint, 5, 7); @@ -149,38 +152,39 @@ pos_hint = db.set_empty(pos_hint, 14, 17); // Check the boundaries. - assert(!db.is_empty(0)); - assert(!db.is_empty(4)); - assert(db.is_empty(5)); - assert(db.is_empty(7)); - assert(!db.is_empty(8)); - assert(db.is_empty(9)); - assert(db.is_empty(12)); - assert(!db.is_empty(13)); - assert(db.is_empty(14)); - assert(db.is_empty(17)); - assert(!db.is_empty(18)); + TEST_ASSERT(!db.is_empty(0)); + TEST_ASSERT(!db.is_empty(4)); + TEST_ASSERT(db.is_empty(5)); + TEST_ASSERT(db.is_empty(7)); + TEST_ASSERT(!db.is_empty(8)); + TEST_ASSERT(db.is_empty(9)); + TEST_ASSERT(db.is_empty(12)); + TEST_ASSERT(!db.is_empty(13)); + TEST_ASSERT(db.is_empty(14)); + TEST_ASSERT(db.is_empty(17)); + TEST_ASSERT(!db.is_empty(18)); } void mtv_test_hints_insert_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(2, true); mtv_type::iterator pos_hint = db.begin(); pos_hint = db.insert_empty(pos_hint, 1, 3); // the size becomes 5. pos_hint = db.insert_empty(pos_hint, 4, 2); // the size now becomes 7. mtv_type::iterator check = db.begin(); - assert(check->type == mdds::mtv::element_type_boolean); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->size == 1); ++check; - assert(check->type == mdds::mtv::element_type_empty); - assert(check->size == 5); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check->size == 5); ++check; - assert(check->type == mdds::mtv::element_type_boolean); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->size == 1); ++check; - assert(check == db.end()); + TEST_ASSERT(check == db.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/insert.inl mdds-3.1.0/test/multi_type_vector/default/tc/insert.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/insert.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/insert.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,36 +28,36 @@ void mtv_test_insert_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { mtv_type db(5); db.insert_empty(0, 5); - assert(db.size() == 10); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.block_size() == 1); // Insert data from row 0 to 4. for (long i = 0; i < 5; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 2); - assert(db.size() == 10); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 10); // Now, insert an empty block of size 2 at the top. db.insert_empty(0, 2); - assert(db.block_size() == 3); - assert(db.size() == 12); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 12); double test; db.get(2, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); // Insert an empty cell into an empty block. This should shift the // data block down by one. db.insert_empty(1, 1); - assert(db.block_size() == 3); - assert(db.size() == 13); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 13); db.get(4, test); - assert(test == 2.0); + TEST_ASSERT(test == 2.0); } { @@ -65,43 +65,43 @@ for (long i = 0; i < 5; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 1); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); // Insert an empty block into the middle of a non-empty block. db.insert_empty(2, 2); - assert(db.block_size() == 3); - assert(db.size() == 7); - assert(db.is_empty(2)); - assert(db.is_empty(3)); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 7); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); double test; db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); db.get(1, test); - assert(test == 2.0); + TEST_ASSERT(test == 2.0); db.get(4, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); db.get(5, test); - assert(test == 4.0); + TEST_ASSERT(test == 4.0); db.get(6, test); - assert(test == 5.0); + TEST_ASSERT(test == 5.0); } { mtv_type db(1); db.set(0, 2.5); db.insert_empty(0, 2); - assert(db.block_size() == 2); - assert(db.size() == 3); - assert(db.is_empty(1)); - assert(!db.is_empty(2)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(!db.is_empty(2)); double test; db.get(2, test); - assert(test == 2.5); + TEST_ASSERT(test == 2.5); } { @@ -110,13 +110,13 @@ db.set(1, 2.3); db.insert_empty(1, 1); - assert(db.block_size() == 3); - assert(db.size() == 3); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 3); double test; db.get(0, test); - assert(test == 1.2); + TEST_ASSERT(test == 1.2); db.get(2, test); - assert(test == 2.3); + TEST_ASSERT(test == 2.3); } { @@ -125,14 +125,14 @@ db.push_back(13.0); db.insert_empty(2, 2); - assert(db.block_size() == 3); - assert(db.size() == 6); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.is_empty(2)); - assert(db.is_empty(3)); - assert(db.get(4) == 12.0); - assert(db.get(5) == 13.0); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.is_empty(2)); + TEST_ASSERT(db.is_empty(3)); + TEST_ASSERT(db.get(4) == 12.0); + TEST_ASSERT(db.get(5) == 13.0); } { @@ -143,83 +143,83 @@ db.push_back(123); db.insert_empty(7, 3); - assert(db.block_size() == 4); - assert(db.size() == 13); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.size() == 13); } } void mtv_test_insert_cells() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; { // Insert into non-empty block of the same type. mtv_type db(1); db.set(0, 1.1); - assert(db.block_size() == 1); - assert(db.size() == 1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 1); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(0, p, p + 3); - assert(db.block_size() == 1); - assert(db.size() == 4); - assert(db.get(0) == 2.1); - assert(db.get(1) == 2.2); - assert(db.get(2) == 2.3); - assert(db.get(3) == 1.1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.get(0) == 2.1); + TEST_ASSERT(db.get(1) == 2.2); + TEST_ASSERT(db.get(2) == 2.3); + TEST_ASSERT(db.get(3) == 1.1); } { // Insert into an existing empty block. mtv_type db(1); - assert(db.block_size() == 1); - assert(db.size() == 1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 1); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(0, p, p + 3); - assert(db.block_size() == 2); - assert(db.size() == 4); - assert(db.get(0) == 2.1); - assert(db.get(1) == 2.2); - assert(db.get(2) == 2.3); - assert(db.is_empty(3)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.get(0) == 2.1); + TEST_ASSERT(db.get(1) == 2.2); + TEST_ASSERT(db.get(2) == 2.3); + TEST_ASSERT(db.is_empty(3)); } { mtv_type db(2); db.set(0, 1.1); - assert(db.block_size() == 2); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 2); - assert(db.size() == 5); - assert(db.get(0) == 1.1); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.is_empty(4)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.is_empty(4)); } { mtv_type db(2); db.set(0, static_cast(23)); - assert(db.block_size() == 2); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 3); - assert(db.size() == 5); - assert(db.get(0) == 23); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.is_empty(4)); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == 23); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.is_empty(4)); } { @@ -227,70 +227,70 @@ double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 3); - assert(db.size() == 5); - assert(db.is_empty(0)); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.is_empty(4)); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.is_empty(4)); } { mtv_type db(2); db.set(0, 1.1); db.set(1, static_cast(23)); - assert(db.block_size() == 2); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 2); - assert(db.size() == 5); - assert(db.get(0) == 1.1); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.get(4) == 23); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.get(4) == 23); } { mtv_type db(2); db.set(0, true); db.set(1, static_cast(23)); - assert(db.block_size() == 2); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 3); - assert(db.size() == 5); - assert(db.get(0) == true); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.get(4) == 23); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == true); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.get(4) == 23); } { mtv_type db(2); db.set(0, static_cast(12)); db.set(1, static_cast(23)); - assert(db.block_size() == 1); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.insert(1, p, p + 3); - assert(db.block_size() == 3); - assert(db.size() == 5); - assert(db.get(0) == 12); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.get(4) == 23); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == 12); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.get(4) == 23); } { @@ -298,13 +298,13 @@ db.set(0, 1.0); db.set(1, std::string("foo")); db.set(2, std::string("baa")); - assert(db.size() == 3); - assert(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); double vals[] = {2.1}; const double* p = &vals[0]; db.insert(2, p, p + 1); - assert(db.size() == 4); - assert(db.block_size() == 4); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.block_size() == 4); } { @@ -314,17 +314,17 @@ double vals[] = {1.2}; const double* p = &vals[0]; db.insert(1, p, p + 1); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); // Append value to the top block. uint64_t vals2[] = {22}; const uint64_t* p2 = &vals2[0]; db.insert(1, p2, p2 + 1); - assert(db.block_size() == 3); - assert(db.get(0) == 11); - assert(db.get(1) == 22); - assert(db.get(2) == 1.2); - assert(db.get(3) == 12); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.get(0) == 11); + TEST_ASSERT(db.get(1) == 22); + TEST_ASSERT(db.get(2) == 1.2); + TEST_ASSERT(db.get(3) == 12); } { @@ -335,18 +335,18 @@ double vals[] = {2.1, 2.2, 2.3}; const double* p = vals; db.insert(2, p, p + 3); - assert(db.block_size() == 4); - assert(db.size() == 10); - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.get(2) == 2.1); - assert(db.get(3) == 2.2); - assert(db.get(4) == 2.3); - assert(db.is_empty(5)); - assert(db.is_empty(6)); - assert(db.is_empty(7)); - assert(db.get(8) == 1.1); - assert(db.get(9) == 1.2); + TEST_ASSERT(db.block_size() == 4); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.get(2) == 2.1); + TEST_ASSERT(db.get(3) == 2.2); + TEST_ASSERT(db.get(4) == 2.3); + TEST_ASSERT(db.is_empty(5)); + TEST_ASSERT(db.is_empty(6)); + TEST_ASSERT(db.is_empty(7)); + TEST_ASSERT(db.get(8) == 1.1); + TEST_ASSERT(db.get(9) == 1.2); } { @@ -357,18 +357,18 @@ int16_t vals[] = {5, 6, 7}; const int16_t* p = vals; db.insert(1, p, p + 3); - assert(db.block_size() == 2); - assert(db.size() == 10); - assert(db.get(0) == 222); - assert(db.get(1) == 5); - assert(db.get(2) == 6); - assert(db.get(3) == 7); - assert(db.get(4) == 222); - assert(db.get(5) == 222); - assert(db.get(6) == 222); - assert(db.get(7) == 222); - assert(db.get(8) == 12); - assert(db.get(9) == 34); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.get(0) == 222); + TEST_ASSERT(db.get(1) == 5); + TEST_ASSERT(db.get(2) == 6); + TEST_ASSERT(db.get(3) == 7); + TEST_ASSERT(db.get(4) == 222); + TEST_ASSERT(db.get(5) == 222); + TEST_ASSERT(db.get(6) == 222); + TEST_ASSERT(db.get(7) == 222); + TEST_ASSERT(db.get(8) == 12); + TEST_ASSERT(db.get(9) == 34); } } diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/iterators.inl mdds-3.1.0/test/multi_type_vector/default/tc/iterators.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/iterators.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/iterators.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,23 +28,24 @@ void mtv_test_iterators() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + { mtv_type db(5); mtv_type::const_iterator it; it = db.begin(); mtv_type::const_iterator it_end = db.end(); size_t len = std::distance(it, it_end); - assert(len == 1); - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 5); + TEST_ASSERT(len == 1); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 5); const mtv_type::const_iterator::value_type& val = *it; - assert(val.type == it->type); - assert(val.size == it->size); + TEST_ASSERT(val.type == it->type); + TEST_ASSERT(val.size == it->size); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } { @@ -53,74 +54,74 @@ db.set(1, 2.2); db.set(4, std::string("boo")); db.set(5, std::string("hoo")); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); { // Forward iterator mtv_type::const_iterator it = db.begin(), it_end = db.end(); size_t len = std::distance(it, it_end); - assert(len == 3); - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(len == 3); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 2); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } { // Reverse iterator mtv_type::const_reverse_iterator it = db.rbegin(), it_end = db.rend(); size_t len = std::distance(it, it_end); - assert(len == 3); - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 2); + TEST_ASSERT(len == 3); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } { // Reverse iterator (C++11) mtv_type::const_reverse_iterator it = db.crbegin(), it_end = db.crend(); size_t len = std::distance(it, it_end); - assert(len == 3); - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 2); + TEST_ASSERT(len == 3); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); ++it; - assert(it != it_end); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(it != it_end); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it == it_end); + TEST_ASSERT(it == it_end); } } @@ -129,21 +130,21 @@ mtv_type db(10); db.set(0, true); mtv_type::const_iterator it = db.begin(); - assert(it->position == 0); - assert(it->size == 1); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->size == 1); ++it; - assert(it->position == 1); - assert(it->size == 9); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->size == 9); --it; - assert(it->position == 0); - assert(it->size == 1); - assert(it == db.begin()); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it == db.begin()); } } void mtv_test_iterators_element_block() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db(10); db.set(0, 1.1); @@ -156,62 +157,62 @@ mtv_type::const_iterator it_blk = db.begin(), it_blk_end = db.end(); // First block is a numeric block. - assert(it_blk != it_blk_end); - assert(it_blk->type == mdds::mtv::element_type_double); - assert(it_blk->size == 3); - assert(it_blk->data); + TEST_ASSERT(it_blk != it_blk_end); + TEST_ASSERT(it_blk->type == mdds::mtv::element_type_double); + TEST_ASSERT(it_blk->size == 3); + TEST_ASSERT(it_blk->data); { mdds::mtv::double_element_block::const_iterator it_data = mdds::mtv::double_element_block::begin(*it_blk->data); mdds::mtv::double_element_block::const_iterator it_data_end = mdds::mtv::double_element_block::end(*it_blk->data); - assert(it_data != it_data_end); - assert(*it_data == 1.1); + TEST_ASSERT(it_data != it_data_end); + TEST_ASSERT(*it_data == 1.1); ++it_data; - assert(*it_data == 1.2); + TEST_ASSERT(*it_data == 1.2); ++it_data; - assert(*it_data == 1.3); + TEST_ASSERT(*it_data == 1.3); ++it_data; - assert(it_data == it_data_end); + TEST_ASSERT(it_data == it_data_end); - assert(mdds::mtv::double_element_block::at(*it_blk->data, 0) == 1.1); - assert(mdds::mtv::double_element_block::at(*it_blk->data, 1) == 1.2); - assert(mdds::mtv::double_element_block::at(*it_blk->data, 2) == 1.3); + TEST_ASSERT(mdds::mtv::double_element_block::at(*it_blk->data, 0) == 1.1); + TEST_ASSERT(mdds::mtv::double_element_block::at(*it_blk->data, 1) == 1.2); + TEST_ASSERT(mdds::mtv::double_element_block::at(*it_blk->data, 2) == 1.3); // Access the underlying data array directly. const double* array = &mdds::mtv::double_element_block::at(*it_blk->data, 0); - assert(*array == 1.1); + TEST_ASSERT(*array == 1.1); ++array; - assert(*array == 1.2); + TEST_ASSERT(*array == 1.2); ++array; - assert(*array == 1.3); + TEST_ASSERT(*array == 1.3); } // Next block is empty. ++it_blk; - assert(it_blk->type == mdds::mtv::element_type_empty); - assert(it_blk->size == 1); - assert(it_blk->data == nullptr); + TEST_ASSERT(it_blk->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it_blk->size == 1); + TEST_ASSERT(it_blk->data == nullptr); // Next block is a string block. ++it_blk; - assert(it_blk->type == mdds::mtv::element_type_string); - assert(it_blk->size == 4); - assert(it_blk->data); + TEST_ASSERT(it_blk->type == mdds::mtv::element_type_string); + TEST_ASSERT(it_blk->size == 4); + TEST_ASSERT(it_blk->data); { mdds::mtv::string_element_block::const_reverse_iterator it_data = mdds::mtv::string_element_block::rbegin(*it_blk->data); mdds::mtv::string_element_block::const_reverse_iterator it_data_end = mdds::mtv::string_element_block::rend(*it_blk->data); - assert(it_data != it_data_end); - assert(*it_data == "D"); + TEST_ASSERT(it_data != it_data_end); + TEST_ASSERT(*it_data == "D"); ++it_data; - assert(*it_data == "C"); + TEST_ASSERT(*it_data == "C"); ++it_data; - assert(*it_data == "B"); + TEST_ASSERT(*it_data == "B"); ++it_data; - assert(*it_data == "A"); + TEST_ASSERT(*it_data == "A"); ++it_data; - assert(it_data == it_data_end); + TEST_ASSERT(it_data == it_data_end); } { @@ -221,31 +222,31 @@ mdds::mtv::string_element_block::crbegin(*it_blk->data); mdds::mtv::string_element_block::const_reverse_iterator it_data_end = mdds::mtv::string_element_block::crend(*it_blk->data); - assert(it_data != it_data_end); - assert(*it_data == "D"); + TEST_ASSERT(it_data != it_data_end); + TEST_ASSERT(*it_data == "D"); ++it_data; - assert(*it_data == "C"); + TEST_ASSERT(*it_data == "C"); ++it_data; - assert(*it_data == "B"); + TEST_ASSERT(*it_data == "B"); ++it_data; - assert(*it_data == "A"); + TEST_ASSERT(*it_data == "A"); ++it_data; - assert(it_data == it_data_end); + TEST_ASSERT(it_data == it_data_end); } // Another empty block follows. ++it_blk; - assert(it_blk->type == mdds::mtv::element_type_empty); - assert(it_blk->size == 2); - assert(it_blk->data == nullptr); + TEST_ASSERT(it_blk->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it_blk->size == 2); + TEST_ASSERT(it_blk->data == nullptr); ++it_blk; - assert(it_blk == it_blk_end); + TEST_ASSERT(it_blk == it_blk_end); } void mtv_test_iterators_mutable_element_block() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; /** * This function is just to ensure that even the non-const iterator can be @@ -257,25 +258,25 @@ auto check_block_iterator = [](const mtv_type::iterator& it, mdds::mtv::element_t expected) { mdds::mtv::element_t actual = it->type; const mtv_type::element_block_type* data = (*it).data; - assert(actual == expected); - assert(data != nullptr); + TEST_ASSERT(actual == expected); + TEST_ASSERT(data != nullptr); }; mtv_type db(1); db.set(0, 1.2); mtv_type::iterator it_blk = db.begin(), it_blk_end = db.end(); size_t n = std::distance(it_blk, it_blk_end); - assert(n == 1); + TEST_ASSERT(n == 1); check_block_iterator(it_blk, mdds::mtv::element_type_double); mdds::mtv::double_element_block::iterator it = mdds::mtv::double_element_block::begin(*it_blk->data); mdds::mtv::double_element_block::iterator it_end = mdds::mtv::double_element_block::end(*it_blk->data); n = std::distance(it, it_end); - assert(n == 1); - assert(*it == 1.2); + TEST_ASSERT(n == 1); + TEST_ASSERT(*it == 1.2); *it = 2.3; // write via iterator. - assert(db.get(0) == 2.3); + TEST_ASSERT(db.get(0) == 2.3); db.resize(3); db.set(1, 2.4); @@ -284,27 +285,27 @@ it_blk = db.begin(); it_blk_end = db.end(); n = std::distance(it_blk, it_blk_end); - assert(n == 1); + TEST_ASSERT(n == 1); check_block_iterator(it_blk, mdds::mtv::element_type_double); it = mdds::mtv::double_element_block::begin(*it_blk->data); it_end = mdds::mtv::double_element_block::end(*it_blk->data); n = std::distance(it, it_end); - assert(n == 3); + TEST_ASSERT(n == 3); *it = 3.1; ++it; *it = 3.2; ++it; *it = 3.3; - assert(db.get(0) == 3.1); - assert(db.get(1) == 3.2); - assert(db.get(2) == 3.3); + TEST_ASSERT(db.get(0) == 3.1); + TEST_ASSERT(db.get(1) == 3.2); + TEST_ASSERT(db.get(2) == 3.3); } void mtv_test_iterators_private_data() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // What the end position iterator stores in the private data area is // intentionally undefined. @@ -314,13 +315,13 @@ // With only a single block mtv_type::iterator it = db.begin(); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); it = db.end(); --it; - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); // With 3 blocks (sizes of 4, 3, and 2 in this order) @@ -329,35 +330,35 @@ db.set(6, 1.1); it = db.begin(); - assert(it->size == 4); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); ++it; - assert(it->size == 3); - assert(it->position == 4); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 1); ++it; - assert(it->size == 2); - assert(it->position == 7); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->position == 7); + TEST_ASSERT(it->__private_data.block_index == 2); ++it; - assert(it == db.end()); // end position reached. + TEST_ASSERT(it == db.end()); // end position reached. // Go in reverse direction. --it; - assert(it->size == 2); - assert(it->position == 7); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->position == 7); + TEST_ASSERT(it->__private_data.block_index == 2); --it; - assert(it->size == 3); - assert(it->position == 4); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 1); --it; - assert(it->size == 4); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); - assert(it == db.begin()); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/iterators_insert.inl mdds-3.1.0/test/multi_type_vector/default/tc/iterators_insert.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/iterators_insert.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/iterators_insert.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_iterators_insert() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type::iterator it, check; std::vector doubles; std::vector bools; @@ -43,14 +44,14 @@ it = db.insert(4, doubles.begin(), doubles.end()); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->size == 5); - assert(it->position == 3); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->position == 3); ++it; - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 6); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Same as above, except that the values will not be appended to the previous block. db = mtv_type(3); @@ -59,31 +60,31 @@ it = db.insert(1, doubles.begin(), doubles.end()); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert into the middle of an empty block. db = mtv_type(2); doubles.resize(3, 1.2); it = db.insert(1, doubles.begin(), doubles.end()); check = db.begin(); - assert(check->type == mdds::mtv::element_type_empty); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_empty); + TEST_ASSERT(check->size == 1); ++check; - assert(check == it); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 3); + TEST_ASSERT(check == it); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 3); ++it; - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert into a block of the same type. db = mtv_type(5, false); @@ -93,11 +94,11 @@ it = db.insert(2, bools.begin(), bools.end()); check = db.begin(); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 6); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 6); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert values which will be append to the previous block. db = mtv_type(5, 1.1); @@ -108,14 +109,14 @@ it = db.insert(2, doubles.begin(), doubles.end()); check = db.begin(); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 3); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 3); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 3); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert between blocks without merge. db = mtv_type(3); @@ -125,19 +126,19 @@ bools.resize(4, true); it = db.insert(1, bools.begin(), bools.end()); check = db.begin(); - assert(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 1); ++it; - assert(it->type == mdds::mtv::element_type_int32); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert values of differing type into middle of a block. db = mtv_type(4, 0.01); @@ -145,38 +146,38 @@ ints.resize(3, 55); it = db.insert(2, ints.begin(), ints.end()); check = db.begin(); - assert(check->type == mdds::mtv::element_type_string); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_string); + TEST_ASSERT(check->size == 1); ++check; - assert(check->type == mdds::mtv::element_type_double); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->size == 1); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_int32); - assert(it->size == 3); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_int32); + TEST_ASSERT(it->size == 3); ++it; - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } void mtv_test_iterators_insert_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // Insert into an already empty spot. mtv_type db(2); db.set(1, 1.2); mtv_type::iterator it = db.insert_empty(0, 3); - assert(it == db.begin()); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert an empty range that will be tucked into the previous empty block. db = mtv_type(4); @@ -186,47 +187,47 @@ it = db.insert_empty(2, 2); mtv_type::iterator check = db.begin(); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 3); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 3); ++it; - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert an empty range between non-empty blocks. db = mtv_type(2, false); db.set(0, 1.1); it = db.insert_empty(1, 2); check = db.begin(); - assert(check->type == mdds::mtv::element_type_double); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->size == 1); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 2); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert in the middle of a non-empty block. db = mtv_type(3, std::string("foo")); it = db.insert_empty(2, 4); check = db.begin(); - assert(check->type == mdds::mtv::element_type_string); - assert(check->size == 2); + TEST_ASSERT(check->type == mdds::mtv::element_type_string); + TEST_ASSERT(check->size == 2); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/iterators_set.inl mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/iterators_set.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set.inl 2025-07-03 16:15:17.000000000 +0000 @@ -31,18 +31,18 @@ */ void mtv_test_iterators_set() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; // single element only mtv_type db(1); mtv_type::iterator it = db.set(0, 1.1); - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); // Set value to the top of the only block. db.clear(); db.resize(3); it = db.set(0, 1.2); - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); // Set value to the bottom of the only block. db.clear(); @@ -50,10 +50,10 @@ it = db.set(2, 1.3); mtv_type::iterator check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); check = db.end(); --check; - assert(it == check); + TEST_ASSERT(it == check); // Set value to the middle of the only block. db.clear(); @@ -61,35 +61,35 @@ it = db.set(1, 1.4); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); check = db.end(); std::advance(check, -2); - assert(it == check); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); // Set value to the top empty block of size 1 followed by a non-empty block. db.clear(); db.resize(2); db.set(1, 2.1); it = db.set(0, 2.2); // same type as that of the following block. - assert(it == db.begin()); - assert(it->size == 2); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); db.set_empty(0, 0); it = db.set(0, true); // different type from that of the following block. - assert(it == db.begin()); - assert(it->size == 1); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); // Set value to the top of the top empty block (not size 1) followed by a non-empty block. db.clear(); db.resize(3); db.set(2, true); it = db.set(0, 5.1); - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); // Set value to the bottom of the top empty block (not size 1) followed by a non-empty block. db.clear(); @@ -98,24 +98,24 @@ it = db.set(1, 6.2); // same type as that of the following block. check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); check = db.end(); --check; - assert(it == check); - assert(it->size == 2); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); db.set_empty(0, 1); it = db.set(1, true); // different type from that of the following block. check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); check = db.end(); std::advance(check, -2); - assert(it == check); - assert(it->size == 1); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); // Set value to the middle of the top empty block (not size 1) followed by a non-empty block. db.clear(); @@ -124,26 +124,26 @@ it = db.set(3, 1.2); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 1); - assert(it->position == 3); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->position == 3); + TEST_ASSERT(it->__private_data.block_index == 1); // Set value to an empty block of size 1 immediately below a non-empty block. db.clear(); db.resize(2); db.set(0, true); it = db.set(1, false); // same type as that of the previous block. - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); // Set value to an empty block of size 1 between non-empty blocks of the same type. db = mtv_type(3, true); db.set_empty(1, 1); it = db.set(1, false); - assert(it == db.begin()); - assert(it->size == 3); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 3); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to an empty block of size 1 between non-empty blocks. The // previous block is of the same type as that of the inserted value. @@ -151,10 +151,10 @@ db.set_empty(0, 1); db.set(0, true); it = db.set(1, false); - assert(it == db.begin()); - assert(it->size == 2); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 2); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the top of an empty block (not of size 1) following a // non-empty block of the same type. @@ -162,15 +162,15 @@ db.resize(3); db.set(0, true); it = db.set(1, false); - assert(it == db.begin()); - assert(it->size == 2); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 2); // Set value to an empty block of size 1, following a non-empty block of different type. db = mtv_type(2); db.set(0, true); it = db.set(1, 1.1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to an empty block of size 1, following a non-empty block of // different type and followed by a non-empty block of different type. @@ -178,7 +178,7 @@ db.set_empty(1, 1); it = db.set(1, 2.1); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to an empty block of size 1, following a non-empty block of // different type but followed by a non-empty block of the same type. @@ -187,11 +187,11 @@ db.set(0, true); it = db.set(2, 2.1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.set(1, 2.2); // same type as that of the following block. - assert(it->size == 2); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the top of an empty block (not of size 1) between // non-empty blocks. The previous block is of different type. @@ -202,61 +202,61 @@ it = db.set(1, 2.2); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 1); - assert(it->position == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->position == 1); // Set value to the bottom of an empty block (not of size 1) between // non-empty blocks. db = mtv_type(7, false); db.set_empty(2, 4); it = db.set(4, true); // Same type as that of the following block. - assert(it->size == 3); - assert(it->position == 4); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db.set_empty(2, 4); it = db.set(4, 1.1); // Different type from that of the following block. - assert(it->size == 1); - assert(it->position == 4); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 2); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the middle of an empty block between non-empty blocks. db = mtv_type(12, true); db.set_empty(3, 7); it = db.set(5, 4.3); - assert(it->size == 1); + TEST_ASSERT(it->size == 1); check = db.begin(); std::advance(check, 2); - assert(check == it); + TEST_ASSERT(check == it); ++it; - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to existing block of the same type. it = db.set(5, 4.5); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->size == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); std::advance(it, 3); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the top of an existing topmost block of different type. db = mtv_type(5, true); it = db.set(0, 1.1); - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the top of an existing block of different type. The block // is below an empty block. @@ -265,9 +265,9 @@ it = db.set(5, 2.1); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the top of an existing block of different type. The block // is below a non-empty block. @@ -277,23 +277,23 @@ it = db.set(5, 2.1); // append to the previous block. check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10, true); db.set(2, doubles.begin(), doubles.end()); // set double's to 2 thru 4. it = db.set(5, std::string("foo")); // type different from that of the previous block. - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); check = db.begin(); std::advance(check, 2); - assert(it == check); + TEST_ASSERT(it == check); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the middle of an existing non-empty block. db = mtv_type(10, true); @@ -301,43 +301,43 @@ doubles.resize(3, 2.3); db.set(0, doubles.begin(), doubles.end()); // set double's to 0 thru 2. it = db.set(6, std::string("text")); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); - assert(it->position == 6); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->position == 6); check = db.begin(); std::advance(check, 2); - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the bottom of the only block that's non-empty. db = mtv_type(10, false); it = db.set(9, 2.1); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the bottom of the topmost non-empty block which is // followed by an empty block. db = mtv_type(10, false); db.set_empty(5, 9); it = db.set(4, 1.1); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); - assert(it->position == 4); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->position == 4); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // This time the following block is not empty but is of different type // than that of the value being set. @@ -346,16 +346,16 @@ doubles.resize(5, 2.1); db.set(5, doubles.begin(), doubles.end()); // numeric at 5 thru 9 it = db.set(4, std::string("foo")); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Same as before, but the value being set is of the same type as that of // the following block. @@ -364,10 +364,10 @@ doubles.resize(5, 2.1); db.set(5, doubles.begin(), doubles.end()); // numeric at 5 thru 9 it = db.set(4, 4.5); // same type as the following block. - assert(it->size == 6); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the bottom of the last non-empty block. db = mtv_type(10, false); @@ -375,10 +375,10 @@ doubles.resize(4, 3.1); db.set(6, doubles.begin(), doubles.end()); // numeric at 6 thru 9 it = db.set(9, true); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the bottom of an non-empty block followed by an empty block. db = mtv_type(10, false); @@ -387,30 +387,30 @@ db.set(2, doubles.begin(), doubles.end()); // numeric at 2 thru 4. db.set_empty(5, 9); it = db.set(4, std::string("foo")); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); - assert(it->position == 4); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 2); ++it; - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Same as before, except the following block isn't empty but of different type. db = mtv_type(10, false); db.set(4, doubles.begin(), doubles.end()); // numeric at 4 thru 6. it = db.set(6, std::string("foo")); // 7 thru 9 is boolean. - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); - assert(it->position == 6); - assert(it->__private_data.block_index == 2); - ++it; - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->position == 7); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->position == 6); + TEST_ASSERT(it->__private_data.block_index == 2); + ++it; + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->position == 7); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Same as before, except the following block is now of the same type. db = mtv_type(10, false); @@ -420,42 +420,42 @@ // Set value to the only block (non-empty) of size 1. db = mtv_type(1, true); it = db.set(0, 1.1); - assert(it == db.begin()); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); // Set value to the topmost non-empty block of size 1, followed by an empty block. db.resize(5); it = db.set(0, std::string("foo")); - assert(it == db.begin()); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); ++it; - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the topmost non-empty block of size 1, followed by a non-empty block. db = mtv_type(5, true); db.set(0, 1.1); it = db.set(0, std::string("foo")); - assert(it == db.begin()); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); ++it; - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // This time set value whose type is the same as that of the following block. it = db.set(0, false); - assert(it == db.begin()); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Set value to the topmost non-empty block of size 1, preceded by an empty block. db = mtv_type(5); @@ -463,11 +463,11 @@ it = db.set(4, 1.2); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // This time the preceding block is not empty, but of different type. db = mtv_type(5, false); @@ -476,35 +476,35 @@ it = db.set(4, 1.2); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); it = db.set(4, true); // Now set value whose type is the same as that of the preceding block. check = db.end(); --check; - assert(it == check); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); --it; - assert(it == db.begin()); + TEST_ASSERT(it == db.begin()); // Set value to a non-empty block of size 1 that lies between existing blocks. db = mtv_type(10); db.set(7, true); it = db.set(7, 1.1); // Both preceding and following blocks are empty. - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10, true); doubles.clear(); @@ -514,54 +514,54 @@ it = db.set(6, std::string("foo")); // Both preceding and following blocks are non-empty. check = db.end(); std::advance(check, -2); - assert(it == check); + TEST_ASSERT(it == check); --it; - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_double); - assert(it->position == 2); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->position == 2); --it; - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->position == 0); - assert(it == db.begin()); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it == db.begin()); it = db.set(6, 4.5); // Same type as those of the preceding and following blocks. - assert(it->size == 8); - assert(it->type == mdds::mtv::element_type_double); - assert(it->position == 2); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it->size == 8); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->position == 2); + TEST_ASSERT(it->__private_data.block_index == 1); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10, true); db.set(4, static_cast(34)); doubles.resize(5, 2.3); db.set(5, doubles.begin(), doubles.end()); it = db.set(4, false); // Same type as that of the preceding block. - assert(it == db.begin()); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db.set(4, static_cast(35)); // Reset to previous state. it = db.set(4, 4.5); // Same type as that of the following block. - assert(it->size == 6); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db.set(4, static_cast(36)); // Reset again. it = db.set(4, static_cast(28)); // Different type from either of the blocks. - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_int16); - assert(it->position == 4); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_int16); + TEST_ASSERT(it->position == 4); + TEST_ASSERT(it->__private_data.block_index == 1); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Preceding block is empty, and the following block is non-empty. db = mtv_type(10); @@ -571,47 +571,47 @@ it = db.set(6, std::string("foo")); // Type different from that of the following block. check = db.begin(); ++check; - assert(it == check); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); - assert(it->position == 6); - ++it; - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_double); - assert(it->position == 7); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->position == 6); + ++it; + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->position == 7); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db.set(6, static_cast(24)); // Reset. it = db.set(6, 4.5); // This time the same type as that of the following block. check = db.begin(); ++check; - assert(it == check); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Now, the preceding block is not empty while the following block is. db = mtv_type(10, static_cast(10)); db.set_empty(4, 6); db.set(3, 1.2); it = db.set(3, static_cast(11)); // Same as the previous block. - assert(it == db.begin()); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_uint16); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_uint16); std::advance(it, 3); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db.set(3, 1.3); // Reset it = db.set(3, std::string("foo")); // This time, different from the previous block. check = db.begin(); ++check; - assert(it == check); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); std::advance(it, 3); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } /** @@ -619,7 +619,8 @@ */ void mtv_test_iterators_set_2() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type::iterator it, check; std::vector doubles(3, 1.1); std::deque bools; @@ -632,9 +633,9 @@ it = db.set(2, doubles.begin(), doubles.end()); check = db.begin(); std::advance(check, 2); - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert and merge with previous block. db = mtv_type(10, true); @@ -644,11 +645,11 @@ db.set(8, std::string("foo")); bools.resize(3, false); it = db.set(5, bools.begin(), bools.end()); - assert(it == db.begin()); - assert(it->size == 8); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 8); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); std::advance(it, 3); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert and merge with previous and next blocks. db = mtv_type(10, true); @@ -657,14 +658,14 @@ db.set(6, 1.2); db.set(7, 1.3); it = db.set(5, bools.begin(), bools.end()); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 9); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 9); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Insert and merge with next block only. db = mtv_type(10); // start empty. @@ -678,11 +679,11 @@ it = db.set(4, doubles.begin(), doubles.end()); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 6); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Replace the upper part of a block and merge with previous block. db = mtv_type(10, false); @@ -693,11 +694,11 @@ db.set(7, 1.6); bools.resize(3, true); it = db.set(3, bools.begin(), bools.end()); - assert(it == db.begin()); - assert(it->size == 6); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->size == 6); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); std::advance(it, 3); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Replace the upper part of a block but don't merge with previous block. db = mtv_type(10, false); @@ -710,17 +711,17 @@ it = db.set(3, doubles.begin(), doubles.end()); check = db.begin(); ++check; - assert(it == check); - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); ++it; - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Overwrite the lower part of a block and merge it with the next block. db = mtv_type(10, false); @@ -728,16 +729,16 @@ db.set(4, 1.1); db.set(5, 1.2); db.set(6, 1.3); - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); bools.resize(2, true); it = db.set(5, bools.begin(), bools.end()); // 5 to 6 check = db.begin(); std::advance(check, 3); - assert(it == check); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Overwrite the lower part of a block but don't merge it with the next block. db = mtv_type(10, std::string("boo")); @@ -749,11 +750,11 @@ it = db.set(6, doubles.begin(), doubles.end()); check = db.begin(); std::advance(check, 3); - assert(it == check); - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Overwrite the lower part of the last block. db = mtv_type(10, std::string("boo")); @@ -762,11 +763,11 @@ it = db.set(7, doubles.begin(), doubles.end()); check = db.begin(); std::advance(check, 2); - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_double); - assert(it == db.end()); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it == db.end()); // Overwrite the middle part of a block. db = mtv_type(10); @@ -774,11 +775,11 @@ it = db.set(3, bools.begin(), bools.end()); check = db.begin(); ++check; - assert(check == it); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check == it); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Overwrite multiple blocks with values whose type matches that of the top block. int32_t int_val = 255; @@ -787,32 +788,32 @@ db.set(4, bools.begin(), bools.end()); // set 4 thru 9 to bool. db.set(5, 1.1); db.set(7, std::string("foo")); - assert(db.block_size() == 6); + TEST_ASSERT(db.block_size() == 6); doubles.resize(4, 4.5); it = db.set(5, doubles.begin(), doubles.end()); // 5 thrugh 8. check = db.begin(); - assert(check->type == mdds::mtv::element_type_int32); + TEST_ASSERT(check->type == mdds::mtv::element_type_int32); ++check; - assert(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 4); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // The same scenario, except that the values also match that of the bottom block. db = mtv_type(10, 1.1); db.set(5, true); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); doubles.resize(3, 2.3); it = db.set(4, doubles.begin(), doubles.end()); - assert(db.block_size() == 1); - assert(it == db.begin()); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 10); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(it == db.begin()); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 10); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // This time, the top block is of different type. db = mtv_type(10, false); @@ -822,19 +823,19 @@ strings.resize(4, std::string("test")); it = db.set(4, strings.begin(), strings.end()); // Overwrite the lower part of the top block. check = db.begin(); - assert(check->type == mdds::mtv::element_type_int32); + TEST_ASSERT(check->type == mdds::mtv::element_type_int32); ++check; - assert(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); ++check; - assert(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10, false); db.set(0, 1.1); @@ -845,18 +846,18 @@ doubles.resize(3, 0.8); it = db.set(6, doubles.begin(), doubles.end()); // Merge with the upper block. check = db.begin(); - assert(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); ++check; - assert(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 5); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 5); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Make sure this also works in scenarios where the values merge with lower block. db = mtv_type(20, false); @@ -869,21 +870,21 @@ it = db.set(7, strings.begin(), strings.end()); // 7 thru 12 // At this point, 7 thru 15 should be strings. - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 9); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 9); check = db.begin(); - assert(check->type == mdds::mtv::element_type_boolean); - assert(check->size == 5); // 0 thru 4 + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->size == 5); // 0 thru 4 ++check; - assert(check->type == mdds::mtv::element_type_double); - assert(check->size == 2); // 5 thru 6 + TEST_ASSERT(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->size == 2); // 5 thru 6 ++check; - assert(it == check); + TEST_ASSERT(it == check); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 4); // 16 thru 19 + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 4); // 16 thru 19 ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/iterators_set_empty.inl mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set_empty.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/iterators_set_empty.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/iterators_set_empty.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_iterators_set_empty() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type::iterator it, check; // Block is already empty. Calling the method does not do anything. @@ -37,7 +38,7 @@ it = db.set_empty(6, 8); check = db.begin(); ++check; - assert(it == check); + TEST_ASSERT(it == check); // Empty a whole block. db = mtv_type(10, false); @@ -46,11 +47,11 @@ it = db.set_empty(2, 9); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 8); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 8); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Empty the upper part of a block. std::vector shorts(8, 23); @@ -58,41 +59,41 @@ it = db.set_empty(2, 6); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 5); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 5); ++it; - assert(it->type == mdds::mtv::element_type_int16); - assert(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_int16); + TEST_ASSERT(it->size == 3); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Empty the lower part of a block. db = mtv_type(10, std::string("foo")); it = db.set_empty(3, 9); check = db.begin(); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 7); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 7); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Empty the middle part of a block. db = mtv_type(10, std::string("baa")); it = db.set_empty(3, 6); check = db.begin(); - assert(check->type == mdds::mtv::element_type_string); - assert(check->size == 3); + TEST_ASSERT(check->type == mdds::mtv::element_type_string); + TEST_ASSERT(check->size == 3); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_string); - assert(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->size == 3); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Empty multiple blocks. The first block is partially emptied. db = mtv_type(10, false); @@ -101,23 +102,23 @@ db.set(4, shorts.begin(), shorts.end()); // 4 thru 6 it = db.set_empty(5, 8); check = db.begin(); - assert(check->type == mdds::mtv::element_type_double); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->size == 1); ++check; - assert(check->type == mdds::mtv::element_type_boolean); - assert(check->size == 3); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->size == 3); ++check; - assert(check->type == mdds::mtv::element_type_int16); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_int16); + TEST_ASSERT(check->size == 1); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // This time, the first block is completely emptied. db = mtv_type(10, false); @@ -126,20 +127,20 @@ db.set(4, shorts.begin(), shorts.end()); // 4 thru 6 it = db.set_empty(4, 7); check = db.begin(); - assert(check->type == mdds::mtv::element_type_double); - assert(check->size == 1); + TEST_ASSERT(check->type == mdds::mtv::element_type_double); + TEST_ASSERT(check->size == 1); ++check; - assert(check->type == mdds::mtv::element_type_boolean); - assert(check->size == 3); + TEST_ASSERT(check->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(check->size == 3); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 4); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 4); ++it; - assert(it->type == mdds::mtv::element_type_boolean); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // And this time, the first block is partially emptied but it's already an // empty block to begin with. @@ -150,14 +151,14 @@ it = db.set_empty(3, 7); check = db.begin(); ++check; - assert(it == check); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 7); + TEST_ASSERT(it == check); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 7); ++it; - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 2); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10); db.set(0, true); @@ -165,51 +166,51 @@ it = db.set_empty(5, 5); // Merge with previous and next blocks. check = db.begin(); ++check; - assert(it == check); - assert(it->size == 9); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 9); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); doubles.resize(3, 32.3); db.set(4, doubles.begin(), doubles.end()); // 4 thru 6 - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); it = db.set_empty(4, 5); // Merge with the previous block. check = db.begin(); ++check; - assert(it == check); - assert(it->size == 5); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 5); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); ++it; - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it->size == 3); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); db = mtv_type(10); db.set(9, false); db.set(3, 1.1); db.set(4, 1.2); db.set(5, 1.3); - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); it = db.set_empty(5, 5); // Merge with the next empty block. - assert(db.block_size() == 4); + TEST_ASSERT(db.block_size() == 4); check = db.begin(); std::advance(check, 2); - assert(it == check); - assert(it->size == 4); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->__private_data.block_index == 2); - assert(it->position == 5); + TEST_ASSERT(it == check); + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->__private_data.block_index == 2); + TEST_ASSERT(it->position == 5); std::advance(it, 2); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/misc.inl mdds-3.1.0/test/multi_type_vector/default/tc/misc.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/misc.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/misc.inl 2025-07-03 16:15:17.000000000 +0000 @@ -62,74 +62,75 @@ void mtv_test_misc_types() { - // Test function overloading of standard types. + MDDS_TEST_FUNC_SCOPE; - stack_printer __stack_printer__(__FUNCTION__); + // Test function overloading of standard types. { bool val = false; - assert(test_type(val) == _mtv_bool); + TEST_ASSERT(test_type(val) == _mtv_bool); cout << "bool is good" << endl; } { int16_t val = 0; - assert(test_type(val) == _mtv_int16); + TEST_ASSERT(test_type(val) == _mtv_int16); cout << "int16 is good" << endl; } { uint16_t val = 0; - assert(test_type(val) == _mtv_uint16); + TEST_ASSERT(test_type(val) == _mtv_uint16); cout << "uint16 is good" << endl; } { int32_t val = 0; - assert(test_type(val) == _mtv_int32); + TEST_ASSERT(test_type(val) == _mtv_int32); cout << "int32 is good" << endl; } { uint32_t val = 0; - assert(test_type(val) == _mtv_uint32); + TEST_ASSERT(test_type(val) == _mtv_uint32); cout << "uint32 is good" << endl; } { int64_t val = 0; - assert(test_type(val) == _mtv_int64); + TEST_ASSERT(test_type(val) == _mtv_int64); cout << "int64 is good" << endl; } { uint64_t val = 0; - assert(test_type(val) == _mtv_uint64); + TEST_ASSERT(test_type(val) == _mtv_uint64); cout << "uint64 is good" << endl; } { float val = 0; - assert(test_type(val) == _mtv_float); + TEST_ASSERT(test_type(val) == _mtv_float); cout << "float is good" << endl; } { double val = 0; - assert(test_type(val) == _mtv_double); + TEST_ASSERT(test_type(val) == _mtv_double); cout << "double is good" << endl; } { std::string val; - assert(test_type(val) == _mtv_string); + TEST_ASSERT(test_type(val) == _mtv_string); cout << "string is good" << endl; } { int8_t val = 0; - assert(test_type(val) == _mtv_int8); + TEST_ASSERT(test_type(val) == _mtv_int8); cout << "int8 is good" << endl; } { uint8_t val = 0; - assert(test_type(val) == _mtv_uint8); + TEST_ASSERT(test_type(val) == _mtv_uint8); cout << "uint8 is good" << endl; } } void mtv_test_misc_swap() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db1(3), db2(5); db1.set(0, 1.0); db1.set(1, 2.0); @@ -140,39 +141,41 @@ db2.set(4, std::string("foo")); db1.swap(db2); - assert(db1.size() == 5 && db1.block_size() == 3); - assert(db2.size() == 3 && db2.block_size() == 1); + TEST_ASSERT(db1.size() == 5 && db1.block_size() == 3); + TEST_ASSERT(db2.size() == 3 && db2.block_size() == 1); } void mtv_test_misc_equality() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + + // Test function overloading of standard types. { // Two columns of equal size. mtv_type db1(3), db2(3); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.set(0, 1.0); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db2.set(0, 1.0); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db2.set(0, 1.2); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.set(0, 1.2); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); } { // Two columns of different sizes. They are always non-equal no // matter what. mtv_type db1(3), db2(4); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.set(0, 1.2); db2.set(0, 1.2); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); // Comparison to self. - assert(db1 == db1); - assert(db2 == db2); + TEST_ASSERT(db1 == db1); + TEST_ASSERT(db2 == db2); } { @@ -188,29 +191,30 @@ db2.set(3, 2.1); db2.set(4, 2.3); // different value - assert(db1 != db2); + TEST_ASSERT(db1 != db2); } { mtv_type db1(2), db2(2); db1.set(1, 10.1); db2.set(1, 10.1); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db2.set(0, std::string("foo")); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.set(0, std::string("foo")); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db2.set_empty(0, 0); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); } } void mtv_test_misc_clone() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db1(3); db1.set(0, 3.4); db1.set(1, std::string("foo")); @@ -219,106 +223,107 @@ // copy construction mtv_type db2(db1); - assert(db1.size() == db2.size()); - assert(db1.block_size() == db2.block_size()); - assert(db1 == db2); + TEST_ASSERT(db1.size() == db2.size()); + TEST_ASSERT(db1.block_size() == db2.block_size()); + TEST_ASSERT(db1 == db2); { double test1, test2; db1.get(0, test1); db2.get(0, test2); - assert(test1 == test2); + TEST_ASSERT(test1 == test2); } { std::string test1, test2; db1.get(1, test1); db2.get(1, test2); - assert(test1 == test2); + TEST_ASSERT(test1 == test2); } { bool test1, test2; db1.get(2, test1); db2.get(2, test2); - assert(test1 == test2); + TEST_ASSERT(test1 == test2); } // assignment mtv_type db3 = db1; - assert(db3 == db1); + TEST_ASSERT(db3 == db1); db3.set(0, std::string("alpha")); - assert(db3 != db1); + TEST_ASSERT(db3 != db1); mtv_type db4, db5; db4 = db5 = db3; - assert(db4 == db5); - assert(db3 == db5); - assert(db3 == db4); + TEST_ASSERT(db4 == db5); + TEST_ASSERT(db3 == db5); + TEST_ASSERT(db3 == db4); } void mtv_test_misc_resize() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(0); - assert(db.size() == 0); - assert(db.empty()); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.empty()); // Resize to create initial empty block. db.resize(3); - assert(db.size() == 3); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 1); // Resize to increase the existing empty block. db.resize(5); - assert(db.size() == 5); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); for (long row = 0; row < 5; ++row) db.set(row, static_cast(row)); - assert(db.size() == 5); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); // Increase its size by one. This should append an empty cell block of size one. db.resize(6); - assert(db.size() == 6); - assert(db.block_size() == 2); - assert(db.is_empty(5)); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.is_empty(5)); // Do it again. db.resize(7); - assert(db.size() == 7); - assert(db.block_size() == 2); + TEST_ASSERT(db.size() == 7); + TEST_ASSERT(db.block_size() == 2); // Now, reduce its size to eliminate the last empty block. db.resize(5); - assert(db.size() == 5); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); // Reset. db.resize(7); - assert(db.size() == 7); - assert(db.block_size() == 2); + TEST_ASSERT(db.size() == 7); + TEST_ASSERT(db.block_size() == 2); // Now, resize across multiple blocks. db.resize(4); - assert(db.size() == 4); - assert(db.block_size() == 1); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.block_size() == 1); double test; db.get(3, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); // Empty it. db.resize(0); - assert(db.size() == 0); - assert(db.block_size() == 0); - assert(db.empty()); + TEST_ASSERT(db.size() == 0); + TEST_ASSERT(db.block_size() == 0); + TEST_ASSERT(db.empty()); } void mtv_test_misc_value_type() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db(5); db.set(0, 1.1); @@ -334,165 +339,167 @@ void mtv_test_misc_block_identifier() { - stack_printer __stack_printer__(__FUNCTION__); - assert(mdds::mtv::double_element_block::block_type == mdds::mtv::element_type_double); - assert(mdds::mtv::string_element_block::block_type == mdds::mtv::element_type_string); - assert(mdds::mtv::int16_element_block::block_type == mdds::mtv::element_type_int16); - assert(mdds::mtv::uint16_element_block::block_type == mdds::mtv::element_type_uint16); - assert(mdds::mtv::int32_element_block::block_type == mdds::mtv::element_type_int32); - assert(mdds::mtv::uint32_element_block::block_type == mdds::mtv::element_type_uint32); - assert(mdds::mtv::int64_element_block::block_type == mdds::mtv::element_type_int64); - assert(mdds::mtv::uint64_element_block::block_type == mdds::mtv::element_type_uint64); - assert(mdds::mtv::boolean_element_block::block_type == mdds::mtv::element_type_boolean); - assert(mdds::mtv::int8_element_block::block_type == mdds::mtv::element_type_int8); - assert(mdds::mtv::uint8_element_block::block_type == mdds::mtv::element_type_uint8); + MDDS_TEST_FUNC_SCOPE; + + TEST_ASSERT(mdds::mtv::double_element_block::block_type == mdds::mtv::element_type_double); + TEST_ASSERT(mdds::mtv::string_element_block::block_type == mdds::mtv::element_type_string); + TEST_ASSERT(mdds::mtv::int16_element_block::block_type == mdds::mtv::element_type_int16); + TEST_ASSERT(mdds::mtv::uint16_element_block::block_type == mdds::mtv::element_type_uint16); + TEST_ASSERT(mdds::mtv::int32_element_block::block_type == mdds::mtv::element_type_int32); + TEST_ASSERT(mdds::mtv::uint32_element_block::block_type == mdds::mtv::element_type_uint32); + TEST_ASSERT(mdds::mtv::int64_element_block::block_type == mdds::mtv::element_type_int64); + TEST_ASSERT(mdds::mtv::uint64_element_block::block_type == mdds::mtv::element_type_uint64); + TEST_ASSERT(mdds::mtv::boolean_element_block::block_type == mdds::mtv::element_type_boolean); + TEST_ASSERT(mdds::mtv::int8_element_block::block_type == mdds::mtv::element_type_int8); + TEST_ASSERT(mdds::mtv::uint8_element_block::block_type == mdds::mtv::element_type_uint8); } void mtv_test_misc_push_back() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db; - assert(db.size() == 0); - assert(db.block_size() == 0); + TEST_ASSERT(db.size() == 0); + TEST_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 == mdds::mtv::element_type_empty); - assert(it->__private_data.block_index == 0); - assert(it == db.begin()); + TEST_ASSERT(db.size() == 1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); ++it; - assert(it == db.end()); + TEST_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 == mdds::mtv::element_type_empty); - assert(it->__private_data.block_index == 0); - assert(it == db.begin()); + TEST_ASSERT(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); ++it; - assert(it == db.end()); + TEST_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 == mdds::mtv::element_type_double); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->__private_data.block_index == 1); mtv_type::iterator check = it; --check; - assert(check == db.begin()); + TEST_ASSERT(check == db.begin()); ++it; - assert(it == db.end()); + TEST_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 == mdds::mtv::element_type_empty); - assert(it->__private_data.block_index == 2); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->__private_data.block_index == 2); check = it; --check; --check; - assert(check == db.begin()); + TEST_ASSERT(check == db.begin()); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); // Check the values. - assert(db.is_empty(0)); - assert(db.is_empty(1)); - assert(db.get(2) == 1.1); - assert(db.is_empty(3)); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.is_empty(1)); + TEST_ASSERT(db.get(2) == 1.1); + TEST_ASSERT(db.is_empty(3)); // Empty the container and push back a non-empty element. db.clear(); it = db.push_back(std::string("push me")); - assert(db.size() == 1); - assert(db.block_size() == 1); - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_string); - assert(it->__private_data.block_index == 0); - assert(it == db.begin()); + TEST_ASSERT(db.size() == 1); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); ++it; - assert(it == db.end()); - assert(db.get(0) == "push me"); + TEST_ASSERT(it == db.end()); + TEST_ASSERT(db.get(0) == "push me"); // Push back a non-empty element of the same type. it = db.push_back(std::string("again")); - assert(db.size() == 2); - assert(db.block_size() == 1); - assert(it->size == 2); - assert(it->type == mdds::mtv::element_type_string); - assert(it->__private_data.block_index == 0); - assert(it == db.begin()); + TEST_ASSERT(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_string); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it == db.begin()); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); - assert(db.get(0) == "push me"); - assert(db.get(1) == "again"); + TEST_ASSERT(db.get(0) == "push me"); + TEST_ASSERT(db.get(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 == mdds::mtv::element_type_double); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); } void mtv_test_misc_capacity() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(10, 1.1); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); mtv_type::const_iterator it = db.begin(); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); size_t cap = mdds::mtv::double_element_block::capacity(*it->data); - assert(cap == 10); + TEST_ASSERT(cap == 10); db.set_empty(3, 3); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); db.shrink_to_fit(); it = db.begin(); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); cap = mdds::mtv::double_element_block::capacity(*it->data); - assert(cap == 3); + TEST_ASSERT(cap == 3); } void mtv_test_misc_position_type_end_position() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; auto run = [](auto& db) { auto pos1 = db.position(9); // last valid position. pos1 = mtv_type::next_position(pos1); auto pos2 = db.position(10); // end position - one position past the last valid position - assert(pos1 == pos2); + TEST_ASSERT(pos1 == pos2); // Move back from the end position by one. It should point to the last // valid position. pos2 = mtv_type::advance_position(pos2, -1); pos1 = db.position(9); - assert(pos1 == pos2); + TEST_ASSERT(pos1 == pos2); // Try the variant of position() method that takes position hint as its first argument. pos1 = db.position(db.begin(), 10); pos1 = mtv_type::advance_position(pos1, -10); pos2 = db.position(0); - assert(pos1 == pos2); + TEST_ASSERT(pos1 == pos2); // A position more than one past the last valid position is considered out-of-range. try { pos1 = db.position(11); - assert(!"No exceptions thrown, but one was expected to be thrown."); + TEST_ASSERT(!"No exceptions thrown, but one was expected to be thrown."); } catch (const std::out_of_range&) { @@ -501,7 +508,7 @@ } catch (...) { - assert(!"An unexpected exception was thrown."); + TEST_ASSERT(!"An unexpected exception was thrown."); } // Try again with the variant that takes a position hint. @@ -509,7 +516,7 @@ try { pos1 = db.position(db.begin(), 11); - assert(!"No exceptions thrown, but one was expected to be thrown."); + TEST_ASSERT(!"No exceptions thrown, but one was expected to be thrown."); } catch (const std::out_of_range&) { @@ -518,7 +525,7 @@ } catch (...) { - assert(!"An unexpected exception was thrown."); + TEST_ASSERT(!"An unexpected exception was thrown."); } }; @@ -536,7 +543,7 @@ */ void mtv_test_misc_block_pos_adjustments() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db(1); @@ -549,8 +556,8 @@ db.insert(0, is.begin(), is.end()); } - assert(db.size() == 81); - assert(db.block_size() == 41); + TEST_ASSERT(db.size() == 81); + TEST_ASSERT(db.block_size() == 41); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/position.inl mdds-3.1.0/test/multi_type_vector/default/tc/position.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/position.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/position.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_position() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(10, false); mtv_type::iterator check; mtv_type::const_iterator const_check; @@ -38,16 +39,16 @@ db.set(9, 1.4); mtv_type::position_type pos = db.position(0); - assert(pos.first == db.begin()); - assert(pos.second == 0); + TEST_ASSERT(pos.first == db.begin()); + TEST_ASSERT(pos.second == 0); pos = db.position(1); - assert(pos.first == db.begin()); - assert(pos.second == 1); + TEST_ASSERT(pos.first == db.begin()); + TEST_ASSERT(pos.second == 1); pos = db.position(5); - assert(pos.first == db.begin()); - assert(pos.second == 5); + TEST_ASSERT(pos.first == db.begin()); + TEST_ASSERT(pos.second == 5); check = db.begin(); ++check; @@ -55,61 +56,62 @@ // These positions should be on the 2nd block. pos = db.position(6); - assert(pos.first == check); - assert(pos.second == 0); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 0); pos = db.position(7); - assert(pos.first == check); - assert(pos.second == 1); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 1); pos = db.position(9); - assert(pos.first == check); - assert(pos.second == 3); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 3); { // Make sure you get the right element. mtv_type::iterator it = pos.first; - assert(it->type == mdds::mtv::element_type_double); - assert(it->data); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->data); mdds::mtv::double_element_block::iterator it_elem = mdds::mtv::double_element_block::begin(*it->data); advance(it_elem, pos.second); - assert(*it_elem == 1.4); + TEST_ASSERT(*it_elem == 1.4); } // Quick check for the const variant. const mtv_type& db_ref = db; mtv_type::const_position_type const_pos = db_ref.position(3); - assert(const_pos.first == db_ref.begin()); - assert(const_pos.second == 3); + TEST_ASSERT(const_pos.first == db_ref.begin()); + TEST_ASSERT(const_pos.second == 3); const_pos = db_ref.position(const_pos.first, 7); const_check = db_ref.begin(); ++const_check; - assert(const_pos.first == const_check); - assert(const_pos.second == 1); + TEST_ASSERT(const_pos.first == const_check); + TEST_ASSERT(const_pos.second == 1); // Check for the variant that takes position hint. pos = db.position(0); - assert(pos.first == db.begin()); - assert(pos.second == 0); + TEST_ASSERT(pos.first == db.begin()); + TEST_ASSERT(pos.second == 0); pos = db.position(pos.first, 6); check = db.begin(); ++check; - assert(pos.first == check); - assert(pos.second == 0); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 0); pos = db.position(pos.first, 7); - assert(pos.first == check); - assert(pos.second == 1); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 1); pos = db.position(pos.first, 9); - assert(pos.first == check); - assert(pos.second == 3); + TEST_ASSERT(pos.first == check); + TEST_ASSERT(pos.second == 3); } void mtv_test_position_next() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(10); db.set(2, 1.1); db.set(3, 1.2); @@ -120,59 +122,60 @@ db.set(8, false); mtv_type::position_type pos = db.position(0); - assert(mtv_type::logical_position(pos) == 0); - assert(pos.first->type == mdds::mtv::element_type_empty); + TEST_ASSERT(mtv_type::logical_position(pos) == 0); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_empty); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 1); - assert(pos.first->type == mdds::mtv::element_type_empty); + TEST_ASSERT(mtv_type::logical_position(pos) == 1); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_empty); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 2); - assert(pos.first->type == mdds::mtv::element_type_double); - assert(mtv_type::get(pos) == 1.1); + TEST_ASSERT(mtv_type::logical_position(pos) == 2); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_double); + TEST_ASSERT(mtv_type::get(pos) == 1.1); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 3); - assert(pos.first->type == mdds::mtv::element_type_double); - assert(mtv_type::get(pos) == 1.2); + TEST_ASSERT(mtv_type::logical_position(pos) == 3); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_double); + TEST_ASSERT(mtv_type::get(pos) == 1.2); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 4); - assert(pos.first->type == mdds::mtv::element_type_string); - assert(mtv_type::get(pos) == "A"); + TEST_ASSERT(mtv_type::logical_position(pos) == 4); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_string); + TEST_ASSERT(mtv_type::get(pos) == "A"); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 5); - assert(pos.first->type == mdds::mtv::element_type_string); - assert(mtv_type::get(pos) == "B"); + TEST_ASSERT(mtv_type::logical_position(pos) == 5); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_string); + TEST_ASSERT(mtv_type::get(pos) == "B"); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 6); - assert(pos.first->type == mdds::mtv::element_type_string); - assert(mtv_type::get(pos) == "C"); + TEST_ASSERT(mtv_type::logical_position(pos) == 6); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_string); + TEST_ASSERT(mtv_type::get(pos) == "C"); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 7); - assert(pos.first->type == mdds::mtv::element_type_boolean); - assert(mtv_type::get(pos) == true); + TEST_ASSERT(mtv_type::logical_position(pos) == 7); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(mtv_type::get(pos) == true); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 8); - assert(pos.first->type == mdds::mtv::element_type_boolean); - assert(mtv_type::get(pos) == false); + TEST_ASSERT(mtv_type::logical_position(pos) == 8); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_boolean); + TEST_ASSERT(mtv_type::get(pos) == false); pos = mtv_type::next_position(pos); - assert(mtv_type::logical_position(pos) == 9); - assert(pos.first->type == mdds::mtv::element_type_empty); + TEST_ASSERT(mtv_type::logical_position(pos) == 9); + TEST_ASSERT(pos.first->type == mdds::mtv::element_type_empty); pos = mtv_type::next_position(pos); - assert(pos.first == db.end()); + TEST_ASSERT(pos.first == db.end()); } void mtv_test_position_advance() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db(10); db.set(2, 1.1); db.set(3, 1.2); @@ -181,22 +184,22 @@ db.set(6, std::string("C")); mtv_type::position_type pos = db.position(0); - assert(mtv_type::logical_position(pos) == 0); + TEST_ASSERT(mtv_type::logical_position(pos) == 0); pos = mtv_type::advance_position(pos, 4); - assert(mtv_type::logical_position(pos) == 4); + TEST_ASSERT(mtv_type::logical_position(pos) == 4); pos = mtv_type::advance_position(pos, 5); - assert(mtv_type::logical_position(pos) == 9); + TEST_ASSERT(mtv_type::logical_position(pos) == 9); pos = mtv_type::advance_position(pos, -3); - assert(mtv_type::logical_position(pos) == 6); + TEST_ASSERT(mtv_type::logical_position(pos) == 6); pos = mtv_type::advance_position(pos, -6); - assert(mtv_type::logical_position(pos) == 0); + TEST_ASSERT(mtv_type::logical_position(pos) == 0); pos = mtv_type::advance_position(pos, 10); - assert(pos.first == db.end()); + TEST_ASSERT(pos.first == db.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/set.inl mdds-3.1.0/test/multi_type_vector/default/tc/set.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/set.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/set.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_set_cells() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + { mtv_type db(5); @@ -44,9 +45,9 @@ double test; db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); db.get(4, test); - assert(test == 5.0); + TEST_ASSERT(test == 5.0); } { @@ -63,9 +64,9 @@ std::string test; db.get(0, test); - assert(test == "1"); + TEST_ASSERT(test == "1"); db.get(4, test); - assert(test == "5"); + TEST_ASSERT(test == "5"); } { @@ -75,9 +76,9 @@ db.set(0, p, p_end); double test; db.get(0, test); - assert(test == 5.0); + TEST_ASSERT(test == 5.0); db.get(4, test); - assert(test == 9.0); + TEST_ASSERT(test == 9.0); } { @@ -89,18 +90,18 @@ db.set(0, p, p_end); double test; db.get(0, test); - assert(test == 5.1); + TEST_ASSERT(test == 5.1); db.get(4, test); - assert(test == 9.1); + TEST_ASSERT(test == 9.1); double vals2[] = {8.2, 9.2}; p = &vals2[0]; p_end = p + 2; db.set(3, p, p_end); db.get(3, test); - assert(test == 8.2); + TEST_ASSERT(test == 8.2); db.get(4, test); - assert(test == 9.2); + TEST_ASSERT(test == 9.2); } { @@ -109,16 +110,16 @@ uint64_t* p = &vals[0]; uint64_t* p_end = p + 3; db.set(0, p, p_end); - assert(db.block_size() == 2); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); uint64_t test; db.get(0, test); - assert(test == 1); + TEST_ASSERT(test == 1); db.get(2, test); - assert(test == 3); + TEST_ASSERT(test == 3); double test2; db.get(3, test2); - assert(test2 == 8.2); + TEST_ASSERT(test2 == 8.2); } { @@ -127,13 +128,13 @@ uint64_t* p = &vals[0]; uint64_t* p_end = p + 2; db.set(3, p, p_end); - assert(db.block_size() == 1); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); uint64_t test; db.get(2, test); - assert(test == 3); + TEST_ASSERT(test == 3); db.get(3, test); - assert(test == 4); + TEST_ASSERT(test == 4); } { @@ -144,24 +145,24 @@ double val = 2.3; db.set(0, val); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); val = 4.5; double* p = &val; double* p_end = p + 1; db.set(1, p, p_end); - assert(db.block_size() == 2); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); { double test; db.get(0, test); - assert(test == 2.3); + TEST_ASSERT(test == 2.3); db.get(1, test); - assert(test == 4.5); + TEST_ASSERT(test == 4.5); } uint64_t test; db.get(2, test); - assert(test == prev_value); + TEST_ASSERT(test == prev_value); } } @@ -170,8 +171,8 @@ for (size_t i = 0; i < 5; ++i) db.set(i, static_cast(i + 1)); - assert(db.block_size() == 1); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); { uint64_t vals[] = {10, 11}; @@ -179,33 +180,33 @@ uint64_t* p_end = p + 2; db.set(3, p, p_end); - assert(db.block_size() == 2); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); double test; db.get(2, test); - assert(test == 3.0); + TEST_ASSERT(test == 3.0); uint64_t test2; db.get(3, test2); - assert(test2 == 10); + TEST_ASSERT(test2 == 10); db.get(4, test2); - assert(test2 == 11); + TEST_ASSERT(test2 == 11); // Insertion into a single block but this time it needs to be // merged with the subsequent block. db.set(1, p, p_end); - assert(db.block_size() == 2); - assert(db.size() == 5); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 5); db.get(1, test2); - assert(test2 == 10); + TEST_ASSERT(test2 == 10); db.get(2, test2); - assert(test2 == 11); + TEST_ASSERT(test2 == 11); db.get(3, test2); - assert(test2 == 10); + TEST_ASSERT(test2 == 10); db.get(4, test2); - assert(test2 == 11); + TEST_ASSERT(test2 == 11); } } @@ -219,43 +220,43 @@ double* p = &vals_d[0]; double* p_end = p + 6; db.set(0, p, p_end); - assert(db.block_size() == 1); - assert(db.size() == 6); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 6); double test; db.get(0, test); - assert(test == 1.0); + TEST_ASSERT(test == 1.0); db.get(5, test); - assert(test == 1.5); + TEST_ASSERT(test == 1.5); } { uint64_t* p = &vals_i[0]; uint64_t* p_end = p + 4; db.set(0, p, p_end); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); uint64_t test; db.get(0, test); - assert(test == 12); + TEST_ASSERT(test == 12); db.get(3, test); - assert(test == 15); + TEST_ASSERT(test == 15); } { std::string* p = &vals_s[0]; std::string* p_end = p + 2; db.set(2, p, p_end); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); std::string test; db.get(2, test); - assert(test == "a"); + TEST_ASSERT(test == "a"); db.get(3, test); - assert(test == "b"); + TEST_ASSERT(test == "b"); double test_d; db.get(4, test_d); - assert(test_d == 1.4); + TEST_ASSERT(test_d == 1.4); uint64_t test_i; db.get(1, test_i); - assert(test_i == 13); + TEST_ASSERT(test_i == 13); } } @@ -266,7 +267,7 @@ double* p = &vals[0]; double* p_end = p + 3; db.set(0, p, p_end); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); } { @@ -274,15 +275,15 @@ uint64_t* p = &val_i; uint64_t* p_end = p + 1; db.set(1, p, p_end); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); uint64_t test; db.get(1, test); - assert(test == 23); + TEST_ASSERT(test == 23); double test_d; db.get(0, test_d); - assert(test_d == 2.1); + TEST_ASSERT(test_d == 2.1); db.get(2, test_d); - assert(test_d == 2.3); + TEST_ASSERT(test_d == 2.3); } } @@ -292,20 +293,20 @@ mtv_type db(2); db.set(0, static_cast(1.1)); db.set(1, std::string("foo")); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); double vals[] = {2.1, 2.2}; double* p = &vals[0]; double* p_end = p + 2; db.set(0, p, p_end); - assert(db.block_size() == 1); - assert(db.size() == 2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 2); double test; db.get(0, test); - assert(test == 2.1); + TEST_ASSERT(test == 2.1); db.get(1, test); - assert(test == 2.2); + TEST_ASSERT(test == 2.2); } { @@ -320,18 +321,18 @@ double* p = &vals[0]; double* p_end = p + 2; db.set(0, p, p_end); - assert(db.block_size() == 2); - assert(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); double test_val; db.get(0, test_val); - assert(test_val == 2.1); + TEST_ASSERT(test_val == 2.1); db.get(1, test_val); - assert(test_val == 2.2); + TEST_ASSERT(test_val == 2.2); std::string test_s; db.get(2, test_s); - assert(test_s == "baa"); + TEST_ASSERT(test_s == "baa"); } { @@ -339,21 +340,21 @@ db.set(0, static_cast(3.1)); db.set(1, static_cast(3.2)); db.set(2, std::string("foo")); - assert(db.block_size() == 2); - assert(db.size() == 3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 3); double vals[] = {2.1, 2.2}; double* p = &vals[0]; double* p_end = p + 2; db.set(1, p, p_end); - assert(db.block_size() == 1); + TEST_ASSERT(db.block_size() == 1); double test; db.get(0, test); - assert(test == 3.1); + TEST_ASSERT(test == 3.1); db.get(1, test); - assert(test == 2.1); + TEST_ASSERT(test == 2.1); db.get(2, test); - assert(test == 2.2); + TEST_ASSERT(test == 2.2); } { @@ -363,19 +364,19 @@ db.set(2, std::string("foo")); db.set(3, 1.3); db.set(4, 1.4); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; double* p_end = p + 3; db.set(1, p, p_end); - assert(db.block_size() == 1); - assert(db.size() == 5); - assert(db.get(0) == 1.1); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); - assert(db.get(4) == 1.4); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 5); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); + TEST_ASSERT(db.get(4) == 1.4); } { @@ -384,16 +385,16 @@ db.set(1, std::string("B")); db.set(2, 1.1); db.set(3, 1.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); double vals[] = {2.1, 2.2, 2.3}; double* p = &vals[0]; db.set(1, p, p + 3); - assert(db.block_size() == 2); - assert(db.get(0) == std::string("A")); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 2.3); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == std::string("A")); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 2.3); } { @@ -402,16 +403,16 @@ db.set(1, std::string("B")); db.set(2, 1.1); db.set(3, 1.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); double vals[] = {2.1, 2.2}; double* p = &vals[0]; db.set(1, p, p + 2); - assert(db.block_size() == 2); - assert(db.get(0) == std::string("A")); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); - assert(db.get(3) == 1.2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == std::string("A")); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); + TEST_ASSERT(db.get(3) == 1.2); } { @@ -421,17 +422,17 @@ db.set(2, 1.1); db.set(3, 1.2); db.set(4, static_cast(12)); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); uint64_t vals[] = {21, 22, 23}; uint64_t* p = &vals[0]; db.set(1, p, p + 3); - assert(db.block_size() == 2); - assert(db.get(0) == std::string("A")); - assert(db.get(1) == 21); - assert(db.get(2) == 22); - assert(db.get(3) == 23); - assert(db.get(4) == 12); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == std::string("A")); + TEST_ASSERT(db.get(1) == 21); + TEST_ASSERT(db.get(2) == 22); + TEST_ASSERT(db.get(3) == 23); + TEST_ASSERT(db.get(4) == 12); } { @@ -439,15 +440,15 @@ db.set(0, std::string("A")); db.set(1, 1.1); db.set(2, 1.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); uint64_t vals[] = {11, 12}; uint64_t* p = &vals[0]; db.set(0, p, p + 2); - assert(db.block_size() == 2); - assert(db.get(0) == 11); - assert(db.get(1) == 12); - assert(db.get(2) == 1.2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == 11); + TEST_ASSERT(db.get(1) == 12); + TEST_ASSERT(db.get(2) == 1.2); } { @@ -456,16 +457,16 @@ db.set(1, std::string("A")); db.set(2, 1.1); db.set(3, 1.2); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); uint64_t vals[] = {11, 12}; uint64_t* p = &vals[0]; db.set(1, p, p + 2); - assert(db.block_size() == 2); - assert(db.get(0) == 35); - assert(db.get(1) == 11); - assert(db.get(2) == 12); - assert(db.get(3) == 1.2); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.get(0) == 35); + TEST_ASSERT(db.get(1) == 11); + TEST_ASSERT(db.get(2) == 12); + TEST_ASSERT(db.get(3) == 1.2); } { @@ -473,29 +474,29 @@ mtv_type db(2); db.set(1, 1.2); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); double vals[] = {2.1, 2.2}; double* p = &vals[0]; db.set(0, p, p + 2); - assert(db.block_size() == 1); - assert(db.get(0) == 2.1); - assert(db.get(1) == 2.2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == 2.1); + TEST_ASSERT(db.get(1) == 2.2); } { mtv_type db(3); db.set(0, 1.1); db.set(2, 1.2); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); double vals[] = {2.1, 2.2}; double* p = &vals[0]; db.set(1, p, p + 2); - assert(db.block_size() == 1); - assert(db.get(0) == 1.1); - assert(db.get(1) == 2.1); - assert(db.get(2) == 2.2); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 2.1); + TEST_ASSERT(db.get(2) == 2.2); } { @@ -503,18 +504,18 @@ db.set(2, std::string("A")); db.set(3, std::string("B")); db.set(4, std::string("C")); - assert(db.block_size() == 2); + TEST_ASSERT(db.block_size() == 2); double vals[] = {1.1, 1.2, 1.3}; double* p = &vals[0]; db.set(1, p, p + 3); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); - assert(db.is_empty(0)); - assert(db.get(1) == 1.1); - assert(db.get(2) == 1.2); - assert(db.get(3) == 1.3); - assert(db.get(4) == std::string("C")); + TEST_ASSERT(db.is_empty(0)); + TEST_ASSERT(db.get(1) == 1.1); + TEST_ASSERT(db.get(2) == 1.2); + TEST_ASSERT(db.get(3) == 1.3); + TEST_ASSERT(db.get(4) == std::string("C")); } { @@ -523,23 +524,23 @@ db.set(3, 1.1); db.set(4, 1.2); db.set(5, 1.3); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); // This should replace the middle numeric block and merge with the top // and bottom ones. db.set(3, bools.begin(), bools.end()); - assert(db.block_size() == 1); - assert(db.size() == 10); - assert(db.get(0) == true); - assert(db.get(1) == true); - assert(db.get(2) == true); - assert(db.get(3) == false); - assert(db.get(4) == false); - assert(db.get(5) == false); - assert(db.get(6) == true); - assert(db.get(7) == true); - assert(db.get(8) == true); - assert(db.get(9) == true); + TEST_ASSERT(db.block_size() == 1); + TEST_ASSERT(db.size() == 10); + TEST_ASSERT(db.get(0) == true); + TEST_ASSERT(db.get(1) == true); + TEST_ASSERT(db.get(2) == true); + TEST_ASSERT(db.get(3) == false); + TEST_ASSERT(db.get(4) == false); + TEST_ASSERT(db.get(5) == false); + TEST_ASSERT(db.get(6) == true); + TEST_ASSERT(db.get(7) == true); + TEST_ASSERT(db.get(8) == true); + TEST_ASSERT(db.get(9) == true); } { @@ -553,21 +554,21 @@ db.set(6, std::string("b")); db.set(7, std::string("c")); db.set(8, std::string("d")); - assert(db.block_size() == 3); + TEST_ASSERT(db.block_size() == 3); std::vector strings(3, std::string("foo")); db.set(2, strings.begin(), strings.end()); // Merge with the next block. - assert(db.block_size() == 2); - assert(db.size() == 9); - assert(db.get(0) == 1.1); - assert(db.get(1) == 1.2); - assert(db.get(2) == "foo"); - assert(db.get(3) == "foo"); - assert(db.get(4) == "foo"); - assert(db.get(5) == "a"); - assert(db.get(6) == "b"); - assert(db.get(7) == "c"); - assert(db.get(8) == "d"); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 9); + TEST_ASSERT(db.get(0) == 1.1); + TEST_ASSERT(db.get(1) == 1.2); + TEST_ASSERT(db.get(2) == "foo"); + TEST_ASSERT(db.get(3) == "foo"); + TEST_ASSERT(db.get(4) == "foo"); + TEST_ASSERT(db.get(5) == "a"); + TEST_ASSERT(db.get(6) == "b"); + TEST_ASSERT(db.get(7) == "c"); + TEST_ASSERT(db.get(8) == "d"); } { @@ -585,17 +586,17 @@ std::vector data(5, 11); db.set(2, data.begin(), data.end()); - assert(db.block_size() == 2); - assert(db.size() == 9); - assert(db.get(0) == 0); - assert(db.get(1) == 1); - assert(db.get(2) == 11); - assert(db.get(3) == 11); - assert(db.get(4) == 11); - assert(db.get(5) == 11); - assert(db.get(6) == 11); - assert(db.is_empty(7)); - assert(db.is_empty(8)); + TEST_ASSERT(db.block_size() == 2); + TEST_ASSERT(db.size() == 9); + TEST_ASSERT(db.get(0) == 0); + TEST_ASSERT(db.get(1) == 1); + TEST_ASSERT(db.get(2) == 11); + TEST_ASSERT(db.get(3) == 11); + TEST_ASSERT(db.get(4) == 11); + TEST_ASSERT(db.get(5) == 11); + TEST_ASSERT(db.get(6) == 11); + TEST_ASSERT(db.is_empty(7)); + TEST_ASSERT(db.is_empty(8)); } { @@ -613,14 +614,14 @@ std::vector data(3, 15); db.set(2, data.begin(), data.end()); - assert(db.block_size() == 3); - assert(db.size() == 6); - assert(db.get(0) == 0); - assert(db.get(1) == 1); - assert(db.get(2) == 15); - assert(db.get(3) == 15); - assert(db.get(4) == 15); - assert(db.get(5) == 21); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(db.get(0) == 0); + TEST_ASSERT(db.get(1) == 1); + TEST_ASSERT(db.get(2) == 15); + TEST_ASSERT(db.get(3) == 15); + TEST_ASSERT(db.get(4) == 15); + TEST_ASSERT(db.get(5) == 21); } { @@ -638,14 +639,14 @@ std::vector data(3, 15); db.set(1, data.begin(), data.end()); - assert(db.block_size() == 3); - assert(db.size() == 6); - assert(db.get(0) == 0); - assert(db.get(1) == 15); - assert(db.get(2) == 15); - assert(db.get(3) == 15); - assert(db.get(4) == 20); - assert(db.get(5) == 21); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(db.get(0) == 0); + TEST_ASSERT(db.get(1) == 15); + TEST_ASSERT(db.get(2) == 15); + TEST_ASSERT(db.get(3) == 15); + TEST_ASSERT(db.get(4) == 20); + TEST_ASSERT(db.get(5) == 21); } } diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/swap_range.inl mdds-3.1.0/test/multi_type_vector/default/tc/swap_range.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/swap_range.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/swap_range.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,7 +28,8 @@ void mtv_test_swap_range() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db1(10), db2(10); db1.set(2, 1.1); db1.set(3, 1.2); @@ -39,35 +40,35 @@ db2.set(4, 2.3); db1.swap(2, 4, db2, 2); - assert(db1.get(2) == 2.1); - assert(db1.get(3) == 2.2); - assert(db1.get(4) == 2.3); - assert(db2.get(2) == 1.1); - assert(db2.get(3) == 1.2); - assert(db2.get(4) == 1.3); + TEST_ASSERT(db1.get(2) == 2.1); + TEST_ASSERT(db1.get(3) == 2.2); + TEST_ASSERT(db1.get(4) == 2.3); + TEST_ASSERT(db2.get(2) == 1.1); + TEST_ASSERT(db2.get(3) == 1.2); + TEST_ASSERT(db2.get(4) == 1.3); // Source is empty but destination is not. db1 = mtv_type(3); db2 = mtv_type(3, 12.3); db1.swap(1, 2, db2, 1); - assert(db1.is_empty(0)); - assert(db1.get(1) == 12.3); - assert(db1.get(2) == 12.3); - assert(db1.block_size() == 2); - assert(db2.get(0) == 12.3); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.get(1) == 12.3); + TEST_ASSERT(db1.get(2) == 12.3); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db2.get(0) == 12.3); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.block_size() == 2); // Go to the opposite direction. db1.swap(1, 2, db2, 1); - assert(db1.block_size() == 1); + TEST_ASSERT(db1.block_size() == 1); mtv_type::iterator it = db1.begin(); - assert(it->type == mdds::mtv::element_type_empty); - assert(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 3); it = db2.begin(); - assert(it->type == mdds::mtv::element_type_double); - assert(it->size == 3); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 3); int32_t int_val = 2; int16_t short_val = 5; @@ -78,19 +79,19 @@ db2.set(3, std::string("abc")); db2.set(4, std::string("def")); db1.swap(1, 2, db2, 3); // Swap 1-2 of source with 3-4 of destination. - assert(db1.get(0) == int_val); - assert(db1.get(1) == "abc"); - assert(db1.get(2) == "def"); - assert(db1.get(3) == int_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 3); - - assert(db2.get(0) == short_val); - assert(db2.get(1) == short_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == 2.3); - assert(db2.get(4) == 2.4); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == "abc"); + TEST_ASSERT(db1.get(2) == "def"); + TEST_ASSERT(db1.get(3) == int_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 3); + + TEST_ASSERT(db2.get(0) == short_val); + TEST_ASSERT(db2.get(1) == short_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == 2.3); + TEST_ASSERT(db2.get(4) == 2.4); + TEST_ASSERT(db2.block_size() == 2); // Merge with the next block in the destination. db1 = mtv_type(5, int_val); @@ -100,19 +101,19 @@ db1.set(3, 1.1); db1.set(4, 1.2); db1.swap(3, 4, db2, 0); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == "A"); - assert(db1.get(4) == "B"); - assert(db1.block_size() == 2); - - assert(db2.get(0) == 1.1); - assert(db2.get(1) == 1.2); - assert(db2.get(2) == 12.3); - assert(db2.get(3) == 12.3); - assert(db2.get(4) == 12.3); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == "A"); + TEST_ASSERT(db1.get(4) == "B"); + TEST_ASSERT(db1.block_size() == 2); + + TEST_ASSERT(db2.get(0) == 1.1); + TEST_ASSERT(db2.get(1) == 1.2); + TEST_ASSERT(db2.get(2) == 12.3); + TEST_ASSERT(db2.get(3) == 12.3); + TEST_ASSERT(db2.get(4) == 12.3); + TEST_ASSERT(db2.block_size() == 1); // Merge with the previous block in the destination. db1 = mtv_type(5, int_val); @@ -124,19 +125,19 @@ db2.set(4, short_val); db1.swap(2, 3, db2, 3); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == short_val); - assert(db1.get(3) == short_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 3); - - assert(db2.get(0) == "default"); - assert(db2.get(1) == "default"); - assert(db2.get(2) == "default"); - assert(db2.get(3) == "A"); - assert(db2.get(4) == "B"); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == short_val); + TEST_ASSERT(db1.get(3) == short_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 3); + + TEST_ASSERT(db2.get(0) == "default"); + TEST_ASSERT(db2.get(1) == "default"); + TEST_ASSERT(db2.get(2) == "default"); + TEST_ASSERT(db2.get(3) == "A"); + TEST_ASSERT(db2.get(4) == "B"); + TEST_ASSERT(db2.block_size() == 1); // Merge with both the previous and next blocks in the destination. db1 = mtv_type(5, int_val); @@ -148,20 +149,20 @@ db2.set(4, short_val); db1.swap(2, 3, db2, 3); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == short_val); - assert(db1.get(3) == short_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 3); - - assert(db2.get(0) == "default"); - assert(db2.get(1) == "default"); - assert(db2.get(2) == "default"); - assert(db2.get(3) == "C"); - assert(db2.get(4) == "D"); - assert(db2.get(5) == "default"); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == short_val); + TEST_ASSERT(db1.get(3) == short_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 3); + + TEST_ASSERT(db2.get(0) == "default"); + TEST_ASSERT(db2.get(1) == "default"); + TEST_ASSERT(db2.get(2) == "default"); + TEST_ASSERT(db2.get(3) == "C"); + TEST_ASSERT(db2.get(4) == "D"); + TEST_ASSERT(db2.get(5) == "default"); + TEST_ASSERT(db2.block_size() == 1); // Set the new elements to the top of a block in the destination. db1 = mtv_type(5, int_val); @@ -169,18 +170,18 @@ db1.set(4, std::string("F")); db2 = mtv_type(5, short_val); db1.swap(3, 4, db2, 0); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == short_val); - assert(db1.get(4) == short_val); - assert(db1.block_size() == 2); - assert(db2.get(0) == "E"); - assert(db2.get(1) == "F"); - assert(db2.get(2) == short_val); - assert(db2.get(3) == short_val); - assert(db2.get(4) == short_val); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == short_val); + TEST_ASSERT(db1.get(4) == short_val); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db2.get(0) == "E"); + TEST_ASSERT(db2.get(1) == "F"); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == short_val); + TEST_ASSERT(db2.get(4) == short_val); + TEST_ASSERT(db2.block_size() == 2); // Do the same as before, but merge with the previous block. db1 = mtv_type(5, int_val); @@ -189,18 +190,18 @@ db2 = mtv_type(5, short_val); db2.set(0, std::string("F")); db1.swap(3, 4, db2, 1); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == short_val); - assert(db1.get(4) == short_val); - assert(db1.block_size() == 2); - assert(db2.get(0) == "F"); - assert(db2.get(1) == "G"); - assert(db2.get(2) == "H"); - assert(db2.get(3) == short_val); - assert(db2.get(4) == short_val); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == short_val); + TEST_ASSERT(db1.get(4) == short_val); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db2.get(0) == "F"); + TEST_ASSERT(db2.get(1) == "G"); + TEST_ASSERT(db2.get(2) == "H"); + TEST_ASSERT(db2.get(3) == short_val); + TEST_ASSERT(db2.get(4) == short_val); + TEST_ASSERT(db2.block_size() == 2); // Set the new element to the middle of a destination block. db1 = mtv_type(5, int_val); @@ -209,19 +210,19 @@ db2 = mtv_type(5, short_val); db2.set(0, std::string("top")); db1.swap(3, 4, db2, 2); - assert(db1.get(0) == int_val); - assert(db1.get(1) == int_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == short_val); - assert(db1.get(4) == short_val); - assert(db1.block_size() == 2); - - assert(db2.get(0) == "top"); - assert(db2.get(1) == short_val); - assert(db2.get(2) == "I"); - assert(db2.get(3) == "J"); - assert(db2.get(4) == short_val); - assert(db2.block_size() == 4); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == short_val); + TEST_ASSERT(db1.get(4) == short_val); + TEST_ASSERT(db1.block_size() == 2); + + TEST_ASSERT(db2.get(0) == "top"); + TEST_ASSERT(db2.get(1) == short_val); + TEST_ASSERT(db2.get(2) == "I"); + TEST_ASSERT(db2.get(3) == "J"); + TEST_ASSERT(db2.get(4) == short_val); + TEST_ASSERT(db2.block_size() == 4); // Set the new element to the lower part of a destination block. db1 = mtv_type(5, int_val); @@ -230,19 +231,19 @@ db2 = mtv_type(5, short_val); db1.swap(0, 1, db2, 3); - assert(db1.get(0) == short_val); - assert(db1.get(1) == short_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == int_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 2); - - assert(db2.get(0) == short_val); - assert(db2.get(1) == short_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == "A1"); - assert(db2.get(4) == "A2"); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == short_val); + TEST_ASSERT(db1.get(1) == short_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == int_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 2); + + TEST_ASSERT(db2.get(0) == short_val); + TEST_ASSERT(db2.get(1) == short_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == "A1"); + TEST_ASSERT(db2.get(4) == "A2"); + TEST_ASSERT(db2.block_size() == 2); // Same as above, except that the new element will be merged with the next // block in the destination. @@ -253,37 +254,37 @@ db2.set(5, std::string("A3")); db1.swap(0, 1, db2, 3); - assert(db1.get(0) == short_val); - assert(db1.get(1) == short_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == int_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 2); - - assert(db2.get(0) == short_val); - assert(db2.get(1) == short_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == "A1"); - assert(db2.get(4) == "A2"); - assert(db2.get(5) == "A3"); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == short_val); + TEST_ASSERT(db1.get(1) == short_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == int_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 2); + + TEST_ASSERT(db2.get(0) == short_val); + TEST_ASSERT(db2.get(1) == short_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == "A1"); + TEST_ASSERT(db2.get(4) == "A2"); + TEST_ASSERT(db2.get(5) == "A3"); + TEST_ASSERT(db2.block_size() == 2); // Swap the top part of source block. db1 = mtv_type(5, int_val); db2 = mtv_type(5, short_val); db1.swap(0, 1, db2, 0); - assert(db1.get(0) == short_val); - assert(db1.get(1) == short_val); - assert(db1.get(2) == int_val); - assert(db1.get(3) == int_val); - assert(db1.get(4) == int_val); - - assert(db2.get(0) == int_val); - assert(db2.get(1) == int_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == short_val); - assert(db2.get(4) == short_val); + TEST_ASSERT(db1.get(0) == short_val); + TEST_ASSERT(db1.get(1) == short_val); + TEST_ASSERT(db1.get(2) == int_val); + TEST_ASSERT(db1.get(3) == int_val); + TEST_ASSERT(db1.get(4) == int_val); + + TEST_ASSERT(db2.get(0) == int_val); + TEST_ASSERT(db2.get(1) == int_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == short_val); + TEST_ASSERT(db2.get(4) == short_val); // Do the same, and merge with the previous block in the source. db1 = mtv_type(5, int_val); @@ -293,37 +294,37 @@ db2.set(1, std::string("C")); db1.swap(1, 2, db2, 0); - assert(db1.get(0) == "A"); - assert(db1.get(1) == "B"); - assert(db1.get(2) == "C"); - assert(db1.get(3) == int_val); - assert(db1.get(4) == int_val); - assert(db1.block_size() == 2); - - assert(db2.get(0) == int_val); - assert(db2.get(1) == int_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == short_val); - assert(db2.get(4) == short_val); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == "A"); + TEST_ASSERT(db1.get(1) == "B"); + TEST_ASSERT(db1.get(2) == "C"); + TEST_ASSERT(db1.get(3) == int_val); + TEST_ASSERT(db1.get(4) == int_val); + TEST_ASSERT(db1.block_size() == 2); + + TEST_ASSERT(db2.get(0) == int_val); + TEST_ASSERT(db2.get(1) == int_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == short_val); + TEST_ASSERT(db2.get(4) == short_val); + TEST_ASSERT(db2.block_size() == 2); // Replace the bottom part of existing source block. db1 = mtv_type(2, true); db2 = mtv_type(1, int_val); db1.swap(1, 1, db2, 0); - assert(db1.get(0) == true); - assert(db1.get(1) == int_val); - assert(db2.get(0) == true); + TEST_ASSERT(db1.get(0) == true); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db2.get(0) == true); // Do the same, but merge with the next block in the source. db1 = mtv_type(3, true); db1.set(2, int_val + 1); db2 = mtv_type(1, int_val); db1.swap(1, 1, db2, 0); - assert(db1.get(0) == true); - assert(db1.get(1) == int_val); - assert(db1.get(2) == int_val + 1); - assert(db2.get(0) == true); + TEST_ASSERT(db1.get(0) == true); + TEST_ASSERT(db1.get(1) == int_val); + TEST_ASSERT(db1.get(2) == int_val + 1); + TEST_ASSERT(db2.get(0) == true); // Replace the middle of existing source block. db1 = mtv_type(5); @@ -336,16 +337,16 @@ db2.set(0, 1.1); db2.set(1, -1.1); db1.swap(2, 3, db2, 0); - assert(db1.get(0) == 'a'); - assert(db1.get(1) == 'b'); - assert(db1.get(2) == 1.1); - assert(db1.get(3) == -1.1); - assert(db1.get(4) == 'e'); - assert(db1.block_size() == 3); - - assert(db2.get(0) == 'c'); - assert(db2.get(1) == 'd'); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == 'a'); + TEST_ASSERT(db1.get(1) == 'b'); + TEST_ASSERT(db1.get(2) == 1.1); + TEST_ASSERT(db1.get(3) == -1.1); + TEST_ASSERT(db1.get(4) == 'e'); + TEST_ASSERT(db1.block_size() == 3); + + TEST_ASSERT(db2.get(0) == 'c'); + TEST_ASSERT(db2.get(1) == 'd'); + TEST_ASSERT(db2.block_size() == 1); // Swap single empty block with multiple destination blocks. db1 = mtv_type(5); @@ -356,18 +357,18 @@ db2.set(3, std::string("abc")); db2.set(4, std::string("def")); db1.swap(0, 3, db2, 1); - assert(db1.get(0) == 2.1); - assert(db1.get(1) == 3.1); - assert(db1.get(2) == "abc"); - assert(db1.get(3) == "def"); - assert(db1.is_empty(4)); - assert(db1.block_size() == 3); - assert(db2.get(0) == 1.1); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == 2.1); + TEST_ASSERT(db1.get(1) == 3.1); + TEST_ASSERT(db1.get(2) == "abc"); + TEST_ASSERT(db1.get(3) == "def"); + TEST_ASSERT(db1.is_empty(4)); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db2.get(0) == 1.1); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.block_size() == 2); // Swap non-empty single block with multiple destination blocks. db1 = mtv_type(4, int_val); @@ -378,17 +379,17 @@ db2.set(3, std::string("abc")); db2.set(4, std::string("def")); db1.swap(0, 3, db2, 1); - assert(db1.get(0) == 2.1); - assert(db1.get(1) == 3.1); - assert(db1.get(2) == "abc"); - assert(db1.get(3) == "def"); - assert(db1.block_size() == 2); - assert(db2.get(0) == 1.1); - assert(db2.get(1) == int_val); - assert(db2.get(2) == int_val); - assert(db2.get(3) == int_val); - assert(db2.get(4) == int_val); - assert(db2.block_size() == 2); + TEST_ASSERT(db1.get(0) == 2.1); + TEST_ASSERT(db1.get(1) == 3.1); + TEST_ASSERT(db1.get(2) == "abc"); + TEST_ASSERT(db1.get(3) == "def"); + TEST_ASSERT(db1.block_size() == 2); + TEST_ASSERT(db2.get(0) == 1.1); + TEST_ASSERT(db2.get(1) == int_val); + TEST_ASSERT(db2.get(2) == int_val); + TEST_ASSERT(db2.get(3) == int_val); + TEST_ASSERT(db2.get(4) == int_val); + TEST_ASSERT(db2.block_size() == 2); // Another scenario. db1 = mtv_type(2, short_val); @@ -396,10 +397,10 @@ db2.set(0, std::string("A")); db2.set(1, 'A'); db1.swap(0, 1, db2, 0); - assert(db1.get(0) == "A"); - assert(db1.get(1) == 'A'); - assert(db2.get(0) == short_val); - assert(db2.get(1) == short_val); + TEST_ASSERT(db1.get(0) == "A"); + TEST_ASSERT(db1.get(1) == 'A'); + TEST_ASSERT(db2.get(0) == short_val); + TEST_ASSERT(db2.get(1) == short_val); // Another scenario. db1 = mtv_type(2, 3.14); @@ -408,11 +409,11 @@ db2.set(1, 'z'); db2.set(2, 'y'); db1.swap(0, 1, db2, 0); - assert(db1.get(0) == "abc"); - assert(db1.get(1) == 'z'); - assert(db2.get(0) == 3.14); - assert(db2.get(1) == 3.14); - assert(db2.get(2) == 'y'); + TEST_ASSERT(db1.get(0) == "abc"); + TEST_ASSERT(db1.get(1) == 'z'); + TEST_ASSERT(db2.get(0) == 3.14); + TEST_ASSERT(db2.get(1) == 3.14); + TEST_ASSERT(db2.get(2) == 'y'); // Another scenario. db1 = mtv_type(5); @@ -426,15 +427,15 @@ db2.set(1, 'B'); db2.set(2, 123); db1.swap(0, 2, db2, 0); - assert(db1.get(0) == 2.3); - assert(db1.get(1) == 'B'); - assert(db1.get(2) == 123); - assert(db1.get(3) == 4); - assert(db1.get(4) == 5); - assert(db2.get(0) == 1); - assert(db2.get(1) == 2); - assert(db2.get(2) == 3); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == 2.3); + TEST_ASSERT(db1.get(1) == 'B'); + TEST_ASSERT(db1.get(2) == 123); + TEST_ASSERT(db1.get(3) == 4); + TEST_ASSERT(db1.get(4) == 5); + TEST_ASSERT(db2.get(0) == 1); + TEST_ASSERT(db2.get(1) == 2); + TEST_ASSERT(db2.get(2) == 3); + TEST_ASSERT(db2.block_size() == 1); // Another one. db1 = mtv_type(3, std::string("test")); @@ -442,11 +443,11 @@ db2.set(0, -99.1); db2.set(1, std::string("foo")); db1.swap(1, 2, db2, 0); - assert(db1.get(0) == "test"); - assert(db1.get(1) == -99.1); - assert(db1.get(2) == "foo"); - assert(db2.get(0) == "test"); - assert(db2.get(1) == "test"); + TEST_ASSERT(db1.get(0) == "test"); + TEST_ASSERT(db1.get(1) == -99.1); + TEST_ASSERT(db1.get(2) == "foo"); + TEST_ASSERT(db2.get(0) == "test"); + TEST_ASSERT(db2.get(1) == "test"); // The source range is in the middle of a block. db1 = mtv_type(8); @@ -459,20 +460,20 @@ db2.set(3, 15.0); db1.swap(3, 5, db2, 1); - assert(db1.get(0) == 2); - assert(db1.get(1) == 3); - assert(db1.get(2) == 4); - assert(db1.get(3) == 13); - assert(db1.get(4) == 14); - assert(db1.get(5) == 15.0); - assert(db1.get(6) == 8); - assert(db1.get(7) == 9); - - assert(db2.get(0) == 12); - assert(db2.get(1) == 5); - assert(db2.get(2) == 6); - assert(db2.get(3) == 7); - assert(db2.block_size() == 1); + TEST_ASSERT(db1.get(0) == 2); + TEST_ASSERT(db1.get(1) == 3); + TEST_ASSERT(db1.get(2) == 4); + TEST_ASSERT(db1.get(3) == 13); + TEST_ASSERT(db1.get(4) == 14); + TEST_ASSERT(db1.get(5) == 15.0); + TEST_ASSERT(db1.get(6) == 8); + TEST_ASSERT(db1.get(7) == 9); + + TEST_ASSERT(db2.get(0) == 12); + TEST_ASSERT(db2.get(1) == 5); + TEST_ASSERT(db2.get(2) == 6); + TEST_ASSERT(db2.get(3) == 7); + TEST_ASSERT(db2.block_size() == 1); // Try swapping in a multi-to-single block direction. db1 = mtv_type(2); @@ -480,19 +481,19 @@ db1.set(1, std::string("123")); db2 = mtv_type(10, short_val); db1.swap(0, 1, db2, 4); - assert(db1.get(0) == short_val); - assert(db1.get(1) == short_val); + TEST_ASSERT(db1.get(0) == short_val); + TEST_ASSERT(db1.get(1) == short_val); - assert(db2.get(0) == short_val); - assert(db2.get(1) == short_val); - assert(db2.get(2) == short_val); - assert(db2.get(3) == short_val); - assert(db2.get(4) == 1.2); - assert(db2.get(5) == "123"); - assert(db2.get(6) == short_val); - assert(db2.get(7) == short_val); - assert(db2.get(8) == short_val); - assert(db2.get(9) == short_val); + TEST_ASSERT(db2.get(0) == short_val); + TEST_ASSERT(db2.get(1) == short_val); + TEST_ASSERT(db2.get(2) == short_val); + TEST_ASSERT(db2.get(3) == short_val); + TEST_ASSERT(db2.get(4) == 1.2); + TEST_ASSERT(db2.get(5) == "123"); + TEST_ASSERT(db2.get(6) == short_val); + TEST_ASSERT(db2.get(7) == short_val); + TEST_ASSERT(db2.get(8) == short_val); + TEST_ASSERT(db2.get(9) == short_val); // Multi-to-multi block swapping. Very simple case. db1 = mtv_type(2); @@ -503,10 +504,10 @@ db2.set(1, short_val); db1.swap(0, 1, db2, 0); - assert(db1.get(0) == int_val); - assert(db1.get(1) == short_val); - assert(db2.get(0) == 2.1); - assert(db2.get(1) == "test"); + TEST_ASSERT(db1.get(0) == int_val); + TEST_ASSERT(db1.get(1) == short_val); + TEST_ASSERT(db2.get(0) == 2.1); + TEST_ASSERT(db2.get(1) == "test"); // More complex case. db1 = mtv_type(10); @@ -523,29 +524,29 @@ db2.set(5, 'Z'); db1.swap(1, 7, db2, 2); - assert(db1.get(0) == 2); - assert(db1.get(1) == 12); - assert(db1.get(2) == 13); - assert(db1.get(3) == 14); - assert(db1.get(4) == 'Z'); - assert(db1.get(5) == 16); - assert(db1.get(6) == 17); - assert(db1.get(7) == 18); - assert(db1.is_empty(8)); - assert(db1.is_empty(9)); - assert(db1.block_size() == 4); - - assert(db2.get(0) == 10); - assert(db2.get(1) == 11); - assert(db2.get(2) == 3); - assert(db2.get(3) == 4); - assert(db2.get(4) == "A"); - assert(db2.get(5) == "B"); - assert(db2.get(6) == "C"); - assert(db2.is_empty(7)); - assert(db2.is_empty(8)); - assert(db2.get(9) == 19); - assert(db2.block_size() == 4); + TEST_ASSERT(db1.get(0) == 2); + TEST_ASSERT(db1.get(1) == 12); + TEST_ASSERT(db1.get(2) == 13); + TEST_ASSERT(db1.get(3) == 14); + TEST_ASSERT(db1.get(4) == 'Z'); + TEST_ASSERT(db1.get(5) == 16); + TEST_ASSERT(db1.get(6) == 17); + TEST_ASSERT(db1.get(7) == 18); + TEST_ASSERT(db1.is_empty(8)); + TEST_ASSERT(db1.is_empty(9)); + TEST_ASSERT(db1.block_size() == 4); + + TEST_ASSERT(db2.get(0) == 10); + TEST_ASSERT(db2.get(1) == 11); + TEST_ASSERT(db2.get(2) == 3); + TEST_ASSERT(db2.get(3) == 4); + TEST_ASSERT(db2.get(4) == "A"); + TEST_ASSERT(db2.get(5) == "B"); + TEST_ASSERT(db2.get(6) == "C"); + TEST_ASSERT(db2.is_empty(7)); + TEST_ASSERT(db2.is_empty(8)); + TEST_ASSERT(db2.get(9) == 19); + TEST_ASSERT(db2.block_size() == 4); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/default/tc/transfer.inl mdds-3.1.0/test/multi_type_vector/default/tc/transfer.inl --- mdds-2.1.1/test/multi_type_vector/default/tc/transfer.inl 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/default/tc/transfer.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,27 +28,28 @@ void mtv_test_transfer() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; + mtv_type db1(5), db2(5); db1.set(0, 1.0); db1.set(1, 2.0); mtv_type::iterator it = db1.transfer(1, 2, db2, 1); - assert(db1.get(0) == 1.0); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.is_empty(0)); - assert(db2.get(1) == 2.0); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - - assert(it->size == 4); - assert(it->__private_data.block_index == 1); - assert(it->position == 1); + TEST_ASSERT(db1.get(0) == 1.0); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1) == 2.0); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + + TEST_ASSERT(it->size == 4); + TEST_ASSERT(it->__private_data.block_index == 1); + TEST_ASSERT(it->position == 1); // Reset and start over. db1.clear(); @@ -62,21 +63,21 @@ // Transfer 1:2 in db1 to 2:3 in db2. it = db1.transfer(1, 2, db2, 2); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.get(3) == 1.3); - assert(db1.is_empty(4)); - - assert(db2.is_empty(0)); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.get(3) == 1.2); - assert(db2.is_empty(4)); - - assert(it->size == 3); - assert(it->position == 0); - assert(it->__private_data.block_index == 0); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.get(3) == 1.3); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.get(3) == 1.2); + TEST_ASSERT(db2.is_empty(4)); + + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->position == 0); + TEST_ASSERT(it->__private_data.block_index == 0); // Reset and start over. db1.clear(); @@ -91,19 +92,19 @@ it = db1.transfer(1, 2, db2, 1); - assert(db1.get(0) == "A"); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.get(3) == 11.2); - - assert(db2.is_empty(0)); - assert(db2.get(1) == "B"); - assert(db2.get(2) == 11.1); - assert(db2.is_empty(3)); - - assert(it->size == 2); - assert(it->position == 1); - assert(it->__private_data.block_index == 1); + TEST_ASSERT(db1.get(0) == "A"); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.get(3) == 11.2); + + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1) == "B"); + TEST_ASSERT(db2.get(2) == 11.1); + TEST_ASSERT(db2.is_empty(3)); + + TEST_ASSERT(it->size == 2); + TEST_ASSERT(it->position == 1); + TEST_ASSERT(it->__private_data.block_index == 1); // Reset and start over. db1.clear(); @@ -128,33 +129,33 @@ 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 == mdds::mtv::element_type_empty); + TEST_ASSERT(db1.block_size() == 1); + TEST_ASSERT(it == db1.begin()); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it->size == 20); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db1.end()); + TEST_ASSERT(it == db1.end()); // Check the destination as well. - assert(db2.block_size() == 3); + TEST_ASSERT(db2.block_size() == 3); it = db2.begin(); - assert(it->size == 9); - assert(it->__private_data.block_index == 0); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 9); + TEST_ASSERT(it->__private_data.block_index == 0); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it->size == 3); - assert(it->__private_data.block_index == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 3); + TEST_ASSERT(it->__private_data.block_index == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it->size == 8); - assert(it->__private_data.block_index == 2); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 8); + TEST_ASSERT(it->__private_data.block_index == 2); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db2.end()); - assert(db2.get(9) == 1.1); - assert(db2.get(10) == 1.2); - assert(db2.get(11) == 1.3); + TEST_ASSERT(it == db2.end()); + TEST_ASSERT(db2.get(9) == 1.1); + TEST_ASSERT(db2.get(10) == 1.2); + TEST_ASSERT(db2.get(11) == 1.3); // Reset and start over. db1.clear(); @@ -169,20 +170,20 @@ 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(8) == 1.0); + TEST_ASSERT(it->__private_data.block_index == 2); + TEST_ASSERT(db1.block_size() == 3); + TEST_ASSERT(db1.get(8) == 1.0); it = db1.begin(); - assert(it->size == 8); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 8); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it->size == 1); - assert(it->type == mdds::mtv::element_type_double); + TEST_ASSERT(it->size == 1); + TEST_ASSERT(it->type == mdds::mtv::element_type_double); ++it; - assert(it->size == 11); - assert(it->type == mdds::mtv::element_type_empty); + TEST_ASSERT(it->size == 11); + TEST_ASSERT(it->type == mdds::mtv::element_type_empty); ++it; - assert(it == db1.end()); + TEST_ASSERT(it == db1.end()); // Reset and start over. db1.clear(); @@ -191,45 +192,45 @@ db1.transfer(0, 4, db2, 1); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - assert(db1.is_empty(5)); - assert(db1.is_empty(6)); - assert(db1.is_empty(7)); - - assert(db2.get(0) == true); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); - assert(db2.get(6) == true); - assert(db2.get(7) == true); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + TEST_ASSERT(db1.is_empty(5)); + TEST_ASSERT(db1.is_empty(6)); + TEST_ASSERT(db1.is_empty(7)); + + TEST_ASSERT(db2.get(0) == true); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); + TEST_ASSERT(db2.get(6) == true); + TEST_ASSERT(db2.get(7) == true); // Start over. db1 = mtv_type(8, int16_t(43)); db2 = mtv_type(8); db1.transfer(3, 5, db2, 0); - assert(db1.get(0) == 43); - assert(db1.get(1) == 43); - assert(db1.get(2) == 43); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - assert(db1.is_empty(5)); - assert(db1.get(6) == 43); - assert(db1.get(7) == 43); - - assert(db2.get(0) == 43); - assert(db2.get(1) == 43); - assert(db2.get(2) == 43); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); - assert(db2.is_empty(6)); - assert(db2.is_empty(7)); + TEST_ASSERT(db1.get(0) == 43); + TEST_ASSERT(db1.get(1) == 43); + TEST_ASSERT(db1.get(2) == 43); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + TEST_ASSERT(db1.is_empty(5)); + TEST_ASSERT(db1.get(6) == 43); + TEST_ASSERT(db1.get(7) == 43); + + TEST_ASSERT(db2.get(0) == 43); + TEST_ASSERT(db2.get(1) == 43); + TEST_ASSERT(db2.get(2) == 43); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); + TEST_ASSERT(db2.is_empty(6)); + TEST_ASSERT(db2.is_empty(7)); // Start over. db1 = mtv_type(5); @@ -241,17 +242,17 @@ db1.transfer(3, 4, db2, 0); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.get(0) == 1.1); - assert(db2.get(1) == 1.2); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.get(0) == 1.1); + TEST_ASSERT(db2.get(1) == 1.2); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); // Start over. db1 = mtv_type(5); @@ -263,17 +264,17 @@ db1.transfer(3, 4, db2, 0); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.get(0) == 1.1); - assert(db2.get(1) == 892); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.get(0) == 1.1); + TEST_ASSERT(db2.get(1) == 892); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); // Start over. db1 = mtv_type(5, false); @@ -286,17 +287,17 @@ db1.transfer(3, 4, db2, 1); - assert(db1.get(0) == false); - assert(db1.get(1) == false); - assert(db1.get(2) == false); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.get(0) == 32); - assert(db2.get(1) == false); - assert(db2.get(2) == 234); - assert(db2.get(3) == 56); - assert(db2.is_empty(4)); + TEST_ASSERT(db1.get(0) == false); + TEST_ASSERT(db1.get(1) == false); + TEST_ASSERT(db1.get(2) == false); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.get(0) == 32); + TEST_ASSERT(db2.get(1) == false); + TEST_ASSERT(db2.get(2) == 234); + TEST_ASSERT(db2.get(3) == 56); + TEST_ASSERT(db2.is_empty(4)); // Start over. db1 = mtv_type(5, false); @@ -306,18 +307,18 @@ db1.transfer(3, 4, db2, 4); - assert(db1.get(0) == false); - assert(db1.get(1) == false); - assert(db1.get(2) == false); - assert(db1.is_empty(3)); - assert(db1.is_empty(4)); - - assert(db2.get(0) == 2345); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.get(4) == false); - assert(db2.get(5) == 234); + TEST_ASSERT(db1.get(0) == false); + TEST_ASSERT(db1.get(1) == false); + TEST_ASSERT(db1.get(2) == false); + TEST_ASSERT(db1.is_empty(3)); + TEST_ASSERT(db1.is_empty(4)); + + TEST_ASSERT(db2.get(0) == 2345); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.get(4) == false); + TEST_ASSERT(db2.get(5) == 234); // Start over db1.clear(); @@ -329,21 +330,21 @@ db1.transfer(0, 3, db2, 6); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.is_empty(3)); - - assert(db2.is_empty(0)); - assert(db2.is_empty(1)); - assert(db2.is_empty(2)); - assert(db2.is_empty(3)); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); - assert(db2.get(6) == 5); - assert(db2.get(7) == 5); - assert(db2.get(8) == 5); - assert(db2.get(9) == 5.0); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.is_empty(3)); + + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.is_empty(1)); + TEST_ASSERT(db2.is_empty(2)); + TEST_ASSERT(db2.is_empty(3)); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); + TEST_ASSERT(db2.get(6) == 5); + TEST_ASSERT(db2.get(7) == 5); + TEST_ASSERT(db2.get(8) == 5); + TEST_ASSERT(db2.get(9) == 5.0); // Start over. db1 = mtv_type(5, true); @@ -351,18 +352,18 @@ db1.transfer(0, 2, db2, 1); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.get(3) == true); - assert(db1.get(4) == true); - - assert(db2.is_empty(0)); - assert(db2.get(1) == true); - assert(db2.get(2) == true); - assert(db2.get(3) == true); - assert(db2.is_empty(4)); - assert(db2.is_empty(5)); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.get(3) == true); + TEST_ASSERT(db1.get(4) == true); + + TEST_ASSERT(db2.is_empty(0)); + TEST_ASSERT(db2.get(1) == true); + TEST_ASSERT(db2.get(2) == true); + TEST_ASSERT(db2.get(3) == true); + TEST_ASSERT(db2.is_empty(4)); + TEST_ASSERT(db2.is_empty(5)); // Start over. db1 = mtv_type(5, int32_t(987)); @@ -375,17 +376,17 @@ db1.transfer(0, 2, db2, 2); - assert(db1.is_empty(0)); - assert(db1.is_empty(1)); - assert(db1.is_empty(2)); - assert(db1.get(3) == 1.1); - assert(db1.get(4) == 1.2); - - assert(db2.get(0) == true); - assert(db2.get(1) == false); - assert(db2.get(2) == 987); - assert(db2.get(3) == 987); - assert(db2.get(4) == 987); + TEST_ASSERT(db1.is_empty(0)); + TEST_ASSERT(db1.is_empty(1)); + TEST_ASSERT(db1.is_empty(2)); + TEST_ASSERT(db1.get(3) == 1.1); + TEST_ASSERT(db1.get(4) == 1.2); + + TEST_ASSERT(db2.get(0) == true); + TEST_ASSERT(db2.get(1) == false); + TEST_ASSERT(db2.get(2) == 987); + TEST_ASSERT(db2.get(3) == 987); + TEST_ASSERT(db2.get(4) == 987); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/Makefile.in mdds-3.1.0/test/multi_type_vector/element-blocks/Makefile.in --- mdds-2.1.1/test/multi_type_vector/element-blocks/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -447,7 +447,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/no_standard_blocks_funcs.inl mdds-3.1.0/test/multi_type_vector/element-blocks/no_standard_blocks_funcs.inl --- mdds-2.1.1/test/multi_type_vector/element-blocks/no_standard_blocks_funcs.inl 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/no_standard_blocks_funcs.inl 2025-07-03 16:15:17.000000000 +0000 @@ -28,6 +28,8 @@ void test_mtv_basic() { + MDDS_TEST_FUNC_SCOPE; + using this_mtv_type = mtv_type; this_mtv_type db{}; @@ -37,12 +39,12 @@ db.push_back(123); db.push_back(456u); - assert(db.size() == 4); - assert(db.block_size() == 3); - assert(db.get(0) == true); - assert(db.get(1) == false); - assert(db.get(2) == 123); - assert(db.get(3) == 456u); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(db.block_size() == 3); + TEST_ASSERT(db.get(0) == true); + TEST_ASSERT(db.get(1) == false); + TEST_ASSERT(db.get(2) == 123); + TEST_ASSERT(db.get(3) == 456u); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/test_functions.cpp mdds-3.1.0/test/multi_type_vector/element-blocks/test_functions.cpp --- mdds-2.1.1/test/multi_type_vector/element-blocks/test_functions.cpp 2023-04-29 13:06:19.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/test_functions.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -44,17 +44,17 @@ auto blk = block_type(values.begin(), values.end()); const auto& crblk = blk; - assert(block_type::size(blk) == 5u); + TEST_ASSERT(block_type::size(blk) == 5u); { auto it = block_type::begin(blk), it_end = block_type::end(blk); - assert(std::distance(it, it_end) == 5u); - assert(*it++ == 1); - assert(*it++ == 2); - assert(*it++ == 3); - assert(*it++ == 4); - assert(*it++ == 5); - assert(it == it_end); + TEST_ASSERT(std::distance(it, it_end) == 5u); + TEST_ASSERT(*it++ == 1); + TEST_ASSERT(*it++ == 2); + TEST_ASSERT(*it++ == 3); + TEST_ASSERT(*it++ == 4); + TEST_ASSERT(*it++ == 5); + TEST_ASSERT(it == it_end); } { @@ -63,10 +63,10 @@ for (auto v : block_type::range(crblk)) { std::cout << "v=" << v << std::endl; - assert(v == *it++); + TEST_ASSERT(v == *it++); } - assert(it == block_type::end(crblk)); + TEST_ASSERT(it == block_type::end(crblk)); } { @@ -75,20 +75,20 @@ for (auto v : block_type::range(blk)) { std::cout << "v=" << v << std::endl; - assert(v == *it); + TEST_ASSERT(v == *it); *it = v + 2; ++it; } - assert(it == block_type::end(blk)); + TEST_ASSERT(it == block_type::end(blk)); it = block_type::begin(blk); - assert(*it++ == 3); - assert(*it++ == 4); - assert(*it++ == 5); - assert(*it++ == 6); - assert(*it++ == 7); - assert(it == block_type::end(blk)); + TEST_ASSERT(*it++ == 3); + TEST_ASSERT(*it++ == 4); + TEST_ASSERT(*it++ == 5); + TEST_ASSERT(*it++ == 6); + TEST_ASSERT(*it++ == 7); + TEST_ASSERT(it == block_type::end(blk)); } } diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/test_no_standard_blocks_aos.cpp mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_aos.cpp --- mdds-2.1.1/test/multi_type_vector/element-blocks/test_no_standard_blocks_aos.cpp 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_aos.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -26,6 +26,7 @@ * ************************************************************************/ +#include "test_aos.hpp" #include "no_standard_blocks_defs.inl" // Settting this to 0 should make the multi_type_vector code to NOT include diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/test_no_standard_blocks_soa.cpp mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_soa.cpp --- mdds-2.1.1/test/multi_type_vector/element-blocks/test_no_standard_blocks_soa.cpp 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/test_no_standard_blocks_soa.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -26,6 +26,7 @@ * ************************************************************************/ +#include "test_soa.hpp" #include "no_standard_blocks_defs.inl" // Settting this to 0 should make the multi_type_vector code to NOT include diff -Nru mdds-2.1.1/test/multi_type_vector/element-blocks/test_store_types.cpp mdds-3.1.0/test/multi_type_vector/element-blocks/test_store_types.cpp --- mdds-2.1.1/test/multi_type_vector/element-blocks/test_store_types.cpp 2022-08-17 03:29:15.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/element-blocks/test_store_types.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -47,15 +47,15 @@ auto* blk = this_block::create_block(10); - assert(mdds::mtv::get_block_type(*blk) == this_block::block_type); - assert(this_block::size(*blk) == 10u); + TEST_ASSERT(mdds::mtv::get_block_type(*blk) == this_block::block_type); + TEST_ASSERT(this_block::size(*blk) == 10u); auto cap = this_block::capacity(*blk); - assert(cap >= 10u); + TEST_ASSERT(cap >= 10u); this_block::reserve(*blk, 100u); cap = this_block::capacity(*blk); - assert(cap >= 100u); + TEST_ASSERT(cap >= 100u); this_block::shrink_to_fit(*blk); @@ -74,8 +74,8 @@ auto* blk = this_block::create_block(10); - assert(mdds::mtv::get_block_type(*blk) == this_block::block_type); - assert(this_block::size(*blk) == 10u); + TEST_ASSERT(mdds::mtv::get_block_type(*blk) == this_block::block_type); + TEST_ASSERT(this_block::size(*blk) == 10u); // std::deque does not have a capacity() method, but this should still compile. [[maybe_unused]] auto cap = this_block::capacity(*blk); diff -Nru mdds-2.1.1/test/multi_type_vector/event/Makefile.in mdds-3.1.0/test/multi_type_vector/event/Makefile.in --- mdds-2.1.1/test/multi_type_vector/event/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/event/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/event/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/event/aos/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -441,7 +441,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/event/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/event/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/event/soa/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -441,7 +441,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/event/tc/Makefile.in mdds-3.1.0/test/multi_type_vector/event/tc/Makefile.in --- mdds-2.1.1/test/multi_type_vector/event/tc/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/tc/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -182,7 +182,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/event/tc/block_counter.inl mdds-3.1.0/test/multi_type_vector/event/tc/block_counter.inl --- mdds-2.1.1/test/multi_type_vector/event/tc/block_counter.inl 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/tc/block_counter.inl 2025-07-03 16:15:17.000000000 +0000 @@ -152,262 +152,262 @@ void mtv_test_block_counter() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; using mtv_type = mtv_template_type; { // Initializing with an empty block should not create any element block. mtv_type db(10); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { // Initializing with one element block of size 10. mtv_type db(10, 1.2); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.clear(); - assert(db.event_handler().block_count == 0); - assert(db.event_handler().block_count_numeric == 0); + TEST_ASSERT(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count_numeric == 0); db.push_back(5.5); // create a new block. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.push_back(6.6); // no new block creation. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.push_back(std::string("foo")); // another new block. - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); // This should remove the last string block. db.resize(2); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 0); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 0); // This should have no effect on the block count. db.resize(1); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); // This should remove the last remaining block. db.resize(0); - assert(db.event_handler().block_count == 0); - assert(db.event_handler().block_count_numeric == 0); + TEST_ASSERT(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count_numeric == 0); } { mtv_type db(5); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); db.set(0, true); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(1, 12.2); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_boolean == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.set(4, std::string("foo")); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(3, std::string("bar")); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_string == 1); // This should delete the top two element blocks. db.set_empty(0, 1); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_boolean == 0); - assert(db.event_handler().block_count_numeric == 0); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_boolean == 0); + TEST_ASSERT(db.event_handler().block_count_numeric == 0); // Now, delete the bottom one. db.set_empty(3, 4); - assert(db.event_handler().block_count == 0); - assert(db.event_handler().block_count_string == 0); + TEST_ASSERT(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count_string == 0); // Create and delete a block in the middle. db.set(3, false); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); db.set_empty(3, 3); - assert(db.event_handler().block_count == 0); - assert(db.event_handler().block_count_boolean == 0); + TEST_ASSERT(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count_boolean == 0); db.set(2, 10.5); db.set(3, std::string("hmm")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set_empty(3, 3); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 0); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 0); // Start over. db.clear(); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); db.push_back(1.1); db.push_back(1.2); db.push_back(1.3); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); // Put empty block in the middle. db.set_empty(1, 1); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 2); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 2); } { mtv_type db(4, 1.2); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); // Split the block into two. db.insert_empty(2, 2); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 2); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 2); } { mtv_type db(2); db.set(1, 1.2); // This creates a new element block. - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(0, 1.1); // The element block count should not change. - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); } { mtv_type db(2); db.set(1, std::string("test")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(0, 1.1); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(0, true); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_boolean == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(0, std::string("foo")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(1, 1.2); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(1, std::string("bar")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); } { mtv_type db(2); db.set(0, std::string("test")); // This creates a new string block. - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(1, std::string("foo")); // This appends to the existing string block. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); } { mtv_type db(3); db.set(0, std::string("test")); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(2, std::string("foo")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_string == 2); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_string == 2); db.set(1, std::string("bar")); // This merges all data into a single string block. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); } { mtv_type db(4); db.set(0, std::string("test")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(2, std::string("foo1")); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(3, std::string("foo2")); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(1, std::string("bar")); // This merges all data into a single string block. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); } { mtv_type db(3); db.set(0, std::string("test")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(2, 1.2); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(1, std::string("bar")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); } { mtv_type db(3); db.set(0, std::string("test")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(2, 1.2); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(1, 1.1); // This will get prepended to the next numeric block. - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); } { std::vector vals = {1.1, 1.2, 1.3}; mtv_type db(vals.size(), vals.begin(), vals.end()); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); mtv_type db2(db); - assert(db2.event_handler().block_count == 1); + TEST_ASSERT(db2.event_handler().block_count == 1); db2.push_back(std::string("foo")); - assert(db2.event_handler().block_count == 2); + TEST_ASSERT(db2.event_handler().block_count == 2); mtv_type db3 = db2; - assert(db3.event_handler().block_count == 2); + TEST_ASSERT(db3.event_handler().block_count == 2); mtv_type db4(3); db4.insert(0, vals.begin(), vals.end()); - assert(db4.event_handler().block_count == 1); + TEST_ASSERT(db4.event_handler().block_count == 1); mtv_type db5(3, int64_t(10)); - assert(db5.event_handler().block_count == 1); + TEST_ASSERT(db5.event_handler().block_count == 1); db5.insert(0, vals.begin(), vals.end()); - assert(db5.event_handler().block_count == 2); + TEST_ASSERT(db5.event_handler().block_count == 2); mtv_type db6(2, int32_t(30)); - assert(db6.event_handler().block_count == 1); + TEST_ASSERT(db6.event_handler().block_count == 1); db6.insert(1, vals.begin(), vals.end()); // Insert to split the block. - assert(db6.event_handler().block_count == 3); - assert(db6.event_handler().block_count_int32 == 2); - assert(db6.event_handler().block_count_numeric == 1); + TEST_ASSERT(db6.event_handler().block_count == 3); + TEST_ASSERT(db6.event_handler().block_count_int32 == 2); + TEST_ASSERT(db6.event_handler().block_count_numeric == 1); } { mtv_type db(3); db.set(1, 1.1); db.set(2, true); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(1, false); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); } { mtv_type db(3); db.set(1, 1.1); db.set(0, true); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_boolean == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.set(1, false); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); } { @@ -415,31 +415,31 @@ db.set(0, true); db.set(1, 1.1); db.set(2, false); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_boolean == 2); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_boolean == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.set(1, true); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); db.set(1, 1.1); - assert(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count == 3); db.set(2, int64_t(10)); db.set(1, true); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_boolean == 1); - assert(db.event_handler().block_count_int64 == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count_int64 == 1); db.set(1, 1.1); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_boolean == 1); - assert(db.event_handler().block_count_int64 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_boolean == 1); + TEST_ASSERT(db.event_handler().block_count_int64 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.set(1, int64_t(20)); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.release(); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { @@ -447,40 +447,40 @@ db.push_back(1.1); db.push_back(int64_t(10)); db.push_back(std::string("foo")); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_int64 == 1); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_int64 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.erase(0, 2); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { mtv_type db; db.push_back(1.1); db.push_back_empty(); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.erase(0, 0); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { mtv_type db(3); db.set(0, std::string("top")); db.set(2, std::string("bottom")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_string == 2); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_string == 2); db.erase(1, 1); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); } { mtv_type db(3); db.set(1, 1.1); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.erase(1, 1); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { @@ -490,12 +490,12 @@ db.set(1, 0.2); db.set(2, std::string("foo")); db.set(3, std::string("bar")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(2, vals.begin(), vals.end()); // remove a block and append to previous one. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { @@ -503,12 +503,12 @@ mtv_type db(4); db.set(0, int32_t(5)); db.set(1, int32_t(10)); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); db.set(2, vals.begin(), vals.end()); // set to empty block. - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { @@ -518,121 +518,121 @@ db.set(1, int32_t(10)); db.set(2, std::string("foo")); db.set(3, std::string("bar")); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(2, vals.begin(), vals.end()); // replace a block. - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { std::vector vals = {1.1, 1.2}; mtv_type db(4, std::string("foo")); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); db.set(0, vals.begin(), vals.end()); // replace the upper part of a block. - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_string == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { std::vector vals = {1.1, 1.2}; mtv_type db(4, std::string("foo")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(2, vals.begin(), vals.end()); // replace the lower part of the last block. - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); } { std::vector vals = {1.1, 1.2}; mtv_type db(4, std::string("foo")); db.push_back(int64_t(100)); - assert(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count == 2); db.set(2, vals.begin(), vals.end()); // replace the lower part of a block. - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_string == 1); - assert(db.event_handler().block_count_int64 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count_int64 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { std::vector vals = {1.1, 1.2}; mtv_type db(6, std::string("foo")); - assert(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count == 1); db.set(2, vals.begin(), vals.end()); // set the values to the middle of a block. - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_string == 2); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_string == 2); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { mtv_type db(1, 0.1); db.push_back(int16_t(1)); db.push_back(int32_t(20)); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_int16 == 1); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_int16 == 1); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); std::vector vals = {1.1, 1.2, 1.3}; // same type as the top block. db.set(0, vals.begin(), vals.end()); // overwrite multiple blocks. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { mtv_type db(1, std::string("foo")); db.push_back(int16_t(1)); db.push_back(int32_t(20)); - assert(db.event_handler().block_count == 3); - assert(db.event_handler().block_count_int16 == 1); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_string == 1); + TEST_ASSERT(db.event_handler().block_count == 3); + TEST_ASSERT(db.event_handler().block_count_int16 == 1); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_string == 1); std::vector vals = {1.1, 1.2, 1.3}; // differene type from that of the top block. db.set(0, vals.begin(), vals.end()); // overwrite multiple blocks. - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); } { mtv_type db(6); db.set(2, 1.1); db.set(3, int32_t(22)); - assert(db.event_handler().block_count == 2); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count == 2); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); db.erase(2, 3); - assert(db.event_handler().block_count == 0); + TEST_ASSERT(db.event_handler().block_count == 0); } { mtv_type db(6, int8_t('a')); db.set(2, 1.1); db.set(3, int32_t(22)); - assert(db.event_handler().block_count == 4); - assert(db.event_handler().block_count_int32 == 1); - assert(db.event_handler().block_count_numeric == 1); - assert(db.event_handler().block_count_int8 == 2); + TEST_ASSERT(db.event_handler().block_count == 4); + TEST_ASSERT(db.event_handler().block_count_int32 == 1); + TEST_ASSERT(db.event_handler().block_count_numeric == 1); + TEST_ASSERT(db.event_handler().block_count_int8 == 2); db.erase(2, 3); - assert(db.event_handler().block_count == 1); - assert(db.event_handler().block_count_int8 == 1); + TEST_ASSERT(db.event_handler().block_count == 1); + TEST_ASSERT(db.event_handler().block_count_int8 == 1); } { mtv_type src(6, int8_t('a')), dst(6); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 0); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 0); src.transfer(0, 2, dst, 0); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.transfer(3, 5, dst, 3); - assert(src.event_handler().block_count == 0); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 0); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -641,20 +641,20 @@ src.set(1, int32_t(10)); src.set(2, int16_t(5)); dst.set(3, 1.1); - assert(src.event_handler().block_count == 3); - assert(src.event_handler().block_count_int8 == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(src.event_handler().block_count_int16 == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 3); + TEST_ASSERT(src.event_handler().block_count_int8 == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count_int16 == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); src.transfer(0, 2, dst, 0); - assert(src.event_handler().block_count == 0); - assert(dst.event_handler().block_count == 4); - assert(dst.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count_int8 == 1); - assert(dst.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count_int16 == 1); + TEST_ASSERT(src.event_handler().block_count == 0); + TEST_ASSERT(dst.event_handler().block_count == 4); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count_int8 == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count_int16 == 1); } { @@ -662,12 +662,12 @@ src.set(0, 1.1); src.set(1, 1.2); src.set(2, 1.3); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 0); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 0); src.transfer(1, 3, dst, 1); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -675,12 +675,12 @@ src.set(3, 1.1); src.set(4, 1.2); src.set(5, 1.3); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 0); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 0); src.transfer(1, 3, dst, 1); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -693,12 +693,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(0, 2, dst, 0); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -712,12 +712,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(0, 2, dst, 0); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -732,12 +732,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(1, 3, dst, 0); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -751,12 +751,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(1, 3, dst, 0); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -771,12 +771,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(1, 3, dst, 0); - assert(src.event_handler().block_count == 2); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -791,12 +791,12 @@ dst.set(1, std::string("2.2")); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(1, 3, dst, 0); - assert(src.event_handler().block_count == 3); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -809,18 +809,18 @@ dst.set(1, int32_t(100)); dst.set(2, std::string("2.3")); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 3); - assert(dst.event_handler().block_count_string == 2); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count_string == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 0); - assert(src.event_handler().block_count == 3); - assert(src.event_handler().block_count_string == 2); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 3); + TEST_ASSERT(src.event_handler().block_count_string == 2); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -837,20 +837,20 @@ dst.set(3, std::string("2.3")); dst.set(4, std::string("2.4")); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 3); - assert(dst.event_handler().block_count_string == 2); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count_string == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(1, 3, dst, 1); - assert(src.event_handler().block_count == 5); - assert(src.event_handler().block_count_numeric == 2); - assert(src.event_handler().block_count_string == 2); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 3); - assert(dst.event_handler().block_count_string == 2); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 5); + TEST_ASSERT(src.event_handler().block_count_numeric == 2); + TEST_ASSERT(src.event_handler().block_count_string == 2); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count_string == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -864,17 +864,17 @@ dst.set(2, int32_t(6)); dst.set(3, int32_t(7)); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -889,17 +889,17 @@ dst.set(3, int32_t(7)); dst.set(4, 2.2); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 3); - assert(dst.event_handler().block_count_numeric == 2); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count_numeric == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -913,17 +913,17 @@ dst.set(2, int32_t(7)); dst.set(3, 2.1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); src.swap(0, 2, dst, 0); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -937,14 +937,14 @@ dst.set(2, int32_t(7)); dst.set(3, int32_t(8)); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(0, 2, dst, 0); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -959,18 +959,18 @@ dst.set(3, int32_t(7)); dst.set(4, int32_t(8)); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); } { @@ -985,15 +985,15 @@ dst.set(3, int32_t(7)); dst.set(4, int32_t(8)); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 3); - assert(dst.event_handler().block_count_int32 == 2); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 3); + TEST_ASSERT(dst.event_handler().block_count_int32 == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -1007,17 +1007,17 @@ dst.set(2, int32_t(6)); dst.set(3, int32_t(7)); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 1); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -1032,18 +1032,18 @@ dst.set(3, int32_t(7)); dst.set(4, 2.1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_numeric == 1); - assert(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); src.swap(0, 2, dst, 1); - assert(src.event_handler().block_count == 1); - assert(src.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count == 2); - assert(dst.event_handler().block_count_int32 == 1); - assert(dst.event_handler().block_count_numeric == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); + TEST_ASSERT(dst.event_handler().block_count_int32 == 1); + TEST_ASSERT(dst.event_handler().block_count_numeric == 1); } { @@ -1055,12 +1055,12 @@ dst.set(0, 2.1); dst.set(4, 2.2); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 2); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 2); src.transfer(0, 2, dst, 1); - assert(src.event_handler().block_count == 0); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 0); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -1070,12 +1070,12 @@ dst.set(10, 2.1); dst.set(11, 2.2); - assert(src.event_handler().block_count == 1); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 1); + TEST_ASSERT(dst.event_handler().block_count == 1); src.transfer(9, 9, dst, 9); - assert(src.event_handler().block_count == 0); - assert(dst.event_handler().block_count == 1); + TEST_ASSERT(src.event_handler().block_count == 0); + TEST_ASSERT(dst.event_handler().block_count == 1); } { @@ -1093,25 +1093,25 @@ db2.set(i, 10 + i); db2.set(5, 'Z'); - assert(db1.event_handler().block_count == 2); - assert(db1.event_handler().block_count_int32 == 1); - assert(db1.event_handler().block_count_string == 1); - - assert(db2.event_handler().block_count == 3); - assert(db2.event_handler().block_count_int32 == 2); - assert(db2.event_handler().block_count_int8 == 1); + TEST_ASSERT(db1.event_handler().block_count == 2); + TEST_ASSERT(db1.event_handler().block_count_int32 == 1); + TEST_ASSERT(db1.event_handler().block_count_string == 1); + + TEST_ASSERT(db2.event_handler().block_count == 3); + TEST_ASSERT(db2.event_handler().block_count_int32 == 2); + TEST_ASSERT(db2.event_handler().block_count_int8 == 1); db1.swap(1, 7, db2, 2); - assert(db1.event_handler().block_count == 3); - assert(db1.event_handler().block_count_int32 == 2); - assert(db1.event_handler().block_count_string == 0); - assert(db1.event_handler().block_count_int8 == 1); - - assert(db2.event_handler().block_count == 3); - assert(db2.event_handler().block_count_int32 == 2); - assert(db2.event_handler().block_count_int8 == 0); - assert(db2.event_handler().block_count_string == 1); + TEST_ASSERT(db1.event_handler().block_count == 3); + TEST_ASSERT(db1.event_handler().block_count_int32 == 2); + TEST_ASSERT(db1.event_handler().block_count_string == 0); + TEST_ASSERT(db1.event_handler().block_count_int8 == 1); + + TEST_ASSERT(db2.event_handler().block_count == 3); + TEST_ASSERT(db2.event_handler().block_count_int32 == 2); + TEST_ASSERT(db2.event_handler().block_count_int8 == 0); + TEST_ASSERT(db2.event_handler().block_count_string == 1); } } diff -Nru mdds-2.1.1/test/multi_type_vector/event/tc/block_init.inl mdds-3.1.0/test/multi_type_vector/event/tc/block_init.inl --- mdds-2.1.1/test/multi_type_vector/event/tc/block_init.inl 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/tc/block_init.inl 2025-07-03 16:15:17.000000000 +0000 @@ -55,26 +55,26 @@ void mtv_test_block_init() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; using mtv_type = mtv_template_type; { mtv_type db(event_block_init("some name")); // pass an rvalue - assert(db.event_handler().name == "some name"); - assert(db.event_handler().ctor_type == "move"); + TEST_ASSERT(db.event_handler().name == "some name"); + TEST_ASSERT(db.event_handler().ctor_type == "move"); auto db2{db}; - assert(db2.event_handler().name == "some name"); - assert(db2.event_handler().ctor_type == "copy"); + TEST_ASSERT(db2.event_handler().name == "some name"); + TEST_ASSERT(db2.event_handler().ctor_type == "copy"); } { event_block_init ebi("other name"); - assert(ebi.ctor_type == "normal"); + TEST_ASSERT(ebi.ctor_type == "normal"); mtv_type db(ebi); // pass an lvalue - assert(db.event_handler().name == "other name"); - assert(db.event_handler().ctor_type == "copy"); + TEST_ASSERT(db.event_handler().name == "other name"); + TEST_ASSERT(db.event_handler().ctor_type == "copy"); } } diff -Nru mdds-2.1.1/test/multi_type_vector/event/tc/swap.inl mdds-3.1.0/test/multi_type_vector/event/tc/swap.inl --- mdds-2.1.1/test/multi_type_vector/event/tc/swap.inl 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/event/tc/swap.inl 2025-07-03 16:15:17.000000000 +0000 @@ -43,24 +43,24 @@ void mtv_test_swap() { - stack_printer __stack_printer__(__FUNCTION__); + MDDS_TEST_FUNC_SCOPE; mtv_type db1(10), db2(2); db1.event_handler().name = "db1"; db2.event_handler().name = "db2"; - assert(db1.size() == 10); - assert(db2.size() == 2); - assert(db1.event_handler().name == "db1"); - assert(db2.event_handler().name == "db2"); + TEST_ASSERT(db1.size() == 10); + TEST_ASSERT(db2.size() == 2); + TEST_ASSERT(db1.event_handler().name == "db1"); + TEST_ASSERT(db2.event_handler().name == "db2"); // This should also swap the event handlers. db1.swap(db2); - assert(db1.size() == 2); - assert(db2.size() == 10); - assert(db1.event_handler().name == "db2"); - assert(db2.event_handler().name == "db1"); + TEST_ASSERT(db1.size() == 2); + TEST_ASSERT(db2.size() == 10); + TEST_ASSERT(db1.event_handler().name == "db2"); + TEST_ASSERT(db2.event_handler().name == "db1"); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/perf/Makefile.in mdds-3.1.0/test/multi_type_vector/perf/Makefile.in --- mdds-2.1.1/test/multi_type_vector/perf/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/perf/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -223,7 +223,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/Makefile.am mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.am --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.am 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,3 @@ +SUBDIRS = aos soa tc + +EXTRA_DIST = common_types.hpp diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/Makefile.in mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.in --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -0,0 +1,638 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = test/multi_type_vector/push-emplace-back +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +API_VERSION = @API_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NODEBUG = @CPPFLAGS_NODEBUG@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_UNITTESTS = @CXXFLAGS_UNITTESTS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +EXPECT = @EXPECT@ +GDB = @GDB@ +HAVE_CXX17 = @HAVE_CXX17@ +INCDIR = @INCDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MISCDIR = @MISCDIR@ +MKDIR_P = @MKDIR_P@ +OBJDIR = @OBJDIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RUNTEST_BIN = @RUNTEST_BIN@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX = @SPHINX@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +SUBDIRS = aos soa tc +EXTRA_DIST = common_types.hpp +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-recursive + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-recursive + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-recursive + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-recursive + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-recursive + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am check-valgrind-am check-valgrind-drd-am \ + check-valgrind-drd-local check-valgrind-helgrind-am \ + check-valgrind-helgrind-local check-valgrind-local \ + check-valgrind-memcheck-am check-valgrind-memcheck-local \ + check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ + clean-generic cscopelist-am ctags ctags-am distclean \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/Makefile.am mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.am --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.am 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,22 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/test/include \ + $(CXXFLAGS_UNITTESTS) + +check_PROGRAMS = test-main + +test_main_SOURCES = \ + test_main.cpp \ + test_push_back.cpp \ + $(top_srcdir)/test/test_global.cpp + +test_main_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../tc \ + $(AM_CPPFLAGS) + +EXTRA_DIST = test_main.hpp + +TESTS = test-main + +@VALGRIND_CHECK_RULES@ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/Makefile.in mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.in --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -0,0 +1,1048 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +check_PROGRAMS = test-main$(EXEEXT) +TESTS = test-main$(EXEEXT) +subdir = test/multi_type_vector/push-emplace-back/aos +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__dirstamp = $(am__leading_dot)dirstamp +am_test_main_OBJECTS = test_main-test_main.$(OBJEXT) \ + test_main-test_push_back.$(OBJEXT) \ + $(top_builddir)/test/test_main-test_global.$(OBJEXT) +test_main_OBJECTS = $(am_test_main_OBJECTS) +test_main_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po \ + ./$(DEPDIR)/test_main-test_main.Po \ + ./$(DEPDIR)/test_main-test_push_back.Po +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(test_main_SOURCES) +DIST_SOURCES = $(test_main_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +API_VERSION = @API_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NODEBUG = @CPPFLAGS_NODEBUG@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_UNITTESTS = @CXXFLAGS_UNITTESTS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +EXPECT = @EXPECT@ +GDB = @GDB@ +HAVE_CXX17 = @HAVE_CXX17@ +INCDIR = @INCDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MISCDIR = @MISCDIR@ +MKDIR_P = @MKDIR_P@ +OBJDIR = @OBJDIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RUNTEST_BIN = @RUNTEST_BIN@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX = @SPHINX@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/test/include \ + $(CXXFLAGS_UNITTESTS) + +test_main_SOURCES = \ + test_main.cpp \ + test_push_back.cpp \ + $(top_srcdir)/test/test_global.cpp + +test_main_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../tc \ + $(AM_CPPFLAGS) + +EXTRA_DIST = test_main.hpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/aos/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/aos/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) +$(top_builddir)/test/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/test + @: > $(top_builddir)/test/$(am__dirstamp) +$(top_builddir)/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/test/$(DEPDIR) + @: > $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) +$(top_builddir)/test/test_main-test_global.$(OBJEXT): \ + $(top_builddir)/test/$(am__dirstamp) \ + $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) + +test-main$(EXEEXT): $(test_main_OBJECTS) $(test_main_DEPENDENCIES) $(EXTRA_test_main_DEPENDENCIES) + @rm -f test-main$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_main_OBJECTS) $(test_main_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f $(top_builddir)/test/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main-test_main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main-test_push_back.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +test_main-test_main.o: test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_main.o -MD -MP -MF $(DEPDIR)/test_main-test_main.Tpo -c -o test_main-test_main.o `test -f 'test_main.cpp' || echo '$(srcdir)/'`test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_main.Tpo $(DEPDIR)/test_main-test_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_main.cpp' object='test_main-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_main.o `test -f 'test_main.cpp' || echo '$(srcdir)/'`test_main.cpp + +test_main-test_main.obj: test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_main.obj -MD -MP -MF $(DEPDIR)/test_main-test_main.Tpo -c -o test_main-test_main.obj `if test -f 'test_main.cpp'; then $(CYGPATH_W) 'test_main.cpp'; else $(CYGPATH_W) '$(srcdir)/test_main.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_main.Tpo $(DEPDIR)/test_main-test_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_main.cpp' object='test_main-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_main.obj `if test -f 'test_main.cpp'; then $(CYGPATH_W) 'test_main.cpp'; else $(CYGPATH_W) '$(srcdir)/test_main.cpp'; fi` + +test_main-test_push_back.o: test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_push_back.o -MD -MP -MF $(DEPDIR)/test_main-test_push_back.Tpo -c -o test_main-test_push_back.o `test -f 'test_push_back.cpp' || echo '$(srcdir)/'`test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_push_back.Tpo $(DEPDIR)/test_main-test_push_back.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_push_back.cpp' object='test_main-test_push_back.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_push_back.o `test -f 'test_push_back.cpp' || echo '$(srcdir)/'`test_push_back.cpp + +test_main-test_push_back.obj: test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_push_back.obj -MD -MP -MF $(DEPDIR)/test_main-test_push_back.Tpo -c -o test_main-test_push_back.obj `if test -f 'test_push_back.cpp'; then $(CYGPATH_W) 'test_push_back.cpp'; else $(CYGPATH_W) '$(srcdir)/test_push_back.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_push_back.Tpo $(DEPDIR)/test_main-test_push_back.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_push_back.cpp' object='test_main-test_push_back.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_push_back.obj `if test -f 'test_push_back.cpp'; then $(CYGPATH_W) 'test_push_back.cpp'; else $(CYGPATH_W) '$(srcdir)/test_push_back.cpp'; fi` + +$(top_builddir)/test/test_main-test_global.o: $(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT $(top_builddir)/test/test_main-test_global.o -MD -MP -MF $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo -c -o $(top_builddir)/test/test_main-test_global.o `test -f '$(top_builddir)/test/test_global.cpp' || echo '$(srcdir)/'`$(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(top_builddir)/test/test_global.cpp' object='$(top_builddir)/test/test_main-test_global.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o $(top_builddir)/test/test_main-test_global.o `test -f '$(top_builddir)/test/test_global.cpp' || echo '$(srcdir)/'`$(top_builddir)/test/test_global.cpp + +$(top_builddir)/test/test_main-test_global.obj: $(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT $(top_builddir)/test/test_main-test_global.obj -MD -MP -MF $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo -c -o $(top_builddir)/test/test_main-test_global.obj `if test -f '$(top_builddir)/test/test_global.cpp'; then $(CYGPATH_W) '$(top_builddir)/test/test_global.cpp'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/test/test_global.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(top_builddir)/test/test_global.cpp' object='$(top_builddir)/test/test_main-test_global.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o $(top_builddir)/test/test_main-test_global.obj `if test -f '$(top_builddir)/test/test_global.cpp'; then $(CYGPATH_W) '$(top_builddir)/test/test_global.cpp'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/test/test_global.cpp'; fi` +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +test-main.log: test-main$(EXEEXT) + @p='test-main$(EXEEXT)'; \ + b='test-main'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(top_builddir)/test/$(DEPDIR)/$(am__dirstamp)" || rm -f $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) + -test -z "$(top_builddir)/test/$(am__dirstamp)" || rm -f $(top_builddir)/test/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po + -rm -f ./$(DEPDIR)/test_main-test_main.Po + -rm -f ./$(DEPDIR)/test_main-test_push_back.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po + -rm -f ./$(DEPDIR)/test_main-test_main.Po + -rm -f ./$(DEPDIR)/test_main-test_push_back.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am check-valgrind-am check-valgrind-drd-am \ + check-valgrind-drd-local check-valgrind-helgrind-am \ + check-valgrind-helgrind-local check-valgrind-local \ + check-valgrind-memcheck-am check-valgrind-memcheck-local \ + check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ + clean-checkPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +@VALGRIND_CHECK_RULES@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_main.cpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.cpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.cpp 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#include "test_global.hpp" // This must be the first header to be included. +#include "test_main.hpp" + +int main() +{ + try + { + test_push_back_copy(); + test_push_back_move(); + test_emplace_back(); + } + catch (const std::exception& e) + { + std::cout << "test failed: " << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_main.hpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.hpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_main.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_main.hpp 2025-06-17 00:32:19.000000000 +0000 @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#pragma once + +#include "common_types.hpp" + +#define MDDS_MULTI_TYPE_VECTOR_DEBUG 1 +#include + +using mtv_type = mdds::mtv::aos::multi_type_vector; + +void test_push_back_copy(); +void test_push_back_move(); +void test_emplace_back(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_push_back.cpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_push_back.cpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/aos/test_push_back.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/aos/test_push_back.cpp 2025-06-17 00:32:19.000000000 +0000 @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#include "test_global.hpp" // This must be the first header to be included. +#include "test_main.hpp" + +#include "push_back.inl" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/common_types.hpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/common_types.hpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/common_types.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/common_types.hpp 2025-06-17 00:32:19.000000000 +0000 @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +struct data_block +{ + std::string value; + + data_block() = default; + + data_block(int v) + { + std::ostringstream os; + os << "int: " << v; + value = os.str(); + } + + data_block(float v) + { + std::ostringstream os; + os << "float: " << v; + value = os.str(); + } + + data_block(short a, short b) + { + std::ostringstream os; + os << "short+short: " << (a + b); + value = os.str(); + } +}; + +class user_cell +{ + std::unique_ptr data; + +public: + static std::size_t copy_count; + static std::size_t move_count; + + static void reset_counter() + { + copy_count = 0; + move_count = 0; + } + + static void print_counters() + { + std::cout << "user_cell: copy count=" << user_cell::copy_count << "; move count=" << user_cell::move_count + << std::endl; + } + + user_cell() : data(std::make_unique()) + { + std::cout << "default constructor" << std::endl; + } + + user_cell(const user_cell& other) : data(std::make_unique(*other.data)) + { + ++user_cell::copy_count; + std::cout << "copy constructor" << std::endl; + } + + user_cell(user_cell&& other) noexcept : data(std::move(other.data)) + { + ++user_cell::move_count; + std::cout << "move constructor" << std::endl; + } + + user_cell(int v) : data(std::make_unique(v)) + { + std::cout << "int constructor" << std::endl; + } + + user_cell(float v) : data(std::make_unique(v)) + { + std::cout << "float constructor" << std::endl; + } + + user_cell(short a, short b) : data(std::make_unique(a, b)) + { + std::cout << "short-short constructor" << std::endl; + } + + user_cell& operator=(const user_cell& other) + { + std::cout << "copy assignment" << std::endl; + data = std::make_unique(*other.data); + return *this; + } + + user_cell& operator=(user_cell&& other) + { + std::cout << "move assignment" << std::endl; + data = std::move(other.data); + return *this; + } + + std::string_view get_value() const + { + return data->value; + } +}; + +inline std::size_t user_cell::copy_count = 0; +inline std::size_t user_cell::move_count = 0; + +constexpr mdds::mtv::element_t element_type_user_block = mdds::mtv::element_type_user_start; + +using user_block = mdds::mtv::default_element_block; + +struct user_traits : public mdds::mtv::default_traits +{ + using block_funcs = mdds::mtv::element_block_funcs; +}; + +MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(user_cell, element_type_user_block, user_cell(), user_block) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/Makefile.am mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.am --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.am 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,22 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/test/include \ + $(CXXFLAGS_UNITTESTS) + +check_PROGRAMS = test-main + +test_main_SOURCES = \ + test_main.cpp \ + test_push_back.cpp \ + $(top_srcdir)/test/test_global.cpp + +test_main_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../tc \ + $(AM_CPPFLAGS) + +EXTRA_DIST = test_main.hpp + +TESTS = test-main + +@VALGRIND_CHECK_RULES@ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/Makefile.in mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.in --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -0,0 +1,1048 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +check_PROGRAMS = test-main$(EXEEXT) +TESTS = test-main$(EXEEXT) +subdir = test/multi_type_vector/push-emplace-back/soa +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__dirstamp = $(am__leading_dot)dirstamp +am_test_main_OBJECTS = test_main-test_main.$(OBJEXT) \ + test_main-test_push_back.$(OBJEXT) \ + $(top_builddir)/test/test_main-test_global.$(OBJEXT) +test_main_OBJECTS = $(am_test_main_OBJECTS) +test_main_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po \ + ./$(DEPDIR)/test_main-test_main.Po \ + ./$(DEPDIR)/test_main-test_push_back.Po +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(test_main_SOURCES) +DIST_SOURCES = $(test_main_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +API_VERSION = @API_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NODEBUG = @CPPFLAGS_NODEBUG@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_UNITTESTS = @CXXFLAGS_UNITTESTS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +EXPECT = @EXPECT@ +GDB = @GDB@ +HAVE_CXX17 = @HAVE_CXX17@ +INCDIR = @INCDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MISCDIR = @MISCDIR@ +MKDIR_P = @MKDIR_P@ +OBJDIR = @OBJDIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RUNTEST_BIN = @RUNTEST_BIN@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX = @SPHINX@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/test/include \ + $(CXXFLAGS_UNITTESTS) + +test_main_SOURCES = \ + test_main.cpp \ + test_push_back.cpp \ + $(top_srcdir)/test/test_global.cpp + +test_main_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../tc \ + $(AM_CPPFLAGS) + +EXTRA_DIST = test_main.hpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/soa/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/soa/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) +$(top_builddir)/test/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/test + @: > $(top_builddir)/test/$(am__dirstamp) +$(top_builddir)/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/test/$(DEPDIR) + @: > $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) +$(top_builddir)/test/test_main-test_global.$(OBJEXT): \ + $(top_builddir)/test/$(am__dirstamp) \ + $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) + +test-main$(EXEEXT): $(test_main_OBJECTS) $(test_main_DEPENDENCIES) $(EXTRA_test_main_DEPENDENCIES) + @rm -f test-main$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_main_OBJECTS) $(test_main_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f $(top_builddir)/test/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main-test_main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main-test_push_back.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +test_main-test_main.o: test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_main.o -MD -MP -MF $(DEPDIR)/test_main-test_main.Tpo -c -o test_main-test_main.o `test -f 'test_main.cpp' || echo '$(srcdir)/'`test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_main.Tpo $(DEPDIR)/test_main-test_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_main.cpp' object='test_main-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_main.o `test -f 'test_main.cpp' || echo '$(srcdir)/'`test_main.cpp + +test_main-test_main.obj: test_main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_main.obj -MD -MP -MF $(DEPDIR)/test_main-test_main.Tpo -c -o test_main-test_main.obj `if test -f 'test_main.cpp'; then $(CYGPATH_W) 'test_main.cpp'; else $(CYGPATH_W) '$(srcdir)/test_main.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_main.Tpo $(DEPDIR)/test_main-test_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_main.cpp' object='test_main-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_main.obj `if test -f 'test_main.cpp'; then $(CYGPATH_W) 'test_main.cpp'; else $(CYGPATH_W) '$(srcdir)/test_main.cpp'; fi` + +test_main-test_push_back.o: test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_push_back.o -MD -MP -MF $(DEPDIR)/test_main-test_push_back.Tpo -c -o test_main-test_push_back.o `test -f 'test_push_back.cpp' || echo '$(srcdir)/'`test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_push_back.Tpo $(DEPDIR)/test_main-test_push_back.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_push_back.cpp' object='test_main-test_push_back.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_push_back.o `test -f 'test_push_back.cpp' || echo '$(srcdir)/'`test_push_back.cpp + +test_main-test_push_back.obj: test_push_back.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_main-test_push_back.obj -MD -MP -MF $(DEPDIR)/test_main-test_push_back.Tpo -c -o test_main-test_push_back.obj `if test -f 'test_push_back.cpp'; then $(CYGPATH_W) 'test_push_back.cpp'; else $(CYGPATH_W) '$(srcdir)/test_push_back.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_main-test_push_back.Tpo $(DEPDIR)/test_main-test_push_back.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test_push_back.cpp' object='test_main-test_push_back.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_main-test_push_back.obj `if test -f 'test_push_back.cpp'; then $(CYGPATH_W) 'test_push_back.cpp'; else $(CYGPATH_W) '$(srcdir)/test_push_back.cpp'; fi` + +$(top_builddir)/test/test_main-test_global.o: $(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT $(top_builddir)/test/test_main-test_global.o -MD -MP -MF $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo -c -o $(top_builddir)/test/test_main-test_global.o `test -f '$(top_builddir)/test/test_global.cpp' || echo '$(srcdir)/'`$(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(top_builddir)/test/test_global.cpp' object='$(top_builddir)/test/test_main-test_global.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o $(top_builddir)/test/test_main-test_global.o `test -f '$(top_builddir)/test/test_global.cpp' || echo '$(srcdir)/'`$(top_builddir)/test/test_global.cpp + +$(top_builddir)/test/test_main-test_global.obj: $(top_builddir)/test/test_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT $(top_builddir)/test/test_main-test_global.obj -MD -MP -MF $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo -c -o $(top_builddir)/test/test_main-test_global.obj `if test -f '$(top_builddir)/test/test_global.cpp'; then $(CYGPATH_W) '$(top_builddir)/test/test_global.cpp'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/test/test_global.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Tpo $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(top_builddir)/test/test_global.cpp' object='$(top_builddir)/test/test_main-test_global.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_main_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o $(top_builddir)/test/test_main-test_global.obj `if test -f '$(top_builddir)/test/test_global.cpp'; then $(CYGPATH_W) '$(top_builddir)/test/test_global.cpp'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/test/test_global.cpp'; fi` +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +test-main.log: test-main$(EXEEXT) + @p='test-main$(EXEEXT)'; \ + b='test-main'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(top_builddir)/test/$(DEPDIR)/$(am__dirstamp)" || rm -f $(top_builddir)/test/$(DEPDIR)/$(am__dirstamp) + -test -z "$(top_builddir)/test/$(am__dirstamp)" || rm -f $(top_builddir)/test/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po + -rm -f ./$(DEPDIR)/test_main-test_main.Po + -rm -f ./$(DEPDIR)/test_main-test_push_back.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(top_builddir)/test/$(DEPDIR)/test_main-test_global.Po + -rm -f ./$(DEPDIR)/test_main-test_main.Po + -rm -f ./$(DEPDIR)/test_main-test_push_back.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am check-valgrind-am check-valgrind-drd-am \ + check-valgrind-drd-local check-valgrind-helgrind-am \ + check-valgrind-helgrind-local check-valgrind-local \ + check-valgrind-memcheck-am check-valgrind-memcheck-local \ + check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ + clean-checkPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +@VALGRIND_CHECK_RULES@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_main.cpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.cpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.cpp 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#include "test_global.hpp" // This must be the first header to be included. +#include "test_main.hpp" + +int main() +{ + try + { + test_push_back_copy(); + test_push_back_move(); + test_emplace_back(); + } + catch (const std::exception& e) + { + std::cout << "test failed: " << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_main.hpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.hpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_main.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_main.hpp 2025-06-17 00:32:19.000000000 +0000 @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#pragma once + +#include "common_types.hpp" + +#define MDDS_MULTI_TYPE_VECTOR_DEBUG 1 +#include + +using mtv_type = mdds::mtv::soa::multi_type_vector; + +void test_push_back_copy(); +void test_push_back_move(); +void test_emplace_back(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_push_back.cpp mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_push_back.cpp --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/soa/test_push_back.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/soa/test_push_back.cpp 2025-06-17 00:32:19.000000000 +0000 @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +#include "test_global.hpp" // This must be the first header to be included. +#include "test_main.hpp" + +#include "push_back.inl" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/Makefile.am mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.am --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.am 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,2 @@ +EXTRA_DIST = \ + push_back.inl diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/Makefile.in mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.in --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -0,0 +1,461 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = test/multi_type_vector/push-emplace-back/tc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +API_VERSION = @API_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NODEBUG = @CPPFLAGS_NODEBUG@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_UNITTESTS = @CXXFLAGS_UNITTESTS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +EXPECT = @EXPECT@ +GDB = @GDB@ +HAVE_CXX17 = @HAVE_CXX17@ +INCDIR = @INCDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MISCDIR = @MISCDIR@ +MKDIR_P = @MKDIR_P@ +OBJDIR = @OBJDIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RUNTEST_BIN = @RUNTEST_BIN@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX = @SPHINX@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +EXTRA_DIST = \ + push_back.inl + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/tc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/multi_type_vector/push-emplace-back/tc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am check-valgrind-am \ + check-valgrind-drd-am check-valgrind-drd-local \ + check-valgrind-helgrind-am check-valgrind-helgrind-local \ + check-valgrind-local check-valgrind-memcheck-am \ + check-valgrind-memcheck-local check-valgrind-sgcheck-am \ + check-valgrind-sgcheck-local clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/push_back.inl mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/push_back.inl --- mdds-2.1.1/test/multi_type_vector/push-emplace-back/tc/push_back.inl 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/multi_type_vector/push-emplace-back/tc/push_back.inl 2025-06-13 02:56:24.000000000 +0000 @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2025 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. + * + ************************************************************************/ + +void test_push_back_copy() +{ + MDDS_TEST_FUNC_SCOPE; + + mtv_type vec; + user_cell::reset_counter(); + + user_cell v; + const user_cell& vref = v; + + // first push_back() call should trigger 1 copy and 0 moves + auto it = vec.push_back(vref); + TEST_ASSERT(it == std::prev(vec.end())); + + user_cell::print_counters(); + TEST_ASSERT(user_cell::copy_count == 1); + TEST_ASSERT(!user_cell::move_count); + + // second push_back() call should trigger another copy, it also may cause + // one move due to reallocation of the buffer in the destination storage, + // so we don't check the move counter. + it = vec.push_back(vref); + TEST_ASSERT(it == std::prev(vec.end())); + user_cell::print_counters(); + TEST_ASSERT(user_cell::copy_count == 2); +} + +void test_push_back_move() +{ + MDDS_TEST_FUNC_SCOPE; + + mtv_type vec; + user_cell::reset_counter(); + + { + // first push_back() call should trigger 0 copies and 1 move + user_cell v; + auto it = vec.push_back(std::move(v)); + TEST_ASSERT(it == std::prev(vec.end())); + + user_cell::print_counters(); + TEST_ASSERT(!user_cell::copy_count); + TEST_ASSERT(user_cell::move_count == 1); + } + + { + // second push_back() call should still trigger 0 copies and may trigger + // move than 2 moves due to buffer reallocation of the destination + // storage + user_cell v; + auto it = vec.push_back(std::move(v)); + TEST_ASSERT(it == std::prev(vec.end())); + user_cell::print_counters(); + TEST_ASSERT(!user_cell::copy_count); + TEST_ASSERT(user_cell::move_count >= 2); + } +} + +void test_emplace_back() +{ + MDDS_TEST_FUNC_SCOPE; + + mtv_type vec; + auto it = vec.emplace_back(int(12)); + TEST_ASSERT(it == std::prev(vec.end())); + + it = vec.emplace_back(float(-42)); + TEST_ASSERT(it == std::prev(vec.end())); + + vec.push_back_empty(); + + it = vec.emplace_back(short(18), short(12)); + TEST_ASSERT(it == std::prev(vec.end())); + + TEST_ASSERT(vec.get(0).get_value() == "int: 12"); + TEST_ASSERT(vec.get(1).get_value() == "float: -42"); + TEST_ASSERT(vec.get(3).get_value() == "short+short: 30"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/point_quad_tree/Makefile.in mdds-3.1.0/test/point_quad_tree/Makefile.in --- mdds-2.1.1/test/point_quad_tree/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/point_quad_tree/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -430,7 +430,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/point_quad_tree/test_main.cpp mdds-3.1.0/test/point_quad_tree/test_main.cpp --- mdds-2.1.1/test/point_quad_tree/test_main.cpp 2022-10-28 01:42:14.000000000 +0000 +++ mdds-3.1.0/test/point_quad_tree/test_main.cpp 2025-07-03 17:05:06.000000000 +0000 @@ -26,7 +26,8 @@ ************************************************************************/ #include "test_global.hpp" // This must be the first header to be included. -#include "mdds/point_quad_tree.hpp" + +#include #include #include @@ -34,13 +35,12 @@ #include #include -using namespace std; using namespace mdds; using ::boost::uint16_t; struct data_printer { - void operator()(const string* p) + void operator()(const std::string* p) { cout << *p << " "; } @@ -49,7 +49,7 @@ template struct search_result_printer { - void operator()(const pair& r) const + void operator()(const std::pair& r) const { cout << " (x=" << r.first.x << ", y=" << r.first.y << ", value='" << *r.second << "')" << endl; } @@ -57,24 +57,25 @@ void pqt_test_basic() { - stack_printer __stack_printer__("::pqt_test"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db; - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); - string G("G"); - string H("H"); - string I("I"); - string J("J"); - string K("K"); - string L("L"); - string M("M"); - string N("N"); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); + std::string G("G"); + std::string H("H"); + std::string I("I"); + std::string J("J"); + std::string K("K"); + std::string L("L"); + std::string M("M"); + std::string N("N"); db.insert(25, 32, &A); db.insert(5, 45, &B); @@ -91,7 +92,7 @@ db.insert(39, 78, &M); db.insert(72, 52, &N); - assert(db.size() == 14); + TEST_ASSERT(db.size() == 14); cout << "node count = " << get_node_instance_count() << endl; db.dump_tree_svg("./obj/test.svg"); @@ -124,35 +125,36 @@ db.remove(20, 20); db.remove(40, 50); - assert(db.size() == 12); + TEST_ASSERT(db.size() == 12); db.dump_tree_svg("./obj/test-remove.svg"); db.clear(); - assert(db.empty()); - assert(db.size() == 0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db.size() == 0); } void pqt_test_insertion_removal() { - stack_printer __stack_printer__("::pqt_test_insertion_removal"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db; // Check its empty-ness... - assert(db.empty()); - assert(db.size() == 0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db.size() == 0); // Create all data instances. - vector> data_store; + std::vector> data_store; data_store.reserve(100); for (size_t i = 0; i < 100; ++i) { - ostringstream os; - os << "0x" << hex << i; - data_store.emplace_back(new string(os.str())); + std::ostringstream os; + os << "0x" << std::hex << i; + data_store.emplace_back(new std::string(os.str())); } - vector expected; + std::vector expected; // Insert data one by one, and verify each insertion. for (int32_t i = 0; i < 10; ++i) @@ -161,18 +163,18 @@ { int32_t x = i * 10 + 1, y = j * 10 + 1; size_t index = i * 10 + j; - const string* data_ptr = data_store[index].get(); + const std::string* data_ptr = data_store[index].get(); cout << "inserting '" << *data_ptr << "' at (" << x << "," << y << ")" << endl; db.insert(x, y, data_ptr); expected.push_back(db_type::node_data(x, y, data_ptr)); - vector stored_data; + std::vector stored_data; db.get_all_stored_data(stored_data); - assert(stored_data.size() == (index + 1)); - assert(db.size() == (index + 1)); - assert(!db.empty()); + TEST_ASSERT(stored_data.size() == (index + 1)); + TEST_ASSERT(db.size() == (index + 1)); + TEST_ASSERT(!db.empty()); bool success = db.verify_data(expected); - assert(success); + TEST_ASSERT(success); } } db.dump_tree_svg("./obj/pqt_test_insertion.svg"); @@ -189,20 +191,21 @@ cout << "removing node at (" << x << "," << y << ") " << "size after removal: " << n << endl; --node_count; - assert(node_count == n); + TEST_ASSERT(node_count == n); } } } void pqt_test_remove_root() { - stack_printer __stack_printer__("::pqt_test_remove_root"); - typedef point_quad_tree db_type; - string O("O"); - string NW("NW"); - string NE("NE"); - string SW("SW"); - string SE("SE"); + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; + std::string O("O"); + std::string NW("NW"); + std::string NE("NE"); + std::string SW("SW"); + std::string SE("SE"); db_type db; // Insert all data and verify their storage. @@ -213,15 +216,15 @@ db.insert(0, 20, &SW); db.dump_tree_svg("./obj/pqt_test_remove_root-1.svg"); - vector expected; + std::vector expected; expected.push_back(db_type::node_data(10, 10, &O)); expected.push_back(db_type::node_data(20, 0, &NE)); expected.push_back(db_type::node_data(0, 0, &NW)); expected.push_back(db_type::node_data(20, 20, &SE)); expected.push_back(db_type::node_data(0, 20, &SW)); bool success = db.verify_data(expected); - assert(success); - assert(db.size() == 5); + TEST_ASSERT(success); + TEST_ASSERT(db.size() == 5); // Now, remove the root node. db.remove(10, 10); @@ -232,41 +235,41 @@ expected.push_back(db_type::node_data(20, 20, &SE)); expected.push_back(db_type::node_data(0, 20, &SW)); success = db.verify_data(expected); - assert(success); - assert(db.size() == 4); + TEST_ASSERT(success); + TEST_ASSERT(db.size() == 4); } void pqt_test_equality() { - stack_printer __stack_printer__("::pqt_test_equality"); + MDDS_TEST_FUNC_SCOPE; - typedef point_quad_tree db_type; + typedef point_quad_tree db_type; db_type db1, db2; - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); - assert(db1 == db2); // both are empty. + TEST_ASSERT(db1 == db2); // both are empty. db1.insert(0, 0, &A); db2.insert(0, 0, &A); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.remove(0, 0); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.insert(0, 0, &B); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db2.insert(0, 0, &B); // B overwrites A. - assert(db1 == db2); // Both should have B at (0,0). + TEST_ASSERT(db1 == db2); // Both should have B at (0,0). db1.insert(1, 1, &C); db2.insert(2, 2, &C); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.insert(2, 2, &C); db2.insert(1, 1, &C); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); // Inserting data in different orders should make no difference in equality. db1.insert(1, 3, &D); @@ -276,86 +279,88 @@ db2.insert(1, 5, &F); db2.insert(1, 4, &E); db2.insert(1, 3, &D); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.remove(1, 4); db2.remove(1, 4); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); // Make them empty again. db1.clear(); db2.clear(); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); } void pqt_test_assignment() { - stack_printer __stack_printer__("::pqt_test_assignment"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db1, db2; - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); db1.insert(0, 10, &A); db1.insert(2, 5, &B); db1.insert(-10, 2, &C); db1.insert(5, 7, &D); - vector expected; + std::vector expected; expected.push_back(db_type::node_data(0, 10, &A)); expected.push_back(db_type::node_data(2, 5, &B)); expected.push_back(db_type::node_data(-10, 2, &C)); expected.push_back(db_type::node_data(5, 7, &D)); bool success = db1.verify_data(expected); - assert(success); + TEST_ASSERT(success); db2 = db1; success = db2.verify_data(expected); - assert(success); + TEST_ASSERT(success); success = db1.verify_data(expected); - assert(success); + TEST_ASSERT(success); db2.insert(12, 45, &E); db2.insert(20, 42, &F); success = db2.verify_data(expected); // This should fail. - assert(!success); + TEST_ASSERT(!success); db2 = db1; // Assign once again. success = db2.verify_data(expected); // This now should succeed. - assert(success); + TEST_ASSERT(success); } void pqt_test_swap() { - stack_printer __stack_printer__("::pqt_test_swap"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db1, db2; - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); db1.insert(0, 10, &A); db1.insert(2, 5, &B); db1.insert(-10, 2, &C); db1.insert(5, 7, &D); - vector expected; + std::vector expected; expected.push_back(db_type::node_data(0, 10, &A)); expected.push_back(db_type::node_data(2, 5, &B)); expected.push_back(db_type::node_data(-10, 2, &C)); expected.push_back(db_type::node_data(5, 7, &D)); bool success = db1.verify_data(expected); - assert(success); - assert(db2.empty()); + TEST_ASSERT(success); + TEST_ASSERT(db2.empty()); db1.swap(db2); - assert(db1.empty()); - assert(!db2.empty()); + TEST_ASSERT(db1.empty()); + TEST_ASSERT(!db2.empty()); success = db2.verify_data(expected); - assert(success); + TEST_ASSERT(success); } template @@ -379,77 +384,79 @@ void pqt_test_find() { - stack_printer __stack_printer__("::pqt_test_find"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db; - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); db.insert(92, 27, &A); db.insert(53, 26, &B); db.insert(69, 18, &C); db.insert(0, 78, &D); db.insert(17, 7, &E); db.insert(91, 88, &F); - assert(db.size() == 6); + TEST_ASSERT(db.size() == 6); db.dump_tree_svg("obj/pqt_test_find.svg"); bool check; check = verify_find(db, 92, 27, &A); - assert(check); + TEST_ASSERT(check); check = verify_find(db, 53, 26, &B); - assert(check); + TEST_ASSERT(check); check = verify_find(db, 69, 18, &C); - assert(check); + TEST_ASSERT(check); check = verify_find(db, 0, 78, &D); - assert(check); + TEST_ASSERT(check); check = verify_find(db, 17, 7, &E); - assert(check); + TEST_ASSERT(check); check = verify_find(db, 91, 88, &F); - assert(check); + TEST_ASSERT(check); // Check for non-existent data. check = verify_find(db, 34, 86, &A); - assert(!check); + TEST_ASSERT(!check); check = verify_find(db, -1, 7, &A); - assert(!check); + TEST_ASSERT(!check); check = verify_find(db, 91, 27, &A); - assert(!check); + TEST_ASSERT(!check); } void pqt_test_node_access() { - stack_printer __stack_printer__("::pqt_test_node_access"); - typedef point_quad_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef point_quad_tree db_type; db_type db; db_type::node_access nac = db.get_node_access(); - assert(!nac); - string A("A"); - string B("B"); - string C("C"); - string D("D"); - string E("E"); - string F("F"); + TEST_ASSERT(!nac); + std::string A("A"); + std::string B("B"); + std::string C("C"); + std::string D("D"); + std::string E("E"); + std::string F("F"); db.insert(92, 27, &A); db.insert(53, 26, &B); db.insert(69, 18, &C); db.insert(0, 78, &D); db.insert(17, 7, &E); db.insert(91, 88, &F); - assert(db.size() == 6); + TEST_ASSERT(db.size() == 6); nac = db.get_node_access(); // Test root node. - assert(nac); - assert(nac.x() == 92); - assert(nac.y() == 27); - assert(nac.data() == &A); + TEST_ASSERT(nac); + TEST_ASSERT(nac.x() == 92); + TEST_ASSERT(nac.y() == 27); + TEST_ASSERT(nac.data() == &A); bool success = db.verify_node_iterator(nac); - assert(success); + TEST_ASSERT(success); } int main() @@ -464,7 +471,7 @@ pqt_test_swap(); pqt_test_find(); pqt_test_node_access(); - assert(get_node_instance_count() == 0); + TEST_ASSERT(get_node_instance_count() == 0); } catch (const std::exception& e) { diff -Nru mdds-2.1.1/test/ref_pair_test.cpp mdds-3.1.0/test/ref_pair_test.cpp --- mdds-2.1.1/test/ref_pair_test.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/ref_pair_test.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -31,11 +31,9 @@ #include -using namespace std; - void test_basic() { - stack_printer __stack_printer__("::test_basic"); + MDDS_TEST_FUNC_SCOPE; using rp_type = mdds::detail::ref_pair; using pair_type = std::pair; @@ -46,24 +44,24 @@ rp.second = 34; - assert(rp == pair_type(11, 34)); - assert(rp != pair_type(12, 34)); - assert(rp != pair_type(11, 32)); - assert(rp == rp); + TEST_ASSERT(rp == pair_type(11, 34)); + TEST_ASSERT(rp != pair_type(12, 34)); + TEST_ASSERT(rp != pair_type(11, 32)); + TEST_ASSERT(rp == rp); int v3 = 23; int v4 = 33; rp_type rp2(v3, v4); - assert(rp != rp2); - assert(rp2 == pair_type(23, 33)); + TEST_ASSERT(rp != rp2); + TEST_ASSERT(rp2 == pair_type(23, 33)); rp_type rp3(rp); - assert(rp3 == rp); + TEST_ASSERT(rp3 == rp); } void test_used_in_iterator() { - stack_printer __stack_printer__("::test_used_in_iterator"); + MDDS_TEST_FUNC_SCOPE; using rp_type = mdds::detail::ref_pair; @@ -88,16 +86,16 @@ fake_iterator it; - assert((*it).first == 222); - assert((*it).second == 456); - assert(it->first == 222); - assert(it->second == 456); + TEST_ASSERT((*it).first == 222); + TEST_ASSERT((*it).second == 456); + TEST_ASSERT(it->first == 222); + TEST_ASSERT(it->second == 456); // Make sure the member values can be modified. it->second = 897; - assert(it->second == 897); + TEST_ASSERT(it->second == 897); (*it).first = -23; - assert(it->first == -23); + TEST_ASSERT(it->first == -23); } int main() diff -Nru mdds-2.1.1/test/rtree/Makefile.in mdds-3.1.0/test/rtree/Makefile.in --- mdds-2.1.1/test/rtree/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/rtree/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -453,7 +453,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/rtree/test_basic.cpp mdds-3.1.0/test/rtree/test_basic.cpp --- mdds-2.1.1/test/rtree/test_basic.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_basic.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_basic_search() { - stack_printer __stack_printer__("::rtree_test_basic_search"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using search_type = rt_type::search_type; rt_type::integrity_check_properties check_props; @@ -47,18 +48,18 @@ tree.insert({{0, 0}, {2, 2}}, "test"); expected_bb = {{0, 0}, {2, 2}}; - assert(tree.extent() == expected_bb); - assert(tree.size() == 1); + TEST_ASSERT(tree.extent() == expected_bb); + TEST_ASSERT(tree.size() == 1); tree.insert({{3, 3}, {5, 5}}, "test again"); expected_bb = {{0, 0}, {5, 5}}; - assert(tree.extent() == expected_bb); - assert(tree.size() == 2); + TEST_ASSERT(tree.extent() == expected_bb); + TEST_ASSERT(tree.size() == 2); tree.insert({{-2, 1}, {3, 6}}, "more test"); expected_bb = {{-2, 0}, {5, 6}}; - assert(tree.extent() == expected_bb); - assert(tree.size() == 3); + TEST_ASSERT(tree.extent() == expected_bb); + TEST_ASSERT(tree.size() == 3); tree.check_integrity(check_props); @@ -69,7 +70,7 @@ auto it = res.cbegin(), it_end = res.cend(); size_t n = std::distance(it, it_end); - assert(n == 2); + TEST_ASSERT(n == 2); std::unordered_map expected_values = { {"test", {{0, 0}, {2, 2}}}, @@ -80,9 +81,9 @@ { cout << "bounding box: " << it.extent().to_string() << "; value: " << *it << "; depth: " << it.depth() << endl; auto itv = expected_values.find(*it); - assert(itv != expected_values.end()); - assert(itv->second == it.extent()); - assert(it.depth() == 1); + TEST_ASSERT(itv != expected_values.end()); + TEST_ASSERT(itv->second == it.extent()); + TEST_ASSERT(it.depth() == 1); } // Perform an out-of-bound search by point. @@ -95,13 +96,14 @@ for (const rt_type::point_type& pt : pts) { res = ctree.search(pt, search_type::overlap); - assert(res.cbegin() == res.cend()); + TEST_ASSERT(res.cbegin() == res.cend()); } } void rtree_test_basic_erase() { - stack_printer __stack_printer__("::rtree_test_basic_erase"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using search_type = rt_type::search_type; rt_type::integrity_check_properties check_props; @@ -110,37 +112,37 @@ rt_type tree; const rt_type& ctree = tree; tree.insert({{-2, -2}, {2, 2}}, "erase me"); - assert(!tree.empty()); - assert(tree.size() == 1); + TEST_ASSERT(!tree.empty()); + TEST_ASSERT(tree.size() == 1); rt_type::const_search_results res = ctree.search({0, 0}, search_type::overlap); size_t n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); rt_type::const_iterator it = res.begin(); - assert(it != res.end()); + TEST_ASSERT(it != res.end()); tree.erase(it); - assert(tree.empty()); - assert(tree.size() == 0); - assert(rt_type::extent_type() == tree.extent()); + TEST_ASSERT(tree.empty()); + TEST_ASSERT(tree.size() == 0); + TEST_ASSERT(rt_type::extent_type() == tree.extent()); tree.insert({{0, 0}, {2, 2}}, "erase me"); tree.insert({{-10, -4}, {0, 0}}, "erase me"); rt_type::extent_type expected_bb({-10, -4}, {2, 2}); - assert(tree.extent() == expected_bb); - assert(tree.size() == 2); + TEST_ASSERT(tree.extent() == expected_bb); + TEST_ASSERT(tree.size() == 2); res = ctree.search({-5, -2}, search_type::overlap); n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it = res.begin(); tree.erase(it); - assert(!tree.empty()); // there should be one value stored in the tree. - assert(tree.size() == 1); + TEST_ASSERT(!tree.empty()); // there should be one value stored in the tree. + TEST_ASSERT(tree.size() == 1); expected_bb = {{0, 0}, {2, 2}}; - assert(tree.extent() == expected_bb); + TEST_ASSERT(tree.extent() == expected_bb); tree.check_integrity(check_props); } diff -Nru mdds-2.1.1/test/rtree/test_bulkload_main.cpp mdds-3.1.0/test/rtree/test_bulkload_main.cpp --- mdds-2.1.1/test/rtree/test_bulkload_main.cpp 2022-10-26 01:43:36.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_bulkload_main.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -38,7 +38,8 @@ void rtree_test_bl_empty() { - stack_printer __stack_printer__("::rtree_test_bl_empty"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; rt_type::integrity_check_properties check_props; check_props.throw_on_first_error = false; @@ -46,13 +47,14 @@ // Load nothing. rt_type::bulk_loader loader; rt_type tree = loader.pack(); - assert(tree.empty()); + TEST_ASSERT(tree.empty()); tree.check_integrity(check_props); } void rtree_test_bl_insert_points_move() { - stack_printer __stack_printer__("::rtree_test_bl_insert_points_move"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using key_type = rt_type::key_type; rt_type::integrity_check_properties check_props; @@ -71,14 +73,15 @@ } auto tree = loader.pack(); - assert(tree.size() == 399); + TEST_ASSERT(tree.size() == 399); tree.check_integrity(check_props); export_tree(tree, "rtree-test-bl-insert-points-move"); } void rtree_test_bl_insert_points_copy() { - stack_printer __stack_printer__("::rtree_test_bl_insert_points_copy"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using point_type = rt_type::point_type; using search_type = rt_type::search_type; @@ -99,7 +102,7 @@ // Insert less than max node size in order to test the packing // implementation that doesn't involve per-level packing. tiny_trait_2d_forced_reinsertion t; - assert(values.size() <= t.max_node_size); + TEST_ASSERT(values.size() <= t.max_node_size); for (size_t n_values = 1; n_values <= values.size(); ++n_values) { @@ -112,26 +115,27 @@ // Populate and pack the tree. auto tree = loader.pack(); tree.check_integrity(check_props); - assert(tree.size() == n_values); + TEST_ASSERT(tree.size() == n_values); // Make sure the inserted values are all there. for (size_t i = 0; i < n_values; ++i) { auto res = tree.search(values[i].point, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); auto it = res.begin(); - assert(*it == values[i].value); + TEST_ASSERT(*it == values[i].value); // The values should all be the immediate children of the root // directory node. - assert(it.depth() == 1); + TEST_ASSERT(it.depth() == 1); } } } void rtree_test_bl_insert_extents_move() { - stack_printer __stack_printer__("::rtree_test_bl_insert_extents_move"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using extent_type = rt_type::extent_type; using search_type = rt_type::search_type; @@ -172,7 +176,7 @@ } auto tree = loader.pack(); - assert(tree.size() == n_values); + TEST_ASSERT(tree.size() == n_values); tree.check_integrity(check_props); // Make sure the values are all there. @@ -181,8 +185,8 @@ const auto& v = values[i]; extent_type extent{{v.x, v.y}, {int16_t(v.x + v.w), int16_t(v.y + v.h)}}; auto res = tree.search(extent, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); - assert(res.begin()->get() == v.value); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(res.begin()->get() == v.value); } if (n_values == values.size()) @@ -192,7 +196,8 @@ void rtree_test_bl_insert_extents_copy() { - stack_printer __stack_printer__("::rtree_test_bl_insert_extents_copy"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using extent_type = rt_type::extent_type; using search_type = rt_type::search_type; @@ -240,7 +245,7 @@ } auto tree = loader.pack(); - assert(tree.size() == n_values); + TEST_ASSERT(tree.size() == n_values); tree.check_integrity(check_props); // Make sure the values are all there. @@ -249,8 +254,8 @@ const auto& v = values[i]; extent_type extent{{v.x, v.y}, {int16_t(v.x + v.w), int16_t(v.y + v.h)}}; auto res = tree.search(extent, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); - assert(res.begin()->get() == v.value); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(res.begin()->get() == v.value); } if (n_values == values.size()) diff -Nru mdds-2.1.1/test/rtree/test_copy.cpp mdds-3.1.0/test/rtree/test_copy.cpp --- mdds-2.1.1/test/rtree/test_copy.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_copy.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_copy() { - stack_printer __stack_printer__("::rtree_test_copy"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using point_type = rt_type::point_type; @@ -68,14 +68,14 @@ std::string str_src = tree.export_tree(rt_type::export_tree_type::formatted_node_properties); std::string str_dst = tree.export_tree(rt_type::export_tree_type::formatted_node_properties); - assert(!str_src.empty() && str_src == str_dst); + TEST_ASSERT(!str_src.empty() && str_src == str_dst); // Test the "copy via assignment" scenario too. auto copied_via_assign = tree; copied_via_assign.check_integrity(check_props); str_dst = copied_via_assign.export_tree(rt_type::export_tree_type::formatted_node_properties); - assert(!str_src.empty() && str_src == str_dst); + TEST_ASSERT(!str_src.empty() && str_src == str_dst); } /** @@ -84,7 +84,7 @@ */ void rtree_test_only_copyable() { - stack_printer __stack_printer__("::rtree_test_only_copyable"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using search_type = rt_type::search_type; @@ -104,43 +104,43 @@ { // Immutable search. auto cres = ctree.search({1, 1}, search_type::overlap); - assert(std::distance(cres.begin(), cres.end()) == 1); - assert(cres.begin()->get() == 11.2); + TEST_ASSERT(std::distance(cres.begin(), cres.end()) == 1); + TEST_ASSERT(cres.begin()->get() == 11.2); cres = ctree.search({9, 9}, search_type::overlap); - assert(std::distance(cres.cbegin(), cres.cend()) == 1); - assert(cres.cbegin()->get() == 12.5); + TEST_ASSERT(std::distance(cres.cbegin(), cres.cend()) == 1); + TEST_ASSERT(cres.cbegin()->get() == 12.5); } { // Mutable search auto res = tree.search({9, 9}, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); - assert(res.begin()->get() == 12.5); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(res.begin()->get() == 12.5); auto it = res.begin(); (*it).set(34.5); res = tree.search({9, 9}, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); - assert(res.begin()->get() == 34.5); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(res.begin()->get() == 34.5); } { // Erase the only object via mutable iterator. - assert(tree.size() == 2); + TEST_ASSERT(tree.size() == 2); rt_type::search_results res = tree.search({{0, 0}, {100, 100}}, search_type::overlap); - assert(std::distance(res.begin(), res.end()) == 2); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 2); res = tree.search({9, 9}, search_type::match); - assert(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); tree.erase(res.begin()); - assert(tree.size() == 1); + TEST_ASSERT(tree.size() == 1); res = tree.search({{0, 0}, {100, 100}}, search_type::overlap); - assert(std::distance(res.begin(), res.end()) == 1); + TEST_ASSERT(std::distance(res.begin(), res.end()) == 1); auto it = res.begin(); - assert(it.extent() == extent_type({{0, 0}, {2, 5}})); - assert(it->get() == 11.2); + TEST_ASSERT(it.extent() == extent_type({{0, 0}, {2, 5}})); + TEST_ASSERT(it->get() == 11.2); } } diff -Nru mdds-2.1.1/test/rtree/test_directory_node_split.cpp mdds-3.1.0/test/rtree/test_directory_node_split.cpp --- mdds-2.1.1/test/rtree/test_directory_node_split.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_directory_node_split.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_directory_node_split() { - stack_printer __stack_printer__("::rtree_test_directory_node_split"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using search_type = rt_type::search_type; rt_type::integrity_check_properties check_props; @@ -62,7 +63,7 @@ } } - assert(tree.size() == 100); + TEST_ASSERT(tree.size() == 100); // All value nodes in this tree should be at depth 4 (root having the // depth of 0). Just check a few of them. @@ -77,8 +78,8 @@ { auto res = ctree.search(pt, search_type::overlap); auto it = res.cbegin(); - assert(it != res.cend()); - assert(it.depth() == 4); + TEST_ASSERT(it != res.cend()); + TEST_ASSERT(it.depth() == 4); } } diff -Nru mdds-2.1.1/test/rtree/test_erase_directories.cpp mdds-3.1.0/test/rtree/test_erase_directories.cpp --- mdds-2.1.1/test/rtree/test_erase_directories.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_erase_directories.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_erase_directories() { - stack_printer __stack_printer__("::rtree_test_erase_directories"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using search_type = rt_type::search_type; rt_type::integrity_check_properties check_props; @@ -62,7 +63,7 @@ } } - assert(tree.size() == 25); + TEST_ASSERT(tree.size() == 25); tree.check_integrity(check_props); cout << tree.export_tree(rt_type::export_tree_type::formatted_node_properties) << endl; @@ -80,21 +81,21 @@ auto res = ctree.search({x2, y2}, search_type::overlap); auto it = res.begin(), ite = res.end(); size_t n = std::distance(it, ite); - assert(n == 1); + TEST_ASSERT(n == 1); tree.erase(it); - assert(tree.size() == --expected_size); + TEST_ASSERT(tree.size() == --expected_size); tree.check_integrity(check_props); res = ctree.search({x2, y2}, search_type::overlap); n = std::distance(res.begin(), res.end()); - assert(n == 0); + TEST_ASSERT(n == 0); } } - assert(tree.empty()); - assert(tree.size() == 0); + TEST_ASSERT(tree.empty()); + TEST_ASSERT(tree.size() == 0); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/rtree/test_exact_search_by_extent.cpp mdds-3.1.0/test/rtree/test_exact_search_by_extent.cpp --- mdds-2.1.1/test/rtree/test_exact_search_by_extent.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_exact_search_by_extent.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_exact_search_by_extent() { - stack_printer __stack_printer__("::rtree_test_exact_search_by_extent"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using extent_type = rt_type::extent_type; @@ -54,22 +54,22 @@ // Immutable search rt_type::const_search_results cres = ctree.search({{1, 1}, {3, 3}}, search_type::overlap); size_t n = std::distance(cres.begin(), cres.end()); - assert(n == 3); + TEST_ASSERT(n == 3); cres = ctree.search({{1, 1}, {3, 3}}, search_type::match); n = std::distance(cres.begin(), cres.end()); - assert(n == 1); + TEST_ASSERT(n == 1); auto it = cres.cbegin(); - assert(*it == 1.2); - assert(it.extent() == extent_type({{1, 1}, {3, 3}})); - assert(it.depth() == 1); + TEST_ASSERT(*it == 1.2); + TEST_ASSERT(it.extent() == extent_type({{1, 1}, {3, 3}})); + TEST_ASSERT(it.depth() == 1); } { // Mutable search rt_type::search_results res = tree.search({{1, 1}, {3, 3}}, search_type::overlap); size_t n = std::distance(res.begin(), res.end()); - assert(n == 3); + TEST_ASSERT(n == 3); // Modify the values. for (double& v : res) @@ -77,8 +77,8 @@ res = tree.search({{1, 1}, {3, 3}}, search_type::match); n = std::distance(res.begin(), res.end()); - assert(n == 1); - assert(*res.begin() == 2.2); // The value should be updated. + TEST_ASSERT(n == 1); + TEST_ASSERT(*res.begin() == 2.2); // The value should be updated. } } diff -Nru mdds-2.1.1/test/rtree/test_exact_search_by_point.cpp mdds-3.1.0/test/rtree/test_exact_search_by_point.cpp --- mdds-2.1.1/test/rtree/test_exact_search_by_point.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_exact_search_by_point.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_exact_search_by_point() { - stack_printer __stack_printer__("::rtree_test_exact_search_by_point"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using point_type = rt_type::point_type; @@ -53,41 +53,41 @@ rt_type::const_search_results res = ctree.search({1, 1}, search_type::overlap); size_t n = std::distance(res.begin(), res.end()); - assert(n == 2); + TEST_ASSERT(n == 2); res = ctree.search({3, 3}, search_type::overlap); n = std::distance(res.begin(), res.end()); - assert(n == 2); + TEST_ASSERT(n == 2); res = ctree.search({2, 2}, search_type::overlap); n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); rt_type::const_iterator it = res.begin(); - assert(*it == 10.0); - assert(it.extent() == extent_type({{0, 0}, {4, 4}})); + TEST_ASSERT(*it == 10.0); + TEST_ASSERT(it.extent() == extent_type({{0, 0}, {4, 4}})); res = ctree.search({1, 1}, search_type::match); n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it = res.begin(); - assert(*it == 11.0); - assert(it.extent().is_point()); - assert(it.extent().start == point_type({1, 1})); + TEST_ASSERT(*it == 11.0); + TEST_ASSERT(it.extent().is_point()); + TEST_ASSERT(it.extent().start == point_type({1, 1})); res = ctree.search({3, 3}, search_type::match); n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it = res.begin(); - assert(*it == 33.0); - assert(it.extent().is_point()); - assert(it.extent().start == point_type({3, 3})); + TEST_ASSERT(*it == 33.0); + TEST_ASSERT(it.extent().is_point()); + TEST_ASSERT(it.extent().start == point_type({3, 3})); res = ctree.search({{0, 0}, {4, 4}}, search_type::match); n = std::distance(res.begin(), res.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it = res.begin(); - assert(*it == 10.0); - assert(it.extent() == extent_type({{0, 0}, {4, 4}})); + TEST_ASSERT(*it == 10.0); + TEST_ASSERT(it.extent() == extent_type({{0, 0}, {4, 4}})); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/rtree/test_forced_reinsertion.cpp mdds-3.1.0/test/rtree/test_forced_reinsertion.cpp --- mdds-2.1.1/test/rtree/test_forced_reinsertion.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_forced_reinsertion.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_forced_reinsertion() { - stack_printer __stack_printer__("::rtree_test_forced_reinsertion"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; rt_type::integrity_check_properties check_props; @@ -51,12 +51,12 @@ tree.insert({{i, i}, {int16_t(i + w), int16_t(i + w)}}, os.str()); } - assert(tree.size() == 6); + TEST_ASSERT(tree.size() == 6); tree.check_integrity(check_props); tree.clear(); - assert(tree.empty()); - assert(tree.size() == 0); + TEST_ASSERT(tree.empty()); + TEST_ASSERT(tree.size() == 0); tree.check_integrity(check_props); for (int16_t x = 0; x < 5; ++x) @@ -74,7 +74,7 @@ } tree.check_integrity(check_props); - assert(tree.size() == 25); + TEST_ASSERT(tree.size() == 25); export_tree(tree, "rtree-test-forced-reinsertion"); } diff -Nru mdds-2.1.1/test/rtree/test_geometry.cpp mdds-3.1.0/test/rtree/test_geometry.cpp --- mdds-2.1.1/test/rtree/test_geometry.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_geometry.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_area_enlargement() { - stack_printer __stack_printer__("::rtree_test_area_enlargement"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using bounding_box = rt_type::extent_type; using mdds::detail::rtree::calc_area_enlargement; @@ -58,13 +59,14 @@ for (const check& c : checks) { int16_t area = calc_area_enlargement(c.host, c.guest); - assert(area == c.expected_area); + TEST_ASSERT(area == c.expected_area); } } void rtree_test_center_point() { - stack_printer __stack_printer__("::rtree_test_center_point"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using mdds::detail::rtree::get_center_point; using extent_type = rt_type::extent_type; @@ -86,7 +88,7 @@ { cout << "extent: " << tc.extent.to_string() << endl; auto pt = get_center_point(tc.extent); - assert(pt == tc.expected); + TEST_ASSERT(pt == tc.expected); } } diff -Nru mdds-2.1.1/test/rtree/test_intersection.cpp mdds-3.1.0/test/rtree/test_intersection.cpp --- mdds-2.1.1/test/rtree/test_intersection.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_intersection.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_intersection() { - stack_printer __stack_printer__("::rtree_test_intersection"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using bounding_box = rt_type::extent_type; using mdds::detail::rtree::calc_intersection; @@ -60,23 +61,23 @@ for (const check& c : checks) { int16_t length1 = calc_linear_intersection(0, c.bb1, c.bb2); - assert(length1 == c.expected_length1); + TEST_ASSERT(length1 == c.expected_length1); int16_t length2 = calc_linear_intersection(1, c.bb1, c.bb2); - assert(length2 == c.expected_length2); + TEST_ASSERT(length2 == c.expected_length2); int16_t area = calc_intersection(c.bb1, c.bb2); int16_t expected_area = c.expected_length1 * c.expected_length2; - assert(area == expected_area); + TEST_ASSERT(area == expected_area); // Swap the boxes and run the same tests. We should get the same results. length1 = calc_linear_intersection(0, c.bb2, c.bb1); - assert(length1 == c.expected_length1); + TEST_ASSERT(length1 == c.expected_length1); length2 = calc_linear_intersection(1, c.bb2, c.bb1); - assert(length2 == c.expected_length2); + TEST_ASSERT(length2 == c.expected_length2); area = calc_intersection(c.bb2, c.bb1); - assert(area == expected_area); + TEST_ASSERT(area == expected_area); } } diff -Nru mdds-2.1.1/test/rtree/test_main.cpp mdds-3.1.0/test/rtree/test_main.cpp --- mdds-2.1.1/test/rtree/test_main.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_main.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -29,8 +29,6 @@ #include "test_global.hpp" // This must be the first header to be included. #include "test_global_rtree.hpp" -using namespace std; - int main() { try @@ -55,11 +53,11 @@ } catch (const std::exception& e) { - cout << "Test failed: " << e.what() << endl; + std::cout << "Test failed: " << e.what() << std::endl; return EXIT_FAILURE; } - cout << "Test finished successfully!" << endl; + std::cout << "Test finished successfully!" << std::endl; return EXIT_SUCCESS; } diff -Nru mdds-2.1.1/test/rtree/test_move.cpp mdds-3.1.0/test/rtree/test_move.cpp --- mdds-2.1.1/test/rtree/test_move.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_move.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_move() { - stack_printer __stack_printer__("::rtree_test_move"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; rt_type::integrity_check_properties check_props; @@ -58,15 +58,15 @@ } tree.check_integrity(check_props); - assert(tree.size() == 25); + TEST_ASSERT(tree.size() == 25); // moved via constructor. rt_type tree_moved(std::move(tree)); tree.check_integrity(check_props); tree_moved.check_integrity(check_props); - assert(tree.empty()); - assert(tree.size() == 0); - assert(tree_moved.size() == 25); + TEST_ASSERT(tree.empty()); + TEST_ASSERT(tree.size() == 0); + TEST_ASSERT(tree_moved.size() == 25); // moved via assignment operator. rt_type tree_moved_2; @@ -74,9 +74,9 @@ tree_moved_2 = std::move(tree_moved); tree_moved.check_integrity(check_props); tree_moved_2.check_integrity(check_props); - assert(tree_moved.empty()); - assert(tree_moved.size() == 0); - assert(tree_moved_2.size() == 25); + TEST_ASSERT(tree_moved.empty()); + TEST_ASSERT(tree_moved.size() == 0); + TEST_ASSERT(tree_moved_2.size() == 25); } /** @@ -85,7 +85,7 @@ */ void rtree_test_move_custom_type() { - stack_printer __stack_printer__("::rtree_test_move_custom_type"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using point_type = rt_type::point_type; @@ -117,7 +117,7 @@ for (const input& i : inputs) tree.insert({i.start, i.end}, only_movable(i.value)); - assert(tree.size() == inputs.size()); + TEST_ASSERT(tree.size() == inputs.size()); tree.check_integrity(check_props); @@ -127,8 +127,8 @@ rt_type tree_moved = std::move(tree); tree.check_integrity(check_props); tree_moved.check_integrity(check_props); - assert(tree.empty()); - assert(tree_moved.size() == inputs.size()); + TEST_ASSERT(tree.empty()); + TEST_ASSERT(tree_moved.size() == inputs.size()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/rtree/test_node_split.cpp mdds-3.1.0/test/rtree/test_node_split.cpp --- mdds-2.1.1/test/rtree/test_node_split.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_node_split.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_node_split() { - stack_printer __stack_printer__("::rtree_test_node_split"); + MDDS_TEST_FUNC_SCOPE; + using rt_type = rtree; using search_type = rt_type::search_type; rt_type::integrity_check_properties check_props; @@ -56,7 +57,7 @@ tree.insert({{i, i}, {int16_t(i + w), int16_t(i + w)}}, os.str()); } - assert(tree.size() == 6); + TEST_ASSERT(tree.size() == 6); cout << tree.export_tree(rt_type::export_tree_type::formatted_node_properties) << endl; @@ -82,9 +83,9 @@ tree.walk(walker); - assert(count_values == 6); - assert(count_leaf == 2); - assert(count_nonleaf == 1); + TEST_ASSERT(count_values == 6); + TEST_ASSERT(count_leaf == 2); + TEST_ASSERT(count_nonleaf == 1); tree.check_integrity(check_props); @@ -99,7 +100,7 @@ tree.insert({{i, i}, {int16_t(i + w), int16_t(i + w)}}, os.str()); } - assert(tree.size() == 8); + TEST_ASSERT(tree.size() == 8); tree.check_integrity(check_props); // Count all the nodes again. @@ -109,20 +110,20 @@ tree.walk(walker); - assert(count_values == 8); - assert(count_leaf == 3); - assert(count_nonleaf == 1); + TEST_ASSERT(count_values == 8); + TEST_ASSERT(count_leaf == 3); + TEST_ASSERT(count_nonleaf == 1); // Erase the entry at (0, 0). There should be only one match. Erasing // this entry will cause the node to be underfilled. rt_type::const_search_results res = ctree.search({0, 0}, search_type::overlap); auto it = res.cbegin(); - assert(it != res.cend()); - assert(std::distance(it, res.cend()) == 1); + TEST_ASSERT(it != res.cend()); + TEST_ASSERT(std::distance(it, res.cend()) == 1); tree.erase(it); - assert(tree.size() == 7); + TEST_ASSERT(tree.size() == 7); tree.check_integrity(check_props); // Count all the nodes again. @@ -132,9 +133,9 @@ tree.walk(walker); - assert(count_values == 7); - assert(count_leaf == 2); - assert(count_nonleaf == 1); + TEST_ASSERT(count_values == 7); + TEST_ASSERT(count_leaf == 2); + TEST_ASSERT(count_nonleaf == 1); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/rtree/test_point_objects.cpp mdds-3.1.0/test/rtree/test_point_objects.cpp --- mdds-2.1.1/test/rtree/test_point_objects.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_point_objects.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,7 @@ void rtree_test_point_objects() { - stack_printer __stack_printer__("::rtree_test_point_objects"); + MDDS_TEST_FUNC_SCOPE; using rt_type = rtree; using key_type = rt_type::key_type; @@ -61,17 +61,17 @@ for (key_type y = 0; y < 10; ++y) { auto results = tree.search({x, y}, search_type::overlap); - assert(std::distance(results.begin(), results.end()) == 1); + TEST_ASSERT(std::distance(results.begin(), results.end()) == 1); double expected = x * y; auto it = results.begin(); - assert(expected == *it); + TEST_ASSERT(expected == *it); } } // Test an extent-based search on point data. auto results = ctree.search({{0, 0}, {3, 3}}, search_type::overlap); size_t n_results = std::distance(results.cbegin(), results.cend()); - assert(n_results == 16); + TEST_ASSERT(n_results == 16); export_tree(tree, "rtree-test-point-objects"); } diff -Nru mdds-2.1.1/test/rtree/test_square_distance.cpp mdds-3.1.0/test/rtree/test_square_distance.cpp --- mdds-2.1.1/test/rtree/test_square_distance.cpp 2022-04-22 00:12:40.000000000 +0000 +++ mdds-3.1.0/test/rtree/test_square_distance.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -35,7 +35,8 @@ void rtree_test_square_distance() { - stack_printer __stack_printer__("::rtree_test_square_distance"); + MDDS_TEST_FUNC_SCOPE; + using mdds::detail::rtree::calc_square_distance; { @@ -61,11 +62,11 @@ cout << "p1: " << tc.p1.to_string() << "; p2: " << tc.p2.to_string() << endl; uint16_t dist = calc_square_distance(tc.p1, tc.p2); - assert(dist == tc.expected); + TEST_ASSERT(dist == tc.expected); // Flip the value to make sure we still get the same result. dist = calc_square_distance(tc.p2, tc.p1); - assert(dist == tc.expected); + TEST_ASSERT(dist == tc.expected); } } @@ -93,11 +94,11 @@ cout << "p1: " << tc.p1.to_string() << "; p2: " << tc.p2.to_string() << endl; uint16_t dist = calc_square_distance(tc.p1, tc.p2); - assert(dist == tc.expected); + TEST_ASSERT(dist == tc.expected); // Flip the value to make sure we still get the same result. dist = calc_square_distance(tc.p2, tc.p1); - assert(dist == tc.expected); + TEST_ASSERT(dist == tc.expected); } } } diff -Nru mdds-2.1.1/test/segment_tree/Makefile.am mdds-3.1.0/test/segment_tree/Makefile.am --- mdds-2.1.1/test/segment_tree/Makefile.am 2022-10-28 01:42:14.000000000 +0000 +++ mdds-3.1.0/test/segment_tree/Makefile.am 2024-03-12 23:40:22.000000000 +0000 @@ -6,7 +6,9 @@ check_PROGRAMS = test-main test_main_SOURCES = \ + test_main.hpp \ test_main.cpp \ + test_move_value.cpp \ $(top_srcdir)/test/test_global.cpp TESTS = test-main diff -Nru mdds-2.1.1/test/segment_tree/Makefile.in mdds-3.1.0/test/segment_tree/Makefile.in --- mdds-2.1.1/test/segment_tree/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/segment_tree/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -100,7 +100,7 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp -am_test_main_OBJECTS = test_main.$(OBJEXT) \ +am_test_main_OBJECTS = test_main.$(OBJEXT) test_move_value.$(OBJEXT) \ $(top_builddir)/test/test_global.$(OBJEXT) test_main_OBJECTS = $(am_test_main_OBJECTS) test_main_LDADD = $(LDADD) @@ -120,7 +120,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = $(top_builddir)/test/$(DEPDIR)/test_global.Po \ - ./$(DEPDIR)/test_main.Po + ./$(DEPDIR)/test_main.Po ./$(DEPDIR)/test_move_value.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -135,6 +135,18 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = SOURCES = $(test_main_SOURCES) DIST_SOURCES = $(test_main_SOURCES) am__can_run_installinfo = \ @@ -430,7 +442,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -491,7 +502,9 @@ $(CXXFLAGS_UNITTESTS) test_main_SOURCES = \ + test_main.hpp \ test_main.cpp \ + test_move_value.cpp \ $(top_srcdir)/test/test_global.cpp all: all-am @@ -553,6 +566,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/test/$(DEPDIR)/test_global.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_move_value.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -896,6 +910,7 @@ distclean: distclean-am -rm -f $(top_builddir)/test/$(DEPDIR)/test_global.Po -rm -f ./$(DEPDIR)/test_main.Po + -rm -f ./$(DEPDIR)/test_move_value.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -943,6 +958,7 @@ maintainer-clean: maintainer-clean-am -rm -f $(top_builddir)/test/$(DEPDIR)/test_global.Po -rm -f ./$(DEPDIR)/test_main.Po + -rm -f ./$(DEPDIR)/test_move_value.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff -Nru mdds-2.1.1/test/segment_tree/test_main.cpp mdds-3.1.0/test/segment_tree/test_main.cpp --- mdds-2.1.1/test/segment_tree/test_main.cpp 2022-10-28 01:42:14.000000000 +0000 +++ mdds-3.1.0/test/segment_tree/test_main.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2010, 2011 Kohei Yoshida + * Copyright (c) 2010-2023 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -25,8 +25,7 @@ * ************************************************************************/ -#include "test_global.hpp" // This must be the first header to be included. -#include "mdds/segment_tree.hpp" +#include "test_main.hpp" #include #include @@ -37,36 +36,22 @@ #include #include -#define ARRAY_SIZE(x) sizeof(x) / sizeof(x[0]) - -using namespace std; using namespace mdds; template void build_and_dump(segment_tree& db) { - cout << "build and dump (start) -----------------------------------------" << endl; db.build_tree(); - db.dump_tree(); - db.dump_leaf_nodes(); - cout << "build and dump (end) -------------------------------------------" << endl; + std::cout << db.to_string() << std::endl; } struct test_data { - string name; // data structure expects the data to have 'name' data member. + std::string name; // data structure expects the data to have 'name' data member. - test_data(const string& s) : name(s) + test_data(const std::string& s) : name(s) {} - struct ptr_printer - { - void operator()(const test_data* data) const - { - cout << data->name << " "; - } - }; - /** * Use this to sort instances of test_data by name, in ascending order. */ @@ -87,37 +72,48 @@ }; }; -template -bool check_leaf_nodes( - const segment_tree& db, const key_type* keys, value_type* data_chain, size_t key_size) +std::ostream& operator<<(std::ostream& os, const test_data* v) { - typedef segment_tree st_type; - vector checks; - checks.reserve(key_size); - size_t dcid = 0; - for (size_t i = 0; i < key_size; ++i) - { - typename st_type::leaf_node_check c; - c.key = keys[i]; - value_type p = data_chain[dcid]; - while (p) - { - c.data_chain.push_back(p); - p = data_chain[++dcid]; - } - checks.push_back(c); - ++dcid; - } + os << v->name; + return os; +} - return db.verify_leaf_nodes(checks); +std::ostream& operator<<(std::ostream& os, const test_data& v) +{ + os << v.name; + return os; } +template +struct segment_data_type +{ + using key_type = typename StoreT::key_type; + using value_type = typename StoreT::value_type; + + key_type begin_key; + key_type end_key; + value_type value; + + segment_data_type(key_type _beg, key_type _end, value_type p) : begin_key(_beg), end_key(_end), value(p) + {} + + bool operator==(const segment_data_type& r) const + { + return begin_key == r.begin_key && end_key == r.end_key && value == r.value; + } + + bool operator!=(const segment_data_type& r) const + { + return !operator==(r); + } +}; + template -bool check_against_expected(const list& test, value_type* expected) +bool check_against_expected(const std::list& test, value_type* expected) { size_t i = 0; value_type p = expected[i++]; - typename list::const_iterator itr = test.begin(), itr_end = test.end(); + typename std::list::const_iterator itr = test.begin(), itr_end = test.end(); while (p) { if (itr == itr_end) @@ -138,23 +134,30 @@ return true; } +template +std::vector to_vector(const ResT& results) +{ + std::vector vec; + for (const auto& v : results) + vec.push_back(v.value); + return vec; +} + /** * Only check the search result against expected result set. The caller * needs to run search and pass the result to this function. */ -template -bool check_search_result_only( - const segment_tree& /*db*/, - const typename segment_tree::search_results_type& result, key_type key, value_type* expected) +template +bool check_search_result_only(std::vector results, KeyT key, ValueT* expected) { cout << "search key: " << key << " "; - list test; - copy(result.begin(), result.end(), back_inserter(test)); + std::list test; + std::copy(results.begin(), results.end(), std::back_inserter(test)); test.sort(test_data::sort_by_name()); cout << "search result (sorted): "; - for_each(test.begin(), test.end(), test_data::name_printer()); + std::for_each(test.begin(), test.end(), test_data::name_printer()); cout << endl; return check_against_expected(test, expected); @@ -163,15 +166,13 @@ /** * Run the search and check the search result. */ -template -bool check_search_result(const segment_tree& db, key_type key, value_type* expected) +template +bool check_search_result(const segment_tree& db, KeyT key, ValueT* expected) { cout << "search key: " << key << " "; - typedef typename segment_tree::search_results_type search_result_type; - search_result_type data_chain; - db.search(key, data_chain); - return check_search_result_only(db, data_chain, key, expected); + auto results = db.search(key); + return check_search_result_only(to_vector(results), key, expected); } template @@ -180,21 +181,39 @@ cout << "search key: " << key << " "; typedef segment_tree db_type; - typename db_type::search_results result = db.search(key); - list test; - copy(result.begin(), result.end(), back_inserter(test)); + typename db_type::search_results results = db.search(key); + std::list test; + for (const auto& v : results) + test.push_back(v.value); + test.sort(test_data::sort_by_name()); cout << "search result (sorted): "; - for_each(test.begin(), test.end(), test_data::name_printer()); + std::for_each(test.begin(), test.end(), test_data::name_printer()); cout << endl; return check_against_expected(test, expected); } +template +bool check_integrity(const TreeT& db, const typename TreeT::integrity_check_properties& props) +{ + try + { + db.check_integrity(props); + } + catch (const mdds::integrity_error& e) + { + std::cout << e.what() << std::endl; + return false; + } + + return true; +} + void st_test_insert_search_removal() { - stack_printer __stack_printer__("::st_test_insert_segments"); + MDDS_TEST_FUNC_SCOPE; typedef long key_type; typedef test_data value_type; @@ -204,324 +223,465 @@ value_type A("A"), B("B"), C("C"), D("D"), E("E"), F("F"), G("G"); build_and_dump(db); - assert(db_type::node::get_instance_count() == 0); + TEST_ASSERT(db_type::node::get_instance_count() == 0); db.insert(0, 10, &A); build_and_dump(db); { - key_type keys[] = {0, 10}; - value_type* data_chain[] = {&A, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&A,}}, + {10u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(0, 5, &B); build_and_dump(db); { - key_type keys[] = {0, 5, 10}; - value_type* data_chain[] = {&A, &B, 0, &A, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&A, &B,}}, + {5u, {&A,}}, + {10u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(5, 12, &C); build_and_dump(db); { - key_type keys[] = {0, 5, 10, 12}; - value_type* data_chain[] = {&A, &B, 0, &A, &C, 0, &C, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&A, &B,}}, + {5u, {&A, &C}}, + {10u, {&C,}}, + {12u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(10, 24, &D); build_and_dump(db); { - key_type keys[] = {0, 5, 10, 12, 24}; - value_type* data_chain[] = {&A, &B, 0, &A, &C, 0, &C, &D, 0, &D, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&A, &B,}}, + {5u, {&A, &C}}, + {10u, {&C, &D}}, + {12u, {&D,}}, + {24u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(4, 24, &E); build_and_dump(db); { - key_type keys[] = {0, 4, 5, 10, 12, 24}; - value_type* data_chain[] = {&B, 0, &B, &E, 0, &A, &C, 0, &C, &D, 0, &D, &E, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&B,}}, + {4u, {&B, &E}}, + {5u, {&A, &C}}, + {10u, {&C, &D}}, + {12u, {&D, &E}}, + {24u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(0, 26, &F); build_and_dump(db); { - key_type keys[] = {0, 4, 5, 10, 12, 24, 26}; - value_type* data_chain[] = {&B, 0, &B, &E, 0, &A, &C, 0, &C, &D, 0, &D, &E, &F, 0, &F, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&B,}}, + {4u, {&B, &E}}, + {5u, {&A, &C}}, + {10u, {&C, &D}}, + {12u, {&D, &E, &F}}, + {24u, {&F,}}, + {26u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } db.insert(12, 26, &G); build_and_dump(db); { - key_type keys[] = {0, 4, 5, 10, 12, 24, 26}; - value_type* data_chain[] = {&B, 0, &B, &E, 0, &A, &C, 0, &C, &D, 0, &D, &E, &F, &G, 0, &F, &G, 0, 0}; - assert(check_leaf_nodes(db, keys, data_chain, ARRAY_SIZE(keys))); - assert(db_type::node::get_instance_count() == db.leaf_size()); - assert(db.verify_node_lists()); + TEST_ASSERT(db_type::node::get_instance_count() == db.leaf_size()); + + db_type::integrity_check_properties props; + // clang-format off + props.leaf_nodes = { + // key, value chain + {0u, {&B,}}, + {4u, {&B, &E}}, + {5u, {&A, &C}}, + {10u, {&C, &D}}, + {12u, {&D, &E, &F, &G}}, + {24u, {&F, &G}}, + {26u, {}}, + }; + // clang-format on + + TEST_ASSERT(check_integrity(db, props)); } // Search tests. Test boundary cases. for (key_type i = -10; i <= 30; ++i) { - db_type::search_results_type data_chain; - db.search(i, data_chain); - cout << "search key " << i << ": "; - for_each(data_chain.begin(), data_chain.end(), test_data::ptr_printer()); - cout << endl; + auto results = db.search(i); + std::cout << "search key " << i << ": "; + for (const auto& result : results) + std::cout << result.value->name << " "; + + std::cout << std::endl; } { key_type key = -1; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 0; value_type* expected[] = {&A, &B, &F, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 4; value_type* expected[] = {&A, &B, &E, &F, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 5; value_type* expected[] = {&A, &C, &E, &F, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 10; value_type* expected[] = {&C, &D, &E, &F, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 12; value_type* expected[] = {&D, &E, &F, &G, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 24; value_type* expected[] = {&F, &G, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 30; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 9999; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } // Remove E, F and G and check search results. + // E: 4-24; F: 0-26; G: 12-26 + { + auto count_before = db.size(); + auto res = db.search(10); + TEST_ASSERT(!res.empty()); + bool erased = false; + for (auto it = res.begin(); it != res.end(); ++it) + { + if (it->value == &E) + { + db.erase(it); + erased = true; + break; + } + } + TEST_ASSERT(erased); + TEST_ASSERT(db.size() == count_before - 1); + } + + { + auto count_before = db.size(); + auto res = db.search(10); + TEST_ASSERT(!res.empty()); + bool erased = false; + for (auto it = res.begin(); it != res.end(); ++it) + { + if (it->value == &F) + { + db.erase(it); + erased = true; + break; + } + } + TEST_ASSERT(erased); + TEST_ASSERT(db.size() == count_before - 1); + } + + { + auto count_before = db.size(); + auto res = db.search(20); + TEST_ASSERT(!res.empty()); + bool erased = false; + for (auto it = res.begin(); it != res.end(); ++it) + { + if (it->value == &G) + { + db.erase(it); + erased = true; + break; + } + } + TEST_ASSERT(erased); + TEST_ASSERT(db.size() == count_before - 1); + } - db.remove(&E); - db.remove(&F); - db.remove(&G); cout << "removed: E F G" << endl; - db.dump_tree(); - db.dump_leaf_nodes(); + cout << db.to_string() << endl; for (key_type i = -10; i <= 30; ++i) { - db_type::search_results_type data_chain; - db.search(i, data_chain); - cout << "search key " << i << ": "; - for_each(data_chain.begin(), data_chain.end(), test_data::ptr_printer()); - cout << endl; + auto results = db.search(i); + std::cout << "search key " << i << ": "; + for (const auto& result : results) + std::cout << result.value->name << " "; + std::cout << std::endl; } { key_type key = -1; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 0; value_type* expected[] = {&A, &B, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 4; value_type* expected[] = {&A, &B, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 5; value_type* expected[] = {&A, &C, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 10; value_type* expected[] = {&C, &D, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 12; value_type* expected[] = {&D, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 24; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 30; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 9999; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } // Re-build the tree and check the search results once again, to make sure // we get the same results. db.build_tree(); - db.dump_tree(); - db.dump_leaf_nodes(); + cout << db.to_string() << endl; { key_type key = -1; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 0; value_type* expected[] = {&A, &B, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 4; value_type* expected[] = {&A, &B, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 5; value_type* expected[] = {&A, &C, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 10; value_type* expected[] = {&C, &D, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 12; value_type* expected[] = {&D, 0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 24; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); } { key_type key = 30; value_type* expected[] = {0}; - assert(check_search_result(db, key, expected)); + TEST_ASSERT(check_search_result(db, key, expected)); + } +} + +void st_test_invalid_insertion() +{ + MDDS_TEST_FUNC_SCOPE; + + using db_type = segment_tree; + db_type db; + + try + { + db.insert(2, 1, "some value"); + TEST_ASSERT(!"exception didn't get thrown!"); + } + catch (const std::invalid_argument&) + { + // expected + } + catch (...) + { + TEST_ASSERT(!"wrong exception caught"); } } void st_test_copy_constructor() { - stack_printer __stack_printer__("::st_test_copy_constructor"); + MDDS_TEST_FUNC_SCOPE; typedef long key_type; typedef test_data value_type; typedef segment_tree db_type; + using segment_data = segment_data_type; db_type db; value_type A("A"), B("B"), C("C"), D("D"), E("E"), F("F"), G("G"); - vector segments; - segments.push_back(db_type::segment_data(0, 10, &A)); - segments.push_back(db_type::segment_data(0, 5, &B)); - segments.push_back(db_type::segment_data(5, 12, &C)); - segments.push_back(db_type::segment_data(10, 24, &D)); - segments.push_back(db_type::segment_data(4, 24, &E)); - segments.push_back(db_type::segment_data(0, 26, &F)); - segments.push_back(db_type::segment_data(12, 26, &G)); - segments.push_back(db_type::segment_data(0, 0, nullptr)); // null-terminated - - db_type::segment_map_type checks; - for (size_t i = 0; segments[i].pdata; ++i) - { - db.insert(segments[i].begin_key, segments[i].end_key, segments[i].pdata); - pair range; - range.first = segments[i].begin_key; - range.second = segments[i].end_key; - checks.insert(db_type::segment_map_type::value_type(segments[i].pdata, range)); - } + std::vector segments; + segments.push_back(segment_data(0, 10, &A)); + segments.push_back(segment_data(0, 5, &B)); + segments.push_back(segment_data(5, 12, &C)); + segments.push_back(segment_data(10, 24, &D)); + segments.push_back(segment_data(4, 24, &E)); + segments.push_back(segment_data(0, 26, &F)); + segments.push_back(segment_data(12, 26, &G)); + segments.push_back(segment_data(0, 0, nullptr)); // null-terminated // Copy before the tree is built. - db.dump_segment_data(); - assert(db.verify_segment_data(checks)); + cout << "--" << endl; + cout << db.to_string() << endl; db_type db_copied(db); - db_copied.dump_segment_data(); - assert(db_copied.verify_segment_data(checks)); - assert(db.is_tree_valid() == db_copied.is_tree_valid()); - assert(db == db_copied); + cout << "--" << endl; + cout << db_copied.to_string() << endl; + TEST_ASSERT(db.valid_tree() == db_copied.valid_tree()); + TEST_ASSERT(db == db_copied); + + db_type db_assigned; + db_assigned = db_copied; // copy assignment + TEST_ASSERT(db_assigned.valid_tree() == db_copied.valid_tree()); + TEST_ASSERT(db_assigned == db_copied); // Copy after the tree is built. db.build_tree(); db_type db_copied_tree(db); - db_copied_tree.dump_segment_data(); - db_copied_tree.dump_tree(); - assert(db_copied_tree.verify_segment_data(checks)); - assert(db.is_tree_valid() == db_copied_tree.is_tree_valid()); - assert(db == db_copied_tree); + cout << "--" << endl; + cout << db_copied_tree.to_string() << endl; + TEST_ASSERT(db.valid_tree() == db_copied_tree.valid_tree()); + TEST_ASSERT(db == db_copied_tree); + + db_assigned = db_copied_tree; // copy assignment + TEST_ASSERT(db_assigned.valid_tree() == db_copied_tree.valid_tree()); + TEST_ASSERT(db_assigned == db_copied_tree); } void st_test_equality() { - stack_printer __stack_printer__("::st_test_equality"); + MDDS_TEST_FUNC_SCOPE; typedef uint32_t key_type; typedef test_data value_type; @@ -532,71 +692,98 @@ db_type db1, db2; db1.insert(0, 10, &A); db2.insert(0, 10, &A); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db2.insert(5, 12, &B); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); db1.insert(5, 12, &C); - assert(db1 != db2); - db1.remove(&C); - db2.remove(&B); - assert(db1 == db2); + TEST_ASSERT(db1 != db2); + auto n_removed = db1.erase_if([&C](key_type, key_type, const auto& value) { return value == &C; }); + TEST_ASSERT(n_removed == 1); + n_removed = db2.erase_if([&B](key_type, key_type, const auto& value) { return value == &B; }); + TEST_ASSERT(n_removed == 1); + TEST_ASSERT(db1 == db2); db1.insert(4, 20, &D); db2.insert(4, 20, &D); - assert(db1 == db2); + TEST_ASSERT(db1 == db2); db1.insert(3, 12, &E); db2.insert(3, 15, &E); - assert(db1 != db2); + TEST_ASSERT(db1 != db2); + } + + { + // different insertion orders + db_type db1, db2; + TEST_ASSERT(db1 == db2); + db1.insert(0, 10, &A); + db1.insert(10, 20, &B); + db2.insert(10, 20, &B); + db2.insert(0, 10, &A); + TEST_ASSERT(db1 == db2); + } + + { + // one contains a deleted segment + db_type db1, db2; + db1.insert(0, 10, &C); + TEST_ASSERT(!db1.empty()); + TEST_ASSERT(db2.empty()); + TEST_ASSERT(db1 != db2); + db1.erase_if([](key_type start, key_type, const auto&) { return start == 0; }); + TEST_ASSERT(db1 == db2); + TEST_ASSERT(db1.empty()); + TEST_ASSERT(db2.empty()); } } void st_test_clear() { - stack_printer __stack_printer__("::st_test_clear"); + MDDS_TEST_FUNC_SCOPE; typedef uint8_t key_type; typedef test_data value_type; typedef segment_tree db_type; + using segment_data = segment_data_type; value_type A("A"), B("B"), C("C"), D("D"), E("E"), F("F"), G("G"); - vector segments; - segments.push_back(db_type::segment_data(0, 10, &A)); - segments.push_back(db_type::segment_data(0, 5, &B)); - segments.push_back(db_type::segment_data(5, 12, &C)); - segments.push_back(db_type::segment_data(10, 24, &D)); - segments.push_back(db_type::segment_data(4, 24, &E)); - segments.push_back(db_type::segment_data(0, 26, &F)); - segments.push_back(db_type::segment_data(12, 26, &G)); - segments.push_back(db_type::segment_data(0, 0, nullptr)); // null-terminated + std::vector segments; + segments.push_back(segment_data(0, 10, &A)); + segments.push_back(segment_data(0, 5, &B)); + segments.push_back(segment_data(5, 12, &C)); + segments.push_back(segment_data(10, 24, &D)); + segments.push_back(segment_data(4, 24, &E)); + segments.push_back(segment_data(0, 26, &F)); + segments.push_back(segment_data(12, 26, &G)); + segments.push_back(segment_data(0, 0, nullptr)); // null-terminated db_type db; - for (size_t i = 0; segments[i].pdata; ++i) - db.insert(segments[i].begin_key, segments[i].end_key, segments[i].pdata); + for (size_t i = 0; segments[i].value; ++i) + db.insert(segments[i].begin_key, segments[i].end_key, segments[i].value); - assert(!db.empty()); - assert(db.size() == 7); + TEST_ASSERT(!db.empty()); + TEST_ASSERT(db.size() == 7); cout << "size of db is " << db.size() << endl; db.clear(); - assert(db.empty()); - assert(db.size() == 0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db.size() == 0); // Insert the same data set once again, but this time build tree afterwards. - for (size_t i = 0; segments[i].pdata; ++i) - db.insert(segments[i].begin_key, segments[i].end_key, segments[i].pdata); + for (size_t i = 0; segments[i].value; ++i) + db.insert(segments[i].begin_key, segments[i].end_key, segments[i].value); db.build_tree(); - assert(!db.empty()); - assert(db.size() == 7); + TEST_ASSERT(!db.empty()); + TEST_ASSERT(db.size() == 7); db.clear(); - assert(db.empty()); - assert(db.size() == 0); + TEST_ASSERT(db.empty()); + TEST_ASSERT(db.size() == 0); } void st_test_duplicate_insertion() { - stack_printer __stack_printer__("::st_test_duplicate_insertion"); + MDDS_TEST_FUNC_SCOPE; typedef short key_type; typedef test_data value_type; @@ -605,13 +792,20 @@ value_type A("A"), B("B"), C("C"), D("D"), E("E"), F("F"), G("G"); db_type db; - assert(db.insert(0, 10, &A)); - assert(!db.insert(0, 10, &A)); - assert(!db.insert(2, 30, &A)); - assert(db.insert(0, 10, &B)); - db.remove(&A); - assert(db.insert(2, 30, &A)); + db.insert(0, 10, &A); + db.insert(0, 10, &A); // duplicate segments are allowed + db.insert(2, 30, &A); + db.insert(0, 10, &B); + TEST_ASSERT(db.size() == 4); + auto n_removed = db.erase_if( + [&A](key_type start, key_type end, const auto& value) { return start == 0 && end == 10 && value == &A; }); + TEST_ASSERT(n_removed == 2); + TEST_ASSERT(db.size() == 2); + db.insert(2, 30, &A); + TEST_ASSERT(db.size() == 3); build_and_dump(db); + TEST_ASSERT(db.size() == 3); + TEST_ASSERT(db.leaf_size() == 4); // 0, 2, 10, 30 } /** @@ -621,7 +815,7 @@ */ void st_test_search_on_uneven_tree() { - stack_printer __stack_printer__("::st_test_search_on_uneven_tree"); + MDDS_TEST_FUNC_SCOPE; typedef int16_t key_type; typedef test_data value_type; @@ -629,15 +823,15 @@ for (key_type data_count = 10; data_count < 20; ++data_count) { - vector> data_store; + std::vector> data_store; data_store.reserve(data_count); for (key_type i = 0; i < data_count; ++i) { - ostringstream os; - os << hex << showbase << i; + std::ostringstream os; + os << std::hex << std::showbase << i; data_store.emplace_back(new test_data(os.str())); } - assert(data_store.size() == static_cast(data_count)); + TEST_ASSERT(data_store.size() == static_cast(data_count)); db_type db; for (key_type i = 0; i < data_count; ++i) @@ -645,25 +839,24 @@ test_data* p = data_store[i].get(); db.insert(0, i + 1, p); } - assert(db.size() == static_cast(data_count)); + TEST_ASSERT(db.size() == static_cast(data_count)); db.build_tree(); for (key_type i = -1; i < data_count + 1; ++i) { - db_type::search_results_type result; - bool success = db.search(i, result); - assert(success); - cout << "search key: " << i << " result: "; - for_each(result.begin(), result.end(), test_data::name_printer()); - cout << endl; + auto results = db.search(i); + std::cout << "search key: " << i << " result: "; + for (const auto& result : results) + std::cout << result.value->name << " "; + std::cout << endl; } } } void st_test_perf_insertion() { - stack_printer __stack_printer__("::st_test_perf_insertion"); + MDDS_TEST_FUNC_SCOPE; typedef uint32_t key_type; typedef test_data value_type; @@ -672,18 +865,18 @@ key_type data_count = 1000000; // First, create test data instances and store them into a vector. - vector> data_store; + std::vector> data_store; { stack_printer __stack_printer2__("::st_test_perf_insertion:: data array creation"); data_store.reserve(data_count); for (key_type i = 0; i < data_count; ++i) { - ostringstream os; - os << hex << i; + std::ostringstream os; + os << std::hex << i; data_store.emplace_back(new test_data(os.str())); } } - assert(data_store.size() == data_count); + TEST_ASSERT(data_store.size() == data_count); db_type db; { @@ -694,41 +887,23 @@ db.insert(0, i + 1, p); } } - assert(db.size() == data_count); + TEST_ASSERT(db.size() == data_count); { stack_printer __stack_printer2__("::st_test_perf_insertion:: build tree"); db.build_tree(); } - assert(db.is_tree_valid()); + TEST_ASSERT(db.valid_tree()); - const test_data* test = nullptr; { stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with max results"); for (key_type i = 0; i < 200; ++i) { - db_type::search_results_type result; - db.search(0, result); - db_type::search_results_type::const_iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } - } - } - - { - stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with max results (iterator)"); - for (key_type i = 0; i < 200; ++i) - { - db_type::search_results result = db.search(0); - db_type::search_results::iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } + auto results = db.search(0); + TEST_ASSERT(results.size() == data_count); + auto it = results.begin(); + ++it; + TEST_ASSERT(it->value); } } @@ -736,28 +911,11 @@ stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with median results"); for (key_type i = 0; i < 200; ++i) { - db_type::search_results_type result; - db.search(data_count / 2, result); - db_type::search_results_type::const_iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } - } - } - - { - stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with median results (iterator)"); - for (key_type i = 0; i < 200; ++i) - { - db_type::search_results result = db.search(data_count / 2); - db_type::search_results::iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } + auto results = db.search(data_count / 2); + TEST_ASSERT(results.size() == data_count / 2); + auto it = results.begin(); + ++it; + TEST_ASSERT(it->value); } } @@ -765,40 +923,33 @@ stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with empty results"); for (key_type i = 0; i < 200; ++i) { - db_type::search_results_type result; - db.search(data_count, result); - db_type::search_results_type::const_iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } + auto results = db.search(data_count); + TEST_ASSERT(results.size() == 0); + TEST_ASSERT(results.begin() == results.end()); } } { - stack_printer __stack_printer2__("::st_test_perf_insertion:: 200 searches with empty results (iterator)"); - for (key_type i = 0; i < 200; ++i) + auto db_copy = db; + stack_printer __stack_printer2__("::st_test_perf_insertion:: first 500 segment removals"); + for (key_type i = 0; i < 500; ++i) { - db_type::search_results result = db.search(data_count); - db_type::search_results::iterator itr = result.begin(), itr_end = result.end(); - for (; itr != itr_end; ++itr) - { - test = *itr; - assert(test); - } + test_data* p = data_store[i].get(); + db_copy.erase_if([p](key_type, key_type, const auto& value) { return value == p; }); } } + TEST_ASSERT(db.size() == data_count); { - stack_printer __stack_printer2__("::st_test_perf_insertion:: 10000 segment removals"); - for (key_type i = 0; i < 10000; ++i) + auto db_copy = db; + stack_printer __stack_printer2__("::st_test_perf_insertion:: last 500 segment removals"); + for (key_type i = 0; i < 500; ++i) { - test_data* p = data_store[i].get(); - db.remove(p); + test_data* p = data_store[data_store.size() - i - 1].get(); + db_copy.erase_if([p](key_type, key_type, const auto& value) { return value == p; }); } } - assert(db.size() == data_count - 10000); + TEST_ASSERT(db.size() == data_count); { stack_printer __stack_printer2__("::st_test_perf_insertion:: clear"); @@ -808,66 +959,78 @@ void st_test_aggregated_search_results() { - stack_printer __stack_printer__("::st_test_aggregated_search_results"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef test_data value_type; typedef segment_tree db_type; + using segment_data = segment_data_type; value_type A("A"), B("B"), C("C"), D("D"), E("E"), F("F"), G("G"); - vector segments; - segments.push_back(db_type::segment_data(0, 10, &A)); - segments.push_back(db_type::segment_data(0, 5, &B)); - segments.push_back(db_type::segment_data(5, 12, &C)); - segments.push_back(db_type::segment_data(10, 24, &D)); - segments.push_back(db_type::segment_data(4, 24, &E)); - segments.push_back(db_type::segment_data(0, 26, &F)); - segments.push_back(db_type::segment_data(12, 26, &G)); - segments.push_back(db_type::segment_data(0, 0, nullptr)); // null-terminated + std::vector segments; + segments.push_back(segment_data(0, 10, &A)); + segments.push_back(segment_data(0, 5, &B)); + segments.push_back(segment_data(5, 12, &C)); + segments.push_back(segment_data(10, 24, &D)); + segments.push_back(segment_data(4, 24, &E)); + segments.push_back(segment_data(0, 26, &F)); + segments.push_back(segment_data(12, 26, &G)); + segments.push_back(segment_data(0, 0, nullptr)); // null-terminated db_type db; - for (size_t i = 0; segments[i].pdata; ++i) - db.insert(segments[i].begin_key, segments[i].end_key, segments[i].pdata); + for (size_t i = 0; segments[i].value; ++i) + db.insert(segments[i].begin_key, segments[i].end_key, segments[i].value); - db.dump_segment_data(); db.build_tree(); - db_type::search_results_type result; + std::vector results; { key_type key = 0; - db.search(key, result); + auto res = db.search(key); + for (const auto& v : res) + results.push_back(v.value); + value_type* expected[] = {&A, &B, &F, 0}; - assert(check_search_result_only(db, result, key, expected)); + TEST_ASSERT(check_search_result_only(results, key, expected)); } { key_type key = 10; - db.search(key, result); + auto res = db.search(key); + for (const auto& v : res) + results.push_back(v.value); + // Note the duplicated F's in the search result. value_type* expected[] = {&A, &B, &C, &D, &E, &F, &F, 0}; - assert(check_search_result_only(db, result, key, expected)); + TEST_ASSERT(check_search_result_only(results, key, expected)); } { key_type key = 5; - db.search(key, result); + auto res = db.search(key); + for (const auto& v : res) + results.push_back(v.value); + value_type* expected[] = {&A, &A, &B, &C, &C, &D, &E, &E, &F, &F, &F, 0}; - assert(check_search_result_only(db, result, key, expected)); + TEST_ASSERT(check_search_result_only(results, key, expected)); } { - result.clear(); // clear the accumulated result set. + results.clear(); // clear the accumulated result set. key_type key = 5; - db.search(key, result); + auto res = db.search(key); + for (const auto& v : res) + results.push_back(v.value); + value_type* expected[] = {&A, &C, &E, &F, 0}; - assert(check_search_result_only(db, result, key, expected)); + TEST_ASSERT(check_search_result_only(results, key, expected)); } } void st_test_dense_tree_search() { - stack_printer __stack_printer__("::st_test_dense_tree_search"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef test_data value_type; @@ -883,54 +1046,54 @@ db.insert(0, 6, &F); db.insert(0, 7, &G); db.build_tree(); - db.dump_tree(); - db.dump_leaf_nodes(); + cout << "--" << endl; + cout << db.to_string() << endl; { db_type::value_type expected[] = {&A, &B, &C, &D, &E, &F, &G, 0}; bool success = check_search_result(db, 0, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&B, &C, &D, &E, &F, &G, 0}; bool success = check_search_result(db, 1, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&C, &D, &E, &F, &G, 0}; bool success = check_search_result(db, 2, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&D, &E, &F, &G, 0}; bool success = check_search_result(db, 3, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&E, &F, &G, 0}; bool success = check_search_result(db, 4, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&F, &G, 0}; bool success = check_search_result(db, 5, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {&G, 0}; bool success = check_search_result(db, 6, expected); - assert(success); + TEST_ASSERT(success); } { db_type::value_type expected[] = {0}; bool success = check_search_result(db, 7, expected); - assert(success); + TEST_ASSERT(success); } } void st_test_search_on_empty_set() { - stack_printer __stack_printer__("::st_test_search_on_empty_set"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef test_data value_type; @@ -941,15 +1104,15 @@ // Search on an empty set should still be considered a success as long as // the tree is built beforehand. - db_type::search_results_type result; - bool success = db.search(0, result); - assert(success); - assert(result.empty()); + auto results = db.search(0); + TEST_ASSERT(results.size() == 0); + TEST_ASSERT(results.empty()); + TEST_ASSERT(results.begin() == results.end()); } void st_test_search_iterator_basic() { - stack_printer __stack_printer__("::st_test_search_iterator"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef test_data value_type; typedef segment_tree db_type; @@ -964,44 +1127,45 @@ db.insert(0, 6, &F); db.insert(0, 7, &G); db.build_tree(); - db.dump_tree(); - db.dump_leaf_nodes(); + cout << "--" << endl; + cout << db.to_string() << endl; - db_type::search_results result = db.search(0); - db_type::search_results::iterator itr; - db_type::search_results::iterator itr_beg = result.begin(); - db_type::search_results::iterator itr_end = result.end(); + db_type::search_results results = db.search(0); + TEST_ASSERT(results.size() == 7); + db_type::search_results::const_iterator itr; + db_type::search_results::const_iterator itr_beg = results.begin(); + db_type::search_results::const_iterator itr_end = results.end(); cout << "Iterate through the search results." << endl; for (itr = itr_beg; itr != itr_end; ++itr) - cout << (*itr)->name << " "; + cout << (*itr).value->name << " "; cout << endl; cout << "Do it again." << endl; for (itr = itr_beg; itr != itr_end; ++itr) - cout << (*itr)->name << " "; + cout << (*itr).value->name << " "; cout << endl; cout << "Iterate backwards" << endl; do { --itr; - cout << (*itr)->name << " "; + cout << (*itr).value->name << " "; } while (itr != itr_beg); cout << endl; cout << "Get the last item from the end position." << endl; itr = itr_end; --itr; - cout << (*itr)->name << endl; + cout << (*itr).value->name << endl; - cout << "Use for_each to print names." << endl; - for_each(itr_beg, itr_end, test_data::ptr_printer()); + cout << "Use std::for_each to print names." << endl; + std::for_each(itr_beg, itr_end, [](const auto& v) { std::cout << v.value->name; }); cout << endl; } void st_test_search_iterator_result_check() { - stack_printer __stack_printer__("::st_test_search_iterator_result_check"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef test_data value_type; @@ -1021,42 +1185,42 @@ { value_type* expected[] = {&A, &B, &C, &D, &E, &F, &G, 0}; bool success = check_search_result_iterator(db, 0, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&B, &C, &D, &E, &F, &G, 0}; bool success = check_search_result_iterator(db, 1, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&C, &D, &E, &F, &G, 0}; bool success = check_search_result_iterator(db, 2, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&D, &E, &F, &G, 0}; bool success = check_search_result_iterator(db, 3, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&E, &F, &G, 0}; bool success = check_search_result_iterator(db, 4, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&F, &G, 0}; bool success = check_search_result_iterator(db, 5, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {&G, 0}; bool success = check_search_result_iterator(db, 6, expected); - assert(success); + TEST_ASSERT(success); } { value_type* expected[] = {0}; bool success = check_search_result_iterator(db, 7, expected); - assert(success); + TEST_ASSERT(success); } } @@ -1066,17 +1230,19 @@ */ void st_test_empty_result_set() { - stack_printer __stack_printer__("::st_test_empty_result_set"); - typedef segment_tree db_type; + MDDS_TEST_FUNC_SCOPE; + + typedef segment_tree db_type; db_type db; - db_type::search_results result = db.search(0); - cout << "size of empty result set: " << result.size() << endl; - assert(result.size() == 0); + db_type::search_results results = db.search(0); + cout << "size of empty result set: " << results.size() << endl; + TEST_ASSERT(results.size() == 0); + TEST_ASSERT(results.empty()); } void st_test_non_pointer_data() { - stack_printer __stack_printer__("::st_test_non_pointer_data"); + MDDS_TEST_FUNC_SCOPE; typedef uint16_t key_type; typedef size_t value_type; @@ -1086,9 +1252,113 @@ db.insert(0, 1, 10); db.build_tree(); - db_type::search_results result = db.search(0); - assert(result.size() == 1); - assert(*result.begin() == 10); + db_type::search_results results = db.search(0); + TEST_ASSERT(results.size() == 1); + TEST_ASSERT(!results.empty()); + TEST_ASSERT(results.begin()->value == 10); +} + +void st_test_erase_on_invalid_tree() +{ + MDDS_TEST_FUNC_SCOPE; + + using db_type = segment_tree; + + db_type db; + db.insert(0, 5, "A"); + db.insert(-10, 2, "B"); + db.insert(2, 10, "C"); + db.build_tree(); + TEST_ASSERT(db.valid_tree()); + + { + // It should contains the "C" segment. + auto results = db.search(5); + auto it = std::find_if(results.begin(), results.end(), [](const auto& v) { return v.value == "C"; }); + TEST_ASSERT(it != results.end()); + } + + db.insert(3, 15, "D"); + TEST_ASSERT(!db.valid_tree()); + // Remove a segment while the tree is invalid. + db.erase_if([](int, int, const auto& v) { return v == "C"; }); + db.build_tree(); + + { + // It should no longer contain the "C" segment. + auto results = db.search(5); + auto it = std::find_if(results.begin(), results.end(), [](const auto& v) { return v.value == "C"; }); + TEST_ASSERT(it == results.end()); + } +} + +void st_test_boundary_keys() +{ + MDDS_TEST_FUNC_SCOPE; + + using db_type = segment_tree; + + db_type db; + auto keys = db.boundary_keys(); + TEST_ASSERT(keys.empty()); + + auto expected = keys; + expected = {1, 3}; + + db.insert(1, 3, true); + TEST_ASSERT(db.size() == 1); + keys = db.boundary_keys(); + TEST_ASSERT(keys == expected); + + db.insert(3, 5, true); + TEST_ASSERT(db.size() == 2); + keys = db.boundary_keys(); + expected = {1, 3, 5}; + TEST_ASSERT(keys == expected); + + db.insert(7, 10, false); + TEST_ASSERT(db.size() == 3); + keys = db.boundary_keys(); + expected = {1, 3, 5, 7, 10}; + TEST_ASSERT(keys == expected); + + db.insert(-5, -2, true); + TEST_ASSERT(db.size() == 4); + keys = db.boundary_keys(); + expected = {-5, -2, 1, 3, 5, 7, 10}; + TEST_ASSERT(keys == expected); + + db.insert(-2, 10, true); // no new keys + TEST_ASSERT(db.size() == 5); + keys = db.boundary_keys(); + TEST_ASSERT(keys == expected); + + db.build_tree(); + keys = db.boundary_keys(); + TEST_ASSERT(keys == expected); + + // erase segments with false value i.e. 7-10. + db.erase_if([](int16_t, int16_t, bool value) { return !value; }); + TEST_ASSERT(db.size() == 4); + keys = db.boundary_keys(); + expected = {-5, -2, 1, 3, 5, 10}; + TEST_ASSERT(keys == expected); + + db.build_tree(); // purge the deleted segment + keys = db.boundary_keys(); + TEST_ASSERT(keys == expected); + + // erase all the other segments + db.erase_if([](int16_t, int16_t, bool value) { return value; }); + TEST_ASSERT(db.empty()); + keys = db.boundary_keys(); + expected.clear(); + TEST_ASSERT(keys == expected); + + db.build_tree(); // purge all deleted segments + TEST_ASSERT(!db.valid_tree()); + keys = db.boundary_keys(); + TEST_ASSERT(keys == expected); } int main(int argc, char** argv) @@ -1102,6 +1372,7 @@ if (opt.test_func) { st_test_insert_search_removal(); + st_test_invalid_insertion(); st_test_copy_constructor(); st_test_equality(); st_test_clear(); @@ -1114,6 +1385,11 @@ st_test_search_iterator_result_check(); st_test_empty_result_set(); st_test_non_pointer_data(); + st_test_erase_on_invalid_tree(); + st_test_boundary_keys(); + + st_test_move_constructor(); + st_test_move_equality(); } if (opt.test_perf) @@ -1124,7 +1400,7 @@ // At this point, all of the nodes created during the test run should have // been destroyed. If not, we are leaking memory. typedef segment_tree db_type; - assert(db_type::node::get_instance_count() == 0); + TEST_ASSERT(db_type::node::get_instance_count() == 0); } catch (const std::exception& e) { diff -Nru mdds-2.1.1/test/segment_tree/test_main.hpp mdds-3.1.0/test/segment_tree/test_main.hpp --- mdds-2.1.1/test/segment_tree/test_main.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/segment_tree/test_main.hpp 2024-03-15 20:46:09.000000000 +0000 @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#pragma once + +#include "test_global.hpp" // This must be the first header to be included. +#define MDDS_SEGMENT_TREE_DEBUG 1 +#include "mdds/segment_tree.hpp" + +void st_test_insert_search_removal(); +void st_test_invalid_insertion(); +void st_test_copy_constructor(); +void st_test_equality(); +void st_test_clear(); +void st_test_duplicate_insertion(); +void st_test_search_on_uneven_tree(); +void st_test_aggregated_search_results(); +void st_test_dense_tree_search(); +void st_test_search_on_empty_set(); +void st_test_search_iterator_basic(); +void st_test_search_iterator_result_check(); +void st_test_empty_result_set(); +void st_test_non_pointer_data(); +void st_test_erase_on_invalid_tree(); +void st_test_boundary_keys(); + +void st_test_move_constructor(); +void st_test_move_equality(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/segment_tree/test_move_value.cpp mdds-3.1.0/test/segment_tree/test_move_value.cpp --- mdds-2.1.1/test/segment_tree/test_move_value.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/segment_tree/test_move_value.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#include "test_main.hpp" + +namespace { + +/** + * This value is not copyable; only moveable. + */ +struct move_data +{ + std::string value; + + move_data() = default; + move_data(const move_data&) = delete; + move_data(move_data&&) = default; + move_data& operator=(const move_data&) = delete; + move_data& operator=(move_data&&) = default; + + move_data(std::string _value) : value(std::move(_value)) + {} + move_data(const char* _value) : value(_value) + {} + + bool operator==(const move_data& r) const + { + return value == r.value; + } +}; + +} // anonymous namespace + +void st_test_move_constructor() +{ + MDDS_TEST_FUNC_SCOPE; + + using db_type = mdds::segment_tree; + + db_type db; + db.insert(-2, 10, "-2:10"); + db.insert(5, 20, "5:20"); + db.insert(6, 15, "6:15"); + db.build_tree(); + + // Since the value type is only moveable, this must trigger the move + // constructor, not the copy constructor. + db_type db_moved(std::move(db)); + + { + TEST_ASSERT(db_moved.valid_tree()); + TEST_ASSERT(db_moved.size() == 3); + + auto results = db_moved.search(19); + TEST_ASSERT(results.size() == 1); + const auto& v = *results.begin(); + TEST_ASSERT(v.start == 5); + TEST_ASSERT(v.end == 20); + TEST_ASSERT(v.value == "5:20"); + TEST_ASSERT(std::next(results.begin()) == results.end()); + } + + db_type db_assigned; + db_assigned = std::move(db_moved); // move assignment + + { + TEST_ASSERT(db_assigned.valid_tree()); + TEST_ASSERT(db_assigned.size() == 3); + + auto results = db_assigned.search(19); + TEST_ASSERT(results.size() == 1); + const auto& v = *results.begin(); + TEST_ASSERT(v.start == 5); + TEST_ASSERT(v.end == 20); + TEST_ASSERT(v.value == "5:20"); + TEST_ASSERT(std::next(results.begin()) == results.end()); + } +} + +void st_test_move_equality() +{ + MDDS_TEST_FUNC_SCOPE; + + using db_type = mdds::segment_tree; + + db_type db1; + db1.insert(-2, 10, "-2:10"); + db1.insert(5, 20, "5:20"); + db1.insert(6, 15, "6:15"); + + db_type db2; + db2.insert(-2, 10, "-2:10"); + db2.insert(5, 20, "5:20"); + db2.insert(6, 15, "6:15"); + + TEST_ASSERT(db1 == db2); + + db2.insert(8, 22, "8:22"); + TEST_ASSERT(db1 != db2); + + db1.insert(8, 22, "8:22"); + TEST_ASSERT(db1 == db2); + + db1.erase_if([](float, float, const move_data& v) { return v.value == "-2:10"; }); + TEST_ASSERT(db1 != db2); + + db2.erase_if([](float, float, const move_data& v) { return v.value == "-2:10"; }); + TEST_ASSERT(db1 == db2); + + db1.build_tree(); + TEST_ASSERT(db1 != db2); + + db2.build_tree(); + TEST_ASSERT(db1 == db2); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/sorted_string_map/Makefile.in mdds-3.1.0/test/sorted_string_map/Makefile.in --- mdds-2.1.1/test/sorted_string_map/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/sorted_string_map/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -430,7 +430,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/test/sorted_string_map/test_main.cpp mdds-3.1.0/test/sorted_string_map/test_main.cpp --- mdds-2.1.1/test/sorted_string_map/test_main.cpp 2022-09-13 02:21:17.000000000 +0000 +++ mdds-3.1.0/test/sorted_string_map/test_main.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -34,6 +34,13 @@ #include #include #include +#include + +#define KEY_FINDER_TYPE \ + do \ + { \ + std::cout << "key finder type: " << keyfinder_name{}() << std::endl; \ + } while (false) enum name_type { @@ -44,63 +51,156 @@ name_david }; +namespace std { + +template<> +struct hash +{ + std::size_t operator()(const name_type& v) const + { + return static_cast(v); + } +}; + +} // namespace std + +struct move_only_value +{ + int value = {}; + + move_only_value() + {} + move_only_value(int _value) : value(_value) + {} + move_only_value(move_only_value&& r) : value(r.value) + { + r.value = {}; + } + + move_only_value(const move_only_value&) = delete; + + bool operator==(const move_only_value& r) const + { + return value == r.value; + } +}; + +namespace std { + +template<> +struct hash +{ + std::size_t operator()(const move_only_value& v) const + { + return std::hash{}(v.value); + } +}; + +} // namespace std + +template class KeyFinderT> +struct keyfinder_name; + +template<> +struct keyfinder_name +{ + std::string_view operator()() const + { + return "linear"; + } +}; + +template<> +struct keyfinder_name +{ + std::string_view operator()() const + { + return "hash"; + } +}; + +template class KeyFinderT> void ssmap_test_basic() { - stack_printer __sp__(__func__); + MDDS_TEST_FUNC_SCOPE; + KEY_FINDER_TYPE; - typedef mdds::sorted_string_map map_type; + using map_type = mdds::sorted_string_map; - 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}, + const typename map_type::entry_type entries[] = { + {"andy", name_andy}, {"andy1", name_andy}, {"andy13", name_andy}, + {"bruce", name_bruce}, {"charlie", name_charlie}, {"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) + constexpr auto n_entries = std::size(entries); + map_type names(entries, n_entries, name_none); + for (size_t i = 0; i < n_entries; ++i) { - cout << "* key = " << entries[i].key << endl; - bool res = names.find(entries[i].key, strlen(entries[i].key)) == entries[i].value; - assert(res); + std::cout << "* key = " << entries[i].key << std::endl; + bool res = names.find(entries[i].key) == entries[i].value; + TEST_ASSERT(res); } // Try invalid keys. - assert(names.find("foo", 3) == name_none); - assert(names.find("andy133", 7) == name_none); + TEST_ASSERT(names.find("foo", 3) == name_none); + TEST_ASSERT(names.find("andy133", 7) == name_none); + + // reverse lookup + TEST_ASSERT(names.find_key(name_bruce) == "bruce"); + TEST_ASSERT(names.find_key(name_charlie) == "charlie"); + TEST_ASSERT(names.find_key(name_david) == "david"); + + // negative case + TEST_ASSERT(names.find_key(name_none).empty()); + + // 'name_andy' is associated with three keys + const std::unordered_set keys_andy = {"andy", "andy1", "andy13"}; + + TEST_ASSERT(keys_andy.count(names.find_key(name_andy)) > 0); } +template class KeyFinderT> void ssmap_test_mixed_case_null() { - stack_printer __sp__(__func__); + MDDS_TEST_FUNC_SCOPE; + KEY_FINDER_TYPE; - typedef mdds::sorted_string_map map_type; + typedef mdds::sorted_string_map map_type; - map_type::entry entries[] = { - {MDDS_ASCII("NULL"), 1}, - {MDDS_ASCII("Null"), 2}, - {MDDS_ASCII("null"), 3}, - {MDDS_ASCII("~"), 4}, + const typename map_type::entry_type entries[] = { + {"NULL", 1}, + {"Null", 2}, + {"null", 3}, + {"~", 4}, }; - size_t entry_count = sizeof(entries) / sizeof(entries[0]); + size_t entry_count = std::size(entries); map_type names(entries, entry_count, -1); 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); + std::cout << "* key = " << entries[i].key << std::endl; + bool res = names.find(entries[i].key) == entries[i].value; + TEST_ASSERT(res); } // Try invalid keys. - assert(names.find(MDDS_ASCII("NUll")) == -1); - assert(names.find(MDDS_ASCII("Oull")) == -1); - assert(names.find(MDDS_ASCII("Mull")) == -1); - assert(names.find(MDDS_ASCII("hell")) == -1); + TEST_ASSERT(names.find(MDDS_ASCII("NUll")) == -1); + TEST_ASSERT(names.find(MDDS_ASCII("Oull")) == -1); + TEST_ASSERT(names.find(MDDS_ASCII("Mull")) == -1); + TEST_ASSERT(names.find(MDDS_ASCII("hell")) == -1); + + // reverse lookup + TEST_ASSERT(names.find_key(1) == "NULL"); + TEST_ASSERT(names.find_key(2) == "Null"); + TEST_ASSERT(names.find_key(3) == "null"); + TEST_ASSERT(names.find_key(4) == "~"); } -void ssmap_test_string_view_entry() +template class KeyFinderT> +void ssmap_test_find_string_view() { - stack_printer __sp__(__func__); + MDDS_TEST_FUNC_SCOPE; + KEY_FINDER_TYPE; constexpr int cv_unknown = -1; constexpr int cv_days = 0; @@ -112,9 +212,9 @@ constexpr int cv_seconds = 6; constexpr int cv_years = 7; - using map_type = mdds::sorted_string_map; + using map_type = mdds::sorted_string_map; - constexpr map_type::entry entries[] = { + constexpr typename map_type::entry_type entries[] = { {"days", cv_days}, {"hours", cv_hours}, {"minutes", cv_minutes}, {"months", cv_months}, {"quarters", cv_quarters}, {"range", cv_range}, {"seconds", cv_seconds}, {"years", cv_years}, }; @@ -124,7 +224,9 @@ for (const auto& entry : entries) { auto v = mapping.find(entry.key); - assert(v == entry.value); + TEST_ASSERT(v == entry.value); + auto k = mapping.find_key(entry.value); + TEST_ASSERT(k == entry.key); } constexpr std::string_view unknown_keys[] = { @@ -134,41 +236,129 @@ for (const auto& key : unknown_keys) { auto v = mapping.find(key); - assert(v == cv_unknown); + TEST_ASSERT(v == cv_unknown); + auto k = mapping.find_key(cv_unknown); + TEST_ASSERT(k.empty()); } } +template class KeyFinderT> +void ssmap_test_move_only_value_type() +{ + MDDS_TEST_FUNC_SCOPE; + KEY_FINDER_TYPE; + + using map_type = mdds::sorted_string_map; + + const typename map_type::entry_type entries[] = { + {"0x01", {1}}, + {"0x02", {2}}, + {"0x03", {3}}, + {"0x04", {4}}, + }; + + map_type mapping{entries, std::size(entries), {0}}; + + for (const auto& e : entries) + { + const move_only_value& v = mapping.find(e.key); + TEST_ASSERT(v.value == e.value.value); + std::string_view k = mapping.find_key(e.value); + TEST_ASSERT(k == e.key); + } + + // test for null value + const auto& v = mapping.find("0x05"); + TEST_ASSERT(v.value == 0); + std::string_view k = mapping.find_key({5}); + TEST_ASSERT(k.empty()); // not found +} + void ssmap_test_perf() { - stack_printer __sp__(__func__); + MDDS_TEST_FUNC_SCOPE; + + std::string content; + { + // load the entire file content in memory + std::ifstream in("../../misc/sorted_string_data.dat"); + TEST_ASSERT(in); + + std::ostringstream os; + os << in.rdbuf(); + content = os.str(); + } + + using map_type = mdds::sorted_string_map; + std::vector entries; + + { + // populate entries from the data file + int i = 0; + const char* p0 = nullptr; + const char* p = content.data(); + const char* p_end = p + content.size(); + for (; p != p_end; ++p) + { + if (!p0) + p0 = p; + + if (*p == '\n') + { + std::size_t n = std::distance(p0, p); + entries.push_back(map_type::entry_type{}); + entries.back().key = std::string_view{p0, n}; + entries.back().value = i++; + p0 = nullptr; + } + } + } + + std::cout << "entry count: " << entries.size() << std::endl; + + map_type names(entries.data(), entries.size(), -1); + + constexpr int repeat = 1000; + { + // worst case performance is when the key is not found + stack_printer sp_find("perf-find-not-found"); + + for (int i = 0; i < repeat; ++i) + { + auto v = names.find("test"); + TEST_ASSERT(v == -1); + } + } - std::ifstream in("misc/sorted_string_data.dat"); - typedef mdds::sorted_string_map map_type; - std::vector data; - std::string line; - int i = 0; - while (std::getline(in, line)) { - data.push_back(map_type::entry()); - data.back().key_length = line.size(); - data.back().value = i; - char* str = new char[line.size()]; - data.back().key = str; - strcpy(str, &line[0]); - ++i; + stack_printer sp_find("perf-find-bottom"); + + for (int i = 0; i < repeat; ++i) + { + auto v = names.find(entries.back().key); + TEST_ASSERT(v == entries.back().value); + } } - assert(data.size() > 1000); { - stack_printer __stack_printer__("::ssmap_test_perf"); - map_type names(data.data(), data.size(), -1); + stack_printer sp_find("perf-find-middle"); + const std::size_t pos = entries.size() / 2; - assert(names.find(MDDS_ASCII("test")) == -1); + for (int i = 0; i < repeat; ++i) + { + auto v = names.find(entries[pos].key); + TEST_ASSERT(v == entries[pos].value); + } } - for (auto it = data.begin(), itEnd = data.end(); it != itEnd; ++it) { - delete[] it->key; + stack_printer sp_find("perf-find-top"); + + for (int i = 0; i < repeat; ++i) + { + auto v = names.find(entries.front().key); + TEST_ASSERT(v == entries.front().value); + } } } @@ -180,9 +370,14 @@ if (opt.test_func) { - ssmap_test_basic(); - ssmap_test_mixed_case_null(); - ssmap_test_string_view_entry(); + ssmap_test_basic(); + ssmap_test_basic(); + ssmap_test_mixed_case_null(); + ssmap_test_mixed_case_null(); + ssmap_test_find_string_view(); + ssmap_test_find_string_view(); + ssmap_test_move_only_value_type(); + ssmap_test_move_only_value_type(); } if (opt.test_perf) @@ -190,7 +385,6 @@ ssmap_test_perf(); } - fprintf(stdout, "Test finished successfully!\n"); return 0; } diff -Nru mdds-2.1.1/test/trie_map/Makefile.am mdds-3.1.0/test/trie_map/Makefile.am --- mdds-2.1.1/test/trie_map/Makefile.am 2022-10-28 01:42:14.000000000 +0000 +++ mdds-3.1.0/test/trie_map/Makefile.am 2025-01-22 02:40:24.000000000 +0000 @@ -5,8 +5,15 @@ check_PROGRAMS = test-main +EXTRA_DIST = \ + test_main.hpp + test_main_SOURCES = \ test_main.cpp \ + test_state.cpp \ + test_node.cpp \ + test_move_value.cpp \ + test_pack_value_type.cpp \ $(top_srcdir)/test/test_global.cpp TESTS = test-main diff -Nru mdds-2.1.1/test/trie_map/Makefile.in mdds-3.1.0/test/trie_map/Makefile.in --- mdds-2.1.1/test/trie_map/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/test/trie_map/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -100,7 +100,9 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp -am_test_main_OBJECTS = test_main.$(OBJEXT) \ +am_test_main_OBJECTS = test_main.$(OBJEXT) test_state.$(OBJEXT) \ + test_node.$(OBJEXT) test_move_value.$(OBJEXT) \ + test_pack_value_type.$(OBJEXT) \ $(top_builddir)/test/test_global.$(OBJEXT) test_main_OBJECTS = $(am_test_main_OBJECTS) test_main_LDADD = $(LDADD) @@ -120,7 +122,9 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = $(top_builddir)/test/$(DEPDIR)/test_global.Po \ - ./$(DEPDIR)/test_main.Po + ./$(DEPDIR)/test_main.Po ./$(DEPDIR)/test_move_value.Po \ + ./$(DEPDIR)/test_node.Po ./$(DEPDIR)/test_pack_value_type.Po \ + ./$(DEPDIR)/test_state.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -430,7 +434,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -490,8 +493,15 @@ -I$(top_srcdir)/test/include \ $(CXXFLAGS_UNITTESTS) +EXTRA_DIST = \ + test_main.hpp + test_main_SOURCES = \ test_main.cpp \ + test_state.cpp \ + test_node.cpp \ + test_move_value.cpp \ + test_pack_value_type.cpp \ $(top_srcdir)/test/test_global.cpp all: all-am @@ -553,6 +563,10 @@ @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/test/$(DEPDIR)/test_global.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_move_value.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_node.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pack_value_type.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_state.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -896,6 +910,10 @@ distclean: distclean-am -rm -f $(top_builddir)/test/$(DEPDIR)/test_global.Po -rm -f ./$(DEPDIR)/test_main.Po + -rm -f ./$(DEPDIR)/test_move_value.Po + -rm -f ./$(DEPDIR)/test_node.Po + -rm -f ./$(DEPDIR)/test_pack_value_type.Po + -rm -f ./$(DEPDIR)/test_state.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -943,6 +961,10 @@ maintainer-clean: maintainer-clean-am -rm -f $(top_builddir)/test/$(DEPDIR)/test_global.Po -rm -f ./$(DEPDIR)/test_main.Po + -rm -f ./$(DEPDIR)/test_move_value.Po + -rm -f ./$(DEPDIR)/test_node.Po + -rm -f ./$(DEPDIR)/test_pack_value_type.Po + -rm -f ./$(DEPDIR)/test_state.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff -Nru mdds-2.1.1/test/trie_map/test_main.cpp mdds-3.1.0/test/trie_map/test_main.cpp --- mdds-2.1.1/test/trie_map/test_main.cpp 2022-11-01 01:26:35.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_main.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -26,33 +26,24 @@ * ************************************************************************/ -#define MDDS_TRIE_MAP_DEBUG 1 -#include "test_global.hpp" // This must be the first header to be included. -//#define MDDS_TRIE_MAP_DEBUG_DUMP_TRIE 1 -//#define MDDS_TRIE_MAP_DEBUG_DUMP_PACKED 1 - -#include "mdds/trie_map.hpp" -#include "mdds/global.hpp" +#include "test_main.hpp" #include #include #include -#include using namespace std; using namespace mdds; -using packed_int_map_type = packed_trie_map; -using packed_str_map_type = packed_trie_map; - -bool verify_entries(const packed_int_map_type& db, const packed_int_map_type::entry* entries, size_t entry_size) +template +bool verify_entries(const MapT& db, const typename MapT::entry* entries, std::size_t entry_size) { auto results = db.prefix_search(nullptr, 0); for (auto it = results.begin(), ite = results.end(); it != ite; ++it) - cout << it->first << ": " << it->second << endl; + std::cout << it->first << ": " << it->second << std::endl; - const packed_int_map_type::entry* p = entries; - const packed_int_map_type::entry* p_end = p + entry_size; + const auto* p = entries; + const auto* p_end = p + entry_size; for (; p != p_end; ++p) { auto it = db.find(p->key, p->keylen); @@ -63,8 +54,8 @@ return true; } -template -bool check_equal(const T& left, const T& right) +template +bool check_equal(const T1& left, const T2& right) { if (left.first != right.first) { @@ -83,9 +74,11 @@ void trie_packed_test1() { - stack_printer __stack_printer__("::trie_packed_test1"); + MDDS_TEST_FUNC_SCOPE; - packed_int_map_type::entry entries[] = { + using _map_type = mdds::packed_trie_map; + + _map_type::entry entries[] = { {MDDS_ASCII("a"), 13}, {MDDS_ASCII("aa"), 10}, {MDDS_ASCII("ab"), 3}, @@ -93,80 +86,84 @@ }; size_t entry_size = std::size(entries); - packed_int_map_type db(entries, entry_size); - assert(db.size() == 4); - assert(verify_entries(db, entries, entry_size)); + _map_type db(entries, entry_size); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(verify_entries(db, entries, entry_size)); // invalid keys - assert(db.find(MDDS_ASCII("ac")) == db.end()); - assert(db.find(MDDS_ASCII("c")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("ac")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("c")) == db.end()); { // Get all key-value pairs. auto results = db.prefix_search(nullptr, 0); size_t n = std::distance(results.begin(), results.end()); - assert(n == 4); + TEST_ASSERT(n == 4); auto it = results.begin(); - assert(it->first == "a"); - assert(it->second == 13); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 13); ++it; - assert(it->first == "aa"); - assert(it->second == 10); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 10); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 7); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 7); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); } { auto it = db.find(MDDS_ASCII("a")); - assert(it->first == "a"); - assert(it->second == 13); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 13); ++it; - assert(it->first == "aa"); - assert(it->second == 10); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 10); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 7); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 7); ++it; - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } } void trie_packed_test2() { - stack_printer __stack_printer__("::trie_packed_test2"); + MDDS_TEST_FUNC_SCOPE; + + using _map_type = mdds::packed_trie_map; - packed_int_map_type::entry entries[] = { + _map_type::entry entries[] = { {MDDS_ASCII("aaron"), 0}, {MDDS_ASCII("al"), 1}, {MDDS_ASCII("aldi"), 2}, {MDDS_ASCII("andy"), 3}, {MDDS_ASCII("bison"), 4}, {MDDS_ASCII("bruce"), 5}, {MDDS_ASCII("charlie"), 6}, {MDDS_ASCII("charlotte"), 7}, {MDDS_ASCII("david"), 8}, {MDDS_ASCII("dove"), 9}, {MDDS_ASCII("e"), 10}, {MDDS_ASCII("eva"), 11}, }; size_t entry_size = std::size(entries); - packed_int_map_type db(entries, entry_size); - assert(db.size() == 12); - assert(verify_entries(db, entries, entry_size)); + _map_type db(entries, entry_size); + TEST_ASSERT(db.size() == 12); + TEST_ASSERT(verify_entries(db, entries, entry_size)); // invalid keys - assert(db.find(MDDS_ASCII("aarons")) == db.end()); - assert(db.find(MDDS_ASCII("a")) == db.end()); - assert(db.find(MDDS_ASCII("biso")) == db.end()); - assert(db.find(MDDS_ASCII("dAvid")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("aarons")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("a")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("biso")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("dAvid")) == db.end()); } void trie_packed_test3() { - stack_printer __stack_printer__("::trie_packed_test3"); + MDDS_TEST_FUNC_SCOPE; - packed_int_map_type::entry entries[] = { + using _map_type = mdds::packed_trie_map; + + _map_type::entry entries[] = { {MDDS_ASCII("NULL"), 1}, {MDDS_ASCII("Null"), 2}, {MDDS_ASCII("null"), 3}, @@ -174,20 +171,20 @@ }; size_t entry_size = std::size(entries); - packed_int_map_type db(entries, entry_size); - assert(db.size() == 4); - assert(verify_entries(db, entries, entry_size)); + _map_type db(entries, entry_size); + TEST_ASSERT(db.size() == 4); + TEST_ASSERT(verify_entries(db, entries, entry_size)); // invalid keys - assert(db.find(MDDS_ASCII("NUll")) == db.end()); - assert(db.find(MDDS_ASCII("Oull")) == db.end()); - assert(db.find(MDDS_ASCII("Mull")) == db.end()); - assert(db.find(MDDS_ASCII("hell")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("NUll")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("Oull")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("Mull")) == db.end()); + TEST_ASSERT(db.find(MDDS_ASCII("hell")) == db.end()); } void trie_packed_test4() { - stack_printer __stack_printer__("::trie_packed_test4"); + MDDS_TEST_FUNC_SCOPE; enum name_type { @@ -198,49 +195,51 @@ name_david }; - packed_int_map_type::entry entries[] = { + using _map_type = mdds::packed_trie_map; + + _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_size = std::size(entries); - packed_int_map_type db(entries, entry_size); - assert(db.size() == 6); - assert(verify_entries(db, entries, entry_size)); + _map_type db(entries, entry_size); + TEST_ASSERT(db.size() == 6); + TEST_ASSERT(verify_entries(db, entries, entry_size)); // Try invalid keys. - assert(db.find("foo", 3) == db.end()); - assert(db.find("andy133", 7) == db.end()); + TEST_ASSERT(db.find("foo", 3) == db.end()); + TEST_ASSERT(db.find("andy133", 7) == db.end()); // Test prefix search on 'andy'. auto results = db.prefix_search(MDDS_ASCII("andy")); size_t n = std::distance(results.begin(), results.end()); - assert(n == 3); + TEST_ASSERT(n == 3); auto it = results.begin(); - assert(it->first == "andy"); + TEST_ASSERT(it->first == "andy"); ++it; - assert(it->first == "andy1"); + TEST_ASSERT(it->first == "andy1"); ++it; - assert(it->first == "andy13"); + TEST_ASSERT(it->first == "andy13"); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); results = db.prefix_search(MDDS_ASCII("andy's toy")); n = std::distance(results.begin(), results.end()); - assert(n == 0); + TEST_ASSERT(n == 0); results = db.prefix_search(MDDS_ASCII("e")); n = std::distance(results.begin(), results.end()); - assert(n == 0); + TEST_ASSERT(n == 0); results = db.prefix_search(MDDS_ASCII("b")); n = std::distance(results.begin(), results.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it = results.begin(); - assert(it->first == "bruce"); - assert(it->second == name_bruce); + TEST_ASSERT(it->first == "bruce"); + TEST_ASSERT(it->second == name_bruce); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); } struct value_wrapper @@ -259,11 +258,11 @@ return os; } -typedef packed_trie_map packed_value_map_type; +typedef packed_trie_map packed_value_map_type; void trie_packed_test_value_life_cycle() { - stack_printer __stack_printer__("::trie_packed_test_value_life_cycle"); + MDDS_TEST_FUNC_SCOPE; using entry = packed_value_map_type::entry; @@ -285,13 +284,13 @@ }); auto it = db.find(MDDS_ASCII("twelve")); - assert(it->second.value == 12); + TEST_ASSERT(it->second.value == 12); it = db.find(MDDS_ASCII("two")); - assert(it->second.value == 2); + TEST_ASSERT(it->second.value == 2); it = db.find(MDDS_ASCII("foo")); - assert(it == db.end()); + TEST_ASSERT(it == db.end()); } struct custom_string @@ -304,47 +303,57 @@ {} }; -struct custom_string_trait +class custom_string_16 { - typedef uint16_t key_unit_type; - typedef custom_string key_type; - typedef std::vector key_buffer_type; + using buffer_type = std::vector; + buffer_type m_buffer; - static key_buffer_type to_key_buffer(const key_unit_type* str, size_t length) - { - key_buffer_type buf; - const key_unit_type* str_end = str + length; - for (; str != str_end; ++str) - buf.push_back(*str); +public: + using value_type = buffer_type::value_type; + using size_type = buffer_type::size_type; + + custom_string_16() = default; - return buf; + custom_string_16(const value_type* p, size_type n) : m_buffer(p, p + n) + {} + + const value_type* data() const + { + return m_buffer.data(); } - static void push_back(key_buffer_type& buffer, key_unit_type c) + value_type* data() { - buffer.push_back(c); + return m_buffer.data(); } - static void pop_back(key_buffer_type& buffer) + void push_back(value_type c) { - buffer.pop_back(); + m_buffer.push_back(c); } - static key_type to_key(const key_buffer_type& buf) + void pop_back() { - // Cast all uint16_t chars to regular chars. - key_type s; + m_buffer.pop_back(); + } - std::for_each(buf.begin(), buf.end(), [&](key_unit_type c) { s.data.push_back(static_cast(c)); }); - return s; + size_type size() const + { + return m_buffer.size(); } }; -typedef packed_trie_map packed_custom_str_map_type; +std::ostream& operator<<(std::ostream& os, const custom_string_16& v) +{ + os << "(custom-string: size=" << v.size() << ")"; + return os; +} + +using packed_custom_str_map_type = packed_trie_map; void trie_packed_test_custom_string() { - stack_printer __stack_printer__("::trie_packed_test_custom_string"); + MDDS_TEST_FUNC_SCOPE; const uint16_t key_alex[] = {0x41, 0x6C, 0x65, 0x78}; const uint16_t key_bob[] = {0x42, 0x6F, 0x62}; @@ -360,72 +369,72 @@ size_t n_entries = std::size(entries); packed_custom_str_map_type db(entries, n_entries); + for (size_t i = 0; i < n_entries; ++i) { auto it = db.find(entries[i].key, entries[i].keylen); cout << it->second << endl; - assert(it->second == entries[i].value); + TEST_ASSERT(it->second == entries[i].value); } // Find all keys that start with 'M'. auto results = db.prefix_search(key_max, 1); size_t n = std::distance(results.begin(), results.end()); - assert(n == 2); + TEST_ASSERT(n == 2); auto it = results.begin(); - assert(it->first.data == it->second); - assert(it->second == "Max"); + TEST_ASSERT(it->second == "Max"); ++it; - assert(it->first.data == it->second); - assert(it->second == "Ming"); + TEST_ASSERT(it->second == "Ming"); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); } void trie_packed_test_iterator_empty() { - stack_printer __stack_printer__("::trie_packed_test_iterator_empty"); + MDDS_TEST_FUNC_SCOPE; + packed_int_map_type db(nullptr, 0); // empty container packed_int_map_type::const_iterator it = db.begin(); packed_int_map_type::const_iterator ite = db.end(); - assert(it == ite); + TEST_ASSERT(it == ite); } void trie_packed_test_iterator() { - stack_printer __stack_printer__("::trie_packed_test_iterator"); + MDDS_TEST_FUNC_SCOPE; - using trie_map_type = trie_map; + using trie_map_type = trie_map; using packed_type = trie_map_type::packed_type; - using kv = packed_type::key_value_type; + using kv = std::pair; trie_map_type db; db.insert(MDDS_ASCII("a"), 1); packed_type packed = db.pack(); - assert(db.size() == packed.size()); + TEST_ASSERT(db.size() == packed.size()); packed_type::const_iterator it = packed.begin(); packed_type::const_iterator ite = packed.end(); - assert(it != ite); - assert(it->first == "a"); - assert(it->second == 1); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 1); db.insert(MDDS_ASCII("ab"), 2); packed = db.pack(); // this invalidates the end position. - assert(db.size() == packed.size()); + TEST_ASSERT(db.size() == packed.size()); it = packed.begin(); ite = packed.end(); - assert(it != ite); - assert(it->first == "a"); - assert(it->second == 1); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 1); ++it; bool check_true = check_equal(*it++, kv("ab", 2)); - assert(check_true); - assert(it == ite); + TEST_ASSERT(check_true); + TEST_ASSERT(it == ite); db.insert(MDDS_ASCII("aba"), 3); db.insert(MDDS_ASCII("abb"), 4); @@ -434,60 +443,60 @@ db.insert(MDDS_ASCII("bcd"), 7); packed = db.pack(); - assert(db.size() == packed.size()); + TEST_ASSERT(db.size() == packed.size()); it = packed.begin(); ite = packed.end(); - assert(*it == kv("a", 1)); - assert(check_equal(*(++it), kv("ab", 2))); - assert(check_equal(*(++it), kv("aba", 3))); - assert(check_equal(*(++it), kv("abb", 4))); - assert(check_equal(*(++it), kv("abc", 5))); - assert(check_equal(*(++it), kv("bc", 6))); - assert(check_equal(*(++it), kv("bcd", 7))); - assert(it->first == "bcd"); - assert(it->second == 7); + TEST_ASSERT(*it == kv("a", 1)); + TEST_ASSERT(check_equal(*(++it), kv("ab", 2))); + TEST_ASSERT(check_equal(*(++it), kv("aba", 3))); + TEST_ASSERT(check_equal(*(++it), kv("abb", 4))); + TEST_ASSERT(check_equal(*(++it), kv("abc", 5))); + TEST_ASSERT(check_equal(*(++it), kv("bc", 6))); + TEST_ASSERT(check_equal(*(++it), kv("bcd", 7))); + TEST_ASSERT(it->first == "bcd"); + TEST_ASSERT(it->second == 7); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); --it; - assert(it != ite); - assert(check_equal(*it, kv("bcd", 7))); + TEST_ASSERT(it != ite); + TEST_ASSERT(check_equal(*it, kv("bcd", 7))); --it; - assert(check_equal(*it, kv("bc", 6))); + TEST_ASSERT(check_equal(*it, kv("bc", 6))); --it; - assert(check_equal(*it, kv("abc", 5))); + TEST_ASSERT(check_equal(*it, kv("abc", 5))); --it; - assert(check_equal(*it, kv("abb", 4))); + TEST_ASSERT(check_equal(*it, kv("abb", 4))); --it; - assert(check_equal(*it, kv("aba", 3))); + TEST_ASSERT(check_equal(*it, kv("aba", 3))); --it; - assert(check_equal(*it, kv("ab", 2))); - assert(check_equal(*(--it), kv("a", 1))); - assert(it == packed.begin()); + TEST_ASSERT(check_equal(*it, kv("ab", 2))); + TEST_ASSERT(check_equal(*(--it), kv("a", 1))); + TEST_ASSERT(it == packed.begin()); - assert(check_equal(*(++it), kv("ab", 2))); - assert(check_equal(*(++it), kv("aba", 3))); + TEST_ASSERT(check_equal(*(++it), kv("ab", 2))); + TEST_ASSERT(check_equal(*(++it), kv("aba", 3))); --it; - assert(check_equal(*it, kv("ab", 2))); + TEST_ASSERT(check_equal(*it, kv("ab", 2))); --it; - assert(check_equal(*it, kv("a", 1))); + TEST_ASSERT(check_equal(*it, kv("a", 1))); ++it; - assert(check_equal(*it, kv("ab", 2))); + TEST_ASSERT(check_equal(*it, kv("ab", 2))); ++it; - assert(check_equal(*it, kv("aba", 3))); + TEST_ASSERT(check_equal(*it, kv("aba", 3))); // Post-decrement operator. - assert(check_equal(*it--, kv("aba", 3))); - assert(check_equal(*it, kv("ab", 2))); + TEST_ASSERT(check_equal(*it--, kv("aba", 3))); + TEST_ASSERT(check_equal(*it, kv("ab", 2))); } void trie_packed_test_prefix_search1() { - stack_printer __stack_printer__("::trie_packed_test_prefix_search1"); + MDDS_TEST_FUNC_SCOPE; - using trie_map_type = trie_map; + using trie_map_type = trie_map; using packed_type = trie_map_type::packed_type; trie_map_type db; @@ -498,42 +507,42 @@ { auto results = db.prefix_search(MDDS_ASCII("andy")); auto it = results.begin(); - assert(it != results.end()); - assert(it->first == "andy"); + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->first == "andy"); ++it; - assert(it->first == "andy1"); + TEST_ASSERT(it->first == "andy1"); ++it; - assert(it->first == "andy12"); + TEST_ASSERT(it->first == "andy12"); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); size_t n = std::distance(results.begin(), results.end()); - assert(n == 3); + TEST_ASSERT(n == 3); } packed_type packed = db.pack(); { auto results = packed.prefix_search(MDDS_ASCII("andy")); auto it = results.begin(); - assert(it != results.end()); - assert(it->first == "andy"); + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->first == "andy"); ++it; - assert(it->first == "andy1"); + TEST_ASSERT(it->first == "andy1"); ++it; - assert(it->first == "andy12"); + TEST_ASSERT(it->first == "andy12"); ++it; - assert(it == results.end()); + TEST_ASSERT(it == results.end()); size_t n = std::distance(results.begin(), results.end()); - assert(n == 3); + TEST_ASSERT(n == 3); } } void trie_packed_test_key_as_input() { - stack_printer __stack_printer__("::trie_packed_test_key_as_input"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; + typedef trie_map trie_map_type; trie_map_type db; db.insert(std::string("string as key"), 1); @@ -541,23 +550,24 @@ auto packed = db.pack(); auto it = packed.find("literal as key"); - assert(it != packed.end()); - assert(it->first == "literal as key"); - assert(it->second == 2); + TEST_ASSERT(it != packed.end()); + TEST_ASSERT(it->first == "literal as key"); + TEST_ASSERT(it->second == 2); auto results = packed.prefix_search("str"); auto rit = results.begin(); - assert(rit != results.end()); - assert(rit->first == "string as key"); - assert(rit->second == 1); + TEST_ASSERT(rit != results.end()); + TEST_ASSERT(rit->first == "string as key"); + TEST_ASSERT(rit->second == 1); ++rit; - assert(rit == results.end()); + TEST_ASSERT(rit == results.end()); } void trie_packed_test_copying() { - stack_printer __stack_printer__("::trie_packed_test_copying"); - using map_type = packed_trie_map; + MDDS_TEST_FUNC_SCOPE; + + using map_type = packed_trie_map; map_type::entry entries[] = { {MDDS_ASCII("aaron"), 0}, {MDDS_ASCII("al"), 1}, {MDDS_ASCII("aldi"), 2}, {MDDS_ASCII("andy"), 3}, @@ -570,66 +580,66 @@ const map_type::entry* p_entries = entries; const map_type::entry* p_entries_end = p_entries + db.size(); size_t n = std::distance(p_entries, p_entries_end); - assert(db.size() == n); - assert(!db.empty()); + TEST_ASSERT(db.size() == n); + TEST_ASSERT(!db.empty()); for (; p_entries != p_entries_end; ++p_entries, ++it) { std::string key_expected(p_entries->key, p_entries->keylen); - assert(key_expected == it->first); - assert(p_entries->value == it->second); + TEST_ASSERT(key_expected == it->first); + TEST_ASSERT(p_entries->value == it->second); } }; auto db = std::make_unique(entries, std::size(entries)); auto db_copied(*db); - assert(*db == db_copied); - assert(db->size() == db_copied.size()); + TEST_ASSERT(*db == db_copied); + TEST_ASSERT(db->size() == db_copied.size()); db.reset(); auto it = db_copied.find("charlie"); - assert(it != db_copied.end()); - assert(it->first == "charlie"); - assert(it->second == 6); + TEST_ASSERT(it != db_copied.end()); + TEST_ASSERT(it->first == "charlie"); + TEST_ASSERT(it->second == 6); verify_content(db_copied); auto db_moved(std::move(db_copied)); - assert(db_copied.empty()); - assert(!db_moved.empty()); - assert(db_moved.size() == std::size(entries)); + TEST_ASSERT(db_copied.empty()); + TEST_ASSERT(!db_moved.empty()); + TEST_ASSERT(db_moved.size() == std::size(entries)); it = db_copied.find("bison"); - assert(it == db_copied.end()); + TEST_ASSERT(it == db_copied.end()); it = db_moved.find("bison"); - assert(it != db_moved.end()); - assert(it->first == "bison"); - assert(it->second == 4); + TEST_ASSERT(it != db_moved.end()); + TEST_ASSERT(it->first == "bison"); + TEST_ASSERT(it->second == 4); verify_content(db_moved); map_type db_copy_assigned; - assert(db_copy_assigned.empty()); + TEST_ASSERT(db_copy_assigned.empty()); db_copy_assigned = db_moved; - assert(db_copy_assigned == db_moved); + TEST_ASSERT(db_copy_assigned == db_moved); verify_content(db_moved); verify_content(db_copy_assigned); map_type db_move_assigned; - assert(db_move_assigned.empty()); + TEST_ASSERT(db_move_assigned.empty()); db_move_assigned = std::move(db_moved); - assert(db_move_assigned != db_moved); + TEST_ASSERT(db_move_assigned != db_moved); verify_content(db_move_assigned); - assert(db_moved.empty()); + TEST_ASSERT(db_moved.empty()); } void trie_packed_test_non_equal() { - stack_printer __stack_printer__("::trie_packed_test_non_equal"); + MDDS_TEST_FUNC_SCOPE; - using map_type = packed_trie_map; + using map_type = packed_trie_map; map_type::entry entries1[] = { {MDDS_ASCII("aaron"), 0}, {MDDS_ASCII("al"), 1}, {MDDS_ASCII("aldi"), 2}, {MDDS_ASCII("andy"), 3}, @@ -654,682 +664,154 @@ map_type db1(entries1, std::size(entries1)); map_type db2(entries2, std::size(entries2)); map_type db3(entries3, std::size(entries3)); - assert(db1 != db2); - assert(db1 != db3); - assert(db2 != db3); + TEST_ASSERT(db1 != db2); + TEST_ASSERT(db1 != db3); + TEST_ASSERT(db2 != db3); map_type db4(entries1, std::size(entries1)); map_type db5(entries2, std::size(entries2)); map_type db6(entries3, std::size(entries3)); - assert(db1 == db4); - assert(db2 == db5); - assert(db3 == db6); -} - -namespace trie_packed_test_save_and_load_state { - -struct _custom_variable_value -{ - enum class v_type - { - unknown, - fp32, - int64 - }; - - v_type type; - - union - { - float fp32; - int64_t int64; - } value; - - _custom_variable_value() : type(v_type::unknown) - {} - - _custom_variable_value(float v) : type(v_type::fp32) - { - value.fp32 = v; - } - - _custom_variable_value(int v) : type(v_type::int64) - { - value.int64 = v; - } - - _custom_variable_value(const _custom_variable_value& other) : type(other.type) - { - switch (type) - { - case v_type::fp32: - value.fp32 = other.value.fp32; - break; - case v_type::int64: - value.int64 = other.value.int64; - break; - default:; - } - } - - bool operator==(const _custom_variable_value& other) const - { - if (type != other.type) - return false; - - switch (type) - { - case v_type::fp32: - return value.fp32 == other.value.fp32; - case v_type::int64: - return value.int64 == other.value.int64; - default:; - } - - return true; - } - - bool operator!=(const _custom_variable_value& other) const - { - return !operator==(other); - } -}; - -struct _custom_variable_serializer -{ - union bin_value - { - char buffer[8]; - float fp32; - int64_t int64; - }; - - static constexpr bool variable_size = true; - - static void write(std::ostream& os, const _custom_variable_value& v) - { - bin_value bv; - - switch (v.type) - { - case _custom_variable_value::v_type::unknown: - { - char c = 0; - os.write(&c, 1); - break; - } - case _custom_variable_value::v_type::fp32: - { - char c = 1; - os.write(&c, 1); - bv.fp32 = v.value.fp32; - os.write(bv.buffer, 4); - break; - } - case _custom_variable_value::v_type::int64: - { - char c = 2; - os.write(&c, 1); - bv.int64 = v.value.int64; - os.write(bv.buffer, 8); - break; - } - } - } - - static void read(std::istream& is, size_t n, _custom_variable_value& v) - { - assert(n > 0); - char c; - is.read(&c, 1); - - switch (c) - { - case 0: - v.type = _custom_variable_value::v_type::unknown; - break; - case 1: - v.type = _custom_variable_value::v_type::fp32; - break; - case 2: - v.type = _custom_variable_value::v_type::int64; - break; - default: - assert(!"invalid value type"); - } - - n -= 1; - bin_value bv; - - switch (v.type) - { - case _custom_variable_value::v_type::fp32: - assert(n == 4); - is.read(bv.buffer, 4); - v.value.fp32 = bv.fp32; - break; - case _custom_variable_value::v_type::int64: - assert(n == 8); - is.read(bv.buffer, 8); - v.value.int64 = bv.int64; - break; - case _custom_variable_value::v_type::unknown: - break; - default: - assert(!"invalid value type"); - } - } -}; - -/** - * mock value struct containing one value string that only stores "zero", - * "one", "two" or "three". We use a custom serializer to store the value - * using only 1 byte each. - */ -struct _custom_fixed_value -{ - std::string value_string; // only stores "zero", "one", "two" or "three". - - _custom_fixed_value() - {} - - _custom_fixed_value(const char* p) : value_string(p, std::strlen(p)) - {} - - bool operator==(const _custom_fixed_value& other) const - { - return value_string == other.value_string; - } - - bool operator!=(const _custom_fixed_value& other) const - { - return !operator==(other); - } -}; - -struct _custom_fixed_serializer -{ - static constexpr bool variable_size = false; - static constexpr size_t value_size = 1; - - static void write(std::ostream& os, const _custom_fixed_value& v) - { - char bv = -1; - - if (v.value_string == "zero") - bv = 0; - else if (v.value_string == "one") - bv = 1; - else if (v.value_string == "two") - bv = 2; - else if (v.value_string == "three") - bv = 3; - - os.write(&bv, 1); - } - - static void read(std::istream& is, size_t n, _custom_fixed_value& v) - { - assert(n == 1); - char bv = -1; - is.read(&bv, 1); - - switch (bv) - { - case 0: - v.value_string = "zero"; - break; - case 1: - v.value_string = "one"; - break; - case 2: - v.value_string = "two"; - break; - case 3: - v.value_string = "three"; - break; - default: - v.value_string = "???"; - } - } -}; - -void test1() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test1"); - packed_int_map_type empty_db; - - std::string saved_state; - - { - std::ostringstream state; - empty_db.save_state(state); - saved_state = state.str(); - } - - packed_int_map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(restored == empty_db); + TEST_ASSERT(db1 == db4); + TEST_ASSERT(db2 == db5); + TEST_ASSERT(db3 == db6); } -void test2() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test2"); - packed_int_map_type::entry entries[] = { - {MDDS_ASCII("bruce"), 5}, {MDDS_ASCII("charlie"), 6}, {MDDS_ASCII("charlotte"), 7}, - {MDDS_ASCII("david"), 8}, {MDDS_ASCII("dove"), 9}, - }; - - packed_int_map_type db(entries, std::size(entries)); - - std::string saved_state; - - { - std::ostringstream state; - db.save_state(state); - saved_state = state.str(); - } - - packed_int_map_type restored; - assert(restored != db); - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(restored == db); -} - -void test3() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test3"); - std::vector entries = { - {MDDS_ASCII("Abby"), "ABBY"}, - {MDDS_ASCII("Ashley"), "ASHLEY"}, - {MDDS_ASCII("Candelaria"), "CANDELARIA"}, - {MDDS_ASCII("Carita"), "CARITA"}, - {MDDS_ASCII("Christal"), "CHRISTAL"}, - {MDDS_ASCII("Cory"), "CORY"}, - {MDDS_ASCII("Estrella"), "ESTRELLA"}, - {MDDS_ASCII("Etha"), "ETHA"}, - {MDDS_ASCII("Harley"), "HARLEY"}, - {MDDS_ASCII("Irish"), "IRISH"}, - {MDDS_ASCII("Kiara"), "KIARA"}, - {MDDS_ASCII("Korey"), "KOREY"}, - {MDDS_ASCII("Laurene"), "LAURENE"}, - {MDDS_ASCII("Michiko"), "MICHIKO"}, - {MDDS_ASCII("Miriam"), "MIRIAM"}, - {MDDS_ASCII("Mitzi"), "MITZI"}, - {MDDS_ASCII("Seth"), "SETH"}, - {MDDS_ASCII("Sindy"), "SINDY"}, - {MDDS_ASCII("Tawanna"), "TAWANNA"}, - {MDDS_ASCII("Tyra"), "TYRA"}, - }; - - packed_str_map_type db(entries.data(), entries.size()); - - // Run some search. - auto results = db.prefix_search("Mi"); - auto it = results.begin(); - assert(it != results.end()); - assert(it->first == "Michiko"); - assert(it->second == "MICHIKO"); - ++it; - assert(it != results.end()); - assert(it->first == "Miriam"); - assert(it->second == "MIRIAM"); - ++it; - assert(it != results.end()); - assert(it->first == "Mitzi"); - assert(it->second == "MITZI"); - ++it; - assert(it == results.end()); - - std::string saved_state; - - { - std::ostringstream state; - db.save_state(state); - saved_state = state.str(); - } - - packed_str_map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(db == restored); -} - -void test4() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test4"); - using map_type = packed_trie_map>; - - std::vector entries = { - {MDDS_ASCII("Abby"), {65, 98, 98, 121}}, - {MDDS_ASCII("Ashley"), {65, 115, 104, 108, 101, 121}}, - {MDDS_ASCII("Christal"), {67, 104, 114, 105, 115, 116, 97, 108}}, - {MDDS_ASCII("Cory"), {67, 111, 114, 121}}, - {MDDS_ASCII("Harley"), {72, 97, 114, 108, 101, 121}}, - {MDDS_ASCII("Kiara"), {75, 105, 97, 114, 97}}, - {MDDS_ASCII("Mitzi"), {77, 105, 116, 122, 105}}, - }; - - map_type db(entries.data(), entries.size()); - assert(db.size() == entries.size()); - - std::string saved_state; - { - std::ostringstream state; - db.save_state(state); - saved_state = state.str(); - } - - map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(db == restored); -} - -void test5() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test5"); - using map_type = packed_trie_map; - - std::vector entries = { - {MDDS_ASCII("Abby"), 1.0f}, {MDDS_ASCII("Ashley"), 1.1f}, {MDDS_ASCII("Christal"), 1.2f}, - {MDDS_ASCII("Cory"), 1.3f}, {MDDS_ASCII("Harley"), 1.4f}, {MDDS_ASCII("Kiara"), 1.5f}, - {MDDS_ASCII("Mitzi"), 1.6f}, - }; - - map_type db(entries.data(), entries.size()); - assert(db.size() == entries.size()); - - std::string saved_state; - { - std::ostringstream state; - db.save_state(state); - saved_state = state.str(); - } - - map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(db == restored); -} - -template -void test6() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test6"); - using map_type = packed_trie_map; - - std::vector entries = { - {MDDS_ASCII("Abby"), {65.0, 98.1, 98.2, 121.3}}, - {MDDS_ASCII("Ashley"), {65.0, 11.5, 1.04, 1.08, .101, .12586}}, - {MDDS_ASCII("Christal"), {67.0, -10.4, -114.236}}, - {MDDS_ASCII("Cory"), {67.0, 122.111}}, - {MDDS_ASCII("Harley"), {72.0, 97.12, -1.114}}, - {MDDS_ASCII("Kiara"), {75.0, 1.05, 9.7, 1.14, -97.5}}, - {MDDS_ASCII("Mitzi"), {77.0, 10.5, 11.6, 1.22, 10.5}}, - }; - - map_type db(entries.data(), entries.size()); - assert(db.size() == entries.size()); - - std::string saved_state; - { - std::ostringstream state; - db.save_state(state); - saved_state = state.str(); - } - - map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state(state); - } - - assert(db == restored); -} - -void test7() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test7"); - using map_type = packed_trie_map; - - std::vector entries = { - {MDDS_ASCII("Alan"), 1.2f}, {MDDS_ASCII("Cory"), -125}, {MDDS_ASCII("Eleni"), 966}, - {MDDS_ASCII("Evia"), -0.987f}, {MDDS_ASCII("Nathaniel"), 0}, {MDDS_ASCII("Rebbecca"), 1.234f}, - {MDDS_ASCII("Rodrick"), 34253536}, {MDDS_ASCII("Stuart"), 12}, {MDDS_ASCII("Verline"), 56}, - }; - - map_type db(entries.data(), entries.size()); - assert(db.size() == entries.size()); - - std::string saved_state; - { - std::ostringstream state; - db.save_state<_custom_variable_serializer>(state); - saved_state = state.str(); - } - - map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state<_custom_variable_serializer>(state); - } - - assert(db == restored); -} - -void test8() -{ - stack_printer __stack_printer__("trie_packed_test_save_and_load_state::test8"); - using map_type = packed_trie_map; - - std::vector entries = { - {MDDS_ASCII("Bernardine"), "zero"}, {MDDS_ASCII("Donny"), "two"}, {MDDS_ASCII("Julia"), "one"}, - {MDDS_ASCII("Lindsy"), "three"}, {MDDS_ASCII("Martine"), "three"}, {MDDS_ASCII("Shana"), "two"}, - {MDDS_ASCII("Sonia"), "zero"}, {MDDS_ASCII("Tracie"), "one"}, {MDDS_ASCII("Vanita"), "two"}, - {MDDS_ASCII("Yung"), "zero"}, - }; - - map_type db(entries.data(), entries.size()); - assert(db.size() == entries.size()); - - std::string saved_state; - { - std::ostringstream state; - db.save_state<_custom_fixed_serializer>(state); - saved_state = state.str(); - } - - map_type restored; - - { - std::istringstream state(saved_state); - restored.load_state<_custom_fixed_serializer>(state); - } - - assert(db == restored); - - // Run some query to make sure it is still functional. - auto it = restored.find("Tracie"); - assert(it->first == "Tracie"); - assert(it->second.value_string == "one"); -} - -void run() -{ - test1(); - test2(); - test3(); - test4(); - test5(); - test6>(); - test6>(); - test6>(); - test7(); - test8(); -} - -} // namespace trie_packed_test_save_and_load_state - void trie_test1() { - stack_printer __stack_printer__("::trie_test1"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; - typedef packed_trie_map packed_trie_map_type; + typedef trie_map trie_map_type; + typedef packed_trie_map packed_trie_map_type; trie_map_type db; const trie_map_type& dbc = db; - assert(db.size() == 0); + TEST_ASSERT(db.size() == 0); db.insert(MDDS_ASCII("Barak"), custom_string("Obama")); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); db.insert(MDDS_ASCII("Bob"), custom_string("Marley")); - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); db.insert(MDDS_ASCII("Hideki"), custom_string("Matsui")); - assert(db.size() == 3); + TEST_ASSERT(db.size() == 3); auto it = dbc.find(MDDS_ASCII("Barak")); - assert(it->first == "Barak"); + TEST_ASSERT(it->first == "Barak"); custom_string res = it->second; - assert(res.data == "Obama"); + TEST_ASSERT(res.data == "Obama"); res = dbc.find(MDDS_ASCII("Bob"))->second; - assert(res.data == "Marley"); + TEST_ASSERT(res.data == "Marley"); res = dbc.find(MDDS_ASCII("Hideki"))->second; - assert(res.data == "Matsui"); + TEST_ASSERT(res.data == "Matsui"); // Non-existent key. it = dbc.find(MDDS_ASCII("Von")); - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); it = dbc.find(MDDS_ASCII("Bar")); - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); // Perform prefix search on "B", which should return both "Barak" and "Bob". // The results should be sorted. { auto matches = dbc.prefix_search(MDDS_ASCII("B")); size_t n = std::distance(matches.begin(), matches.end()); - assert(n == 2); + TEST_ASSERT(n == 2); auto it2 = matches.begin(); - assert(it2->first == "Barak"); - assert(it2->second.data == "Obama"); + TEST_ASSERT(it2->first == "Barak"); + TEST_ASSERT(it2->second.data == "Obama"); ++it2; - assert(it2->first == "Bob"); - assert(it2->second.data == "Marley"); + TEST_ASSERT(it2->first == "Bob"); + TEST_ASSERT(it2->second.data == "Marley"); matches = dbc.prefix_search(MDDS_ASCII("Hi")); n = std::distance(matches.begin(), matches.end()); - assert(n == 1); + TEST_ASSERT(n == 1); it2 = matches.begin(); - assert(it2->first == "Hideki"); - assert(it2->second.data == "Matsui"); + TEST_ASSERT(it2->first == "Hideki"); + TEST_ASSERT(it2->second.data == "Matsui"); // Invalid prefix searches. matches = dbc.prefix_search(MDDS_ASCII("Bad")); - assert(matches.begin() == matches.end()); + TEST_ASSERT(matches.begin() == matches.end()); matches = dbc.prefix_search(MDDS_ASCII("Foo")); - assert(matches.begin() == matches.end()); + TEST_ASSERT(matches.begin() == matches.end()); } { // Create a packed version from it, and make sure it still generates the // same results. packed_trie_map_type packed(dbc); - assert(packed.size() == dbc.size()); + TEST_ASSERT(packed.size() == dbc.size()); { auto results = packed.prefix_search(MDDS_ASCII("B")); size_t n = std::distance(results.begin(), results.end()); - assert(n == 2); + TEST_ASSERT(n == 2); auto it2 = results.begin(); - assert(it2->first == "Barak"); - assert(it2->second.data == "Obama"); + TEST_ASSERT(it2->first == "Barak"); + TEST_ASSERT(it2->second.data == "Obama"); ++it2; - assert(it2->first == "Bob"); - assert(it2->second.data == "Marley"); + TEST_ASSERT(it2->first == "Bob"); + TEST_ASSERT(it2->second.data == "Marley"); ++it2; - assert(it2 == results.end()); + TEST_ASSERT(it2 == results.end()); } { auto results = dbc.prefix_search(MDDS_ASCII("Hi")); size_t n = std::distance(results.begin(), results.end()); - assert(n == 1); + TEST_ASSERT(n == 1); auto it2 = results.begin(); - assert(it2->first == "Hideki"); - assert(it2->second.data == "Matsui"); + TEST_ASSERT(it2->first == "Hideki"); + TEST_ASSERT(it2->second.data == "Matsui"); } // Invalid prefix searches. auto results = dbc.prefix_search(MDDS_ASCII("Bad")); - assert(results.begin() == results.end()); + TEST_ASSERT(results.begin() == results.end()); results = dbc.prefix_search(MDDS_ASCII("Foo")); - assert(results.begin() == results.end()); + TEST_ASSERT(results.begin() == results.end()); } { - auto packed = dbc.pack(); + trie_map_type copied(dbc); + auto packed = copied.pack(); auto results = packed.prefix_search(MDDS_ASCII("B")); size_t n = std::distance(results.begin(), results.end()); - assert(n == 2); + TEST_ASSERT(n == 2); auto it2 = results.begin(); - assert(it2->first == "Barak"); - assert(it2->second.data == "Obama"); + TEST_ASSERT(it2->first == "Barak"); + TEST_ASSERT(it2->second.data == "Obama"); ++it2; - assert(it2->first == "Bob"); - assert(it2->second.data == "Marley"); + TEST_ASSERT(it2->first == "Bob"); + TEST_ASSERT(it2->second.data == "Marley"); } // Erase an existing key. bool erased = db.erase(MDDS_ASCII("Hideki")); - assert(erased); - assert(db.size() == 2); + TEST_ASSERT(erased); + TEST_ASSERT(db.size() == 2); it = dbc.find(MDDS_ASCII("Hideki")); - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); // Try to erase a key that doesn't exist. erased = db.erase(MDDS_ASCII("Foo")); - assert(!erased); - assert(db.size() == 2); + TEST_ASSERT(!erased); + TEST_ASSERT(db.size() == 2); // Clear the whole thing. db.clear(); - assert(db.size() == 0); + TEST_ASSERT(db.size() == 0); } void trie_test2() { - stack_printer __stack_printer__("::trie_test2"); - using key_trait = trie::std_container_traits>; - using map_type = trie_map; - using key_type = map_type::key_type; + MDDS_TEST_FUNC_SCOPE; + + using key_type = std::vector; + using map_type = trie_map; auto print_key = [](const std::vector& key, const char* msg) { cout << msg << ": "; @@ -1342,30 +824,31 @@ print_key(key, "original"); int value = 1; db.insert(key, value); - assert(db.size() == 1); + TEST_ASSERT(db.size() == 1); { auto it = db.begin(); - assert(it != db.end()); - assert(it->first == key); + TEST_ASSERT(it != db.end()); + TEST_ASSERT(it->first == key); print_key(it->first, "from trie_map"); } auto packed = db.pack(); - assert(packed.size() == 1); + TEST_ASSERT(packed.size() == 1); { auto it = packed.begin(); - assert(it != packed.end()); + TEST_ASSERT(it != packed.end()); print_key(it->first, "from packed_trie_map"); - assert(it->first == key); + TEST_ASSERT(it->first == key); } } void trie_test_iterator_empty() { - stack_printer __stack_printer__("::trie_test_iterator_empty"); - typedef trie_map trie_map_type; + MDDS_TEST_FUNC_SCOPE; + + typedef trie_map trie_map_type; trie_map_type db; const trie_map_type& dbc = db; @@ -1373,16 +856,17 @@ trie_map_type::const_iterator it = dbc.begin(); trie_map_type::const_iterator ite = dbc.end(); - assert(it == ite); - assert(db.begin() == dbc.begin()); // non-const vs const iterators - assert(dbc.end() == db.end()); // const vs non-const iterators + TEST_ASSERT(it == ite); + TEST_ASSERT(db.begin() == dbc.begin()); // non-const vs const iterators + TEST_ASSERT(dbc.end() == db.end()); // const vs non-const iterators } void trie_test_iterator() { - stack_printer __stack_printer__("::trie_test_iterator"); - typedef trie_map trie_map_type; - using kv = trie_map_type::key_value_type; + MDDS_TEST_FUNC_SCOPE; + + typedef trie_map trie_map_type; + using kv = std::pair; trie_map_type db; const trie_map_type& dbc = db; @@ -1396,28 +880,28 @@ // the root node which will never get modified as long as the parent // container is alive. - assert(it == ite); + TEST_ASSERT(it == ite); cout << "one element" << endl; db.insert(MDDS_ASCII("a"), 1); it = dbc.begin(); - assert(it != ite); - assert(*it == kv("a", 1)); + TEST_ASSERT(it != ite); + TEST_ASSERT(*it == kv("a", 1)); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); cout << "two elements" << endl; db.insert(MDDS_ASCII("ab"), 2); it = dbc.begin(); - assert(it != ite); - assert(*it == kv("a", 1)); + TEST_ASSERT(it != ite); + TEST_ASSERT(*it == kv("a", 1)); ++it; - assert(it != ite); - assert(*it == kv("ab", 2)); + TEST_ASSERT(it != ite); + TEST_ASSERT(*it == kv("ab", 2)); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); cout << "more than two elements" << endl; @@ -1428,62 +912,63 @@ db.insert(MDDS_ASCII("bcd"), 7); it = dbc.begin(); - assert(*it == kv("a", 1)); + TEST_ASSERT(*it == kv("a", 1)); ++it; - assert(*it == kv("ab", 2)); + TEST_ASSERT(*it == kv("ab", 2)); ++it; - assert(*it == kv("aba", 3)); + TEST_ASSERT(*it == kv("aba", 3)); ++it; - assert(*it == kv("abb", 4)); + TEST_ASSERT(*it == kv("abb", 4)); ++it; - assert(*it == kv("abc", 5)); + TEST_ASSERT(*it == kv("abc", 5)); ++it; - assert(*it == kv("bc", 6)); + TEST_ASSERT(*it == kv("bc", 6)); ++it; - assert(*it == kv("bcd", 7)); - assert(it->first == "bcd"); - assert(it->second == 7); + TEST_ASSERT(*it == kv("bcd", 7)); + TEST_ASSERT(it->first == "bcd"); + TEST_ASSERT(it->second == 7); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); --it; - assert(it != ite); - assert(*it == kv("bcd", 7)); + TEST_ASSERT(it != ite); + TEST_ASSERT(*it == kv("bcd", 7)); --it; - assert(*it == kv("bc", 6)); + TEST_ASSERT(*it == kv("bc", 6)); --it; - assert(*it == kv("abc", 5)); + TEST_ASSERT(*it == kv("abc", 5)); --it; - assert(*it == kv("abb", 4)); + TEST_ASSERT(*it == kv("abb", 4)); --it; - assert(*it == kv("aba", 3)); + TEST_ASSERT(*it == kv("aba", 3)); --it; - assert(*it == kv("ab", 2)); + TEST_ASSERT(*it == kv("ab", 2)); --it; - assert(*it == kv("a", 1)); - assert(it == dbc.begin()); + TEST_ASSERT(*it == kv("a", 1)); + TEST_ASSERT(it == dbc.begin()); ++it; - assert(*it == kv("ab", 2)); + TEST_ASSERT(*it == kv("ab", 2)); ++it; - assert(*it == kv("aba", 3)); + TEST_ASSERT(*it == kv("aba", 3)); --it; - assert(*it == kv("ab", 2)); + TEST_ASSERT(*it == kv("ab", 2)); --it; - assert(*it == kv("a", 1)); + TEST_ASSERT(*it == kv("a", 1)); ++it; - assert(*it == kv("ab", 2)); + TEST_ASSERT(*it == kv("ab", 2)); ++it; - assert(*it == kv("aba", 3)); + TEST_ASSERT(*it == kv("aba", 3)); - assert(db.begin() != dbc.end()); // non-const vs const iterators - assert(dbc.begin() != db.end()); // const vs non-const iterators + TEST_ASSERT(db.begin() != dbc.end()); // non-const vs const iterators + TEST_ASSERT(dbc.begin() != db.end()); // const vs non-const iterators } void trie_test_iterator_with_erase() { - stack_printer __stack_printer__("::trie_test_iterator_with_erase"); - typedef trie_map trie_map_type; - using kv = trie_map_type::key_value_type; + MDDS_TEST_FUNC_SCOPE; + + typedef trie_map trie_map_type; + using kv = std::pair; trie_map_type db; const trie_map_type& dbc = db; bool check_true = false; @@ -1493,22 +978,22 @@ auto it = dbc.begin(), ite = dbc.end(); check_true = (*it++ == kv("C++", 2)); - assert(check_true); + TEST_ASSERT(check_true); check_true = (*it++ == kv("Python", 1)); - assert(check_true); - assert(it == ite); + TEST_ASSERT(check_true); + TEST_ASSERT(it == ite); db.erase(MDDS_ASCII("C++")); it = dbc.begin(); check_true = (*it++ == kv("Python", 1)); - assert(check_true); - assert(it == ite); + TEST_ASSERT(check_true); + TEST_ASSERT(it == ite); check_true = (*(--it) == kv("Python", 1)); - assert(check_true); - assert(it == dbc.begin()); + TEST_ASSERT(check_true); + TEST_ASSERT(it == dbc.begin()); db.clear(); - assert(dbc.begin() == dbc.end()); + TEST_ASSERT(dbc.begin() == dbc.end()); db.insert(MDDS_ASCII("A"), 1); db.insert(MDDS_ASCII("AB"), 2); @@ -1517,16 +1002,16 @@ it = dbc.begin(); check_true = (*it++ == kv("A", 1)); - assert(check_true); + TEST_ASSERT(check_true); check_true = (*it++ == kv("ABC", 3)); - assert(check_true); - assert(it == ite); + TEST_ASSERT(check_true); + TEST_ASSERT(it == ite); check_true = (*(--it) == kv("ABC", 3)); - assert(check_true); + TEST_ASSERT(check_true); check_true = (*(--it) == kv("A", 1)); - assert(check_true); - assert(it == dbc.begin()); + TEST_ASSERT(check_true); + TEST_ASSERT(it == dbc.begin()); db.clear(); db.insert(MDDS_ASCII("A"), 1); @@ -1536,27 +1021,28 @@ it = dbc.begin(); check_true = (*it++ == kv("A", 1)); - assert(check_true); + TEST_ASSERT(check_true); check_true = (*it++ == kv("AB", 2)); - assert(check_true); - assert(it == ite); + TEST_ASSERT(check_true); + TEST_ASSERT(it == ite); check_true = (*(--it) == kv("AB", 2)); - assert(check_true); + TEST_ASSERT(check_true); check_true = (*(--it) == kv("A", 1)); - assert(check_true); - assert(it == dbc.begin()); + TEST_ASSERT(check_true); + TEST_ASSERT(it == dbc.begin()); it = ite; --it; - assert(*it-- == kv("AB", 2)); // test post-decrement operator. - assert(*it == kv("A", 1)); + TEST_ASSERT(*it-- == kv("AB", 2)); // test post-decrement operator. + TEST_ASSERT(*it == kv("A", 1)); } void trie_test_find_iterator() { - stack_printer __stack_printer__("::trie_test_find_iterator"); - typedef trie_map trie_map_type; + MDDS_TEST_FUNC_SCOPE; + + typedef trie_map trie_map_type; trie_map_type db; const trie_map_type& dbc = db; @@ -1566,99 +1052,99 @@ db.insert(MDDS_ASCII("b"), 4); { auto it = dbc.find(MDDS_ASCII("a")); - assert(it->first == "a"); - assert(it->second == 1); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 1); ++it; - assert(it->first == "aa"); - assert(it->second == 2); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 2); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); it = dbc.find(MDDS_ASCII("aa")); - assert(it->first == "aa"); - assert(it->second == 2); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 2); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); it = dbc.find(MDDS_ASCII("ab")); - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); it = dbc.find(MDDS_ASCII("b")); - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == dbc.end()); + TEST_ASSERT(it == dbc.end()); } trie_map_type::packed_type packed = db.pack(); { auto it = packed.find(MDDS_ASCII("a")); - assert(it->first == "a"); - assert(it->second == 1); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 1); ++it; - assert(it->first == "aa"); - assert(it->second == 2); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 2); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == packed.end()); + TEST_ASSERT(it == packed.end()); it = packed.find(MDDS_ASCII("aa")); - assert(it->first == "aa"); - assert(it->second == 2); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 2); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == packed.end()); + TEST_ASSERT(it == packed.end()); it = packed.find(MDDS_ASCII("ab")); - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == packed.end()); + TEST_ASSERT(it == packed.end()); it = packed.find(MDDS_ASCII("b")); - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == packed.end()); + TEST_ASSERT(it == packed.end()); } } void trie_test_prefix_search() { - stack_printer __stack_printer__("::trie_test_prefix_search"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; + typedef trie_map trie_map_type; trie_map_type db; const trie_map_type& dbc = db; @@ -1672,35 +1158,35 @@ trie_map_type::search_results results = dbc.prefix_search(MDDS_ASCII("a")); auto it = results.begin(); auto ite = results.end(); - assert(it != ite); - assert(it->first == "a"); - assert(it->second == 1); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->first == "a"); + TEST_ASSERT(it->second == 1); ++it; - assert(it->first == "aa"); - assert(it->second == 2); + TEST_ASSERT(it->first == "aa"); + TEST_ASSERT(it->second == 2); ++it; - assert(it->first == "ab"); - assert(it->second == 3); + TEST_ASSERT(it->first == "ab"); + TEST_ASSERT(it->second == 3); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); size_t n = std::distance(results.begin(), results.end()); - assert(n == 3); + TEST_ASSERT(n == 3); cout << "Performing prefix search on 'b'..." << endl; results = dbc.prefix_search(MDDS_ASCII("b")); it = results.begin(); ite = results.end(); - assert(it != ite); - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it != ite); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); ++it; - assert(it == ite); + TEST_ASSERT(it == ite); --it; - assert(it->first == "b"); - assert(it->second == 4); + TEST_ASSERT(it->first == "b"); + TEST_ASSERT(it->second == 4); n = std::distance(results.begin(), results.end()); - assert(n == 1); + TEST_ASSERT(n == 1); // Only one element. db.clear(); @@ -1710,22 +1196,22 @@ results = dbc.prefix_search(MDDS_ASCII("du")); it = results.begin(); - assert(it->first == "dust"); - assert(it->second == 10); + TEST_ASSERT(it->first == "dust"); + TEST_ASSERT(it->second == 10); bool check_true = (++it == results.end()); - assert(check_true); + TEST_ASSERT(check_true); --it; - assert(it->first == "dust"); - assert(it->second == 10); + TEST_ASSERT(it->first == "dust"); + TEST_ASSERT(it->second == 10); n = std::distance(results.begin(), results.end()); - assert(n == 1); + TEST_ASSERT(n == 1); } void trie_test_key_as_input() { - stack_printer __stack_printer__("::trie_test_key_as_input"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; + typedef trie_map trie_map_type; trie_map_type db; const trie_map_type& dbc = db; @@ -1733,51 +1219,51 @@ db.insert("literal as key", 2); auto it = dbc.find("literal as key"); - assert(it != dbc.end()); - assert(it->first == "literal as key"); - assert(it->second == 2); + TEST_ASSERT(it != dbc.end()); + TEST_ASSERT(it->first == "literal as key"); + TEST_ASSERT(it->second == 2); auto results = dbc.prefix_search("str"); auto rit = results.begin(); - assert(rit != results.end()); - assert(rit->first == "string as key"); - assert(rit->second == 1); + TEST_ASSERT(rit != results.end()); + TEST_ASSERT(rit->first == "string as key"); + TEST_ASSERT(rit->second == 1); ++rit; - assert(rit == results.end()); + TEST_ASSERT(rit == results.end()); } void trie_test_copying() { - stack_printer __stack_printer__("::trie_test_copying"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; + typedef trie_map trie_map_type; trie_map_type db; - assert(db.empty()); + TEST_ASSERT(db.empty()); { auto db_copied(db); - assert(db_copied.empty()); + TEST_ASSERT(db_copied.empty()); } db.insert("twenty", 20); db.insert("twelve", 12); - assert(db.size() == 2); + TEST_ASSERT(db.size() == 2); { // copy constructor auto db_copied(db); const trie_map_type& dbc_copied = db_copied; - assert(db_copied.size() == 2); + TEST_ASSERT(db_copied.size() == 2); auto it = dbc_copied.find("twenty"); - assert(it != dbc_copied.end()); - assert(it->first == "twenty"); - assert(it->second == 20); + TEST_ASSERT(it != dbc_copied.end()); + TEST_ASSERT(it->first == "twenty"); + TEST_ASSERT(it->second == 20); it = dbc_copied.find("twelve"); - assert(it != dbc_copied.end()); - assert(it->first == "twelve"); - assert(it->second == 12); + TEST_ASSERT(it != dbc_copied.end()); + TEST_ASSERT(it->first == "twelve"); + TEST_ASSERT(it->second == 12); } { @@ -1785,17 +1271,17 @@ trie_map_type db_copied; db_copied = db; const trie_map_type& dbc_copied = db_copied; - assert(db_copied.size() == 2); + TEST_ASSERT(db_copied.size() == 2); auto it = dbc_copied.find("twenty"); - assert(it != dbc_copied.end()); - assert(it->first == "twenty"); - assert(it->second == 20); + TEST_ASSERT(it != dbc_copied.end()); + TEST_ASSERT(it->first == "twenty"); + TEST_ASSERT(it->second == 20); it = dbc_copied.find("twelve"); - assert(it != dbc_copied.end()); - assert(it->first == "twelve"); - assert(it->second == 12); + TEST_ASSERT(it != dbc_copied.end()); + TEST_ASSERT(it->first == "twelve"); + TEST_ASSERT(it->second == 12); } { @@ -1803,18 +1289,18 @@ auto db_copied(db); auto db_moved(std::move(db_copied)); const trie_map_type& dbc_moved = db_moved; - assert(db_moved.size() == 2); - assert(db_copied.empty()); + TEST_ASSERT(db_moved.size() == 2); + TEST_ASSERT(db_copied.empty()); auto it = dbc_moved.find("twenty"); - assert(it != dbc_moved.end()); - assert(it->first == "twenty"); - assert(it->second == 20); + TEST_ASSERT(it != dbc_moved.end()); + TEST_ASSERT(it->first == "twenty"); + TEST_ASSERT(it->second == 20); it = dbc_moved.find("twelve"); - assert(it != dbc_moved.end()); - assert(it->first == "twelve"); - assert(it->second == 12); + TEST_ASSERT(it != dbc_moved.end()); + TEST_ASSERT(it->first == "twelve"); + TEST_ASSERT(it->second == 12); } { @@ -1823,46 +1309,87 @@ trie_map_type db_moved; db_moved = std::move(db_copied); const trie_map_type& dbc_moved = db_moved; - assert(db_moved.size() == 2); - assert(db_copied.empty()); + TEST_ASSERT(db_moved.size() == 2); + TEST_ASSERT(db_copied.empty()); auto it = dbc_moved.find("twenty"); - assert(it != dbc_moved.end()); - assert(it->first == "twenty"); - assert(it->second == 20); + TEST_ASSERT(it != dbc_moved.end()); + TEST_ASSERT(it->first == "twenty"); + TEST_ASSERT(it->second == 20); it = dbc_moved.find("twelve"); - assert(it != dbc_moved.end()); - assert(it->first == "twelve"); - assert(it->second == 12); + TEST_ASSERT(it != dbc_moved.end()); + TEST_ASSERT(it->first == "twelve"); + TEST_ASSERT(it->second == 12); } } void trie_test_value_update_from_iterator() { - stack_printer __stack_printer__("::trie_test_value_update_from_iterator"); + MDDS_TEST_FUNC_SCOPE; - typedef trie_map trie_map_type; + typedef trie_map trie_map_type; trie_map_type db; db.insert("one", 1); db.insert("two", 2); db.insert("three", 3); trie_map_type::iterator it = db.begin(); - assert(it->first == "one"); - assert(it->second == 1); + TEST_ASSERT(it->first == "one"); + TEST_ASSERT(it->second == 1); it->second = 10; // update the value. it = db.begin(); - assert(it->first == "one"); - assert(it->second == 10); + TEST_ASSERT(it->first == "one"); + TEST_ASSERT(it->second == 10); it = db.find("three"); - assert(it->first == "three"); - assert(it->second == 3); + TEST_ASSERT(it->first == "three"); + TEST_ASSERT(it->second == 3); it->second = 345; // update the value again. it = db.find("three"); - assert(it->first == "three"); - assert(it->second == 345); + TEST_ASSERT(it->first == "three"); + TEST_ASSERT(it->second == 345); +} + +void trie_test_equality() +{ + MDDS_TEST_FUNC_SCOPE; + + using trie_map_type = trie_map; + + trie_map_type db1, db2; + TEST_ASSERT(db1 == db2); + + db1.insert("a", 1); + TEST_ASSERT(db1 != db2); + db2.insert("a", 1); + TEST_ASSERT(db1 == db2); + + db1.insert("ab", 2); + TEST_ASSERT(db1 != db2); + db2.insert("ab", 2); + TEST_ASSERT(db1 == db2); + + db1.insert("ac", 3); // different value + TEST_ASSERT(db1 != db2); + db2.insert("ac", 4); // different value + TEST_ASSERT(db1 != db2); + + auto it = db1.find("ac"); + it->second = 4; // make the value equal + TEST_ASSERT(db1 == db2); + + db1.clear(); + db2.clear(); + db1.insert("ab", 1); + db2.insert("a", 1); + TEST_ASSERT(db1 != db2); + + db1.clear(); + db2.clear(); + db1.insert("a", 1); + db2.insert("b", 1); + TEST_ASSERT(db1 != db2); } int main() @@ -1894,6 +1421,11 @@ trie_test_key_as_input(); trie_test_copying(); trie_test_value_update_from_iterator(); + trie_test_equality(); + + trie_test_node::run(); + trie_test_move_value::run(); + trie_test_pack_value_type::run(); } catch (const std::exception& e) { diff -Nru mdds-2.1.1/test/trie_map/test_main.hpp mdds-3.1.0/test/trie_map/test_main.hpp --- mdds-2.1.1/test/trie_map/test_main.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_main.hpp 2024-03-26 01:55:58.000000000 +0000 @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#pragma once + +#define MDDS_TRIE_MAP_DEBUG 1 +#include "test_global.hpp" // This must be the first header to be included. + +#include +#include + +struct local_debug_traits : mdds::trie::default_traits +{ + static constexpr bool dump_packed_construction_state = true; +}; + +using packed_int_map_type = mdds::packed_trie_map; +using packed_str_map_type = mdds::packed_trie_map; + +void trie_packed_test1(); +void trie_packed_test2(); +void trie_packed_test3(); +void trie_packed_test4(); +void trie_packed_test_value_life_cycle(); +void trie_packed_test_custom_string(); +void trie_packed_test_iterator_empty(); +void trie_packed_test_iterator(); +void trie_packed_test_prefix_search1(); +void trie_packed_test_key_as_input(); +void trie_packed_test_copying(); +void trie_packed_test_non_equal(); + +namespace trie_packed_test_save_and_load_state { + +void run(); + +} + +void trie_test1(); +void trie_test2(); +void trie_test_iterator_empty(); +void trie_test_iterator(); +void trie_test_iterator_with_erase(); +void trie_test_find_iterator(); +void trie_test_prefix_search(); +void trie_test_key_as_input(); +void trie_test_copying(); +void trie_test_value_update_from_iterator(); +void trie_test_equality(); + +namespace trie_test_node { + +void run(); + +} + +namespace trie_test_move_value { + +void run(); + +} + +namespace trie_test_pack_value_type { + +void run(); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/trie_map/test_move_value.cpp mdds-3.1.0/test/trie_map/test_move_value.cpp --- mdds-2.1.1/test/trie_map/test_move_value.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_move_value.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -0,0 +1,244 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#include "test_main.hpp" +#include + +#define _TEST_FUNC_SCOPE MDDS_TEST_FUNC_SCOPE_NS("trie_test_move_value") + +namespace trie_test_move_value { + +namespace { + +struct move_value +{ + std::string value; + + move_value() = default; + move_value(std::string v) : value(std::move(v)) + {} + move_value(const move_value&) = delete; + move_value(move_value&&) = default; + + move_value& operator=(const move_value&) = delete; + move_value& operator=(move_value&&) = default; + + bool operator==(const move_value& other) const + { + return value == other.value; + } +}; + +static_assert(!std::is_copy_constructible_v); +static_assert(std::is_move_constructible_v); + +using map_type = mdds::trie_map; + +void test_basic() +{ + _TEST_FUNC_SCOPE; + + map_type store; + store.insert("test", move_value("one")); + store.insert("test", move_value("two")); // overwrite + + { + auto results = store.prefix_search("te"); + auto it = results.begin(); + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->second.value == "two"); + TEST_ASSERT(++it == results.end()); + } + + { + auto it = store.find("test"); + TEST_ASSERT(it != store.end()); + TEST_ASSERT(it->second.value == "two"); + TEST_ASSERT(++it == store.end()); + } + + auto packed = store.pack(); + + { + auto results = packed.prefix_search("te"); + auto it = results.begin(); + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->second.value == "two"); + TEST_ASSERT(++it == results.end()); + } + + { + auto it = packed.find("test"); + TEST_ASSERT(it != packed.end()); + TEST_ASSERT(it->second.value == "two"); + TEST_ASSERT(++it == packed.end()); + } +} + +void test_node_traversal() +{ + _TEST_FUNC_SCOPE; + + map_type store; + store.insert("one", move_value("one")); + store.insert("two", move_value("two")); + + { + auto node = store.root_node(); + TEST_ASSERT(node.valid()); + node = node.child('o'); + TEST_ASSERT(node.valid()); + node = node.child('n'); + TEST_ASSERT(node.valid()); + node = node.child('e'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value().value == "one"); + + node = store.root_node(); + TEST_ASSERT(node.valid()); + node = node.child('t'); + TEST_ASSERT(node.valid()); + node = node.child('w'); + TEST_ASSERT(node.valid()); + node = node.child('o'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value().value == "two"); + } + + auto packed = store.pack(); + + { + auto node = packed.root_node(); + TEST_ASSERT(node.valid()); + node = node.child('o'); + TEST_ASSERT(node.valid()); + node = node.child('n'); + TEST_ASSERT(node.valid()); + node = node.child('e'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value().value == "one"); + + node = packed.root_node(); + TEST_ASSERT(node.valid()); + node = node.child('t'); + TEST_ASSERT(node.valid()); + node = node.child('w'); + TEST_ASSERT(node.valid()); + node = node.child('o'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value().value == "two"); + } +} + +void test_equality() +{ + _TEST_FUNC_SCOPE; + + map_type store1, store2; + store1.insert("one", move_value("one")); + store1.insert("two", move_value("two")); + store2.insert("one", move_value("one")); + store2.insert("two", move_value("two")); + + // TODO: implement operator== for trie_map + // TEST_ASSERT(store1 == store2); + + auto packed1 = store1.pack(); + auto packed2 = store2.pack(); + + TEST_ASSERT(packed1 == packed2); +} + +void test_non_equality() +{ + _TEST_FUNC_SCOPE; + + map_type store1, store2; + store1.insert("one", move_value("one")); + store1.insert("two", move_value("two")); + store2.insert("one", move_value("1")); + store2.insert("two", move_value("2")); + + // TODO: implement operator!= for trie_map + // TEST_ASSERT(store1 != store2); + + auto packed1 = store1.pack(); + auto packed2 = store2.pack(); + + TEST_ASSERT(packed1 != packed2); +} + +void test_move_construction() +{ + _TEST_FUNC_SCOPE; + + map_type store; + store.insert("one", move_value("one")); + store.insert("two", move_value("two")); + + map_type moved(std::move(store)); + + { + auto it = moved.find("one"); + TEST_ASSERT(it != moved.end()); + TEST_ASSERT(it->second.value == "one"); + it = moved.find("two"); + TEST_ASSERT(it != moved.end()); + TEST_ASSERT(it->second.value == "two"); + } + + auto packed = moved.pack(); + decltype(packed) packed_moved(std::move(packed)); + { + auto it = packed_moved.find("one"); + TEST_ASSERT(it != packed_moved.end()); + TEST_ASSERT(it->second.value == "one"); + it = packed_moved.find("two"); + TEST_ASSERT(it != packed_moved.end()); + TEST_ASSERT(it->second.value == "two"); + } +} + +} // anonymous namespace + +void run() +{ + test_basic(); + test_node_traversal(); + test_equality(); + test_non_equality(); + test_move_construction(); +} + +} // namespace trie_test_move_value + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/trie_map/test_node.cpp mdds-3.1.0/test/trie_map/test_node.cpp --- mdds-2.1.1/test/trie_map/test_node.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_node.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#include "test_main.hpp" + +#define _TEST_FUNC_SCOPE MDDS_TEST_FUNC_SCOPE_NS("trie_test_node") + +namespace trie_test_node { + +namespace { + +using map_type = mdds::trie_map; +using mdds::trie::dump_structure_type; + +void test_empty() +{ + _TEST_FUNC_SCOPE; + + { + map_type::const_node_type node; // default constructor + TEST_ASSERT(!node.valid()); + TEST_ASSERT(!node.has_child()); + TEST_ASSERT(!node.has_value()); + TEST_ASSERT(!node.child('c').valid()); + } + + { + map_type::packed_type::const_node_type node; // default constructor + TEST_ASSERT(!node.valid()); + TEST_ASSERT(!node.has_child()); + TEST_ASSERT(!node.has_value()); + TEST_ASSERT(!node.child('c').valid()); + } + + auto verify = [](std::string_view name, const auto& trie) { + std::cout << "trie type: " << name << std::endl; + + auto node = trie.root_node(); + TEST_ASSERT(node.valid()); + TEST_ASSERT(!node.has_child()); + TEST_ASSERT(!node.has_value()); + TEST_ASSERT(!node.child('d').valid()); + }; + + map_type original; + verify("original", original); + + auto packed = original.pack(); + verify("packed", packed); + + std::cout << packed.dump_structure(dump_structure_type::packed_buffer) << std::endl; + std::cout << packed.dump_structure(dump_structure_type::trie_traversal) << std::endl; +} + +void test_basic() +{ + _TEST_FUNC_SCOPE; + + auto verify = [](std::string_view name, const auto& trie) { + std::cout << "trie type: " << name << std::endl; + + auto node = trie.root_node(); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_child()); + TEST_ASSERT(!node.has_value()); + + node = node.child('t'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_child()); + TEST_ASSERT(!node.has_value()); + + node = node.child('e'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_child()); + TEST_ASSERT(!node.has_value()); + + node = node.child('s'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_child()); + TEST_ASSERT(!node.has_value()); + + node = node.child('t'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(!node.has_child()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value() == 42); + + // no more child nodes + TEST_ASSERT(!node.child('f').valid()); + }; + + map_type original; + original.insert("test", 42); + verify("original", original); + + auto packed = original.pack(); + verify("packed", packed); + + std::cout << packed.dump_structure(dump_structure_type::packed_buffer) << std::endl; + std::cout << packed.dump_structure(dump_structure_type::trie_traversal) << std::endl; +} + +void test_26_child_nodes() +{ + _TEST_FUNC_SCOPE; + + auto verify = [](std::string_view name, const auto& trie) { + std::cout << "trie type: " << name << std::endl; + + auto node = trie.root_node(); + TEST_ASSERT(node.valid()); + TEST_ASSERT(!node.has_value()); + TEST_ASSERT(node.has_child()); + + for (char c = 'a'; c <= 'z'; ++c) + { + auto child = node.child(c); + TEST_ASSERT(child.valid()); + TEST_ASSERT(child.has_value()); + TEST_ASSERT(child.value() == int(c - 'a')); + std::cout << "- char='" << c << "'; value=" << child.value() << std::endl; + } + }; + + map_type original; + + for (char c = 'a'; c <= 'z'; ++c) + original.insert(std::string{c}, int(c - 'a')); + + verify("original", original); + auto packed = original.pack(); + verify("packed", packed); + + std::cout << packed.dump_structure(dump_structure_type::packed_buffer) << std::endl; + std::cout << packed.dump_structure(dump_structure_type::trie_traversal) << std::endl; +} + +void test_packed_nodes() +{ + _TEST_FUNC_SCOPE; + + using _map_type = mdds::packed_trie_map; + + // Keys must be sorted. + const _map_type::entry entries[] = { + {MDDS_ASCII("DIV/0!"), true}, {MDDS_ASCII("N/A"), true}, {MDDS_ASCII("NAME?"), true}, + {MDDS_ASCII("NULL!"), true}, {MDDS_ASCII("NUM!"), true}, {MDDS_ASCII("REF!"), true}, + {MDDS_ASCII("VALUE!"), true}, + }; + + _map_type errors(entries, std::size(entries)); + + auto it = errors.find("REF!"); + TEST_ASSERT(it != errors.end()); + TEST_ASSERT(it->second == true); + + auto node = errors.root_node(); + TEST_ASSERT(node.valid()); + node = node.child('R'); + TEST_ASSERT(node.valid()); + node = node.child('E'); + TEST_ASSERT(node.valid()); + node = node.child('F'); + TEST_ASSERT(node.valid()); + node = node.child('!'); + TEST_ASSERT(node.valid()); + TEST_ASSERT(node.has_value()); + TEST_ASSERT(node.value() == true); +} + +} // anonymous namespace + +void run() +{ + test_empty(); + test_basic(); + test_26_child_nodes(); + test_packed_nodes(); +} + +} // namespace trie_test_node + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/trie_map/test_pack_value_type.cpp mdds-3.1.0/test/trie_map/test_pack_value_type.cpp --- mdds-2.1.1/test/trie_map/test_pack_value_type.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_pack_value_type.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#include "test_main.hpp" + +#include + +#define _TEST_FUNC_SCOPE MDDS_TEST_FUNC_SCOPE_NS("trie_test_pack_value_type") + +namespace trie_test_pack_value_type { + +namespace { + +struct uint8_traits : mdds::trie::default_traits +{ + using pack_value_type = std::uint8_t; +}; + +struct uint16_traits : mdds::trie::default_traits +{ + using pack_value_type = std::uint16_t; +}; + +struct uint32_traits : mdds::trie::default_traits +{ + using pack_value_type = std::uint32_t; +}; + +struct uint64_traits : mdds::trie::default_traits +{ + using pack_value_type = std::uint64_t; +}; + +using uint8_map_type = mdds::trie_map; +using uint16_map_type = mdds::trie_map; +using uint32_map_type = mdds::trie_map; +using uint64_map_type = mdds::trie_map; + +} // anonymous namespace + +void test_uint8_max_value() +{ + _TEST_FUNC_SCOPE; + + uint8_map_type db; + + auto max_value = std::numeric_limits::max(); + + for (std::uint8_t i = 0; i < max_value; ++i) + db.insert(std::to_string(i), i); + + TEST_ASSERT(db.size() == max_value); + + try + { + // packed variant receives copied values + auto packed = uint8_map_type::packed_type(db); + TEST_ASSERT(!"size_error was expected to be thrown"); + } + catch (const mdds::size_error&) + { + // expected + } + + try + { + // packed variant receives moved values + auto packed = db.pack(); + TEST_ASSERT(!"size_error was expected to be thrown"); + } + catch (const mdds::size_error&) + { + // expected + } + + std::vector> entries_pool; + + for (std::uint8_t i = 0; i < max_value; ++i) + entries_pool.emplace_back(std::to_string(i), i); + + std::sort(entries_pool.begin(), entries_pool.end(), [](const auto& l, const auto& r) { return l.first < r.first; }); + + std::vector entries; + for (const auto& [key, value] : entries_pool) + entries.emplace_back(key.data(), key.size(), value); + + TEST_ASSERT(entries.size() == max_value); + + try + { + uint8_map_type::packed_type packed(entries.data(), entries.size()); + TEST_ASSERT(!"size_error was expected to be thrown"); + } + catch (const mdds::size_error&) + { + // expected + } +} + +template +std::size_t calc_state_size() +{ + using pack_value_type = typename MapT::traits_type::pack_value_type; + std::cout << "pack value size: " << sizeof(pack_value_type) << std::endl; + + MapT db; + auto max_value = std::numeric_limits::max(); + + for (std::uint8_t i = 1; i < max_value; ++i) + db.insert(std::to_string(i), i); + + std::cout << "value count: " << db.size() << std::endl; + + auto packed = db.pack(); + std::ostringstream os; + packed.save_state(os); + + auto bin = os.str(); + std::cout << "state size: " << bin.size() << std::endl; + return bin.size(); +} + +void test_state_size() +{ + _TEST_FUNC_SCOPE; + + auto i8_size = calc_state_size(); + auto i16_size = calc_state_size(); + auto i32_size = calc_state_size(); + auto i64_size = calc_state_size(); + TEST_ASSERT(i8_size < i16_size); + TEST_ASSERT(i16_size < i32_size); + TEST_ASSERT(i32_size < i64_size); +} + +void run() +{ + test_uint8_max_value(); + test_state_size(); +} + +} // namespace trie_test_pack_value_type + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/test/trie_map/test_state.cpp mdds-3.1.0/test/trie_map/test_state.cpp --- mdds-2.1.1/test/trie_map/test_state.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mdds-3.1.0/test/trie_map/test_state.cpp 2025-07-03 16:15:17.000000000 +0000 @@ -0,0 +1,576 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2024 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. + * + ************************************************************************/ + +#include "test_main.hpp" + +#include + +#define _TEST_FUNC_SCOPE MDDS_TEST_FUNC_SCOPE_NS("trie_packed_test_save_and_load_state") + +namespace trie_packed_test_save_and_load_state { + +namespace { + +struct _custom_variable_value +{ + enum class v_type + { + unknown, + fp32, + int64 + }; + + v_type type; + + union + { + float fp32; + int64_t int64; + } value; + + _custom_variable_value() : type(v_type::unknown) + {} + + _custom_variable_value(float v) : type(v_type::fp32) + { + value.fp32 = v; + } + + _custom_variable_value(int v) : type(v_type::int64) + { + value.int64 = v; + } + + _custom_variable_value(const _custom_variable_value& other) : type(other.type) + { + switch (type) + { + case v_type::fp32: + value.fp32 = other.value.fp32; + break; + case v_type::int64: + value.int64 = other.value.int64; + break; + default:; + } + } + + bool operator==(const _custom_variable_value& other) const + { + if (type != other.type) + return false; + + switch (type) + { + case v_type::fp32: + return value.fp32 == other.value.fp32; + case v_type::int64: + return value.int64 == other.value.int64; + default:; + } + + return true; + } + + bool operator!=(const _custom_variable_value& other) const + { + return !operator==(other); + } +}; + +struct _custom_variable_serializer +{ + union bin_value + { + char buffer[8]; + float fp32; + int64_t int64; + }; + + static constexpr bool variable_size = true; + + static void write(std::ostream& os, const _custom_variable_value& v) + { + bin_value bv; + + switch (v.type) + { + case _custom_variable_value::v_type::unknown: + { + char c = 0; + os.write(&c, 1); + break; + } + case _custom_variable_value::v_type::fp32: + { + char c = 1; + os.write(&c, 1); + bv.fp32 = v.value.fp32; + os.write(bv.buffer, 4); + break; + } + case _custom_variable_value::v_type::int64: + { + char c = 2; + os.write(&c, 1); + bv.int64 = v.value.int64; + os.write(bv.buffer, 8); + break; + } + } + } + + static void read(std::istream& is, size_t n, _custom_variable_value& v) + { + TEST_ASSERT(n > 0); + char c; + is.read(&c, 1); + + switch (c) + { + case 0: + v.type = _custom_variable_value::v_type::unknown; + break; + case 1: + v.type = _custom_variable_value::v_type::fp32; + break; + case 2: + v.type = _custom_variable_value::v_type::int64; + break; + default: + TEST_ASSERT(!"invalid value type"); + } + + n -= 1; + bin_value bv; + + switch (v.type) + { + case _custom_variable_value::v_type::fp32: + TEST_ASSERT(n == 4); + is.read(bv.buffer, 4); + v.value.fp32 = bv.fp32; + break; + case _custom_variable_value::v_type::int64: + TEST_ASSERT(n == 8); + is.read(bv.buffer, 8); + v.value.int64 = bv.int64; + break; + case _custom_variable_value::v_type::unknown: + break; + default: + TEST_ASSERT(!"invalid value type"); + } + } +}; + +/** + * mock value struct containing one value string that only stores "zero", + * "one", "two" or "three". We use a custom serializer to store the value + * using only 1 byte each. + */ +struct _custom_fixed_value +{ + std::string value_string; // only stores "zero", "one", "two" or "three". + + _custom_fixed_value() + {} + + _custom_fixed_value(const char* p) : value_string(p, std::strlen(p)) + {} + + bool operator==(const _custom_fixed_value& other) const + { + return value_string == other.value_string; + } + + bool operator!=(const _custom_fixed_value& other) const + { + return !operator==(other); + } +}; + +struct _custom_fixed_serializer +{ + static constexpr bool variable_size = false; + static constexpr size_t value_size = 1; + + static void write(std::ostream& os, const _custom_fixed_value& v) + { + char bv = -1; + + if (v.value_string == "zero") + bv = 0; + else if (v.value_string == "one") + bv = 1; + else if (v.value_string == "two") + bv = 2; + else if (v.value_string == "three") + bv = 3; + + os.write(&bv, 1); + } + + static void read(std::istream& is, size_t n, _custom_fixed_value& v) + { + TEST_ASSERT(n == 1); + char bv = -1; + is.read(&bv, 1); + + switch (bv) + { + case 0: + v.value_string = "zero"; + break; + case 1: + v.value_string = "one"; + break; + case 2: + v.value_string = "two"; + break; + case 3: + v.value_string = "three"; + break; + default: + v.value_string = "???"; + } + } +}; + +void test_1() +{ + _TEST_FUNC_SCOPE; + + packed_int_map_type empty_db; + + std::string saved_state; + + { + std::ostringstream state; + empty_db.save_state(state); + saved_state = state.str(); + } + + packed_int_map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(restored == empty_db); +} + +void test_2() +{ + _TEST_FUNC_SCOPE; + + packed_int_map_type::entry entries[] = { + {MDDS_ASCII("bruce"), 5}, {MDDS_ASCII("charlie"), 6}, {MDDS_ASCII("charlotte"), 7}, + {MDDS_ASCII("david"), 8}, {MDDS_ASCII("dove"), 9}, + }; + + packed_int_map_type db(entries, std::size(entries)); + + std::string saved_state; + + { + std::ostringstream state; + db.save_state(state); + saved_state = state.str(); + } + + packed_int_map_type restored; + TEST_ASSERT(restored != db); + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(restored == db); +} + +void test_3() +{ + _TEST_FUNC_SCOPE; + + std::vector entries = { + {MDDS_ASCII("Abby"), "ABBY"}, + {MDDS_ASCII("Ashley"), "ASHLEY"}, + {MDDS_ASCII("Candelaria"), "CANDELARIA"}, + {MDDS_ASCII("Carita"), "CARITA"}, + {MDDS_ASCII("Christal"), "CHRISTAL"}, + {MDDS_ASCII("Cory"), "CORY"}, + {MDDS_ASCII("Estrella"), "ESTRELLA"}, + {MDDS_ASCII("Etha"), "ETHA"}, + {MDDS_ASCII("Harley"), "HARLEY"}, + {MDDS_ASCII("Irish"), "IRISH"}, + {MDDS_ASCII("Kiara"), "KIARA"}, + {MDDS_ASCII("Korey"), "KOREY"}, + {MDDS_ASCII("Laurene"), "LAURENE"}, + {MDDS_ASCII("Michiko"), "MICHIKO"}, + {MDDS_ASCII("Miriam"), "MIRIAM"}, + {MDDS_ASCII("Mitzi"), "MITZI"}, + {MDDS_ASCII("Seth"), "SETH"}, + {MDDS_ASCII("Sindy"), "SINDY"}, + {MDDS_ASCII("Tawanna"), "TAWANNA"}, + {MDDS_ASCII("Tyra"), "TYRA"}, + }; + + packed_str_map_type db(entries.data(), entries.size()); + + // Run some search. + auto results = db.prefix_search("Mi"); + auto it = results.begin(); + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->first == "Michiko"); + TEST_ASSERT(it->second == "MICHIKO"); + ++it; + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->first == "Miriam"); + TEST_ASSERT(it->second == "MIRIAM"); + ++it; + TEST_ASSERT(it != results.end()); + TEST_ASSERT(it->first == "Mitzi"); + TEST_ASSERT(it->second == "MITZI"); + ++it; + TEST_ASSERT(it == results.end()); + + std::string saved_state; + + { + std::ostringstream state; + db.save_state(state); + saved_state = state.str(); + } + + packed_str_map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(db == restored); +} + +void test_4() +{ + _TEST_FUNC_SCOPE; + + using map_type = mdds::packed_trie_map>; + + std::vector entries = { + {MDDS_ASCII("Abby"), {65, 98, 98, 121}}, + {MDDS_ASCII("Ashley"), {65, 115, 104, 108, 101, 121}}, + {MDDS_ASCII("Christal"), {67, 104, 114, 105, 115, 116, 97, 108}}, + {MDDS_ASCII("Cory"), {67, 111, 114, 121}}, + {MDDS_ASCII("Harley"), {72, 97, 114, 108, 101, 121}}, + {MDDS_ASCII("Kiara"), {75, 105, 97, 114, 97}}, + {MDDS_ASCII("Mitzi"), {77, 105, 116, 122, 105}}, + }; + + map_type db(entries.data(), entries.size()); + TEST_ASSERT(db.size() == entries.size()); + + std::string saved_state; + { + std::ostringstream state; + db.save_state(state); + saved_state = state.str(); + } + + map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(db == restored); +} + +void test_5() +{ + _TEST_FUNC_SCOPE; + + using map_type = mdds::packed_trie_map; + + std::vector entries = { + {MDDS_ASCII("Abby"), 1.0f}, {MDDS_ASCII("Ashley"), 1.1f}, {MDDS_ASCII("Christal"), 1.2f}, + {MDDS_ASCII("Cory"), 1.3f}, {MDDS_ASCII("Harley"), 1.4f}, {MDDS_ASCII("Kiara"), 1.5f}, + {MDDS_ASCII("Mitzi"), 1.6f}, + }; + + map_type db(entries.data(), entries.size()); + TEST_ASSERT(db.size() == entries.size()); + + std::string saved_state; + { + std::ostringstream state; + db.save_state(state); + saved_state = state.str(); + } + + map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(db == restored); +} + +template +void test_6() +{ + _TEST_FUNC_SCOPE; + + using map_type = mdds::packed_trie_map; + + std::vector entries = { + {MDDS_ASCII("Abby"), {65.0, 98.1, 98.2, 121.3}}, + {MDDS_ASCII("Ashley"), {65.0, 11.5, 1.04, 1.08, .101, .12586}}, + {MDDS_ASCII("Christal"), {67.0, -10.4, -114.236}}, + {MDDS_ASCII("Cory"), {67.0, 122.111}}, + {MDDS_ASCII("Harley"), {72.0, 97.12, -1.114}}, + {MDDS_ASCII("Kiara"), {75.0, 1.05, 9.7, 1.14, -97.5}}, + {MDDS_ASCII("Mitzi"), {77.0, 10.5, 11.6, 1.22, 10.5}}, + }; + + map_type db(entries.data(), entries.size()); + TEST_ASSERT(db.size() == entries.size()); + + std::string saved_state; + { + std::ostringstream state; + db.save_state(state); + saved_state = state.str(); + } + + map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state(state); + } + + TEST_ASSERT(db == restored); +} + +void test_7() +{ + _TEST_FUNC_SCOPE; + + using map_type = mdds::packed_trie_map; + + std::vector entries = { + {MDDS_ASCII("Alan"), 1.2f}, {MDDS_ASCII("Cory"), -125}, {MDDS_ASCII("Eleni"), 966}, + {MDDS_ASCII("Evia"), -0.987f}, {MDDS_ASCII("Nathaniel"), 0}, {MDDS_ASCII("Rebbecca"), 1.234f}, + {MDDS_ASCII("Rodrick"), 34253536}, {MDDS_ASCII("Stuart"), 12}, {MDDS_ASCII("Verline"), 56}, + }; + + map_type db(entries.data(), entries.size()); + TEST_ASSERT(db.size() == entries.size()); + + std::string saved_state; + { + std::ostringstream state; + db.save_state<_custom_variable_serializer>(state); + saved_state = state.str(); + } + + map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state<_custom_variable_serializer>(state); + } + + TEST_ASSERT(db == restored); +} + +void test_8() +{ + _TEST_FUNC_SCOPE; + + using map_type = mdds::packed_trie_map; + + std::vector entries = { + {MDDS_ASCII("Bernardine"), "zero"}, {MDDS_ASCII("Donny"), "two"}, {MDDS_ASCII("Julia"), "one"}, + {MDDS_ASCII("Lindsy"), "three"}, {MDDS_ASCII("Martine"), "three"}, {MDDS_ASCII("Shana"), "two"}, + {MDDS_ASCII("Sonia"), "zero"}, {MDDS_ASCII("Tracie"), "one"}, {MDDS_ASCII("Vanita"), "two"}, + {MDDS_ASCII("Yung"), "zero"}, + }; + + map_type db(entries.data(), entries.size()); + TEST_ASSERT(db.size() == entries.size()); + + std::string saved_state; + { + std::ostringstream state; + db.save_state<_custom_fixed_serializer>(state); + saved_state = state.str(); + } + + map_type restored; + + { + std::istringstream state(saved_state); + restored.load_state<_custom_fixed_serializer>(state); + } + + TEST_ASSERT(db == restored); + + // Run some query to make sure it is still functional. + auto it = restored.find("Tracie"); + TEST_ASSERT(it->first == "Tracie"); + TEST_ASSERT(it->second.value_string == "one"); +} + +} // anonymous namespace + +void run() +{ + test_1(); + test_2(); + test_3(); + test_4(); + test_5(); + test_6>(); + test_6>(); + test_6>(); + test_7(); + test_8(); +} + +} // namespace trie_packed_test_save_and_load_state + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff -Nru mdds-2.1.1/tools/Makefile.in mdds-3.1.0/tools/Makefile.in --- mdds-2.1.1/tools/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/tools/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -240,7 +240,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ diff -Nru mdds-2.1.1/tools/runtime-env/Makefile.in mdds-3.1.0/tools/runtime-env/Makefile.in --- mdds-2.1.1/tools/runtime-env/Makefile.in 2023-04-29 13:07:55.000000000 +0000 +++ mdds-3.1.0/tools/runtime-env/Makefile.in 2025-07-10 01:41:53.000000000 +0000 @@ -221,7 +221,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -QUICKCHECKDIR = @QUICKCHECKDIR@ RUNTEST_BIN = @RUNTEST_BIN@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@