1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle // static_map-inl.h: StaticMap implementation.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // See static_map.h for documentation.
32*9712c20fSFrederick Mayle //
33*9712c20fSFrederick Mayle // Author: Siyang Xie ([email protected])
34*9712c20fSFrederick Mayle
35*9712c20fSFrederick Mayle
36*9712c20fSFrederick Mayle #ifndef PROCESSOR_STATIC_MAP_INL_H__
37*9712c20fSFrederick Mayle #define PROCESSOR_STATIC_MAP_INL_H__
38*9712c20fSFrederick Mayle
39*9712c20fSFrederick Mayle #include "processor/static_map.h"
40*9712c20fSFrederick Mayle #include "processor/static_map_iterator-inl.h"
41*9712c20fSFrederick Mayle #include "processor/logging.h"
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle namespace google_breakpad {
44*9712c20fSFrederick Mayle
45*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
StaticMap(const char * raw_data)46*9712c20fSFrederick Mayle StaticMap<Key, Value, Compare>::StaticMap(const char* raw_data)
47*9712c20fSFrederick Mayle : raw_data_(raw_data),
48*9712c20fSFrederick Mayle compare_() {
49*9712c20fSFrederick Mayle // First 4 Bytes store the number of nodes.
50*9712c20fSFrederick Mayle num_nodes_ = *(reinterpret_cast<const uint32_t*>(raw_data_));
51*9712c20fSFrederick Mayle
52*9712c20fSFrederick Mayle offsets_ = reinterpret_cast<const uint32_t*>(
53*9712c20fSFrederick Mayle raw_data_ + sizeof(num_nodes_));
54*9712c20fSFrederick Mayle
55*9712c20fSFrederick Mayle keys_ = reinterpret_cast<const Key*>(
56*9712c20fSFrederick Mayle raw_data_ + (1 + num_nodes_) * sizeof(uint32_t));
57*9712c20fSFrederick Mayle }
58*9712c20fSFrederick Mayle
59*9712c20fSFrederick Mayle // find(), lower_bound() and upper_bound() implement binary search algorithm.
60*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
61*9712c20fSFrederick Mayle StaticMapIterator<Key, Value, Compare>
find(const Key & key)62*9712c20fSFrederick Mayle StaticMap<Key, Value, Compare>::find(const Key& key) const {
63*9712c20fSFrederick Mayle int begin = 0;
64*9712c20fSFrederick Mayle int end = num_nodes_;
65*9712c20fSFrederick Mayle int middle;
66*9712c20fSFrederick Mayle int compare_result;
67*9712c20fSFrederick Mayle while (begin < end) {
68*9712c20fSFrederick Mayle middle = begin + (end - begin) / 2;
69*9712c20fSFrederick Mayle compare_result = compare_(key, GetKeyAtIndex(middle));
70*9712c20fSFrederick Mayle if (compare_result == 0)
71*9712c20fSFrederick Mayle return IteratorAtIndex(middle);
72*9712c20fSFrederick Mayle if (compare_result < 0) {
73*9712c20fSFrederick Mayle end = middle;
74*9712c20fSFrederick Mayle } else {
75*9712c20fSFrederick Mayle begin = middle + 1;
76*9712c20fSFrederick Mayle }
77*9712c20fSFrederick Mayle }
78*9712c20fSFrederick Mayle return this->end();
79*9712c20fSFrederick Mayle }
80*9712c20fSFrederick Mayle
81*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
82*9712c20fSFrederick Mayle StaticMapIterator<Key, Value, Compare>
lower_bound(const Key & key)83*9712c20fSFrederick Mayle StaticMap<Key, Value, Compare>::lower_bound(const Key& key) const {
84*9712c20fSFrederick Mayle int begin = 0;
85*9712c20fSFrederick Mayle int end = num_nodes_;
86*9712c20fSFrederick Mayle int middle;
87*9712c20fSFrederick Mayle int comp_result;
88*9712c20fSFrederick Mayle while (begin < end) {
89*9712c20fSFrederick Mayle middle = begin + (end - begin) / 2;
90*9712c20fSFrederick Mayle comp_result = compare_(key, GetKeyAtIndex(middle));
91*9712c20fSFrederick Mayle if (comp_result == 0)
92*9712c20fSFrederick Mayle return IteratorAtIndex(middle);
93*9712c20fSFrederick Mayle if (comp_result < 0) {
94*9712c20fSFrederick Mayle end = middle;
95*9712c20fSFrederick Mayle } else {
96*9712c20fSFrederick Mayle begin = middle + 1;
97*9712c20fSFrederick Mayle }
98*9712c20fSFrederick Mayle }
99*9712c20fSFrederick Mayle return IteratorAtIndex(begin);
100*9712c20fSFrederick Mayle }
101*9712c20fSFrederick Mayle
102*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
103*9712c20fSFrederick Mayle StaticMapIterator<Key, Value, Compare>
upper_bound(const Key & key)104*9712c20fSFrederick Mayle StaticMap<Key, Value, Compare>::upper_bound(const Key& key) const {
105*9712c20fSFrederick Mayle int begin = 0;
106*9712c20fSFrederick Mayle int end = num_nodes_;
107*9712c20fSFrederick Mayle int middle;
108*9712c20fSFrederick Mayle int compare_result;
109*9712c20fSFrederick Mayle while (begin < end) {
110*9712c20fSFrederick Mayle middle = begin + (end - begin) / 2;
111*9712c20fSFrederick Mayle compare_result = compare_(key, GetKeyAtIndex(middle));
112*9712c20fSFrederick Mayle if (compare_result == 0)
113*9712c20fSFrederick Mayle return IteratorAtIndex(middle + 1);
114*9712c20fSFrederick Mayle if (compare_result < 0) {
115*9712c20fSFrederick Mayle end = middle;
116*9712c20fSFrederick Mayle } else {
117*9712c20fSFrederick Mayle begin = middle + 1;
118*9712c20fSFrederick Mayle }
119*9712c20fSFrederick Mayle }
120*9712c20fSFrederick Mayle return IteratorAtIndex(begin);
121*9712c20fSFrederick Mayle }
122*9712c20fSFrederick Mayle
123*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
ValidateInMemoryStructure()124*9712c20fSFrederick Mayle bool StaticMap<Key, Value, Compare>::ValidateInMemoryStructure() const {
125*9712c20fSFrederick Mayle // check the number of nodes is non-negative:
126*9712c20fSFrederick Mayle if (!raw_data_) return false;
127*9712c20fSFrederick Mayle int32_t num_nodes = *(reinterpret_cast<const int32_t*>(raw_data_));
128*9712c20fSFrederick Mayle if (num_nodes < 0) {
129*9712c20fSFrederick Mayle BPLOG(INFO) << "StaticMap check failed: negative number of nodes";
130*9712c20fSFrederick Mayle return false;
131*9712c20fSFrederick Mayle }
132*9712c20fSFrederick Mayle
133*9712c20fSFrederick Mayle int node_index = 0;
134*9712c20fSFrederick Mayle if (num_nodes_) {
135*9712c20fSFrederick Mayle uint64_t first_offset = sizeof(int32_t) * (num_nodes_ + 1)
136*9712c20fSFrederick Mayle + sizeof(Key) * num_nodes_;
137*9712c20fSFrederick Mayle // Num_nodes_ is too large.
138*9712c20fSFrederick Mayle if (first_offset > 0xffffffffUL) {
139*9712c20fSFrederick Mayle BPLOG(INFO) << "StaticMap check failed: size exceeds limit";
140*9712c20fSFrederick Mayle return false;
141*9712c20fSFrederick Mayle }
142*9712c20fSFrederick Mayle if (offsets_[node_index] != static_cast<uint32_t>(first_offset)) {
143*9712c20fSFrederick Mayle BPLOG(INFO) << "StaticMap check failed: first node offset is incorrect";
144*9712c20fSFrederick Mayle return false;
145*9712c20fSFrederick Mayle }
146*9712c20fSFrederick Mayle }
147*9712c20fSFrederick Mayle
148*9712c20fSFrederick Mayle for (node_index = 1; node_index < num_nodes_; ++node_index) {
149*9712c20fSFrederick Mayle // Check offsets[i] is strictly increasing:
150*9712c20fSFrederick Mayle if (offsets_[node_index] <= offsets_[node_index - 1]) {
151*9712c20fSFrederick Mayle BPLOG(INFO) << "StaticMap check failed: node offsets non-increasing";
152*9712c20fSFrederick Mayle return false;
153*9712c20fSFrederick Mayle }
154*9712c20fSFrederick Mayle // Check Key[i] is strictly increasing as no duplicate keys are allowed.
155*9712c20fSFrederick Mayle if (compare_(GetKeyAtIndex(node_index),
156*9712c20fSFrederick Mayle GetKeyAtIndex(node_index - 1)) <= 0) {
157*9712c20fSFrederick Mayle BPLOG(INFO) << "StaticMap check failed: node keys non-increasing";
158*9712c20fSFrederick Mayle return false;
159*9712c20fSFrederick Mayle }
160*9712c20fSFrederick Mayle }
161*9712c20fSFrederick Mayle return true;
162*9712c20fSFrederick Mayle }
163*9712c20fSFrederick Mayle
164*9712c20fSFrederick Mayle template<typename Key, typename Value, typename Compare>
GetKeyAtIndex(int index)165*9712c20fSFrederick Mayle const Key StaticMap<Key, Value, Compare>::GetKeyAtIndex(int index) const {
166*9712c20fSFrederick Mayle if (index < 0 || index >= num_nodes_) {
167*9712c20fSFrederick Mayle BPLOG(ERROR) << "Key index out of range error";
168*9712c20fSFrederick Mayle // Key type is required to be primitive type. Return 0 if index is invalid.
169*9712c20fSFrederick Mayle return 0;
170*9712c20fSFrederick Mayle }
171*9712c20fSFrederick Mayle return keys_[index];
172*9712c20fSFrederick Mayle }
173*9712c20fSFrederick Mayle
174*9712c20fSFrederick Mayle } // namespace google_breakpad
175*9712c20fSFrederick Mayle
176*9712c20fSFrederick Mayle #endif // PROCESSOR_STATIC_MAP_INL_H__
177