toolkit/crashreporter/google-breakpad/src/common/unique_string.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial