~alinuxninja/nginx-edge/trunk

« back to all changes in this revision

Viewing changes to debian/modules/ngx_pagespeed/psol/include/third_party/chromium/src/base/containers/small_map.h

  • Committer: Vivian
  • Date: 2015-12-04 18:20:11 UTC
  • Revision ID: git-v1:a36f2bc32e884f7473b3a47040e5411306144d7d
* Do not extract psol.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
 
// Use of this source code is governed by a BSD-style license that can be
3
 
// found in the LICENSE file.
4
 
 
5
 
#ifndef BASE_CONTAINERS_SMALL_MAP_H_
6
 
#define BASE_CONTAINERS_SMALL_MAP_H_
7
 
 
8
 
#include <map>
9
 
#include <string>
10
 
#include <utility>
11
 
 
12
 
#include "base/basictypes.h"
13
 
#include "base/containers/hash_tables.h"
14
 
#include "base/logging.h"
15
 
#include "base/memory/manual_constructor.h"
16
 
 
17
 
namespace base {
18
 
 
19
 
// An STL-like associative container which starts out backed by a simple
20
 
// array but switches to some other container type if it grows beyond a
21
 
// fixed size.
22
 
//
23
 
// WHAT TYPE OF MAP SHOULD YOU USE?
24
 
// --------------------------------
25
 
//
26
 
//  - std::map should be the default if you're not sure, since it's the most
27
 
//    difficult to mess up. Generally this is backed by a red-black tree. It
28
 
//    will generate a lot of code (if you use a common key type like int or
29
 
//    string the linker will probably emiminate the duplicates). It will
30
 
//    do heap allocations for each element.
31
 
//
32
 
//  - If you only ever keep a couple of items and have very simple usage,
33
 
//    consider whether a using a vector and brute-force searching it will be
34
 
//    the most efficient. It's not a lot of generated code (less then a
35
 
//    red-black tree if your key is "weird" and not eliminated as duplicate of
36
 
//    something else) and will probably be faster and do fewer heap allocations
37
 
//    than std::map if you have just a couple of items.
38
 
//
39
 
//  - base::hash_map should be used if you need O(1) lookups. It may waste
40
 
//    space in the hash table, and it can be easy to write correct-looking
41
 
//    code with the default hash function being wrong or poorly-behaving.
42
 
//
43
 
//  - SmallMap combines the performance benefits of the brute-force-searched
44
 
//    vector for small cases (no extra heap allocations), but can efficiently
45
 
//    fall back if you end up adding many items. It will generate more code
46
 
//    than std::map (at least 160 bytes for operator[]) which is bad if you
47
 
//    have a "weird" key where map functions can't be
48
 
//    duplicate-code-eliminated. If you have a one-off key and aren't in
49
 
//    performance-critical code, this bloat may negate some of the benefits and
50
 
//    you should consider on of the other options.
51
 
//
52
 
// SmallMap will pick up the comparator from the underlying map type. In
53
 
// std::map (and in MSVC additionally hash_map) only a "less" operator is
54
 
// defined, which requires us to do two comparisons per element when doing the
55
 
// brute-force search in the simple array.
56
 
//
57
 
// We define default overrides for the common map types to avoid this
58
 
// double-compare, but you should be aware of this if you use your own
59
 
// operator< for your map and supply yor own version of == to the SmallMap.
60
 
// You can use regular operator== by just doing:
61
 
//
62
 
//   base::SmallMap<std::map<MyKey, MyValue>, 4, std::equal_to<KyKey> >
63
 
//
64
 
//
65
 
// USAGE
66
 
// -----
67
 
//
68
 
// NormalMap:  The map type to fall back to.  This also defines the key
69
 
//             and value types for the SmallMap.
70
 
// kArraySize:  The size of the initial array of results. This will be
71
 
//              allocated with the SmallMap object rather than separately on
72
 
//              the heap. Once the map grows beyond this size, the map type
73
 
//              will be used instead.
74
 
// EqualKey:  A functor which tests two keys for equality.  If the wrapped
75
 
//            map type has a "key_equal" member (hash_map does), then that will
76
 
//            be used by default. If the wrapped map type has a strict weak
77
 
//            ordering "key_compare" (std::map does), that will be used to
78
 
//            implement equality by default.
79
 
// MapInit: A functor that takes a ManualConstructor<NormalMap>* and uses it to
80
 
//          initialize the map. This functor will be called at most once per
81
 
//          SmallMap, when the map exceeds the threshold of kArraySize and we
82
 
//          are about to copy values from the array to the map. The functor
83
 
//          *must* call one of the Init() methods provided by
84
 
//          ManualConstructor, since after it runs we assume that the NormalMap
85
 
//          has been initialized.
86
 
//
87
 
// example:
88
 
//   base::SmallMap< std::map<string, int> > days;
89
 
//   days["sunday"   ] = 0;
90
 
//   days["monday"   ] = 1;
91
 
//   days["tuesday"  ] = 2;
92
 
//   days["wednesday"] = 3;
93
 
//   days["thursday" ] = 4;
94
 
//   days["friday"   ] = 5;
95
 
//   days["saturday" ] = 6;
96
 
//
97
 
// You should assume that SmallMap might invalidate all the iterators
98
 
// on any call to erase(), insert() and operator[].
99
 
 
100
 
namespace internal {
101
 
 
102
 
template <typename NormalMap>
103
 
class SmallMapDefaultInit {
104
 
 public:
105
 
  void operator()(ManualConstructor<NormalMap>* map) const {
106
 
    map->Init();
107
 
  }
108
 
};
109
 
 
110
 
// has_key_equal<M>::value is true iff there exists a type M::key_equal. This is
111
 
// used to dispatch to one of the select_equal_key<> metafunctions below.
112
 
template <typename M>
113
 
struct has_key_equal {
114
 
  typedef char sml;  // "small" is sometimes #defined so we use an abbreviation.
115
 
  typedef struct { char dummy[2]; } big;
116
 
  // Two functions, one accepts types that have a key_equal member, and one that
117
 
  // accepts anything. They each return a value of a different size, so we can
118
 
  // determine at compile-time which function would have been called.
119
 
  template <typename U> static big test(typename U::key_equal*);
120
 
  template <typename> static sml test(...);
121
 
  // Determines if M::key_equal exists by looking at the size of the return
122
 
  // type of the compiler-chosen test() function.
123
 
  static const bool value = (sizeof(test<M>(0)) == sizeof(big));
124
 
};
125
 
template <typename M> const bool has_key_equal<M>::value;
126
 
 
127
 
// Base template used for map types that do NOT have an M::key_equal member,
128
 
// e.g., std::map<>. These maps have a strict weak ordering comparator rather
129
 
// than an equality functor, so equality will be implemented in terms of that
130
 
// comparator.
131
 
//
132
 
// There's a partial specialization of this template below for map types that do
133
 
// have an M::key_equal member.
134
 
template <typename M, bool has_key_equal_value>
135
 
struct select_equal_key {
136
 
  struct equal_key {
137
 
    bool operator()(const typename M::key_type& left,
138
 
                    const typename M::key_type& right) {
139
 
      // Implements equality in terms of a strict weak ordering comparator.
140
 
      typename M::key_compare comp;
141
 
      return !comp(left, right) && !comp(right, left);
142
 
    }
143
 
  };
144
 
};
145
 
 
146
 
// Provide overrides to use operator== for key compare for the "normal" map and
147
 
// hash map types. If you override the default comparator or allocator for a
148
 
// map or hash_map, or use another type of map, this won't get used.
149
 
//
150
 
// If we switch to using std::unordered_map for base::hash_map, then the
151
 
// hash_map specialization can be removed.
152
 
template <typename KeyType, typename ValueType>
153
 
struct select_equal_key< std::map<KeyType, ValueType>, false> {
154
 
  struct equal_key {
155
 
    bool operator()(const KeyType& left, const KeyType& right) {
156
 
      return left == right;
157
 
    }
158
 
  };
159
 
};
160
 
template <typename KeyType, typename ValueType>
161
 
struct select_equal_key< base::hash_map<KeyType, ValueType>, false> {
162
 
  struct equal_key {
163
 
    bool operator()(const KeyType& left, const KeyType& right) {
164
 
      return left == right;
165
 
    }
166
 
  };
167
 
};
168
 
 
169
 
// Partial template specialization handles case where M::key_equal exists, e.g.,
170
 
// hash_map<>.
171
 
template <typename M>
172
 
struct select_equal_key<M, true> {
173
 
  typedef typename M::key_equal equal_key;
174
 
};
175
 
 
176
 
}  // namespace internal
177
 
 
178
 
template <typename NormalMap,
179
 
          int kArraySize = 4,
180
 
          typename EqualKey =
181
 
              typename internal::select_equal_key<
182
 
                  NormalMap,
183
 
                  internal::has_key_equal<NormalMap>::value>::equal_key,
184
 
          typename MapInit = internal::SmallMapDefaultInit<NormalMap> >
185
 
class SmallMap {
186
 
  // We cannot rely on the compiler to reject array of size 0.  In
187
 
  // particular, gcc 2.95.3 does it but later versions allow 0-length
188
 
  // arrays.  Therefore, we explicitly reject non-positive kArraySize
189
 
  // here.
190
 
  COMPILE_ASSERT(kArraySize > 0, default_initial_size_should_be_positive);
191
 
 
192
 
 public:
193
 
  typedef typename NormalMap::key_type key_type;
194
 
  typedef typename NormalMap::mapped_type data_type;
195
 
  typedef typename NormalMap::mapped_type mapped_type;
196
 
  typedef typename NormalMap::value_type value_type;
197
 
  typedef EqualKey key_equal;
198
 
 
199
 
  SmallMap() : size_(0), functor_(MapInit()) {}
200
 
 
201
 
  explicit SmallMap(const MapInit& functor) : size_(0), functor_(functor) {}
202
 
 
203
 
  // Allow copy-constructor and assignment, since STL allows them too.
204
 
  SmallMap(const SmallMap& src) {
205
 
    // size_ and functor_ are initted in InitFrom()
206
 
    InitFrom(src);
207
 
  }
208
 
  void operator=(const SmallMap& src) {
209
 
    if (&src == this) return;
210
 
 
211
 
    // This is not optimal. If src and dest are both using the small
212
 
    // array, we could skip the teardown and reconstruct. One problem
213
 
    // to be resolved is that the value_type itself is pair<const K,
214
 
    // V>, and const K is not assignable.
215
 
    Destroy();
216
 
    InitFrom(src);
217
 
  }
218
 
  ~SmallMap() {
219
 
    Destroy();
220
 
  }
221
 
 
222
 
  class const_iterator;
223
 
 
224
 
  class iterator {
225
 
   public:
226
 
    typedef typename NormalMap::iterator::iterator_category iterator_category;
227
 
    typedef typename NormalMap::iterator::value_type value_type;
228
 
    typedef typename NormalMap::iterator::difference_type difference_type;
229
 
    typedef typename NormalMap::iterator::pointer pointer;
230
 
    typedef typename NormalMap::iterator::reference reference;
231
 
 
232
 
    inline iterator(): array_iter_(NULL) {}
233
 
 
234
 
    inline iterator& operator++() {
235
 
      if (array_iter_ != NULL) {
236
 
        ++array_iter_;
237
 
      } else {
238
 
        ++hash_iter_;
239
 
      }
240
 
      return *this;
241
 
    }
242
 
    inline iterator operator++(int /*unused*/) {
243
 
      iterator result(*this);
244
 
      ++(*this);
245
 
      return result;
246
 
    }
247
 
    inline iterator& operator--() {
248
 
      if (array_iter_ != NULL) {
249
 
        --array_iter_;
250
 
      } else {
251
 
        --hash_iter_;
252
 
      }
253
 
      return *this;
254
 
    }
255
 
    inline iterator operator--(int /*unused*/) {
256
 
      iterator result(*this);
257
 
      --(*this);
258
 
      return result;
259
 
    }
260
 
    inline value_type* operator->() const {
261
 
      if (array_iter_ != NULL) {
262
 
        return array_iter_->get();
263
 
      } else {
264
 
        return hash_iter_.operator->();
265
 
      }
266
 
    }
267
 
 
268
 
    inline value_type& operator*() const {
269
 
      if (array_iter_ != NULL) {
270
 
        return *array_iter_->get();
271
 
      } else {
272
 
        return *hash_iter_;
273
 
      }
274
 
    }
275
 
 
276
 
    inline bool operator==(const iterator& other) const {
277
 
      if (array_iter_ != NULL) {
278
 
        return array_iter_ == other.array_iter_;
279
 
      } else {
280
 
        return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
281
 
      }
282
 
    }
283
 
 
284
 
    inline bool operator!=(const iterator& other) const {
285
 
      return !(*this == other);
286
 
    }
287
 
 
288
 
    bool operator==(const const_iterator& other) const;
289
 
    bool operator!=(const const_iterator& other) const;
290
 
 
291
 
   private:
292
 
    friend class SmallMap;
293
 
    friend class const_iterator;
294
 
    inline explicit iterator(ManualConstructor<value_type>* init)
295
 
      : array_iter_(init) {}
296
 
    inline explicit iterator(const typename NormalMap::iterator& init)
297
 
      : array_iter_(NULL), hash_iter_(init) {}
298
 
 
299
 
    ManualConstructor<value_type>* array_iter_;
300
 
    typename NormalMap::iterator hash_iter_;
301
 
  };
302
 
 
303
 
  class const_iterator {
304
 
   public:
305
 
    typedef typename NormalMap::const_iterator::iterator_category
306
 
        iterator_category;
307
 
    typedef typename NormalMap::const_iterator::value_type value_type;
308
 
    typedef typename NormalMap::const_iterator::difference_type difference_type;
309
 
    typedef typename NormalMap::const_iterator::pointer pointer;
310
 
    typedef typename NormalMap::const_iterator::reference reference;
311
 
 
312
 
    inline const_iterator(): array_iter_(NULL) {}
313
 
    // Non-explicit ctor lets us convert regular iterators to const iterators
314
 
    inline const_iterator(const iterator& other)
315
 
      : array_iter_(other.array_iter_), hash_iter_(other.hash_iter_) {}
316
 
 
317
 
    inline const_iterator& operator++() {
318
 
      if (array_iter_ != NULL) {
319
 
        ++array_iter_;
320
 
      } else {
321
 
        ++hash_iter_;
322
 
      }
323
 
      return *this;
324
 
    }
325
 
    inline const_iterator operator++(int /*unused*/) {
326
 
      const_iterator result(*this);
327
 
      ++(*this);
328
 
      return result;
329
 
    }
330
 
 
331
 
    inline const_iterator& operator--() {
332
 
      if (array_iter_ != NULL) {
333
 
        --array_iter_;
334
 
      } else {
335
 
        --hash_iter_;
336
 
      }
337
 
      return *this;
338
 
    }
339
 
    inline const_iterator operator--(int /*unused*/) {
340
 
      const_iterator result(*this);
341
 
      --(*this);
342
 
      return result;
343
 
    }
344
 
 
345
 
    inline const value_type* operator->() const {
346
 
      if (array_iter_ != NULL) {
347
 
        return array_iter_->get();
348
 
      } else {
349
 
        return hash_iter_.operator->();
350
 
      }
351
 
    }
352
 
 
353
 
    inline const value_type& operator*() const {
354
 
      if (array_iter_ != NULL) {
355
 
        return *array_iter_->get();
356
 
      } else {
357
 
        return *hash_iter_;
358
 
      }
359
 
    }
360
 
 
361
 
    inline bool operator==(const const_iterator& other) const {
362
 
      if (array_iter_ != NULL) {
363
 
        return array_iter_ == other.array_iter_;
364
 
      } else {
365
 
        return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
366
 
      }
367
 
    }
368
 
 
369
 
    inline bool operator!=(const const_iterator& other) const {
370
 
      return !(*this == other);
371
 
    }
372
 
 
373
 
   private:
374
 
    friend class SmallMap;
375
 
    inline explicit const_iterator(
376
 
        const ManualConstructor<value_type>* init)
377
 
      : array_iter_(init) {}
378
 
    inline explicit const_iterator(
379
 
        const typename NormalMap::const_iterator& init)
380
 
      : array_iter_(NULL), hash_iter_(init) {}
381
 
 
382
 
    const ManualConstructor<value_type>* array_iter_;
383
 
    typename NormalMap::const_iterator hash_iter_;
384
 
  };
385
 
 
386
 
  iterator find(const key_type& key) {
387
 
    key_equal compare;
388
 
    if (size_ >= 0) {
389
 
      for (int i = 0; i < size_; i++) {
390
 
        if (compare(array_[i]->first, key)) {
391
 
          return iterator(array_ + i);
392
 
        }
393
 
      }
394
 
      return iterator(array_ + size_);
395
 
    } else {
396
 
      return iterator(map()->find(key));
397
 
    }
398
 
  }
399
 
 
400
 
  const_iterator find(const key_type& key) const {
401
 
    key_equal compare;
402
 
    if (size_ >= 0) {
403
 
      for (int i = 0; i < size_; i++) {
404
 
        if (compare(array_[i]->first, key)) {
405
 
          return const_iterator(array_ + i);
406
 
        }
407
 
      }
408
 
      return const_iterator(array_ + size_);
409
 
    } else {
410
 
      return const_iterator(map()->find(key));
411
 
    }
412
 
  }
413
 
 
414
 
  // Invalidates iterators.
415
 
  data_type& operator[](const key_type& key) {
416
 
    key_equal compare;
417
 
 
418
 
    if (size_ >= 0) {
419
 
      // operator[] searches backwards, favoring recently-added
420
 
      // elements.
421
 
      for (int i = size_-1; i >= 0; --i) {
422
 
        if (compare(array_[i]->first, key)) {
423
 
          return array_[i]->second;
424
 
        }
425
 
      }
426
 
      if (size_ == kArraySize) {
427
 
        ConvertToRealMap();
428
 
        return (*map_)[key];
429
 
      } else {
430
 
        array_[size_].Init(key, data_type());
431
 
        return array_[size_++]->second;
432
 
      }
433
 
    } else {
434
 
      return (*map_)[key];
435
 
    }
436
 
  }
437
 
 
438
 
  // Invalidates iterators.
439
 
  std::pair<iterator, bool> insert(const value_type& x) {
440
 
    key_equal compare;
441
 
 
442
 
    if (size_ >= 0) {
443
 
      for (int i = 0; i < size_; i++) {
444
 
        if (compare(array_[i]->first, x.first)) {
445
 
          return std::make_pair(iterator(array_ + i), false);
446
 
        }
447
 
      }
448
 
      if (size_ == kArraySize) {
449
 
        ConvertToRealMap();  // Invalidates all iterators!
450
 
        std::pair<typename NormalMap::iterator, bool> ret = map_->insert(x);
451
 
        return std::make_pair(iterator(ret.first), ret.second);
452
 
      } else {
453
 
        array_[size_].Init(x);
454
 
        return std::make_pair(iterator(array_ + size_++), true);
455
 
      }
456
 
    } else {
457
 
      std::pair<typename NormalMap::iterator, bool> ret = map_->insert(x);
458
 
      return std::make_pair(iterator(ret.first), ret.second);
459
 
    }
460
 
  }
461
 
 
462
 
  // Invalidates iterators.
463
 
  template <class InputIterator>
464
 
  void insert(InputIterator f, InputIterator l) {
465
 
    while (f != l) {
466
 
      insert(*f);
467
 
      ++f;
468
 
    }
469
 
  }
470
 
 
471
 
  iterator begin() {
472
 
    if (size_ >= 0) {
473
 
      return iterator(array_);
474
 
    } else {
475
 
      return iterator(map_->begin());
476
 
    }
477
 
  }
478
 
  const_iterator begin() const {
479
 
    if (size_ >= 0) {
480
 
      return const_iterator(array_);
481
 
    } else {
482
 
      return const_iterator(map_->begin());
483
 
    }
484
 
  }
485
 
 
486
 
  iterator end() {
487
 
    if (size_ >= 0) {
488
 
      return iterator(array_ + size_);
489
 
    } else {
490
 
      return iterator(map_->end());
491
 
    }
492
 
  }
493
 
  const_iterator end() const {
494
 
    if (size_ >= 0) {
495
 
      return const_iterator(array_ + size_);
496
 
    } else {
497
 
      return const_iterator(map_->end());
498
 
    }
499
 
  }
500
 
 
501
 
  void clear() {
502
 
    if (size_ >= 0) {
503
 
      for (int i = 0; i < size_; i++) {
504
 
        array_[i].Destroy();
505
 
      }
506
 
    } else {
507
 
      map_.Destroy();
508
 
    }
509
 
    size_ = 0;
510
 
  }
511
 
 
512
 
  // Invalidates iterators.
513
 
  void erase(const iterator& position) {
514
 
    if (size_ >= 0) {
515
 
      int i = position.array_iter_ - array_;
516
 
      array_[i].Destroy();
517
 
      --size_;
518
 
      if (i != size_) {
519
 
        array_[i].Init(*array_[size_]);
520
 
        array_[size_].Destroy();
521
 
      }
522
 
    } else {
523
 
      map_->erase(position.hash_iter_);
524
 
    }
525
 
  }
526
 
 
527
 
  size_t erase(const key_type& key) {
528
 
    iterator iter = find(key);
529
 
    if (iter == end()) return 0u;
530
 
    erase(iter);
531
 
    return 1u;
532
 
  }
533
 
 
534
 
  size_t count(const key_type& key) const {
535
 
    return (find(key) == end()) ? 0 : 1;
536
 
  }
537
 
 
538
 
  size_t size() const {
539
 
    if (size_ >= 0) {
540
 
      return static_cast<size_t>(size_);
541
 
    } else {
542
 
      return map_->size();
543
 
    }
544
 
  }
545
 
 
546
 
  bool empty() const {
547
 
    if (size_ >= 0) {
548
 
      return (size_ == 0);
549
 
    } else {
550
 
      return map_->empty();
551
 
    }
552
 
  }
553
 
 
554
 
  // Returns true if we have fallen back to using the underlying map
555
 
  // representation.
556
 
  bool UsingFullMap() const {
557
 
    return size_ < 0;
558
 
  }
559
 
 
560
 
  inline NormalMap* map() {
561
 
    CHECK(UsingFullMap());
562
 
    return map_.get();
563
 
  }
564
 
  inline const NormalMap* map() const {
565
 
    CHECK(UsingFullMap());
566
 
    return map_.get();
567
 
  }
568
 
 
569
 
 private:
570
 
  int size_;  // negative = using hash_map
571
 
 
572
 
  MapInit functor_;
573
 
 
574
 
  // We want to call constructors and destructors manually, but we don't
575
 
  // want to allocate and deallocate the memory used for them separately.
576
 
  // So, we use this crazy ManualConstructor class.
577
 
  //
578
 
  // Since array_ and map_ are mutually exclusive, we'll put them in a
579
 
  // union, too.  We add in a dummy_ value which quiets MSVC from otherwise
580
 
  // giving an erroneous "union member has copy constructor" error message
581
 
  // (C2621). This dummy member has to come before array_ to quiet the
582
 
  // compiler.
583
 
  //
584
 
  // TODO(brettw) remove this and use C++11 unions when we require C++11.
585
 
  union {
586
 
    ManualConstructor<value_type> dummy_;
587
 
    ManualConstructor<value_type> array_[kArraySize];
588
 
    ManualConstructor<NormalMap> map_;
589
 
  };
590
 
 
591
 
  void ConvertToRealMap() {
592
 
    // Move the current elements into a temporary array.
593
 
    ManualConstructor<value_type> temp_array[kArraySize];
594
 
 
595
 
    for (int i = 0; i < kArraySize; i++) {
596
 
      temp_array[i].Init(*array_[i]);
597
 
      array_[i].Destroy();
598
 
    }
599
 
 
600
 
    // Initialize the map.
601
 
    size_ = -1;
602
 
    functor_(&map_);
603
 
 
604
 
    // Insert elements into it.
605
 
    for (int i = 0; i < kArraySize; i++) {
606
 
      map_->insert(*temp_array[i]);
607
 
      temp_array[i].Destroy();
608
 
    }
609
 
  }
610
 
 
611
 
  // Helpers for constructors and destructors.
612
 
  void InitFrom(const SmallMap& src) {
613
 
    functor_ = src.functor_;
614
 
    size_ = src.size_;
615
 
    if (src.size_ >= 0) {
616
 
      for (int i = 0; i < size_; i++) {
617
 
        array_[i].Init(*src.array_[i]);
618
 
      }
619
 
    } else {
620
 
      functor_(&map_);
621
 
      (*map_.get()) = (*src.map_.get());
622
 
    }
623
 
  }
624
 
  void Destroy() {
625
 
    if (size_ >= 0) {
626
 
      for (int i = 0; i < size_; i++) {
627
 
        array_[i].Destroy();
628
 
      }
629
 
    } else {
630
 
      map_.Destroy();
631
 
    }
632
 
  }
633
 
};
634
 
 
635
 
template <typename NormalMap, int kArraySize, typename EqualKey,
636
 
          typename Functor>
637
 
inline bool SmallMap<NormalMap, kArraySize, EqualKey,
638
 
                     Functor>::iterator::operator==(
639
 
    const const_iterator& other) const {
640
 
  return other == *this;
641
 
}
642
 
template <typename NormalMap, int kArraySize, typename EqualKey,
643
 
          typename Functor>
644
 
inline bool SmallMap<NormalMap, kArraySize, EqualKey,
645
 
                     Functor>::iterator::operator!=(
646
 
    const const_iterator& other) const {
647
 
  return other != *this;
648
 
}
649
 
 
650
 
}  // namespace base
651
 
 
652
 
#endif  // BASE_CONTAINERS_SMALL_MAP_H_