Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 // Copyright (c) 2013 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef COMMON_UNIQUE_STRING_H_
31 #define COMMON_UNIQUE_STRING_H_
33 #include <map>
34 #include <string>
35 #include "common/using_std_string.h"
37 namespace google_breakpad {
39 // Abstract type
40 class UniqueString;
42 // Unique-ify a string. |ToUniqueString| can never return NULL.
43 const UniqueString* ToUniqueString(string);
45 // ditto, starting instead from the first n characters of a C string
46 const UniqueString* ToUniqueString_n(const char* str, size_t n);
48 // Pull chars out of the string. No range checking.
49 const char Index(const UniqueString*, int);
51 // Get the contained C string (debugging only)
52 const char* const FromUniqueString(const UniqueString*);
54 // Do a strcmp-style comparison on the contained C string
55 int StrcmpUniqueString(const UniqueString*, const UniqueString*);
57 // Less-than comparison of two UniqueStrings, usable for std::sort.
58 bool LessThan_UniqueString(const UniqueString*, const UniqueString*);
60 // Some handy pre-uniqified strings. Z is an escape character:
61 // ZS '$'
62 // ZD '.'
63 // Zeq '='
64 // Zplus '+'
65 // Zstar '*'
66 // Zslash '/'
67 // Zpercent '%'
68 // Zat '@'
69 // Zcaret '^'
71 // Note that ustr__empty and (UniqueString*)NULL are considered
72 // to be different.
73 //
74 // Unfortunately these have to be written as functions so as to
75 // make them safe to use in static initialisers.
77 // ""
78 inline static const UniqueString* ustr__empty() {
79 static const UniqueString* us = NULL;
80 if (!us) us = ToUniqueString("");
81 return us;
82 }
84 // "$eip"
85 inline static const UniqueString* ustr__ZSeip() {
86 static const UniqueString* us = NULL;
87 if (!us) us = ToUniqueString("$eip");
88 return us;
89 }
91 // "$ebp"
92 inline static const UniqueString* ustr__ZSebp() {
93 static const UniqueString* us = NULL;
94 if (!us) us = ToUniqueString("$ebp");
95 return us;
96 }
98 // "$esp"
99 inline static const UniqueString* ustr__ZSesp() {
100 static const UniqueString* us = NULL;
101 if (!us) us = ToUniqueString("$esp");
102 return us;
103 }
105 // "$ebx"
106 inline static const UniqueString* ustr__ZSebx() {
107 static const UniqueString* us = NULL;
108 if (!us) us = ToUniqueString("$ebx");
109 return us;
110 }
112 // "$esi"
113 inline static const UniqueString* ustr__ZSesi() {
114 static const UniqueString* us = NULL;
115 if (!us) us = ToUniqueString("$esi");
116 return us;
117 }
119 // "$edi"
120 inline static const UniqueString* ustr__ZSedi() {
121 static const UniqueString* us = NULL;
122 if (!us) us = ToUniqueString("$edi");
123 return us;
124 }
126 // ".cbCalleeParams"
127 inline static const UniqueString* ustr__ZDcbCalleeParams() {
128 static const UniqueString* us = NULL;
129 if (!us) us = ToUniqueString(".cbCalleeParams");
130 return us;
131 }
133 // ".cbSavedRegs"
134 inline static const UniqueString* ustr__ZDcbSavedRegs() {
135 static const UniqueString* us = NULL;
136 if (!us) us = ToUniqueString(".cbSavedRegs");
137 return us;
138 }
140 // ".cbLocals"
141 inline static const UniqueString* ustr__ZDcbLocals() {
142 static const UniqueString* us = NULL;
143 if (!us) us = ToUniqueString(".cbLocals");
144 return us;
145 }
147 // ".raSearchStart"
148 inline static const UniqueString* ustr__ZDraSearchStart() {
149 static const UniqueString* us = NULL;
150 if (!us) us = ToUniqueString(".raSearchStart");
151 return us;
152 }
154 // ".raSearch"
155 inline static const UniqueString* ustr__ZDraSearch() {
156 static const UniqueString* us = NULL;
157 if (!us) us = ToUniqueString(".raSearch");
158 return us;
159 }
161 // ".cbParams"
162 inline static const UniqueString* ustr__ZDcbParams() {
163 static const UniqueString* us = NULL;
164 if (!us) us = ToUniqueString(".cbParams");
165 return us;
166 }
168 // "+"
169 inline static const UniqueString* ustr__Zplus() {
170 static const UniqueString* us = NULL;
171 if (!us) us = ToUniqueString("+");
172 return us;
173 }
175 // "-"
176 inline static const UniqueString* ustr__Zminus() {
177 static const UniqueString* us = NULL;
178 if (!us) us = ToUniqueString("-");
179 return us;
180 }
182 // "*"
183 inline static const UniqueString* ustr__Zstar() {
184 static const UniqueString* us = NULL;
185 if (!us) us = ToUniqueString("*");
186 return us;
187 }
189 // "/"
190 inline static const UniqueString* ustr__Zslash() {
191 static const UniqueString* us = NULL;
192 if (!us) us = ToUniqueString("/");
193 return us;
194 }
196 // "%"
197 inline static const UniqueString* ustr__Zpercent() {
198 static const UniqueString* us = NULL;
199 if (!us) us = ToUniqueString("%");
200 return us;
201 }
203 // "@"
204 inline static const UniqueString* ustr__Zat() {
205 static const UniqueString* us = NULL;
206 if (!us) us = ToUniqueString("@");
207 return us;
208 }
210 // "^"
211 inline static const UniqueString* ustr__Zcaret() {
212 static const UniqueString* us = NULL;
213 if (!us) us = ToUniqueString("^");
214 return us;
215 }
217 // "="
218 inline static const UniqueString* ustr__Zeq() {
219 static const UniqueString* us = NULL;
220 if (!us) us = ToUniqueString("=");
221 return us;
222 }
224 // ".cfa"
225 inline static const UniqueString* ustr__ZDcfa() {
226 static const UniqueString* us = NULL;
227 if (!us) us = ToUniqueString(".cfa");
228 return us;
229 }
231 // ".ra"
232 inline static const UniqueString* ustr__ZDra() {
233 static const UniqueString* us = NULL;
234 if (!us) us = ToUniqueString(".ra");
235 return us;
236 }
238 // "pc"
239 inline static const UniqueString* ustr__pc() {
240 static const UniqueString* us = NULL;
241 if (!us) us = ToUniqueString("pc");
242 return us;
243 }
245 // "lr"
246 inline static const UniqueString* ustr__lr() {
247 static const UniqueString* us = NULL;
248 if (!us) us = ToUniqueString("lr");
249 return us;
250 }
252 // "sp"
253 inline static const UniqueString* ustr__sp() {
254 static const UniqueString* us = NULL;
255 if (!us) us = ToUniqueString("sp");
256 return us;
257 }
259 template <typename ValueType>
260 class UniqueStringMap
261 {
262 private:
263 static const int N_FIXED = 10;
265 public:
266 UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {};
267 ~UniqueStringMap() {};
269 // Empty out the map.
270 void clear() {
271 ++n_clears_;
272 map_.clear();
273 n_fixed_ = 0;
274 }
276 // Do "map[ix] = v".
277 void set(const UniqueString* ix, ValueType v) {
278 ++n_sets_;
279 int i;
280 for (i = 0; i < n_fixed_; ++i) {
281 if (fixed_keys_[i] == ix) {
282 fixed_vals_[i] = v;
283 return;
284 }
285 }
286 if (n_fixed_ < N_FIXED) {
287 i = n_fixed_;
288 fixed_keys_[i] = ix;
289 fixed_vals_[i] = v;
290 ++n_fixed_;
291 } else {
292 map_[ix] = v;
293 }
294 }
296 // Lookup 'ix' in the map, and also return a success/fail boolean.
297 ValueType get(/*OUT*/bool* have, const UniqueString* ix) const {
298 ++n_gets_;
299 int i;
300 for (i = 0; i < n_fixed_; ++i) {
301 if (fixed_keys_[i] == ix) {
302 *have = true;
303 return fixed_vals_[i];
304 }
305 }
306 typename std::map<const UniqueString*, ValueType>::const_iterator it
307 = map_.find(ix);
308 if (it == map_.end()) {
309 *have = false;
310 return ValueType();
311 } else {
312 *have = true;
313 return it->second;
314 }
315 };
317 // Lookup 'ix' in the map, and return zero if it is not present.
318 ValueType get(const UniqueString* ix) const {
319 ++n_gets_;
320 bool found;
321 ValueType v = get(&found, ix);
322 return found ? v : ValueType();
323 }
325 // Find out whether 'ix' is in the map.
326 bool have(const UniqueString* ix) const {
327 ++n_gets_;
328 bool found;
329 (void)get(&found, ix);
330 return found;
331 }
333 // Copy the contents to a std::map, generally for testing.
334 void copy_to_map(std::map<const UniqueString*, ValueType>* m) const {
335 m->clear();
336 int i;
337 for (i = 0; i < n_fixed_; ++i) {
338 (*m)[fixed_keys_[i]] = fixed_vals_[i];
339 }
340 m->insert(map_.begin(), map_.end());
341 }
343 // Note that users of this class rely on having also a sane
344 // assignment operator. The default one is OK, though.
345 // AFAICT there are no uses of the copy constructor, but if
346 // there were, the default one would also suffice.
348 private:
349 // Quick (hopefully) cache
350 const UniqueString* fixed_keys_[N_FIXED];
351 ValueType fixed_vals_[N_FIXED];
352 int n_fixed_; // 0 .. N_FIXED inclusive
353 // Fallback storage when the cache is filled
354 std::map<const UniqueString*, ValueType> map_;
356 // For tracking usage stats.
357 mutable int n_sets_, n_gets_, n_clears_;
358 };
360 } // namespace google_breakpad
362 #endif // COMMON_UNIQUE_STRING_H_