OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // STL utility functions. Usually, these replace built-in, but slow(!), | 5 // STL utility functions. Usually, these replace built-in, but slow(!), |
6 // STL functions with more efficient versions. | 6 // STL functions with more efficient versions. |
7 | 7 |
8 #ifndef BASE_STL_UTIL_INL_H_ | 8 #ifndef BASE_STL_UTIL_INL_H_ |
9 #define BASE_STL_UTIL_INL_H_ | 9 #define BASE_STL_UTIL_INL_H_ |
10 #pragma once | 10 #pragma once |
11 | 11 |
12 #include <assert.h> | |
12 #include <string.h> // for memcpy | 13 #include <string.h> // for memcpy |
14 | |
13 #include <functional> | 15 #include <functional> |
14 #include <set> | 16 #include <set> |
15 #include <string> | 17 #include <string> |
16 #include <vector> | 18 #include <vector> |
17 #include <cassert> | |
18 | 19 |
19 // Clear internal memory of an STL object. | 20 // Clear internal memory of an STL object. |
20 // STL clear()/reserve(0) does not always free internal memory allocated | 21 // STL clear()/reserve(0) does not always free internal memory allocated |
21 // This function uses swap/destructor to ensure the internal memory is freed. | 22 // This function uses swap/destructor to ensure the internal memory is freed. |
22 template<class T> void STLClearObject(T* obj) { | 23 template<class T> void STLClearObject(T* obj) { |
23 T tmp; | 24 T tmp; |
24 tmp.swap(*obj); | 25 tmp.swap(*obj); |
25 obj->reserve(0); // this is because sometimes "T tmp" allocates objects with | 26 // Sometimes "T tmp" allocates objects with memory (arena implementation?). |
26 // memory (arena implementation?). use reserve() | 27 // Hence using additional reserve(0) even if it doesn't always work. |
27 // to clear() even if it doesn't always work | 28 obj->reserve(0); |
28 } | |
29 | |
30 // Reduce memory usage on behalf of object if it is using more than | |
31 // "bytes" bytes of space. By default, we clear objects over 1MB. | |
32 template <class T> inline void STLClearIfBig(T* obj, size_t limit = 1<<20) { | |
33 if (obj->capacity() >= limit) { | |
34 STLClearObject(obj); | |
35 } else { | |
36 obj->clear(); | |
37 } | |
38 } | |
39 | |
40 // Reserve space for STL object. | |
41 // STL's reserve() will always copy. | |
42 // This function avoid the copy if we already have capacity | |
43 template<class T> void STLReserveIfNeeded(T* obj, int new_size) { | |
44 if (obj->capacity() < new_size) // increase capacity | |
45 obj->reserve(new_size); | |
46 else if (obj->size() > new_size) // reduce size | |
47 obj->resize(new_size); | |
48 } | 29 } |
49 | 30 |
50 // STLDeleteContainerPointers() | 31 // STLDeleteContainerPointers() |
51 // For a range within a container of pointers, calls delete | 32 // For a range within a container of pointers, calls delete |
52 // (non-array version) on these pointers. | 33 // (non-array version) on these pointers. |
53 // NOTE: for these three functions, we could just implement a DeleteObject | 34 // NOTE: for these three functions, we could just implement a DeleteObject |
54 // functor and then call for_each() on the range and functor, but this | 35 // functor and then call for_each() on the range and functor, but this |
55 // requires us to pull in all of algorithm.h, which seems expensive. | 36 // requires us to pull in all of algorithm.h, which seems expensive. |
56 // For hash_[multi]set, it is important that this deletes behind the iterator | 37 // For hash_[multi]set, it is important that this deletes behind the iterator |
57 // because the hash_set may call the hash function on the iterator when it is | 38 // because the hash_set may call the hash function on the iterator when it is |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 // (non-array version) on the SECOND item in the pairs. | 85 // (non-array version) on the SECOND item in the pairs. |
105 template <class ForwardIterator> | 86 template <class ForwardIterator> |
106 void STLDeleteContainerPairSecondPointers(ForwardIterator begin, | 87 void STLDeleteContainerPairSecondPointers(ForwardIterator begin, |
107 ForwardIterator end) { | 88 ForwardIterator end) { |
108 while (begin != end) { | 89 while (begin != end) { |
109 delete begin->second; | 90 delete begin->second; |
110 ++begin; | 91 ++begin; |
111 } | 92 } |
112 } | 93 } |
113 | 94 |
114 template<typename T> | |
115 inline void STLAssignToVector(std::vector<T>* vec, | |
116 const T* ptr, | |
117 size_t n) { | |
118 vec->resize(n); | |
119 memcpy(&vec->front(), ptr, n*sizeof(T)); | |
120 } | |
121 | |
122 /***** Hack to allow faster assignment to a vector *****/ | |
123 | |
124 // This routine speeds up an assignment of 32 bytes to a vector from | |
125 // about 250 cycles per assignment to about 140 cycles. | |
126 // | |
127 // Usage: | |
128 // STLAssignToVectorChar(&vec, ptr, size); | |
129 // STLAssignToString(&str, ptr, size); | |
130 | |
131 inline void STLAssignToVectorChar(std::vector<char>* vec, | |
132 const char* ptr, | |
133 size_t n) { | |
134 STLAssignToVector(vec, ptr, n); | |
135 } | |
136 | |
137 inline void STLAssignToString(std::string* str, const char* ptr, size_t n) { | |
138 str->resize(n); | |
139 memcpy(&*str->begin(), ptr, n); | |
140 } | |
141 | |
142 // To treat a possibly-empty vector as an array, use these functions. | 95 // To treat a possibly-empty vector as an array, use these functions. |
143 // If you know the array will never be empty, you can use &*v.begin() | 96 // If you know the array will never be empty, you can use &*v.begin() |
144 // directly, but that is allowed to dump core if v is empty. This | 97 // directly, but that is undefined behaviour if v is empty. |
145 // function is the most efficient code that will work, taking into | |
146 // account how our STL is actually implemented. THIS IS NON-PORTABLE | |
147 // CODE, so call us instead of repeating the nonportable code | |
148 // everywhere. If our STL implementation changes, we will need to | |
149 // change this as well. | |
150 | 98 |
151 template<typename T> | 99 template<typename T> |
152 inline T* vector_as_array(std::vector<T>* v) { | 100 inline T* vector_as_array(std::vector<T>* v) { |
153 # ifdef NDEBUG | 101 # ifdef NDEBUG |
154 return &*v->begin(); | 102 return &*v->begin(); |
155 # else | 103 # else |
156 return v->empty() ? NULL : &*v->begin(); | 104 return v->empty() ? NULL : &*v->begin(); |
157 # endif | 105 # endif |
158 } | 106 } |
159 | 107 |
160 template<typename T> | 108 template<typename T> |
161 inline const T* vector_as_array(const std::vector<T>* v) { | 109 inline const T* vector_as_array(const std::vector<T>* v) { |
162 # ifdef NDEBUG | 110 # ifdef NDEBUG |
163 return &*v->begin(); | 111 return &*v->begin(); |
164 # else | 112 # else |
165 return v->empty() ? NULL : &*v->begin(); | 113 return v->empty() ? NULL : &*v->begin(); |
166 # endif | 114 # endif |
167 } | 115 } |
168 | 116 |
169 // Return a mutable char* pointing to a string's internal buffer, | 117 // Return a mutable char* pointing to a string's internal buffer, |
170 // which may not be null-terminated. Writing through this pointer will | 118 // which may be not null-terminated. Writing through this pointer will |
brettw
2011/07/15 05:32:38
Seems like the old comment was fine (and grammatic
Denis Lagno
2011/07/18 16:12:38
Reverted.
| |
171 // modify the string. | 119 // modify the string. |
172 // | 120 // |
173 // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the | 121 // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the |
174 // next call to a string method that invalidates iterators. | 122 // next call to a string method that invalidates iterators. |
175 // | 123 // |
176 // As of 2006-04, there is no standard-blessed way of getting a | 124 // As of 2006-04, there is no standard-blessed way of getting a |
177 // mutable reference to a string's internal buffer. However, issue 530 | 125 // mutable reference to a string's internal buffer. However, issue 530 |
178 // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) | 126 // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) |
179 // proposes this as the method. According to Matt Austern, this should | 127 // proposes this as the method. According to Matt Austern, this should |
180 // already work on all current implementations. | 128 // already work on all current implementations. |
181 inline char* string_as_array(std::string* str) { | 129 inline char* string_as_array(std::string* str) { |
182 // DO NOT USE const_cast<char*>(str->data())! See the unittest for why. | 130 // DO NOT USE const_cast<char*>(str->data()) |
183 return str->empty() ? NULL : &*str->begin(); | 131 return str->empty() ? NULL : &*str->begin(); |
184 } | 132 } |
185 | 133 |
134 template<typename T> | |
135 inline void STLAssignToVector(std::vector<T>* vec, const T* ptr, size_t n) { | |
136 vec->resize(n); | |
137 memcpy(vector_as_array(vec), ptr, n*sizeof(T)); | |
138 } | |
139 | |
140 inline void STLAssignToString(std::string* str, const char* ptr, size_t n) { | |
141 str->resize(n); | |
142 memcpy(string_as_array(str), ptr, n); | |
143 } | |
144 | |
186 // These are methods that test two hash maps/sets for equality. These exist | 145 // These are methods that test two hash maps/sets for equality. These exist |
187 // because the == operator in the STL can return false when the maps/sets | 146 // because the == operator in the STL can return false when the maps/sets |
188 // contain identical elements. This is because it compares the internal hash | 147 // contain identical elements. This is because it compares the internal hash |
189 // tables which may be different if the order of insertions and deletions | 148 // tables which may be different if the order of insertions and deletions |
190 // differed. | 149 // differed. |
191 | 150 |
192 template <class HashSet> | 151 template <class HashSet> |
193 inline bool HashSetEquality(const HashSet& set_a, const HashSet& set_b) { | 152 inline bool HashSetEquality(const HashSet& set_a, const HashSet& set_b) { |
194 if (set_a.size() != set_b.size()) return false; | 153 if (set_a.size() != set_b.size()) return false; |
195 for (typename HashSet::const_iterator i = set_a.begin(); | 154 for (typename HashSet::const_iterator i = set_a.begin(); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 } | 402 } |
444 | 403 |
445 // Test to see if a set, map, hash_set or hash_map contains a particular key. | 404 // Test to see if a set, map, hash_set or hash_map contains a particular key. |
446 // Returns true if the key is in the collection. | 405 // Returns true if the key is in the collection. |
447 template <typename Collection, typename Key> | 406 template <typename Collection, typename Key> |
448 bool ContainsKey(const Collection& collection, const Key& key) { | 407 bool ContainsKey(const Collection& collection, const Key& key) { |
449 return collection.find(key) != collection.end(); | 408 return collection.find(key) != collection.end(); |
450 } | 409 } |
451 | 410 |
452 #endif // BASE_STL_UTIL_INL_H_ | 411 #endif // BASE_STL_UTIL_INL_H_ |
OLD | NEW |