diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..e908f4a4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.6) + +project(cppbtree CXX) + +option(build_tests "Build B-tree tests" OFF) +add_definitions(-std=c++0x) +set(CMAKE_CXX_FLAGS "-g") + +# CMake doesn't have a way to pure template library, +add_library(cppbtree btree.h btree_map.h btree_set.h safe_btree.h safe_btree_map.h safe_btree_set.h) +set_target_properties(cppbtree PROPERTIES LINKER_LANGUAGE CXX) + +if(build_tests) + enable_testing() + include_directories($ENV{GTEST_ROOT}/include) + link_directories($ENV{GTEST_ROOT}) + add_executable(btree_test btree_test.cc btree_test_flags.cc) + add_executable(safe_btree_test safe_btree_test.cc btree_test_flags.cc) + add_executable(btree_bench btree_bench.cc btree_test_flags.cc) + target_link_libraries(btree_test gtest_main gflags) + target_link_libraries(safe_btree_test gtest_main gflags) + target_link_libraries(btree_bench gflags) +endif() diff --git a/README b/README new file mode 100644 index 00000000..152972cf --- /dev/null +++ b/README @@ -0,0 +1,15 @@ +This library is a C++ template library and, as such, there is no +library to build and install. + +---- + +To build and run the provided tests, however, you will need to install +CMake and the Google C++ Test framework. + +Download CMake from http://www.cmake.org + +Download the GoogleTest framework from http://code.google.com/p/googletest + +export GTEST_ROOT=/path/for/gtest-x.y + +cmake . -Dbuild_tests=ON diff --git a/btree.h b/btree.h index d8e485ef..a8d3152d 100644 --- a/btree.h +++ b/btree.h @@ -35,11 +35,6 @@ // // btree_bench --benchmarks=. 2>&1 | ./benchmarks.awk // -// NOTE(pmattis): My warpstation (pmattis-warp.nyc) often produces slower -// results when running the benchmarks on CPUs 0 and 1 vs CPUs 2 and 3. To get -// consistent benchmark results, I run "taskset 0xc " to run the -// benchmark on CPUs 2 and 3. -// // Run on pmattis-warp.nyc (4 X 2200 MHz CPUs); 2010/03/04-15:23:06 // Benchmark STL(ns) B-Tree(ns) @ // -------------------------------------------------------- @@ -91,61 +86,29 @@ // BM_map_string_mixedaddrem 6400 5200 +18.75% <256> [72.0, 57.8] // BM_map_string_fifo 398 596 -49.75% <256> [72.0, 44.0] // BM_map_string_fwditer 243 113 +53.50% <256> [72.0, 55.8] -// BM_set_cord_insert 3661 2680 +26.80% <256> [40.0, 10.5] -// BM_set_cord_lookup 2920 2293 +21.47% <256> [40.0, 10.5] -// BM_set_cord_fulllookup 2960 2267 +23.41% <256> [40.0, 8.8] -// BM_set_cord_delete 4679 2535 +45.82% <256> [40.0, 10.5] -// BM_set_cord_queueaddrem 8230 5600 +31.96% <256> [40.0, 11.3] -// BM_set_cord_mixedaddrem 8497 6080 +28.45% <256> [40.0, 10.7] -// BM_set_cord_fifo 358 370 -3.35% <256> [40.0, 8.8] -// BM_set_cord_fwditer 352 193 +45.17% <256> [40.0, 10.5] -// BM_map_cord_insert 3680 2927 +20.46% <256> [48.0, 20.7] -// BM_map_cord_lookup 3018 2466 +18.29% <256> [48.0, 20.7] -// BM_map_cord_fulllookup 2943 2466 +16.21% <256> [48.0, 17.2] -// BM_map_cord_delete 4675 2775 +40.64% <256> [48.0, 20.7] -// BM_map_cord_queueaddrem 8383 6360 +24.13% <256> [48.0, 22.2] -// BM_map_cord_mixedaddrem 8952 6760 +24.49% <256> [48.0, 21.2] -// BM_map_cord_fifo 444 463 -4.28% <256> [48.0, 17.2] -// BM_map_cord_fwditer 391 225 +42.46% <256> [48.0, 20.7] #ifndef UTIL_BTREE_BTREE_H__ #define UTIL_BTREE_BTREE_H__ +#include #include #include #include #include #include #include -#include // IWYU pragma: export // Clients can rely on this. +#include #include +#include #include -#include // IWYU pragma: export // Clients can rely on this. +#include #include #include -#include "base/gdb-scripting.h" -#include "base/integral_types.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/template_util.h" -#include "base/type_traits.h" -#include "strings/cord.h" -#include "strings/stringpiece.h" +#ifndef NDEBUG +#define NDEBUG 1 +#endif -// iwyu.py found std::swap in , but we include . -// IWYU pragma: no_include -// -// iwyu.py doesn't think we need , so wants . -// IWYU pragma: no_include -// -// iwyu.py sure wants to bring in a lot of private STL headers. -// IWYU pragma: no_include -// IWYU pragma: no_include -// IWYU pragma: no_include -// IWYU pragma: no_include - -namespace util { namespace btree { // Inside a btree method, if we just call swap(), it will choose the @@ -161,6 +124,32 @@ inline void btree_swap_helper(T &a, T &b) { swap(a, b); } +// A template helper used to select A or B based on a condition. +template +struct if_{ + typedef A type; +}; + +template +struct if_ { + typedef B type; +}; + +// Types small_ and big_ are promise that sizeof(small_) < sizeof(big_) +typedef char small_; + +struct big_ { + char dummy[2]; +}; + +// A compile-time assertion. +template +struct CompileAssert { +}; + +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] + // A helper type used to indicate that a key-compare-to functor has been // provided. A user can specify a key-compare-to functor by doing: // @@ -180,7 +169,7 @@ struct btree_key_compare_to_tag { // btree_key_compare_to_tag. template struct btree_is_key_compare_to - : public base::is_convertible { + : public std::is_convertible { }; // A helper class to convert a boolean comparison into a three-way "compare-to" @@ -201,77 +190,29 @@ struct btree_key_compare_to_adapter : Compare { }; template <> -struct btree_key_compare_to_adapter > +struct btree_key_compare_to_adapter > : public btree_key_compare_to_tag { btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const less&) {} + btree_key_compare_to_adapter(const std::less&) {} btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const string &a, const string &b) const { + const btree_key_compare_to_adapter >&) {} + int operator()(const std::string &a, const std::string &b) const { return a.compare(b); } }; template <> -struct btree_key_compare_to_adapter > +struct btree_key_compare_to_adapter > : public btree_key_compare_to_tag { btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const greater&) {} + btree_key_compare_to_adapter(const std::greater&) {} btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const string &a, const string &b) const { + const btree_key_compare_to_adapter >&) {} + int operator()(const std::string &a, const std::string &b) const { return b.compare(a); } }; -template <> -struct btree_key_compare_to_adapter > - : public btree_key_compare_to_tag { - btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const less&) {} - btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const StringPiece &a, const StringPiece &b) const { - return a.compare(b); - } -}; - -template <> -struct btree_key_compare_to_adapter > - : public btree_key_compare_to_tag { - btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const greater&) {} - btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const StringPiece &a, const StringPiece &b) const { - return b.compare(a); - } -}; - -template <> -struct btree_key_compare_to_adapter > - : public btree_key_compare_to_tag { - btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const less&) {} - btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const Cord &a, const Cord &b) const { - return a.CompareTo(b); - } -}; - -template <> -struct btree_key_compare_to_adapter > - : public btree_key_compare_to_tag { - btree_key_compare_to_adapter() {} - btree_key_compare_to_adapter(const greater&) {} - btree_key_compare_to_adapter( - const btree_key_compare_to_adapter >&) {} - int operator()(const Cord &a, const Cord &b) const { - return b.CompareTo(a); - } -}; - // A helper class that allows a compare-to functor to behave like a plain // compare functor. This specialization is used when we do not have a // compare-to functor. @@ -322,7 +263,7 @@ struct btree_common_params { // If Compare is derived from btree_key_compare_to_tag then use it as the // key_compare type. Otherwise, use btree_key_compare_to_adapter<> which will // fall-back to Compare if we don't have an appropriate specialization. - typedef typename base::if_< + typedef typename if_< btree_is_key_compare_to::value, Compare, btree_key_compare_to_adapter >::type key_compare; // A type which indicates if we have a key-compare-to functor or a plain old @@ -344,10 +285,10 @@ struct btree_common_params { // This is an integral type large enough to hold as many // ValueSize-values as will fit a node of TargetNodeSize bytes. - typedef typename base::if_< + typedef typename if_< (kNodeValueSpace / ValueSize) >= 256, - uint16, - uint8>::type node_count_type; + uint16_t, + uint8_t>::type node_count_type; }; // A parameters structure for holding the type parameters for a btree_map. @@ -358,8 +299,8 @@ struct btree_map_params sizeof(Key) + sizeof(Data)> { typedef Data data_type; typedef Data mapped_type; - typedef pair value_type; - typedef pair mutable_value_type; + typedef std::pair value_type; + typedef std::pair mutable_value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; @@ -382,8 +323,8 @@ template struct btree_set_params : public btree_common_params { - typedef base::false_type data_type; - typedef base::false_type mapped_type; + typedef std::false_type data_type; + typedef std::false_type mapped_type; typedef Key value_type; typedef value_type mutable_value_type; typedef value_type* pointer; @@ -499,22 +440,22 @@ class btree_node { key_type, self_type, key_compare> binary_search_compare_to_type; // If we have a valid key-compare-to type, use linear_search_compare_to, // otherwise use linear_search_plain_compare. - typedef typename base::if_< + typedef typename if_< Params::is_key_compare_to::value, linear_search_compare_to_type, linear_search_plain_compare_type>::type linear_search_type; // If we have a valid key-compare-to type, use binary_search_compare_to, // otherwise use binary_search_plain_compare. - typedef typename base::if_< + typedef typename if_< Params::is_key_compare_to::value, binary_search_compare_to_type, binary_search_plain_compare_type>::type binary_search_type; // If the key is an integral or floating point type, use linear search which // is faster than binary search for such types. Might be wise to also // configure linear search based on node-size. - typedef typename base::if_< - base::is_integral::value || - base::is_floating_point::value, + typedef typename if_< + std::is_integral::value || + std::is_floating_point::value, linear_search_type, binary_search_type>::type search_type; struct base_fields { @@ -586,7 +527,7 @@ class btree_node { // be a leaf. bool is_root() const { return parent()->leaf(); } void make_root() { - DCHECK(parent()->is_root()); + assert(parent()->is_root()); fields_.parent = fields_.parent->parent(); } @@ -739,7 +680,7 @@ class btree_node { f->max_count = max_count; f->count = 0; f->parent = parent; - if (DEBUG_MODE) { + if (!NDEBUG) { memset(&f->values, 0, max_count * sizeof(value_type)); } return n; @@ -747,7 +688,7 @@ class btree_node { static btree_node* init_internal(internal_fields *f, btree_node *parent) { btree_node *n = init_leaf(f, parent, kNodeValues); f->leaf = 0; - if (DEBUG_MODE) { + if (!NDEBUG) { memset(f->children, 0, sizeof(f->children)); } return n; @@ -779,7 +720,8 @@ class btree_node { root_fields fields_; private: - DISALLOW_EVIL_CONSTRUCTORS(btree_node); + btree_node(const btree_node&); + void operator=(const btree_node&); }; template @@ -790,7 +732,7 @@ struct btree_iterator { typedef typename Node::params_type params_type; typedef Node node_type; - typedef typename base::remove_const::type normal_node; + typedef typename std::remove_const::type normal_node; typedef const Node const_node; typedef typename params_type::value_type value_type; typedef typename params_type::pointer normal_pointer; @@ -800,7 +742,7 @@ struct btree_iterator { typedef Pointer pointer; typedef Reference reference; - typedef bidirectional_iterator_tag iterator_category; + typedef std::bidirectional_iterator_tag iterator_category; typedef btree_iterator< normal_node, normal_reference, normal_pointer> iterator; @@ -885,7 +827,7 @@ struct btree_iterator { // Dispatch helper class for using btree::internal_locate with plain compare. struct btree_internal_locate_plain_compare { template - static pair dispatch(const K &k, const T &t, Iter iter) { + static std::pair dispatch(const K &k, const T &t, Iter iter) { return t.internal_locate_plain_compare(k, iter); } }; @@ -893,7 +835,7 @@ struct btree_internal_locate_plain_compare { // Dispatch helper class for using btree::internal_locate with compare-to. struct btree_internal_locate_compare_to { template - static pair dispatch(const K &k, const T &t, Iter iter) { + static std::pair dispatch(const K &k, const T &t, Iter iter) { return t.internal_locate_compare_to(k, iter); } }; @@ -910,7 +852,7 @@ class btree : public Params::key_compare { friend class btree_internal_locate_plain_compare; friend class btree_internal_locate_compare_to; - typedef typename base::if_< + typedef typename if_< is_key_compare_to::value, btree_internal_locate_compare_to, btree_internal_locate_plain_compare>::type internal_locate_type; @@ -1037,11 +979,11 @@ class btree : public Params::key_compare { // Finds the range of values which compare equal to key. The first member of // the returned pair is equal to lower_bound(key). The second member pair of // the pair is equal to upper_bound(key). - pair equal_range(const key_type &key) { - return make_pair(lower_bound(key), upper_bound(key)); + std::pair equal_range(const key_type &key) { + return std::make_pair(lower_bound(key), upper_bound(key)); } - pair equal_range(const key_type &key) const { - return make_pair(lower_bound(key), upper_bound(key)); + std::pair equal_range(const key_type &key) const { + return std::make_pair(lower_bound(key), upper_bound(key)); } // Inserts a value into the btree only if it does not already exist. The @@ -1050,11 +992,11 @@ class btree : public Params::key_compare { // is being inserted. Value is not dereferenced if the key already exists in // the btree. See btree_map::operator[]. template - pair insert_unique(const key_type &key, ValuePointer value); + std::pair insert_unique(const key_type &key, ValuePointer value); // Inserts a value into the btree only if it does not already exist. The // boolean return value indicates whether insertion succeeded or failed. - pair insert_unique(const value_type &v) { + std::pair insert_unique(const value_type &v) { return insert_unique(params_type::key(v), &v); } @@ -1170,7 +1112,7 @@ class btree : public Params::key_compare { // Dump the btree to the specified ostream. Requires that operator<< is // defined for Key and Value. - void dump(ostream &os) const { + void dump(std::ostream &os) const { if (root() != NULL) { internal_dump(os, root(), 0); } @@ -1185,7 +1127,7 @@ class btree : public Params::key_compare { if (root()->leaf()) return root()->count(); return root()->size(); } - size_type max_size() const { return numeric_limits::max(); } + size_type max_size() const { return std::numeric_limits::max(); } bool empty() const { return root() == NULL; } // The height of the btree. An empty tree will have height 0. @@ -1310,7 +1252,7 @@ class btree : public Params::key_compare { } void delete_internal_node(node_type *node) { node->destroy(); - DCHECK(node != root()); + assert(node != root()); mutable_internal_allocator()->deallocate( reinterpret_cast(node), sizeof(internal_fields)); } @@ -1368,15 +1310,15 @@ class btree : public Params::key_compare { // key was found in the tree) or -kExactMatch (if it wasn't) in the second // field of the pair. The compare_to specialization allows the caller to // avoid a subsequent comparison to determine if an exact match was made, - // speeding up string, cord and StringPiece keys. + // speeding up string keys. template - pair internal_locate( + std::pair internal_locate( const key_type &key, IterType iter) const; template - pair internal_locate_plain_compare( + std::pair internal_locate_plain_compare( const key_type &key, IterType iter) const; template - pair internal_locate_compare_to( + std::pair internal_locate_compare_to( const key_type &key, IterType iter) const; // Internal routine which implements lower_bound(). @@ -1403,7 +1345,7 @@ class btree : public Params::key_compare { void internal_clear(node_type *node); // Dumps a node and all of its children to the specified ostream. - void internal_dump(ostream &os, const node_type *node, int level) const; + void internal_dump(std::ostream &os, const node_type *node, int level) const; // Verifies the tree structure of node. int internal_verify(const node_type *node, @@ -1427,14 +1369,14 @@ class btree : public Params::key_compare { empty_base_handle root_; private: - // A never instantiated helper function that returns base::big_ if we have a - // key-compare-to functor or if R is bool and base::small_ otherwise. + // A never instantiated helper function that returns big_ if we have a + // key-compare-to functor or if R is bool and small_ otherwise. template - static typename base::if_< - base::if_, - base::type_equals_ >::type::value, - base::big_, base::small_>::type key_compare_checker(R); + static typename if_< + if_, + std::is_same >::type::value, + big_, small_>::type key_compare_checker(R); // A never instantiated helper function that returns the key comparison // functor. @@ -1445,10 +1387,10 @@ class btree : public Params::key_compare { // is never actually invoked. The compiler will select which // key_compare_checker() to instantiate and then figure out the size of the // return type of key_compare_checker() at compile time which we then check - // against the sizeof of base::big_. + // against the sizeof of big_. COMPILE_ASSERT( sizeof(key_compare_checker(key_compare_helper()(key_type(), key_type()))) == - sizeof(base::big_), + sizeof(big_), key_comparison_function_must_return_bool); // Note: We insist on kTargetValues, which is computed from @@ -1466,7 +1408,7 @@ class btree : public Params::key_compare { // btree_node methods template inline void btree_node

::insert_value(int i, const value_type &x) { - DCHECK_LE(i, count()); + assert(i <= count()); value_init(count(), x); for (int j = count(); j > i; --j) { value_swap(j, this, j - 1); @@ -1486,7 +1428,7 @@ inline void btree_node

::insert_value(int i, const value_type &x) { template inline void btree_node

::remove_value(int i) { if (!leaf()) { - DCHECK_EQ(child(i + 1)->count(), 0); + assert(child(i + 1)->count() == 0); for (int j = i + 1; j < count(); ++j) { *mutable_child(j) = child(j + 1); child(j)->set_position(j); @@ -1503,11 +1445,11 @@ inline void btree_node

::remove_value(int i) { template void btree_node

::rebalance_right_to_left(btree_node *src, int to_move) { - DCHECK_EQ(parent(), src->parent()); - DCHECK_EQ(position() + 1, src->position()); - DCHECK_GE(src->count(), count()); - DCHECK_GE(to_move, 1); - DCHECK_LE(to_move, src->count()); + assert(parent() == src->parent()); + assert(position() + 1 == src->position()); + assert(src->count() >= count()); + assert(to_move >= 1); + assert(to_move <= src->count()); // Make room in the left node for the new values. for (int i = 0; i < to_move; ++i) { @@ -1537,7 +1479,7 @@ void btree_node

::rebalance_right_to_left(btree_node *src, int to_move) { set_child(1 + count() + i, src->child(i)); } for (int i = 0; i <= src->count() - to_move; ++i) { - DCHECK_LE(i + to_move, src->max_count()); + assert(i + to_move <= src->max_count()); src->set_child(i, src->child(i + to_move)); *src->mutable_child(i + to_move) = NULL; } @@ -1550,11 +1492,11 @@ void btree_node

::rebalance_right_to_left(btree_node *src, int to_move) { template void btree_node

::rebalance_left_to_right(btree_node *dest, int to_move) { - DCHECK_EQ(parent(), dest->parent()); - DCHECK_EQ(position() + 1, dest->position()); - DCHECK_GE(count(), dest->count()); - DCHECK_GE(to_move, 1); - DCHECK_LE(to_move, count()); + assert(parent() == dest->parent()); + assert(position() + 1 == dest->position()); + assert(count() >= dest->count()); + assert(to_move >= 1); + assert(to_move <= count()); // Make room in the right node for the new values. for (int i = 0; i < to_move; ++i) { @@ -1595,7 +1537,7 @@ void btree_node

::rebalance_left_to_right(btree_node *dest, int to_move) { template void btree_node

::split(btree_node *dest, int insert_position) { - DCHECK_EQ(dest->count(), 0); + assert(dest->count() == 0); // We bias the split based on the position being inserted. If we're // inserting at the beginning of the left node then bias the split to put @@ -1609,7 +1551,7 @@ void btree_node

::split(btree_node *dest, int insert_position) { dest->set_count(count() / 2); } set_count(count() - dest->count()); - DCHECK_GE(count(), 1); + assert(count() >= 1); // Move values from the left sibling to the right sibling. for (int i = 0; i < dest->count(); ++i) { @@ -1627,7 +1569,7 @@ void btree_node

::split(btree_node *dest, int insert_position) { if (!leaf()) { for (int i = 0; i <= dest->count(); ++i) { - DCHECK(child(count() + i + 1) != NULL); + assert(child(count() + i + 1) != NULL); dest->set_child(i, child(count() + i + 1)); *mutable_child(count() + i + 1) = NULL; } @@ -1636,8 +1578,8 @@ void btree_node

::split(btree_node *dest, int insert_position) { template void btree_node

::merge(btree_node *src) { - DCHECK_EQ(parent(), src->parent()); - DCHECK_EQ(position() + 1, src->position()); + assert(parent() == src->parent()); + assert(position() + 1 == src->position()); // Move the delimiting value to the left node. value_init(count()); @@ -1668,7 +1610,7 @@ void btree_node

::merge(btree_node *src) { template void btree_node

::swap(btree_node *x) { - DCHECK_EQ(leaf(), x->leaf()); + assert(leaf() == x->leaf()); // Swap the values. for (int i = count(); i < x->count(); ++i) { @@ -1677,7 +1619,7 @@ void btree_node

::swap(btree_node *x) { for (int i = x->count(); i < count(); ++i) { x->value_init(i); } - int n = max(count(), x->count()); + int n = std::max(count(), x->count()); for (int i = 0; i < n; ++i) { value_swap(i, x, i); } @@ -1710,10 +1652,10 @@ void btree_node

::swap(btree_node *x) { template void btree_iterator::increment_slow() { if (node->leaf()) { - DCHECK_GE(position, node->count()); + assert(position >= node->count()); self_type save(*this); while (position == node->count() && !node->is_root()) { - DCHECK_EQ(node->parent()->child(node->position()), node); + assert(node->parent()->child(node->position()) == node); position = node->position(); node = node->parent(); } @@ -1721,7 +1663,7 @@ void btree_iterator::increment_slow() { *this = save; } } else { - DCHECK_LT(position, node->count()); + assert(position < node->count()); node = node->child(position + 1); while (!node->leaf()) { node = node->child(0); @@ -1735,7 +1677,7 @@ void btree_iterator::increment_by(int count) { while (count > 0) { if (node->leaf()) { int rest = node->count() - position; - position += min(rest, count); + position += std::min(rest, count); count = count - rest; if (position < node->count()) { return; @@ -1750,10 +1692,10 @@ void btree_iterator::increment_by(int count) { template void btree_iterator::decrement_slow() { if (node->leaf()) { - DCHECK_LE(position, -1); + assert(position <= -1); self_type save(*this); while (position < 0 && !node->is_root()) { - DCHECK_EQ(node->parent()->child(node->position()), node); + assert(node->parent()->child(node->position()) == node); position = node->position() - 1; node = node->parent(); } @@ -1761,7 +1703,7 @@ void btree_iterator::decrement_slow() { *this = save; } } else { - DCHECK_GE(position, 0); + assert(position >= 0); node = node->child(position); while (!node->leaf()) { node = node->child(node->count()); @@ -1786,26 +1728,26 @@ btree

::btree(const self_type &x) } template template -pair::iterator, bool> +std::pair::iterator, bool> btree

::insert_unique(const key_type &key, ValuePointer value) { if (empty()) { *mutable_root() = new_leaf_root_node(1); } - pair res = internal_locate(key, iterator(root(), 0)); + std::pair res = internal_locate(key, iterator(root(), 0)); iterator &iter = res.first; if (res.second == kExactMatch) { // The key already exists in the tree, do nothing. - return make_pair(internal_last(iter), false); + return std::make_pair(internal_last(iter), false); } else if (!res.second) { iterator last = internal_last(iter); if (last.node && !compare_keys(key, last.key())) { // The key already exists in the tree, do nothing. - return make_pair(last, false); + return std::make_pair(last, false); } } - return make_pair(internal_insert(iter, *value), true); + return std::make_pair(internal_insert(iter, *value), true); } template @@ -1912,8 +1854,8 @@ typename btree

::iterator btree

::erase(iterator iter) { // Deletion of a value on an internal node. Swap the key with the largest // value of our left child. This is easy, we just decrement iter. iterator tmp_iter(iter--); - DCHECK(iter.node->leaf()); - DCHECK(!compare_keys(tmp_iter.key(), iter.key())); + assert(iter.node->leaf()); + assert(!compare_keys(tmp_iter.key(), iter.key())); iter.node->value_swap(iter.position, tmp_iter.node, tmp_iter.position); internal_delete = true; --*mutable_size(); @@ -2010,22 +1952,22 @@ void btree

::clear() { template void btree

::swap(self_type &x) { - ::swap(static_cast(*this), static_cast(x)); - ::swap(root_, x.root_); + std::swap(static_cast(*this), static_cast(x)); + std::swap(root_, x.root_); } template void btree

::verify() const { if (root() != NULL) { - CHECK_EQ(size(), internal_verify(root(), NULL, NULL)); - CHECK_EQ(leftmost(), (++const_iterator(root(), -1)).node); - CHECK_EQ(rightmost(), (--const_iterator(root(), root()->count())).node); - CHECK(leftmost()->leaf()); - CHECK(rightmost()->leaf()); + assert(size() == internal_verify(root(), NULL, NULL)); + assert(leftmost() == (++const_iterator(root(), -1)).node); + assert(rightmost() == (--const_iterator(root(), root()->count())).node); + assert(leftmost()->leaf()); + assert(rightmost()->leaf()); } else { - CHECK_EQ(size(), 0); - CHECK(leftmost() == NULL); - CHECK(rightmost() == NULL); + assert(size() == 0); + assert(leftmost() == NULL); + assert(rightmost() == NULL); } } @@ -2033,7 +1975,7 @@ template void btree

::rebalance_or_split(iterator *iter) { node_type *&node = iter->node; int &insert_position = iter->position; - DCHECK_EQ(node->count(), node->max_count()); + assert(node->count() == node->max_count()); // First try to make room on the node by rebalancing. node_type *parent = node->parent(); @@ -2047,20 +1989,20 @@ void btree

::rebalance_or_split(iterator *iter) { // fill up the left node. int to_move = (left->max_count() - left->count()) / (1 + (insert_position < left->max_count())); - to_move = max(1, to_move); + to_move = std::max(1, to_move); if (((insert_position - to_move) >= 0) || ((left->count() + to_move) < left->max_count())) { left->rebalance_right_to_left(node, to_move); - DCHECK_EQ(node->max_count() - node->count(), to_move); + assert(node->max_count() - node->count() == to_move); insert_position = insert_position - to_move; if (insert_position < 0) { insert_position = insert_position + left->count() + 1; node = left; } - DCHECK_LT(node->count(), node->max_count()); + assert(node->count() < node->max_count()); return; } } @@ -2075,7 +2017,7 @@ void btree

::rebalance_or_split(iterator *iter) { // to fill up the right node. int to_move = (right->max_count() - right->count()) / (1 + (insert_position > 0)); - to_move = max(1, to_move); + to_move = std::max(1, to_move); if ((insert_position <= (node->count() - to_move)) || ((right->count() + to_move) < right->max_count())) { @@ -2086,7 +2028,7 @@ void btree

::rebalance_or_split(iterator *iter) { node = right; } - DCHECK_LT(node->count(), node->max_count()); + assert(node->count() < node->max_count()); return; } } @@ -2106,7 +2048,7 @@ void btree

::rebalance_or_split(iterator *iter) { parent = new_internal_root_node(); parent->set_child(0, root()); *mutable_root() = parent; - DCHECK(*mutable_rightmost() == parent->child(0)); + assert(*mutable_rightmost() == parent->child(0)); } else { // The root node is an internal node. We do not want to create a new root // node because the root node is special and holds the size of the tree @@ -2179,7 +2121,7 @@ bool btree

::try_merge_or_rebalance(iterator *iter) { ((iter->node->count() == 0) || (iter->position > 0))) { int to_move = (right->count() - iter->node->count()) / 2; - to_move = min(to_move, right->count() - 1); + to_move = std::min(to_move, right->count() - 1); iter->node->rebalance_right_to_left(right, to_move); return false; } @@ -2194,7 +2136,7 @@ bool btree

::try_merge_or_rebalance(iterator *iter) { ((iter->node->count() == 0) || (iter->position < iter->node->count()))) { int to_move = (left->count() - iter->node->count()) / 2; - to_move = min(to_move, left->count() - 1); + to_move = std::min(to_move, left->count() - 1); left->rebalance_left_to_right(iter->node, to_move); iter->position += to_move; return false; @@ -2210,7 +2152,7 @@ void btree

::try_shrink() { } // Deleted the last item on the root node, shrink the height of the tree. if (root()->leaf()) { - DCHECK_EQ(size(), 0); + assert(size() == 0); delete_leaf_node(root()); *mutable_root() = NULL; } else { @@ -2256,9 +2198,9 @@ btree

::internal_insert(iterator iter, const value_type &v) { if (iter.node->max_count() < kNodeValues) { // Insertion into the root where the root is smaller that the full node // size. Simply grow the size of the root node. - DCHECK(iter.node == root()); + assert(iter.node == root()); iter.node = new_leaf_root_node( - min(kNodeValues, 2 * iter.node->max_count())); + std::min(kNodeValues, 2 * iter.node->max_count())); iter.node->swap(root()); delete_leaf_node(root()); *mutable_root() = iter.node; @@ -2274,13 +2216,13 @@ btree

::internal_insert(iterator iter, const value_type &v) { } template template -inline pair btree

::internal_locate( +inline std::pair btree

::internal_locate( const key_type &key, IterType iter) const { return internal_locate_type::dispatch(key, *this, iter); } template template -inline pair btree

::internal_locate_plain_compare( +inline std::pair btree

::internal_locate_plain_compare( const key_type &key, IterType iter) const { for (;;) { iter.position = iter.node->lower_bound(key, key_comp()); @@ -2289,24 +2231,24 @@ inline pair btree

::internal_locate_plain_compare( } iter.node = iter.node->child(iter.position); } - return make_pair(iter, 0); + return std::make_pair(iter, 0); } template template -inline pair btree

::internal_locate_compare_to( +inline std::pair btree

::internal_locate_compare_to( const key_type &key, IterType iter) const { for (;;) { int res = iter.node->lower_bound(key, key_comp()); iter.position = res & kMatchMask; if (res & kExactMatch) { - return make_pair(iter, static_cast(kExactMatch)); + return std::make_pair(iter, static_cast(kExactMatch)); } if (iter.node->leaf()) { break; } iter.node = iter.node->child(iter.position); } - return make_pair(iter, -kExactMatch); + return std::make_pair(iter, -kExactMatch); } template template @@ -2346,7 +2288,7 @@ template template IterType btree

::internal_find_unique( const key_type &key, IterType iter) const { if (iter.node) { - pair res = internal_locate(key, iter); + std::pair res = internal_locate(key, iter); if (res.second == kExactMatch) { return res.first; } @@ -2393,7 +2335,7 @@ void btree

::internal_clear(node_type *node) { template void btree

::internal_dump( - ostream &os, const node_type *node, int level) const { + std::ostream &os, const node_type *node, int level) const { for (int i = 0; i < node->count(); ++i) { if (!node->leaf()) { internal_dump(os, node->child(i), level + 1); @@ -2411,23 +2353,23 @@ void btree

::internal_dump( template int btree

::internal_verify( const node_type *node, const key_type *lo, const key_type *hi) const { - CHECK_GT(node->count(), 0); - CHECK_LE(node->count(), node->max_count()); + assert(node->count() > 0); + assert(node->count() <= node->max_count()); if (lo) { - CHECK(!compare_keys(node->key(0), *lo)); + assert(!compare_keys(node->key(0), *lo)); } if (hi) { - CHECK(!compare_keys(*hi, node->key(node->count() - 1))); + assert(!compare_keys(*hi, node->key(node->count() - 1))); } for (int i = 1; i < node->count(); ++i) { - CHECK(!compare_keys(node->key(i), node->key(i - 1))); + assert(!compare_keys(node->key(i), node->key(i - 1))); } int count = node->count(); if (!node->leaf()) { for (int i = 0; i <= node->count(); ++i) { - CHECK(node->child(i) != NULL); - CHECK_EQ(node->child(i)->parent(), node); - CHECK_EQ(node->child(i)->position(), i); + assert(node->child(i) != NULL); + assert(node->child(i)->parent() == node); + assert(node->child(i)->position() == i); count += internal_verify( node->child(i), (i == 0) ? lo : &node->key(i - 1), @@ -2438,8 +2380,5 @@ int btree

::internal_verify( } } // namespace btree -} // namespace util - -DEFINE_GDB_AUTO_SCRIPT("util/btree/btree_printer.py") #endif // UTIL_BTREE_BTREE_H__ diff --git a/btree_bench.cc b/btree_bench.cc index 94a1f272..1b45582a 100644 --- a/btree_bench.cc +++ b/btree_bench.cc @@ -26,7 +26,6 @@ DECLARE_int32(benchmark_max_iters); -namespace util { namespace btree { namespace { @@ -480,7 +479,6 @@ MY_BENCHMARK(multimap_cord); } // namespace } // namespace btree -} // namespace util int main(int argc, char **argv) { FLAGS_logtostderr = true; diff --git a/btree_container.h b/btree_container.h index beebf6ff..510c9ae6 100644 --- a/btree_container.h +++ b/btree_container.h @@ -8,9 +8,8 @@ #include #include -#include "util/btree/btree.h" // IWYU pragma: export +#include "btree.h" -namespace util { namespace btree { // A common base class for btree_set, btree_map, btree_multiset and @@ -70,10 +69,10 @@ class btree_container { const_iterator upper_bound(const key_type &key) const { return tree_.upper_bound(key); } - pair equal_range(const key_type &key) { + std::pair equal_range(const key_type &key) { return tree_.equal_range(key); } - pair equal_range(const key_type &key) const { + std::pair equal_range(const key_type &key) const { return tree_.equal_range(key); } @@ -84,7 +83,7 @@ class btree_container { void swap(self_type &x) { tree_.swap(x.tree_); } - void dump(ostream &os) const { + void dump(std::ostream &os) const { tree_.dump(os); } void verify() const { @@ -128,7 +127,7 @@ class btree_container { }; template -inline ostream& operator<<(ostream &os, const btree_container &b) { +inline std::ostream& operator<<(std::ostream &os, const btree_container &b) { b.dump(os); return os; } @@ -181,7 +180,7 @@ class btree_unique_container : public btree_container { } // Insertion routines. - pair insert(const value_type &x) { + std::pair insert(const value_type &x) { return this->tree_.insert_unique(x); } iterator insert(iterator position, const value_type &x) { @@ -230,7 +229,7 @@ class btree_map_container : public btree_unique_container { : key(k) { } value_type operator*() const { - return make_pair(key, data_type()); + return std::make_pair(key, data_type()); } const key_type &key; }; @@ -337,6 +336,5 @@ class btree_multi_container : public btree_container { }; } // namespace btree -} // namespace util #endif // UTIL_BTREE_BTREE_CONTAINER_H__ diff --git a/btree_map.h b/btree_map.h index 3c61a7f2..6e965590 100644 --- a/btree_map.h +++ b/btree_map.h @@ -1,4 +1,4 @@ -// Copyright 2007 Google Inc. All Rights Reserved. +// Copyright 2007, 2012 Google Inc. All Rights Reserved. // Author: jmacd@google.com (Josh MacDonald) // Author: pmattis@google.com (Peter Mattis) // @@ -18,16 +18,15 @@ #include #include -#include "util/btree/btree.h" // IWYU pragma: export -#include "util/btree/btree_container.h" // IWYU pragma: export +#include "btree.h" +#include "btree_container.h" -namespace util { namespace btree { // The btree_map class is needed mainly for it's constructors. template , - typename Alloc = std::allocator >, + typename Compare = std::less, + typename Alloc = std::allocator >, int TargetNodeSize = 256> class btree_map : public btree_map_container< btree > > { @@ -71,8 +70,8 @@ inline void swap(btree_map &x, // The btree_multimap class is needed mainly for it's constructors. template , - typename Alloc = std::allocator >, + typename Compare = std::less, + typename Alloc = std::allocator >, int TargetNodeSize = 256> class btree_multimap : public btree_multi_container< btree > > { @@ -117,6 +116,5 @@ inline void swap(btree_multimap &x, } } // namespace btree -} // namespace util #endif // UTIL_BTREE_BTREE_MAP_H__ diff --git a/btree_set.h b/btree_set.h index 7b5ea88d..0b51e494 100644 --- a/btree_set.h +++ b/btree_set.h @@ -14,15 +14,14 @@ #include #include -#include "util/btree/btree.h" // IWYU pragma: export -#include "util/btree/btree_container.h" // IWYU pragma: export +#include "btree.h" +#include "btree_container.h" -namespace util { namespace btree { // The btree_set class is needed mainly for it's constructors. template , + typename Compare = std::less, typename Alloc = std::allocator, int TargetNodeSize = 256> class btree_set : public btree_unique_container< @@ -65,7 +64,7 @@ inline void swap(btree_set &x, btree_set &y) { // The btree_multiset class is needed mainly for it's constructors. template , + typename Compare = std::less, typename Alloc = std::allocator, int TargetNodeSize = 256> class btree_multiset : public btree_multi_container< @@ -108,6 +107,5 @@ inline void swap(btree_multiset &x, } } // namespace btree -} // namespace util #endif // UTIL_BTREE_BTREE_SET_H__ diff --git a/btree_test.cc b/btree_test.cc index 335318de..7b9cafa5 100644 --- a/btree_test.cc +++ b/btree_test.cc @@ -2,128 +2,120 @@ // Author: jmacd@google.com (Josh MacDonald) // Author: pmattis@google.com (Peter Mattis) -#include "base/arena-inl.h" -#include "base/init_google.h" -#include "base/integral_types.h" -#include "base/logging.h" -#include "strings/stringpiece.h" -#include "testing/base/public/gunit.h" -#include "util/btree/btree_map.h" -#include "util/btree/btree_set.h" -#include "util/btree/btree_test.h" +#include "gtest/gtest.h" +#include "btree_map.h" +#include "btree_set.h" +#include "btree_test.h" -namespace util { namespace btree { namespace { template void SetTest() { - typedef ArenaAllocator ArenaAlloc; - CHECK_EQ(sizeof(btree_set), sizeof(void*)); - BtreeTest, allocator, N>, set >(); - BtreeArenaTest, ArenaAlloc, N> >(); + typedef TestAllocator TestAlloc; + ASSERT_EQ(sizeof(btree_set), sizeof(void*)); + BtreeTest, std::allocator, N>, std::set >(); + BtreeAllocatorTest, TestAlloc, N> >(); } template void MapTest() { - typedef ArenaAllocator ArenaAlloc; - CHECK_EQ(sizeof(btree_map), sizeof(void*)); - BtreeTest, allocator, N>, map >(); - BtreeArenaTest, ArenaAlloc, N> >(); - BtreeMapTest, allocator, N> >(); + typedef TestAllocator TestAlloc; + ASSERT_EQ(sizeof(btree_map), sizeof(void*)); + BtreeTest, std::allocator, N>, std::map >(); + BtreeAllocatorTest, TestAlloc, N> >(); + BtreeMapTest, std::allocator, N> >(); } -TEST(Btree, set_int32_32) { SetTest(); } -TEST(Btree, set_int32_64) { SetTest(); } -TEST(Btree, set_int32_128) { SetTest(); } -TEST(Btree, set_int32_256) { SetTest(); } -TEST(Btree, set_int64_256) { SetTest(); } -TEST(Btree, set_string_256) { SetTest(); } -TEST(Btree, set_cord_256) { SetTest(); } -TEST(Btree, set_pair_256) { SetTest, 256>(); } -TEST(Btree, map_int32_256) { MapTest(); } -TEST(Btree, map_int64_256) { MapTest(); } -TEST(Btree, map_string_256) { MapTest(); } -TEST(Btree, map_cord_256) { MapTest(); } -TEST(Btree, map_pair_256) { MapTest, 256>(); } +TEST(Btree, set_int32_32) { SetTest(); } +TEST(Btree, set_int32_64) { SetTest(); } +TEST(Btree, set_int32_128) { SetTest(); } +TEST(Btree, set_int32_256) { SetTest(); } +TEST(Btree, set_int64_256) { SetTest(); } +TEST(Btree, set_string_256) { SetTest(); } +TEST(Btree, set_pair_256) { SetTest, 256>(); } +TEST(Btree, map_int32_256) { MapTest(); } +TEST(Btree, map_int64_256) { MapTest(); } +TEST(Btree, map_string_256) { MapTest(); } +TEST(Btree, map_pair_256) { MapTest, 256>(); } // Large-node tests -TEST(Btree, map_int32_1024) { MapTest(); } -TEST(Btree, map_int32_1032) { MapTest(); } -TEST(Btree, map_int32_1040) { MapTest(); } -TEST(Btree, map_int32_1048) { MapTest(); } -TEST(Btree, map_int32_1056) { MapTest(); } +TEST(Btree, map_int32_1024) { MapTest(); } +TEST(Btree, map_int32_1032) { MapTest(); } +TEST(Btree, map_int32_1040) { MapTest(); } +TEST(Btree, map_int32_1048) { MapTest(); } +TEST(Btree, map_int32_1056) { MapTest(); } -TEST(Btree, map_int32_2048) { MapTest(); } -TEST(Btree, map_int32_4096) { MapTest(); } -TEST(Btree, set_int32_1024) { SetTest(); } -TEST(Btree, set_int32_2048) { SetTest(); } -TEST(Btree, set_int32_4096) { SetTest(); } -TEST(Btree, map_string_1024) { MapTest(); } -TEST(Btree, map_string_2048) { MapTest(); } -TEST(Btree, map_string_4096) { MapTest(); } -TEST(Btree, set_string_1024) { SetTest(); } -TEST(Btree, set_string_2048) { SetTest(); } -TEST(Btree, set_string_4096) { SetTest(); } +TEST(Btree, map_int32_2048) { MapTest(); } +TEST(Btree, map_int32_4096) { MapTest(); } +TEST(Btree, set_int32_1024) { SetTest(); } +TEST(Btree, set_int32_2048) { SetTest(); } +TEST(Btree, set_int32_4096) { SetTest(); } +TEST(Btree, map_string_1024) { MapTest(); } +TEST(Btree, map_string_2048) { MapTest(); } +TEST(Btree, map_string_4096) { MapTest(); } +TEST(Btree, set_string_1024) { SetTest(); } +TEST(Btree, set_string_2048) { SetTest(); } +TEST(Btree, set_string_4096) { SetTest(); } template void MultiSetTest() { - typedef ArenaAllocator ArenaAlloc; - CHECK_EQ(sizeof(btree_multiset), sizeof(void*)); - BtreeMultiTest, allocator, N>, - multiset >(); - BtreeArenaTest, ArenaAlloc, N> >(); + typedef TestAllocator TestAlloc; + ASSERT_EQ(sizeof(btree_multiset), sizeof(void*)); + BtreeMultiTest, std::allocator, N>, + std::multiset >(); + BtreeAllocatorTest, TestAlloc, N> >(); } template void MultiMapTest() { - typedef ArenaAllocator ArenaAlloc; - CHECK_EQ(sizeof(btree_multimap), sizeof(void*)); - BtreeMultiTest, allocator, N>, - multimap >(); - BtreeMultiMapTest, allocator, N> >(); - BtreeArenaTest, ArenaAlloc, N> >(); + typedef TestAllocator TestAlloc; + ASSERT_EQ(sizeof(btree_multimap), sizeof(void*)); + BtreeMultiTest, std::allocator, N>, + std::multimap >(); + BtreeMultiMapTest, std::allocator, N> >(); + BtreeAllocatorTest, TestAlloc, N> >(); } -TEST(Btree, multiset_int32_256) { MultiSetTest(); } -TEST(Btree, multiset_int64_256) { MultiSetTest(); } -TEST(Btree, multiset_string_256) { MultiSetTest(); } -TEST(Btree, multiset_cord_256) { MultiSetTest(); } -TEST(Btree, multiset_pair_256) { MultiSetTest, 256>(); } -TEST(Btree, multimap_int32_256) { MultiMapTest(); } -TEST(Btree, multimap_int64_256) { MultiMapTest(); } -TEST(Btree, multimap_string_256) { MultiMapTest(); } -TEST(Btree, multimap_cord_256) { MultiMapTest(); } -TEST(Btree, multimap_pair_256) { MultiMapTest, 256>(); } +TEST(Btree, multiset_int32_256) { MultiSetTest(); } +TEST(Btree, multiset_int64_256) { MultiSetTest(); } +TEST(Btree, multiset_string_256) { MultiSetTest(); } +TEST(Btree, multiset_pair_256) { MultiSetTest, 256>(); } +TEST(Btree, multimap_int32_256) { MultiMapTest(); } +TEST(Btree, multimap_int64_256) { MultiMapTest(); } +TEST(Btree, multimap_string_256) { MultiMapTest(); } +TEST(Btree, multimap_pair_256) { MultiMapTest, 256>(); } // Large-node tests -TEST(Btree, multimap_int32_1024) { MultiMapTest(); } -TEST(Btree, multimap_int32_2048) { MultiMapTest(); } -TEST(Btree, multimap_int32_4096) { MultiMapTest(); } -TEST(Btree, multiset_int32_1024) { MultiSetTest(); } -TEST(Btree, multiset_int32_2048) { MultiSetTest(); } -TEST(Btree, multiset_int32_4096) { MultiSetTest(); } -TEST(Btree, multimap_string_1024) { MultiMapTest(); } -TEST(Btree, multimap_string_2048) { MultiMapTest(); } -TEST(Btree, multimap_string_4096) { MultiMapTest(); } -TEST(Btree, multiset_string_1024) { MultiSetTest(); } -TEST(Btree, multiset_string_2048) { MultiSetTest(); } -TEST(Btree, multiset_string_4096) { MultiSetTest(); } +TEST(Btree, multimap_int32_1024) { MultiMapTest(); } +TEST(Btree, multimap_int32_2048) { MultiMapTest(); } +TEST(Btree, multimap_int32_4096) { MultiMapTest(); } +TEST(Btree, multiset_int32_1024) { MultiSetTest(); } +TEST(Btree, multiset_int32_2048) { MultiSetTest(); } +TEST(Btree, multiset_int32_4096) { MultiSetTest(); } +TEST(Btree, multimap_string_1024) { MultiMapTest(); } +TEST(Btree, multimap_string_2048) { MultiMapTest(); } +TEST(Btree, multimap_string_4096) { MultiMapTest(); } +TEST(Btree, multiset_string_1024) { MultiSetTest(); } +TEST(Btree, multiset_string_2048) { MultiSetTest(); } +TEST(Btree, multiset_string_4096) { MultiSetTest(); } // Verify that swapping btrees swaps the key comparision functors. struct SubstringLess { SubstringLess() : n(2) {} - SubstringLess(int length) + SubstringLess(size_t length) : n(length) { } - bool operator()(const string &a, const string &b) const { - return StringPiece(a).substr(0, n) < StringPiece(b).substr(0, n); + bool operator()(const std::string &a, const std::string &b) const { + std::string as(a.data(), std::min(n, a.size())); + std::string bs(b.data(), std::min(n, b.size())); + return as < bs; } - int n; + size_t n; }; TEST(Btree, SwapKeyCompare) { - typedef btree_set SubstringSet; + typedef btree_set SubstringSet; SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type()); SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type()); @@ -147,7 +139,7 @@ TEST(Btree, SwapKeyCompare) { TEST(Btree, UpperBoundRegression) { // Regress a bug where upper_bound would default-construct a new key_compare // instead of copying the existing one. - typedef btree_set SubstringSet; + typedef btree_set SubstringSet; SubstringSet my_set(SubstringLess(3)); my_set.insert("aab"); my_set.insert("abb"); @@ -164,25 +156,25 @@ TEST(Btree, UpperBoundRegression) { TEST(Btree, IteratorIncrementBy) { // Test that increment_by returns the same position as increment. const int kSetSize = 2341; - btree_set my_set; + btree_set my_set; for (int i = 0; i < kSetSize; ++i) { my_set.insert(i); } { // Simple increment vs. increment by. - btree_set::iterator a = my_set.begin(); - btree_set::iterator b = my_set.begin(); + btree_set::iterator a = my_set.begin(); + btree_set::iterator b = my_set.begin(); a.increment(); b.increment_by(1); EXPECT_EQ(*a, *b); } - btree_set::iterator a = my_set.begin(); + btree_set::iterator a = my_set.begin(); for (int i = 1; i < kSetSize; ++i) { ++a; // increment_by - btree_set::iterator b = my_set.begin(); + btree_set::iterator b = my_set.begin(); b.increment_by(i); EXPECT_EQ(*a, *b) << ": i=" << i; } @@ -190,11 +182,11 @@ TEST(Btree, IteratorIncrementBy) { TEST(Btree, Comparison) { const int kSetSize = 1201; - btree_set my_set; + btree_set my_set; for (int i = 0; i < kSetSize; ++i) { my_set.insert(i); } - btree_set my_set_copy(my_set); + btree_set my_set_copy(my_set); EXPECT_TRUE(my_set_copy == my_set); EXPECT_TRUE(my_set == my_set_copy); EXPECT_FALSE(my_set_copy != my_set); @@ -212,17 +204,17 @@ TEST(Btree, Comparison) { EXPECT_TRUE(my_set_copy != my_set); EXPECT_TRUE(my_set != my_set_copy); - btree_map my_map; + btree_map my_map; for (int i = 0; i < kSetSize; ++i) { - my_map[string(i, 'a')] = i; + my_map[std::string(i, 'a')] = i; } - btree_map my_map_copy(my_map); + btree_map my_map_copy(my_map); EXPECT_TRUE(my_map_copy == my_map); EXPECT_TRUE(my_map == my_map_copy); EXPECT_FALSE(my_map_copy != my_map); EXPECT_FALSE(my_map != my_map_copy); - ++my_map_copy[string(7, 'a')]; + ++my_map_copy[std::string(7, 'a')]; EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); @@ -235,7 +227,7 @@ TEST(Btree, Comparison) { EXPECT_TRUE(my_map_copy != my_map); EXPECT_TRUE(my_map != my_map_copy); - my_map.erase(string(kSetSize - 1, 'a')); + my_map.erase(std::string(kSetSize - 1, 'a')); EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); @@ -244,10 +236,3 @@ TEST(Btree, Comparison) { } // namespace } // namespace btree -} // namespace util - -int main(int argc, char **argv) { - FLAGS_logtostderr = true; - InitGoogle(argv[0], &argc, &argv, true); - return RUN_ALL_TESTS(); -} diff --git a/btree_test.h b/btree_test.h index 557c1e54..c368573e 100644 --- a/btree_test.h +++ b/btree_test.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,53 +17,50 @@ #include #include -#include "base/arena.h" -#include "base/commandlineflags.h" -#include "base/logging.h" -#include "base/type_traits.h" -#include "strings/cord.h" -#include "strings/util.h" -#include "testing/base/public/googletest.h" -#include "util/btree/btree_container.h" -#include "util/random/acmrandom.h" +#include "gtest/gtest.h" +#include "gflags/gflags.h" +#include "btree_container.h" DECLARE_int32(test_values); DECLARE_int32(benchmark_values); namespace std { -// Provide operator<< support for pair. +// Provide operator<< support for std::pair. template -ostream& operator<<(ostream &os, const pair &p) { +ostream& operator<<(ostream &os, const std::pair &p) { os << "(" << p.first << "," << p.second << ")"; return os; } // Provide pair equality testing that works as long as x.first is comparable to // y.first and x.second is comparable to y.second. Needed in the test for -// comparing pair to pair. +// comparing std::pair to std::pair. template -bool operator==(const pair &x, const pair &y) { +bool operator==(const std::pair &x, const std::pair &y) { return x.first == y.first && x.second == y.second; } -} // namespace std - -namespace base { - // Partial specialization of remove_const that propagates the removal through // std::pair. template -struct remove_const > { - typedef std::pair::type, - typename remove_const::type> type; +struct remove_const > { + typedef pair::type, + typename remove_const::type> type; }; -} // namespace base +} // namespace std -namespace util { namespace btree { +// Select the first member of a pair. +template +struct select1st : public std::unary_function<_Pair, typename _Pair::first_type> { + const typename _Pair::first_type& operator()(const _Pair& __x) const { + return __x.first; + } +}; + // Utility class to provide an accessor for a key given a value. The default // behavior is to treat the value as a pair and return the first element. template @@ -70,6 +68,11 @@ struct KeyOfValue { typedef select1st type; }; +template +struct identity { + inline const T& operator()(const T& t) const { return t; } +}; + // Partial specialization of KeyOfValue class for when the key and value are // the same type such as in set<> and btree_set<>. template @@ -77,6 +80,29 @@ struct KeyOfValue { typedef identity type; }; +// Counts the number of occurances of "c" in a buffer. +inline ptrdiff_t strcount(const char* buf_begin, const char* buf_end, char c) { + if (buf_begin == NULL) + return 0; + if (buf_end <= buf_begin) + return 0; + ptrdiff_t num = 0; + for (const char* bp = buf_begin; bp != buf_end; bp++) { + if (*bp == c) + num++; + } + return num; +} + +// for when the string is not null-terminated. +inline ptrdiff_t strcount(const char* buf, size_t len, char c) { + return strcount(buf, buf + len, c); +} + +inline ptrdiff_t strcount(const std::string& buf, char c) { + return strcount(buf.c_str(), buf.size(), c); +} + // The base class for a sorted associative container checker. TreeType is the // container type to check and CheckerType is the container type to check // against. TreeType is expected to be btree_{set,map,multiset,multimap} and @@ -127,9 +153,9 @@ class base_checker { IterType iter_check( IterType tree_iter, CheckerIterType checker_iter) const { if (tree_iter == tree_.end()) { - CHECK(checker_iter == checker_.end()); + EXPECT_EQ(checker_iter, checker_.end()); } else { - CHECK_EQ(*tree_iter, *checker_iter); + EXPECT_EQ(*tree_iter, *checker_iter); } return tree_iter; } @@ -137,9 +163,9 @@ class base_checker { IterType riter_check( IterType tree_iter, CheckerIterType checker_iter) const { if (tree_iter == tree_.rend()) { - CHECK(checker_iter == checker_.rend()); + EXPECT_EQ(checker_iter, checker_.rend()); } else { - CHECK_EQ(*tree_iter, *checker_iter); + EXPECT_EQ(*tree_iter, *checker_iter); } return tree_iter; } @@ -147,17 +173,17 @@ class base_checker { typename KeyOfValue::type key_of_value; const key_type &key = key_of_value(x); - CHECK_EQ(*find(key), x); + EXPECT_EQ(*find(key), x); lower_bound(key); upper_bound(key); equal_range(key); count(key); } void erase_check(const key_type &key) { - CHECK(tree_.find(key) == const_tree_.end()); - CHECK(const_tree_.find(key) == tree_.end()); - CHECK(tree_.equal_range(key).first == - const_tree_.equal_range(key).second); + EXPECT_TRUE(tree_.find(key) == const_tree_.end()); + EXPECT_TRUE(const_tree_.find(key) == tree_.end()); + EXPECT_TRUE(tree_.equal_range(key).first == + const_tree_.equal_range(key).second); } // Lookup routines. @@ -173,20 +199,20 @@ class base_checker { const_iterator upper_bound(const key_type &key) const { return iter_check(tree_.upper_bound(key), checker_.upper_bound(key)); } - pair equal_range(const key_type &key) { - pair equal_range(const key_type &key) { + std::pair checker_res = checker_.equal_range(key); - pair tree_res = tree_.equal_range(key); + std::pair tree_res = tree_.equal_range(key); iter_check(tree_res.first, checker_res.first); iter_check(tree_res.second, checker_res.second); return tree_res; } - pair equal_range(const key_type &key) const { - pair equal_range(const key_type &key) const { + std::pair checker_res = checker_.equal_range(key); - pair tree_res = tree_.equal_range(key); + std::pair tree_res = tree_.equal_range(key); iter_check(tree_res.first, checker_res.first); iter_check(tree_res.second, checker_res.second); return tree_res; @@ -199,7 +225,7 @@ class base_checker { } size_type count(const key_type &key) const { size_type res = checker_.count(key); - CHECK_EQ(res, tree_.count(key)); + EXPECT_EQ(res, tree_.count(key)); return res; } @@ -214,10 +240,10 @@ class base_checker { int erase(const key_type &key) { int size = tree_.size(); int res = checker_.erase(key); - CHECK_EQ(res, tree_.count(key)); - CHECK_EQ(res, tree_.erase(key)); - CHECK_EQ(tree_.count(key), 0); - CHECK_EQ(tree_.size(), size - res); + EXPECT_EQ(res, tree_.count(key)); + EXPECT_EQ(res, tree_.erase(key)); + EXPECT_EQ(tree_.count(key), 0); + EXPECT_EQ(tree_.size(), size - res); erase_check(key); return res; } @@ -233,9 +259,9 @@ class base_checker { ++checker_next; checker_.erase(checker_iter); iter = tree_.erase(iter); - CHECK_EQ(tree_.size(), checker_.size()); - CHECK_EQ(tree_.size(), size - 1); - CHECK_EQ(tree_.count(key), count - 1); + EXPECT_EQ(tree_.size(), checker_.size()); + EXPECT_EQ(tree_.size(), size - 1); + EXPECT_EQ(tree_.count(key), count - 1); if (count == 1) { erase_check(key); } @@ -258,8 +284,8 @@ class base_checker { } checker_.erase(checker_begin, checker_end); tree_.erase(begin, end); - CHECK_EQ(tree_.size(), checker_.size()); - CHECK_EQ(tree_.size(), size - count); + EXPECT_EQ(tree_.size(), checker_.size()); + EXPECT_EQ(tree_.size(), size - count); } // Utility routines. @@ -274,7 +300,7 @@ class base_checker { void verify() const { tree_.verify(); - CHECK_EQ(tree_.size(), checker_.size()); + EXPECT_EQ(tree_.size(), checker_.size()); // Move through the forward iterators using increment. typename CheckerType::const_iterator @@ -282,7 +308,7 @@ class base_checker { const_iterator tree_iter(tree_.begin()); for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) { - CHECK_EQ(*tree_iter, *checker_iter); + EXPECT_EQ(*tree_iter, *checker_iter); } // Move through the forward iterators using decrement. @@ -291,8 +317,8 @@ class base_checker { --tree_iter; --checker_iter; } - CHECK(tree_iter == tree_.begin()); - CHECK(checker_iter == checker_.begin()); + EXPECT_TRUE(tree_iter == tree_.begin()); + EXPECT_TRUE(checker_iter == checker_.begin()); // Move through the reverse iterators using increment. typename CheckerType::const_reverse_iterator @@ -300,7 +326,7 @@ class base_checker { const_reverse_iterator tree_riter(tree_.rbegin()); for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) { - CHECK_EQ(*tree_riter, *checker_riter); + EXPECT_EQ(*tree_riter, *checker_riter); } // Move through the reverse iterators using decrement. @@ -309,8 +335,8 @@ class base_checker { --tree_riter; --checker_riter; } - CHECK(tree_riter == tree_.rbegin()); - CHECK(checker_riter == checker_.rbegin()); + EXPECT_EQ(tree_riter, tree_.rbegin()); + EXPECT_EQ(checker_riter, checker_.rbegin()); } // Access to the underlying btree. @@ -318,12 +344,12 @@ class base_checker { // Size routines. size_type size() const { - CHECK_EQ(tree_.size(), checker_.size()); + EXPECT_EQ(tree_.size(), checker_.size()); return tree_.size(); } size_type max_size() const { return tree_.max_size(); } bool empty() const { - CHECK_EQ(tree_.empty(), checker_.empty()); + EXPECT_EQ(tree_.empty(), checker_.empty()); return tree_.empty(); } size_type height() const { return tree_.height(); } @@ -367,25 +393,25 @@ class unique_checker : public base_checker { } // Insertion routines. - pair insert(const value_type &x) { + std::pair insert(const value_type &x) { int size = this->tree_.size(); - pair checker_res = + std::pair checker_res = this->checker_.insert(x); - pair tree_res = this->tree_.insert(x); - CHECK_EQ(*tree_res.first, *checker_res.first); - CHECK_EQ(tree_res.second, checker_res.second); - CHECK_EQ(this->tree_.size(), this->checker_.size()); - CHECK_EQ(this->tree_.size(), size + tree_res.second); + std::pair tree_res = this->tree_.insert(x); + EXPECT_EQ(*tree_res.first, *checker_res.first); + EXPECT_EQ(tree_res.second, checker_res.second); + EXPECT_EQ(this->tree_.size(), this->checker_.size()); + EXPECT_EQ(this->tree_.size(), size + tree_res.second); return tree_res; } iterator insert(iterator position, const value_type &x) { int size = this->tree_.size(); - pair checker_res = + std::pair checker_res = this->checker_.insert(x); iterator tree_res = this->tree_.insert(position, x); - CHECK_EQ(*tree_res, *checker_res.first); - CHECK_EQ(this->tree_.size(), this->checker_.size()); - CHECK_EQ(this->tree_.size(), size + checker_res.second); + EXPECT_EQ(*tree_res, *checker_res.first); + EXPECT_EQ(this->tree_.size(), this->checker_.size()); + EXPECT_EQ(this->tree_.size(), size + checker_res.second); return tree_res; } template @@ -428,18 +454,18 @@ class multi_checker : public base_checker { int size = this->tree_.size(); typename CheckerType::iterator checker_res = this->checker_.insert(x); iterator tree_res = this->tree_.insert(x); - CHECK_EQ(*tree_res, *checker_res); - CHECK_EQ(this->tree_.size(), this->checker_.size()); - CHECK_EQ(this->tree_.size(), size + 1); + EXPECT_EQ(*tree_res, *checker_res); + EXPECT_EQ(this->tree_.size(), this->checker_.size()); + EXPECT_EQ(this->tree_.size(), size + 1); return tree_res; } iterator insert(iterator position, const value_type &x) { int size = this->tree_.size(); typename CheckerType::iterator checker_res = this->checker_.insert(x); iterator tree_res = this->tree_.insert(position, x); - CHECK_EQ(*tree_res, *checker_res); - CHECK_EQ(this->tree_.size(), this->checker_.size()); - CHECK_EQ(this->tree_.size(), size + 1); + EXPECT_EQ(*tree_res, *checker_res); + EXPECT_EQ(this->tree_.size(), this->checker_.size()); + EXPECT_EQ(this->tree_.size(), size + 1); return tree_res; } template @@ -451,7 +477,7 @@ class multi_checker : public base_checker { }; char* GenerateDigits(char buf[16], int val, int maxval) { - DCHECK_LE(val, maxval); + EXPECT_LE(val, maxval); int p = 15; buf[p--] = 0; while (maxval > 0) { @@ -469,61 +495,48 @@ struct Generator { : maxval(m) { } K operator()(int i) const { - DCHECK_LE(i, maxval); + EXPECT_LE(i, maxval); return i; } }; template <> -struct Generator { +struct Generator { int maxval; Generator(int m) : maxval(m) { } - string operator()(int i) const { + std::string operator()(int i) const { char buf[16]; return GenerateDigits(buf, i, maxval); } }; -template <> -struct Generator { - int maxval; - Generator(int m) - : maxval(m) { - } - Cord operator()(int i) const { - char buf[16]; - return Cord(GenerateDigits(buf, i, maxval)); - } -}; - template -struct Generator > { - Generator::type> tgen; - Generator::type> ugen; +struct Generator > { + Generator::type> tgen; + Generator::type> ugen; Generator(int m) : tgen(m), ugen(m) { } - pair operator()(int i) const { - return make_pair(tgen(i), ugen(i)); + std::pair operator()(int i) const { + return std::make_pair(tgen(i), ugen(i)); } }; // Generate values for our tests and benchmarks. Value range is [0, maxval]. -const vector& GenerateNumbers(int n, int maxval) { - static ACMRandom rand(FLAGS_test_random_seed); - static vector values; - static set unique_values; +const std::vector& GenerateNumbers(int n, int maxval) { + static std::vector values; + static std::set unique_values; if (values.size() < n) { for (int i = values.size(); i < n; i++) { int value; do { - value = rand.Next() % (maxval + 1); + value = rand() % (maxval + 1); } while (unique_values.find(value) != unique_values.end()); values.push_back(value); @@ -537,13 +550,13 @@ const vector& GenerateNumbers(int n, int maxval) { // Generates values in the range // [0, 4 * min(FLAGS_benchmark_values, FLAGS_test_values)] template -vector GenerateValues(int n) { - int two_times_max = 2 * max(FLAGS_benchmark_values, FLAGS_test_values); +std::vector GenerateValues(int n) { + int two_times_max = 2 * std::max(FLAGS_benchmark_values, FLAGS_test_values); int four_times_max = 2 * two_times_max; - DCHECK_LE(n, two_times_max); - const vector &nums = GenerateNumbers(n, four_times_max); + EXPECT_LE(n, two_times_max); + const std::vector &nums = GenerateNumbers(n, four_times_max); Generator gen(four_times_max); - vector vec; + std::vector vec; for (int i = 0; i < n; i++) { vec.push_back(gen(nums[i])); @@ -553,44 +566,44 @@ vector GenerateValues(int n) { } template -double ContainerInfo(const set &s) { +double ContainerInfo(const std::set &s) { int sizeof_node = sizeof(std::_Rb_tree_node); int bytes_used = sizeof(s) + s.size() * sizeof_node; double bytes_per_value = (double) bytes_used / s.size(); - VLOG(1) << " size=" << s.size() + std::cout << " size=" << s.size() << " bytes-used=" << bytes_used << " bytes-per-value=" << bytes_per_value; return bytes_per_value; } template -double ContainerInfo(const multiset &s) { +double ContainerInfo(const std::multiset &s) { int sizeof_node = sizeof(std::_Rb_tree_node); int bytes_used = sizeof(s) + s.size() * sizeof_node; double bytes_per_value = (double) bytes_used / s.size(); - VLOG(1) << " size=" << s.size() + std::cout << " size=" << s.size() << " bytes-used=" << bytes_used << " bytes-per-value=" << bytes_per_value; return bytes_per_value; } template -double ContainerInfo(const map &m) { - int sizeof_node = sizeof(std::_Rb_tree_node >); +double ContainerInfo(const std::map &m) { + int sizeof_node = sizeof(std::_Rb_tree_node >); int bytes_used = sizeof(m) + m.size() * sizeof_node; double bytes_per_value = (double) bytes_used / m.size(); - VLOG(1) << " size=" << m.size() + std::cout << " size=" << m.size() << " bytes-used=" << bytes_used << " bytes-per-value=" << bytes_per_value; return bytes_per_value; } template -double ContainerInfo(const multimap &m) { - int sizeof_node = sizeof(std::_Rb_tree_node >); +double ContainerInfo(const std::multimap &m) { + int sizeof_node = sizeof(std::_Rb_tree_node >); int bytes_used = sizeof(m) + m.size() * sizeof_node; double bytes_per_value = (double) bytes_used / m.size(); - VLOG(1) << " size=" << m.size() + std::cout << " size=" << m.size() << " bytes-used=" << bytes_used << " bytes-per-value=" << bytes_per_value; return bytes_per_value; @@ -600,7 +613,7 @@ template double ContainerInfo(const btree_container

&b) { double bytes_used = sizeof(b) + b.bytes_used(); double bytes_per_value = (double) bytes_used / b.size(); - VLOG(1) << " size=" << b.size() + std::cout << " size=" << b.size() << " bytes-used=" << bytes_used << " bytes-per-value=" << bytes_per_value << " height=" << b.height() @@ -612,7 +625,7 @@ double ContainerInfo(const btree_container

&b) { } template -void DoTest(const char *name, T *b, const vector &values) { +void DoTest(const char *name, T *b, const std::vector &values) { typename KeyOfValue::type key_of_value; T &mutable_b = *b; @@ -631,22 +644,22 @@ void DoTest(const char *name, T *b, const vector &values) { // Test copy constructor. T b_copy(const_b); - CHECK_EQ(b_copy.size(), const_b.size()); - CHECK_LE(b_copy.height(), const_b.height()); - CHECK_LE(b_copy.internal_nodes(), const_b.internal_nodes()); - CHECK_LE(b_copy.leaf_nodes(), const_b.leaf_nodes()); + EXPECT_EQ(b_copy.size(), const_b.size()); + EXPECT_LE(b_copy.height(), const_b.height()); + EXPECT_LE(b_copy.internal_nodes(), const_b.internal_nodes()); + EXPECT_LE(b_copy.leaf_nodes(), const_b.leaf_nodes()); for (int i = 0; i < values.size(); ++i) { - CHECK_EQ(*b_copy.find(key_of_value(values[i])), values[i]); + EXPECT_EQ(*b_copy.find(key_of_value(values[i])), values[i]); } // Test range constructor. T b_range(const_b.begin(), const_b.end()); - CHECK_EQ(b_range.size(), const_b.size()); - CHECK_LE(b_range.height(), const_b.height()); - CHECK_LE(b_range.internal_nodes(), const_b.internal_nodes()); - CHECK_LE(b_range.leaf_nodes(), const_b.leaf_nodes()); + EXPECT_EQ(b_range.size(), const_b.size()); + EXPECT_LE(b_range.height(), const_b.height()); + EXPECT_LE(b_range.internal_nodes(), const_b.internal_nodes()); + EXPECT_LE(b_range.leaf_nodes(), const_b.leaf_nodes()); for (int i = 0; i < values.size(); ++i) { - CHECK_EQ(*b_range.find(key_of_value(values[i])), values[i]); + EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]); } // Test range insertion for values that already exist. @@ -656,36 +669,36 @@ void DoTest(const char *name, T *b, const vector &values) { // Test range insertion for new values. b_range.clear(); b_range.insert(b_copy.begin(), b_copy.end()); - CHECK_EQ(b_range.size(), b_copy.size()); - CHECK_EQ(b_range.height(), b_copy.height()); - CHECK_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); - CHECK_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); + EXPECT_EQ(b_range.size(), b_copy.size()); + EXPECT_EQ(b_range.height(), b_copy.height()); + EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); + EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); for (int i = 0; i < values.size(); ++i) { - CHECK_EQ(*b_range.find(key_of_value(values[i])), values[i]); + EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]); } // Test assignment to self. Nothing should change. b_range.operator=(b_range); - CHECK_EQ(b_range.size(), b_copy.size()); - CHECK_EQ(b_range.height(), b_copy.height()); - CHECK_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); - CHECK_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); + EXPECT_EQ(b_range.size(), b_copy.size()); + EXPECT_EQ(b_range.height(), b_copy.height()); + EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); + EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); // Test assignment of new values. b_range.clear(); b_range = b_copy; - CHECK_EQ(b_range.size(), b_copy.size()); - CHECK_EQ(b_range.height(), b_copy.height()); - CHECK_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); - CHECK_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); + EXPECT_EQ(b_range.size(), b_copy.size()); + EXPECT_EQ(b_range.height(), b_copy.height()); + EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes()); + EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes()); // Test swap. b_range.clear(); b_range.swap(b_copy); - CHECK_EQ(b_copy.size(), 0); - CHECK_EQ(b_range.size(), const_b.size()); + EXPECT_EQ(b_copy.size(), 0); + EXPECT_EQ(b_range.size(), const_b.size()); for (int i = 0; i < values.size(); ++i) { - CHECK_EQ(*b_range.find(key_of_value(values[i])), values[i]); + EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]); } b_range.swap(b_copy); @@ -693,13 +706,13 @@ void DoTest(const char *name, T *b, const vector &values) { for (int i = 0; i < values.size(); ++i) { mutable_b.erase(key_of_value(values[i])); // Erasing a non-existent key should have no effect. - CHECK_EQ(mutable_b.erase(key_of_value(values[i])), 0); + EXPECT_EQ(mutable_b.erase(key_of_value(values[i])), 0); } const_b.verify(); - CHECK_EQ(const_b.internal_nodes(), 0); - CHECK_EQ(const_b.leaf_nodes(), 0); - CHECK_EQ(const_b.size(), 0); + EXPECT_EQ(const_b.internal_nodes(), 0); + EXPECT_EQ(const_b.leaf_nodes(), 0); + EXPECT_EQ(const_b.size(), 0); // Test erase via iterators. mutable_b = b_copy; @@ -708,9 +721,9 @@ void DoTest(const char *name, T *b, const vector &values) { } const_b.verify(); - CHECK_EQ(const_b.internal_nodes(), 0); - CHECK_EQ(const_b.leaf_nodes(), 0); - CHECK_EQ(const_b.size(), 0); + EXPECT_EQ(const_b.internal_nodes(), 0); + EXPECT_EQ(const_b.leaf_nodes(), 0); + EXPECT_EQ(const_b.size(), 0); // Test insert with hint. for (int i = 0; i < values.size(); i++) { @@ -721,13 +734,13 @@ void DoTest(const char *name, T *b, const vector &values) { // Test dumping of the btree to an ostream. There should be 1 line for each // value. - ostringstream strm; + std::stringstream strm; strm << mutable_b.tree(); - CHECK_EQ(mutable_b.size(), strcount(strm.str(), '\n')); + EXPECT_EQ(mutable_b.size(), strcount(strm.str(), '\n')); // Test range erase. mutable_b.erase(mutable_b.begin(), mutable_b.end()); - CHECK_EQ(mutable_b.size(), 0); + EXPECT_EQ(mutable_b.size(), 0); const_b.verify(); // First half. @@ -735,7 +748,7 @@ void DoTest(const char *name, T *b, const vector &values) { typename T::iterator mutable_iter_end = mutable_b.begin(); for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end; mutable_b.erase(mutable_b.begin(), mutable_iter_end); - CHECK_EQ(mutable_b.size(), values.size() - values.size() / 2); + EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2); const_b.verify(); // Second half. @@ -743,7 +756,7 @@ void DoTest(const char *name, T *b, const vector &values) { typename T::iterator mutable_iter_begin = mutable_b.begin(); for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin; mutable_b.erase(mutable_iter_begin, mutable_b.end()); - CHECK_EQ(mutable_b.size(), values.size() / 2); + EXPECT_EQ(mutable_b.size(), values.size() / 2); const_b.verify(); // Second quarter. @@ -753,7 +766,7 @@ void DoTest(const char *name, T *b, const vector &values) { mutable_iter_end = mutable_iter_begin; for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end; mutable_b.erase(mutable_iter_begin, mutable_iter_end); - CHECK_EQ(mutable_b.size(), values.size() - values.size() / 4); + EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4); const_b.verify(); mutable_b.clear(); @@ -770,62 +783,62 @@ void ConstTest() { // Insert a single value into the container and test looking it up. value_type value = Generator(2)(2); mutable_b.insert(value); - CHECK(mutable_b.find(key_of_value(value)) != const_b.end()); - CHECK(const_b.find(key_of_value(value)) != mutable_b.end()); - CHECK_EQ(*const_b.lower_bound(key_of_value(value)), value); - CHECK(const_b.upper_bound(key_of_value(value)) == const_b.end()); - CHECK_EQ(*const_b.equal_range(key_of_value(value)).first, value); + EXPECT_TRUE(mutable_b.find(key_of_value(value)) != const_b.end()); + EXPECT_TRUE(const_b.find(key_of_value(value)) != mutable_b.end()); + EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value); + EXPECT_TRUE(const_b.upper_bound(key_of_value(value)) == const_b.end()); + EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value); // We can only create a non-const iterator from a non-const container. typename T::iterator mutable_iter(mutable_b.begin()); - CHECK(mutable_iter == const_b.begin()); - CHECK(mutable_iter != const_b.end()); - CHECK(const_b.begin() == mutable_iter); - CHECK(const_b.end() != mutable_iter); + EXPECT_TRUE(mutable_iter == const_b.begin()); + EXPECT_TRUE(mutable_iter != const_b.end()); + EXPECT_TRUE(const_b.begin() == mutable_iter); + EXPECT_TRUE(const_b.end() != mutable_iter); typename T::reverse_iterator mutable_riter(mutable_b.rbegin()); - CHECK(mutable_riter == const_b.rbegin()); - CHECK(mutable_riter != const_b.rend()); - CHECK(const_b.rbegin() == mutable_riter); - CHECK(const_b.rend() != mutable_riter); + EXPECT_TRUE(mutable_riter == const_b.rbegin()); + EXPECT_TRUE(mutable_riter != const_b.rend()); + EXPECT_TRUE(const_b.rbegin() == mutable_riter); + EXPECT_TRUE(const_b.rend() != mutable_riter); // We can create a const iterator from a non-const iterator. typename T::const_iterator const_iter(mutable_iter); - CHECK(const_iter == mutable_b.begin()); - CHECK(const_iter != mutable_b.end()); - CHECK(mutable_b.begin() == const_iter); - CHECK(mutable_b.end() != const_iter); + EXPECT_TRUE(const_iter == mutable_b.begin()); + EXPECT_TRUE(const_iter != mutable_b.end()); + EXPECT_TRUE(mutable_b.begin() == const_iter); + EXPECT_TRUE(mutable_b.end() != const_iter); typename T::const_reverse_iterator const_riter(mutable_riter); - CHECK(const_riter == mutable_b.rbegin()); - CHECK(const_riter != mutable_b.rend()); - CHECK(mutable_b.rbegin() == const_riter); - CHECK(mutable_b.rend() != const_riter); + EXPECT_EQ(const_riter, mutable_b.rbegin()); + EXPECT_TRUE(const_riter != mutable_b.rend()); + EXPECT_EQ(mutable_b.rbegin(), const_riter); + EXPECT_TRUE(mutable_b.rend() != const_riter); // Make sure various methods can be invoked on a const container. const_b.verify(); - CHECK(!const_b.empty()); - CHECK_EQ(const_b.size(), 1); - CHECK_GT(const_b.max_size(), 0); - CHECK_EQ(const_b.height(), 1); - CHECK_EQ(const_b.count(key_of_value(value)), 1); - CHECK_EQ(const_b.internal_nodes(), 0); - CHECK_EQ(const_b.leaf_nodes(), 1); - CHECK_EQ(const_b.nodes(), 1); - CHECK_GT(const_b.bytes_used(), 0); - CHECK_GT(const_b.fullness(), 0); - CHECK_GT(const_b.overhead(), 0); + EXPECT_FALSE(const_b.empty()); + EXPECT_EQ(const_b.size(), 1); + EXPECT_GT(const_b.max_size(), 0); + EXPECT_EQ(const_b.height(), 1); + EXPECT_EQ(const_b.count(key_of_value(value)), 1); + EXPECT_EQ(const_b.internal_nodes(), 0); + EXPECT_EQ(const_b.leaf_nodes(), 1); + EXPECT_EQ(const_b.nodes(), 1); + EXPECT_GT(const_b.bytes_used(), 0); + EXPECT_GT(const_b.fullness(), 0); + EXPECT_GT(const_b.overhead(), 0); } template void BtreeTest() { ConstTest(); - typedef typename base::remove_const::type V; - vector random_values = GenerateValues(FLAGS_test_values); + typedef typename std::remove_const::type V; + std::vector random_values = GenerateValues(FLAGS_test_values); unique_checker container; // Test key insertion/deletion in sorted order. - vector sorted_values(random_values); + std::vector sorted_values(random_values); sort(sorted_values.begin(), sorted_values.end()); DoTest("sorted: ", &container, sorted_values); @@ -841,13 +854,13 @@ template void BtreeMultiTest() { ConstTest(); - typedef typename base::remove_const::type V; - const vector& random_values = GenerateValues(FLAGS_test_values); + typedef typename std::remove_const::type V; + const std::vector& random_values = GenerateValues(FLAGS_test_values); multi_checker container; // Test keys in sorted order. - vector sorted_values(random_values); + std::vector sorted_values(random_values); sort(sorted_values.begin(), sorted_values.end()); DoTest("sorted: ", &container, sorted_values); @@ -859,25 +872,64 @@ void BtreeMultiTest() { DoTest("random: ", &container, random_values); // Test keys in random order w/ duplicates. - vector duplicate_values(random_values); + std::vector duplicate_values(random_values); duplicate_values.insert( duplicate_values.end(), random_values.begin(), random_values.end()); DoTest("duplicates:", &container, duplicate_values); // Test all identical keys. - vector identical_values(100); + std::vector identical_values(100); fill(identical_values.begin(), identical_values.end(), Generator(2)(2)); DoTest("identical: ", &container, identical_values); } +template > +class TestAllocator : public Alloc { + public: + typedef typename Alloc::pointer pointer; + typedef typename Alloc::size_type size_type; + + TestAllocator() : bytes_used_(NULL) { } + TestAllocator(int64_t *bytes_used) : bytes_used_(bytes_used) { } + + // Constructor used for rebinding + template + TestAllocator(const TestAllocator& x) + : Alloc(x), + bytes_used_(x.bytes_used()) { + } + + pointer allocate(size_type n, std::allocator::const_pointer hint = 0) { + EXPECT_TRUE(bytes_used_ != NULL); + *bytes_used_ += n * sizeof(T); + return Alloc::allocate(n, hint); + } + + void deallocate(pointer p, size_type n) { + Alloc::deallocate(p, n); + EXPECT_TRUE(bytes_used_ != NULL); + *bytes_used_ -= n * sizeof(T); + } + + // Rebind allows an allocator to be used for a different type + template struct rebind { + typedef TestAllocator::other> other; + }; + + int64_t* bytes_used() const { return bytes_used_; } + + private: + int64_t *bytes_used_; +}; + template -void BtreeArenaTest() { +void BtreeAllocatorTest() { typedef typename T::value_type value_type; - UnsafeArena arena1(1000); - UnsafeArena arena2(1000); - T b1(typename T::key_compare(), &arena1); - T b2(typename T::key_compare(), &arena2); + int64_t alloc1 = 0; + int64_t alloc2 = 0; + T b1(typename T::key_compare(), &alloc1); + T b2(typename T::key_compare(), &alloc2); // This should swap the allocators! swap(b1, b2); @@ -886,9 +938,9 @@ void BtreeArenaTest() { b1.insert(Generator(1000)(i)); } - // We should have allocated out of arena2! - CHECK_LE(b1.bytes_used(), arena2.status().bytes_allocated()); - CHECK_GT(arena2.block_count(), arena1.block_count()); + // We should have allocated out of alloc2! + EXPECT_LE(b1.bytes_used(), alloc2 + sizeof(b1)); + EXPECT_GT(alloc2, alloc1); } template @@ -906,15 +958,15 @@ void BtreeMapTest() { value_type v = Generator(1000)(i); b[v.first] = v.second; } - CHECK_EQ(b.size(), 1000); + EXPECT_EQ(b.size(), 1000); // Test whether we can use the "->" operator on iterators and // reverse_iterators. This stresses the btree_map_params::pair_pointer // mechanism. - CHECK_EQ(b.begin()->first, Generator(1000)(0).first); - CHECK_EQ(b.begin()->second, Generator(1000)(0).second); - CHECK_EQ(b.rbegin()->first, Generator(1000)(999).first); - CHECK_EQ(b.rbegin()->second, Generator(1000)(999).second); + EXPECT_EQ(b.begin()->first, Generator(1000)(0).first); + EXPECT_EQ(b.begin()->second, Generator(1000)(0).second); + EXPECT_EQ(b.rbegin()->first, Generator(1000)(999).first); + EXPECT_EQ(b.rbegin()->second, Generator(1000)(999).second); } template @@ -925,6 +977,5 @@ void BtreeMultiMapTest() { } } // namespace btree -} // namespace util #endif // UTIL_BTREE_BTREE_TEST_H__ diff --git a/btree_test_flags.cc b/btree_test_flags.cc index 512c24e1..d43d9250 100644 --- a/btree_test_flags.cc +++ b/btree_test_flags.cc @@ -1,7 +1,7 @@ // Copyright 2007 Google Inc. All Rights Reserved. // Author: pmattis@google.com (Peter Mattis) -#include "base/commandlineflags.h" +#include "gflags/gflags.h" DEFINE_int32(test_values, 10000, "The number of values to use for tests."); diff --git a/safe_btree.h b/safe_btree.h index 2a354232..01cf9faf 100644 --- a/safe_btree.h +++ b/safe_btree.h @@ -21,11 +21,8 @@ #include #include -#include "base/integral_types.h" -#include "base/logging.h" -#include "util/btree/btree.h" +#include "btree.h" -namespace util { namespace btree { template @@ -77,7 +74,7 @@ class safe_btree_iterator { } Tree* tree() const { return tree_; } - int64 generation() const { return generation_; } + int64_t generation() const { return generation_; } Iterator* mutable_iter() const { if (generation_ != tree_->generation()) { @@ -114,13 +111,13 @@ class safe_btree_iterator { // This reference value is potentially invalidated by any non-const // method on the tree; it is NOT safe. reference operator*() const { - DCHECK_GT(generation_, 0); + assert(generation_ > 0); return iter().operator*(); } // This pointer value is potentially invalidated by any non-const // method on the tree; it is NOT safe. pointer operator->() const { - DCHECK_GT(generation_, 0); + assert(generation_ > 0); return iter().operator->(); } @@ -148,7 +145,7 @@ class safe_btree_iterator { private: // The generation of the tree when "iter" was updated. - mutable int64 generation_; + mutable int64_t generation_; // The key the iterator points to. mutable key_type key_; // The underlying iterator. @@ -236,14 +233,14 @@ class safe_btree { const_iterator upper_bound(const key_type &key) const { return const_iterator(this, tree_.upper_bound(key)); } - pair equal_range(const key_type &key) { - pair p = tree_.equal_range(key); - return make_pair(iterator(this, p.first), + std::pair equal_range(const key_type &key) { + std::pair p = tree_.equal_range(key); + return std::make_pair(iterator(this, p.first), iterator(this, p.second)); } - pair equal_range(const key_type &key) const { - pair p = tree_.equal_range(key); - return make_pair(const_iterator(this, p.first), + std::pair equal_range(const key_type &key) const { + std::pair p = tree_.equal_range(key); + return std::make_pair(const_iterator(this, p.first), const_iterator(this, p.second)); } iterator find_unique(const key_type &key) { @@ -267,15 +264,15 @@ class safe_btree { // Insertion routines. template - pair insert_unique(const key_type &key, ValuePointer value) { - pair p = tree_.insert_unique(key, value); + std::pair insert_unique(const key_type &key, ValuePointer value) { + std::pair p = tree_.insert_unique(key, value); generation_ += p.second; - return make_pair(iterator(this, p.first), p.second); + return std::make_pair(iterator(this, p.first), p.second); } - pair insert_unique(const value_type &v) { - pair p = tree_.insert_unique(v); + std::pair insert_unique(const value_type &v) { + std::pair p = tree_.insert_unique(v); generation_ += p.second; - return make_pair(iterator(this, p.first), p.second); + return std::make_pair(iterator(this, p.first), p.second); } iterator insert_unique(iterator position, const value_type &v) { tree_iterator tree_pos = position.iter(); @@ -351,13 +348,13 @@ class safe_btree { ++x.generation_; tree_.swap(x.tree_); } - void dump(ostream &os) const { + void dump(std::ostream &os) const { tree_.dump(os); } void verify() const { tree_.verify(); } - int64 generation() const { + int64_t generation() const { return generation_; } key_compare key_comp() const { return tree_.key_comp(); } @@ -379,10 +376,9 @@ class safe_btree { private: btree_type tree_; - int64 generation_; + int64_t generation_; }; } // namespace btree -} // namespace util #endif // UTIL_BTREE_SAFE_BTREE_H__ diff --git a/safe_btree_map.h b/safe_btree_map.h index 11274930..b8aa787e 100644 --- a/safe_btree_map.h +++ b/safe_btree_map.h @@ -22,17 +22,16 @@ #include #include -#include "util/btree/btree_container.h" -#include "util/btree/btree_map.h" -#include "util/btree/safe_btree.h" +#include "btree_container.h" +#include "btree_map.h" +#include "safe_btree.h" -namespace util { namespace btree { // The safe_btree_map class is needed mainly for its constructors. template , - typename Alloc = std::allocator >, + typename Compare = std::less, + typename Alloc = std::allocator >, int TargetNodeSize = 256> class safe_btree_map : public btree_map_container< safe_btree > > { @@ -75,6 +74,5 @@ inline void swap(safe_btree_map &x, } } // namespace btree -} // namespace util #endif // UTIL_BTREE_SAFE_BTREE_MAP_H__ diff --git a/safe_btree_set.h b/safe_btree_set.h index 72ed2d91..de8f823a 100644 --- a/safe_btree_set.h +++ b/safe_btree_set.h @@ -22,16 +22,15 @@ #include #include -#include "util/btree/btree_container.h" -#include "util/btree/btree_set.h" -#include "util/btree/safe_btree.h" +#include "btree_container.h" +#include "btree_set.h" +#include "safe_btree.h" -namespace util { namespace btree { // The safe_btree_set class is needed mainly for its constructors. template , + typename Compare = std::less, typename Alloc = std::allocator, int TargetNodeSize = 256> class safe_btree_set : public btree_unique_container< @@ -74,6 +73,5 @@ inline void swap(safe_btree_set &x, } } // namespace btree -} // namespace util #endif // UTIL_BTREE_SAFE_BTREE_SET_H__ diff --git a/safe_btree_test.cc b/safe_btree_test.cc index cf179b28..4965916b 100644 --- a/safe_btree_test.cc +++ b/safe_btree_test.cc @@ -11,58 +11,50 @@ #include #include -#include "base/arena-inl.h" -#include "base/init_google.h" -#include "base/integral_types.h" -#include "base/logging.h" -#include "strings/cord.h" -#include "testing/base/public/gunit.h" -#include "util/btree/btree_test.h" -#include "util/btree/safe_btree_map.h" -#include "util/btree/safe_btree_set.h" +#include "gtest/gtest.h" +#include "btree_test.h" +#include "safe_btree_map.h" +#include "safe_btree_set.h" class UnsafeArena; -namespace util { namespace btree { namespace { template void SetTest() { - typedef ArenaAllocator ArenaAlloc; - BtreeTest, allocator, N>, set >(); - BtreeArenaTest, ArenaAlloc, N> >(); + typedef TestAllocator TestAlloc; + BtreeTest, std::allocator, N>, std::set >(); + BtreeAllocatorTest, TestAlloc, N> >(); } template void MapTest() { - typedef ArenaAllocator ArenaAlloc; - BtreeTest, allocator, N>, map >(); - BtreeArenaTest, ArenaAlloc, N> >(); - BtreeMapTest, allocator, N> >(); + typedef TestAllocator TestAlloc; + BtreeTest, std::allocator, N>, std::map >(); + BtreeAllocatorTest, TestAlloc, N> >(); + BtreeMapTest, std::allocator, N> >(); } -TEST(SafeBtree, set_int32_32) { SetTest(); } -TEST(SafeBtree, set_int32_64) { SetTest(); } -TEST(SafeBtree, set_int32_128) { SetTest(); } -TEST(SafeBtree, set_int32_256) { SetTest(); } -TEST(SafeBtree, set_int64_256) { SetTest(); } -TEST(SafeBtree, set_string_256) { SetTest(); } -TEST(SafeBtree, set_cord_256) { SetTest(); } -TEST(SafeBtree, set_pair_256) { SetTest, 256>(); } -TEST(SafeBtree, map_int32_256) { MapTest(); } -TEST(SafeBtree, map_int64_256) { MapTest(); } -TEST(SafeBtree, map_string_256) { MapTest(); } -TEST(SafeBtree, map_cord_256) { MapTest(); } -TEST(SafeBtree, map_pair_256) { MapTest, 256>(); } +TEST(SafeBtree, set_int32_32) { SetTest(); } +TEST(SafeBtree, set_int32_64) { SetTest(); } +TEST(SafeBtree, set_int32_128) { SetTest(); } +TEST(SafeBtree, set_int32_256) { SetTest(); } +TEST(SafeBtree, set_int64_256) { SetTest(); } +TEST(SafeBtree, set_string_256) { SetTest(); } +TEST(SafeBtree, set_pair_256) { SetTest, 256>(); } +TEST(SafeBtree, map_int32_256) { MapTest(); } +TEST(SafeBtree, map_int64_256) { MapTest(); } +TEST(SafeBtree, map_string_256) { MapTest(); } +TEST(SafeBtree, map_pair_256) { MapTest, 256>(); } TEST(SafeBtree, Comparison) { const int kSetSize = 1201; - safe_btree_set my_set; + safe_btree_set my_set; for (int i = 0; i < kSetSize; ++i) { my_set.insert(i); } - safe_btree_set my_set_copy(my_set); + safe_btree_set my_set_copy(my_set); EXPECT_TRUE(my_set_copy == my_set); EXPECT_TRUE(my_set == my_set_copy); EXPECT_FALSE(my_set_copy != my_set); @@ -80,17 +72,17 @@ TEST(SafeBtree, Comparison) { EXPECT_TRUE(my_set_copy != my_set); EXPECT_TRUE(my_set != my_set_copy); - safe_btree_map my_map; + safe_btree_map my_map; for (int i = 0; i < kSetSize; ++i) { - my_map[string(i, 'a')] = i; + my_map[std::string(i, 'a')] = i; } - safe_btree_map my_map_copy(my_map); + safe_btree_map my_map_copy(my_map); EXPECT_TRUE(my_map_copy == my_map); EXPECT_TRUE(my_map == my_map_copy); EXPECT_FALSE(my_map_copy != my_map); EXPECT_FALSE(my_map != my_map_copy); - ++my_map_copy[string(7, 'a')]; + ++my_map_copy[std::string(7, 'a')]; EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); @@ -103,7 +95,7 @@ TEST(SafeBtree, Comparison) { EXPECT_TRUE(my_map_copy != my_map); EXPECT_TRUE(my_map != my_map_copy); - my_map.erase(string(kSetSize - 1, 'a')); + my_map.erase(std::string(kSetSize - 1, 'a')); EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); @@ -112,10 +104,3 @@ TEST(SafeBtree, Comparison) { } // namespace } // namespace btree -} // namespace util - -int main(int argc, char **argv) { - FLAGS_logtostderr = true; - InitGoogle(argv[0], &argc, &argv, true); - return RUN_ALL_TESTS(); -}