File indexing completed on 2025-01-18 09:28:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_HASH_MAP_HPP
0012 #define BOOST_ASIO_DETAIL_HASH_MAP_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <list>
0020 #include <utility>
0021 #include <boost/asio/detail/assert.hpp>
0022 #include <boost/asio/detail/noncopyable.hpp>
0023
0024 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0025 # include <boost/asio/detail/socket_types.hpp>
0026 #endif
0027
0028 #include <boost/asio/detail/push_options.hpp>
0029
0030 namespace boost {
0031 namespace asio {
0032 namespace detail {
0033
0034 inline std::size_t calculate_hash_value(int i)
0035 {
0036 return static_cast<std::size_t>(i);
0037 }
0038
0039 inline std::size_t calculate_hash_value(void* p)
0040 {
0041 return reinterpret_cast<std::size_t>(p)
0042 + (reinterpret_cast<std::size_t>(p) >> 3);
0043 }
0044
0045 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0046 inline std::size_t calculate_hash_value(SOCKET s)
0047 {
0048 return static_cast<std::size_t>(s);
0049 }
0050 #endif
0051
0052
0053 template <typename K, typename V>
0054 class hash_map
0055 : private noncopyable
0056 {
0057 public:
0058
0059 typedef std::pair<K, V> value_type;
0060
0061
0062 typedef typename std::list<value_type>::iterator iterator;
0063
0064
0065 typedef typename std::list<value_type>::const_iterator const_iterator;
0066
0067
0068 hash_map()
0069 : size_(0),
0070 buckets_(0),
0071 num_buckets_(0)
0072 {
0073 }
0074
0075
0076 ~hash_map()
0077 {
0078 delete[] buckets_;
0079 }
0080
0081
0082 iterator begin()
0083 {
0084 return values_.begin();
0085 }
0086
0087
0088 const_iterator begin() const
0089 {
0090 return values_.begin();
0091 }
0092
0093
0094 iterator end()
0095 {
0096 return values_.end();
0097 }
0098
0099
0100 const_iterator end() const
0101 {
0102 return values_.end();
0103 }
0104
0105
0106 bool empty() const
0107 {
0108 return values_.empty();
0109 }
0110
0111
0112 iterator find(const K& k)
0113 {
0114 if (num_buckets_)
0115 {
0116 size_t bucket = calculate_hash_value(k) % num_buckets_;
0117 iterator it = buckets_[bucket].first;
0118 if (it == values_.end())
0119 return values_.end();
0120 iterator end_it = buckets_[bucket].last;
0121 ++end_it;
0122 while (it != end_it)
0123 {
0124 if (it->first == k)
0125 return it;
0126 ++it;
0127 }
0128 }
0129 return values_.end();
0130 }
0131
0132
0133 const_iterator find(const K& k) const
0134 {
0135 if (num_buckets_)
0136 {
0137 size_t bucket = calculate_hash_value(k) % num_buckets_;
0138 const_iterator it = buckets_[bucket].first;
0139 if (it == values_.end())
0140 return it;
0141 const_iterator end_it = buckets_[bucket].last;
0142 ++end_it;
0143 while (it != end_it)
0144 {
0145 if (it->first == k)
0146 return it;
0147 ++it;
0148 }
0149 }
0150 return values_.end();
0151 }
0152
0153
0154 std::pair<iterator, bool> insert(const value_type& v)
0155 {
0156 if (size_ + 1 >= num_buckets_)
0157 rehash(hash_size(size_ + 1));
0158 size_t bucket = calculate_hash_value(v.first) % num_buckets_;
0159 iterator it = buckets_[bucket].first;
0160 if (it == values_.end())
0161 {
0162 buckets_[bucket].first = buckets_[bucket].last =
0163 values_insert(values_.end(), v);
0164 ++size_;
0165 return std::pair<iterator, bool>(buckets_[bucket].last, true);
0166 }
0167 iterator end_it = buckets_[bucket].last;
0168 ++end_it;
0169 while (it != end_it)
0170 {
0171 if (it->first == v.first)
0172 return std::pair<iterator, bool>(it, false);
0173 ++it;
0174 }
0175 buckets_[bucket].last = values_insert(end_it, v);
0176 ++size_;
0177 return std::pair<iterator, bool>(buckets_[bucket].last, true);
0178 }
0179
0180
0181 void erase(iterator it)
0182 {
0183 BOOST_ASIO_ASSERT(it != values_.end());
0184 BOOST_ASIO_ASSERT(num_buckets_ != 0);
0185
0186 size_t bucket = calculate_hash_value(it->first) % num_buckets_;
0187 bool is_first = (it == buckets_[bucket].first);
0188 bool is_last = (it == buckets_[bucket].last);
0189 if (is_first && is_last)
0190 buckets_[bucket].first = buckets_[bucket].last = values_.end();
0191 else if (is_first)
0192 ++buckets_[bucket].first;
0193 else if (is_last)
0194 --buckets_[bucket].last;
0195
0196 values_erase(it);
0197 --size_;
0198 }
0199
0200
0201 void erase(const K& k)
0202 {
0203 iterator it = find(k);
0204 if (it != values_.end())
0205 erase(it);
0206 }
0207
0208
0209 void clear()
0210 {
0211
0212 values_.clear();
0213 size_ = 0;
0214
0215
0216 iterator end_it = values_.end();
0217 for (size_t i = 0; i < num_buckets_; ++i)
0218 buckets_[i].first = buckets_[i].last = end_it;
0219 }
0220
0221 private:
0222
0223 static std::size_t hash_size(std::size_t num_elems)
0224 {
0225 static std::size_t sizes[] =
0226 {
0227 #if defined(BOOST_ASIO_HASH_MAP_BUCKETS)
0228 BOOST_ASIO_HASH_MAP_BUCKETS
0229 #else
0230 3, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
0231 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
0232 12582917, 25165843
0233 #endif
0234 };
0235 const std::size_t nth_size = sizeof(sizes) / sizeof(std::size_t) - 1;
0236 for (std::size_t i = 0; i < nth_size; ++i)
0237 if (num_elems < sizes[i])
0238 return sizes[i];
0239 return sizes[nth_size];
0240 }
0241
0242
0243 void rehash(std::size_t num_buckets)
0244 {
0245 if (num_buckets == num_buckets_)
0246 return;
0247 BOOST_ASIO_ASSERT(num_buckets != 0);
0248
0249 iterator end_iter = values_.end();
0250
0251
0252 bucket_type* tmp = new bucket_type[num_buckets];
0253 delete[] buckets_;
0254 buckets_ = tmp;
0255 num_buckets_ = num_buckets;
0256 for (std::size_t i = 0; i < num_buckets_; ++i)
0257 buckets_[i].first = buckets_[i].last = end_iter;
0258
0259
0260 iterator iter = values_.begin();
0261 while (iter != end_iter)
0262 {
0263 std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_;
0264 if (buckets_[bucket].last == end_iter)
0265 {
0266 buckets_[bucket].first = buckets_[bucket].last = iter++;
0267 }
0268 else if (++buckets_[bucket].last == iter)
0269 {
0270 ++iter;
0271 }
0272 else
0273 {
0274 values_.splice(buckets_[bucket].last, values_, iter++);
0275 --buckets_[bucket].last;
0276 }
0277 }
0278 }
0279
0280
0281
0282 iterator values_insert(iterator it, const value_type& v)
0283 {
0284 if (spares_.empty())
0285 {
0286 return values_.insert(it, v);
0287 }
0288 else
0289 {
0290 spares_.front() = v;
0291 values_.splice(it, spares_, spares_.begin());
0292 return --it;
0293 }
0294 }
0295
0296
0297 void values_erase(iterator it)
0298 {
0299 *it = value_type();
0300 spares_.splice(spares_.begin(), values_, it);
0301 }
0302
0303
0304 std::size_t size_;
0305
0306
0307 std::list<value_type> values_;
0308
0309
0310
0311 std::list<value_type> spares_;
0312
0313
0314 struct bucket_type
0315 {
0316 iterator first;
0317 iterator last;
0318 };
0319
0320
0321 bucket_type* buckets_;
0322
0323
0324 std::size_t num_buckets_;
0325 };
0326
0327 }
0328 }
0329 }
0330
0331 #include <boost/asio/detail/pop_options.hpp>
0332
0333 #endif