Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: client/simple_string_dictionary.h

Issue 489993002: Add SimpleStringDictionary and its test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Rename the template to TSimpleStringDictionary<> Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « client/client.gyp ('k') | client/simple_string_dictionary.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
16 #define CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
17
18 #include <string.h>
19
20 #include "base/basictypes.h"
21 #include "base/logging.h"
22
23 namespace crashpad {
24
25 // Opaque type for the serialized representation of a TSimpleStringDictionary.
26 // One is created in TSimpleStringDictionary::Serialize and can be deserialized
27 // using one of the constructors.
28 struct SerializedSimpleStringDictionary;
29
30 // TSimpleStringDictionary is an implementation of a map/dictionary collection
31 // that uses a fixed amount of storage, so that it does not perform any dynamic
32 // allocations for its operations.
33 //
34 // The actual map storage (the Entry) is guaranteed to be POD, so that it can be
35 // transmitted over various IPC mechanisms.
36 //
37 // The template parameters control the amount of storage used for the key,
38 // value, and map. The KeySize and ValueSize are measured in bytes, not glyphs,
39 // and includes space for a \0 byte. This gives space for KeySize-1 and
40 // ValueSize-1 characters in an entry. NumEntries is the total number of entries
41 // that will fit in the map.
42 template <size_t KeySize = 256, size_t ValueSize = 256, size_t NumEntries = 64>
43 class TSimpleStringDictionary {
44 public:
45 // Constant and publicly accessible versions of the template parameters.
46 static const size_t key_size = KeySize;
47 static const size_t value_size = ValueSize;
48 static const size_t num_entries = NumEntries;
49
50 // An Entry object is a single entry in the map. If the key is a 0-length
51 // NUL-terminated string, the entry is empty.
52 struct Entry {
53 char key[KeySize];
54 char value[ValueSize];
55
56 bool is_active() const {
57 return key[0] != '\0';
58 }
59 };
60
61 // An Iterator can be used to iterate over all the active entries in a
62 // TSimpleStringDictionary.
63 class Iterator {
64 public:
65 explicit Iterator(const TSimpleStringDictionary& map)
66 : map_(map),
67 current_(0) {
68 }
69
70 // Returns the next entry in the map, or NULL if at the end of the
71 // collection.
72 const Entry* Next() {
73 while (current_ < map_.num_entries) {
74 const Entry* entry = &map_.entries_[current_++];
75 if (entry->is_active()) {
76 return entry;
77 }
78 }
79 return NULL;
80 }
81
82 private:
83 const TSimpleStringDictionary& map_;
84 size_t current_;
85
86 DISALLOW_COPY_AND_ASSIGN(Iterator);
87 };
88
89 TSimpleStringDictionary()
90 : entries_() {
91 }
92
93 TSimpleStringDictionary(const TSimpleStringDictionary& other) {
94 *this = other;
95 }
96
97 TSimpleStringDictionary& operator=(const TSimpleStringDictionary& other) {
98 memcpy(entries_, other.entries_, sizeof(entries_));
99 return *this;
100 }
101
102 // Constructs a map from its serialized form. |map| should be the out
103 // parameter from Serialize() and |size| should be its return value.
104 TSimpleStringDictionary(
105 const SerializedSimpleStringDictionary* map, size_t size) {
106 DCHECK_EQ(size, sizeof(entries_));
107 if (size == sizeof(entries_)) {
108 memcpy(entries_, map, size);
109 }
110 }
111
112 // Returns the number of active key/value pairs. The upper limit for this is
113 // NumEntries.
114 size_t GetCount() const {
115 size_t count = 0;
116 for (size_t i = 0; i < num_entries; ++i) {
117 if (entries_[i].is_active()) {
118 ++count;
119 }
120 }
121 return count;
122 }
123
124 // Given |key|, returns its corresponding |value|. |key| must not be NULL. If
125 // the key is not found, NULL is returned.
126 const char* GetValueForKey(const char* key) const {
127 DCHECK(key);
128 if (!key) {
129 return NULL;
130 }
131
132 const Entry* entry = GetConstEntryForKey(key);
133 if (!entry) {
134 return NULL;
135 }
136
137 return entry->value;
138 }
139
140 // Stores |value| into |key|, replacing the existing value if |key| is already
141 // present. |key| must not be NULL. If |value| is NULL, the key is removed
142 // from the map. If there is no more space in the map, then the operation
143 // silently fails.
144 void SetKeyValue(const char* key, const char* value) {
145 if (!value) {
146 RemoveKey(key);
147 return;
148 }
149
150 DCHECK(key);
151 if (!key) {
152 return;
153 }
154
155 // Key must not be an empty string.
156 DCHECK_NE(key[0], '\0');
157 if (key[0] == '\0') {
158 return;
159 }
160
161 Entry* entry = GetEntryForKey(key);
162
163 // If it does not yet exist, attempt to insert it.
164 if (!entry) {
165 for (size_t i = 0; i < num_entries; ++i) {
166 if (!entries_[i].is_active()) {
167 entry = &entries_[i];
168
169 strncpy(entry->key, key, key_size);
170 entry->key[key_size - 1] = '\0';
171
172 break;
173 }
174 }
175 }
176
177 // If the map is out of space, entry will be NULL.
178 if (!entry) {
179 return;
180 }
181
182 #ifndef NDEBUG
183 // Sanity check that the key only appears once.
184 int count = 0;
185 for (size_t i = 0; i < num_entries; ++i) {
186 if (strncmp(entries_[i].key, key, key_size) == 0) {
187 ++count;
188 }
189 }
190 DCHECK_EQ(count, 1);
191 #endif
192
193 strncpy(entry->value, value, value_size);
194 entry->value[value_size - 1] = '\0';
195 }
196
197 // Given |key|, removes any associated value. |key| must not be NULL. If the
198 // key is not found, this is a noop.
199 void RemoveKey(const char* key) {
200 DCHECK(key);
201 if (!key) {
202 return;
203 }
204
205 Entry* entry = GetEntryForKey(key);
206 if (entry) {
207 entry->key[0] = '\0';
208 entry->value[0] = '\0';
209 }
210
211 DCHECK_EQ(GetEntryForKey(key), static_cast<void*>(NULL));
212 }
213
214 // Places a serialized version of the map into |map| and returns the size.
215 // Both of these should be passed to the deserializing constructor. Note that
216 // the serialized |map| is scoped to the lifetime of the non-serialized
217 // instance of this class. The |map| can be copied across IPC boundaries.
218 size_t Serialize(const SerializedSimpleStringDictionary** map) const {
219 *map = reinterpret_cast<const SerializedSimpleStringDictionary*>(entries_);
220 return sizeof(entries_);
221 }
222
223 private:
224 const Entry* GetConstEntryForKey(const char* key) const {
225 for (size_t i = 0; i < num_entries; ++i) {
226 if (strncmp(key, entries_[i].key, key_size) == 0) {
227 return &entries_[i];
228 }
229 }
230 return NULL;
231 }
232
233 Entry* GetEntryForKey(const char* key) {
234 return const_cast<Entry*>(GetConstEntryForKey(key));
235 }
236
237 Entry entries_[NumEntries];
238 };
239
240 // For historical reasons this specialized version is available with the same
241 // size factors as a previous implementation.
242 typedef TSimpleStringDictionary<256, 256, 64> SimpleStringDictionary;
243
244 } // namespace crashpad
245
246 #endif // CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
OLDNEW
« no previous file with comments | « client/client.gyp ('k') | client/simple_string_dictionary.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698