summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh MacDonald <josh.macdonald@gmail.com>2014-11-01 00:13:18 -0700
committerJosh MacDonald <josh.macdonald@gmail.com>2014-11-01 00:13:18 -0700
commit336445673c60b7c05b015114077f49493f18e7f4 (patch)
tree844bb336d19e65c517109987e2daa39d038f3224
parent9d4f55040311a16b32973b284e9cdfdf843ddf66 (diff)
Checksum test under development
-rw-r--r--xdelta3/cpp-btree/CMakeLists.txt40
-rw-r--r--xdelta3/cpp-btree/COPYING202
-rw-r--r--xdelta3/cpp-btree/README31
-rw-r--r--xdelta3/cpp-btree/btree.h2394
-rw-r--r--xdelta3/cpp-btree/btree_bench.cc593
-rw-r--r--xdelta3/cpp-btree/btree_container.h349
-rw-r--r--xdelta3/cpp-btree/btree_map.h130
-rw-r--r--xdelta3/cpp-btree/btree_set.h121
-rw-r--r--xdelta3/cpp-btree/btree_test.cc270
-rw-r--r--xdelta3/cpp-btree/btree_test.h940
-rw-r--r--xdelta3/cpp-btree/btree_test_flags.cc20
-rw-r--r--xdelta3/cpp-btree/safe_btree.h395
-rw-r--r--xdelta3/cpp-btree/safe_btree_map.h89
-rw-r--r--xdelta3/cpp-btree/safe_btree_set.h88
-rw-r--r--xdelta3/cpp-btree/safe_btree_test.cc116
-rwxr-xr-xxdelta3/run_release.sh9
-rw-r--r--xdelta3/testing/checksum_test.cc31
17 files changed, 5798 insertions, 20 deletions
diff --git a/xdelta3/cpp-btree/CMakeLists.txt b/xdelta3/cpp-btree/CMakeLists.txt
new file mode 100644
index 0000000..d005e15
--- /dev/null
+++ b/xdelta3/cpp-btree/CMakeLists.txt
@@ -0,0 +1,40 @@
1# Copyright 2013 Google Inc. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15cmake_minimum_required(VERSION 2.6)
16
17project(cppbtree CXX)
18
19option(build_tests "Build B-tree tests" OFF)
20add_definitions(-std=c++11)
21set(CMAKE_CXX_FLAGS "-g -O2")
22
23# CMake doesn't have a way to pure template library,
24# add_library(cppbtree btree.h btree_map.h btree_set.h
25# safe_btree.h safe_btree_map.h safe_btree_set.h)
26# set_target_properties(cppbtree PROPERTIES LINKER_LANGUAGE CXX)
27
28if(build_tests)
29 enable_testing()
30 include_directories($ENV{GTEST_ROOT}/include)
31 link_directories($ENV{GTEST_ROOT})
32 include_directories($ENV{GFLAGS_ROOT}/include)
33 link_directories($ENV{GFLAGS_ROOT}/lib)
34 add_executable(btree_test btree_test.cc btree_test_flags.cc)
35 add_executable(safe_btree_test safe_btree_test.cc btree_test_flags.cc)
36 add_executable(btree_bench btree_bench.cc btree_test_flags.cc)
37 target_link_libraries(btree_test gtest_main gtest gflags)
38 target_link_libraries(safe_btree_test gtest_main gtest gflags)
39 target_link_libraries(btree_bench gflags gtest)
40endif()
diff --git a/xdelta3/cpp-btree/COPYING b/xdelta3/cpp-btree/COPYING
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/xdelta3/cpp-btree/COPYING
@@ -0,0 +1,202 @@
1
2 Apache License
3 Version 2.0, January 2004
4 http://www.apache.org/licenses/
5
6 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8 1. Definitions.
9
10 "License" shall mean the terms and conditions for use, reproduction,
11 and distribution as defined by Sections 1 through 9 of this document.
12
13 "Licensor" shall mean the copyright owner or entity authorized by
14 the copyright owner that is granting the License.
15
16 "Legal Entity" shall mean the union of the acting entity and all
17 other entities that control, are controlled by, or are under common
18 control with that entity. For the purposes of this definition,
19 "control" means (i) the power, direct or indirect, to cause the
20 direction or management of such entity, whether by contract or
21 otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 outstanding shares, or (iii) beneficial ownership of such entity.
23
24 "You" (or "Your") shall mean an individual or Legal Entity
25 exercising permissions granted by this License.
26
27 "Source" form shall mean the preferred form for making modifications,
28 including but not limited to software source code, documentation
29 source, and configuration files.
30
31 "Object" form shall mean any form resulting from mechanical
32 transformation or translation of a Source form, including but
33 not limited to compiled object code, generated documentation,
34 and conversions to other media types.
35
36 "Work" shall mean the work of authorship, whether in Source or
37 Object form, made available under the License, as indicated by a
38 copyright notice that is included in or attached to the work
39 (an example is provided in the Appendix below).
40
41 "Derivative Works" shall mean any work, whether in Source or Object
42 form, that is based on (or derived from) the Work and for which the
43 editorial revisions, annotations, elaborations, or other modifications
44 represent, as a whole, an original work of authorship. For the purposes
45 of this License, Derivative Works shall not include works that remain
46 separable from, or merely link (or bind by name) to the interfaces of,
47 the Work and Derivative Works thereof.
48
49 "Contribution" shall mean any work of authorship, including
50 the original version of the Work and any modifications or additions
51 to that Work or Derivative Works thereof, that is intentionally
52 submitted to Licensor for inclusion in the Work by the copyright owner
53 or by an individual or Legal Entity authorized to submit on behalf of
54 the copyright owner. For the purposes of this definition, "submitted"
55 means any form of electronic, verbal, or written communication sent
56 to the Licensor or its representatives, including but not limited to
57 communication on electronic mailing lists, source code control systems,
58 and issue tracking systems that are managed by, or on behalf of, the
59 Licensor for the purpose of discussing and improving the Work, but
60 excluding communication that is conspicuously marked or otherwise
61 designated in writing by the copyright owner as "Not a Contribution."
62
63 "Contributor" shall mean Licensor and any individual or Legal Entity
64 on behalf of whom a Contribution has been received by Licensor and
65 subsequently incorporated within the Work.
66
67 2. Grant of Copyright License. Subject to the terms and conditions of
68 this License, each Contributor hereby grants to You a perpetual,
69 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 copyright license to reproduce, prepare Derivative Works of,
71 publicly display, publicly perform, sublicense, and distribute the
72 Work and such Derivative Works in Source or Object form.
73
74 3. Grant of Patent License. Subject to the terms and conditions of
75 this License, each Contributor hereby grants to You a perpetual,
76 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 (except as stated in this section) patent license to make, have made,
78 use, offer to sell, sell, import, and otherwise transfer the Work,
79 where such license applies only to those patent claims licensable
80 by such Contributor that are necessarily infringed by their
81 Contribution(s) alone or by combination of their Contribution(s)
82 with the Work to which such Contribution(s) was submitted. If You
83 institute patent litigation against any entity (including a
84 cross-claim or counterclaim in a lawsuit) alleging that the Work
85 or a Contribution incorporated within the Work constitutes direct
86 or contributory patent infringement, then any patent licenses
87 granted to You under this License for that Work shall terminate
88 as of the date such litigation is filed.
89
90 4. Redistribution. You may reproduce and distribute copies of the
91 Work or Derivative Works thereof in any medium, with or without
92 modifications, and in Source or Object form, provided that You
93 meet the following conditions:
94
95 (a) You must give any other recipients of the Work or
96 Derivative Works a copy of this License; and
97
98 (b) You must cause any modified files to carry prominent notices
99 stating that You changed the files; and
100
101 (c) You must retain, in the Source form of any Derivative Works
102 that You distribute, all copyright, patent, trademark, and
103 attribution notices from the Source form of the Work,
104 excluding those notices that do not pertain to any part of
105 the Derivative Works; and
106
107 (d) If the Work includes a "NOTICE" text file as part of its
108 distribution, then any Derivative Works that You distribute must
109 include a readable copy of the attribution notices contained
110 within such NOTICE file, excluding those notices that do not
111 pertain to any part of the Derivative Works, in at least one
112 of the following places: within a NOTICE text file distributed
113 as part of the Derivative Works; within the Source form or
114 documentation, if provided along with the Derivative Works; or,
115 within a display generated by the Derivative Works, if and
116 wherever such third-party notices normally appear. The contents
117 of the NOTICE file are for informational purposes only and
118 do not modify the License. You may add Your own attribution
119 notices within Derivative Works that You distribute, alongside
120 or as an addendum to the NOTICE text from the Work, provided
121 that such additional attribution notices cannot be construed
122 as modifying the License.
123
124 You may add Your own copyright statement to Your modifications and
125 may provide additional or different license terms and conditions
126 for use, reproduction, or distribution of Your modifications, or
127 for any such Derivative Works as a whole, provided Your use,
128 reproduction, and distribution of the Work otherwise complies with
129 the conditions stated in this License.
130
131 5. Submission of Contributions. Unless You explicitly state otherwise,
132 any Contribution intentionally submitted for inclusion in the Work
133 by You to the Licensor shall be under the terms and conditions of
134 this License, without any additional terms or conditions.
135 Notwithstanding the above, nothing herein shall supersede or modify
136 the terms of any separate license agreement you may have executed
137 with Licensor regarding such Contributions.
138
139 6. Trademarks. This License does not grant permission to use the trade
140 names, trademarks, service marks, or product names of the Licensor,
141 except as required for reasonable and customary use in describing the
142 origin of the Work and reproducing the content of the NOTICE file.
143
144 7. Disclaimer of Warranty. Unless required by applicable law or
145 agreed to in writing, Licensor provides the Work (and each
146 Contributor provides its Contributions) on an "AS IS" BASIS,
147 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 implied, including, without limitation, any warranties or conditions
149 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 PARTICULAR PURPOSE. You are solely responsible for determining the
151 appropriateness of using or redistributing the Work and assume any
152 risks associated with Your exercise of permissions under this License.
153
154 8. Limitation of Liability. In no event and under no legal theory,
155 whether in tort (including negligence), contract, or otherwise,
156 unless required by applicable law (such as deliberate and grossly
157 negligent acts) or agreed to in writing, shall any Contributor be
158 liable to You for damages, including any direct, indirect, special,
159 incidental, or consequential damages of any character arising as a
160 result of this License or out of the use or inability to use the
161 Work (including but not limited to damages for loss of goodwill,
162 work stoppage, computer failure or malfunction, or any and all
163 other commercial damages or losses), even if such Contributor
164 has been advised of the possibility of such damages.
165
166 9. Accepting Warranty or Additional Liability. While redistributing
167 the Work or Derivative Works thereof, You may choose to offer,
168 and charge a fee for, acceptance of support, warranty, indemnity,
169 or other liability obligations and/or rights consistent with this
170 License. However, in accepting such obligations, You may act only
171 on Your own behalf and on Your sole responsibility, not on behalf
172 of any other Contributor, and only if You agree to indemnify,
173 defend, and hold each Contributor harmless for any liability
174 incurred by, or claims asserted against, such Contributor by reason
175 of your accepting any such warranty or additional liability.
176
177 END OF TERMS AND CONDITIONS
178
179 APPENDIX: How to apply the Apache License to your work.
180
181 To apply the Apache License to your work, attach the following
182 boilerplate notice, with the fields enclosed by brackets "[]"
183 replaced with your own identifying information. (Don't include
184 the brackets!) The text should be enclosed in the appropriate
185 comment syntax for the file format. We also recommend that a
186 file or class name and description of purpose be included on the
187 same "printed page" as the copyright notice for easier
188 identification within third-party archives.
189
190 Copyright [yyyy] [name of copyright owner]
191
192 Licensed under the Apache License, Version 2.0 (the "License");
193 you may not use this file except in compliance with the License.
194 You may obtain a copy of the License at
195
196 http://www.apache.org/licenses/LICENSE-2.0
197
198 Unless required by applicable law or agreed to in writing, software
199 distributed under the License is distributed on an "AS IS" BASIS,
200 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 See the License for the specific language governing permissions and
202 limitations under the License.
diff --git a/xdelta3/cpp-btree/README b/xdelta3/cpp-btree/README
new file mode 100644
index 0000000..319fe9b
--- /dev/null
+++ b/xdelta3/cpp-btree/README
@@ -0,0 +1,31 @@
1This library is a C++ template library and, as such, there is no
2library to build and install. Copy the .h files and use them!
3
4See http://code.google.com/p/cpp-btree/wiki/UsageInstructions for
5details.
6
7----
8
9To build and run the provided tests, however, you will need to install
10CMake, the Google C++ Test framework, and the Google flags package.
11
12Download and install CMake from http://www.cmake.org
13
14Download and build the GoogleTest framework from
15http://code.google.com/p/googletest
16
17Download and install gflags from https://code.google.com/p/gflags
18
19Set GTEST_ROOT to the directory where GTEST was built.
20Set GFLAGS_ROOT to the directory prefix where GFLAGS is installed.
21
22export GTEST_ROOT=/path/for/gtest-x.y
23export GFLAGS_ROOT=/opt
24
25cmake . -Dbuild_tests=ON
26
27For example, to build on a Unix system with the clang++ compiler,
28
29export GTEST_ROOT=$(HOME)/src/googletest
30export GFLAGS_ROOT=/opt
31cmake . -G "Unix Makefiles" -Dbuild_tests=ON -DCMAKE_CXX_COMPILER=clang++
diff --git a/xdelta3/cpp-btree/btree.h b/xdelta3/cpp-btree/btree.h
new file mode 100644
index 0000000..cdd2b52
--- /dev/null
+++ b/xdelta3/cpp-btree/btree.h
@@ -0,0 +1,2394 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// A btree implementation of the STL set and map interfaces. A btree is both
16// smaller and faster than STL set/map. The red-black tree implementation of
17// STL set/map has an overhead of 3 pointers (left, right and parent) plus the
18// node color information for each stored value. So a set<int32> consumes 20
19// bytes for each value stored. This btree implementation stores multiple
20// values on fixed size nodes (usually 256 bytes) and doesn't store child
21// pointers for leaf nodes. The result is that a btree_set<int32> may use much
22// less memory per stored value. For the random insertion benchmark in
23// btree_test.cc, a btree_set<int32> with node-size of 256 uses 4.9 bytes per
24// stored value.
25//
26// The packing of multiple values on to each node of a btree has another effect
27// besides better space utilization: better cache locality due to fewer cache
28// lines being accessed. Better cache locality translates into faster
29// operations.
30//
31// CAVEATS
32//
33// Insertions and deletions on a btree can cause splitting, merging or
34// rebalancing of btree nodes. And even without these operations, insertions
35// and deletions on a btree will move values around within a node. In both
36// cases, the result is that insertions and deletions can invalidate iterators
37// pointing to values other than the one being inserted/deleted. This is
38// notably different from STL set/map which takes care to not invalidate
39// iterators on insert/erase except, of course, for iterators pointing to the
40// value being erased. A partial workaround when erasing is available:
41// erase() returns an iterator pointing to the item just after the one that was
42// erased (or end() if none exists). See also safe_btree.
43
44// PERFORMANCE
45//
46// btree_bench --benchmarks=. 2>&1 | ./benchmarks.awk
47//
48// Run on pmattis-warp.nyc (4 X 2200 MHz CPUs); 2010/03/04-15:23:06
49// Benchmark STL(ns) B-Tree(ns) @ <size>
50// --------------------------------------------------------
51// BM_set_int32_insert 1516 608 +59.89% <256> [40.0, 5.2]
52// BM_set_int32_lookup 1160 414 +64.31% <256> [40.0, 5.2]
53// BM_set_int32_fulllookup 960 410 +57.29% <256> [40.0, 4.4]
54// BM_set_int32_delete 1741 528 +69.67% <256> [40.0, 5.2]
55// BM_set_int32_queueaddrem 3078 1046 +66.02% <256> [40.0, 5.5]
56// BM_set_int32_mixedaddrem 3600 1384 +61.56% <256> [40.0, 5.3]
57// BM_set_int32_fifo 227 113 +50.22% <256> [40.0, 4.4]
58// BM_set_int32_fwditer 158 26 +83.54% <256> [40.0, 5.2]
59// BM_map_int32_insert 1551 636 +58.99% <256> [48.0, 10.5]
60// BM_map_int32_lookup 1200 508 +57.67% <256> [48.0, 10.5]
61// BM_map_int32_fulllookup 989 487 +50.76% <256> [48.0, 8.8]
62// BM_map_int32_delete 1794 628 +64.99% <256> [48.0, 10.5]
63// BM_map_int32_queueaddrem 3189 1266 +60.30% <256> [48.0, 11.6]
64// BM_map_int32_mixedaddrem 3822 1623 +57.54% <256> [48.0, 10.9]
65// BM_map_int32_fifo 151 134 +11.26% <256> [48.0, 8.8]
66// BM_map_int32_fwditer 161 32 +80.12% <256> [48.0, 10.5]
67// BM_set_int64_insert 1546 636 +58.86% <256> [40.0, 10.5]
68// BM_set_int64_lookup 1200 512 +57.33% <256> [40.0, 10.5]
69// BM_set_int64_fulllookup 971 487 +49.85% <256> [40.0, 8.8]
70// BM_set_int64_delete 1745 616 +64.70% <256> [40.0, 10.5]
71// BM_set_int64_queueaddrem 3163 1195 +62.22% <256> [40.0, 11.6]
72// BM_set_int64_mixedaddrem 3760 1564 +58.40% <256> [40.0, 10.9]
73// BM_set_int64_fifo 146 103 +29.45% <256> [40.0, 8.8]
74// BM_set_int64_fwditer 162 31 +80.86% <256> [40.0, 10.5]
75// BM_map_int64_insert 1551 720 +53.58% <256> [48.0, 20.7]
76// BM_map_int64_lookup 1214 612 +49.59% <256> [48.0, 20.7]
77// BM_map_int64_fulllookup 994 592 +40.44% <256> [48.0, 17.2]
78// BM_map_int64_delete 1778 764 +57.03% <256> [48.0, 20.7]
79// BM_map_int64_queueaddrem 3189 1547 +51.49% <256> [48.0, 20.9]
80// BM_map_int64_mixedaddrem 3779 1887 +50.07% <256> [48.0, 21.6]
81// BM_map_int64_fifo 147 145 +1.36% <256> [48.0, 17.2]
82// BM_map_int64_fwditer 162 41 +74.69% <256> [48.0, 20.7]
83// BM_set_string_insert 1989 1966 +1.16% <256> [64.0, 44.5]
84// BM_set_string_lookup 1709 1600 +6.38% <256> [64.0, 44.5]
85// BM_set_string_fulllookup 1573 1529 +2.80% <256> [64.0, 35.4]
86// BM_set_string_delete 2520 1920 +23.81% <256> [64.0, 44.5]
87// BM_set_string_queueaddrem 4706 4309 +8.44% <256> [64.0, 48.3]
88// BM_set_string_mixedaddrem 5080 4654 +8.39% <256> [64.0, 46.7]
89// BM_set_string_fifo 318 512 -61.01% <256> [64.0, 35.4]
90// BM_set_string_fwditer 182 93 +48.90% <256> [64.0, 44.5]
91// BM_map_string_insert 2600 2227 +14.35% <256> [72.0, 55.8]
92// BM_map_string_lookup 2068 1730 +16.34% <256> [72.0, 55.8]
93// BM_map_string_fulllookup 1859 1618 +12.96% <256> [72.0, 44.0]
94// BM_map_string_delete 3168 2080 +34.34% <256> [72.0, 55.8]
95// BM_map_string_queueaddrem 5840 4701 +19.50% <256> [72.0, 59.4]
96// BM_map_string_mixedaddrem 6400 5200 +18.75% <256> [72.0, 57.8]
97// BM_map_string_fifo 398 596 -49.75% <256> [72.0, 44.0]
98// BM_map_string_fwditer 243 113 +53.50% <256> [72.0, 55.8]
99
100#ifndef UTIL_BTREE_BTREE_H__
101#define UTIL_BTREE_BTREE_H__
102
103#include <assert.h>
104#include <stddef.h>
105#include <string.h>
106#include <sys/types.h>
107#include <algorithm>
108#include <functional>
109#include <iostream>
110#include <iterator>
111#include <limits>
112#include <type_traits>
113#include <new>
114#include <ostream>
115#include <string>
116#include <utility>
117
118#ifndef NDEBUG
119#define NDEBUG 1
120#endif
121
122namespace btree {
123
124// Inside a btree method, if we just call swap(), it will choose the
125// btree::swap method, which we don't want. And we can't say ::swap
126// because then MSVC won't pickup any std::swap() implementations. We
127// can't just use std::swap() directly because then we don't get the
128// specialization for types outside the std namespace. So the solution
129// is to have a special swap helper function whose name doesn't
130// collide with other swap functions defined by the btree classes.
131template <typename T>
132inline void btree_swap_helper(T &a, T &b) {
133 using std::swap;
134 swap(a, b);
135}
136
137// A template helper used to select A or B based on a condition.
138template<bool cond, typename A, typename B>
139struct if_{
140 typedef A type;
141};
142
143template<typename A, typename B>
144struct if_<false, A, B> {
145 typedef B type;
146};
147
148// Types small_ and big_ are promise that sizeof(small_) < sizeof(big_)
149typedef char small_;
150
151struct big_ {
152 char dummy[2];
153};
154
155// A compile-time assertion.
156template <bool>
157struct CompileAssert {
158};
159
160#define COMPILE_ASSERT(expr, msg) \
161 typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
162
163// A helper type used to indicate that a key-compare-to functor has been
164// provided. A user can specify a key-compare-to functor by doing:
165//
166// struct MyStringComparer
167// : public util::btree::btree_key_compare_to_tag {
168// int operator()(const string &a, const string &b) const {
169// return a.compare(b);
170// }
171// };
172//
173// Note that the return type is an int and not a bool. There is a
174// COMPILE_ASSERT which enforces this return type.
175struct btree_key_compare_to_tag {
176};
177
178// A helper class that indicates if the Compare parameter is derived from
179// btree_key_compare_to_tag.
180template <typename Compare>
181struct btree_is_key_compare_to
182 : public std::is_convertible<Compare, btree_key_compare_to_tag> {
183};
184
185// A helper class to convert a boolean comparison into a three-way
186// "compare-to" comparison that returns a negative value to indicate
187// less-than, zero to indicate equality and a positive value to
188// indicate greater-than. This helper class is specialized for
189// less<string> and greater<string>. The btree_key_compare_to_adapter
190// class is provided so that btree users automatically get the more
191// efficient compare-to code when using common google string types
192// with common comparison functors.
193template <typename Compare>
194struct btree_key_compare_to_adapter : Compare {
195 btree_key_compare_to_adapter() { }
196 btree_key_compare_to_adapter(const Compare &c) : Compare(c) { }
197 btree_key_compare_to_adapter(const btree_key_compare_to_adapter<Compare> &c)
198 : Compare(c) {
199 }
200};
201
202template <>
203struct btree_key_compare_to_adapter<std::less<std::string> >
204 : public btree_key_compare_to_tag {
205 btree_key_compare_to_adapter() {}
206 btree_key_compare_to_adapter(const std::less<std::string>&) {}
207 btree_key_compare_to_adapter(
208 const btree_key_compare_to_adapter<std::less<std::string> >&) {}
209 int operator()(const std::string &a, const std::string &b) const {
210 return a.compare(b);
211 }
212};
213
214template <>
215struct btree_key_compare_to_adapter<std::greater<std::string> >
216 : public btree_key_compare_to_tag {
217 btree_key_compare_to_adapter() {}
218 btree_key_compare_to_adapter(const std::greater<std::string>&) {}
219 btree_key_compare_to_adapter(
220 const btree_key_compare_to_adapter<std::greater<std::string> >&) {}
221 int operator()(const std::string &a, const std::string &b) const {
222 return b.compare(a);
223 }
224};
225
226// A helper class that allows a compare-to functor to behave like a plain
227// compare functor. This specialization is used when we do not have a
228// compare-to functor.
229template <typename Key, typename Compare, bool HaveCompareTo>
230struct btree_key_comparer {
231 btree_key_comparer() {}
232 btree_key_comparer(Compare c) : comp(c) {}
233 static bool bool_compare(const Compare &comp, const Key &x, const Key &y) {
234 return comp(x, y);
235 }
236 bool operator()(const Key &x, const Key &y) const {
237 return bool_compare(comp, x, y);
238 }
239 Compare comp;
240};
241
242// A specialization of btree_key_comparer when a compare-to functor is
243// present. We need a plain (boolean) comparison in some parts of the btree
244// code, such as insert-with-hint.
245template <typename Key, typename Compare>
246struct btree_key_comparer<Key, Compare, true> {
247 btree_key_comparer() {}
248 btree_key_comparer(Compare c) : comp(c) {}
249 static bool bool_compare(const Compare &comp, const Key &x, const Key &y) {
250 return comp(x, y) < 0;
251 }
252 bool operator()(const Key &x, const Key &y) const {
253 return bool_compare(comp, x, y);
254 }
255 Compare comp;
256};
257
258// A helper function to compare to keys using the specified compare
259// functor. This dispatches to the appropriate btree_key_comparer comparison,
260// depending on whether we have a compare-to functor or not (which depends on
261// whether Compare is derived from btree_key_compare_to_tag).
262template <typename Key, typename Compare>
263static bool btree_compare_keys(
264 const Compare &comp, const Key &x, const Key &y) {
265 typedef btree_key_comparer<Key, Compare,
266 btree_is_key_compare_to<Compare>::value> key_comparer;
267 return key_comparer::bool_compare(comp, x, y);
268}
269
270template <typename Key, typename Compare,
271 typename Alloc, int TargetNodeSize, int ValueSize>
272struct btree_common_params {
273 // If Compare is derived from btree_key_compare_to_tag then use it as the
274 // key_compare type. Otherwise, use btree_key_compare_to_adapter<> which will
275 // fall-back to Compare if we don't have an appropriate specialization.
276 typedef typename if_<
277 btree_is_key_compare_to<Compare>::value,
278 Compare, btree_key_compare_to_adapter<Compare> >::type key_compare;
279 // A type which indicates if we have a key-compare-to functor or a plain old
280 // key-compare functor.
281 typedef btree_is_key_compare_to<key_compare> is_key_compare_to;
282
283 typedef Alloc allocator_type;
284 typedef Key key_type;
285 typedef ssize_t size_type;
286 typedef ptrdiff_t difference_type;
287
288 enum {
289 kTargetNodeSize = TargetNodeSize,
290
291 // Available space for values. This is largest for leaf nodes,
292 // which has overhead no fewer than two pointers.
293 kNodeValueSpace = TargetNodeSize - 2 * sizeof(void*),
294 };
295
296 // This is an integral type large enough to hold as many
297 // ValueSize-values as will fit a node of TargetNodeSize bytes.
298 typedef typename if_<
299 (kNodeValueSpace / ValueSize) >= 256,
300 uint16_t,
301 uint8_t>::type node_count_type;
302};
303
304// A parameters structure for holding the type parameters for a btree_map.
305template <typename Key, typename Data, typename Compare,
306 typename Alloc, int TargetNodeSize>
307struct btree_map_params
308 : public btree_common_params<Key, Compare, Alloc, TargetNodeSize,
309 sizeof(Key) + sizeof(Data)> {
310 typedef Data data_type;
311 typedef Data mapped_type;
312 typedef std::pair<const Key, data_type> value_type;
313 typedef std::pair<Key, data_type> mutable_value_type;
314 typedef value_type* pointer;
315 typedef const value_type* const_pointer;
316 typedef value_type& reference;
317 typedef const value_type& const_reference;
318
319 enum {
320 kValueSize = sizeof(Key) + sizeof(data_type),
321 };
322
323 static const Key& key(const value_type &x) { return x.first; }
324 static const Key& key(const mutable_value_type &x) { return x.first; }
325 static void swap(mutable_value_type *a, mutable_value_type *b) {
326 btree_swap_helper(a->first, b->first);
327 btree_swap_helper(a->second, b->second);
328 }
329};
330
331// A parameters structure for holding the type parameters for a btree_set.
332template <typename Key, typename Compare, typename Alloc, int TargetNodeSize>
333struct btree_set_params
334 : public btree_common_params<Key, Compare, Alloc, TargetNodeSize,
335 sizeof(Key)> {
336 typedef std::false_type data_type;
337 typedef std::false_type mapped_type;
338 typedef Key value_type;
339 typedef value_type mutable_value_type;
340 typedef value_type* pointer;
341 typedef const value_type* const_pointer;
342 typedef value_type& reference;
343 typedef const value_type& const_reference;
344
345 enum {
346 kValueSize = sizeof(Key),
347 };
348
349 static const Key& key(const value_type &x) { return x; }
350 static void swap(mutable_value_type *a, mutable_value_type *b) {
351 btree_swap_helper<mutable_value_type>(*a, *b);
352 }
353};
354
355// An adapter class that converts a lower-bound compare into an upper-bound
356// compare.
357template <typename Key, typename Compare>
358struct btree_upper_bound_adapter : public Compare {
359 btree_upper_bound_adapter(Compare c) : Compare(c) {}
360 bool operator()(const Key &a, const Key &b) const {
361 return !static_cast<const Compare&>(*this)(b, a);
362 }
363};
364
365template <typename Key, typename CompareTo>
366struct btree_upper_bound_compare_to_adapter : public CompareTo {
367 btree_upper_bound_compare_to_adapter(CompareTo c) : CompareTo(c) {}
368 int operator()(const Key &a, const Key &b) const {
369 return static_cast<const CompareTo&>(*this)(b, a);
370 }
371};
372
373// Dispatch helper class for using linear search with plain compare.
374template <typename K, typename N, typename Compare>
375struct btree_linear_search_plain_compare {
376 static int lower_bound(const K &k, const N &n, Compare comp) {
377 return n.linear_search_plain_compare(k, 0, n.count(), comp);
378 }
379 static int upper_bound(const K &k, const N &n, Compare comp) {
380 typedef btree_upper_bound_adapter<K, Compare> upper_compare;
381 return n.linear_search_plain_compare(k, 0, n.count(), upper_compare(comp));
382 }
383};
384
385// Dispatch helper class for using linear search with compare-to
386template <typename K, typename N, typename CompareTo>
387struct btree_linear_search_compare_to {
388 static int lower_bound(const K &k, const N &n, CompareTo comp) {
389 return n.linear_search_compare_to(k, 0, n.count(), comp);
390 }
391 static int upper_bound(const K &k, const N &n, CompareTo comp) {
392 typedef btree_upper_bound_adapter<K,
393 btree_key_comparer<K, CompareTo, true> > upper_compare;
394 return n.linear_search_plain_compare(k, 0, n.count(), upper_compare(comp));
395 }
396};
397
398// Dispatch helper class for using binary search with plain compare.
399template <typename K, typename N, typename Compare>
400struct btree_binary_search_plain_compare {
401 static int lower_bound(const K &k, const N &n, Compare comp) {
402 return n.binary_search_plain_compare(k, 0, n.count(), comp);
403 }
404 static int upper_bound(const K &k, const N &n, Compare comp) {
405 typedef btree_upper_bound_adapter<K, Compare> upper_compare;
406 return n.binary_search_plain_compare(k, 0, n.count(), upper_compare(comp));
407 }
408};
409
410// Dispatch helper class for using binary search with compare-to.
411template <typename K, typename N, typename CompareTo>
412struct btree_binary_search_compare_to {
413 static int lower_bound(const K &k, const N &n, CompareTo comp) {
414 return n.binary_search_compare_to(k, 0, n.count(), CompareTo());
415 }
416 static int upper_bound(const K &k, const N &n, CompareTo comp) {
417 typedef btree_upper_bound_adapter<K,
418 btree_key_comparer<K, CompareTo, true> > upper_compare;
419 return n.linear_search_plain_compare(k, 0, n.count(), upper_compare(comp));
420 }
421};
422
423// A node in the btree holding. The same node type is used for both internal
424// and leaf nodes in the btree, though the nodes are allocated in such a way
425// that the children array is only valid in internal nodes.
426template <typename Params>
427class btree_node {
428 public:
429 typedef Params params_type;
430 typedef btree_node<Params> self_type;
431 typedef typename Params::key_type key_type;
432 typedef typename Params::data_type data_type;
433 typedef typename Params::value_type value_type;
434 typedef typename Params::mutable_value_type mutable_value_type;
435 typedef typename Params::pointer pointer;
436 typedef typename Params::const_pointer const_pointer;
437 typedef typename Params::reference reference;
438 typedef typename Params::const_reference const_reference;
439 typedef typename Params::key_compare key_compare;
440 typedef typename Params::size_type size_type;
441 typedef typename Params::difference_type difference_type;
442 // Typedefs for the various types of node searches.
443 typedef btree_linear_search_plain_compare<
444 key_type, self_type, key_compare> linear_search_plain_compare_type;
445 typedef btree_linear_search_compare_to<
446 key_type, self_type, key_compare> linear_search_compare_to_type;
447 typedef btree_binary_search_plain_compare<
448 key_type, self_type, key_compare> binary_search_plain_compare_type;
449 typedef btree_binary_search_compare_to<
450 key_type, self_type, key_compare> binary_search_compare_to_type;
451 // If we have a valid key-compare-to type, use linear_search_compare_to,
452 // otherwise use linear_search_plain_compare.
453 typedef typename if_<
454 Params::is_key_compare_to::value,
455 linear_search_compare_to_type,
456 linear_search_plain_compare_type>::type linear_search_type;
457 // If we have a valid key-compare-to type, use binary_search_compare_to,
458 // otherwise use binary_search_plain_compare.
459 typedef typename if_<
460 Params::is_key_compare_to::value,
461 binary_search_compare_to_type,
462 binary_search_plain_compare_type>::type binary_search_type;
463 // If the key is an integral or floating point type, use linear search which
464 // is faster than binary search for such types. Might be wise to also
465 // configure linear search based on node-size.
466 typedef typename if_<
467 std::is_integral<key_type>::value ||
468 std::is_floating_point<key_type>::value,
469 linear_search_type, binary_search_type>::type search_type;
470
471 struct base_fields {
472 typedef typename Params::node_count_type field_type;
473
474 // A boolean indicating whether the node is a leaf or not.
475 bool leaf;
476 // The position of the node in the node's parent.
477 field_type position;
478 // The maximum number of values the node can hold.
479 field_type max_count;
480 // The count of the number of values in the node.
481 field_type count;
482 // A pointer to the node's parent.
483 btree_node *parent;
484 };
485
486 enum {
487 kValueSize = params_type::kValueSize,
488 kTargetNodeSize = params_type::kTargetNodeSize,
489
490 // Compute how many values we can fit onto a leaf node.
491 kNodeTargetValues = (kTargetNodeSize - sizeof(base_fields)) / kValueSize,
492 // We need a minimum of 3 values per internal node in order to perform
493 // splitting (1 value for the two nodes involved in the split and 1 value
494 // propagated to the parent as the delimiter for the split).
495 kNodeValues = kNodeTargetValues >= 3 ? kNodeTargetValues : 3,
496
497 kExactMatch = 1 << 30,
498 kMatchMask = kExactMatch - 1,
499 };
500
501 struct leaf_fields : public base_fields {
502 // The array of values. Only the first count of these values have been
503 // constructed and are valid.
504 mutable_value_type values[kNodeValues];
505 };
506
507 struct internal_fields : public leaf_fields {
508 // The array of child pointers. The keys in children_[i] are all less than
509 // key(i). The keys in children_[i + 1] are all greater than key(i). There
510 // are always count + 1 children.
511 btree_node *children[kNodeValues + 1];
512 };
513
514 struct root_fields : public internal_fields {
515 btree_node *rightmost;
516 size_type size;
517 };
518
519 public:
520 // Getter/setter for whether this is a leaf node or not. This value doesn't
521 // change after the node is created.
522 bool leaf() const { return fields_.leaf; }
523
524 // Getter for the position of this node in its parent.
525 int position() const { return fields_.position; }
526 void set_position(int v) { fields_.position = v; }
527
528 // Getter/setter for the number of values stored in this node.
529 int count() const { return fields_.count; }
530 void set_count(int v) { fields_.count = v; }
531 int max_count() const { return fields_.max_count; }
532
533 // Getter for the parent of this node.
534 btree_node* parent() const { return fields_.parent; }
535 // Getter for whether the node is the root of the tree. The parent of the
536 // root of the tree is the leftmost node in the tree which is guaranteed to
537 // be a leaf.
538 bool is_root() const { return parent()->leaf(); }
539 void make_root() {
540 assert(parent()->is_root());
541 fields_.parent = fields_.parent->parent();
542 }
543
544 // Getter for the rightmost root node field. Only valid on the root node.
545 btree_node* rightmost() const { return fields_.rightmost; }
546 btree_node** mutable_rightmost() { return &fields_.rightmost; }
547
548 // Getter for the size root node field. Only valid on the root node.
549 size_type size() const { return fields_.size; }
550 size_type* mutable_size() { return &fields_.size; }
551
552 // Getters for the key/value at position i in the node.
553 const key_type& key(int i) const {
554 return params_type::key(fields_.values[i]);
555 }
556 reference value(int i) {
557 return reinterpret_cast<reference>(fields_.values[i]);
558 }
559 const_reference value(int i) const {
560 return reinterpret_cast<const_reference>(fields_.values[i]);
561 }
562 mutable_value_type* mutable_value(int i) {
563 return &fields_.values[i];
564 }
565
566 // Swap value i in this node with value j in node x.
567 void value_swap(int i, btree_node *x, int j) {
568 params_type::swap(mutable_value(i), x->mutable_value(j));
569 }
570
571 // Getters/setter for the child at position i in the node.
572 btree_node* child(int i) const { return fields_.children[i]; }
573 btree_node** mutable_child(int i) { return &fields_.children[i]; }
574 void set_child(int i, btree_node *c) {
575 *mutable_child(i) = c;
576 c->fields_.parent = this;
577 c->fields_.position = i;
578 }
579
580 // Returns the position of the first value whose key is not less than k.
581 template <typename Compare>
582 int lower_bound(const key_type &k, const Compare &comp) const {
583 return search_type::lower_bound(k, *this, comp);
584 }
585 // Returns the position of the first value whose key is greater than k.
586 template <typename Compare>
587 int upper_bound(const key_type &k, const Compare &comp) const {
588 return search_type::upper_bound(k, *this, comp);
589 }
590
591 // Returns the position of the first value whose key is not less than k using
592 // linear search performed using plain compare.
593 template <typename Compare>
594 int linear_search_plain_compare(
595 const key_type &k, int s, int e, const Compare &comp) const {
596 while (s < e) {
597 if (!btree_compare_keys(comp, key(s), k)) {
598 break;
599 }
600 ++s;
601 }
602 return s;
603 }
604
605 // Returns the position of the first value whose key is not less than k using
606 // linear search performed using compare-to.
607 template <typename Compare>
608 int linear_search_compare_to(
609 const key_type &k, int s, int e, const Compare &comp) const {
610 while (s < e) {
611 int c = comp(key(s), k);
612 if (c == 0) {
613 return s | kExactMatch;
614 } else if (c > 0) {
615 break;
616 }
617 ++s;
618 }
619 return s;
620 }
621
622 // Returns the position of the first value whose key is not less than k using
623 // binary search performed using plain compare.
624 template <typename Compare>
625 int binary_search_plain_compare(
626 const key_type &k, int s, int e, const Compare &comp) const {
627 while (s != e) {
628 int mid = (s + e) / 2;
629 if (btree_compare_keys(comp, key(mid), k)) {
630 s = mid + 1;
631 } else {
632 e = mid;
633 }
634 }
635 return s;
636 }
637
638 // Returns the position of the first value whose key is not less than k using
639 // binary search performed using compare-to.
640 template <typename CompareTo>
641 int binary_search_compare_to(
642 const key_type &k, int s, int e, const CompareTo &comp) const {
643 while (s != e) {
644 int mid = (s + e) / 2;
645 int c = comp(key(mid), k);
646 if (c < 0) {
647 s = mid + 1;
648 } else if (c > 0) {
649 e = mid;
650 } else {
651 // Need to return the first value whose key is not less than k, which
652 // requires continuing the binary search. Note that we are guaranteed
653 // that the result is an exact match because if "key(mid-1) < k" the
654 // call to binary_search_compare_to() will return "mid".
655 s = binary_search_compare_to(k, s, mid, comp);
656 return s | kExactMatch;
657 }
658 }
659 return s;
660 }
661
662 // Inserts the value x at position i, shifting all existing values and
663 // children at positions >= i to the right by 1.
664 void insert_value(int i, const value_type &x);
665
666 // Removes the value at position i, shifting all existing values and children
667 // at positions > i to the left by 1.
668 void remove_value(int i);
669
670 // Rebalances a node with its right sibling.
671 void rebalance_right_to_left(btree_node *sibling, int to_move);
672 void rebalance_left_to_right(btree_node *sibling, int to_move);
673
674 // Splits a node, moving a portion of the node's values to its right sibling.
675 void split(btree_node *sibling, int insert_position);
676
677 // Merges a node with its right sibling, moving all of the values and the
678 // delimiting key in the parent node onto itself.
679 void merge(btree_node *sibling);
680
681 // Swap the contents of "this" and "src".
682 void swap(btree_node *src);
683
684 // Node allocation/deletion routines.
685 static btree_node* init_leaf(
686 leaf_fields *f, btree_node *parent, int max_count) {
687 btree_node *n = reinterpret_cast<btree_node*>(f);
688 f->leaf = 1;
689 f->position = 0;
690 f->max_count = max_count;
691 f->count = 0;
692 f->parent = parent;
693 if (!NDEBUG) {
694 memset(&f->values, 0, max_count * sizeof(value_type));
695 }
696 return n;
697 }
698 static btree_node* init_internal(internal_fields *f, btree_node *parent) {
699 btree_node *n = init_leaf(f, parent, kNodeValues);
700 f->leaf = 0;
701 if (!NDEBUG) {
702 memset(f->children, 0, sizeof(f->children));
703 }
704 return n;
705 }
706 static btree_node* init_root(root_fields *f, btree_node *parent) {
707 btree_node *n = init_internal(f, parent);
708 f->rightmost = parent;
709 f->size = parent->count();
710 return n;
711 }
712 void destroy() {
713 for (int i = 0; i < count(); ++i) {
714 value_destroy(i);
715 }
716 }
717
718 private:
719 void value_init(int i) {
720 new (&fields_.values[i]) mutable_value_type;
721 }
722 void value_init(int i, const value_type &x) {
723 new (&fields_.values[i]) mutable_value_type(x);
724 }
725 void value_destroy(int i) {
726 fields_.values[i].~mutable_value_type();
727 }
728
729 private:
730 root_fields fields_;
731
732 private:
733 btree_node(const btree_node&);
734 void operator=(const btree_node&);
735};
736
737template <typename Node, typename Reference, typename Pointer>
738struct btree_iterator {
739 typedef typename Node::key_type key_type;
740 typedef typename Node::size_type size_type;
741 typedef typename Node::difference_type difference_type;
742 typedef typename Node::params_type params_type;
743
744 typedef Node node_type;
745 typedef typename std::remove_const<Node>::type normal_node;
746 typedef const Node const_node;
747 typedef typename params_type::value_type value_type;
748 typedef typename params_type::pointer normal_pointer;
749 typedef typename params_type::reference normal_reference;
750 typedef typename params_type::const_pointer const_pointer;
751 typedef typename params_type::const_reference const_reference;
752
753 typedef Pointer pointer;
754 typedef Reference reference;
755 typedef std::bidirectional_iterator_tag iterator_category;
756
757 typedef btree_iterator<
758 normal_node, normal_reference, normal_pointer> iterator;
759 typedef btree_iterator<
760 const_node, const_reference, const_pointer> const_iterator;
761 typedef btree_iterator<Node, Reference, Pointer> self_type;
762
763 btree_iterator()
764 : node(NULL),
765 position(-1) {
766 }
767 btree_iterator(Node *n, int p)
768 : node(n),
769 position(p) {
770 }
771 btree_iterator(const iterator &x)
772 : node(x.node),
773 position(x.position) {
774 }
775
776 // Increment/decrement the iterator.
777 void increment() {
778 if (node->leaf() && ++position < node->count()) {
779 return;
780 }
781 increment_slow();
782 }
783 void increment_by(int count);
784 void increment_slow();
785
786 void decrement() {
787 if (node->leaf() && --position >= 0) {
788 return;
789 }
790 decrement_slow();
791 }
792 void decrement_slow();
793
794 bool operator==(const const_iterator &x) const {
795 return node == x.node && position == x.position;
796 }
797 bool operator!=(const const_iterator &x) const {
798 return node != x.node || position != x.position;
799 }
800
801 // Accessors for the key/value the iterator is pointing at.
802 const key_type& key() const {
803 return node->key(position);
804 }
805 reference operator*() const {
806 return node->value(position);
807 }
808 pointer operator->() const {
809 return &node->value(position);
810 }
811
812 self_type& operator++() {
813 increment();
814 return *this;
815 }
816 self_type& operator--() {
817 decrement();
818 return *this;
819 }
820 self_type operator++(int) {
821 self_type tmp = *this;
822 ++*this;
823 return tmp;
824 }
825 self_type operator--(int) {
826 self_type tmp = *this;
827 --*this;
828 return tmp;
829 }
830
831 // The node in the tree the iterator is pointing at.
832 Node *node;
833 // The position within the node of the tree the iterator is pointing at.
834 int position;
835};
836
837// Dispatch helper class for using btree::internal_locate with plain compare.
838struct btree_internal_locate_plain_compare {
839 template <typename K, typename T, typename Iter>
840 static std::pair<Iter, int> dispatch(const K &k, const T &t, Iter iter) {
841 return t.internal_locate_plain_compare(k, iter);
842 }
843};
844
845// Dispatch helper class for using btree::internal_locate with compare-to.
846struct btree_internal_locate_compare_to {
847 template <typename K, typename T, typename Iter>
848 static std::pair<Iter, int> dispatch(const K &k, const T &t, Iter iter) {
849 return t.internal_locate_compare_to(k, iter);
850 }
851};
852
853template <typename Params>
854class btree : public Params::key_compare {
855 typedef btree<Params> self_type;
856 typedef btree_node<Params> node_type;
857 typedef typename node_type::base_fields base_fields;
858 typedef typename node_type::leaf_fields leaf_fields;
859 typedef typename node_type::internal_fields internal_fields;
860 typedef typename node_type::root_fields root_fields;
861 typedef typename Params::is_key_compare_to is_key_compare_to;
862
863 friend struct btree_internal_locate_plain_compare;
864 friend struct btree_internal_locate_compare_to;
865 typedef typename if_<
866 is_key_compare_to::value,
867 btree_internal_locate_compare_to,
868 btree_internal_locate_plain_compare>::type internal_locate_type;
869
870 enum {
871 kNodeValues = node_type::kNodeValues,
872 kMinNodeValues = kNodeValues / 2,
873 kValueSize = node_type::kValueSize,
874 kExactMatch = node_type::kExactMatch,
875 kMatchMask = node_type::kMatchMask,
876 };
877
878 // A helper class to get the empty base class optimization for 0-size
879 // allocators. Base is internal_allocator_type.
880 // (e.g. empty_base_handle<internal_allocator_type, node_type*>). If Base is
881 // 0-size, the compiler doesn't have to reserve any space for it and
882 // sizeof(empty_base_handle) will simply be sizeof(Data). Google [empty base
883 // class optimization] for more details.
884 template <typename Base, typename Data>
885 struct empty_base_handle : public Base {
886 empty_base_handle(const Base &b, const Data &d)
887 : Base(b),
888 data(d) {
889 }
890 Data data;
891 };
892
893 struct node_stats {
894 node_stats(ssize_t l, ssize_t i)
895 : leaf_nodes(l),
896 internal_nodes(i) {
897 }
898
899 node_stats& operator+=(const node_stats &x) {
900 leaf_nodes += x.leaf_nodes;
901 internal_nodes += x.internal_nodes;
902 return *this;
903 }
904
905 ssize_t leaf_nodes;
906 ssize_t internal_nodes;
907 };
908
909 public:
910 typedef Params params_type;
911 typedef typename Params::key_type key_type;
912 typedef typename Params::data_type data_type;
913 typedef typename Params::mapped_type mapped_type;
914 typedef typename Params::value_type value_type;
915 typedef typename Params::key_compare key_compare;
916 typedef typename Params::pointer pointer;
917 typedef typename Params::const_pointer const_pointer;
918 typedef typename Params::reference reference;
919 typedef typename Params::const_reference const_reference;
920 typedef typename Params::size_type size_type;
921 typedef typename Params::difference_type difference_type;
922 typedef btree_iterator<node_type, reference, pointer> iterator;
923 typedef typename iterator::const_iterator const_iterator;
924 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
925 typedef std::reverse_iterator<iterator> reverse_iterator;
926
927 typedef typename Params::allocator_type allocator_type;
928 typedef typename allocator_type::template rebind<char>::other
929 internal_allocator_type;
930
931 public:
932 // Default constructor.
933 btree(const key_compare &comp, const allocator_type &alloc);
934
935 // Copy constructor.
936 btree(const self_type &x);
937
938 // Destructor.
939 ~btree() {
940 clear();
941 }
942
943 // Iterator routines.
944 iterator begin() {
945 return iterator(leftmost(), 0);
946 }
947 const_iterator begin() const {
948 return const_iterator(leftmost(), 0);
949 }
950 iterator end() {
951 return iterator(rightmost(), rightmost() ? rightmost()->count() : 0);
952 }
953 const_iterator end() const {
954 return const_iterator(rightmost(), rightmost() ? rightmost()->count() : 0);
955 }
956 reverse_iterator rbegin() {
957 return reverse_iterator(end());
958 }
959 const_reverse_iterator rbegin() const {
960 return const_reverse_iterator(end());
961 }
962 reverse_iterator rend() {
963 return reverse_iterator(begin());
964 }
965 const_reverse_iterator rend() const {
966 return const_reverse_iterator(begin());
967 }
968
969 // Finds the first element whose key is not less than key.
970 iterator lower_bound(const key_type &key) {
971 return internal_end(
972 internal_lower_bound(key, iterator(root(), 0)));
973 }
974 const_iterator lower_bound(const key_type &key) const {
975 return internal_end(
976 internal_lower_bound(key, const_iterator(root(), 0)));
977 }
978
979 // Finds the first element whose key is greater than key.
980 iterator upper_bound(const key_type &key) {
981 return internal_end(
982 internal_upper_bound(key, iterator(root(), 0)));
983 }
984 const_iterator upper_bound(const key_type &key) const {
985 return internal_end(
986 internal_upper_bound(key, const_iterator(root(), 0)));
987 }
988
989 // Finds the range of values which compare equal to key. The first member of
990 // the returned pair is equal to lower_bound(key). The second member pair of
991 // the pair is equal to upper_bound(key).
992 std::pair<iterator,iterator> equal_range(const key_type &key) {
993 return std::make_pair(lower_bound(key), upper_bound(key));
994 }
995 std::pair<const_iterator,const_iterator> equal_range(const key_type &key) const {
996 return std::make_pair(lower_bound(key), upper_bound(key));
997 }
998
999 // Inserts a value into the btree only if it does not already exist. The
1000 // boolean return value indicates whether insertion succeeded or failed. The
1001 // ValuePointer type is used to avoid instatiating the value unless the key
1002 // is being inserted. Value is not dereferenced if the key already exists in
1003 // the btree. See btree_map::operator[].
1004 template <typename ValuePointer>
1005 std::pair<iterator,bool> insert_unique(const key_type &key, ValuePointer value);
1006
1007 // Inserts a value into the btree only if it does not already exist. The
1008 // boolean return value indicates whether insertion succeeded or failed.
1009 std::pair<iterator,bool> insert_unique(const value_type &v) {
1010 return insert_unique(params_type::key(v), &v);
1011 }
1012
1013 // Insert with hint. Check to see if the value should be placed immediately
1014 // before position in the tree. If it does, then the insertion will take
1015 // amortized constant time. If not, the insertion will take amortized
1016 // logarithmic time as if a call to insert_unique(v) were made.
1017 iterator insert_unique(iterator position, const value_type &v);
1018
1019 // Insert a range of values into the btree.
1020 template <typename InputIterator>
1021 void insert_unique(InputIterator b, InputIterator e);
1022
1023 // Inserts a value into the btree. The ValuePointer type is used to avoid
1024 // instatiating the value unless the key is being inserted. Value is not
1025 // dereferenced if the key already exists in the btree. See
1026 // btree_map::operator[].
1027 template <typename ValuePointer>
1028 iterator insert_multi(const key_type &key, ValuePointer value);
1029
1030 // Inserts a value into the btree.
1031 iterator insert_multi(const value_type &v) {
1032 return insert_multi(params_type::key(v), &v);
1033 }
1034
1035 // Insert with hint. Check to see if the value should be placed immediately
1036 // before position in the tree. If it does, then the insertion will take
1037 // amortized constant time. If not, the insertion will take amortized
1038 // logarithmic time as if a call to insert_multi(v) were made.
1039 iterator insert_multi(iterator position, const value_type &v);
1040
1041 // Insert a range of values into the btree.
1042 template <typename InputIterator>
1043 void insert_multi(InputIterator b, InputIterator e);
1044
1045 void assign(const self_type &x);
1046
1047 // Erase the specified iterator from the btree. The iterator must be valid
1048 // (i.e. not equal to end()). Return an iterator pointing to the node after
1049 // the one that was erased (or end() if none exists).
1050 iterator erase(iterator iter);
1051
1052 // Erases range. Returns the number of keys erased.
1053 int erase(iterator begin, iterator end);
1054
1055 // Erases the specified key from the btree. Returns 1 if an element was
1056 // erased and 0 otherwise.
1057 int erase_unique(const key_type &key);
1058
1059 // Erases all of the entries matching the specified key from the
1060 // btree. Returns the number of elements erased.
1061 int erase_multi(const key_type &key);
1062
1063 // Finds the iterator corresponding to a key or returns end() if the key is
1064 // not present.
1065 iterator find_unique(const key_type &key) {
1066 return internal_end(
1067 internal_find_unique(key, iterator(root(), 0)));
1068 }
1069 const_iterator find_unique(const key_type &key) const {
1070 return internal_end(
1071 internal_find_unique(key, const_iterator(root(), 0)));
1072 }
1073 iterator find_multi(const key_type &key) {
1074 return internal_end(
1075 internal_find_multi(key, iterator(root(), 0)));
1076 }
1077 const_iterator find_multi(const key_type &key) const {
1078 return internal_end(
1079 internal_find_multi(key, const_iterator(root(), 0)));
1080 }
1081
1082 // Returns a count of the number of times the key appears in the btree.
1083 size_type count_unique(const key_type &key) const {
1084 const_iterator b = internal_find_unique(
1085 key, const_iterator(root(), 0));
1086 if (!b.node) {
1087 // The key doesn't exist in the tree.
1088 return 0;
1089 }
1090 return 1;
1091 }
1092 // Returns a count of the number of times the key appears in the btree.
1093 size_type count_multi(const key_type &key) const {
1094 return distance(lower_bound(key), upper_bound(key));
1095 }
1096
1097 // Clear the btree, deleting all of the values it contains.
1098 void clear();
1099
1100 // Swap the contents of *this and x.
1101 void swap(self_type &x);
1102
1103 // Assign the contents of x to *this.
1104 self_type& operator=(const self_type &x) {
1105 if (&x == this) {
1106 // Don't copy onto ourselves.
1107 return *this;
1108 }
1109 assign(x);
1110 return *this;
1111 }
1112
1113 key_compare* mutable_key_comp() {
1114 return this;
1115 }
1116 const key_compare& key_comp() const {
1117 return *this;
1118 }
1119 bool compare_keys(const key_type &x, const key_type &y) const {
1120 return btree_compare_keys(key_comp(), x, y);
1121 }
1122
1123 // Dump the btree to the specified ostream. Requires that operator<< is
1124 // defined for Key and Value.
1125 void dump(std::ostream &os) const {
1126 if (root() != NULL) {
1127 internal_dump(os, root(), 0);
1128 }
1129 }
1130
1131 // Verifies the structure of the btree.
1132 void verify() const;
1133
1134 // Size routines. Note that empty() is slightly faster than doing size()==0.
1135 size_type size() const {
1136 if (empty()) return 0;
1137 if (root()->leaf()) return root()->count();
1138 return root()->size();
1139 }
1140 size_type max_size() const { return std::numeric_limits<size_type>::max(); }
1141 bool empty() const { return root() == NULL; }
1142
1143 // The height of the btree. An empty tree will have height 0.
1144 size_type height() const {
1145 size_type h = 0;
1146 if (root()) {
1147 // Count the length of the chain from the leftmost node up to the
1148 // root. We actually count from the root back around to the level below
1149 // the root, but the calculation is the same because of the circularity
1150 // of that traversal.
1151 const node_type *n = root();
1152 do {
1153 ++h;
1154 n = n->parent();
1155 } while (n != root());
1156 }
1157 return h;
1158 }
1159
1160 // The number of internal, leaf and total nodes used by the btree.
1161 size_type leaf_nodes() const {
1162 return internal_stats(root()).leaf_nodes;
1163 }
1164 size_type internal_nodes() const {
1165 return internal_stats(root()).internal_nodes;
1166 }
1167 size_type nodes() const {
1168 node_stats stats = internal_stats(root());
1169 return stats.leaf_nodes + stats.internal_nodes;
1170 }
1171
1172 // The total number of bytes used by the btree.
1173 size_type bytes_used() const {
1174 node_stats stats = internal_stats(root());
1175 if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
1176 return sizeof(*this) +
1177 sizeof(base_fields) + root()->max_count() * sizeof(value_type);
1178 } else {
1179 return sizeof(*this) +
1180 sizeof(root_fields) - sizeof(internal_fields) +
1181 stats.leaf_nodes * sizeof(leaf_fields) +
1182 stats.internal_nodes * sizeof(internal_fields);
1183 }
1184 }
1185
1186 // The average number of bytes used per value stored in the btree.
1187 static double average_bytes_per_value() {
1188 // Returns the number of bytes per value on a leaf node that is 75%
1189 // full. Experimentally, this matches up nicely with the computed number of
1190 // bytes per value in trees that had their values inserted in random order.
1191 return sizeof(leaf_fields) / (kNodeValues * 0.75);
1192 }
1193
1194 // The fullness of the btree. Computed as the number of elements in the btree
1195 // divided by the maximum number of elements a tree with the current number
1196 // of nodes could hold. A value of 1 indicates perfect space
1197 // utilization. Smaller values indicate space wastage.
1198 double fullness() const {
1199 return double(size()) / (nodes() * kNodeValues);
1200 }
1201 // The overhead of the btree structure in bytes per node. Computed as the
1202 // total number of bytes used by the btree minus the number of bytes used for
1203 // storing elements divided by the number of elements.
1204 double overhead() const {
1205 if (empty()) {
1206 return 0.0;
1207 }
1208 return (bytes_used() - size() * kValueSize) / double(size());
1209 }
1210
1211 private:
1212 // Internal accessor routines.
1213 node_type* root() { return root_.data; }
1214 const node_type* root() const { return root_.data; }
1215 node_type** mutable_root() { return &root_.data; }
1216
1217 // The rightmost node is stored in the root node.
1218 node_type* rightmost() {
1219 return (!root() || root()->leaf()) ? root() : root()->rightmost();
1220 }
1221 const node_type* rightmost() const {
1222 return (!root() || root()->leaf()) ? root() : root()->rightmost();
1223 }
1224 node_type** mutable_rightmost() { return root()->mutable_rightmost(); }
1225
1226 // The leftmost node is stored as the parent of the root node.
1227 node_type* leftmost() { return root() ? root()->parent() : NULL; }
1228 const node_type* leftmost() const { return root() ? root()->parent() : NULL; }
1229
1230 // The size of the tree is stored in the root node.
1231 size_type* mutable_size() { return root()->mutable_size(); }
1232
1233 // Allocator routines.
1234 internal_allocator_type* mutable_internal_allocator() {
1235 return static_cast<internal_allocator_type*>(&root_);
1236 }
1237 const internal_allocator_type& internal_allocator() const {
1238 return *static_cast<const internal_allocator_type*>(&root_);
1239 }
1240
1241 // Node creation/deletion routines.
1242 node_type* new_internal_node(node_type *parent) {
1243 internal_fields *p = reinterpret_cast<internal_fields*>(
1244 mutable_internal_allocator()->allocate(sizeof(internal_fields)));
1245 return node_type::init_internal(p, parent);
1246 }
1247 node_type* new_internal_root_node() {
1248 root_fields *p = reinterpret_cast<root_fields*>(
1249 mutable_internal_allocator()->allocate(sizeof(root_fields)));
1250 return node_type::init_root(p, root()->parent());
1251 }
1252 node_type* new_leaf_node(node_type *parent) {
1253 leaf_fields *p = reinterpret_cast<leaf_fields*>(
1254 mutable_internal_allocator()->allocate(sizeof(leaf_fields)));
1255 return node_type::init_leaf(p, parent, kNodeValues);
1256 }
1257 node_type* new_leaf_root_node(int max_count) {
1258 leaf_fields *p = reinterpret_cast<leaf_fields*>(
1259 mutable_internal_allocator()->allocate(
1260 sizeof(base_fields) + max_count * sizeof(value_type)));
1261 return node_type::init_leaf(p, reinterpret_cast<node_type*>(p), max_count);
1262 }
1263 void delete_internal_node(node_type *node) {
1264 node->destroy();
1265 assert(node != root());
1266 mutable_internal_allocator()->deallocate(
1267 reinterpret_cast<char*>(node), sizeof(internal_fields));
1268 }
1269 void delete_internal_root_node() {
1270 root()->destroy();
1271 mutable_internal_allocator()->deallocate(
1272 reinterpret_cast<char*>(root()), sizeof(root_fields));
1273 }
1274 void delete_leaf_node(node_type *node) {
1275 node->destroy();
1276 mutable_internal_allocator()->deallocate(
1277 reinterpret_cast<char*>(node),
1278 sizeof(base_fields) + node->max_count() * sizeof(value_type));
1279 }
1280
1281 // Rebalances or splits the node iter points to.
1282 void rebalance_or_split(iterator *iter);
1283
1284 // Merges the values of left, right and the delimiting key on their parent
1285 // onto left, removing the delimiting key and deleting right.
1286 void merge_nodes(node_type *left, node_type *right);
1287
1288 // Tries to merge node with its left or right sibling, and failing that,
1289 // rebalance with its left or right sibling. Returns true if a merge
1290 // occurred, at which point it is no longer valid to access node. Returns
1291 // false if no merging took place.
1292 bool try_merge_or_rebalance(iterator *iter);
1293
1294 // Tries to shrink the height of the tree by 1.
1295 void try_shrink();
1296
1297 iterator internal_end(iterator iter) {
1298 return iter.node ? iter : end();
1299 }
1300 const_iterator internal_end(const_iterator iter) const {
1301 return iter.node ? iter : end();
1302 }
1303
1304 // Inserts a value into the btree immediately before iter. Requires that
1305 // key(v) <= iter.key() and (--iter).key() <= key(v).
1306 iterator internal_insert(iterator iter, const value_type &v);
1307
1308 // Returns an iterator pointing to the first value >= the value "iter" is
1309 // pointing at. Note that "iter" might be pointing to an invalid location as
1310 // iter.position == iter.node->count(). This routine simply moves iter up in
1311 // the tree to a valid location.
1312 template <typename IterType>
1313 static IterType internal_last(IterType iter);
1314
1315 // Returns an iterator pointing to the leaf position at which key would
1316 // reside in the tree. We provide 2 versions of internal_locate. The first
1317 // version (internal_locate_plain_compare) always returns 0 for the second
1318 // field of the pair. The second version (internal_locate_compare_to) is for
1319 // the key-compare-to specialization and returns either kExactMatch (if the
1320 // key was found in the tree) or -kExactMatch (if it wasn't) in the second
1321 // field of the pair. The compare_to specialization allows the caller to
1322 // avoid a subsequent comparison to determine if an exact match was made,
1323 // speeding up string keys.
1324 template <typename IterType>
1325 std::pair<IterType, int> internal_locate(
1326 const key_type &key, IterType iter) const;
1327 template <typename IterType>
1328 std::pair<IterType, int> internal_locate_plain_compare(
1329 const key_type &key, IterType iter) const;
1330 template <typename IterType>
1331 std::pair<IterType, int> internal_locate_compare_to(
1332 const key_type &key, IterType iter) const;
1333
1334 // Internal routine which implements lower_bound().
1335 template <typename IterType>
1336 IterType internal_lower_bound(
1337 const key_type &key, IterType iter) const;
1338
1339 // Internal routine which implements upper_bound().
1340 template <typename IterType>
1341 IterType internal_upper_bound(
1342 const key_type &key, IterType iter) const;
1343
1344 // Internal routine which implements find_unique().
1345 template <typename IterType>
1346 IterType internal_find_unique(
1347 const key_type &key, IterType iter) const;
1348
1349 // Internal routine which implements find_multi().
1350 template <typename IterType>
1351 IterType internal_find_multi(
1352 const key_type &key, IterType iter) const;
1353
1354 // Deletes a node and all of its children.
1355 void internal_clear(node_type *node);
1356
1357 // Dumps a node and all of its children to the specified ostream.
1358 void internal_dump(std::ostream &os, const node_type *node, int level) const;
1359
1360 // Verifies the tree structure of node.
1361 int internal_verify(const node_type *node,
1362 const key_type *lo, const key_type *hi) const;
1363
1364 node_stats internal_stats(const node_type *node) const {
1365 if (!node) {
1366 return node_stats(0, 0);
1367 }
1368 if (node->leaf()) {
1369 return node_stats(1, 0);
1370 }
1371 node_stats res(0, 1);
1372 for (int i = 0; i <= node->count(); ++i) {
1373 res += internal_stats(node->child(i));
1374 }
1375 return res;
1376 }
1377
1378 private:
1379 empty_base_handle<internal_allocator_type, node_type*> root_;
1380
1381 private:
1382 // A never instantiated helper function that returns big_ if we have a
1383 // key-compare-to functor or if R is bool and small_ otherwise.
1384 template <typename R>
1385 static typename if_<
1386 if_<is_key_compare_to::value,
1387 std::is_same<R, int>,
1388 std::is_same<R, bool> >::type::value,
1389 big_, small_>::type key_compare_checker(R);
1390
1391 // A never instantiated helper function that returns the key comparison
1392 // functor.
1393 static key_compare key_compare_helper();
1394
1395 // Verify that key_compare returns a bool. This is similar to the way
1396 // is_convertible in base/type_traits.h works. Note that key_compare_checker
1397 // is never actually invoked. The compiler will select which
1398 // key_compare_checker() to instantiate and then figure out the size of the
1399 // return type of key_compare_checker() at compile time which we then check
1400 // against the sizeof of big_.
1401 COMPILE_ASSERT(
1402 sizeof(key_compare_checker(key_compare_helper()(key_type(), key_type()))) ==
1403 sizeof(big_),
1404 key_comparison_function_must_return_bool);
1405
1406 // Note: We insist on kTargetValues, which is computed from
1407 // Params::kTargetNodeSize, must fit the base_fields::field_type.
1408 COMPILE_ASSERT(kNodeValues <
1409 (1 << (8 * sizeof(typename base_fields::field_type))),
1410 target_node_size_too_large);
1411
1412 // Test the assumption made in setting kNodeValueSpace.
1413 COMPILE_ASSERT(sizeof(base_fields) >= 2 * sizeof(void*),
1414 node_space_assumption_incorrect);
1415};
1416
1417////
1418// btree_node methods
1419template <typename P>
1420inline void btree_node<P>::insert_value(int i, const value_type &x) {
1421 assert(i <= count());
1422 value_init(count(), x);
1423 for (int j = count(); j > i; --j) {
1424 value_swap(j, this, j - 1);
1425 }
1426 set_count(count() + 1);
1427
1428 if (!leaf()) {
1429 ++i;
1430 for (int j = count(); j > i; --j) {
1431 *mutable_child(j) = child(j - 1);
1432 child(j)->set_position(j);
1433 }
1434 *mutable_child(i) = NULL;
1435 }
1436}
1437
1438template <typename P>
1439inline void btree_node<P>::remove_value(int i) {
1440 if (!leaf()) {
1441 assert(child(i + 1)->count() == 0);
1442 for (int j = i + 1; j < count(); ++j) {
1443 *mutable_child(j) = child(j + 1);
1444 child(j)->set_position(j);
1445 }
1446 *mutable_child(count()) = NULL;
1447 }
1448
1449 set_count(count() - 1);
1450 for (; i < count(); ++i) {
1451 value_swap(i, this, i + 1);
1452 }
1453 value_destroy(i);
1454}
1455
1456template <typename P>
1457void btree_node<P>::rebalance_right_to_left(btree_node *src, int to_move) {
1458 assert(parent() == src->parent());
1459 assert(position() + 1 == src->position());
1460 assert(src->count() >= count());
1461 assert(to_move >= 1);
1462 assert(to_move <= src->count());
1463
1464 // Make room in the left node for the new values.
1465 for (int i = 0; i < to_move; ++i) {
1466 value_init(i + count());
1467 }
1468
1469 // Move the delimiting value to the left node and the new delimiting value
1470 // from the right node.
1471 value_swap(count(), parent(), position());
1472 parent()->value_swap(position(), src, to_move - 1);
1473
1474 // Move the values from the right to the left node.
1475 for (int i = 1; i < to_move; ++i) {
1476 value_swap(count() + i, src, i - 1);
1477 }
1478 // Shift the values in the right node to their correct position.
1479 for (int i = to_move; i < src->count(); ++i) {
1480 src->value_swap(i - to_move, src, i);
1481 }
1482 for (int i = 1; i <= to_move; ++i) {
1483 src->value_destroy(src->count() - i);
1484 }
1485
1486 if (!leaf()) {
1487 // Move the child pointers from the right to the left node.
1488 for (int i = 0; i < to_move; ++i) {
1489 set_child(1 + count() + i, src->child(i));
1490 }
1491 for (int i = 0; i <= src->count() - to_move; ++i) {
1492 assert(i + to_move <= src->max_count());
1493 src->set_child(i, src->child(i + to_move));
1494 *src->mutable_child(i + to_move) = NULL;
1495 }
1496 }
1497
1498 // Fixup the counts on the src and dest nodes.
1499 set_count(count() + to_move);
1500 src->set_count(src->count() - to_move);
1501}
1502
1503template <typename P>
1504void btree_node<P>::rebalance_left_to_right(btree_node *dest, int to_move) {
1505 assert(parent() == dest->parent());
1506 assert(position() + 1 == dest->position());
1507 assert(count() >= dest->count());
1508 assert(to_move >= 1);
1509 assert(to_move <= count());
1510
1511 // Make room in the right node for the new values.
1512 for (int i = 0; i < to_move; ++i) {
1513 dest->value_init(i + dest->count());
1514 }
1515 for (int i = dest->count() - 1; i >= 0; --i) {
1516 dest->value_swap(i, dest, i + to_move);
1517 }
1518
1519 // Move the delimiting value to the right node and the new delimiting value
1520 // from the left node.
1521 dest->value_swap(to_move - 1, parent(), position());
1522 parent()->value_swap(position(), this, count() - to_move);
1523 value_destroy(count() - to_move);
1524
1525 // Move the values from the left to the right node.
1526 for (int i = 1; i < to_move; ++i) {
1527 value_swap(count() - to_move + i, dest, i - 1);
1528 value_destroy(count() - to_move + i);
1529 }
1530
1531 if (!leaf()) {
1532 // Move the child pointers from the left to the right node.
1533 for (int i = dest->count(); i >= 0; --i) {
1534 dest->set_child(i + to_move, dest->child(i));
1535 *dest->mutable_child(i) = NULL;
1536 }
1537 for (int i = 1; i <= to_move; ++i) {
1538 dest->set_child(i - 1, child(count() - to_move + i));
1539 *mutable_child(count() - to_move + i) = NULL;
1540 }
1541 }
1542
1543 // Fixup the counts on the src and dest nodes.
1544 set_count(count() - to_move);
1545 dest->set_count(dest->count() + to_move);
1546}
1547
1548template <typename P>
1549void btree_node<P>::split(btree_node *dest, int insert_position) {
1550 assert(dest->count() == 0);
1551
1552 // We bias the split based on the position being inserted. If we're
1553 // inserting at the beginning of the left node then bias the split to put
1554 // more values on the right node. If we're inserting at the end of the
1555 // right node then bias the split to put more values on the left node.
1556 if (insert_position == 0) {
1557 dest->set_count(count() - 1);
1558 } else if (insert_position == max_count()) {
1559 dest->set_count(0);
1560 } else {
1561 dest->set_count(count() / 2);
1562 }
1563 set_count(count() - dest->count());
1564 assert(count() >= 1);
1565
1566 // Move values from the left sibling to the right sibling.
1567 for (int i = 0; i < dest->count(); ++i) {
1568 dest->value_init(i);
1569 value_swap(count() + i, dest, i);
1570 value_destroy(count() + i);
1571 }
1572
1573 // The split key is the largest value in the left sibling.
1574 set_count(count() - 1);
1575 parent()->insert_value(position(), value_type());
1576 value_swap(count(), parent(), position());
1577 value_destroy(count());
1578 parent()->set_child(position() + 1, dest);
1579
1580 if (!leaf()) {
1581 for (int i = 0; i <= dest->count(); ++i) {
1582 assert(child(count() + i + 1) != NULL);
1583 dest->set_child(i, child(count() + i + 1));
1584 *mutable_child(count() + i + 1) = NULL;
1585 }
1586 }
1587}
1588
1589template <typename P>
1590void btree_node<P>::merge(btree_node *src) {
1591 assert(parent() == src->parent());
1592 assert(position() + 1 == src->position());
1593
1594 // Move the delimiting value to the left node.
1595 value_init(count());
1596 value_swap(count(), parent(), position());
1597
1598 // Move the values from the right to the left node.
1599 for (int i = 0; i < src->count(); ++i) {
1600 value_init(1 + count() + i);
1601 value_swap(1 + count() + i, src, i);
1602 src->value_destroy(i);
1603 }
1604
1605 if (!leaf()) {
1606 // Move the child pointers from the right to the left node.
1607 for (int i = 0; i <= src->count(); ++i) {
1608 set_child(1 + count() + i, src->child(i));
1609 *src->mutable_child(i) = NULL;
1610 }
1611 }
1612
1613 // Fixup the counts on the src and dest nodes.
1614 set_count(1 + count() + src->count());
1615 src->set_count(0);
1616
1617 // Remove the value on the parent node.
1618 parent()->remove_value(position());
1619}
1620
1621template <typename P>
1622void btree_node<P>::swap(btree_node *x) {
1623 assert(leaf() == x->leaf());
1624
1625 // Swap the values.
1626 for (int i = count(); i < x->count(); ++i) {
1627 value_init(i);
1628 }
1629 for (int i = x->count(); i < count(); ++i) {
1630 x->value_init(i);
1631 }
1632 int n = std::max(count(), x->count());
1633 for (int i = 0; i < n; ++i) {
1634 value_swap(i, x, i);
1635 }
1636 for (int i = count(); i < x->count(); ++i) {
1637 x->value_destroy(i);
1638 }
1639 for (int i = x->count(); i < count(); ++i) {
1640 value_destroy(i);
1641 }
1642
1643 if (!leaf()) {
1644 // Swap the child pointers.
1645 for (int i = 0; i <= n; ++i) {
1646 btree_swap_helper(*mutable_child(i), *x->mutable_child(i));
1647 }
1648 for (int i = 0; i <= count(); ++i) {
1649 x->child(i)->fields_.parent = x;
1650 }
1651 for (int i = 0; i <= x->count(); ++i) {
1652 child(i)->fields_.parent = this;
1653 }
1654 }
1655
1656 // Swap the counts.
1657 btree_swap_helper(fields_.count, x->fields_.count);
1658}
1659
1660////
1661// btree_iterator methods
1662template <typename N, typename R, typename P>
1663void btree_iterator<N, R, P>::increment_slow() {
1664 if (node->leaf()) {
1665 assert(position >= node->count());
1666 self_type save(*this);
1667 while (position == node->count() && !node->is_root()) {
1668 assert(node->parent()->child(node->position()) == node);
1669 position = node->position();
1670 node = node->parent();
1671 }
1672 if (position == node->count()) {
1673 *this = save;
1674 }
1675 } else {
1676 assert(position < node->count());
1677 node = node->child(position + 1);
1678 while (!node->leaf()) {
1679 node = node->child(0);
1680 }
1681 position = 0;
1682 }
1683}
1684
1685template <typename N, typename R, typename P>
1686void btree_iterator<N, R, P>::increment_by(int count) {
1687 while (count > 0) {
1688 if (node->leaf()) {
1689 int rest = node->count() - position;
1690 position += std::min(rest, count);
1691 count = count - rest;
1692 if (position < node->count()) {
1693 return;
1694 }
1695 } else {
1696 --count;
1697 }
1698 increment_slow();
1699 }
1700}
1701
1702template <typename N, typename R, typename P>
1703void btree_iterator<N, R, P>::decrement_slow() {
1704 if (node->leaf()) {
1705 assert(position <= -1);
1706 self_type save(*this);
1707 while (position < 0 && !node->is_root()) {
1708 assert(node->parent()->child(node->position()) == node);
1709 position = node->position() - 1;
1710 node = node->parent();
1711 }
1712 if (position < 0) {
1713 *this = save;
1714 }
1715 } else {
1716 assert(position >= 0);
1717 node = node->child(position);
1718 while (!node->leaf()) {
1719 node = node->child(node->count());
1720 }
1721 position = node->count() - 1;
1722 }
1723}
1724
1725////
1726// btree methods
1727template <typename P>
1728btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
1729 : key_compare(comp),
1730 root_(alloc, NULL) {
1731}
1732
1733template <typename P>
1734btree<P>::btree(const self_type &x)
1735 : key_compare(x.key_comp()),
1736 root_(x.internal_allocator(), NULL) {
1737 assign(x);
1738}
1739
1740template <typename P> template <typename ValuePointer>
1741std::pair<typename btree<P>::iterator, bool>
1742btree<P>::insert_unique(const key_type &key, ValuePointer value) {
1743 if (empty()) {
1744 *mutable_root() = new_leaf_root_node(1);
1745 }
1746
1747 std::pair<iterator, int> res = internal_locate(key, iterator(root(), 0));
1748 iterator &iter = res.first;
1749 if (res.second == kExactMatch) {
1750 // The key already exists in the tree, do nothing.
1751 return std::make_pair(internal_last(iter), false);
1752 } else if (!res.second) {
1753 iterator last = internal_last(iter);
1754 if (last.node && !compare_keys(key, last.key())) {
1755 // The key already exists in the tree, do nothing.
1756 return std::make_pair(last, false);
1757 }
1758 }
1759
1760 return std::make_pair(internal_insert(iter, *value), true);
1761}
1762
1763template <typename P>
1764inline typename btree<P>::iterator
1765btree<P>::insert_unique(iterator position, const value_type &v) {
1766 if (!empty()) {
1767 const key_type &key = params_type::key(v);
1768 if (position == end() || compare_keys(key, position.key())) {
1769 iterator prev = position;
1770 if (position == begin() || compare_keys((--prev).key(), key)) {
1771 // prev.key() < key < position.key()
1772 return internal_insert(position, v);
1773 }
1774 } else if (compare_keys(position.key(), key)) {
1775 iterator next = position;
1776 ++next;
1777 if (next == end() || compare_keys(key, next.key())) {
1778 // position.key() < key < next.key()
1779 return internal_insert(next, v);
1780 }
1781 } else {
1782 // position.key() == key
1783 return position;
1784 }
1785 }
1786 return insert_unique(v).first;
1787}
1788
1789template <typename P> template <typename InputIterator>
1790void btree<P>::insert_unique(InputIterator b, InputIterator e) {
1791 for (; b != e; ++b) {
1792 insert_unique(end(), *b);
1793 }
1794}
1795
1796template <typename P> template <typename ValuePointer>
1797typename btree<P>::iterator
1798btree<P>::insert_multi(const key_type &key, ValuePointer value) {
1799 if (empty()) {
1800 *mutable_root() = new_leaf_root_node(1);
1801 }
1802
1803 iterator iter = internal_upper_bound(key, iterator(root(), 0));
1804 if (!iter.node) {
1805 iter = end();
1806 }
1807 return internal_insert(iter, *value);
1808}
1809
1810template <typename P>
1811typename btree<P>::iterator
1812btree<P>::insert_multi(iterator position, const value_type &v) {
1813 if (!empty()) {
1814 const key_type &key = params_type::key(v);
1815 if (position == end() || !compare_keys(position.key(), key)) {
1816 iterator prev = position;
1817 if (position == begin() || !compare_keys(key, (--prev).key())) {
1818 // prev.key() <= key <= position.key()
1819 return internal_insert(position, v);
1820 }
1821 } else {
1822 iterator next = position;
1823 ++next;
1824 if (next == end() || !compare_keys(next.key(), key)) {
1825 // position.key() < key <= next.key()
1826 return internal_insert(next, v);
1827 }
1828 }
1829 }
1830 return insert_multi(v);
1831}
1832
1833template <typename P> template <typename InputIterator>
1834void btree<P>::insert_multi(InputIterator b, InputIterator e) {
1835 for (; b != e; ++b) {
1836 insert_multi(end(), *b);
1837 }
1838}
1839
1840template <typename P>
1841void btree<P>::assign(const self_type &x) {
1842 clear();
1843
1844 *mutable_key_comp() = x.key_comp();
1845 *mutable_internal_allocator() = x.internal_allocator();
1846
1847 // Assignment can avoid key comparisons because we know the order of the
1848 // values is the same order we'll store them in.
1849 for (const_iterator iter = x.begin(); iter != x.end(); ++iter) {
1850 if (empty()) {
1851 insert_multi(*iter);
1852 } else {
1853 // If the btree is not empty, we can just insert the new value at the end
1854 // of the tree!
1855 internal_insert(end(), *iter);
1856 }
1857 }
1858}
1859
1860template <typename P>
1861typename btree<P>::iterator btree<P>::erase(iterator iter) {
1862 bool internal_delete = false;
1863 if (!iter.node->leaf()) {
1864 // Deletion of a value on an internal node. Swap the key with the largest
1865 // value of our left child. This is easy, we just decrement iter.
1866 iterator tmp_iter(iter--);
1867 assert(iter.node->leaf());
1868 assert(!compare_keys(tmp_iter.key(), iter.key()));
1869 iter.node->value_swap(iter.position, tmp_iter.node, tmp_iter.position);
1870 internal_delete = true;
1871 --*mutable_size();
1872 } else if (!root()->leaf()) {
1873 --*mutable_size();
1874 }
1875
1876 // Delete the key from the leaf.
1877 iter.node->remove_value(iter.position);
1878
1879 // We want to return the next value after the one we just erased. If we
1880 // erased from an internal node (internal_delete == true), then the next
1881 // value is ++(++iter). If we erased from a leaf node (internal_delete ==
1882 // false) then the next value is ++iter. Note that ++iter may point to an
1883 // internal node and the value in the internal node may move to a leaf node
1884 // (iter.node) when rebalancing is performed at the leaf level.
1885
1886 // Merge/rebalance as we walk back up the tree.
1887 iterator res(iter);
1888 for (;;) {
1889 if (iter.node == root()) {
1890 try_shrink();
1891 if (empty()) {
1892 return end();
1893 }
1894 break;
1895 }
1896 if (iter.node->count() >= kMinNodeValues) {
1897 break;
1898 }
1899 bool merged = try_merge_or_rebalance(&iter);
1900 if (iter.node->leaf()) {
1901 res = iter;
1902 }
1903 if (!merged) {
1904 break;
1905 }
1906 iter.node = iter.node->parent();
1907 }
1908
1909 // Adjust our return value. If we're pointing at the end of a node, advance
1910 // the iterator.
1911 if (res.position == res.node->count()) {
1912 res.position = res.node->count() - 1;
1913 ++res;
1914 }
1915 // If we erased from an internal node, advance the iterator.
1916 if (internal_delete) {
1917 ++res;
1918 }
1919 return res;
1920}
1921
1922template <typename P>
1923int btree<P>::erase(iterator b, iterator e) {
1924 int count = distance(b, e);
1925 for (int i = 0; i < count; i++) {
1926 b = erase(b);
1927 }
1928 return count;
1929}
1930
1931template <typename P>
1932int btree<P>::erase_unique(const key_type &key) {
1933 iterator iter = internal_find_unique(key, iterator(root(), 0));
1934 if (!iter.node) {
1935 // The key doesn't exist in the tree, return nothing done.
1936 return 0;
1937 }
1938 erase(iter);
1939 return 1;
1940}
1941
1942template <typename P>
1943int btree<P>::erase_multi(const key_type &key) {
1944 iterator b = internal_lower_bound(key, iterator(root(), 0));
1945 if (!b.node) {
1946 // The key doesn't exist in the tree, return nothing done.
1947 return 0;
1948 }
1949 // Delete all of the keys between begin and upper_bound(key).
1950 iterator e = internal_end(
1951 internal_upper_bound(key, iterator(root(), 0)));
1952 return erase(b, e);
1953}
1954
1955template <typename P>
1956void btree<P>::clear() {
1957 if (root() != NULL) {
1958 internal_clear(root());
1959 }
1960 *mutable_root() = NULL;
1961}
1962
1963template <typename P>
1964void btree<P>::swap(self_type &x) {
1965 std::swap(static_cast<key_compare&>(*this), static_cast<key_compare&>(x));
1966 std::swap(root_, x.root_);
1967}
1968
1969template <typename P>
1970void btree<P>::verify() const {
1971 if (root() != NULL) {
1972 assert(size() == internal_verify(root(), NULL, NULL));
1973 assert(leftmost() == (++const_iterator(root(), -1)).node);
1974 assert(rightmost() == (--const_iterator(root(), root()->count())).node);
1975 assert(leftmost()->leaf());
1976 assert(rightmost()->leaf());
1977 } else {
1978 assert(size() == 0);
1979 assert(leftmost() == NULL);
1980 assert(rightmost() == NULL);
1981 }
1982}
1983
1984template <typename P>
1985void btree<P>::rebalance_or_split(iterator *iter) {
1986 node_type *&node = iter->node;
1987 int &insert_position = iter->position;
1988 assert(node->count() == node->max_count());
1989
1990 // First try to make room on the node by rebalancing.
1991 node_type *parent = node->parent();
1992 if (node != root()) {
1993 if (node->position() > 0) {
1994 // Try rebalancing with our left sibling.
1995 node_type *left = parent->child(node->position() - 1);
1996 if (left->count() < left->max_count()) {
1997 // We bias rebalancing based on the position being inserted. If we're
1998 // inserting at the end of the right node then we bias rebalancing to
1999 // fill up the left node.
2000 int to_move = (left->max_count() - left->count()) /
2001 (1 + (insert_position < left->max_count()));
2002 to_move = std::max(1, to_move);
2003
2004 if (((insert_position - to_move) >= 0) ||
2005 ((left->count() + to_move) < left->max_count())) {
2006 left->rebalance_right_to_left(node, to_move);
2007
2008 assert(node->max_count() - node->count() == to_move);
2009 insert_position = insert_position - to_move;
2010 if (insert_position < 0) {
2011 insert_position = insert_position + left->count() + 1;
2012 node = left;
2013 }
2014
2015 assert(node->count() < node->max_count());
2016 return;
2017 }
2018 }
2019 }
2020
2021 if (node->position() < parent->count()) {
2022 // Try rebalancing with our right sibling.
2023 node_type *right = parent->child(node->position() + 1);
2024 if (right->count() < right->max_count()) {
2025 // We bias rebalancing based on the position being inserted. If we're
2026 // inserting at the beginning of the left node then we bias rebalancing
2027 // to fill up the right node.
2028 int to_move = (right->max_count() - right->count()) /
2029 (1 + (insert_position > 0));
2030 to_move = std::max(1, to_move);
2031
2032 if ((insert_position <= (node->count() - to_move)) ||
2033 ((right->count() + to_move) < right->max_count())) {
2034 node->rebalance_left_to_right(right, to_move);
2035
2036 if (insert_position > node->count()) {
2037 insert_position = insert_position - node->count() - 1;
2038 node = right;
2039 }
2040
2041 assert(node->count() < node->max_count());
2042 return;
2043 }
2044 }
2045 }
2046
2047 // Rebalancing failed, make sure there is room on the parent node for a new
2048 // value.
2049 if (parent->count() == parent->max_count()) {
2050 iterator parent_iter(node->parent(), node->position());
2051 rebalance_or_split(&parent_iter);
2052 }
2053 } else {
2054 // Rebalancing not possible because this is the root node.
2055 if (root()->leaf()) {
2056 // The root node is currently a leaf node: create a new root node and set
2057 // the current root node as the child of the new root.
2058 parent = new_internal_root_node();
2059 parent->set_child(0, root());
2060 *mutable_root() = parent;
2061 assert(*mutable_rightmost() == parent->child(0));
2062 } else {
2063 // The root node is an internal node. We do not want to create a new root
2064 // node because the root node is special and holds the size of the tree
2065 // and a pointer to the rightmost node. So we create a new internal node
2066 // and move all of the items on the current root into the new node.
2067 parent = new_internal_node(parent);
2068 parent->set_child(0, parent);
2069 parent->swap(root());
2070 node = parent;
2071 }
2072 }
2073
2074 // Split the node.
2075 node_type *split_node;
2076 if (node->leaf()) {
2077 split_node = new_leaf_node(parent);
2078 node->split(split_node, insert_position);
2079 if (rightmost() == node) {
2080 *mutable_rightmost() = split_node;
2081 }
2082 } else {
2083 split_node = new_internal_node(parent);
2084 node->split(split_node, insert_position);
2085 }
2086
2087 if (insert_position > node->count()) {
2088 insert_position = insert_position - node->count() - 1;
2089 node = split_node;
2090 }
2091}
2092
2093template <typename P>
2094void btree<P>::merge_nodes(node_type *left, node_type *right) {
2095 left->merge(right);
2096 if (right->leaf()) {
2097 if (rightmost() == right) {
2098 *mutable_rightmost() = left;
2099 }
2100 delete_leaf_node(right);
2101 } else {
2102 delete_internal_node(right);
2103 }
2104}
2105
2106template <typename P>
2107bool btree<P>::try_merge_or_rebalance(iterator *iter) {
2108 node_type *parent = iter->node->parent();
2109 if (iter->node->position() > 0) {
2110 // Try merging with our left sibling.
2111 node_type *left = parent->child(iter->node->position() - 1);
2112 if ((1 + left->count() + iter->node->count()) <= left->max_count()) {
2113 iter->position += 1 + left->count();
2114 merge_nodes(left, iter->node);
2115 iter->node = left;
2116 return true;
2117 }
2118 }
2119 if (iter->node->position() < parent->count()) {
2120 // Try merging with our right sibling.
2121 node_type *right = parent->child(iter->node->position() + 1);
2122 if ((1 + iter->node->count() + right->count()) <= right->max_count()) {
2123 merge_nodes(iter->node, right);
2124 return true;
2125 }
2126 // Try rebalancing with our right sibling. We don't perform rebalancing if
2127 // we deleted the first element from iter->node and the node is not
2128 // empty. This is a small optimization for the common pattern of deleting
2129 // from the front of the tree.
2130 if ((right->count() > kMinNodeValues) &&
2131 ((iter->node->count() == 0) ||
2132 (iter->position > 0))) {
2133 int to_move = (right->count() - iter->node->count()) / 2;
2134 to_move = std::min(to_move, right->count() - 1);
2135 iter->node->rebalance_right_to_left(right, to_move);
2136 return false;
2137 }
2138 }
2139 if (iter->node->position() > 0) {
2140 // Try rebalancing with our left sibling. We don't perform rebalancing if
2141 // we deleted the last element from iter->node and the node is not
2142 // empty. This is a small optimization for the common pattern of deleting
2143 // from the back of the tree.
2144 node_type *left = parent->child(iter->node->position() - 1);
2145 if ((left->count() > kMinNodeValues) &&
2146 ((iter->node->count() == 0) ||
2147 (iter->position < iter->node->count()))) {
2148 int to_move = (left->count() - iter->node->count()) / 2;
2149 to_move = std::min(to_move, left->count() - 1);
2150 left->rebalance_left_to_right(iter->node, to_move);
2151 iter->position += to_move;
2152 return false;
2153 }
2154 }
2155 return false;
2156}
2157
2158template <typename P>
2159void btree<P>::try_shrink() {
2160 if (root()->count() > 0) {
2161 return;
2162 }
2163 // Deleted the last item on the root node, shrink the height of the tree.
2164 if (root()->leaf()) {
2165 assert(size() == 0);
2166 delete_leaf_node(root());
2167 *mutable_root() = NULL;
2168 } else {
2169 node_type *child = root()->child(0);
2170 if (child->leaf()) {
2171 // The child is a leaf node so simply make it the root node in the tree.
2172 child->make_root();
2173 delete_internal_root_node();
2174 *mutable_root() = child;
2175 } else {
2176 // The child is an internal node. We want to keep the existing root node
2177 // so we move all of the values from the child node into the existing
2178 // (empty) root node.
2179 child->swap(root());
2180 delete_internal_node(child);
2181 }
2182 }
2183}
2184
2185template <typename P> template <typename IterType>
2186inline IterType btree<P>::internal_last(IterType iter) {
2187 while (iter.node && iter.position == iter.node->count()) {
2188 iter.position = iter.node->position();
2189 iter.node = iter.node->parent();
2190 if (iter.node->leaf()) {
2191 iter.node = NULL;
2192 }
2193 }
2194 return iter;
2195}
2196
2197template <typename P>
2198inline typename btree<P>::iterator
2199btree<P>::internal_insert(iterator iter, const value_type &v) {
2200 if (!iter.node->leaf()) {
2201 // We can't insert on an internal node. Instead, we'll insert after the
2202 // previous value which is guaranteed to be on a leaf node.
2203 --iter;
2204 ++iter.position;
2205 }
2206 if (iter.node->count() == iter.node->max_count()) {
2207 // Make room in the leaf for the new item.
2208 if (iter.node->max_count() < kNodeValues) {
2209 // Insertion into the root where the root is smaller that the full node
2210 // size. Simply grow the size of the root node.
2211 assert(iter.node == root());
2212 iter.node = new_leaf_root_node(
2213 std::min<int>(kNodeValues, 2 * iter.node->max_count()));
2214 iter.node->swap(root());
2215 delete_leaf_node(root());
2216 *mutable_root() = iter.node;
2217 } else {
2218 rebalance_or_split(&iter);
2219 ++*mutable_size();
2220 }
2221 } else if (!root()->leaf()) {
2222 ++*mutable_size();
2223 }
2224 iter.node->insert_value(iter.position, v);
2225 return iter;
2226}
2227
2228template <typename P> template <typename IterType>
2229inline std::pair<IterType, int> btree<P>::internal_locate(
2230 const key_type &key, IterType iter) const {
2231 return internal_locate_type::dispatch(key, *this, iter);
2232}
2233
2234template <typename P> template <typename IterType>
2235inline std::pair<IterType, int> btree<P>::internal_locate_plain_compare(
2236 const key_type &key, IterType iter) const {
2237 for (;;) {
2238 iter.position = iter.node->lower_bound(key, key_comp());
2239 if (iter.node->leaf()) {
2240 break;
2241 }
2242 iter.node = iter.node->child(iter.position);
2243 }
2244 return std::make_pair(iter, 0);
2245}
2246
2247template <typename P> template <typename IterType>
2248inline std::pair<IterType, int> btree<P>::internal_locate_compare_to(
2249 const key_type &key, IterType iter) const {
2250 for (;;) {
2251 int res = iter.node->lower_bound(key, key_comp());
2252 iter.position = res & kMatchMask;
2253 if (res & kExactMatch) {
2254 return std::make_pair(iter, static_cast<int>(kExactMatch));
2255 }
2256 if (iter.node->leaf()) {
2257 break;
2258 }
2259 iter.node = iter.node->child(iter.position);
2260 }
2261 return std::make_pair(iter, -kExactMatch);
2262}
2263
2264template <typename P> template <typename IterType>
2265IterType btree<P>::internal_lower_bound(
2266 const key_type &key, IterType iter) const {
2267 if (iter.node) {
2268 for (;;) {
2269 iter.position =
2270 iter.node->lower_bound(key, key_comp()) & kMatchMask;
2271 if (iter.node->leaf()) {
2272 break;
2273 }
2274 iter.node = iter.node->child(iter.position);
2275 }
2276 iter = internal_last(iter);
2277 }
2278 return iter;
2279}
2280
2281template <typename P> template <typename IterType>
2282IterType btree<P>::internal_upper_bound(
2283 const key_type &key, IterType iter) const {
2284 if (iter.node) {
2285 for (;;) {
2286 iter.position = iter.node->upper_bound(key, key_comp());
2287 if (iter.node->leaf()) {
2288 break;
2289 }
2290 iter.node = iter.node->child(iter.position);
2291 }
2292 iter = internal_last(iter);
2293 }
2294 return iter;
2295}
2296
2297template <typename P> template <typename IterType>
2298IterType btree<P>::internal_find_unique(
2299 const key_type &key, IterType iter) const {
2300 if (iter.node) {
2301 std::pair<IterType, int> res = internal_locate(key, iter);
2302 if (res.second == kExactMatch) {
2303 return res.first;
2304 }
2305 if (!res.second) {
2306 iter = internal_last(res.first);
2307 if (iter.node && !compare_keys(key, iter.key())) {
2308 return iter;
2309 }
2310 }
2311 }
2312 return IterType(NULL, 0);
2313}
2314
2315template <typename P> template <typename IterType>
2316IterType btree<P>::internal_find_multi(
2317 const key_type &key, IterType iter) const {
2318 if (iter.node) {
2319 iter = internal_lower_bound(key, iter);
2320 if (iter.node) {
2321 iter = internal_last(iter);
2322 if (iter.node && !compare_keys(key, iter.key())) {
2323 return iter;
2324 }
2325 }
2326 }
2327 return IterType(NULL, 0);
2328}
2329
2330template <typename P>
2331void btree<P>::internal_clear(node_type *node) {
2332 if (!node->leaf()) {
2333 for (int i = 0; i <= node->count(); ++i) {
2334 internal_clear(node->child(i));
2335 }
2336 if (node == root()) {
2337 delete_internal_root_node();
2338 } else {
2339 delete_internal_node(node);
2340 }
2341 } else {
2342 delete_leaf_node(node);
2343 }
2344}
2345
2346template <typename P>
2347void btree<P>::internal_dump(
2348 std::ostream &os, const node_type *node, int level) const {
2349 for (int i = 0; i < node->count(); ++i) {
2350 if (!node->leaf()) {
2351 internal_dump(os, node->child(i), level + 1);
2352 }
2353 for (int j = 0; j < level; ++j) {
2354 os << " ";
2355 }
2356 os << node->key(i) << " [" << level << "]\n";
2357 }
2358 if (!node->leaf()) {
2359 internal_dump(os, node->child(node->count()), level + 1);
2360 }
2361}
2362
2363template <typename P>
2364int btree<P>::internal_verify(
2365 const node_type *node, const key_type *lo, const key_type *hi) const {
2366 assert(node->count() > 0);
2367 assert(node->count() <= node->max_count());
2368 if (lo) {
2369 assert(!compare_keys(node->key(0), *lo));
2370 }
2371 if (hi) {
2372 assert(!compare_keys(*hi, node->key(node->count() - 1)));
2373 }
2374 for (int i = 1; i < node->count(); ++i) {
2375 assert(!compare_keys(node->key(i), node->key(i - 1)));
2376 }
2377 int count = node->count();
2378 if (!node->leaf()) {
2379 for (int i = 0; i <= node->count(); ++i) {
2380 assert(node->child(i) != NULL);
2381 assert(node->child(i)->parent() == node);
2382 assert(node->child(i)->position() == i);
2383 count += internal_verify(
2384 node->child(i),
2385 (i == 0) ? lo : &node->key(i - 1),
2386 (i == node->count()) ? hi : &node->key(i));
2387 }
2388 }
2389 return count;
2390}
2391
2392} // namespace btree
2393
2394#endif // UTIL_BTREE_BTREE_H__
diff --git a/xdelta3/cpp-btree/btree_bench.cc b/xdelta3/cpp-btree/btree_bench.cc
new file mode 100644
index 0000000..6eaed99
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_bench.cc
@@ -0,0 +1,593 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <stdint.h>
16#include <stdlib.h>
17#include <algorithm>
18#include <functional>
19#include <map>
20#include <set>
21#include <string>
22#include <sys/time.h>
23#include <type_traits>
24#include <vector>
25
26#include "gflags/gflags.h"
27#include "btree_map.h"
28#include "btree_set.h"
29#include "btree_test.h"
30
31DEFINE_int32(test_random_seed, 123456789, "Seed for srand()");
32DEFINE_int32(benchmark_max_iters, 10000000, "Maximum test iterations");
33DEFINE_int32(benchmark_min_iters, 100, "Minimum test iterations");
34DEFINE_int32(benchmark_target_seconds, 1,
35 "Attempt to benchmark for this many seconds");
36
37using std::allocator;
38using std::less;
39using std::map;
40using std::max;
41using std::min;
42using std::multimap;
43using std::multiset;
44using std::set;
45using std::string;
46using std::vector;
47
48namespace btree {
49namespace {
50
51struct RandGen {
52 typedef ptrdiff_t result_type;
53 RandGen(result_type seed) {
54 srand(seed);
55 }
56 result_type operator()(result_type l) {
57 return rand() % l;
58 }
59};
60
61struct BenchmarkRun {
62 BenchmarkRun(const char *name, void (*func)(int));
63 void Run();
64 void Stop();
65 void Start();
66 void Reset();
67
68 BenchmarkRun *next_benchmark;
69 const char *benchmark_name;
70 void (*benchmark_func)(int);
71 int64_t accum_micros;
72 int64_t last_started;
73};
74
75BenchmarkRun *first_benchmark;
76BenchmarkRun *current_benchmark;
77
78int64_t get_micros () {
79 timeval tv;
80 gettimeofday(&tv, NULL);
81 return tv.tv_sec * 1000000 + tv.tv_usec;
82}
83
84BenchmarkRun::BenchmarkRun(const char *name, void (*func)(int))
85 : next_benchmark(first_benchmark),
86 benchmark_name(name),
87 benchmark_func(func),
88 accum_micros(0),
89 last_started(0) {
90 first_benchmark = this;
91}
92
93#define BTREE_BENCHMARK(name) \
94 BTREE_BENCHMARK2(#name, name, __COUNTER__)
95#define BTREE_BENCHMARK2(name, func, counter) \
96 BTREE_BENCHMARK3(name, func, counter)
97#define BTREE_BENCHMARK3(name, func, counter) \
98 BenchmarkRun bench ## counter (name, func)
99
100void StopBenchmarkTiming() {
101 current_benchmark->Stop();
102}
103
104void StartBenchmarkTiming() {
105 current_benchmark->Start();
106}
107
108void RunBenchmarks() {
109 for (BenchmarkRun *bench = first_benchmark; bench;
110 bench = bench->next_benchmark) {
111 bench->Run();
112 }
113}
114
115void BenchmarkRun::Start() {
116 assert(!last_started);
117 last_started = get_micros();
118}
119
120void BenchmarkRun::Stop() {
121 if (last_started == 0) {
122 return;
123 }
124 accum_micros += get_micros() - last_started;
125 last_started = 0;
126}
127
128void BenchmarkRun::Reset() {
129 last_started = 0;
130 accum_micros = 0;
131}
132
133void BenchmarkRun::Run() {
134 assert(current_benchmark == NULL);
135 current_benchmark = this;
136 int iters = FLAGS_benchmark_min_iters;
137 for (;;) {
138 Reset();
139 Start();
140 benchmark_func(iters);
141 Stop();
142 if (accum_micros > FLAGS_benchmark_target_seconds * 1000000 ||
143 iters >= FLAGS_benchmark_max_iters) {
144 break;
145 } else if (accum_micros == 0) {
146 iters *= 100;
147 } else {
148 int64_t target_micros = FLAGS_benchmark_target_seconds * 1000000;
149 iters = target_micros * iters / accum_micros;
150 }
151 iters = min(iters, FLAGS_benchmark_max_iters);
152 }
153 std::cout << benchmark_name << "\t"
154 << accum_micros * 1000 / iters << "\t"
155 << iters;
156 current_benchmark = NULL;
157}
158
159// Used to avoid compiler optimizations for these benchmarks.
160template <typename T>
161void sink(const T& t0) {
162 volatile T t = t0;
163}
164
165// Benchmark insertion of values into a container.
166template <typename T>
167void BM_Insert(int n) {
168 typedef typename std::remove_const<typename T::value_type>::type V;
169 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
170
171 // Disable timing while we perform some initialization.
172 StopBenchmarkTiming();
173
174 T container;
175 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values);
176 for (int i = 0; i < values.size(); i++) {
177 container.insert(values[i]);
178 }
179
180 for (int i = 0; i < n; ) {
181 // Remove and re-insert 10% of the keys
182 int m = min(n - i, FLAGS_benchmark_values / 10);
183
184 for (int j = i; j < i + m; j++) {
185 int x = j % FLAGS_benchmark_values;
186 container.erase(key_of_value(values[x]));
187 }
188
189 StartBenchmarkTiming();
190
191 for (int j = i; j < i + m; j++) {
192 int x = j % FLAGS_benchmark_values;
193 container.insert(values[x]);
194 }
195
196 StopBenchmarkTiming();
197
198 i += m;
199 }
200}
201
202// Benchmark lookup of values in a container.
203template <typename T>
204void BM_Lookup(int n) {
205 typedef typename std::remove_const<typename T::value_type>::type V;
206 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
207
208 // Disable timing while we perform some initialization.
209 StopBenchmarkTiming();
210
211 T container;
212 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values);
213
214 for (int i = 0; i < values.size(); i++) {
215 container.insert(values[i]);
216 }
217
218 V r = V();
219
220 StartBenchmarkTiming();
221
222 for (int i = 0; i < n; i++) {
223 int m = i % values.size();
224 r = *container.find(key_of_value(values[m]));
225 }
226
227 StopBenchmarkTiming();
228
229 sink(r); // Keep compiler from optimizing away r.
230}
231
232// Benchmark lookup of values in a full container, meaning that values
233// are inserted in-order to take advantage of biased insertion, which
234// yields a full tree.
235template <typename T>
236void BM_FullLookup(int n) {
237 typedef typename std::remove_const<typename T::value_type>::type V;
238 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
239
240 // Disable timing while we perform some initialization.
241 StopBenchmarkTiming();
242
243 T container;
244 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values);
245 vector<V> sorted(values);
246 sort(sorted.begin(), sorted.end());
247
248 for (int i = 0; i < sorted.size(); i++) {
249 container.insert(sorted[i]);
250 }
251
252 V r = V();
253
254 StartBenchmarkTiming();
255
256 for (int i = 0; i < n; i++) {
257 int m = i % values.size();
258 r = *container.find(key_of_value(values[m]));
259 }
260
261 StopBenchmarkTiming();
262
263 sink(r); // Keep compiler from optimizing away r.
264}
265
266// Benchmark deletion of values from a container.
267template <typename T>
268void BM_Delete(int n) {
269 typedef typename std::remove_const<typename T::value_type>::type V;
270 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
271
272 // Disable timing while we perform some initialization.
273 StopBenchmarkTiming();
274
275 T container;
276 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values);
277 for (int i = 0; i < values.size(); i++) {
278 container.insert(values[i]);
279 }
280
281 for (int i = 0; i < n; ) {
282 // Remove and re-insert 10% of the keys
283 int m = min(n - i, FLAGS_benchmark_values / 10);
284
285 StartBenchmarkTiming();
286
287 for (int j = i; j < i + m; j++) {
288 int x = j % FLAGS_benchmark_values;
289 container.erase(key_of_value(values[x]));
290 }
291
292 StopBenchmarkTiming();
293
294 for (int j = i; j < i + m; j++) {
295 int x = j % FLAGS_benchmark_values;
296 container.insert(values[x]);
297 }
298
299 i += m;
300 }
301}
302
303// Benchmark steady-state insert (into first half of range) and remove
304// (from second second half of range), treating the container
305// approximately like a queue with log-time access for all elements.
306// This benchmark does not test the case where insertion and removal
307// happen in the same region of the tree. This benchmark counts two
308// value constructors.
309template <typename T>
310void BM_QueueAddRem(int n) {
311 typedef typename std::remove_const<typename T::value_type>::type V;
312 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
313
314 // Disable timing while we perform some initialization.
315 StopBenchmarkTiming();
316 assert(FLAGS_benchmark_values % 2 == 0);
317
318 T container;
319
320 const int half = FLAGS_benchmark_values / 2;
321 vector<int> remove_keys(half);
322 vector<int> add_keys(half);
323
324 for (int i = 0; i < half; i++) {
325 remove_keys[i] = i;
326 add_keys[i] = i;
327 }
328
329 RandGen rand(FLAGS_test_random_seed);
330
331 random_shuffle(remove_keys.begin(), remove_keys.end(), rand);
332 random_shuffle(add_keys.begin(), add_keys.end(), rand);
333
334 Generator<V> g(FLAGS_benchmark_values + FLAGS_benchmark_max_iters);
335
336 for (int i = 0; i < half; i++) {
337 container.insert(g(add_keys[i]));
338 container.insert(g(half + remove_keys[i]));
339 }
340
341 // There are three parts each of size "half":
342 // 1 is being deleted from [offset - half, offset)
343 // 2 is standing [offset, offset + half)
344 // 3 is being inserted into [offset + half, offset + 2 * half)
345 int offset = 0;
346
347 StartBenchmarkTiming();
348
349 for (int i = 0; i < n; i++) {
350 int idx = i % half;
351
352 if (idx == 0) {
353 StopBenchmarkTiming();
354 random_shuffle(remove_keys.begin(), remove_keys.end(), rand);
355 random_shuffle(add_keys.begin(), add_keys.end(), rand);
356 offset += half;
357 StartBenchmarkTiming();
358 }
359
360 int e = container.erase(key_of_value(g(offset - half + remove_keys[idx])));
361 assert(e == 1);
362 container.insert(g(offset + half + add_keys[idx]));
363 }
364
365 StopBenchmarkTiming();
366}
367
368// Mixed insertion and deletion in the same range using pre-constructed values.
369template <typename T>
370void BM_MixedAddRem(int n) {
371 typedef typename std::remove_const<typename T::value_type>::type V;
372 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
373
374 // Disable timing while we perform some initialization.
375 StopBenchmarkTiming();
376 assert(FLAGS_benchmark_values % 2 == 0);
377
378 T container;
379 RandGen rand(FLAGS_test_random_seed);
380
381 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values * 2);
382
383 // Create two random shuffles
384 vector<int> remove_keys(FLAGS_benchmark_values);
385 vector<int> add_keys(FLAGS_benchmark_values);
386
387 // Insert the first half of the values (already in random order)
388 for (int i = 0; i < FLAGS_benchmark_values; i++) {
389 container.insert(values[i]);
390
391 // remove_keys and add_keys will be swapped before each round,
392 // therefore fill add_keys here w/ the keys being inserted, so
393 // they'll be the first to be removed.
394 remove_keys[i] = i + FLAGS_benchmark_values;
395 add_keys[i] = i;
396 }
397
398 StartBenchmarkTiming();
399
400 for (int i = 0; i < n; i++) {
401 int idx = i % FLAGS_benchmark_values;
402
403 if (idx == 0) {
404 StopBenchmarkTiming();
405 remove_keys.swap(add_keys);
406 random_shuffle(remove_keys.begin(), remove_keys.end(), rand);
407 random_shuffle(add_keys.begin(), add_keys.end(), rand);
408 StartBenchmarkTiming();
409 }
410
411 int e = container.erase(key_of_value(values[remove_keys[idx]]));
412 assert(e == 1);
413 container.insert(values[add_keys[idx]]);
414 }
415
416 StopBenchmarkTiming();
417}
418
419// Insertion at end, removal from the beginning. This benchmark
420// counts two value constructors.
421template <typename T>
422void BM_Fifo(int n) {
423 typedef typename std::remove_const<typename T::value_type>::type V;
424
425 // Disable timing while we perform some initialization.
426 StopBenchmarkTiming();
427
428 T container;
429 Generator<V> g(FLAGS_benchmark_values + FLAGS_benchmark_max_iters);
430
431 for (int i = 0; i < FLAGS_benchmark_values; i++) {
432 container.insert(g(i));
433 }
434
435 StartBenchmarkTiming();
436
437 for (int i = 0; i < n; i++) {
438 container.erase(container.begin());
439 container.insert(container.end(), g(i + FLAGS_benchmark_values));
440 }
441
442 StopBenchmarkTiming();
443}
444
445// Iteration (forward) through the tree
446template <typename T>
447void BM_FwdIter(int n) {
448 typedef typename std::remove_const<typename T::value_type>::type V;
449
450 // Disable timing while we perform some initialization.
451 StopBenchmarkTiming();
452
453 T container;
454 vector<V> values = GenerateValues<V>(FLAGS_benchmark_values);
455
456 for (int i = 0; i < FLAGS_benchmark_values; i++) {
457 container.insert(values[i]);
458 }
459
460 typename T::iterator iter;
461
462 V r = V();
463
464 StartBenchmarkTiming();
465
466 for (int i = 0; i < n; i++) {
467 int idx = i % FLAGS_benchmark_values;
468
469 if (idx == 0) {
470 iter = container.begin();
471 }
472 r = *iter;
473 ++iter;
474 }
475
476 StopBenchmarkTiming();
477
478 sink(r); // Keep compiler from optimizing away r.
479}
480
481typedef set<int32_t> stl_set_int32;
482typedef set<int64_t> stl_set_int64;
483typedef set<string> stl_set_string;
484
485typedef map<int32_t, intptr_t> stl_map_int32;
486typedef map<int64_t, intptr_t> stl_map_int64;
487typedef map<string, intptr_t> stl_map_string;
488
489typedef multiset<int32_t> stl_multiset_int32;
490typedef multiset<int64_t> stl_multiset_int64;
491typedef multiset<string> stl_multiset_string;
492
493typedef multimap<int32_t, intptr_t> stl_multimap_int32;
494typedef multimap<int64_t, intptr_t> stl_multimap_int64;
495typedef multimap<string, intptr_t> stl_multimap_string;
496
497#define MY_BENCHMARK_TYPES2(value, name, size) \
498 typedef btree ## _set<value, less<value>, allocator<value>, size> \
499 btree ## _ ## size ## _set_ ## name; \
500 typedef btree ## _map<value, int, less<value>, allocator<value>, size> \
501 btree ## _ ## size ## _map_ ## name; \
502 typedef btree ## _multiset<value, less<value>, allocator<value>, size> \
503 btree ## _ ## size ## _multiset_ ## name; \
504 typedef btree ## _multimap<value, int, less<value>, allocator<value>, size> \
505 btree ## _ ## size ## _multimap_ ## name
506
507#define MY_BENCHMARK_TYPES(value, name) \
508 MY_BENCHMARK_TYPES2(value, name, 128); \
509 MY_BENCHMARK_TYPES2(value, name, 160); \
510 MY_BENCHMARK_TYPES2(value, name, 192); \
511 MY_BENCHMARK_TYPES2(value, name, 224); \
512 MY_BENCHMARK_TYPES2(value, name, 256); \
513 MY_BENCHMARK_TYPES2(value, name, 288); \
514 MY_BENCHMARK_TYPES2(value, name, 320); \
515 MY_BENCHMARK_TYPES2(value, name, 352); \
516 MY_BENCHMARK_TYPES2(value, name, 384); \
517 MY_BENCHMARK_TYPES2(value, name, 416); \
518 MY_BENCHMARK_TYPES2(value, name, 448); \
519 MY_BENCHMARK_TYPES2(value, name, 480); \
520 MY_BENCHMARK_TYPES2(value, name, 512); \
521 MY_BENCHMARK_TYPES2(value, name, 1024); \
522 MY_BENCHMARK_TYPES2(value, name, 1536); \
523 MY_BENCHMARK_TYPES2(value, name, 2048)
524
525MY_BENCHMARK_TYPES(int32_t, int32);
526MY_BENCHMARK_TYPES(int64_t, int64);
527MY_BENCHMARK_TYPES(string, string);
528
529#define MY_BENCHMARK4(type, name, func) \
530 void BM_ ## type ## _ ## name(int n) { BM_ ## func <type>(n); } \
531 BTREE_BENCHMARK(BM_ ## type ## _ ## name)
532
533// Define NODESIZE_TESTING when running btree_perf.py.
534
535#ifdef NODESIZE_TESTING
536#define MY_BENCHMARK3(tree, type, name, func) \
537 MY_BENCHMARK4(tree ## _128_ ## type, name, func); \
538 MY_BENCHMARK4(tree ## _160_ ## type, name, func); \
539 MY_BENCHMARK4(tree ## _192_ ## type, name, func); \
540 MY_BENCHMARK4(tree ## _224_ ## type, name, func); \
541 MY_BENCHMARK4(tree ## _256_ ## type, name, func); \
542 MY_BENCHMARK4(tree ## _288_ ## type, name, func); \
543 MY_BENCHMARK4(tree ## _320_ ## type, name, func); \
544 MY_BENCHMARK4(tree ## _352_ ## type, name, func); \
545 MY_BENCHMARK4(tree ## _384_ ## type, name, func); \
546 MY_BENCHMARK4(tree ## _416_ ## type, name, func); \
547 MY_BENCHMARK4(tree ## _448_ ## type, name, func); \
548 MY_BENCHMARK4(tree ## _480_ ## type, name, func); \
549 MY_BENCHMARK4(tree ## _512_ ## type, name, func); \
550 MY_BENCHMARK4(tree ## _1024_ ## type, name, func); \
551 MY_BENCHMARK4(tree ## _1536_ ## type, name, func); \
552 MY_BENCHMARK4(tree ## _2048_ ## type, name, func)
553#else
554#define MY_BENCHMARK3(tree, type, name, func) \
555 MY_BENCHMARK4(tree ## _256_ ## type, name, func); \
556 MY_BENCHMARK4(tree ## _2048_ ## type, name, func)
557#endif
558
559#define MY_BENCHMARK2(type, name, func) \
560 MY_BENCHMARK4(stl_ ## type, name, func); \
561 MY_BENCHMARK3(btree, type, name, func)
562
563#define MY_BENCHMARK(type) \
564 MY_BENCHMARK2(type, insert, Insert); \
565 MY_BENCHMARK2(type, lookup, Lookup); \
566 MY_BENCHMARK2(type, fulllookup, FullLookup); \
567 MY_BENCHMARK2(type, delete, Delete); \
568 MY_BENCHMARK2(type, queueaddrem, QueueAddRem); \
569 MY_BENCHMARK2(type, mixedaddrem, MixedAddRem); \
570 MY_BENCHMARK2(type, fifo, Fifo); \
571 MY_BENCHMARK2(type, fwditer, FwdIter)
572
573MY_BENCHMARK(set_int32);
574MY_BENCHMARK(map_int32);
575MY_BENCHMARK(set_int64);
576MY_BENCHMARK(map_int64);
577MY_BENCHMARK(set_string);
578MY_BENCHMARK(map_string);
579
580MY_BENCHMARK(multiset_int32);
581MY_BENCHMARK(multimap_int32);
582MY_BENCHMARK(multiset_int64);
583MY_BENCHMARK(multimap_int64);
584MY_BENCHMARK(multiset_string);
585MY_BENCHMARK(multimap_string);
586
587} // namespace
588} // namespace btree
589
590int main(int argc, char **argv) {
591 btree::RunBenchmarks();
592 return 0;
593}
diff --git a/xdelta3/cpp-btree/btree_container.h b/xdelta3/cpp-btree/btree_container.h
new file mode 100644
index 0000000..fb617ab
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_container.h
@@ -0,0 +1,349 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef UTIL_BTREE_BTREE_CONTAINER_H__
16#define UTIL_BTREE_BTREE_CONTAINER_H__
17
18#include <iosfwd>
19#include <utility>
20
21#include "btree.h"
22
23namespace btree {
24
25// A common base class for btree_set, btree_map, btree_multiset and
26// btree_multimap.
27template <typename Tree>
28class btree_container {
29 typedef btree_container<Tree> self_type;
30
31 public:
32 typedef typename Tree::params_type params_type;
33 typedef typename Tree::key_type key_type;
34 typedef typename Tree::value_type value_type;
35 typedef typename Tree::key_compare key_compare;
36 typedef typename Tree::allocator_type allocator_type;
37 typedef typename Tree::pointer pointer;
38 typedef typename Tree::const_pointer const_pointer;
39 typedef typename Tree::reference reference;
40 typedef typename Tree::const_reference const_reference;
41 typedef typename Tree::size_type size_type;
42 typedef typename Tree::difference_type difference_type;
43 typedef typename Tree::iterator iterator;
44 typedef typename Tree::const_iterator const_iterator;
45 typedef typename Tree::reverse_iterator reverse_iterator;
46 typedef typename Tree::const_reverse_iterator const_reverse_iterator;
47
48 public:
49 // Default constructor.
50 btree_container(const key_compare &comp, const allocator_type &alloc)
51 : tree_(comp, alloc) {
52 }
53
54 // Copy constructor.
55 btree_container(const self_type &x)
56 : tree_(x.tree_) {
57 }
58
59 // Iterator routines.
60 iterator begin() { return tree_.begin(); }
61 const_iterator begin() const { return tree_.begin(); }
62 iterator end() { return tree_.end(); }
63 const_iterator end() const { return tree_.end(); }
64 reverse_iterator rbegin() { return tree_.rbegin(); }
65 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
66 reverse_iterator rend() { return tree_.rend(); }
67 const_reverse_iterator rend() const { return tree_.rend(); }
68
69 // Lookup routines.
70 iterator lower_bound(const key_type &key) {
71 return tree_.lower_bound(key);
72 }
73 const_iterator lower_bound(const key_type &key) const {
74 return tree_.lower_bound(key);
75 }
76 iterator upper_bound(const key_type &key) {
77 return tree_.upper_bound(key);
78 }
79 const_iterator upper_bound(const key_type &key) const {
80 return tree_.upper_bound(key);
81 }
82 std::pair<iterator,iterator> equal_range(const key_type &key) {
83 return tree_.equal_range(key);
84 }
85 std::pair<const_iterator,const_iterator> equal_range(const key_type &key) const {
86 return tree_.equal_range(key);
87 }
88
89 // Utility routines.
90 void clear() {
91 tree_.clear();
92 }
93 void swap(self_type &x) {
94 tree_.swap(x.tree_);
95 }
96 void dump(std::ostream &os) const {
97 tree_.dump(os);
98 }
99 void verify() const {
100 tree_.verify();
101 }
102
103 // Size routines.
104 size_type size() const { return tree_.size(); }
105 size_type max_size() const { return tree_.max_size(); }
106 bool empty() const { return tree_.empty(); }
107 size_type height() const { return tree_.height(); }
108 size_type internal_nodes() const { return tree_.internal_nodes(); }
109 size_type leaf_nodes() const { return tree_.leaf_nodes(); }
110 size_type nodes() const { return tree_.nodes(); }
111 size_type bytes_used() const { return tree_.bytes_used(); }
112 static double average_bytes_per_value() {
113 return Tree::average_bytes_per_value();
114 }
115 double fullness() const { return tree_.fullness(); }
116 double overhead() const { return tree_.overhead(); }
117
118 bool operator==(const self_type& x) const {
119 if (size() != x.size()) {
120 return false;
121 }
122 for (const_iterator i = begin(), xi = x.begin(); i != end(); ++i, ++xi) {
123 if (*i != *xi) {
124 return false;
125 }
126 }
127 return true;
128 }
129
130 bool operator!=(const self_type& other) const {
131 return !operator==(other);
132 }
133
134
135 protected:
136 Tree tree_;
137};
138
139template <typename T>
140inline std::ostream& operator<<(std::ostream &os, const btree_container<T> &b) {
141 b.dump(os);
142 return os;
143}
144
145// A common base class for btree_set and safe_btree_set.
146template <typename Tree>
147class btree_unique_container : public btree_container<Tree> {
148 typedef btree_unique_container<Tree> self_type;
149 typedef btree_container<Tree> super_type;
150
151 public:
152 typedef typename Tree::key_type key_type;
153 typedef typename Tree::value_type value_type;
154 typedef typename Tree::size_type size_type;
155 typedef typename Tree::key_compare key_compare;
156 typedef typename Tree::allocator_type allocator_type;
157 typedef typename Tree::iterator iterator;
158 typedef typename Tree::const_iterator const_iterator;
159
160 public:
161 // Default constructor.
162 btree_unique_container(const key_compare &comp = key_compare(),
163 const allocator_type &alloc = allocator_type())
164 : super_type(comp, alloc) {
165 }
166
167 // Copy constructor.
168 btree_unique_container(const self_type &x)
169 : super_type(x) {
170 }
171
172 // Range constructor.
173 template <class InputIterator>
174 btree_unique_container(InputIterator b, InputIterator e,
175 const key_compare &comp = key_compare(),
176 const allocator_type &alloc = allocator_type())
177 : super_type(comp, alloc) {
178 insert(b, e);
179 }
180
181 // Lookup routines.
182 iterator find(const key_type &key) {
183 return this->tree_.find_unique(key);
184 }
185 const_iterator find(const key_type &key) const {
186 return this->tree_.find_unique(key);
187 }
188 size_type count(const key_type &key) const {
189 return this->tree_.count_unique(key);
190 }
191
192 // Insertion routines.
193 std::pair<iterator,bool> insert(const value_type &x) {
194 return this->tree_.insert_unique(x);
195 }
196 iterator insert(iterator position, const value_type &x) {
197 return this->tree_.insert_unique(position, x);
198 }
199 template <typename InputIterator>
200 void insert(InputIterator b, InputIterator e) {
201 this->tree_.insert_unique(b, e);
202 }
203
204 // Deletion routines.
205 int erase(const key_type &key) {
206 return this->tree_.erase_unique(key);
207 }
208 // Erase the specified iterator from the btree. The iterator must be valid
209 // (i.e. not equal to end()). Return an iterator pointing to the node after
210 // the one that was erased (or end() if none exists).
211 iterator erase(const iterator &iter) {
212 return this->tree_.erase(iter);
213 }
214 void erase(const iterator &first, const iterator &last) {
215 this->tree_.erase(first, last);
216 }
217};
218
219// A common base class for btree_map and safe_btree_map.
220template <typename Tree>
221class btree_map_container : public btree_unique_container<Tree> {
222 typedef btree_map_container<Tree> self_type;
223 typedef btree_unique_container<Tree> super_type;
224
225 public:
226 typedef typename Tree::key_type key_type;
227 typedef typename Tree::data_type data_type;
228 typedef typename Tree::value_type value_type;
229 typedef typename Tree::mapped_type mapped_type;
230 typedef typename Tree::key_compare key_compare;
231 typedef typename Tree::allocator_type allocator_type;
232
233 private:
234 // A pointer-like object which only generates its value when
235 // dereferenced. Used by operator[] to avoid constructing an empty data_type
236 // if the key already exists in the map.
237 struct generate_value {
238 generate_value(const key_type &k)
239 : key(k) {
240 }
241 value_type operator*() const {
242 return std::make_pair(key, data_type());
243 }
244 const key_type &key;
245 };
246
247 public:
248 // Default constructor.
249 btree_map_container(const key_compare &comp = key_compare(),
250 const allocator_type &alloc = allocator_type())
251 : super_type(comp, alloc) {
252 }
253
254 // Copy constructor.
255 btree_map_container(const self_type &x)
256 : super_type(x) {
257 }
258
259 // Range constructor.
260 template <class InputIterator>
261 btree_map_container(InputIterator b, InputIterator e,
262 const key_compare &comp = key_compare(),
263 const allocator_type &alloc = allocator_type())
264 : super_type(b, e, comp, alloc) {
265 }
266
267 // Insertion routines.
268 data_type& operator[](const key_type &key) {
269 return this->tree_.insert_unique(key, generate_value(key)).first->second;
270 }
271};
272
273// A common base class for btree_multiset and btree_multimap.
274template <typename Tree>
275class btree_multi_container : public btree_container<Tree> {
276 typedef btree_multi_container<Tree> self_type;
277 typedef btree_container<Tree> super_type;
278
279 public:
280 typedef typename Tree::key_type key_type;
281 typedef typename Tree::value_type value_type;
282 typedef typename Tree::size_type size_type;
283 typedef typename Tree::key_compare key_compare;
284 typedef typename Tree::allocator_type allocator_type;
285 typedef typename Tree::iterator iterator;
286 typedef typename Tree::const_iterator const_iterator;
287
288 public:
289 // Default constructor.
290 btree_multi_container(const key_compare &comp = key_compare(),
291 const allocator_type &alloc = allocator_type())
292 : super_type(comp, alloc) {
293 }
294
295 // Copy constructor.
296 btree_multi_container(const self_type &x)
297 : super_type(x) {
298 }
299
300 // Range constructor.
301 template <class InputIterator>
302 btree_multi_container(InputIterator b, InputIterator e,
303 const key_compare &comp = key_compare(),
304 const allocator_type &alloc = allocator_type())
305 : super_type(comp, alloc) {
306 insert(b, e);
307 }
308
309 // Lookup routines.
310 iterator find(const key_type &key) {
311 return this->tree_.find_multi(key);
312 }
313 const_iterator find(const key_type &key) const {
314 return this->tree_.find_multi(key);
315 }
316 size_type count(const key_type &key) const {
317 return this->tree_.count_multi(key);
318 }
319
320 // Insertion routines.
321 iterator insert(const value_type &x) {
322 return this->tree_.insert_multi(x);
323 }
324 iterator insert(iterator position, const value_type &x) {
325 return this->tree_.insert_multi(position, x);
326 }
327 template <typename InputIterator>
328 void insert(InputIterator b, InputIterator e) {
329 this->tree_.insert_multi(b, e);
330 }
331
332 // Deletion routines.
333 int erase(const key_type &key) {
334 return this->tree_.erase_multi(key);
335 }
336 // Erase the specified iterator from the btree. The iterator must be valid
337 // (i.e. not equal to end()). Return an iterator pointing to the node after
338 // the one that was erased (or end() if none exists).
339 iterator erase(const iterator &iter) {
340 return this->tree_.erase(iter);
341 }
342 void erase(const iterator &first, const iterator &last) {
343 this->tree_.erase(first, last);
344 }
345};
346
347} // namespace btree
348
349#endif // UTIL_BTREE_BTREE_CONTAINER_H__
diff --git a/xdelta3/cpp-btree/btree_map.h b/xdelta3/cpp-btree/btree_map.h
new file mode 100644
index 0000000..b83489f
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_map.h
@@ -0,0 +1,130 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// A btree_map<> implements the STL unique sorted associative container
16// interface and the pair associative container interface (a.k.a map<>) using a
17// btree. A btree_multimap<> implements the STL multiple sorted associative
18// container interface and the pair associtive container interface (a.k.a
19// multimap<>) using a btree. See btree.h for details of the btree
20// implementation and caveats.
21
22#ifndef UTIL_BTREE_BTREE_MAP_H__
23#define UTIL_BTREE_BTREE_MAP_H__
24
25#include <algorithm>
26#include <functional>
27#include <memory>
28#include <string>
29#include <utility>
30
31#include "btree.h"
32#include "btree_container.h"
33
34namespace btree {
35
36// The btree_map class is needed mainly for its constructors.
37template <typename Key, typename Value,
38 typename Compare = std::less<Key>,
39 typename Alloc = std::allocator<std::pair<const Key, Value> >,
40 int TargetNodeSize = 256>
41class btree_map : public btree_map_container<
42 btree<btree_map_params<Key, Value, Compare, Alloc, TargetNodeSize> > > {
43
44 typedef btree_map<Key, Value, Compare, Alloc, TargetNodeSize> self_type;
45 typedef btree_map_params<
46 Key, Value, Compare, Alloc, TargetNodeSize> params_type;
47 typedef btree<params_type> btree_type;
48 typedef btree_map_container<btree_type> super_type;
49
50 public:
51 typedef typename btree_type::key_compare key_compare;
52 typedef typename btree_type::allocator_type allocator_type;
53
54 public:
55 // Default constructor.
56 btree_map(const key_compare &comp = key_compare(),
57 const allocator_type &alloc = allocator_type())
58 : super_type(comp, alloc) {
59 }
60
61 // Copy constructor.
62 btree_map(const self_type &x)
63 : super_type(x) {
64 }
65
66 // Range constructor.
67 template <class InputIterator>
68 btree_map(InputIterator b, InputIterator e,
69 const key_compare &comp = key_compare(),
70 const allocator_type &alloc = allocator_type())
71 : super_type(b, e, comp, alloc) {
72 }
73};
74
75template <typename K, typename V, typename C, typename A, int N>
76inline void swap(btree_map<K, V, C, A, N> &x,
77 btree_map<K, V, C, A, N> &y) {
78 x.swap(y);
79}
80
81// The btree_multimap class is needed mainly for its constructors.
82template <typename Key, typename Value,
83 typename Compare = std::less<Key>,
84 typename Alloc = std::allocator<std::pair<const Key, Value> >,
85 int TargetNodeSize = 256>
86class btree_multimap : public btree_multi_container<
87 btree<btree_map_params<Key, Value, Compare, Alloc, TargetNodeSize> > > {
88
89 typedef btree_multimap<Key, Value, Compare, Alloc, TargetNodeSize> self_type;
90 typedef btree_map_params<
91 Key, Value, Compare, Alloc, TargetNodeSize> params_type;
92 typedef btree<params_type> btree_type;
93 typedef btree_multi_container<btree_type> super_type;
94
95 public:
96 typedef typename btree_type::key_compare key_compare;
97 typedef typename btree_type::allocator_type allocator_type;
98 typedef typename btree_type::data_type data_type;
99 typedef typename btree_type::mapped_type mapped_type;
100
101 public:
102 // Default constructor.
103 btree_multimap(const key_compare &comp = key_compare(),
104 const allocator_type &alloc = allocator_type())
105 : super_type(comp, alloc) {
106 }
107
108 // Copy constructor.
109 btree_multimap(const self_type &x)
110 : super_type(x) {
111 }
112
113 // Range constructor.
114 template <class InputIterator>
115 btree_multimap(InputIterator b, InputIterator e,
116 const key_compare &comp = key_compare(),
117 const allocator_type &alloc = allocator_type())
118 : super_type(b, e, comp, alloc) {
119 }
120};
121
122template <typename K, typename V, typename C, typename A, int N>
123inline void swap(btree_multimap<K, V, C, A, N> &x,
124 btree_multimap<K, V, C, A, N> &y) {
125 x.swap(y);
126}
127
128} // namespace btree
129
130#endif // UTIL_BTREE_BTREE_MAP_H__
diff --git a/xdelta3/cpp-btree/btree_set.h b/xdelta3/cpp-btree/btree_set.h
new file mode 100644
index 0000000..f9b2e75
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_set.h
@@ -0,0 +1,121 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// A btree_set<> implements the STL unique sorted associative container
16// interface (a.k.a set<>) using a btree. A btree_multiset<> implements the STL
17// multiple sorted associative container interface (a.k.a multiset<>) using a
18// btree. See btree.h for details of the btree implementation and caveats.
19
20#ifndef UTIL_BTREE_BTREE_SET_H__
21#define UTIL_BTREE_BTREE_SET_H__
22
23#include <functional>
24#include <memory>
25#include <string>
26
27#include "btree.h"
28#include "btree_container.h"
29
30namespace btree {
31
32// The btree_set class is needed mainly for its constructors.
33template <typename Key,
34 typename Compare = std::less<Key>,
35 typename Alloc = std::allocator<Key>,
36 int TargetNodeSize = 256>
37class btree_set : public btree_unique_container<
38 btree<btree_set_params<Key, Compare, Alloc, TargetNodeSize> > > {
39
40 typedef btree_set<Key, Compare, Alloc, TargetNodeSize> self_type;
41 typedef btree_set_params<Key, Compare, Alloc, TargetNodeSize> params_type;
42 typedef btree<params_type> btree_type;
43 typedef btree_unique_container<btree_type> super_type;
44
45 public:
46 typedef typename btree_type::key_compare key_compare;
47 typedef typename btree_type::allocator_type allocator_type;
48
49 public:
50 // Default constructor.
51 btree_set(const key_compare &comp = key_compare(),
52 const allocator_type &alloc = allocator_type())
53 : super_type(comp, alloc) {
54 }
55
56 // Copy constructor.
57 btree_set(const self_type &x)
58 : super_type(x) {
59 }
60
61 // Range constructor.
62 template <class InputIterator>
63 btree_set(InputIterator b, InputIterator e,
64 const key_compare &comp = key_compare(),
65 const allocator_type &alloc = allocator_type())
66 : super_type(b, e, comp, alloc) {
67 }
68};
69
70template <typename K, typename C, typename A, int N>
71inline void swap(btree_set<K, C, A, N> &x, btree_set<K, C, A, N> &y) {
72 x.swap(y);
73}
74
75// The btree_multiset class is needed mainly for its constructors.
76template <typename Key,
77 typename Compare = std::less<Key>,
78 typename Alloc = std::allocator<Key>,
79 int TargetNodeSize = 256>
80class btree_multiset : public btree_multi_container<
81 btree<btree_set_params<Key, Compare, Alloc, TargetNodeSize> > > {
82
83 typedef btree_multiset<Key, Compare, Alloc, TargetNodeSize> self_type;
84 typedef btree_set_params<Key, Compare, Alloc, TargetNodeSize> params_type;
85 typedef btree<params_type> btree_type;
86 typedef btree_multi_container<btree_type> super_type;
87
88 public:
89 typedef typename btree_type::key_compare key_compare;
90 typedef typename btree_type::allocator_type allocator_type;
91
92 public:
93 // Default constructor.
94 btree_multiset(const key_compare &comp = key_compare(),
95 const allocator_type &alloc = allocator_type())
96 : super_type(comp, alloc) {
97 }
98
99 // Copy constructor.
100 btree_multiset(const self_type &x)
101 : super_type(x) {
102 }
103
104 // Range constructor.
105 template <class InputIterator>
106 btree_multiset(InputIterator b, InputIterator e,
107 const key_compare &comp = key_compare(),
108 const allocator_type &alloc = allocator_type())
109 : super_type(b, e, comp, alloc) {
110 }
111};
112
113template <typename K, typename C, typename A, int N>
114inline void swap(btree_multiset<K, C, A, N> &x,
115 btree_multiset<K, C, A, N> &y) {
116 x.swap(y);
117}
118
119} // namespace btree
120
121#endif // UTIL_BTREE_BTREE_SET_H__
diff --git a/xdelta3/cpp-btree/btree_test.cc b/xdelta3/cpp-btree/btree_test.cc
new file mode 100644
index 0000000..6b1837d
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_test.cc
@@ -0,0 +1,270 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "gtest/gtest.h"
16#include "btree_map.h"
17#include "btree_set.h"
18#include "btree_test.h"
19
20namespace btree {
21namespace {
22
23template <typename K, int N>
24void SetTest() {
25 typedef TestAllocator<K> TestAlloc;
26 ASSERT_EQ(sizeof(btree_set<K>), sizeof(void*));
27 BtreeTest<btree_set<K, std::less<K>, std::allocator<K>, N>, std::set<K> >();
28 BtreeAllocatorTest<btree_set<K, std::less<K>, TestAlloc, N> >();
29}
30
31template <typename K, int N>
32void MapTest() {
33 typedef TestAllocator<K> TestAlloc;
34 ASSERT_EQ(sizeof(btree_map<K, K>), sizeof(void*));
35 BtreeTest<btree_map<K, K, std::less<K>, std::allocator<K>, N>, std::map<K, K> >();
36 BtreeAllocatorTest<btree_map<K, K, std::less<K>, TestAlloc, N> >();
37 BtreeMapTest<btree_map<K, K, std::less<K>, std::allocator<K>, N> >();
38}
39
40TEST(Btree, set_int32_32) { SetTest<int32_t, 32>(); }
41TEST(Btree, set_int32_64) { SetTest<int32_t, 64>(); }
42TEST(Btree, set_int32_128) { SetTest<int32_t, 128>(); }
43TEST(Btree, set_int32_256) { SetTest<int32_t, 256>(); }
44TEST(Btree, set_int64_256) { SetTest<int64_t, 256>(); }
45TEST(Btree, set_string_256) { SetTest<std::string, 256>(); }
46TEST(Btree, set_pair_256) { SetTest<std::pair<int, int>, 256>(); }
47TEST(Btree, map_int32_256) { MapTest<int32_t, 256>(); }
48TEST(Btree, map_int64_256) { MapTest<int64_t, 256>(); }
49TEST(Btree, map_string_256) { MapTest<std::string, 256>(); }
50TEST(Btree, map_pair_256) { MapTest<std::pair<int, int>, 256>(); }
51
52// Large-node tests
53TEST(Btree, map_int32_1024) { MapTest<int32_t, 1024>(); }
54TEST(Btree, map_int32_1032) { MapTest<int32_t, 1032>(); }
55TEST(Btree, map_int32_1040) { MapTest<int32_t, 1040>(); }
56TEST(Btree, map_int32_1048) { MapTest<int32_t, 1048>(); }
57TEST(Btree, map_int32_1056) { MapTest<int32_t, 1056>(); }
58
59TEST(Btree, map_int32_2048) { MapTest<int32_t, 2048>(); }
60TEST(Btree, map_int32_4096) { MapTest<int32_t, 4096>(); }
61TEST(Btree, set_int32_1024) { SetTest<int32_t, 1024>(); }
62TEST(Btree, set_int32_2048) { SetTest<int32_t, 2048>(); }
63TEST(Btree, set_int32_4096) { SetTest<int32_t, 4096>(); }
64TEST(Btree, map_string_1024) { MapTest<std::string, 1024>(); }
65TEST(Btree, map_string_2048) { MapTest<std::string, 2048>(); }
66TEST(Btree, map_string_4096) { MapTest<std::string, 4096>(); }
67TEST(Btree, set_string_1024) { SetTest<std::string, 1024>(); }
68TEST(Btree, set_string_2048) { SetTest<std::string, 2048>(); }
69TEST(Btree, set_string_4096) { SetTest<std::string, 4096>(); }
70
71template <typename K, int N>
72void MultiSetTest() {
73 typedef TestAllocator<K> TestAlloc;
74 ASSERT_EQ(sizeof(btree_multiset<K>), sizeof(void*));
75 BtreeMultiTest<btree_multiset<K, std::less<K>, std::allocator<K>, N>,
76 std::multiset<K> >();
77 BtreeAllocatorTest<btree_multiset<K, std::less<K>, TestAlloc, N> >();
78}
79
80template <typename K, int N>
81void MultiMapTest() {
82 typedef TestAllocator<K> TestAlloc;
83 ASSERT_EQ(sizeof(btree_multimap<K, K>), sizeof(void*));
84 BtreeMultiTest<btree_multimap<K, K, std::less<K>, std::allocator<K>, N>,
85 std::multimap<K, K> >();
86 BtreeMultiMapTest<btree_multimap<K, K, std::less<K>, std::allocator<K>, N> >();
87 BtreeAllocatorTest<btree_multimap<K, K, std::less<K>, TestAlloc, N> >();
88}
89
90TEST(Btree, multiset_int32_256) { MultiSetTest<int32_t, 256>(); }
91TEST(Btree, multiset_int64_256) { MultiSetTest<int64_t, 256>(); }
92TEST(Btree, multiset_string_256) { MultiSetTest<std::string, 256>(); }
93TEST(Btree, multiset_pair_256) { MultiSetTest<std::pair<int, int>, 256>(); }
94TEST(Btree, multimap_int32_256) { MultiMapTest<int32_t, 256>(); }
95TEST(Btree, multimap_int64_256) { MultiMapTest<int64_t, 256>(); }
96TEST(Btree, multimap_string_256) { MultiMapTest<std::string, 256>(); }
97TEST(Btree, multimap_pair_256) { MultiMapTest<std::pair<int, int>, 256>(); }
98
99// Large-node tests
100TEST(Btree, multimap_int32_1024) { MultiMapTest<int32_t, 1024>(); }
101TEST(Btree, multimap_int32_2048) { MultiMapTest<int32_t, 2048>(); }
102TEST(Btree, multimap_int32_4096) { MultiMapTest<int32_t, 4096>(); }
103TEST(Btree, multiset_int32_1024) { MultiSetTest<int32_t, 1024>(); }
104TEST(Btree, multiset_int32_2048) { MultiSetTest<int32_t, 2048>(); }
105TEST(Btree, multiset_int32_4096) { MultiSetTest<int32_t, 4096>(); }
106TEST(Btree, multimap_string_1024) { MultiMapTest<std::string, 1024>(); }
107TEST(Btree, multimap_string_2048) { MultiMapTest<std::string, 2048>(); }
108TEST(Btree, multimap_string_4096) { MultiMapTest<std::string, 4096>(); }
109TEST(Btree, multiset_string_1024) { MultiSetTest<std::string, 1024>(); }
110TEST(Btree, multiset_string_2048) { MultiSetTest<std::string, 2048>(); }
111TEST(Btree, multiset_string_4096) { MultiSetTest<std::string, 4096>(); }
112
113// Verify that swapping btrees swaps the key comparision functors.
114struct SubstringLess {
115 SubstringLess() : n(2) {}
116 SubstringLess(size_t length)
117 : n(length) {
118 }
119 bool operator()(const std::string &a, const std::string &b) const {
120 std::string as(a.data(), std::min(n, a.size()));
121 std::string bs(b.data(), std::min(n, b.size()));
122 return as < bs;
123 }
124 size_t n;
125};
126
127TEST(Btree, SwapKeyCompare) {
128 typedef btree_set<std::string, SubstringLess> SubstringSet;
129 SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());
130 SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());
131
132 ASSERT_TRUE(s1.insert("a").second);
133 ASSERT_FALSE(s1.insert("aa").second);
134
135 ASSERT_TRUE(s2.insert("a").second);
136 ASSERT_TRUE(s2.insert("aa").second);
137 ASSERT_FALSE(s2.insert("aaa").second);
138
139 swap(s1, s2);
140
141 ASSERT_TRUE(s1.insert("b").second);
142 ASSERT_TRUE(s1.insert("bb").second);
143 ASSERT_FALSE(s1.insert("bbb").second);
144
145 ASSERT_TRUE(s2.insert("b").second);
146 ASSERT_FALSE(s2.insert("bb").second);
147}
148
149TEST(Btree, UpperBoundRegression) {
150 // Regress a bug where upper_bound would default-construct a new key_compare
151 // instead of copying the existing one.
152 typedef btree_set<std::string, SubstringLess> SubstringSet;
153 SubstringSet my_set(SubstringLess(3));
154 my_set.insert("aab");
155 my_set.insert("abb");
156 // We call upper_bound("aaa"). If this correctly uses the length 3
157 // comparator, aaa < aab < abb, so we should get aab as the result.
158 // If it instead uses the default-constructed length 2 comparator,
159 // aa == aa < ab, so we'll get abb as our result.
160 SubstringSet::iterator it = my_set.upper_bound("aaa");
161 ASSERT_TRUE(it != my_set.end());
162 EXPECT_EQ("aab", *it);
163}
164
165
166TEST(Btree, IteratorIncrementBy) {
167 // Test that increment_by returns the same position as increment.
168 const int kSetSize = 2341;
169 btree_set<int32_t> my_set;
170 for (int i = 0; i < kSetSize; ++i) {
171 my_set.insert(i);
172 }
173
174 {
175 // Simple increment vs. increment by.
176 btree_set<int32_t>::iterator a = my_set.begin();
177 btree_set<int32_t>::iterator b = my_set.begin();
178 a.increment();
179 b.increment_by(1);
180 EXPECT_EQ(*a, *b);
181 }
182
183 btree_set<int32_t>::iterator a = my_set.begin();
184 for (int i = 1; i < kSetSize; ++i) {
185 ++a;
186 // increment_by
187 btree_set<int32_t>::iterator b = my_set.begin();
188 b.increment_by(i);
189 EXPECT_EQ(*a, *b) << ": i=" << i;
190 }
191}
192
193TEST(Btree, Comparison) {
194 const int kSetSize = 1201;
195 btree_set<int64_t> my_set;
196 for (int i = 0; i < kSetSize; ++i) {
197 my_set.insert(i);
198 }
199 btree_set<int64_t> my_set_copy(my_set);
200 EXPECT_TRUE(my_set_copy == my_set);
201 EXPECT_TRUE(my_set == my_set_copy);
202 EXPECT_FALSE(my_set_copy != my_set);
203 EXPECT_FALSE(my_set != my_set_copy);
204
205 my_set.insert(kSetSize);
206 EXPECT_FALSE(my_set_copy == my_set);
207 EXPECT_FALSE(my_set == my_set_copy);
208 EXPECT_TRUE(my_set_copy != my_set);
209 EXPECT_TRUE(my_set != my_set_copy);
210
211 my_set.erase(kSetSize - 1);
212 EXPECT_FALSE(my_set_copy == my_set);
213 EXPECT_FALSE(my_set == my_set_copy);
214 EXPECT_TRUE(my_set_copy != my_set);
215 EXPECT_TRUE(my_set != my_set_copy);
216
217 btree_map<std::string, int64_t> my_map;
218 for (int i = 0; i < kSetSize; ++i) {
219 my_map[std::string(i, 'a')] = i;
220 }
221 btree_map<std::string, int64_t> my_map_copy(my_map);
222 EXPECT_TRUE(my_map_copy == my_map);
223 EXPECT_TRUE(my_map == my_map_copy);
224 EXPECT_FALSE(my_map_copy != my_map);
225 EXPECT_FALSE(my_map != my_map_copy);
226
227 ++my_map_copy[std::string(7, 'a')];
228 EXPECT_FALSE(my_map_copy == my_map);
229 EXPECT_FALSE(my_map == my_map_copy);
230 EXPECT_TRUE(my_map_copy != my_map);
231 EXPECT_TRUE(my_map != my_map_copy);
232
233 my_map_copy = my_map;
234 my_map["hello"] = kSetSize;
235 EXPECT_FALSE(my_map_copy == my_map);
236 EXPECT_FALSE(my_map == my_map_copy);
237 EXPECT_TRUE(my_map_copy != my_map);
238 EXPECT_TRUE(my_map != my_map_copy);
239
240 my_map.erase(std::string(kSetSize - 1, 'a'));
241 EXPECT_FALSE(my_map_copy == my_map);
242 EXPECT_FALSE(my_map == my_map_copy);
243 EXPECT_TRUE(my_map_copy != my_map);
244 EXPECT_TRUE(my_map != my_map_copy);
245}
246
247TEST(Btree, RangeCtorSanity) {
248 typedef btree_set<int, std::less<int>, std::allocator<int>, 256> test_set;
249 typedef btree_map<int, int, std::less<int>, std::allocator<int>, 256>
250 test_map;
251 typedef btree_multiset<int, std::less<int>, std::allocator<int>, 256>
252 test_mset;
253 typedef btree_multimap<int, int, std::less<int>, std::allocator<int>, 256>
254 test_mmap;
255 std::vector<int> ivec;
256 ivec.push_back(1);
257 std::map<int, int> imap;
258 imap.insert(std::make_pair(1, 2));
259 test_mset tmset(ivec.begin(), ivec.end());
260 test_mmap tmmap(imap.begin(), imap.end());
261 test_set tset(ivec.begin(), ivec.end());
262 test_map tmap(imap.begin(), imap.end());
263 EXPECT_EQ(1, tmset.size());
264 EXPECT_EQ(1, tmmap.size());
265 EXPECT_EQ(1, tset.size());
266 EXPECT_EQ(1, tmap.size());
267}
268
269} // namespace
270} // namespace btree
diff --git a/xdelta3/cpp-btree/btree_test.h b/xdelta3/cpp-btree/btree_test.h
new file mode 100644
index 0000000..413dc3c
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_test.h
@@ -0,0 +1,940 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef UTIL_BTREE_BTREE_TEST_H__
16#define UTIL_BTREE_BTREE_TEST_H__
17
18#include <stdio.h>
19#include <algorithm>
20#include <functional>
21#include <type_traits>
22#include <iosfwd>
23#include <map>
24#include <set>
25#include <sstream>
26#include <string>
27#include <utility>
28#include <vector>
29
30#include "gtest/gtest.h"
31#include "gflags/gflags.h"
32#include "btree_container.h"
33
34DECLARE_int32(test_values);
35DECLARE_int32(benchmark_values);
36
37namespace std {
38
39// Provide operator<< support for std::pair<T, U>.
40template <typename T, typename U>
41ostream& operator<<(ostream &os, const std::pair<T, U> &p) {
42 os << "(" << p.first << "," << p.second << ")";
43 return os;
44}
45
46// Provide pair equality testing that works as long as x.first is comparable to
47// y.first and x.second is comparable to y.second. Needed in the test for
48// comparing std::pair<T, U> to std::pair<const T, U>.
49template <typename T, typename U, typename V, typename W>
50bool operator==(const std::pair<T, U> &x, const std::pair<V, W> &y) {
51 return x.first == y.first && x.second == y.second;
52}
53
54// Partial specialization of remove_const that propagates the removal through
55// std::pair.
56template <typename T, typename U>
57struct remove_const<pair<T, U> > {
58 typedef pair<typename remove_const<T>::type,
59 typename remove_const<U>::type> type;
60};
61
62} // namespace std
63
64namespace btree {
65
66// Select the first member of a pair.
67template <class _Pair>
68struct select1st : public std::unary_function<_Pair, typename _Pair::first_type> {
69 const typename _Pair::first_type& operator()(const _Pair& __x) const {
70 return __x.first;
71 }
72};
73
74// Utility class to provide an accessor for a key given a value. The default
75// behavior is to treat the value as a pair and return the first element.
76template <typename K, typename V>
77struct KeyOfValue {
78 typedef select1st<V> type;
79};
80
81template <typename T>
82struct identity {
83 inline const T& operator()(const T& t) const { return t; }
84};
85
86// Partial specialization of KeyOfValue class for when the key and value are
87// the same type such as in set<> and btree_set<>.
88template <typename K>
89struct KeyOfValue<K, K> {
90 typedef identity<K> type;
91};
92
93// Counts the number of occurances of "c" in a buffer.
94inline ptrdiff_t strcount(const char* buf_begin, const char* buf_end, char c) {
95 if (buf_begin == NULL)
96 return 0;
97 if (buf_end <= buf_begin)
98 return 0;
99 ptrdiff_t num = 0;
100 for (const char* bp = buf_begin; bp != buf_end; bp++) {
101 if (*bp == c)
102 num++;
103 }
104 return num;
105}
106
107// for when the string is not null-terminated.
108inline ptrdiff_t strcount(const char* buf, size_t len, char c) {
109 return strcount(buf, buf + len, c);
110}
111
112inline ptrdiff_t strcount(const std::string& buf, char c) {
113 return strcount(buf.c_str(), buf.size(), c);
114}
115
116// The base class for a sorted associative container checker. TreeType is the
117// container type to check and CheckerType is the container type to check
118// against. TreeType is expected to be btree_{set,map,multiset,multimap} and
119// CheckerType is expected to be {set,map,multiset,multimap}.
120template <typename TreeType, typename CheckerType>
121class base_checker {
122 typedef base_checker<TreeType, CheckerType> self_type;
123
124 public:
125 typedef typename TreeType::key_type key_type;
126 typedef typename TreeType::value_type value_type;
127 typedef typename TreeType::key_compare key_compare;
128 typedef typename TreeType::pointer pointer;
129 typedef typename TreeType::const_pointer const_pointer;
130 typedef typename TreeType::reference reference;
131 typedef typename TreeType::const_reference const_reference;
132 typedef typename TreeType::size_type size_type;
133 typedef typename TreeType::difference_type difference_type;
134 typedef typename TreeType::iterator iterator;
135 typedef typename TreeType::const_iterator const_iterator;
136 typedef typename TreeType::reverse_iterator reverse_iterator;
137 typedef typename TreeType::const_reverse_iterator const_reverse_iterator;
138
139 public:
140 // Default constructor.
141 base_checker()
142 : const_tree_(tree_) {
143 }
144 // Copy constructor.
145 base_checker(const self_type &x)
146 : tree_(x.tree_),
147 const_tree_(tree_),
148 checker_(x.checker_) {
149 }
150 // Range constructor.
151 template <typename InputIterator>
152 base_checker(InputIterator b, InputIterator e)
153 : tree_(b, e),
154 const_tree_(tree_),
155 checker_(b, e) {
156 }
157
158 // Iterator routines.
159 iterator begin() { return tree_.begin(); }
160 const_iterator begin() const { return tree_.begin(); }
161 iterator end() { return tree_.end(); }
162 const_iterator end() const { return tree_.end(); }
163 reverse_iterator rbegin() { return tree_.rbegin(); }
164 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
165 reverse_iterator rend() { return tree_.rend(); }
166 const_reverse_iterator rend() const { return tree_.rend(); }
167
168 // Helper routines.
169 template <typename IterType, typename CheckerIterType>
170 IterType iter_check(
171 IterType tree_iter, CheckerIterType checker_iter) const {
172 if (tree_iter == tree_.end()) {
173 EXPECT_EQ(checker_iter, checker_.end());
174 } else {
175 EXPECT_EQ(*tree_iter, *checker_iter);
176 }
177 return tree_iter;
178 }
179 template <typename IterType, typename CheckerIterType>
180 IterType riter_check(
181 IterType tree_iter, CheckerIterType checker_iter) const {
182 if (tree_iter == tree_.rend()) {
183 EXPECT_EQ(checker_iter, checker_.rend());
184 } else {
185 EXPECT_EQ(*tree_iter, *checker_iter);
186 }
187 return tree_iter;
188 }
189 void value_check(const value_type &x) {
190 typename KeyOfValue<typename TreeType::key_type,
191 typename TreeType::value_type>::type key_of_value;
192 const key_type &key = key_of_value(x);
193 EXPECT_EQ(*find(key), x);
194 lower_bound(key);
195 upper_bound(key);
196 equal_range(key);
197 count(key);
198 }
199 void erase_check(const key_type &key) {
200 EXPECT_TRUE(tree_.find(key) == const_tree_.end());
201 EXPECT_TRUE(const_tree_.find(key) == tree_.end());
202 EXPECT_TRUE(tree_.equal_range(key).first ==
203 const_tree_.equal_range(key).second);
204 }
205
206 // Lookup routines.
207 iterator lower_bound(const key_type &key) {
208 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
209 }
210 const_iterator lower_bound(const key_type &key) const {
211 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
212 }
213 iterator upper_bound(const key_type &key) {
214 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
215 }
216 const_iterator upper_bound(const key_type &key) const {
217 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
218 }
219 std::pair<iterator,iterator> equal_range(const key_type &key) {
220 std::pair<typename CheckerType::iterator,
221 typename CheckerType::iterator> checker_res =
222 checker_.equal_range(key);
223 std::pair<iterator, iterator> tree_res = tree_.equal_range(key);
224 iter_check(tree_res.first, checker_res.first);
225 iter_check(tree_res.second, checker_res.second);
226 return tree_res;
227 }
228 std::pair<const_iterator,const_iterator> equal_range(const key_type &key) const {
229 std::pair<typename CheckerType::const_iterator,
230 typename CheckerType::const_iterator> checker_res =
231 checker_.equal_range(key);
232 std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key);
233 iter_check(tree_res.first, checker_res.first);
234 iter_check(tree_res.second, checker_res.second);
235 return tree_res;
236 }
237 iterator find(const key_type &key) {
238 return iter_check(tree_.find(key), checker_.find(key));
239 }
240 const_iterator find(const key_type &key) const {
241 return iter_check(tree_.find(key), checker_.find(key));
242 }
243 size_type count(const key_type &key) const {
244 size_type res = checker_.count(key);
245 EXPECT_EQ(res, tree_.count(key));
246 return res;
247 }
248
249 // Assignment operator.
250 self_type& operator=(const self_type &x) {
251 tree_ = x.tree_;
252 checker_ = x.checker_;
253 return *this;
254 }
255
256 // Deletion routines.
257 int erase(const key_type &key) {
258 int size = tree_.size();
259 int res = checker_.erase(key);
260 EXPECT_EQ(res, tree_.count(key));
261 EXPECT_EQ(res, tree_.erase(key));
262 EXPECT_EQ(tree_.count(key), 0);
263 EXPECT_EQ(tree_.size(), size - res);
264 erase_check(key);
265 return res;
266 }
267 iterator erase(iterator iter) {
268 key_type key = iter.key();
269 int size = tree_.size();
270 int count = tree_.count(key);
271 typename CheckerType::iterator checker_iter = checker_.find(key);
272 for (iterator tmp(tree_.find(key)); tmp != iter; ++tmp) {
273 ++checker_iter;
274 }
275 typename CheckerType::iterator checker_next = checker_iter;
276 ++checker_next;
277 checker_.erase(checker_iter);
278 iter = tree_.erase(iter);
279 EXPECT_EQ(tree_.size(), checker_.size());
280 EXPECT_EQ(tree_.size(), size - 1);
281 EXPECT_EQ(tree_.count(key), count - 1);
282 if (count == 1) {
283 erase_check(key);
284 }
285 return iter_check(iter, checker_next);
286 }
287
288 void erase(iterator begin, iterator end) {
289 int size = tree_.size();
290 int count = distance(begin, end);
291 typename CheckerType::iterator checker_begin = checker_.find(begin.key());
292 for (iterator tmp(tree_.find(begin.key())); tmp != begin; ++tmp) {
293 ++checker_begin;
294 }
295 typename CheckerType::iterator checker_end =
296 end == tree_.end() ? checker_.end() : checker_.find(end.key());
297 if (end != tree_.end()) {
298 for (iterator tmp(tree_.find(end.key())); tmp != end; ++tmp) {
299 ++checker_end;
300 }
301 }
302 checker_.erase(checker_begin, checker_end);
303 tree_.erase(begin, end);
304 EXPECT_EQ(tree_.size(), checker_.size());
305 EXPECT_EQ(tree_.size(), size - count);
306 }
307
308 // Utility routines.
309 void clear() {
310 tree_.clear();
311 checker_.clear();
312 }
313 void swap(self_type &x) {
314 tree_.swap(x.tree_);
315 checker_.swap(x.checker_);
316 }
317
318 void verify() const {
319 tree_.verify();
320 EXPECT_EQ(tree_.size(), checker_.size());
321
322 // Move through the forward iterators using increment.
323 typename CheckerType::const_iterator
324 checker_iter(checker_.begin());
325 const_iterator tree_iter(tree_.begin());
326 for (; tree_iter != tree_.end();
327 ++tree_iter, ++checker_iter) {
328 EXPECT_EQ(*tree_iter, *checker_iter);
329 }
330
331 // Move through the forward iterators using decrement.
332 for (int n = tree_.size() - 1; n >= 0; --n) {
333 iter_check(tree_iter, checker_iter);
334 --tree_iter;
335 --checker_iter;
336 }
337 EXPECT_TRUE(tree_iter == tree_.begin());
338 EXPECT_TRUE(checker_iter == checker_.begin());
339
340 // Move through the reverse iterators using increment.
341 typename CheckerType::const_reverse_iterator
342 checker_riter(checker_.rbegin());
343 const_reverse_iterator tree_riter(tree_.rbegin());
344 for (; tree_riter != tree_.rend();
345 ++tree_riter, ++checker_riter) {
346 EXPECT_EQ(*tree_riter, *checker_riter);
347 }
348
349 // Move through the reverse iterators using decrement.
350 for (int n = tree_.size() - 1; n >= 0; --n) {
351 riter_check(tree_riter, checker_riter);
352 --tree_riter;
353 --checker_riter;
354 }
355 EXPECT_EQ(tree_riter, tree_.rbegin());
356 EXPECT_EQ(checker_riter, checker_.rbegin());
357 }
358
359 // Access to the underlying btree.
360 const TreeType& tree() const { return tree_; }
361
362 // Size routines.
363 size_type size() const {
364 EXPECT_EQ(tree_.size(), checker_.size());
365 return tree_.size();
366 }
367 size_type max_size() const { return tree_.max_size(); }
368 bool empty() const {
369 EXPECT_EQ(tree_.empty(), checker_.empty());
370 return tree_.empty();
371 }
372 size_type height() const { return tree_.height(); }
373 size_type internal_nodes() const { return tree_.internal_nodes(); }
374 size_type leaf_nodes() const { return tree_.leaf_nodes(); }
375 size_type nodes() const { return tree_.nodes(); }
376 size_type bytes_used() const { return tree_.bytes_used(); }
377 double fullness() const { return tree_.fullness(); }
378 double overhead() const { return tree_.overhead(); }
379
380 protected:
381 TreeType tree_;
382 const TreeType &const_tree_;
383 CheckerType checker_;
384};
385
386// A checker for unique sorted associative containers. TreeType is expected to
387// be btree_{set,map} and CheckerType is expected to be {set,map}.
388template <typename TreeType, typename CheckerType>
389class unique_checker : public base_checker<TreeType, CheckerType> {
390 typedef base_checker<TreeType, CheckerType> super_type;
391 typedef unique_checker<TreeType, CheckerType> self_type;
392
393 public:
394 typedef typename super_type::iterator iterator;
395 typedef typename super_type::value_type value_type;
396
397 public:
398 // Default constructor.
399 unique_checker()
400 : super_type() {
401 }
402 // Copy constructor.
403 unique_checker(const self_type &x)
404 : super_type(x) {
405 }
406 // Range constructor.
407 template <class InputIterator>
408 unique_checker(InputIterator b, InputIterator e)
409 : super_type(b, e) {
410 }
411
412 // Insertion routines.
413 std::pair<iterator,bool> insert(const value_type &x) {
414 int size = this->tree_.size();
415 std::pair<typename CheckerType::iterator,bool> checker_res =
416 this->checker_.insert(x);
417 std::pair<iterator,bool> tree_res = this->tree_.insert(x);
418 EXPECT_EQ(*tree_res.first, *checker_res.first);
419 EXPECT_EQ(tree_res.second, checker_res.second);
420 EXPECT_EQ(this->tree_.size(), this->checker_.size());
421 EXPECT_EQ(this->tree_.size(), size + tree_res.second);
422 return tree_res;
423 }
424 iterator insert(iterator position, const value_type &x) {
425 int size = this->tree_.size();
426 std::pair<typename CheckerType::iterator,bool> checker_res =
427 this->checker_.insert(x);
428 iterator tree_res = this->tree_.insert(position, x);
429 EXPECT_EQ(*tree_res, *checker_res.first);
430 EXPECT_EQ(this->tree_.size(), this->checker_.size());
431 EXPECT_EQ(this->tree_.size(), size + checker_res.second);
432 return tree_res;
433 }
434 template <typename InputIterator>
435 void insert(InputIterator b, InputIterator e) {
436 for (; b != e; ++b) {
437 insert(*b);
438 }
439 }
440};
441
442// A checker for multiple sorted associative containers. TreeType is expected
443// to be btree_{multiset,multimap} and CheckerType is expected to be
444// {multiset,multimap}.
445template <typename TreeType, typename CheckerType>
446class multi_checker : public base_checker<TreeType, CheckerType> {
447 typedef base_checker<TreeType, CheckerType> super_type;
448 typedef multi_checker<TreeType, CheckerType> self_type;
449
450 public:
451 typedef typename super_type::iterator iterator;
452 typedef typename super_type::value_type value_type;
453
454 public:
455 // Default constructor.
456 multi_checker()
457 : super_type() {
458 }
459 // Copy constructor.
460 multi_checker(const self_type &x)
461 : super_type(x) {
462 }
463 // Range constructor.
464 template <class InputIterator>
465 multi_checker(InputIterator b, InputIterator e)
466 : super_type(b, e) {
467 }
468
469 // Insertion routines.
470 iterator insert(const value_type &x) {
471 int size = this->tree_.size();
472 typename CheckerType::iterator checker_res = this->checker_.insert(x);
473 iterator tree_res = this->tree_.insert(x);
474 EXPECT_EQ(*tree_res, *checker_res);
475 EXPECT_EQ(this->tree_.size(), this->checker_.size());
476 EXPECT_EQ(this->tree_.size(), size + 1);
477 return tree_res;
478 }
479 iterator insert(iterator position, const value_type &x) {
480 int size = this->tree_.size();
481 typename CheckerType::iterator checker_res = this->checker_.insert(x);
482 iterator tree_res = this->tree_.insert(position, x);
483 EXPECT_EQ(*tree_res, *checker_res);
484 EXPECT_EQ(this->tree_.size(), this->checker_.size());
485 EXPECT_EQ(this->tree_.size(), size + 1);
486 return tree_res;
487 }
488 template <typename InputIterator>
489 void insert(InputIterator b, InputIterator e) {
490 for (; b != e; ++b) {
491 insert(*b);
492 }
493 }
494};
495
496char* GenerateDigits(char buf[16], int val, int maxval) {
497 EXPECT_LE(val, maxval);
498 int p = 15;
499 buf[p--] = 0;
500 while (maxval > 0) {
501 buf[p--] = '0' + (val % 10);
502 val /= 10;
503 maxval /= 10;
504 }
505 return buf + p + 1;
506}
507
508template <typename K>
509struct Generator {
510 int maxval;
511 Generator(int m)
512 : maxval(m) {
513 }
514 K operator()(int i) const {
515 EXPECT_LE(i, maxval);
516 return i;
517 }
518};
519
520template <>
521struct Generator<std::string> {
522 int maxval;
523 Generator(int m)
524 : maxval(m) {
525 }
526 std::string operator()(int i) const {
527 char buf[16];
528 return GenerateDigits(buf, i, maxval);
529 }
530};
531
532template <typename T, typename U>
533struct Generator<std::pair<T, U> > {
534 Generator<typename std::remove_const<T>::type> tgen;
535 Generator<typename std::remove_const<U>::type> ugen;
536
537 Generator(int m)
538 : tgen(m),
539 ugen(m) {
540 }
541 std::pair<T, U> operator()(int i) const {
542 return std::make_pair(tgen(i), ugen(i));
543 }
544};
545
546// Generate values for our tests and benchmarks. Value range is [0, maxval].
547const std::vector<int>& GenerateNumbers(int n, int maxval) {
548 static std::vector<int> values;
549 static std::set<int> unique_values;
550
551 if (values.size() < n) {
552
553 for (int i = values.size(); i < n; i++) {
554 int value;
555 do {
556 value = rand() % (maxval + 1);
557 } while (unique_values.find(value) != unique_values.end());
558
559 values.push_back(value);
560 unique_values.insert(value);
561 }
562 }
563
564 return values;
565}
566
567// Generates values in the range
568// [0, 4 * min(FLAGS_benchmark_values, FLAGS_test_values)]
569template <typename V>
570std::vector<V> GenerateValues(int n) {
571 int two_times_max = 2 * std::max(FLAGS_benchmark_values, FLAGS_test_values);
572 int four_times_max = 2 * two_times_max;
573 EXPECT_LE(n, two_times_max);
574 const std::vector<int> &nums = GenerateNumbers(n, four_times_max);
575 Generator<V> gen(four_times_max);
576 std::vector<V> vec;
577
578 for (int i = 0; i < n; i++) {
579 vec.push_back(gen(nums[i]));
580 }
581
582 return vec;
583}
584
585template <typename T, typename V>
586void DoTest(const char *name, T *b, const std::vector<V> &values) {
587 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
588
589 T &mutable_b = *b;
590 const T &const_b = *b;
591
592 // Test insert.
593 for (int i = 0; i < values.size(); ++i) {
594 mutable_b.insert(values[i]);
595 mutable_b.value_check(values[i]);
596 }
597 assert(mutable_b.size() == values.size());
598
599 const_b.verify();
600 printf(" %s fullness=%0.2f overhead=%0.2f bytes-per-value=%0.2f\n",
601 name, const_b.fullness(), const_b.overhead(),
602 double(const_b.bytes_used()) / const_b.size());
603
604 // Test copy constructor.
605 T b_copy(const_b);
606 EXPECT_EQ(b_copy.size(), const_b.size());
607 EXPECT_LE(b_copy.height(), const_b.height());
608 EXPECT_LE(b_copy.internal_nodes(), const_b.internal_nodes());
609 EXPECT_LE(b_copy.leaf_nodes(), const_b.leaf_nodes());
610 for (int i = 0; i < values.size(); ++i) {
611 EXPECT_EQ(*b_copy.find(key_of_value(values[i])), values[i]);
612 }
613
614 // Test range constructor.
615 T b_range(const_b.begin(), const_b.end());
616 EXPECT_EQ(b_range.size(), const_b.size());
617 EXPECT_LE(b_range.height(), const_b.height());
618 EXPECT_LE(b_range.internal_nodes(), const_b.internal_nodes());
619 EXPECT_LE(b_range.leaf_nodes(), const_b.leaf_nodes());
620 for (int i = 0; i < values.size(); ++i) {
621 EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]);
622 }
623
624 // Test range insertion for values that already exist.
625 b_range.insert(b_copy.begin(), b_copy.end());
626 b_range.verify();
627
628 // Test range insertion for new values.
629 b_range.clear();
630 b_range.insert(b_copy.begin(), b_copy.end());
631 EXPECT_EQ(b_range.size(), b_copy.size());
632 EXPECT_EQ(b_range.height(), b_copy.height());
633 EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes());
634 EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes());
635 for (int i = 0; i < values.size(); ++i) {
636 EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]);
637 }
638
639 // Test assignment to self. Nothing should change.
640 b_range.operator=(b_range);
641 EXPECT_EQ(b_range.size(), b_copy.size());
642 EXPECT_EQ(b_range.height(), b_copy.height());
643 EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes());
644 EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes());
645
646 // Test assignment of new values.
647 b_range.clear();
648 b_range = b_copy;
649 EXPECT_EQ(b_range.size(), b_copy.size());
650 EXPECT_EQ(b_range.height(), b_copy.height());
651 EXPECT_EQ(b_range.internal_nodes(), b_copy.internal_nodes());
652 EXPECT_EQ(b_range.leaf_nodes(), b_copy.leaf_nodes());
653
654 // Test swap.
655 b_range.clear();
656 b_range.swap(b_copy);
657 EXPECT_EQ(b_copy.size(), 0);
658 EXPECT_EQ(b_range.size(), const_b.size());
659 for (int i = 0; i < values.size(); ++i) {
660 EXPECT_EQ(*b_range.find(key_of_value(values[i])), values[i]);
661 }
662 b_range.swap(b_copy);
663
664 // Test erase via values.
665 for (int i = 0; i < values.size(); ++i) {
666 mutable_b.erase(key_of_value(values[i]));
667 // Erasing a non-existent key should have no effect.
668 EXPECT_EQ(mutable_b.erase(key_of_value(values[i])), 0);
669 }
670
671 const_b.verify();
672 EXPECT_EQ(const_b.internal_nodes(), 0);
673 EXPECT_EQ(const_b.leaf_nodes(), 0);
674 EXPECT_EQ(const_b.size(), 0);
675
676 // Test erase via iterators.
677 mutable_b = b_copy;
678 for (int i = 0; i < values.size(); ++i) {
679 mutable_b.erase(mutable_b.find(key_of_value(values[i])));
680 }
681
682 const_b.verify();
683 EXPECT_EQ(const_b.internal_nodes(), 0);
684 EXPECT_EQ(const_b.leaf_nodes(), 0);
685 EXPECT_EQ(const_b.size(), 0);
686
687 // Test insert with hint.
688 for (int i = 0; i < values.size(); i++) {
689 mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]);
690 }
691
692 const_b.verify();
693
694 // Test dumping of the btree to an ostream. There should be 1 line for each
695 // value.
696 std::stringstream strm;
697 strm << mutable_b.tree();
698 EXPECT_EQ(mutable_b.size(), strcount(strm.str(), '\n'));
699
700 // Test range erase.
701 mutable_b.erase(mutable_b.begin(), mutable_b.end());
702 EXPECT_EQ(mutable_b.size(), 0);
703 const_b.verify();
704
705 // First half.
706 mutable_b = b_copy;
707 typename T::iterator mutable_iter_end = mutable_b.begin();
708 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end;
709 mutable_b.erase(mutable_b.begin(), mutable_iter_end);
710 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2);
711 const_b.verify();
712
713 // Second half.
714 mutable_b = b_copy;
715 typename T::iterator mutable_iter_begin = mutable_b.begin();
716 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin;
717 mutable_b.erase(mutable_iter_begin, mutable_b.end());
718 EXPECT_EQ(mutable_b.size(), values.size() / 2);
719 const_b.verify();
720
721 // Second quarter.
722 mutable_b = b_copy;
723 mutable_iter_begin = mutable_b.begin();
724 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin;
725 mutable_iter_end = mutable_iter_begin;
726 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end;
727 mutable_b.erase(mutable_iter_begin, mutable_iter_end);
728 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4);
729 const_b.verify();
730
731 mutable_b.clear();
732}
733
734template <typename T>
735void ConstTest() {
736 typedef typename T::value_type value_type;
737 typename KeyOfValue<typename T::key_type, value_type>::type key_of_value;
738
739 T mutable_b;
740 const T &const_b = mutable_b;
741
742 // Insert a single value into the container and test looking it up.
743 value_type value = Generator<value_type>(2)(2);
744 mutable_b.insert(value);
745 EXPECT_TRUE(mutable_b.find(key_of_value(value)) != const_b.end());
746 EXPECT_TRUE(const_b.find(key_of_value(value)) != mutable_b.end());
747 EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value);
748 EXPECT_TRUE(const_b.upper_bound(key_of_value(value)) == const_b.end());
749 EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value);
750
751 // We can only create a non-const iterator from a non-const container.
752 typename T::iterator mutable_iter(mutable_b.begin());
753 EXPECT_TRUE(mutable_iter == const_b.begin());
754 EXPECT_TRUE(mutable_iter != const_b.end());
755 EXPECT_TRUE(const_b.begin() == mutable_iter);
756 EXPECT_TRUE(const_b.end() != mutable_iter);
757 typename T::reverse_iterator mutable_riter(mutable_b.rbegin());
758 EXPECT_TRUE(mutable_riter == const_b.rbegin());
759 EXPECT_TRUE(mutable_riter != const_b.rend());
760 EXPECT_TRUE(const_b.rbegin() == mutable_riter);
761 EXPECT_TRUE(const_b.rend() != mutable_riter);
762
763 // We can create a const iterator from a non-const iterator.
764 typename T::const_iterator const_iter(mutable_iter);
765 EXPECT_TRUE(const_iter == mutable_b.begin());
766 EXPECT_TRUE(const_iter != mutable_b.end());
767 EXPECT_TRUE(mutable_b.begin() == const_iter);
768 EXPECT_TRUE(mutable_b.end() != const_iter);
769 typename T::const_reverse_iterator const_riter(mutable_riter);
770 EXPECT_EQ(const_riter, mutable_b.rbegin());
771 EXPECT_TRUE(const_riter != mutable_b.rend());
772 EXPECT_EQ(mutable_b.rbegin(), const_riter);
773 EXPECT_TRUE(mutable_b.rend() != const_riter);
774
775 // Make sure various methods can be invoked on a const container.
776 const_b.verify();
777 EXPECT_FALSE(const_b.empty());
778 EXPECT_EQ(const_b.size(), 1);
779 EXPECT_GT(const_b.max_size(), 0);
780 EXPECT_EQ(const_b.height(), 1);
781 EXPECT_EQ(const_b.count(key_of_value(value)), 1);
782 EXPECT_EQ(const_b.internal_nodes(), 0);
783 EXPECT_EQ(const_b.leaf_nodes(), 1);
784 EXPECT_EQ(const_b.nodes(), 1);
785 EXPECT_GT(const_b.bytes_used(), 0);
786 EXPECT_GT(const_b.fullness(), 0);
787 EXPECT_GT(const_b.overhead(), 0);
788}
789
790template <typename T, typename C>
791void BtreeTest() {
792 ConstTest<T>();
793
794 typedef typename std::remove_const<typename T::value_type>::type V;
795 std::vector<V> random_values = GenerateValues<V>(FLAGS_test_values);
796
797 unique_checker<T, C> container;
798
799 // Test key insertion/deletion in sorted order.
800 std::vector<V> sorted_values(random_values);
801 sort(sorted_values.begin(), sorted_values.end());
802 DoTest("sorted: ", &container, sorted_values);
803
804 // Test key insertion/deletion in reverse sorted order.
805 reverse(sorted_values.begin(), sorted_values.end());
806 DoTest("rsorted: ", &container, sorted_values);
807
808 // Test key insertion/deletion in random order.
809 DoTest("random: ", &container, random_values);
810}
811
812template <typename T, typename C>
813void BtreeMultiTest() {
814 ConstTest<T>();
815
816 typedef typename std::remove_const<typename T::value_type>::type V;
817 const std::vector<V>& random_values = GenerateValues<V>(FLAGS_test_values);
818
819 multi_checker<T, C> container;
820
821 // Test keys in sorted order.
822 std::vector<V> sorted_values(random_values);
823 sort(sorted_values.begin(), sorted_values.end());
824 DoTest("sorted: ", &container, sorted_values);
825
826 // Test keys in reverse sorted order.
827 reverse(sorted_values.begin(), sorted_values.end());
828 DoTest("rsorted: ", &container, sorted_values);
829
830 // Test keys in random order.
831 DoTest("random: ", &container, random_values);
832
833 // Test keys in random order w/ duplicates.
834 std::vector<V> duplicate_values(random_values);
835 duplicate_values.insert(
836 duplicate_values.end(), random_values.begin(), random_values.end());
837 DoTest("duplicates:", &container, duplicate_values);
838
839 // Test all identical keys.
840 std::vector<V> identical_values(100);
841 fill(identical_values.begin(), identical_values.end(), Generator<V>(2)(2));
842 DoTest("identical: ", &container, identical_values);
843}
844
845template <typename T, typename Alloc = std::allocator<T> >
846class TestAllocator : public Alloc {
847 public:
848 typedef typename Alloc::pointer pointer;
849 typedef typename Alloc::size_type size_type;
850
851 TestAllocator() : bytes_used_(NULL) { }
852 TestAllocator(int64_t *bytes_used) : bytes_used_(bytes_used) { }
853
854 // Constructor used for rebinding
855 template <class U>
856 TestAllocator(const TestAllocator<U>& x)
857 : Alloc(x),
858 bytes_used_(x.bytes_used()) {
859 }
860
861 pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) {
862 EXPECT_TRUE(bytes_used_ != NULL);
863 *bytes_used_ += n * sizeof(T);
864 return Alloc::allocate(n, hint);
865 }
866
867 void deallocate(pointer p, size_type n) {
868 Alloc::deallocate(p, n);
869 EXPECT_TRUE(bytes_used_ != NULL);
870 *bytes_used_ -= n * sizeof(T);
871 }
872
873 // Rebind allows an allocator<T> to be used for a different type
874 template <class U> struct rebind {
875 typedef TestAllocator<U, typename Alloc::template rebind<U>::other> other;
876 };
877
878 int64_t* bytes_used() const { return bytes_used_; }
879
880 private:
881 int64_t *bytes_used_;
882};
883
884template <typename T>
885void BtreeAllocatorTest() {
886 typedef typename T::value_type value_type;
887
888 int64_t alloc1 = 0;
889 int64_t alloc2 = 0;
890 T b1(typename T::key_compare(), &alloc1);
891 T b2(typename T::key_compare(), &alloc2);
892
893 // This should swap the allocators!
894 swap(b1, b2);
895
896 for (int i = 0; i < 1000; i++) {
897 b1.insert(Generator<value_type>(1000)(i));
898 }
899
900 // We should have allocated out of alloc2!
901 EXPECT_LE(b1.bytes_used(), alloc2 + sizeof(b1));
902 EXPECT_GT(alloc2, alloc1);
903}
904
905template <typename T>
906void BtreeMapTest() {
907 typedef typename T::value_type value_type;
908 typedef typename T::mapped_type mapped_type;
909
910 mapped_type m = Generator<mapped_type>(0)(0);
911 (void) m;
912
913 T b;
914
915 // Verify we can insert using operator[].
916 for (int i = 0; i < 1000; i++) {
917 value_type v = Generator<value_type>(1000)(i);
918 b[v.first] = v.second;
919 }
920 EXPECT_EQ(b.size(), 1000);
921
922 // Test whether we can use the "->" operator on iterators and
923 // reverse_iterators. This stresses the btree_map_params::pair_pointer
924 // mechanism.
925 EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first);
926 EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second);
927 EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first);
928 EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second);
929}
930
931template <typename T>
932void BtreeMultiMapTest() {
933 typedef typename T::mapped_type mapped_type;
934 mapped_type m = Generator<mapped_type>(0)(0);
935 (void) m;
936}
937
938} // namespace btree
939
940#endif // UTIL_BTREE_BTREE_TEST_H__
diff --git a/xdelta3/cpp-btree/btree_test_flags.cc b/xdelta3/cpp-btree/btree_test_flags.cc
new file mode 100644
index 0000000..bf608a9
--- /dev/null
+++ b/xdelta3/cpp-btree/btree_test_flags.cc
@@ -0,0 +1,20 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "gflags/gflags.h"
16
17DEFINE_int32(test_values, 10000,
18 "The number of values to use for tests.");
19DEFINE_int32(benchmark_values, 1000000,
20 "The number of values to use for benchmarks.");
diff --git a/xdelta3/cpp-btree/safe_btree.h b/xdelta3/cpp-btree/safe_btree.h
new file mode 100644
index 0000000..2d85c70
--- /dev/null
+++ b/xdelta3/cpp-btree/safe_btree.h
@@ -0,0 +1,395 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// A safe_btree<> wraps around a btree<> and removes the caveat that insertion
16// and deletion invalidate iterators. A safe_btree<> maintains a generation
17// number that is incremented on every mutation. A safe_btree<>::iterator keeps
18// a pointer to the safe_btree<> it came from, the generation of the tree when
19// it was last validated and the key the underlying btree<>::iterator points
20// to. If an iterator is accessed and its generation differs from the tree
21// generation it is revalidated.
22//
23// References and pointers returned by safe_btree iterators are not safe.
24//
25// See the incorrect usage examples mentioned in safe_btree_set.h and
26// safe_btree_map.h.
27
28#ifndef UTIL_BTREE_SAFE_BTREE_H__
29#define UTIL_BTREE_SAFE_BTREE_H__
30
31#include <stddef.h>
32#include <iosfwd>
33#include <utility>
34
35#include "btree.h"
36
37namespace btree {
38
39template <typename Tree, typename Iterator>
40class safe_btree_iterator {
41 public:
42 typedef typename Iterator::key_type key_type;
43 typedef typename Iterator::value_type value_type;
44 typedef typename Iterator::size_type size_type;
45 typedef typename Iterator::difference_type difference_type;
46 typedef typename Iterator::pointer pointer;
47 typedef typename Iterator::reference reference;
48 typedef typename Iterator::const_pointer const_pointer;
49 typedef typename Iterator::const_reference const_reference;
50 typedef typename Iterator::iterator_category iterator_category;
51 typedef typename Tree::iterator iterator;
52 typedef typename Tree::const_iterator const_iterator;
53 typedef safe_btree_iterator<Tree, Iterator> self_type;
54
55 void update() const {
56 if (iter_ != tree_->internal_btree()->end()) {
57 // A positive generation indicates a valid key.
58 generation_ = tree_->generation();
59 key_ = iter_.key();
60 } else {
61 // Use a negative generation to indicate iter_ points to end().
62 generation_ = -tree_->generation();
63 }
64 }
65
66 public:
67 safe_btree_iterator()
68 : generation_(0),
69 key_(),
70 iter_(),
71 tree_(NULL) {
72 }
73 safe_btree_iterator(const iterator &x)
74 : generation_(x.generation()),
75 key_(x.key()),
76 iter_(x.iter()),
77 tree_(x.tree()) {
78 }
79 safe_btree_iterator(Tree *tree, const Iterator &iter)
80 : generation_(),
81 key_(),
82 iter_(iter),
83 tree_(tree) {
84 update();
85 }
86
87 Tree* tree() const { return tree_; }
88 int64_t generation() const { return generation_; }
89
90 Iterator* mutable_iter() const {
91 if (generation_ != tree_->generation()) {
92 if (generation_ > 0) {
93 // This does the wrong thing for a multi{set,map}. If my iter was
94 // pointing to the 2nd of 2 values with the same key, then this will
95 // reset it to point to the first. This is why we don't provide a
96 // safe_btree_multi{set,map}.
97 iter_ = tree_->internal_btree()->lower_bound(key_);
98 update();
99 } else if (-generation_ != tree_->generation()) {
100 iter_ = tree_->internal_btree()->end();
101 generation_ = -tree_->generation();
102 }
103 }
104 return &iter_;
105 }
106 const Iterator& iter() const {
107 return *mutable_iter();
108 }
109
110 // Equality/inequality operators.
111 bool operator==(const const_iterator &x) const {
112 return iter() == x.iter();
113 }
114 bool operator!=(const const_iterator &x) const {
115 return iter() != x.iter();
116 }
117
118 // Accessors for the key/value the iterator is pointing at.
119 const key_type& key() const {
120 return key_;
121 }
122 // This reference value is potentially invalidated by any non-const
123 // method on the tree; it is NOT safe.
124 reference operator*() const {
125 assert(generation_ > 0);
126 return iter().operator*();
127 }
128 // This pointer value is potentially invalidated by any non-const
129 // method on the tree; it is NOT safe.
130 pointer operator->() const {
131 assert(generation_ > 0);
132 return iter().operator->();
133 }
134
135 // Increment/decrement operators.
136 self_type& operator++() {
137 ++(*mutable_iter());
138 update();
139 return *this;
140 }
141 self_type& operator--() {
142 --(*mutable_iter());
143 update();
144 return *this;
145 }
146 self_type operator++(int) {
147 self_type tmp = *this;
148 ++*this;
149 return tmp;
150 }
151 self_type operator--(int) {
152 self_type tmp = *this;
153 --*this;
154 return tmp;
155 }
156
157 private:
158 // The generation of the tree when "iter" was updated.
159 mutable int64_t generation_;
160 // The key the iterator points to.
161 mutable key_type key_;
162 // The underlying iterator.
163 mutable Iterator iter_;
164 // The tree the iterator is associated with.
165 Tree *tree_;
166};
167
168template <typename Params>
169class safe_btree {
170 typedef safe_btree<Params> self_type;
171
172 typedef btree<Params> btree_type;
173 typedef typename btree_type::iterator tree_iterator;
174 typedef typename btree_type::const_iterator tree_const_iterator;
175
176 public:
177 typedef typename btree_type::params_type params_type;
178 typedef typename btree_type::key_type key_type;
179 typedef typename btree_type::data_type data_type;
180 typedef typename btree_type::mapped_type mapped_type;
181 typedef typename btree_type::value_type value_type;
182 typedef typename btree_type::key_compare key_compare;
183 typedef typename btree_type::allocator_type allocator_type;
184 typedef typename btree_type::pointer pointer;
185 typedef typename btree_type::const_pointer const_pointer;
186 typedef typename btree_type::reference reference;
187 typedef typename btree_type::const_reference const_reference;
188 typedef typename btree_type::size_type size_type;
189 typedef typename btree_type::difference_type difference_type;
190 typedef safe_btree_iterator<self_type, tree_iterator> iterator;
191 typedef safe_btree_iterator<
192 const self_type, tree_const_iterator> const_iterator;
193 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
194 typedef std::reverse_iterator<iterator> reverse_iterator;
195
196 public:
197 // Default constructor.
198 safe_btree(const key_compare &comp, const allocator_type &alloc)
199 : tree_(comp, alloc),
200 generation_(1) {
201 }
202
203 // Copy constructor.
204 safe_btree(const self_type &x)
205 : tree_(x.tree_),
206 generation_(1) {
207 }
208
209 iterator begin() {
210 return iterator(this, tree_.begin());
211 }
212 const_iterator begin() const {
213 return const_iterator(this, tree_.begin());
214 }
215 iterator end() {
216 return iterator(this, tree_.end());
217 }
218 const_iterator end() const {
219 return const_iterator(this, tree_.end());
220 }
221 reverse_iterator rbegin() {
222 return reverse_iterator(end());
223 }
224 const_reverse_iterator rbegin() const {
225 return const_reverse_iterator(end());
226 }
227 reverse_iterator rend() {
228 return reverse_iterator(begin());
229 }
230 const_reverse_iterator rend() const {
231 return const_reverse_iterator(begin());
232 }
233
234 // Lookup routines.
235 iterator lower_bound(const key_type &key) {
236 return iterator(this, tree_.lower_bound(key));
237 }
238 const_iterator lower_bound(const key_type &key) const {
239 return const_iterator(this, tree_.lower_bound(key));
240 }
241 iterator upper_bound(const key_type &key) {
242 return iterator(this, tree_.upper_bound(key));
243 }
244 const_iterator upper_bound(const key_type &key) const {
245 return const_iterator(this, tree_.upper_bound(key));
246 }
247 std::pair<iterator, iterator> equal_range(const key_type &key) {
248 std::pair<tree_iterator, tree_iterator> p = tree_.equal_range(key);
249 return std::make_pair(iterator(this, p.first),
250 iterator(this, p.second));
251 }
252 std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
253 std::pair<tree_const_iterator, tree_const_iterator> p = tree_.equal_range(key);
254 return std::make_pair(const_iterator(this, p.first),
255 const_iterator(this, p.second));
256 }
257 iterator find_unique(const key_type &key) {
258 return iterator(this, tree_.find_unique(key));
259 }
260 const_iterator find_unique(const key_type &key) const {
261 return const_iterator(this, tree_.find_unique(key));
262 }
263 iterator find_multi(const key_type &key) {
264 return iterator(this, tree_.find_multi(key));
265 }
266 const_iterator find_multi(const key_type &key) const {
267 return const_iterator(this, tree_.find_multi(key));
268 }
269 size_type count_unique(const key_type &key) const {
270 return tree_.count_unique(key);
271 }
272 size_type count_multi(const key_type &key) const {
273 return tree_.count_multi(key);
274 }
275
276 // Insertion routines.
277 template <typename ValuePointer>
278 std::pair<iterator, bool> insert_unique(const key_type &key, ValuePointer value) {
279 std::pair<tree_iterator, bool> p = tree_.insert_unique(key, value);
280 generation_ += p.second;
281 return std::make_pair(iterator(this, p.first), p.second);
282 }
283 std::pair<iterator, bool> insert_unique(const value_type &v) {
284 std::pair<tree_iterator, bool> p = tree_.insert_unique(v);
285 generation_ += p.second;
286 return std::make_pair(iterator(this, p.first), p.second);
287 }
288 iterator insert_unique(iterator position, const value_type &v) {
289 tree_iterator tree_pos = position.iter();
290 ++generation_;
291 return iterator(this, tree_.insert_unique(tree_pos, v));
292 }
293 template <typename InputIterator>
294 void insert_unique(InputIterator b, InputIterator e) {
295 for (; b != e; ++b) {
296 insert_unique(*b);
297 }
298 }
299 iterator insert_multi(const value_type &v) {
300 ++generation_;
301 return iterator(this, tree_.insert_multi(v));
302 }
303 iterator insert_multi(iterator position, const value_type &v) {
304 tree_iterator tree_pos = position.iter();
305 ++generation_;
306 return iterator(this, tree_.insert_multi(tree_pos, v));
307 }
308 template <typename InputIterator>
309 void insert_multi(InputIterator b, InputIterator e) {
310 for (; b != e; ++b) {
311 insert_multi(*b);
312 }
313 }
314 self_type& operator=(const self_type &x) {
315 if (&x == this) {
316 // Don't copy onto ourselves.
317 return *this;
318 }
319 ++generation_;
320 tree_ = x.tree_;
321 return *this;
322 }
323
324 // Deletion routines.
325 void erase(const iterator &begin, const iterator &end) {
326 tree_.erase(begin.iter(), end.iter());
327 ++generation_;
328 }
329 // Erase the specified iterator from the btree. The iterator must be valid
330 // (i.e. not equal to end()). Return an iterator pointing to the node after
331 // the one that was erased (or end() if none exists).
332 iterator erase(iterator iter) {
333 tree_iterator res = tree_.erase(iter.iter());
334 ++generation_;
335 return iterator(this, res);
336 }
337 int erase_unique(const key_type &key) {
338 int res = tree_.erase_unique(key);
339 generation_ += res;
340 return res;
341 }
342 int erase_multi(const key_type &key) {
343 int res = tree_.erase_multi(key);
344 generation_ += res;
345 return res;
346 }
347
348 // Access to the underlying btree.
349 btree_type* internal_btree() { return &tree_; }
350 const btree_type* internal_btree() const { return &tree_; }
351
352 // Utility routines.
353 void clear() {
354 ++generation_;
355 tree_.clear();
356 }
357 void swap(self_type &x) {
358 ++generation_;
359 ++x.generation_;
360 tree_.swap(x.tree_);
361 }
362 void dump(std::ostream &os) const {
363 tree_.dump(os);
364 }
365 void verify() const {
366 tree_.verify();
367 }
368 int64_t generation() const {
369 return generation_;
370 }
371 key_compare key_comp() const { return tree_.key_comp(); }
372
373 // Size routines.
374 size_type size() const { return tree_.size(); }
375 size_type max_size() const { return tree_.max_size(); }
376 bool empty() const { return tree_.empty(); }
377 size_type height() const { return tree_.height(); }
378 size_type internal_nodes() const { return tree_.internal_nodes(); }
379 size_type leaf_nodes() const { return tree_.leaf_nodes(); }
380 size_type nodes() const { return tree_.nodes(); }
381 size_type bytes_used() const { return tree_.bytes_used(); }
382 static double average_bytes_per_value() {
383 return btree_type::average_bytes_per_value();
384 }
385 double fullness() const { return tree_.fullness(); }
386 double overhead() const { return tree_.overhead(); }
387
388 private:
389 btree_type tree_;
390 int64_t generation_;
391};
392
393} // namespace btree
394
395#endif // UTIL_BTREE_SAFE_BTREE_H__
diff --git a/xdelta3/cpp-btree/safe_btree_map.h b/xdelta3/cpp-btree/safe_btree_map.h
new file mode 100644
index 0000000..a0668f1
--- /dev/null
+++ b/xdelta3/cpp-btree/safe_btree_map.h
@@ -0,0 +1,89 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// The safe_btree_map<> is like btree_map<> except that it removes the caveat
16// about insertion and deletion invalidating existing iterators at a small cost
17// in making iterators larger and slower.
18//
19// Revalidation occurs whenever an iterator is accessed. References
20// and pointers returned by safe_btree_map<> iterators are not stable,
21// they are potentially invalidated by any non-const method on the map.
22//
23// BEGIN INCORRECT EXAMPLE
24// for (auto i = safe_map->begin(); i != safe_map->end(); ++i) {
25// const T *value = &i->second; // DO NOT DO THIS
26// [code that modifies safe_map and uses value];
27// }
28// END INCORRECT EXAMPLE
29#ifndef UTIL_BTREE_SAFE_BTREE_MAP_H__
30#define UTIL_BTREE_SAFE_BTREE_MAP_H__
31
32#include <functional>
33#include <memory>
34#include <utility>
35
36#include "btree_container.h"
37#include "btree_map.h"
38#include "safe_btree.h"
39
40namespace btree {
41
42// The safe_btree_map class is needed mainly for its constructors.
43template <typename Key, typename Value,
44 typename Compare = std::less<Key>,
45 typename Alloc = std::allocator<std::pair<const Key, Value> >,
46 int TargetNodeSize = 256>
47class safe_btree_map : public btree_map_container<
48 safe_btree<btree_map_params<Key, Value, Compare, Alloc, TargetNodeSize> > > {
49
50 typedef safe_btree_map<Key, Value, Compare, Alloc, TargetNodeSize> self_type;
51 typedef btree_map_params<
52 Key, Value, Compare, Alloc, TargetNodeSize> params_type;
53 typedef safe_btree<params_type> btree_type;
54 typedef btree_map_container<btree_type> super_type;
55
56 public:
57 typedef typename btree_type::key_compare key_compare;
58 typedef typename btree_type::allocator_type allocator_type;
59
60 public:
61 // Default constructor.
62 safe_btree_map(const key_compare &comp = key_compare(),
63 const allocator_type &alloc = allocator_type())
64 : super_type(comp, alloc) {
65 }
66
67 // Copy constructor.
68 safe_btree_map(const self_type &x)
69 : super_type(x) {
70 }
71
72 // Range constructor.
73 template <class InputIterator>
74 safe_btree_map(InputIterator b, InputIterator e,
75 const key_compare &comp = key_compare(),
76 const allocator_type &alloc = allocator_type())
77 : super_type(b, e, comp, alloc) {
78 }
79};
80
81template <typename K, typename V, typename C, typename A, int N>
82inline void swap(safe_btree_map<K, V, C, A, N> &x,
83 safe_btree_map<K, V, C, A, N> &y) {
84 x.swap(y);
85}
86
87} // namespace btree
88
89#endif // UTIL_BTREE_SAFE_BTREE_MAP_H__
diff --git a/xdelta3/cpp-btree/safe_btree_set.h b/xdelta3/cpp-btree/safe_btree_set.h
new file mode 100644
index 0000000..a6cd541
--- /dev/null
+++ b/xdelta3/cpp-btree/safe_btree_set.h
@@ -0,0 +1,88 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// The safe_btree_set<> is like btree_set<> except that it removes the caveat
16// about insertion and deletion invalidating existing iterators at a small cost
17// in making iterators larger and slower.
18//
19// Revalidation occurs whenever an iterator is accessed. References
20// and pointers returned by safe_btree_map<> iterators are not stable,
21// they are potentially invalidated by any non-const method on the set.
22//
23// BEGIN INCORRECT EXAMPLE
24// for (auto i = safe_set->begin(); i != safe_set->end(); ++i) {
25// const T &value = *i; // DO NOT DO THIS
26// [code that modifies safe_set and uses value];
27// }
28// END INCORRECT EXAMPLE
29
30#ifndef UTIL_BTREE_SAFE_BTREE_SET_H__
31#define UTIL_BTREE_SAFE_BTREE_SET_H__
32
33#include <functional>
34#include <memory>
35
36#include "btree_container.h"
37#include "btree_set.h"
38#include "safe_btree.h"
39
40namespace btree {
41
42// The safe_btree_set class is needed mainly for its constructors.
43template <typename Key,
44 typename Compare = std::less<Key>,
45 typename Alloc = std::allocator<Key>,
46 int TargetNodeSize = 256>
47class safe_btree_set : public btree_unique_container<
48 safe_btree<btree_set_params<Key, Compare, Alloc, TargetNodeSize> > > {
49
50 typedef safe_btree_set<Key, Compare, Alloc, TargetNodeSize> self_type;
51 typedef btree_set_params<Key, Compare, Alloc, TargetNodeSize> params_type;
52 typedef safe_btree<params_type> btree_type;
53 typedef btree_unique_container<btree_type> super_type;
54
55 public:
56 typedef typename btree_type::key_compare key_compare;
57 typedef typename btree_type::allocator_type allocator_type;
58
59 public:
60 // Default constructor.
61 safe_btree_set(const key_compare &comp = key_compare(),
62 const allocator_type &alloc = allocator_type())
63 : super_type(comp, alloc) {
64 }
65
66 // Copy constructor.
67 safe_btree_set(const self_type &x)
68 : super_type(x) {
69 }
70
71 // Range constructor.
72 template <class InputIterator>
73 safe_btree_set(InputIterator b, InputIterator e,
74 const key_compare &comp = key_compare(),
75 const allocator_type &alloc = allocator_type())
76 : super_type(b, e, comp, alloc) {
77 }
78};
79
80template <typename K, typename C, typename A, int N>
81inline void swap(safe_btree_set<K, C, A, N> &x,
82 safe_btree_set<K, C, A, N> &y) {
83 x.swap(y);
84}
85
86} // namespace btree
87
88#endif // UTIL_BTREE_SAFE_BTREE_SET_H__
diff --git a/xdelta3/cpp-btree/safe_btree_test.cc b/xdelta3/cpp-btree/safe_btree_test.cc
new file mode 100644
index 0000000..0d77ae0
--- /dev/null
+++ b/xdelta3/cpp-btree/safe_btree_test.cc
@@ -0,0 +1,116 @@
1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// TODO(pmattis): Add some tests that iterators are not invalidated by
16// insertion and deletion.
17
18#include <functional>
19#include <map>
20#include <set>
21#include <string>
22#include <utility>
23
24#include "gtest/gtest.h"
25#include "btree_test.h"
26#include "safe_btree_map.h"
27#include "safe_btree_set.h"
28
29class UnsafeArena;
30
31namespace btree {
32namespace {
33
34template <typename K, int N>
35void SetTest() {
36 typedef TestAllocator<K> TestAlloc;
37 BtreeTest<safe_btree_set<K, std::less<K>, std::allocator<K>, N>, std::set<K> >();
38 BtreeAllocatorTest<safe_btree_set<K, std::less<K>, TestAlloc, N> >();
39}
40
41template <typename K, int N>
42void MapTest() {
43 typedef TestAllocator<K> TestAlloc;
44 BtreeTest<safe_btree_map<K, K, std::less<K>, std::allocator<K>, N>, std::map<K, K> >();
45 BtreeAllocatorTest<safe_btree_map<K, K, std::less<K>, TestAlloc, N> >();
46 BtreeMapTest<safe_btree_map<K, K, std::less<K>, std::allocator<K>, N> >();
47}
48
49TEST(SafeBtree, set_int32_32) { SetTest<int32_t, 32>(); }
50TEST(SafeBtree, set_int32_64) { SetTest<int32_t, 64>(); }
51TEST(SafeBtree, set_int32_128) { SetTest<int32_t, 128>(); }
52TEST(SafeBtree, set_int32_256) { SetTest<int32_t, 256>(); }
53TEST(SafeBtree, set_int64_256) { SetTest<int64_t, 256>(); }
54TEST(SafeBtree, set_string_256) { SetTest<std::string, 256>(); }
55TEST(SafeBtree, set_pair_256) { SetTest<std::pair<int, int>, 256>(); }
56TEST(SafeBtree, map_int32_256) { MapTest<int32_t, 256>(); }
57TEST(SafeBtree, map_int64_256) { MapTest<int64_t, 256>(); }
58TEST(SafeBtree, map_string_256) { MapTest<std::string, 256>(); }
59TEST(SafeBtree, map_pair_256) { MapTest<std::pair<int, int>, 256>(); }
60
61TEST(SafeBtree, Comparison) {
62 const int kSetSize = 1201;
63 safe_btree_set<int64_t> my_set;
64 for (int i = 0; i < kSetSize; ++i) {
65 my_set.insert(i);
66 }
67 safe_btree_set<int64_t> my_set_copy(my_set);
68 EXPECT_TRUE(my_set_copy == my_set);
69 EXPECT_TRUE(my_set == my_set_copy);
70 EXPECT_FALSE(my_set_copy != my_set);
71 EXPECT_FALSE(my_set != my_set_copy);
72
73 my_set.insert(kSetSize);
74 EXPECT_FALSE(my_set_copy == my_set);
75 EXPECT_FALSE(my_set == my_set_copy);
76 EXPECT_TRUE(my_set_copy != my_set);
77 EXPECT_TRUE(my_set != my_set_copy);
78
79 my_set.erase(kSetSize - 1);
80 EXPECT_FALSE(my_set_copy == my_set);
81 EXPECT_FALSE(my_set == my_set_copy);
82 EXPECT_TRUE(my_set_copy != my_set);
83 EXPECT_TRUE(my_set != my_set_copy);
84
85 safe_btree_map<std::string, int64_t> my_map;
86 for (int i = 0; i < kSetSize; ++i) {
87 my_map[std::string(i, 'a')] = i;
88 }
89 safe_btree_map<std::string, int64_t> my_map_copy(my_map);
90 EXPECT_TRUE(my_map_copy == my_map);
91 EXPECT_TRUE(my_map == my_map_copy);
92 EXPECT_FALSE(my_map_copy != my_map);
93 EXPECT_FALSE(my_map != my_map_copy);
94
95 ++my_map_copy[std::string(7, 'a')];
96 EXPECT_FALSE(my_map_copy == my_map);
97 EXPECT_FALSE(my_map == my_map_copy);
98 EXPECT_TRUE(my_map_copy != my_map);
99 EXPECT_TRUE(my_map != my_map_copy);
100
101 my_map_copy = my_map;
102 my_map["hello"] = kSetSize;
103 EXPECT_FALSE(my_map_copy == my_map);
104 EXPECT_FALSE(my_map == my_map_copy);
105 EXPECT_TRUE(my_map_copy != my_map);
106 EXPECT_TRUE(my_map != my_map_copy);
107
108 my_map.erase(std::string(kSetSize - 1, 'a'));
109 EXPECT_FALSE(my_map_copy == my_map);
110 EXPECT_FALSE(my_map == my_map_copy);
111 EXPECT_TRUE(my_map_copy != my_map);
112 EXPECT_TRUE(my_map != my_map_copy);
113}
114
115} // namespace
116} // namespace btree
diff --git a/xdelta3/run_release.sh b/xdelta3/run_release.sh
index 8e99c6b..21ae8fb 100755
--- a/xdelta3/run_release.sh
+++ b/xdelta3/run_release.sh
@@ -53,7 +53,6 @@ function buildit {
53 D=build/$MACH/${sizebits}size-${offsetbits}off 53 D=build/$MACH/${sizebits}size-${offsetbits}off
54 mkdir -p $D 54 mkdir -p $D
55 (cd $D && $SRCDIR/configure --prefix=$PWD/bin --enable-debug-symbols) 55 (cd $D && $SRCDIR/configure --prefix=$PWD/bin --enable-debug-symbols)
56 (cd $D && make all)
57} 56}
58 57
59function buildall { 58function buildall {
@@ -63,10 +62,10 @@ function buildall {
63 addflag -DXD3_USE_LARGEWINDOW64=0 62 addflag -DXD3_USE_LARGEWINDOW64=0
64 buildit 32 32 63 buildit 32 32
65 64
66 # resetflag $MACH 65 resetflag $MACH
67 # addflag -DXD3_USE_LARGEFILE64=1 66 addflag -DXD3_USE_LARGEFILE64=1
68 # addflag -DXD3_USE_LARGEWINDOW64=0 67 addflag -DXD3_USE_LARGEWINDOW64=0
69 # buildit 32 64 68 buildit 32 64
70 69
71 resetflag $MACH 70 resetflag $MACH
72 addflag -DXD3_USE_LARGEFILE64=1 71 addflag -DXD3_USE_LARGEFILE64=1
diff --git a/xdelta3/testing/checksum_test.cc b/xdelta3/testing/checksum_test.cc
index 53566b9..1643c9f 100644
--- a/xdelta3/testing/checksum_test.cc
+++ b/xdelta3/testing/checksum_test.cc
@@ -4,9 +4,10 @@
4#include <assert.h> 4#include <assert.h>
5#include <list> 5#include <list>
6#include <vector> 6#include <vector>
7#include <map>
8#include <algorithm> 7#include <algorithm>
9 8
9#include "../cpp-btree/btree_map.h"
10
10extern "C" { 11extern "C" {
11uint32_t xd3_large32_cksum_old (xd3_hash_cfg *cfg, const uint8_t *base, const usize_t look); 12uint32_t xd3_large32_cksum_old (xd3_hash_cfg *cfg, const uint8_t *base, const usize_t look);
12uint32_t xd3_large32_cksum_update_old (xd3_hash_cfg *cfg, uint32_t cksum, 13uint32_t xd3_large32_cksum_update_old (xd3_hash_cfg *cfg, uint32_t cksum,
@@ -17,8 +18,8 @@ uint64_t xd3_large64_cksum_update_old (xd3_hash_cfg *cfg, uint64_t cksum,
17 const uint8_t *base, const usize_t look); 18 const uint8_t *base, const usize_t look);
18} 19}
19 20
21using btree::btree_map;
20using std::list; 22using std::list;
21using std::map;
22using std::vector; 23using std::vector;
23 24
24// MLCG parameters 25// MLCG parameters
@@ -229,7 +230,7 @@ template <typename Word>
229struct file_stats { 230struct file_stats {
230 typedef std::list<const uint8_t*> ptr_list; 231 typedef std::list<const uint8_t*> ptr_list;
231 typedef Word word_type; 232 typedef Word word_type;
232 typedef std::map<word_type, ptr_list> table_type; 233 typedef btree::btree_map<word_type, ptr_list> table_type;
233 typedef typename table_type::iterator table_iterator; 234 typedef typename table_type::iterator table_iterator;
234 typedef typename ptr_list::iterator ptr_iterator; 235 typedef typename ptr_list::iterator ptr_iterator;
235 236
@@ -264,12 +265,13 @@ struct file_stats {
264 table.insert(std::make_pair(word, ptr_list())); 265 table.insert(std::make_pair(word, ptr_list()));
265 } 266 }
266 267
267 ptr_list &pl = table[word]; 268 ptr_list &pl = table[word]; // ???
268 269
269 int collisions = 0; 270 int collisions = 0;
270 for (ptr_iterator p_i = pl.begin(); 271 for (ptr_iterator p_i = pl.begin();
271 p_i != pl.end(); 272 p_i != pl.end();
272 ++p_i) { 273 ++p_i) {
274 // TODO !!! Use btree here too duh
273 if (memcmp(*p_i, ptr, cksum_size) == 0) { 275 if (memcmp(*p_i, ptr, cksum_size) == 0) {
274 return; 276 return;
275 } 277 }
@@ -662,10 +664,9 @@ int main(int argc, char** argv) {
662 return 1; 664 return 1;
663 } 665 }
664 666
667// TODO: The xdelta3-hash.h code is identical now; add sameness test.
668// using rabin_karp<> template.
665#define TEST(T,Z,S,C) \ 669#define TEST(T,Z,S,C) \
666 test_result<rabin_karp<T,Z,S,hhash<T>,C>> \
667 _rka_ ## T ## _ ## Z ## _ ## S ## _ ## C \
668 ("rka_" #T "_" #Z "_" #S "_" #C); \
669 test_result<large_cksum<T,Z,S,hhash<T>,C>> \ 670 test_result<large_cksum<T,Z,S,hhash<T>,C>> \
670 _xck_ ## T ## _ ## Z ## _ ## S ## _ ## C \ 671 _xck_ ## T ## _ ## Z ## _ ## S ## _ ## C \
671 ("xck_" #T "_" #Z "_" #S "_" #C); \ 672 ("xck_" #T "_" #Z "_" #S "_" #C); \
@@ -678,13 +679,13 @@ int main(int argc, char** argv) {
678 TEST(usize_t, SIZE, SKIP, 2) 679 TEST(usize_t, SIZE, SKIP, 2)
679 680
680 TESTS(9, 1); 681 TESTS(9, 1);
681 TESTS(9, 9); 682 // TESTS(9, 9);
682 TESTS(15, 1); 683 // TESTS(15, 1);
683 TESTS(15, 15); 684 // TESTS(15, 15);
684 TESTS(127, 1); 685 // TESTS(127, 1);
685 TESTS(127, 127); 686 // TESTS(127, 127);
686 TESTS(211, 1); 687 // TESTS(211, 1);
687 TESTS(211, 211); 688 // TESTS(211, 211);
688 689
689 for (i = 1; i < argc; i++) { 690 for (i = 1; i < argc; i++) {
690 if ((ret = read_whole_file(argv[i], 691 if ((ret = read_whole_file(argv[i],
@@ -704,7 +705,7 @@ int main(int argc, char** argv) {
704 test_result_base *test = *iter; 705 test_result_base *test = *iter;
705 test->reset(); 706 test->reset();
706 707
707 usize_t iters = 200; 708 usize_t iters = 1; // TODO
708 long start_test = get_millisecs_now(); 709 long start_test = get_millisecs_now();
709 710
710 do { 711 do {