|
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. |
|
29 |
|
30 #ifndef COMMON_UNIQUE_STRING_H_ |
|
31 #define COMMON_UNIQUE_STRING_H_ |
|
32 |
|
33 #include <map> |
|
34 #include <string> |
|
35 #include "common/using_std_string.h" |
|
36 |
|
37 namespace google_breakpad { |
|
38 |
|
39 // Abstract type |
|
40 class UniqueString; |
|
41 |
|
42 // Unique-ify a string. |ToUniqueString| can never return NULL. |
|
43 const UniqueString* ToUniqueString(string); |
|
44 |
|
45 // ditto, starting instead from the first n characters of a C string |
|
46 const UniqueString* ToUniqueString_n(const char* str, size_t n); |
|
47 |
|
48 // Pull chars out of the string. No range checking. |
|
49 const char Index(const UniqueString*, int); |
|
50 |
|
51 // Get the contained C string (debugging only) |
|
52 const char* const FromUniqueString(const UniqueString*); |
|
53 |
|
54 // Do a strcmp-style comparison on the contained C string |
|
55 int StrcmpUniqueString(const UniqueString*, const UniqueString*); |
|
56 |
|
57 // Less-than comparison of two UniqueStrings, usable for std::sort. |
|
58 bool LessThan_UniqueString(const UniqueString*, const UniqueString*); |
|
59 |
|
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 '^' |
|
70 |
|
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. |
|
76 |
|
77 // "" |
|
78 inline static const UniqueString* ustr__empty() { |
|
79 static const UniqueString* us = NULL; |
|
80 if (!us) us = ToUniqueString(""); |
|
81 return us; |
|
82 } |
|
83 |
|
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 } |
|
90 |
|
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 } |
|
97 |
|
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 } |
|
104 |
|
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 } |
|
111 |
|
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 } |
|
118 |
|
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 } |
|
125 |
|
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 } |
|
132 |
|
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 } |
|
139 |
|
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 } |
|
146 |
|
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 } |
|
153 |
|
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 } |
|
160 |
|
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 } |
|
167 |
|
168 // "+" |
|
169 inline static const UniqueString* ustr__Zplus() { |
|
170 static const UniqueString* us = NULL; |
|
171 if (!us) us = ToUniqueString("+"); |
|
172 return us; |
|
173 } |
|
174 |
|
175 // "-" |
|
176 inline static const UniqueString* ustr__Zminus() { |
|
177 static const UniqueString* us = NULL; |
|
178 if (!us) us = ToUniqueString("-"); |
|
179 return us; |
|
180 } |
|
181 |
|
182 // "*" |
|
183 inline static const UniqueString* ustr__Zstar() { |
|
184 static const UniqueString* us = NULL; |
|
185 if (!us) us = ToUniqueString("*"); |
|
186 return us; |
|
187 } |
|
188 |
|
189 // "/" |
|
190 inline static const UniqueString* ustr__Zslash() { |
|
191 static const UniqueString* us = NULL; |
|
192 if (!us) us = ToUniqueString("/"); |
|
193 return us; |
|
194 } |
|
195 |
|
196 // "%" |
|
197 inline static const UniqueString* ustr__Zpercent() { |
|
198 static const UniqueString* us = NULL; |
|
199 if (!us) us = ToUniqueString("%"); |
|
200 return us; |
|
201 } |
|
202 |
|
203 // "@" |
|
204 inline static const UniqueString* ustr__Zat() { |
|
205 static const UniqueString* us = NULL; |
|
206 if (!us) us = ToUniqueString("@"); |
|
207 return us; |
|
208 } |
|
209 |
|
210 // "^" |
|
211 inline static const UniqueString* ustr__Zcaret() { |
|
212 static const UniqueString* us = NULL; |
|
213 if (!us) us = ToUniqueString("^"); |
|
214 return us; |
|
215 } |
|
216 |
|
217 // "=" |
|
218 inline static const UniqueString* ustr__Zeq() { |
|
219 static const UniqueString* us = NULL; |
|
220 if (!us) us = ToUniqueString("="); |
|
221 return us; |
|
222 } |
|
223 |
|
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 } |
|
230 |
|
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 } |
|
237 |
|
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 } |
|
244 |
|
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 } |
|
251 |
|
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 } |
|
258 |
|
259 template <typename ValueType> |
|
260 class UniqueStringMap |
|
261 { |
|
262 private: |
|
263 static const int N_FIXED = 10; |
|
264 |
|
265 public: |
|
266 UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {}; |
|
267 ~UniqueStringMap() {}; |
|
268 |
|
269 // Empty out the map. |
|
270 void clear() { |
|
271 ++n_clears_; |
|
272 map_.clear(); |
|
273 n_fixed_ = 0; |
|
274 } |
|
275 |
|
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 } |
|
295 |
|
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 }; |
|
316 |
|
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 } |
|
324 |
|
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 } |
|
332 |
|
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 } |
|
342 |
|
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. |
|
347 |
|
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_; |
|
355 |
|
356 // For tracking usage stats. |
|
357 mutable int n_sets_, n_gets_, n_clears_; |
|
358 }; |
|
359 |
|
360 } // namespace google_breakpad |
|
361 |
|
362 #endif // COMMON_UNIQUE_STRING_H_ |