1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140

base / value_iterators.h [blame]

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_VALUE_ITERATORS_H_
#define BASE_VALUE_ITERATORS_H_

#include <memory>
#include <string>
#include <utility>

#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"

namespace base {

class Value;

namespace detail {

using DictStorage = base::flat_map<std::string, std::unique_ptr<Value>>;

// This iterator closely resembles DictStorage::iterator, with one
// important exception. It abstracts the underlying unique_ptr away, meaning its
// value_type is std::pair<const std::string, Value>. It's reference type is a
// std::pair<const std::string&, Value&>, so that callers have read-write
// access without incurring a copy.
class BASE_EXPORT dict_iterator {
 public:
  using difference_type = DictStorage::iterator::difference_type;
  using value_type = std::pair<const std::string, Value>;
  using reference = std::pair<const std::string&, Value&>;
  using iterator_category = std::bidirectional_iterator_tag;

  class pointer {
   public:
    explicit pointer(const reference& ref);
    pointer(const pointer& ptr);
    pointer& operator=(const pointer& ptr) = delete;

    reference* operator->() { return &ref_; }

   private:
    reference ref_;
  };

  constexpr dict_iterator() = default;
  explicit dict_iterator(DictStorage::iterator dict_iter);
  dict_iterator(const dict_iterator& dict_iter);
  dict_iterator& operator=(const dict_iterator& dict_iter);
  ~dict_iterator();

  reference operator*();
  pointer operator->();

  dict_iterator& operator++();
  dict_iterator operator++(int);
  dict_iterator& operator--();
  dict_iterator operator--(int);

  BASE_EXPORT friend bool operator==(const dict_iterator& lhs,
                                     const dict_iterator& rhs);
  BASE_EXPORT friend bool operator!=(const dict_iterator& lhs,
                                     const dict_iterator& rhs);

  // Currently, there is no easy way to friend Value::Dict. Once dictionary
  // storage is updated to not require a proxy iterator, the implementation can
  // be folded into //base/values.h and a standard friend declaration can be
  // used instead.
  const DictStorage::iterator& GetUnderlyingIteratorDoNotUse() const
      LIFETIME_BOUND {
    return dict_iter_;
  }

 private:
  DictStorage::iterator dict_iter_;
};

// This iterator closely resembles DictStorage::const_iterator, with one
// important exception. It abstracts the underlying unique_ptr away, meaning its
// value_type is std::pair<const std::string, Value>. It's reference type is a
// std::pair<const std::string&, const Value&>, so that callers have read-only
// access without incurring a copy.
class BASE_EXPORT const_dict_iterator {
 public:
  using difference_type = DictStorage::const_iterator::difference_type;
  using value_type = std::pair<const std::string, Value>;
  using reference = std::pair<const std::string&, const Value&>;
  using iterator_category = std::bidirectional_iterator_tag;

  class pointer {
   public:
    explicit pointer(const reference& ref);
    pointer(const pointer& ptr);
    pointer& operator=(const pointer& ptr) = delete;

    const reference* operator->() const { return &ref_; }

   private:
    const reference ref_;
  };

  constexpr const_dict_iterator() = default;
  explicit const_dict_iterator(DictStorage::const_iterator dict_iter);
  const_dict_iterator(const const_dict_iterator& dict_iter);
  const_dict_iterator& operator=(const const_dict_iterator& dict_iter);
  ~const_dict_iterator();

  reference operator*() const;
  pointer operator->() const;

  const_dict_iterator& operator++();
  const_dict_iterator operator++(int);
  const_dict_iterator& operator--();
  const_dict_iterator operator--(int);

  BASE_EXPORT friend bool operator==(const const_dict_iterator& lhs,
                                     const const_dict_iterator& rhs);
  BASE_EXPORT friend bool operator!=(const const_dict_iterator& lhs,
                                     const const_dict_iterator& rhs);

  // Currently, there is no easy way to friend Value::Dict. Once dictionary
  // storage is updated to not require a proxy iterator, the implementation can
  // be folded into //base/values.h and a standard friend declaration can be
  // used instead.
  const DictStorage::const_iterator& GetUnderlyingIteratorDoNotUse() {
    return dict_iter_;
  }

 private:
  DictStorage::const_iterator dict_iter_;
};

}  // namespace detail

}  // namespace base

#endif  // BASE_VALUE_ITERATORS_H_