Page Speed Optimization Libraries  1.13.35.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
string_multi_map.h
Go to the documentation of this file.
1 // Copyright 2010 Google Inc.
16 
17 #ifndef PAGESPEED_KERNEL_BASE_STRING_MULTI_MAP_H_
18 #define PAGESPEED_KERNEL_BASE_STRING_MULTI_MAP_H_
19 
20 #include <algorithm>
21 #include <set>
22 #include <utility>
23 #include <vector>
24 
25 #include "base/logging.h"
29 
30 namespace net_instaweb {
31 
39 template<class StringCompare> class StringMultiMap {
40  public:
41  StringMultiMap() { }
42  ~StringMultiMap() {
43  Clear();
44  }
45 
46  bool empty() const {
47  return vector_.empty();
48  }
49 
50  void Clear() {
51  for (int i = 0, n = vector_.size(); i < n; ++i) {
52  delete vector_[i].second;
53  }
54  set_.clear();
55  vector_.clear();
56  }
57 
59  int num_names() const { return set_.size(); }
60 
63  int num_values() const { return vector_.size(); }
64 
69  bool Lookup(const StringPiece& name, ConstStringStarVector* values) const {
70  SetEntry lookup_entry(name);
71  typename Set::const_iterator p = set_.find(lookup_entry);
72  bool ret = false;
73  if (p != set_.end()) {
74  ret = true;
75  const SetEntry& stored_entry = *p;
76  *values = stored_entry.values();
77  }
78  return ret;
79  }
80 
83  const GoogleString* Lookup1(const StringPiece& name) const {
84  ConstStringStarVector v;
85  if (Lookup(name, &v) && v.size() == 1) {
86  return v[0];
87  }
88  return NULL;
89  }
90 
91  bool Has(const StringPiece& name) const {
92  SetEntry lookup_entry(name);
93  return set_.find(lookup_entry) != set_.end();
94  }
95 
97  bool RemoveAll(const StringPiece& key) {
98  return RemoveAllFromSortedArray(&key, 1);
99  }
100 
104  bool RemoveAllFromSortedArray(const StringPiece* names, int names_size) {
105 #ifndef NDEBUG
106  for (int i = 1; i < names_size; ++i) {
107  StringCompare compare;
113  DCHECK(!compare(names[i], names[i - 1]))
114  << "\"" << names[i - 1] << "\" vs \"" << names[i];
115  }
116 #endif
117 
120  SetEntry lookup_entry;
121 
126  const int kNotFound = -1;
127  int index_of_first_match = kNotFound;
128  typename Set::iterator set_entry_of_first_match;
129  for (int i = 0; i < names_size; ++i) {
130  lookup_entry.set_key(names[i]);
131  set_entry_of_first_match = set_.find(lookup_entry);
132  if (set_entry_of_first_match != set_.end()) {
133  index_of_first_match = i;
134  break;
135  }
136  }
137 
138  if (index_of_first_match == kNotFound) {
139  return false;
140  } else {
141  StringPairVector temp_vector;
142  temp_vector.reserve(vector_.size() - 1);
143  StringCompare compare;
144  for (int i = 0; i < num_values(); ++i) {
145  if (std::binary_search(names, names + names_size, name(i), compare)) {
146  delete vector_[i].second;
147  } else {
148  temp_vector.push_back(vector_[i]);
149  }
150  }
151 
152  vector_.swap(temp_vector);
153 
154  set_.erase(set_entry_of_first_match);
155  for (int i = index_of_first_match + 1; i < names_size; ++i) {
156  lookup_entry.set_key(names[i]);
157  set_.erase(lookup_entry);
158  }
159  }
160  return true;
161  }
162 
163  StringPiece name(int index) const { return vector_[index].first; }
164 
166  const GoogleString* value(int index) const { return vector_[index].second; }
167 
169  void Add(const StringPiece& key, const StringPiece& value) {
170  SetEntry lookup_entry(key);
171  std::pair<typename Set::iterator, bool> iter_inserted =
172  set_.insert(lookup_entry);
173  typename Set::iterator iter = iter_inserted.first;
174 
184  SetEntry& entry = const_cast<SetEntry&>(*iter);
185  if (iter_inserted.second) {
187  entry.SaveKey();
188  }
189  GoogleString* value_copy = NULL;
190  if (value.data() != NULL) {
191  value_copy = new GoogleString(value.as_string());
192  }
193  entry.AddValue(value_copy);
194  vector_.push_back(StringPair(iter->key(), value_copy));
195  }
196 
203  void AddFromNameValuePairs(const StringPiece& name_value_list,
204  const StringPiece& separators,
205  char value_separator,
206  bool omit_if_no_value) {
207  StringPieceVector pairs;
208  SplitStringPieceToVector(name_value_list, separators, &pairs, true);
209  for (int i = 0, n = pairs.size(); i < n; ++i) {
210  StringPiece& pair = pairs[i];
211  StringPiece::size_type pos = pair.find(value_separator);
212  if (pos != StringPiece::npos) {
213  Add(pair.substr(0, pos), pair.substr(pos + 1));
214  } else if (!omit_if_no_value) {
215  Add(pair, StringPiece(NULL, 0));
216  }
217  }
218  }
219 
220  void CopyFrom(const StringMultiMap& string_multi_map) {
221  Clear();
222  for (int i = 0; i < string_multi_map.num_values(); ++i) {
223  const GoogleString* value = string_multi_map.value(i);
224  if (value != NULL) {
225  Add(string_multi_map.name(i), *value);
226  } else {
227  Add(string_multi_map.name(i), StringPiece());
228  }
229  }
230  }
231 
232  private:
235  class SetEntry {
236  public:
237  SetEntry() { }
238  SetEntry(StringPiece key) : key_(key) { }
239  SetEntry(const SetEntry& src)
240  : key_(src.key_) {
243  DCHECK(src.values_.empty());
244  }
245 
246  SetEntry& operator=(const SetEntry& src) {
247  if (&src != this) {
248  DCHECK(src.values_.empty());
249  key_ = src.key_;
250  }
251  return *this;
252  }
253 
254  void set_key(StringPiece key) {
255  key_ = key;
256  }
257 
258  void AddValue(const GoogleString* value) {
259  values_.push_back(value);
260  }
261 
265  void SaveKey() {
266  key_.CopyToString(&key_storage_);
267  key_ = key_storage_;
268  }
269 
270  StringPiece key() const { return key_; }
271  const ConstStringStarVector& values() const { return values_; }
272 
273  private:
274  GoogleString key_storage_;
275  StringPiece key_;
276  ConstStringStarVector values_;
277  };
278 
279  struct EntryCompare {
280  bool operator()(const SetEntry& a, const SetEntry& b) const {
281  return compare(a.key(), b.key());
282  }
283 
284  StringCompare compare;
285  };
286 
296  typedef std::pair<StringPiece, GoogleString*> StringPair;
297  typedef std::set<SetEntry, EntryCompare> Set;
298  typedef std::vector<StringPair> StringPairVector;
299 
300  Set set_;
301  StringPairVector vector_;
302 
303 
304 };
305 
307  : public StringMultiMap<StringCompareInsensitive> {
308  public:
310  private:
311 
312 };
313 
314 class StringMultiMapSensitive : public StringMultiMap<StringCompareSensitive> {
315  public:
317  private:
318 
319 };
320 
321 }
322 
323 #endif
void Add(const StringPiece &key, const StringPiece &value)
Add a new variable. The value can be null.
Definition: string_multi_map.h:169
bool Lookup(const StringPiece &name, ConstStringStarVector *values) const
Definition: string_multi_map.h:69
bool RemoveAll(const StringPiece &key)
Remove all variables by name. Returns true if anything was removed.
Definition: string_multi_map.h:97
int num_values() const
Definition: string_multi_map.h:63
Definition: string_multi_map.h:39
int num_names() const
Returns the number of distinct names.
Definition: string_multi_map.h:59
std::string GoogleString
PAGESPEED_KERNEL_BASE_STRING_H_.
Definition: string.h:24
void AddFromNameValuePairs(const StringPiece &name_value_list, const StringPiece &separators, char value_separator, bool omit_if_no_value)
Definition: string_multi_map.h:203
Definition: string_multi_map.h:314
const GoogleString * value(int index) const
Note that the value can be NULL.
Definition: string_multi_map.h:166
Definition: string_multi_map.h:306
const GoogleString * Lookup1(const StringPiece &name) const
Definition: string_multi_map.h:83
bool RemoveAllFromSortedArray(const StringPiece *names, int names_size)
Definition: string_multi_map.h:104
void SplitStringPieceToVector(StringPiece sp, StringPiece separators, StringPieceVector *components, bool omit_empty_strings)