00001
00016
00017 #ifndef NET_INSTAWEB_UTIL_PUBLIC_STRING_MULTI_MAP_H_
00018 #define NET_INSTAWEB_UTIL_PUBLIC_STRING_MULTI_MAP_H_
00019
00020 #include <map>
00021 #include <utility>
00022 #include <vector>
00023 #include "net/instaweb/util/public/basictypes.h"
00024 #include "net/instaweb/util/public/string.h"
00025 #include "net/instaweb/util/public/string_util.h"
00026
00027 namespace net_instaweb {
00028
00032 template<class StringCompare> class StringMultiMap {
00033 public:
00034 StringMultiMap() { }
00035 ~StringMultiMap() {
00036 Clear();
00037 }
00038
00039 bool empty() {
00040 return vector_.empty();
00041 }
00042
00043 void Clear() {
00044 for (int i = 0, n = vector_.size(); i < n; ++i) {
00045 delete vector_[i].second;
00046 }
00047 map_.clear();
00048 vector_.clear();
00049 }
00050
00052 int num_names() const { return map_.size(); }
00053
00056 int num_values() const { return vector_.size(); }
00057
00062 bool Lookup(const StringPiece& name, ConstStringStarVector* values) const {
00063 typename Map::const_iterator p = map_.find(name.as_string());
00064 bool ret = false;
00065 if (p != map_.end()) {
00066 ret = true;
00067 *values = p->second;
00068 }
00069 return ret;
00070 }
00071
00072 bool Has(const StringPiece& name) const {
00073 return map_.find(name.as_string()) != map_.end();
00074 }
00075
00077 bool RemoveAll(const StringPiece& var_name) {
00078 GoogleString var_string(var_name.data(), var_name.size());
00079 typename Map::iterator p = map_.find(var_string);
00080 bool removed = (p != map_.end());
00081 if (removed) {
00082 StringPairVector temp_vector;
00083 temp_vector.reserve(vector_.size());
00084 for (int i = 0; i < num_values(); ++i) {
00085 if (!StringCaseEqual(name(i), var_string)) {
00086 temp_vector.push_back(vector_[i]);
00087 } else {
00088 removed = true;
00089 delete vector_[i].second;
00090 }
00091 }
00092
00093 vector_.swap(temp_vector);
00094
00096 map_.erase(p);
00097 }
00098 return removed;
00099 }
00100
00101 const char* name(int index) const { return vector_[index].first; }
00102
00104 const GoogleString* value(int index) const { return vector_[index].second; }
00105
00107 void Add(const StringPiece& var_name, const StringPiece& value) {
00108 ConstStringStarVector dummy_values;
00109 GoogleString name_buf(var_name.data(), var_name.size());
00110 std::pair<typename Map::iterator, bool> iter_inserted = map_.insert(
00111 typename Map::value_type(name_buf, dummy_values));
00112 typename Map::iterator iter = iter_inserted.first;
00113 ConstStringStarVector& values = iter->second;
00114 GoogleString* value_copy = NULL;
00115 if (value.data() != NULL) {
00116 value_copy = new GoogleString(value.as_string());
00117 }
00118 values.push_back(value_copy);
00119 vector_.push_back(StringPair(iter->first.c_str(), value_copy));
00120 }
00121
00122 void CopyFrom(const StringMultiMap& string_multi_map) {
00123 Clear();
00124 for (int i = 0; i < string_multi_map.num_values(); ++i) {
00125 const GoogleString* value = string_multi_map.value(i);
00126 if (value != NULL) {
00127 Add(string_multi_map.name(i), *value);
00128 } else {
00129 Add(string_multi_map.name(i), NULL);
00130 }
00131 }
00132 }
00133
00134 private:
00143 typedef std::pair<const char*, GoogleString*> StringPair;
00144 typedef std::map<GoogleString, ConstStringStarVector, StringCompare> Map;
00145 typedef std::vector<StringPair> StringPairVector;
00146
00147 Map map_;
00148 StringPairVector vector_;
00149
00150 DISALLOW_COPY_AND_ASSIGN(StringMultiMap);
00151 };
00152
00153 class StringMultiMapInsensitive
00154 : public StringMultiMap<StringCompareInsensitive> {
00155 public:
00156 StringMultiMapInsensitive() { }
00157 private:
00158 DISALLOW_COPY_AND_ASSIGN(StringMultiMapInsensitive);
00159 };
00160
00161 class StringMultiMapSensitive : public StringMultiMap<StringCompareSensitive> {
00162 public:
00163 StringMultiMapSensitive() { }
00164 private:
00165 DISALLOW_COPY_AND_ASSIGN(StringMultiMapSensitive);
00166 };
00167
00168 }
00169
00170 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_STRING_MULTI_MAP_H_