Breakpad, a crash reporter, from Google.
Original home: https://chromium.googlesource.com/breakpad/breakpad/
修订版 | 5dad29423e62292c6ff468cabfee4422ba55b18b (tree) |
---|---|
时间 | 2017-11-03 02:56:17 |
作者 | Mark Mentovai <mark@chro...> |
Commiter | Mark Mentovai |
Revert "Create LongStringDictionary and replace SimpleStringDictionary usages in client/ios/Breakpad.mm."
This reverts commit fd0a0d2b7ae9dd3d8a02b6a12e7941f7189fbb6c.
Reason for revert: Build failures reported at https://chromium-review.googlesource.com/c/chromium/src/+/750591#message-cc4f7dd486fa1da7373ad5d83d56f550d607d429
Failed build on chromium.mac/ios-device: https://build.chromium.org/p/chromium.mac/builders/ios-device/builds/73163, https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.mac%2Fios-device%2F73163%2F%2B%2Frecipes%2Fsteps%2Fcompile%2F0%2Fstdout
[637/3593] CXX obj/third_party/breakpad/client/long_string_dictionary.o
FAILED: obj/third_party/breakpad/client/long_string_dictionary.o
[…]
../../third_party/breakpad/breakpad/src/common/long_string_dictionary.cc:46:16: error: unused variable 'kMaxSuffixLength' [-Werror,-Wunused-const-variable]
1 error generated.
[…]
[641/3593] CXX ios_clang_arm64/obj/third_party/breakpad/client/long_string_dictionary.o
FAILED: ios_clang_arm64/obj/third_party/breakpad/client/long_string_dictionary.o
../../third_party/breakpad/breakpad/src/common/long_string_dictionary.cc:46:16: error: unused variable 'kMaxSuffixLength' [-Werror,-Wunused-const-variable]
1 error generated.
Change-Id: I285eaac6abfcb7d173a0d1e4998b92d5c8dd6ecb
Reviewed-on: https://chromium-review.googlesource.com/751723
Reviewed-by: Mark Mentovai <mark@chromium.org>
@@ -38,15 +38,13 @@ | ||
38 | 38 | #include <sys/sysctl.h> |
39 | 39 | #include <TargetConditionals.h> |
40 | 40 | |
41 | -#include <string> | |
42 | - | |
43 | 41 | #import "client/ios/handler/ios_exception_minidump_generator.h" |
44 | 42 | #import "client/mac/crash_generation/ConfigFile.h" |
45 | 43 | #import "client/mac/handler/exception_handler.h" |
46 | 44 | #import "client/mac/handler/minidump_generator.h" |
47 | -#import "client/mac/handler/protected_memory_allocator.h" | |
48 | 45 | #import "client/mac/sender/uploader.h" |
49 | -#import "common/long_string_dictionary.h" | |
46 | +#import "client/mac/handler/protected_memory_allocator.h" | |
47 | +#import "common/simple_string_dictionary.h" | |
50 | 48 | |
51 | 49 | #if !TARGET_OS_TV && !TARGET_OS_WATCH |
52 | 50 | #import "client/mac/handler/exception_handler.h" |
@@ -68,7 +66,7 @@ | ||
68 | 66 | |
69 | 67 | using google_breakpad::ConfigFile; |
70 | 68 | using google_breakpad::EnsureDirectoryPathExists; |
71 | -using google_breakpad::LongStringDictionary; | |
69 | +using google_breakpad::SimpleStringDictionary; | |
72 | 70 | |
73 | 71 | //============================================================================= |
74 | 72 | // We want any memory allocations which are used by breakpad during the |
@@ -199,7 +197,7 @@ class Breakpad { | ||
199 | 197 | // MachineExceptions.h, we have to explicitly name the handler. |
200 | 198 | google_breakpad::ExceptionHandler *handler_; // The actual handler (STRONG) |
201 | 199 | |
202 | - LongStringDictionary *config_params_; // Create parameters (STRONG) | |
200 | + SimpleStringDictionary *config_params_; // Create parameters (STRONG) | |
203 | 201 | |
204 | 202 | ConfigFile config_file_; |
205 | 203 |
@@ -315,7 +313,7 @@ Breakpad::~Breakpad() { | ||
315 | 313 | // since they were allocated by ProtectedMemoryAllocator objects. |
316 | 314 | // |
317 | 315 | if (config_params_) { |
318 | - config_params_->~LongStringDictionary(); | |
316 | + config_params_->~SimpleStringDictionary(); | |
319 | 317 | } |
320 | 318 | |
321 | 319 | if (handler_) |
@@ -383,10 +381,10 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) { | ||
383 | 381 | } |
384 | 382 | |
385 | 383 | config_params_ = |
386 | - new (gKeyValueAllocator->Allocate(sizeof(LongStringDictionary))) | |
387 | - LongStringDictionary(); | |
384 | + new (gKeyValueAllocator->Allocate(sizeof(SimpleStringDictionary)) ) | |
385 | + SimpleStringDictionary(); | |
388 | 386 | |
389 | - LongStringDictionary &dictionary = *config_params_; | |
387 | + SimpleStringDictionary &dictionary = *config_params_; | |
390 | 388 | |
391 | 389 | dictionary.SetKeyValue(BREAKPAD_SERVER_TYPE, [serverType UTF8String]); |
392 | 390 | dictionary.SetKeyValue(BREAKPAD_PRODUCT_DISPLAY, [display UTF8String]); |
@@ -429,8 +427,8 @@ NSString *Breakpad::KeyValue(NSString *key) { | ||
429 | 427 | if (!config_params_ || !key) |
430 | 428 | return nil; |
431 | 429 | |
432 | - const std::string value = config_params_->GetValueForKey([key UTF8String]); | |
433 | - return value.empty() ? nil : [NSString stringWithUTF8String:value.c_str()]; | |
430 | + const char *value = config_params_->GetValueForKey([key UTF8String]); | |
431 | + return value ? [NSString stringWithUTF8String:value] : nil; | |
434 | 432 | } |
435 | 433 | |
436 | 434 | //============================================================================= |
@@ -504,8 +502,8 @@ void Breakpad::UploadData(NSData *data, NSString *name, | ||
504 | 502 | NSDictionary *server_parameters) { |
505 | 503 | NSMutableDictionary *config = [NSMutableDictionary dictionary]; |
506 | 504 | |
507 | - LongStringDictionary::Iterator it(*config_params_); | |
508 | - while (const LongStringDictionary::Entry *next = it.Next()) { | |
505 | + SimpleStringDictionary::Iterator it(*config_params_); | |
506 | + while (const SimpleStringDictionary::Entry *next = it.Next()) { | |
509 | 507 | [config setValue:[NSString stringWithUTF8String:next->value] |
510 | 508 | forKey:[NSString stringWithUTF8String:next->key]]; |
511 | 509 | } |
@@ -534,7 +532,7 @@ NSDictionary *Breakpad::GenerateReport(NSDictionary *server_parameters) { | ||
534 | 532 | if (!success) |
535 | 533 | return nil; |
536 | 534 | |
537 | - LongStringDictionary params = *config_params_; | |
535 | + SimpleStringDictionary params = *config_params_; | |
538 | 536 | for (NSString *key in server_parameters) { |
539 | 537 | params.SetKeyValue([key UTF8String], |
540 | 538 | [[server_parameters objectForKey:key] UTF8String]); |
@@ -569,7 +567,7 @@ bool Breakpad::HandleMinidump(const char *dump_dir, | ||
569 | 567 | void Breakpad::HandleUncaughtException(NSException *exception) { |
570 | 568 | // Generate the minidump. |
571 | 569 | google_breakpad::IosExceptionMinidumpGenerator generator(exception); |
572 | - const std::string minidump_path = | |
570 | + const char *minidump_path = | |
573 | 571 | config_params_->GetValueForKey(BREAKPAD_DUMP_DIRECTORY); |
574 | 572 | std::string minidump_id; |
575 | 573 | std::string minidump_filename = generator.UniqueNameInDirectory(minidump_path, |
@@ -582,7 +580,7 @@ void Breakpad::HandleUncaughtException(NSException *exception) { | ||
582 | 580 | // 2- If the application crash while trying to handle this exception, a usual |
583 | 581 | // report will be generated. This report must not contain these special |
584 | 582 | // keys. |
585 | - LongStringDictionary params = *config_params_; | |
583 | + SimpleStringDictionary params = *config_params_; | |
586 | 584 | params.SetKeyValue(BREAKPAD_SERVER_PARAMETER_PREFIX "type", "exception"); |
587 | 585 | params.SetKeyValue(BREAKPAD_SERVER_PARAMETER_PREFIX "exceptionName", |
588 | 586 | [[exception name] UTF8String]); |
@@ -591,9 +589,9 @@ void Breakpad::HandleUncaughtException(NSException *exception) { | ||
591 | 589 | |
592 | 590 | // And finally write the config file. |
593 | 591 | ConfigFile config_file; |
594 | - config_file.WriteFile(minidump_path.c_str(), | |
592 | + config_file.WriteFile(minidump_path, | |
595 | 593 | ¶ms, |
596 | - minidump_path.c_str(), | |
594 | + minidump_path, | |
597 | 595 | minidump_id.c_str()); |
598 | 596 | } |
599 | 597 |
@@ -621,9 +619,9 @@ BreakpadRef BreakpadCreate(NSDictionary *parameters) { | ||
621 | 619 | |
622 | 620 | gKeyValueAllocator = |
623 | 621 | new (gMasterAllocator->Allocate(sizeof(ProtectedMemoryAllocator))) |
624 | - ProtectedMemoryAllocator(sizeof(LongStringDictionary)); | |
622 | + ProtectedMemoryAllocator(sizeof(SimpleStringDictionary)); | |
625 | 623 | |
626 | - // Create a mutex for use in accessing the LongStringDictionary | |
624 | + // Create a mutex for use in accessing the SimpleStringDictionary | |
627 | 625 | int mutexResult = pthread_mutex_init(&gDictionaryMutex, NULL); |
628 | 626 | if (mutexResult == 0) { |
629 | 627 |
@@ -57,8 +57,6 @@ | ||
57 | 57 | 1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */; }; |
58 | 58 | AA747D9F0F9514B9006C5449 /* Breakpad_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* Breakpad_Prefix.pch */; }; |
59 | 59 | AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; }; |
60 | - CF6D547D1F9E6FFE00E95174 /* long_string_dictionary.cc in Sources */ = {isa = PBXBuildFile; fileRef = CF6D547C1F9E6FFE00E95174 /* long_string_dictionary.cc */; }; | |
61 | - CF706DC11F7C6EFB002C54C7 /* long_string_dictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = CF706DC01F7C6EFB002C54C7 /* long_string_dictionary.h */; }; | |
62 | 60 | /* End PBXBuildFile section */ |
63 | 61 | |
64 | 62 | /* Begin PBXFileReference section */ |
@@ -113,8 +111,6 @@ | ||
113 | 111 | 1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simple_string_dictionary.h; sourceTree = "<group>"; }; |
114 | 112 | AA747D9E0F9514B9006C5449 /* Breakpad_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpad_Prefix.pch; sourceTree = SOURCE_ROOT; }; |
115 | 113 | AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; |
116 | - CF6D547C1F9E6FFE00E95174 /* long_string_dictionary.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = long_string_dictionary.cc; sourceTree = "<group>"; }; | |
117 | - CF706DC01F7C6EFB002C54C7 /* long_string_dictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = long_string_dictionary.h; sourceTree = "<group>"; }; | |
118 | 114 | D2AAC07E0554694100DB518D /* libBreakpad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBreakpad.a; sourceTree = BUILT_PRODUCTS_DIR; }; |
119 | 115 | /* End PBXFileReference section */ |
120 | 116 |
@@ -268,8 +264,6 @@ | ||
268 | 264 | 16C7CC47147D4A4300776EAD /* common */ = { |
269 | 265 | isa = PBXGroup; |
270 | 266 | children = ( |
271 | - CF706DC01F7C6EFB002C54C7 /* long_string_dictionary.h */, | |
272 | - CF6D547C1F9E6FFE00E95174 /* long_string_dictionary.cc */, | |
273 | 267 | 1EEEB60C1720821900F7E689 /* simple_string_dictionary.cc */, |
274 | 268 | 1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */, |
275 | 269 | 16C7CC4A147D4A4300776EAD /* convert_UTF.c */, |
@@ -345,7 +339,6 @@ | ||
345 | 339 | 16C7CEA8147D4A4300776EAD /* string_conversion.h in Headers */, |
346 | 340 | 16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */, |
347 | 341 | 16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */, |
348 | - CF706DC11F7C6EFB002C54C7 /* long_string_dictionary.h in Headers */, | |
349 | 342 | 1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */, |
350 | 343 | 14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */, |
351 | 344 | ); |
@@ -423,7 +416,6 @@ | ||
423 | 416 | 16C7CDFC147D4A4300776EAD /* minidump_generator.cc in Sources */, |
424 | 417 | 16C7CDFE147D4A4300776EAD /* protected_memory_allocator.cc in Sources */, |
425 | 418 | 16C7CE09147D4A4300776EAD /* uploader.mm in Sources */, |
426 | - CF6D547D1F9E6FFE00E95174 /* long_string_dictionary.cc in Sources */, | |
427 | 419 | 16C7CE19147D4A4300776EAD /* minidump_file_writer.cc in Sources */, |
428 | 420 | 16C7CE40147D4A4300776EAD /* convert_UTF.c in Sources */, |
429 | 421 | 16C7CE79147D4A4300776EAD /* GTMLogger.m in Sources */, |
@@ -121,8 +121,6 @@ | ||
121 | 121 | 'linux/safe_readlink.h', |
122 | 122 | 'linux/synth_elf.cc', |
123 | 123 | 'linux/synth_elf.h', |
124 | - 'long_string_dictionary.cc', | |
125 | - 'long_string_dictionary.h', | |
126 | 124 | 'mac/arch_utilities.cc', |
127 | 125 | 'mac/arch_utilities.h', |
128 | 126 | 'mac/bootstrap_compat.cc', |
@@ -222,7 +220,6 @@ | ||
222 | 220 | 'linux/tests/auto_testfile.h', |
223 | 221 | 'linux/tests/crash_generator.cc', |
224 | 222 | 'linux/tests/crash_generator.h', |
225 | - 'long_string_dictionary_unittest.cc', | |
226 | 223 | 'mac/macho_reader_unittest.cc', |
227 | 224 | 'memory_allocator_unittest.cc', |
228 | 225 | 'memory_range_unittest.cc', |
@@ -1,175 +0,0 @@ | ||
1 | -// Copyright (c) 2017, 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 | -#include "common/long_string_dictionary.h" | |
31 | - | |
32 | -#include <string.h> | |
33 | - | |
34 | -#include <algorithm> | |
35 | -#include <string> | |
36 | - | |
37 | -#include "common/simple_string_dictionary.h" | |
38 | - | |
39 | -#define arraysize(f) (sizeof(f) / sizeof(*f)) | |
40 | - | |
41 | -namespace { | |
42 | - // Suffixes for segment keys. | |
43 | - const char* const kSuffixes[] = {"__1", "__2", "__3", "__4", "__5", "__6", | |
44 | - "__7", "__8", "__9", "__10"}; | |
45 | - // The maximum suffix string length. | |
46 | - const size_t kMaxSuffixLength = 4; | |
47 | -} // namespace | |
48 | - | |
49 | -namespace google_breakpad { | |
50 | - | |
51 | -using std::string; | |
52 | - | |
53 | -void LongStringDictionary::SetKeyValue(const char* key, const char* value) { | |
54 | - assert(key); | |
55 | - if (!key) | |
56 | - return; | |
57 | - | |
58 | - RemoveKey(key); | |
59 | - | |
60 | - if (!value) { | |
61 | - return; | |
62 | - } | |
63 | - | |
64 | - // Key must not be an empty string. | |
65 | - assert(key[0] != '\0'); | |
66 | - if (key[0] == '\0') | |
67 | - return; | |
68 | - | |
69 | - // If the value is not valid for segmentation, forwards the key and the value | |
70 | - // to SetKeyValue of SimpleStringDictionary and returns. | |
71 | - size_t value_length = strlen(value); | |
72 | - if (value_length <= (value_size - 1)) { | |
73 | - SimpleStringDictionary::SetKeyValue(key, value); | |
74 | - return; | |
75 | - } | |
76 | - | |
77 | - size_t key_length = strlen(key); | |
78 | - assert(key_length + kMaxSuffixLength <= (key_size - 1)); | |
79 | - | |
80 | - char segment_key[key_size]; | |
81 | - char segment_value[value_size]; | |
82 | - | |
83 | - strcpy(segment_key, key); | |
84 | - | |
85 | - const char* remain_value = value; | |
86 | - size_t remain_value_length = strlen(value); | |
87 | - | |
88 | - for (unsigned long i = 0; i < arraysize(kSuffixes); i++) { | |
89 | - if (remain_value_length == 0) { | |
90 | - return; | |
91 | - } | |
92 | - | |
93 | - strcpy(segment_key + key_length, kSuffixes[i]); | |
94 | - | |
95 | - size_t segment_value_length = | |
96 | - std::min(remain_value_length, value_size - 1); | |
97 | - | |
98 | - strncpy(segment_value, remain_value, segment_value_length); | |
99 | - segment_value[segment_value_length] = '\0'; | |
100 | - | |
101 | - remain_value += segment_value_length; | |
102 | - remain_value_length -= segment_value_length; | |
103 | - | |
104 | - SimpleStringDictionary::SetKeyValue(segment_key, segment_value); | |
105 | - } | |
106 | -} | |
107 | - | |
108 | -bool LongStringDictionary::RemoveKey(const char* key) { | |
109 | - assert(key); | |
110 | - if (!key) | |
111 | - return false; | |
112 | - | |
113 | - if (SimpleStringDictionary::RemoveKey(key)) { | |
114 | - return true; | |
115 | - } | |
116 | - | |
117 | - size_t key_length = strlen(key); | |
118 | - assert(key_length + kMaxSuffixLength <= (key_size - 1)); | |
119 | - | |
120 | - char segment_key[key_size]; | |
121 | - strcpy(segment_key, key); | |
122 | - | |
123 | - unsigned long i = 0; | |
124 | - for (; i < arraysize(kSuffixes); i++) { | |
125 | - strcpy(segment_key + key_length, kSuffixes[i]); | |
126 | - if (!SimpleStringDictionary::RemoveKey(segment_key)) { | |
127 | - break; | |
128 | - } | |
129 | - } | |
130 | - return i != 0; | |
131 | -} | |
132 | - | |
133 | -const string LongStringDictionary::GetValueForKey(const char* key) const { | |
134 | - assert(key); | |
135 | - if (!key) | |
136 | - return ""; | |
137 | - | |
138 | - // Key must not be an empty string. | |
139 | - assert(key[0] != '\0'); | |
140 | - if (key[0] == '\0') | |
141 | - return ""; | |
142 | - | |
143 | - const char* value = SimpleStringDictionary::GetValueForKey(key); | |
144 | - if (value) | |
145 | - return string(value); | |
146 | - | |
147 | - size_t key_length = strlen(key); | |
148 | - assert(key_length + kMaxSuffixLength <= (key_size - 1)); | |
149 | - | |
150 | - bool found_segment = false; | |
151 | - char segment_key[key_size]; | |
152 | - string return_value; | |
153 | - | |
154 | - strcpy(segment_key, key); | |
155 | - for (unsigned long i = 0; i < arraysize(kSuffixes); i++) { | |
156 | - strcpy(segment_key + key_length, kSuffixes[i]); | |
157 | - | |
158 | - const char* segment_value = | |
159 | - SimpleStringDictionary::GetValueForKey(segment_key); | |
160 | - | |
161 | - if (segment_value != NULL) { | |
162 | - found_segment = true; | |
163 | - return_value.append(segment_value); | |
164 | - } else { | |
165 | - break; | |
166 | - } | |
167 | - } | |
168 | - | |
169 | - if (found_segment) { | |
170 | - return return_value; | |
171 | - } | |
172 | - return ""; | |
173 | -} | |
174 | - | |
175 | -} // namespace google_breakpad |
@@ -1,87 +0,0 @@ | ||
1 | -// Copyright (c) 2017, 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_LONG_STRING_DICTIONARY_H_ | |
31 | -#define COMMON_LONG_STRING_DICTIONARY_H_ | |
32 | - | |
33 | -#include <string> | |
34 | - | |
35 | -#include "common/simple_string_dictionary.h" | |
36 | - | |
37 | -namespace google_breakpad { | |
38 | -// key_size is the maxium size that |key| can take in | |
39 | -// SimpleStringDictionary which is defined in simple_string_dictionary.h. | |
40 | -// | |
41 | -// value_size is the maxium size that |value| can take in | |
42 | -// SimpleStringDictionary which is defined in simple_string_dictionary.h. | |
43 | -// | |
44 | -// LongStringDictionary is a subclass of SimpleStringDictionary which supports | |
45 | -// longer values to be stored in the dictionary. The maximum length supported is | |
46 | -// (value_size - 1) * 10. | |
47 | -// | |
48 | -// For example, LongStringDictionary will store long value with key 'abc' into | |
49 | -// segment values with segment keys 'abc__1', 'abc__2', 'abc__3', ... | |
50 | -// | |
51 | -// Clients must avoid using the same suffixes as their key's suffix when | |
52 | -// LongStringDictionary is used. | |
53 | -class LongStringDictionary : public SimpleStringDictionary { | |
54 | - public: | |
55 | - // Stores |value| into |key|, or segment values into segment keys. The maxium | |
56 | - // number of segments is 10. If |value| can not be stored in 10 segments, it | |
57 | - // will be truncated. Replacing the existing value if |key| is already present | |
58 | - // and replacing the existing segment values if segment keys are already | |
59 | - // present. | |
60 | - // | |
61 | - // |key| must not be NULL. If the |value| need to be divided into segments, | |
62 | - // the lengh of |key| must be smaller enough so that lengths of segment keys | |
63 | - // which are key with suffixes are all samller than (key_size - 1). Currently, | |
64 | - // the max length of suffixes are 4. | |
65 | - // | |
66 | - // If |value| is NULL, the key and its corresponding segment keys are removed | |
67 | - // from the map. If there is no more space in the map, then the operation | |
68 | - // silently fails. | |
69 | - void SetKeyValue(const char* key, const char* value); | |
70 | - | |
71 | - // Given |key|, removes any associated value or associated segment values. | |
72 | - // |key| must not be NULL. If the key is not found, searchs its segment keys | |
73 | - // and removes corresponding segment values if found. | |
74 | - bool RemoveKey(const char* key); | |
75 | - | |
76 | - // Given |key|, returns its corresponding |value|. |key| must not be NULL. If | |
77 | - // the key is found, its corresponding |value| is returned. | |
78 | - // | |
79 | - // If no corresponding |value| is found, segment keys of the given |key| will | |
80 | - // be used to search for corresponding segment values. If segment values | |
81 | - // exist, assembled value from them is returned. If no segment value exists, | |
82 | - // NULL is returned. | |
83 | - const std::string GetValueForKey(const char* key) const; | |
84 | -}; | |
85 | -} // namespace google_breakpad | |
86 | - | |
87 | -#endif // COMMON_LONG_STRING_DICTIONARY_H_ |
@@ -1,301 +0,0 @@ | ||
1 | -// Copyright (c) 2017, 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 | -#include <algorithm> | |
31 | -#include <string> | |
32 | - | |
33 | -#include "breakpad_googletest_includes.h" | |
34 | -#include "common/long_string_dictionary.h" | |
35 | - | |
36 | -namespace google_breakpad { | |
37 | - | |
38 | -using std::string; | |
39 | - | |
40 | -TEST(LongStringDictionary, LongStringDictionary) { | |
41 | - // Make a new dictionary | |
42 | - LongStringDictionary dict; | |
43 | - | |
44 | - // Set three distinct values on three keys | |
45 | - dict.SetKeyValue("key1", "value1"); | |
46 | - dict.SetKeyValue("key2", "value2"); | |
47 | - dict.SetKeyValue("key3", "value3"); | |
48 | - | |
49 | - EXPECT_EQ("value1", dict.GetValueForKey("key1")); | |
50 | - EXPECT_EQ("value2", dict.GetValueForKey("key2")); | |
51 | - EXPECT_EQ("value3", dict.GetValueForKey("key3")); | |
52 | - EXPECT_EQ(3u, dict.GetCount()); | |
53 | - // try an unknown key | |
54 | - EXPECT_EQ("", dict.GetValueForKey("key4")); | |
55 | - | |
56 | - // Remove a key | |
57 | - dict.RemoveKey("key3"); | |
58 | - | |
59 | - // Now make sure it's not there anymore | |
60 | - EXPECT_EQ("", dict.GetValueForKey("key3")); | |
61 | - | |
62 | - // Remove by setting value to NULL | |
63 | - dict.SetKeyValue("key2", NULL); | |
64 | - | |
65 | - // Now make sure it's not there anymore | |
66 | - EXPECT_EQ("", dict.GetValueForKey("key2")); | |
67 | -} | |
68 | - | |
69 | -// Add a bunch of values to the dictionary, remove some entries in the middle, | |
70 | -// and then add more. | |
71 | -TEST(LongStringDictionary, Iterator) { | |
72 | - LongStringDictionary* dict = new LongStringDictionary(); | |
73 | - ASSERT_TRUE(dict); | |
74 | - | |
75 | - char key[LongStringDictionary::key_size]; | |
76 | - char value[LongStringDictionary::value_size]; | |
77 | - | |
78 | - const int kDictionaryCapacity = LongStringDictionary::num_entries; | |
79 | - const int kPartitionIndex = kDictionaryCapacity - 5; | |
80 | - | |
81 | - // We assume at least this size in the tests below | |
82 | - ASSERT_GE(kDictionaryCapacity, 64); | |
83 | - | |
84 | - // We'll keep track of the number of key/value pairs we think should | |
85 | - // be in the dictionary | |
86 | - int expectedDictionarySize = 0; | |
87 | - | |
88 | - // Set a bunch of key/value pairs like key0/value0, key1/value1, ... | |
89 | - for (int i = 0; i < kPartitionIndex; ++i) { | |
90 | - sprintf(key, "key%d", i); | |
91 | - sprintf(value, "value%d", i); | |
92 | - dict->SetKeyValue(key, value); | |
93 | - } | |
94 | - expectedDictionarySize = kPartitionIndex; | |
95 | - | |
96 | - // set a couple of the keys twice (with the same value) - should be nop | |
97 | - dict->SetKeyValue("key2", "value2"); | |
98 | - dict->SetKeyValue("key4", "value4"); | |
99 | - dict->SetKeyValue("key15", "value15"); | |
100 | - | |
101 | - // Remove some random elements in the middle | |
102 | - dict->RemoveKey("key7"); | |
103 | - dict->RemoveKey("key18"); | |
104 | - dict->RemoveKey("key23"); | |
105 | - dict->RemoveKey("key31"); | |
106 | - expectedDictionarySize -= 4; // we just removed four key/value pairs | |
107 | - | |
108 | - // Set some more key/value pairs like key59/value59, key60/value60, ... | |
109 | - for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) { | |
110 | - sprintf(key, "key%d", i); | |
111 | - sprintf(value, "value%d", i); | |
112 | - dict->SetKeyValue(key, value); | |
113 | - } | |
114 | - expectedDictionarySize += kDictionaryCapacity - kPartitionIndex; | |
115 | - | |
116 | - // Now create an iterator on the dictionary | |
117 | - SimpleStringDictionary::Iterator iter(*dict); | |
118 | - | |
119 | - // We then verify that it iterates through exactly the number of | |
120 | - // key/value pairs we expect, and that they match one-for-one with what we | |
121 | - // would expect. The ordering of the iteration does not matter... | |
122 | - | |
123 | - // used to keep track of number of occurrences found for key/value pairs | |
124 | - int count[kDictionaryCapacity]; | |
125 | - memset(count, 0, sizeof(count)); | |
126 | - | |
127 | - int totalCount = 0; | |
128 | - | |
129 | - const SimpleStringDictionary::Entry* entry; | |
130 | - while ((entry = iter.Next())) { | |
131 | - totalCount++; | |
132 | - | |
133 | - // Extract keyNumber from a string of the form key<keyNumber> | |
134 | - int keyNumber; | |
135 | - sscanf(entry->key, "key%d", &keyNumber); | |
136 | - | |
137 | - // Extract valueNumber from a string of the form value<valueNumber> | |
138 | - int valueNumber; | |
139 | - sscanf(entry->value, "value%d", &valueNumber); | |
140 | - | |
141 | - // The value number should equal the key number since that's how we set them | |
142 | - EXPECT_EQ(keyNumber, valueNumber); | |
143 | - | |
144 | - // Key and value numbers should be in proper range: | |
145 | - // 0 <= keyNumber < kDictionaryCapacity | |
146 | - bool isKeyInGoodRange = (keyNumber >= 0 && keyNumber < kDictionaryCapacity); | |
147 | - bool isValueInGoodRange = | |
148 | - (valueNumber >= 0 && valueNumber < kDictionaryCapacity); | |
149 | - EXPECT_TRUE(isKeyInGoodRange); | |
150 | - EXPECT_TRUE(isValueInGoodRange); | |
151 | - | |
152 | - if (isKeyInGoodRange && isValueInGoodRange) { | |
153 | - ++count[keyNumber]; | |
154 | - } | |
155 | - } | |
156 | - | |
157 | - // Make sure each of the key/value pairs showed up exactly one time, except | |
158 | - // for the ones which we removed. | |
159 | - for (size_t i = 0; i < kDictionaryCapacity; ++i) { | |
160 | - // Skip over key7, key18, key23, and key31, since we removed them | |
161 | - if (!(i == 7 || i == 18 || i == 23 || i == 31)) { | |
162 | - EXPECT_EQ(count[i], 1); | |
163 | - } | |
164 | - } | |
165 | - | |
166 | - // Make sure the number of iterations matches the expected dictionary size. | |
167 | - EXPECT_EQ(totalCount, expectedDictionarySize); | |
168 | -} | |
169 | - | |
170 | -TEST(LongStringDictionary, AddRemove) { | |
171 | - LongStringDictionary dict; | |
172 | - dict.SetKeyValue("rob", "ert"); | |
173 | - dict.SetKeyValue("mike", "pink"); | |
174 | - dict.SetKeyValue("mark", "allays"); | |
175 | - | |
176 | - EXPECT_EQ(3u, dict.GetCount()); | |
177 | - EXPECT_EQ("ert", dict.GetValueForKey("rob")); | |
178 | - EXPECT_EQ("pink", dict.GetValueForKey("mike")); | |
179 | - EXPECT_EQ("allays", dict.GetValueForKey("mark")); | |
180 | - | |
181 | - dict.RemoveKey("mike"); | |
182 | - | |
183 | - EXPECT_EQ(2u, dict.GetCount()); | |
184 | - EXPECT_EQ("", dict.GetValueForKey("mike")); | |
185 | - | |
186 | - dict.SetKeyValue("mark", "mal"); | |
187 | - EXPECT_EQ(2u, dict.GetCount()); | |
188 | - EXPECT_EQ("mal", dict.GetValueForKey("mark")); | |
189 | - | |
190 | - dict.RemoveKey("mark"); | |
191 | - EXPECT_EQ(1u, dict.GetCount()); | |
192 | - EXPECT_EQ("", dict.GetValueForKey("mark")); | |
193 | -} | |
194 | - | |
195 | -TEST(LongStringDictionary, AddRemoveLongValue) { | |
196 | - LongStringDictionary dict; | |
197 | - | |
198 | - string long_value = string(256, 'x'); | |
199 | - dict.SetKeyValue("rob", long_value.c_str()); | |
200 | - | |
201 | - EXPECT_EQ(2u, dict.GetCount()); | |
202 | - | |
203 | - string long_value_part_1 = string(255, 'x'); | |
204 | - | |
205 | - EXPECT_EQ(long_value_part_1, dict.GetValueForKey("rob__1")); | |
206 | - EXPECT_EQ("x", dict.GetValueForKey("rob__2")); | |
207 | - | |
208 | - EXPECT_EQ(long_value, dict.GetValueForKey("rob")); | |
209 | - | |
210 | - dict.RemoveKey("rob"); | |
211 | - EXPECT_EQ(0u, dict.GetCount()); | |
212 | -} | |
213 | - | |
214 | -TEST(LongStringDictionary, AddRemoveSuperLongValue) { | |
215 | - LongStringDictionary dict; | |
216 | - | |
217 | - string long_value = string(255 * 10, 'x'); | |
218 | - dict.SetKeyValue("rob", long_value.c_str()); | |
219 | - | |
220 | - EXPECT_EQ(10u, dict.GetCount()); | |
221 | - | |
222 | - string long_value_part = string(255, 'x'); | |
223 | - | |
224 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__1")); | |
225 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__2")); | |
226 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__3")); | |
227 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__4")); | |
228 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__5")); | |
229 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__6")); | |
230 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__7")); | |
231 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__8")); | |
232 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__9")); | |
233 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__10")); | |
234 | - EXPECT_EQ(10u, dict.GetCount()); | |
235 | - | |
236 | - EXPECT_EQ(long_value, dict.GetValueForKey("rob")); | |
237 | - | |
238 | - dict.RemoveKey("rob"); | |
239 | - EXPECT_EQ(0u, dict.GetCount()); | |
240 | -} | |
241 | - | |
242 | -TEST(LongStringDictionary, TruncateSuperLongValue) { | |
243 | - LongStringDictionary dict; | |
244 | - | |
245 | - string long_value = string(255 * 11, 'x'); | |
246 | - dict.SetKeyValue("rob", long_value.c_str()); | |
247 | - | |
248 | - EXPECT_EQ(10u, dict.GetCount()); | |
249 | - | |
250 | - string long_value_part = string(255, 'x'); | |
251 | - | |
252 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__1")); | |
253 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__2")); | |
254 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__3")); | |
255 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__4")); | |
256 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__5")); | |
257 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__6")); | |
258 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__7")); | |
259 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__8")); | |
260 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__9")); | |
261 | - EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__10")); | |
262 | - EXPECT_EQ(10u, dict.GetCount()); | |
263 | - | |
264 | - string expected_long_value = string(255 * 10, 'x'); | |
265 | - EXPECT_EQ(expected_long_value, dict.GetValueForKey("rob")); | |
266 | - | |
267 | - dict.RemoveKey("rob"); | |
268 | - EXPECT_EQ(0u, dict.GetCount()); | |
269 | -} | |
270 | - | |
271 | -TEST(LongStringDictionary, OverrideLongValue) { | |
272 | - LongStringDictionary dict; | |
273 | - | |
274 | - string long_value = string(255 * 10, 'x'); | |
275 | - dict.SetKeyValue("rob", long_value.c_str()); | |
276 | - | |
277 | - EXPECT_EQ(10u, dict.GetCount()); | |
278 | - EXPECT_EQ(long_value, dict.GetValueForKey("rob")); | |
279 | - | |
280 | - dict.SetKeyValue("rob", "short_value"); | |
281 | - | |
282 | - EXPECT_EQ(1u, dict.GetCount()); | |
283 | - EXPECT_EQ("short_value", dict.GetValueForKey("rob")); | |
284 | -} | |
285 | - | |
286 | -TEST(LongStringDictionary, OverrideShortValue) { | |
287 | - LongStringDictionary dict; | |
288 | - | |
289 | - dict.SetKeyValue("rob", "short_value"); | |
290 | - | |
291 | - EXPECT_EQ(1u, dict.GetCount()); | |
292 | - EXPECT_EQ("short_value", dict.GetValueForKey("rob")); | |
293 | - | |
294 | - string long_value = string(255 * 10, 'x'); | |
295 | - dict.SetKeyValue("rob", long_value.c_str()); | |
296 | - | |
297 | - EXPECT_EQ(10u, dict.GetCount()); | |
298 | - EXPECT_EQ(long_value, dict.GetValueForKey("rob")); | |
299 | -} | |
300 | - | |
301 | -} // namespace google_breakpad |
@@ -209,22 +209,20 @@ class NonAllocatingMap { | ||
209 | 209 | |
210 | 210 | // Given |key|, removes any associated value. |key| must not be NULL. If |
211 | 211 | // the key is not found, this is a noop. |
212 | - bool RemoveKey(const char* key) { | |
212 | + void RemoveKey(const char* key) { | |
213 | 213 | assert(key); |
214 | 214 | if (!key) |
215 | - return false; | |
215 | + return; | |
216 | 216 | |
217 | 217 | Entry* entry = GetEntryForKey(key); |
218 | 218 | if (entry) { |
219 | 219 | entry->key[0] = '\0'; |
220 | 220 | entry->value[0] = '\0'; |
221 | - return true; | |
222 | 221 | } |
223 | 222 | |
224 | 223 | #ifndef NDEBUG |
225 | 224 | assert(GetEntryForKey(key) == NULL); |
226 | 225 | #endif |
227 | - return false; | |
228 | 226 | } |
229 | 227 | |
230 | 228 | // Places a serialized version of the map into |map| and returns the size. |