1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/unique_string.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,362 @@ 1.4 +// Copyright (c) 2013 Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +#ifndef COMMON_UNIQUE_STRING_H_ 1.34 +#define COMMON_UNIQUE_STRING_H_ 1.35 + 1.36 +#include <map> 1.37 +#include <string> 1.38 +#include "common/using_std_string.h" 1.39 + 1.40 +namespace google_breakpad { 1.41 + 1.42 +// Abstract type 1.43 +class UniqueString; 1.44 + 1.45 +// Unique-ify a string. |ToUniqueString| can never return NULL. 1.46 +const UniqueString* ToUniqueString(string); 1.47 + 1.48 +// ditto, starting instead from the first n characters of a C string 1.49 +const UniqueString* ToUniqueString_n(const char* str, size_t n); 1.50 + 1.51 +// Pull chars out of the string. No range checking. 1.52 +const char Index(const UniqueString*, int); 1.53 + 1.54 +// Get the contained C string (debugging only) 1.55 +const char* const FromUniqueString(const UniqueString*); 1.56 + 1.57 +// Do a strcmp-style comparison on the contained C string 1.58 +int StrcmpUniqueString(const UniqueString*, const UniqueString*); 1.59 + 1.60 +// Less-than comparison of two UniqueStrings, usable for std::sort. 1.61 +bool LessThan_UniqueString(const UniqueString*, const UniqueString*); 1.62 + 1.63 +// Some handy pre-uniqified strings. Z is an escape character: 1.64 +// ZS '$' 1.65 +// ZD '.' 1.66 +// Zeq '=' 1.67 +// Zplus '+' 1.68 +// Zstar '*' 1.69 +// Zslash '/' 1.70 +// Zpercent '%' 1.71 +// Zat '@' 1.72 +// Zcaret '^' 1.73 + 1.74 +// Note that ustr__empty and (UniqueString*)NULL are considered 1.75 +// to be different. 1.76 +// 1.77 +// Unfortunately these have to be written as functions so as to 1.78 +// make them safe to use in static initialisers. 1.79 + 1.80 +// "" 1.81 +inline static const UniqueString* ustr__empty() { 1.82 + static const UniqueString* us = NULL; 1.83 + if (!us) us = ToUniqueString(""); 1.84 + return us; 1.85 +} 1.86 + 1.87 +// "$eip" 1.88 +inline static const UniqueString* ustr__ZSeip() { 1.89 + static const UniqueString* us = NULL; 1.90 + if (!us) us = ToUniqueString("$eip"); 1.91 + return us; 1.92 +} 1.93 + 1.94 +// "$ebp" 1.95 +inline static const UniqueString* ustr__ZSebp() { 1.96 + static const UniqueString* us = NULL; 1.97 + if (!us) us = ToUniqueString("$ebp"); 1.98 + return us; 1.99 +} 1.100 + 1.101 +// "$esp" 1.102 +inline static const UniqueString* ustr__ZSesp() { 1.103 + static const UniqueString* us = NULL; 1.104 + if (!us) us = ToUniqueString("$esp"); 1.105 + return us; 1.106 +} 1.107 + 1.108 +// "$ebx" 1.109 +inline static const UniqueString* ustr__ZSebx() { 1.110 + static const UniqueString* us = NULL; 1.111 + if (!us) us = ToUniqueString("$ebx"); 1.112 + return us; 1.113 +} 1.114 + 1.115 +// "$esi" 1.116 +inline static const UniqueString* ustr__ZSesi() { 1.117 + static const UniqueString* us = NULL; 1.118 + if (!us) us = ToUniqueString("$esi"); 1.119 + return us; 1.120 +} 1.121 + 1.122 +// "$edi" 1.123 +inline static const UniqueString* ustr__ZSedi() { 1.124 + static const UniqueString* us = NULL; 1.125 + if (!us) us = ToUniqueString("$edi"); 1.126 + return us; 1.127 +} 1.128 + 1.129 +// ".cbCalleeParams" 1.130 +inline static const UniqueString* ustr__ZDcbCalleeParams() { 1.131 + static const UniqueString* us = NULL; 1.132 + if (!us) us = ToUniqueString(".cbCalleeParams"); 1.133 + return us; 1.134 +} 1.135 + 1.136 +// ".cbSavedRegs" 1.137 +inline static const UniqueString* ustr__ZDcbSavedRegs() { 1.138 + static const UniqueString* us = NULL; 1.139 + if (!us) us = ToUniqueString(".cbSavedRegs"); 1.140 + return us; 1.141 +} 1.142 + 1.143 +// ".cbLocals" 1.144 +inline static const UniqueString* ustr__ZDcbLocals() { 1.145 + static const UniqueString* us = NULL; 1.146 + if (!us) us = ToUniqueString(".cbLocals"); 1.147 + return us; 1.148 +} 1.149 + 1.150 +// ".raSearchStart" 1.151 +inline static const UniqueString* ustr__ZDraSearchStart() { 1.152 + static const UniqueString* us = NULL; 1.153 + if (!us) us = ToUniqueString(".raSearchStart"); 1.154 + return us; 1.155 +} 1.156 + 1.157 +// ".raSearch" 1.158 +inline static const UniqueString* ustr__ZDraSearch() { 1.159 + static const UniqueString* us = NULL; 1.160 + if (!us) us = ToUniqueString(".raSearch"); 1.161 + return us; 1.162 +} 1.163 + 1.164 +// ".cbParams" 1.165 +inline static const UniqueString* ustr__ZDcbParams() { 1.166 + static const UniqueString* us = NULL; 1.167 + if (!us) us = ToUniqueString(".cbParams"); 1.168 + return us; 1.169 +} 1.170 + 1.171 +// "+" 1.172 +inline static const UniqueString* ustr__Zplus() { 1.173 + static const UniqueString* us = NULL; 1.174 + if (!us) us = ToUniqueString("+"); 1.175 + return us; 1.176 +} 1.177 + 1.178 +// "-" 1.179 +inline static const UniqueString* ustr__Zminus() { 1.180 + static const UniqueString* us = NULL; 1.181 + if (!us) us = ToUniqueString("-"); 1.182 + return us; 1.183 +} 1.184 + 1.185 +// "*" 1.186 +inline static const UniqueString* ustr__Zstar() { 1.187 + static const UniqueString* us = NULL; 1.188 + if (!us) us = ToUniqueString("*"); 1.189 + return us; 1.190 +} 1.191 + 1.192 +// "/" 1.193 +inline static const UniqueString* ustr__Zslash() { 1.194 + static const UniqueString* us = NULL; 1.195 + if (!us) us = ToUniqueString("/"); 1.196 + return us; 1.197 +} 1.198 + 1.199 +// "%" 1.200 +inline static const UniqueString* ustr__Zpercent() { 1.201 + static const UniqueString* us = NULL; 1.202 + if (!us) us = ToUniqueString("%"); 1.203 + return us; 1.204 +} 1.205 + 1.206 +// "@" 1.207 +inline static const UniqueString* ustr__Zat() { 1.208 + static const UniqueString* us = NULL; 1.209 + if (!us) us = ToUniqueString("@"); 1.210 + return us; 1.211 +} 1.212 + 1.213 +// "^" 1.214 +inline static const UniqueString* ustr__Zcaret() { 1.215 + static const UniqueString* us = NULL; 1.216 + if (!us) us = ToUniqueString("^"); 1.217 + return us; 1.218 +} 1.219 + 1.220 +// "=" 1.221 +inline static const UniqueString* ustr__Zeq() { 1.222 + static const UniqueString* us = NULL; 1.223 + if (!us) us = ToUniqueString("="); 1.224 + return us; 1.225 +} 1.226 + 1.227 +// ".cfa" 1.228 +inline static const UniqueString* ustr__ZDcfa() { 1.229 + static const UniqueString* us = NULL; 1.230 + if (!us) us = ToUniqueString(".cfa"); 1.231 + return us; 1.232 +} 1.233 + 1.234 +// ".ra" 1.235 +inline static const UniqueString* ustr__ZDra() { 1.236 + static const UniqueString* us = NULL; 1.237 + if (!us) us = ToUniqueString(".ra"); 1.238 + return us; 1.239 +} 1.240 + 1.241 +// "pc" 1.242 +inline static const UniqueString* ustr__pc() { 1.243 + static const UniqueString* us = NULL; 1.244 + if (!us) us = ToUniqueString("pc"); 1.245 + return us; 1.246 +} 1.247 + 1.248 +// "lr" 1.249 +inline static const UniqueString* ustr__lr() { 1.250 + static const UniqueString* us = NULL; 1.251 + if (!us) us = ToUniqueString("lr"); 1.252 + return us; 1.253 +} 1.254 + 1.255 +// "sp" 1.256 +inline static const UniqueString* ustr__sp() { 1.257 + static const UniqueString* us = NULL; 1.258 + if (!us) us = ToUniqueString("sp"); 1.259 + return us; 1.260 +} 1.261 + 1.262 +template <typename ValueType> 1.263 +class UniqueStringMap 1.264 +{ 1.265 + private: 1.266 + static const int N_FIXED = 10; 1.267 + 1.268 + public: 1.269 + UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {}; 1.270 + ~UniqueStringMap() {}; 1.271 + 1.272 + // Empty out the map. 1.273 + void clear() { 1.274 + ++n_clears_; 1.275 + map_.clear(); 1.276 + n_fixed_ = 0; 1.277 + } 1.278 + 1.279 + // Do "map[ix] = v". 1.280 + void set(const UniqueString* ix, ValueType v) { 1.281 + ++n_sets_; 1.282 + int i; 1.283 + for (i = 0; i < n_fixed_; ++i) { 1.284 + if (fixed_keys_[i] == ix) { 1.285 + fixed_vals_[i] = v; 1.286 + return; 1.287 + } 1.288 + } 1.289 + if (n_fixed_ < N_FIXED) { 1.290 + i = n_fixed_; 1.291 + fixed_keys_[i] = ix; 1.292 + fixed_vals_[i] = v; 1.293 + ++n_fixed_; 1.294 + } else { 1.295 + map_[ix] = v; 1.296 + } 1.297 + } 1.298 + 1.299 + // Lookup 'ix' in the map, and also return a success/fail boolean. 1.300 + ValueType get(/*OUT*/bool* have, const UniqueString* ix) const { 1.301 + ++n_gets_; 1.302 + int i; 1.303 + for (i = 0; i < n_fixed_; ++i) { 1.304 + if (fixed_keys_[i] == ix) { 1.305 + *have = true; 1.306 + return fixed_vals_[i]; 1.307 + } 1.308 + } 1.309 + typename std::map<const UniqueString*, ValueType>::const_iterator it 1.310 + = map_.find(ix); 1.311 + if (it == map_.end()) { 1.312 + *have = false; 1.313 + return ValueType(); 1.314 + } else { 1.315 + *have = true; 1.316 + return it->second; 1.317 + } 1.318 + }; 1.319 + 1.320 + // Lookup 'ix' in the map, and return zero if it is not present. 1.321 + ValueType get(const UniqueString* ix) const { 1.322 + ++n_gets_; 1.323 + bool found; 1.324 + ValueType v = get(&found, ix); 1.325 + return found ? v : ValueType(); 1.326 + } 1.327 + 1.328 + // Find out whether 'ix' is in the map. 1.329 + bool have(const UniqueString* ix) const { 1.330 + ++n_gets_; 1.331 + bool found; 1.332 + (void)get(&found, ix); 1.333 + return found; 1.334 + } 1.335 + 1.336 + // Copy the contents to a std::map, generally for testing. 1.337 + void copy_to_map(std::map<const UniqueString*, ValueType>* m) const { 1.338 + m->clear(); 1.339 + int i; 1.340 + for (i = 0; i < n_fixed_; ++i) { 1.341 + (*m)[fixed_keys_[i]] = fixed_vals_[i]; 1.342 + } 1.343 + m->insert(map_.begin(), map_.end()); 1.344 + } 1.345 + 1.346 + // Note that users of this class rely on having also a sane 1.347 + // assignment operator. The default one is OK, though. 1.348 + // AFAICT there are no uses of the copy constructor, but if 1.349 + // there were, the default one would also suffice. 1.350 + 1.351 + private: 1.352 + // Quick (hopefully) cache 1.353 + const UniqueString* fixed_keys_[N_FIXED]; 1.354 + ValueType fixed_vals_[N_FIXED]; 1.355 + int n_fixed_; // 0 .. N_FIXED inclusive 1.356 + // Fallback storage when the cache is filled 1.357 + std::map<const UniqueString*, ValueType> map_; 1.358 + 1.359 + // For tracking usage stats. 1.360 + mutable int n_sets_, n_gets_, n_clears_; 1.361 +}; 1.362 + 1.363 +} // namespace google_breakpad 1.364 + 1.365 +#endif // COMMON_UNIQUE_STRING_H_