Commit 46992f02 authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[base] Use Checked Iterators in ListValue

While base::Value switched to checked iterators in its list API,
base::ListValue still used unchecked std::vector<Value>::iterators.
This change fixes this oversight and slightly improves the checked
iterator interface by making the comparison operators non-members, thus
allowing implicit conversions on both arguments.

Bug: 990059
Change-Id: I7b3bb4573300fe7f391c6b911817448f8aee7519
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2060672
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#743050}
parent 9b056aff
...@@ -2487,6 +2487,7 @@ test("base_unittests") { ...@@ -2487,6 +2487,7 @@ test("base_unittests") {
"component_export_unittest.cc", "component_export_unittest.cc",
"containers/adapters_unittest.cc", "containers/adapters_unittest.cc",
"containers/buffer_iterator_unittest.cc", "containers/buffer_iterator_unittest.cc",
"containers/checked_iterators_unittest.cc",
"containers/checked_range_unittest.cc", "containers/checked_range_unittest.cc",
"containers/circular_deque_unittest.cc", "containers/circular_deque_unittest.cc",
"containers/flat_map_unittest.cc", "containers/flat_map_unittest.cc",
......
...@@ -60,34 +60,39 @@ class CheckedContiguousIterator { ...@@ -60,34 +60,39 @@ class CheckedContiguousIterator {
constexpr CheckedContiguousIterator& operator=( constexpr CheckedContiguousIterator& operator=(
const CheckedContiguousIterator& other) = default; const CheckedContiguousIterator& other) = default;
constexpr bool operator==(const CheckedContiguousIterator& other) const { friend constexpr bool operator==(const CheckedContiguousIterator& lhs,
CheckComparable(other); const CheckedContiguousIterator& rhs) {
return current_ == other.current_; lhs.CheckComparable(rhs);
return lhs.current_ == rhs.current_;
} }
constexpr bool operator!=(const CheckedContiguousIterator& other) const { friend constexpr bool operator!=(const CheckedContiguousIterator& lhs,
CheckComparable(other); const CheckedContiguousIterator& rhs) {
return current_ != other.current_; lhs.CheckComparable(rhs);
return lhs.current_ != rhs.current_;
} }
constexpr bool operator<(const CheckedContiguousIterator& other) const { friend constexpr bool operator<(const CheckedContiguousIterator& lhs,
CheckComparable(other); const CheckedContiguousIterator& rhs) {
return current_ < other.current_; lhs.CheckComparable(rhs);
return lhs.current_ < rhs.current_;
} }
constexpr bool operator<=(const CheckedContiguousIterator& other) const { friend constexpr bool operator<=(const CheckedContiguousIterator& lhs,
CheckComparable(other); const CheckedContiguousIterator& rhs) {
return current_ <= other.current_; lhs.CheckComparable(rhs);
return lhs.current_ <= rhs.current_;
} }
friend constexpr bool operator>(const CheckedContiguousIterator& lhs,
constexpr bool operator>(const CheckedContiguousIterator& other) const { const CheckedContiguousIterator& rhs) {
CheckComparable(other); lhs.CheckComparable(rhs);
return current_ > other.current_; return lhs.current_ > rhs.current_;
} }
constexpr bool operator>=(const CheckedContiguousIterator& other) const { friend constexpr bool operator>=(const CheckedContiguousIterator& lhs,
CheckComparable(other); const CheckedContiguousIterator& rhs) {
return current_ >= other.current_; lhs.CheckComparable(rhs);
return lhs.current_ >= rhs.current_;
} }
constexpr CheckedContiguousIterator& operator++() { constexpr CheckedContiguousIterator& operator++() {
...@@ -149,8 +154,7 @@ class CheckedContiguousIterator { ...@@ -149,8 +154,7 @@ class CheckedContiguousIterator {
constexpr friend difference_type operator-( constexpr friend difference_type operator-(
const CheckedContiguousIterator& lhs, const CheckedContiguousIterator& lhs,
const CheckedContiguousIterator& rhs) { const CheckedContiguousIterator& rhs) {
CHECK_EQ(lhs.start_, rhs.start_); lhs.CheckComparable(rhs);
CHECK_EQ(lhs.end_, rhs.end_);
return lhs.current_ - rhs.current_; return lhs.current_ - rhs.current_;
} }
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/containers/checked_iterators.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
// Checks that constexpr CheckedContiguousConstIterators can be compared at
// compile time.
TEST(CheckedContiguousIterator, StaticComparisonOperators) {
static constexpr int arr[] = {0};
constexpr CheckedContiguousConstIterator<int> begin(arr, arr, arr + 1);
constexpr CheckedContiguousConstIterator<int> end(arr, arr + 1, arr + 1);
static_assert(begin == begin, "");
static_assert(end == end, "");
static_assert(begin != end, "");
static_assert(end != begin, "");
static_assert(begin < end, "");
static_assert(begin <= begin, "");
static_assert(begin <= end, "");
static_assert(end <= end, "");
static_assert(end > begin, "");
static_assert(end >= end, "");
static_assert(end >= begin, "");
static_assert(begin >= begin, "");
}
// Checks that comparison between iterators and const iterators works in both
// directions.
TEST(CheckedContiguousIterator, ConvertingComparisonOperators) {
static int arr[] = {0};
CheckedContiguousIterator<int> begin(arr, arr, arr + 1);
CheckedContiguousConstIterator<int> cbegin(arr, arr, arr + 1);
CheckedContiguousIterator<int> end(arr, arr + 1, arr + 1);
CheckedContiguousConstIterator<int> cend(arr, arr + 1, arr + 1);
EXPECT_EQ(begin, cbegin);
EXPECT_EQ(cbegin, begin);
EXPECT_EQ(end, cend);
EXPECT_EQ(cend, end);
EXPECT_NE(begin, cend);
EXPECT_NE(cbegin, end);
EXPECT_NE(end, cbegin);
EXPECT_NE(cend, begin);
EXPECT_LT(begin, cend);
EXPECT_LT(cbegin, end);
EXPECT_LE(begin, cbegin);
EXPECT_LE(cbegin, begin);
EXPECT_LE(begin, cend);
EXPECT_LE(cbegin, end);
EXPECT_LE(end, cend);
EXPECT_LE(cend, end);
EXPECT_GT(end, cbegin);
EXPECT_GT(cend, begin);
EXPECT_GE(end, cend);
EXPECT_GE(cend, end);
EXPECT_GE(end, cbegin);
EXPECT_GE(cend, begin);
EXPECT_GE(begin, cbegin);
EXPECT_GE(cbegin, begin);
}
} // namespace base
...@@ -414,7 +414,7 @@ CheckedContiguousIterator<Value> Value::Insert( ...@@ -414,7 +414,7 @@ CheckedContiguousIterator<Value> Value::Insert(
bool Value::EraseListIter(CheckedContiguousConstIterator<Value> iter) { bool Value::EraseListIter(CheckedContiguousConstIterator<Value> iter) {
CHECK(is_list()); CHECK(is_list());
const auto offset = iter - make_span(list_).begin(); const auto offset = iter - ListView(list_).begin();
auto list_iter = list_.begin() + offset; auto list_iter = list_.begin() + offset;
if (list_iter == list_.end()) if (list_iter == list_.end())
return false; return false;
...@@ -1752,7 +1752,10 @@ ListValue::iterator ListValue::Erase(iterator iter, ...@@ -1752,7 +1752,10 @@ ListValue::iterator ListValue::Erase(iterator iter,
if (out_value) if (out_value)
*out_value = std::make_unique<Value>(std::move(*iter)); *out_value = std::make_unique<Value>(std::move(*iter));
return list_.erase(iter); auto list_iter = list_.begin() + (iter - GetList().begin());
CHECK(list_iter != list_.end());
list_iter = list_.erase(list_iter);
return GetList().begin() + (list_iter - list_.begin());
} }
void ListValue::Append(std::unique_ptr<Value> in_value) { void ListValue::Append(std::unique_ptr<Value> in_value) {
...@@ -1810,7 +1813,7 @@ bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { ...@@ -1810,7 +1813,7 @@ bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
} }
ListValue::const_iterator ListValue::Find(const Value& value) const { ListValue::const_iterator ListValue::Find(const Value& value) const {
return std::find(list_.begin(), list_.end(), value); return std::find(GetList().begin(), GetList().end(), value);
} }
void ListValue::Swap(ListValue* other) { void ListValue::Swap(ListValue* other) {
......
...@@ -784,8 +784,8 @@ class BASE_EXPORT DictionaryValue : public Value { ...@@ -784,8 +784,8 @@ class BASE_EXPORT DictionaryValue : public Value {
// This type of Value represents a list of other Value values. // This type of Value represents a list of other Value values.
class BASE_EXPORT ListValue : public Value { class BASE_EXPORT ListValue : public Value {
public: public:
using const_iterator = ListStorage::const_iterator; using const_iterator = ListView::const_iterator;
using iterator = ListStorage::iterator; using iterator = ListView::iterator;
// Returns |value| if it is a list, nullptr otherwise. // Returns |value| if it is a list, nullptr otherwise.
static std::unique_ptr<ListValue> From(std::unique_ptr<Value> value); static std::unique_ptr<ListValue> From(std::unique_ptr<Value> value);
...@@ -910,14 +910,14 @@ class BASE_EXPORT ListValue : public Value { ...@@ -910,14 +910,14 @@ class BASE_EXPORT ListValue : public Value {
// Iteration. // Iteration.
// DEPRECATED, use GetList()::begin() instead. // DEPRECATED, use GetList()::begin() instead.
iterator begin() { return list_.begin(); } iterator begin() { return GetList().begin(); }
// DEPRECATED, use GetList()::end() instead. // DEPRECATED, use GetList()::end() instead.
iterator end() { return list_.end(); } iterator end() { return GetList().end(); }
// DEPRECATED, use GetList()::begin() instead. // DEPRECATED, use GetList()::begin() instead.
const_iterator begin() const { return list_.begin(); } const_iterator begin() const { return GetList().begin(); }
// DEPRECATED, use GetList()::end() instead. // DEPRECATED, use GetList()::end() instead.
const_iterator end() const { return list_.end(); } const_iterator end() const { return GetList().end(); }
// DEPRECATED, use Value::Clone() instead. // DEPRECATED, use Value::Clone() instead.
// TODO(crbug.com/646113): Delete this and migrate callsites. // TODO(crbug.com/646113): Delete this and migrate callsites.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment