Update googleurl to the latest version from Chromium
The version used is cc5912fc759fc64d7b8553cd9bb912f2a26c0cc7 from
Mon Oct 3 10:33:09 2022 +0000
Change-Id: I29d5289b4d383141f182640436c02f8c89f878fe
diff --git a/.bazelversion b/.bazelversion
index 831446c..03f488b 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-5.1.0
+5.3.0
diff --git a/AUTHORS b/AUTHORS
index abd2e53..59ecce0 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -71,6 +71,7 @@
Alexey Kuts <kruntuid@gmail.com>
Alexey Kuzmin <alex.s.kuzmin@gmail.com>
Alexey Kuznetsov <saturas2000@gmail.com>
+Alexey Terentiev <alexeyter@gmail.com>
Alexis Brenon <brenon.alexis@gmail.com>
Alexis La Goutte <alexis.lagoutte@gmail.com>
Alexis Menard <alexis.menard@intel.com>
@@ -167,6 +168,7 @@
Bhagirathi Satpathy <bhagirathi.s@samsung.com>
Bhanukrushana Rout <b.rout@samsung.com>
Biljith Jayan <billy.jayan@samsung.com>
+Bin Liao <bin.liao@intel.com>
Boaz Sender <boaz@bocoup.com>
Bobby Powers <bobbypowers@gmail.com>
Branden Archer <bma4@zips.uakron.edu>
@@ -223,6 +225,7 @@
Charles Vaughn <cvaughn@gmail.com>
Cheng Zhao <zcbenz@gmail.com>
Cheng Yu <yuzichengcode@gmail.com>
+Cheung Ho <uioptt24@gmail.com>
Choongwoo Han <cwhan.tunz@gmail.com>
Chris Greene <cwgreene@amazon.com>
Chris Harrelson <chrishtr@gmail.com>
@@ -338,6 +341,7 @@
Ehsan Akhgari <ehsan.akhgari@gmail.com>
Ehsan Akhgari <ehsan@mightyapp.com>
Elan Ruusamäe <elan.ruusamae@gmail.com>
+Emil Suleymanov <emil@esnx.xyz>
Ergun Erdogmus <erdogmusergun@gmail.com>
Eric Ahn <byungwook.ahn@gmail.com>
Eric Huang <ele828@gmail.com>
@@ -363,6 +367,7 @@
Felipe Erias Morandeira <felipeerias@gmail.com>
Felix H. Dahlke <fhd@ubercode.de>
Felix Weilbach <feweilbach@gmail.com>
+Feng Yu <f3n67u@gmail.com>
Fengrong Fang <fr.fang@samsung.com>
Fernando Jiménez Moreno <ferjmoreno@gmail.com>
Finbar Crago <finbar.crago@gmail.com>
@@ -385,6 +390,7 @@
Ganesh Borle <ganesh.borle@samsung.com>
Gao Chun <chun.gao@intel.com>
Gao Chun <gaochun.dev@gmail.com>
+Gao Sheng <gaosheng08@meituan.com>
Gao Yu <wanggao@tencent.com>
Gaurav Dhol <gaurav.dhol@einfochips.com>
Gautham Banasandra <gautham.bangalore@gmail.com>
@@ -421,6 +427,7 @@
Hans Hillen <hans.hillen@gmail.com>
Hao Li <hao.x.li@intel.com>
Haojian Wu <hokein.wu@gmail.com>
+Haoxuan Zhang <zhanghaoxuan.59@bytedance.com>
Hari Singh <hari.singh1@samsung.com>
Harpreet Singh Khurana <harpreet.sk@samsung.com>
Harshikesh Kumar <harshikeshnobug@gmail.com>
@@ -431,6 +438,7 @@
Henrique de Carvalho <decarv.henrique@gmail.com>
Henrique Limas <henrique.ramos.limas@gmail.com>
Himanshu Joshi <h.joshi@samsung.com>
+Hiroki Oshima <hiroki.oshima@gmail.com>
Hiroyuki Matsuda <gsittyz@gmail.com>
Hodol Han <bab6ting@gmail.com>
Holger Kraus <kraush@amazon.com>
@@ -497,6 +505,7 @@
Jakub Machacek <xtreit@gmail.com>
James Burton <jb@0.me.uk>
James Choi <jchoi42@pha.jhu.edu>
+James Raphael Tiovalen <jamestiotio@gmail.com>
James Stanley <james@apphaus.co.uk>
James Vega <vega.james@gmail.com>
James Wei <james.wei@intel.com>
@@ -646,6 +655,7 @@
Kaustubh Atrawalkar <kaustubh.ra@gmail.com>
Ke He <ke.he@intel.com>
Keeley Hammond <vertedinde@electronjs.org>
+Keeling <liqining.keeling@bytedance.com>
Keene Pan <keenepan@linpus.com>
Keiichiro Nagashima <n4ag3a2sh1i@gmail.com>
Keita Suzuki <keitasuzuki.park@gmail.com>
@@ -715,6 +725,7 @@
Lingqi Chi <someway.bit@gmail.com>
Lingyun Cai <lingyun.cai@intel.com>
Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Lisha Guo <lisha.guo@intel.com>
Lizhi Fan <lizhi.fan@samsung.com>
Loo Rong Jie <loorongjie@gmail.com>
Lorenzo Stoakes <lstoakes@gmail.com>
@@ -796,6 +807,7 @@
Md Abdullah Al Alamin <a.alamin.cse@gmail.com>
Md. Hasanur Rashid <hasanur.r@samsung.com>
Md Jobed Hossain <jobed.h@samsung.com>
+Md Raiyan bin Sayeed <mrbsayee@uwaterloo.ca>
Md Sami Uddin <md.sami@samsung.com>
Micha Hanselmann <micha.hanselmann@gmail.com>
Michael Cirone <mikecirone@gmail.com>
@@ -927,6 +939,7 @@
Peter Snyder <snyderp@gmail.com>
Peter Varga <pvarga@inf.u-szeged.hu>
Peter Wong <peter.wm.wong@gmail.com>
+Phan Quang Minh <phanquangminh217@gmail.com>
Philip Hanson <philip.hanson@intel.com>
Philipp Hancke <fippo@andyet.net>
Philipp Hancke <philipp.hancke@googlemail.com>
@@ -1059,10 +1072,12 @@
Sean DuBois <seaduboi@amazon.com>
Sebastian Amend <sebastian.amend@googlemail.com>
Sebastian Krzyszkowiak <dos@dosowisko.net>
+Sebastjan Raspor <sebastjan.raspor1@gmail.com>
Seo Sanghyeon <sanxiyn@gmail.com>
Seokju Kwon <seokju.kwon@gmail.com>
Seokho Song <0xdevssh@gmail.com>
SeongTae Jeong <ferendevelop.gl@gmail.com>
+Sergei Romanov <rsv.981@gmail.com>
Sergey Kipet <sergey.kipet@gmail.com>
Sergey Putilin <p.sergey@samsung.com>
Sergey Shekyan <shekyan@gmail.com>
@@ -1307,11 +1322,13 @@
Yong Ling <yongling@tencent.com>
Yong Shin <sy3620@gmail.com>
Yong Wang <ccyongwang@tencent.com>
+Yonggang Luo <luoyonggang@gmail.com>
Yongha Lee <yongha78.lee@samsung.com>
Yongseok Choi <yongseok.choi@navercorp.com>
Yongsheng Zhu <yongsheng.zhu@intel.com>
Yoonjae Cho <yoonjae.cho92@gmail.com>
Yoshinori Sano <yoshinori.sano@gmail.com>
+Young Min Kim <y@ylem.kim>
Youngho Seo <hazivoo@gmail.com>
Youngjin Choi <cyjin9.yc@gmail.com>
YoungKi Hong <simon.hong81@gmail.com>
@@ -1324,6 +1341,7 @@
Yuki Tsuchiya <Yuki.Tsuchiya@sony.com>
Yuma Takai <tara20070827@gmail.com>
Yumikiyo Osanai <yumios.art@gmail.com>
+Yumin Su <yuminsu.hi@gmail.com>
Yunchao He <yunchao.he@intel.com>
Yupei Lin <yplam@yplam.com>
Yupei Wang <perryuwang@tencent.com>
@@ -1337,6 +1355,7 @@
Zachary Capalbo <zach.geek@gmail.com>
Zeno Albisser <zeno.albisser@digia.com>
Zeqin Chen <talonchen@tencent.com>
+Zhang Hao <zhanghao.m@bytedance.com>
Zhang Hao <15686357310a@gmail.com>
Zhaoze Zhou <zhaoze.zhou@partner.samsung.com>
Zheda Chen <zheda.chen@intel.com>
@@ -1348,6 +1367,7 @@
Zhibo Wang <zhibo1.wang@intel.com>
Zhifei Fang <facetothefate@gmail.com>
Zhiyuan Ye <zhiyuanye@tencent.com>
+Zhou Jun <zhoujun@uniontech.com>
Zhuoyu Qian <zhuoyu.qian@samsung.com>
Ziran Sun <ziran.sun@samsung.com>
Zoltan Czirkos <czirkos.zoltan@gmail.com>
@@ -1429,12 +1449,14 @@
The Chromium Authors <*@chromium.org>
The MathWorks, Inc. <binod.pant@mathworks.com>
THEO Technologies <*@theoplayer.com>
+Tien Hock Loh <tienhock.loh@starfivetech.com>
Torchmobile Inc.
Upwork <*@cloud.upwork.com>
Venture 3 Systems LLC <*@venture3systems.com>
Vewd Software AS <*@vewd.com>
Vivaldi Technologies AS <*@vivaldi.com>
Wacom <*@wacom.com>
+Whist Technologies <*@whist.com>
Xperi Corporation <*@xperi.com>
Yandex LLC <*@yandex-team.ru>
Zuckjet <zuckjet@gmail.com>
diff --git a/LICENSE b/LICENSE
index a32e00c..2249a28 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
-// * Neither the name of Google Inc. nor the names of its
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
diff --git a/base/BUILD b/base/BUILD
index 69dffea..60ca578 100644
--- a/base/BUILD
+++ b/base/BUILD
@@ -25,6 +25,7 @@
"containers/span.h",
"containers/util.h",
"cxx17_backports.h",
+ "cxx20_is_constant_evaluated.h",
"cxx20_to_address.h",
"debug/crash_logging.h",
"debug/leak_annotations.h",
@@ -34,8 +35,14 @@
"memory/raw_ptr.h",
"memory/raw_ptr_exclusion.h",
"no_destructor.h",
+ "numerics/checked_math.h",
+ "numerics/checked_math_impl.h",
+ "numerics/clamped_math.h",
+ "numerics/clamped_math_impl.h",
"numerics/safe_conversions.h",
"numerics/safe_conversions_impl.h",
+ "numerics/safe_math_clang_gcc_impl.h",
+ "numerics/safe_math_shared_impl.h",
"ranges/algorithm.h",
"ranges/functional.h",
"ranges/ranges.h",
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 5719020..0174b6d 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -406,4 +406,17 @@
#define GSL_POINTER
#endif
+// Adds the "logically_const" tag to a symbol's mangled name. The "Mutable
+// Constants" check [1] detects instances of constants that aren't in .rodata,
+// e.g. due to a missing `const`. Using this tag suppresses the check for this
+// symbol, allowing it to live outside .rodata without a warning.
+//
+// [1]:
+// https://crsrc.org/c/docs/speed/binary_size/android_binary_size_trybot.md#Mutable-Constants
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define LOGICALLY_CONST [[gnu::abi_tag("logically_const")]]
+#else
+#define LOGICALLY_CONST
+#endif
+
#endif // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h
index c4e1e69..dc8d2ba 100644
--- a/base/containers/checked_iterators.h
+++ b/base/containers/checked_iterators.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/containers/contains.h b/base/containers/contains.h
index 559ff2c..430f79e 100644
--- a/base/containers/contains.h
+++ b/base/containers/contains.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/containers/contiguous_iterator.h b/base/containers/contiguous_iterator.h
index 6229efb..7f06432 100644
--- a/base/containers/contiguous_iterator.h
+++ b/base/containers/contiguous_iterator.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/containers/span.h b/base/containers/span.h
index 5bb30d1..40e325f 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
@@ -286,7 +286,10 @@
typename End,
typename = internal::EnableIfCompatibleContiguousIterator<It, T>,
typename = std::enable_if_t<!std::is_convertible<End, size_t>::value>>
- constexpr span(It begin, End end) noexcept : span(begin, end - begin) {
+ constexpr span(It begin, End end) noexcept
+ // Subtracting two iterators gives a ptrdiff_t, but the result should be
+ // non-negative: see GURL_CHECK below.
+ : span(begin, static_cast<size_t>(end - begin)) {
// Note: GURL_CHECK_LE is not constexpr, hence regular GURL_CHECK must be used.
GURL_CHECK(begin <= end);
}
diff --git a/base/containers/util.h b/base/containers/util.h
index 7a65b6a..928263c 100644
--- a/base/containers/util.h
+++ b/base/containers/util.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/cxx17_backports.h b/base/cxx17_backports.h
index 86976d4..ce59af0 100644
--- a/base/cxx17_backports.h
+++ b/base/cxx17_backports.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,12 +6,8 @@
#define BASE_CXX17_BACKPORTS_H_
#include <functional>
-#include <tuple>
-#include <type_traits>
-#include <utility>
#include "polyfills/base/check.h"
-#include "base/functional/invoke.h"
namespace gurl_base {
@@ -31,26 +27,6 @@
return gurl_base::clamp(v, lo, hi, std::less<T>{});
}
-// C++14 implementation of C++17's std::apply():
-// https://en.cppreference.com/w/cpp/utility/apply
-namespace internal {
-template <class F, class Tuple, std::size_t... I>
-constexpr decltype(auto) apply_impl(F&& f,
- Tuple&& t,
- std::index_sequence<I...>) {
- return gurl_base::invoke(std::forward<F>(f),
- std::get<I>(std::forward<Tuple>(t))...);
-}
-} // namespace internal
-
-template <class F, class Tuple>
-constexpr decltype(auto) apply(F&& f, Tuple&& t) {
- return internal::apply_impl(
- std::forward<F>(f), std::forward<Tuple>(t),
- std::make_index_sequence<
- std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
-}
-
} // namespace base
#endif // BASE_CXX17_BACKPORTS_H_
diff --git a/base/cxx20_is_constant_evaluated.h b/base/cxx20_is_constant_evaluated.h
new file mode 100644
index 0000000..41fb247
--- /dev/null
+++ b/base/cxx20_is_constant_evaluated.h
@@ -0,0 +1,21 @@
+// Copyright 2022 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_CXX20_IS_CONSTANT_EVALUATED_H_
+#define BASE_CXX20_IS_CONSTANT_EVALUATED_H_
+
+namespace gurl_base {
+
+// Implementation of C++20's std::is_constant_evaluated.
+//
+// References:
+// - https://en.cppreference.com/w/cpp/types/is_constant_evaluated
+// - https://wg21.link/meta.const.eval
+constexpr bool is_constant_evaluated() noexcept {
+ return __builtin_is_constant_evaluated();
+}
+
+} // namespace base
+
+#endif // BASE_CXX20_IS_CONSTANT_EVALUATED_H_
diff --git a/base/cxx20_to_address.h b/base/cxx20_to_address.h
index 56a87b7..ef67a9b 100644
--- a/base/cxx20_to_address.h
+++ b/base/cxx20_to_address.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,9 +9,10 @@
namespace gurl_base {
-// Simplified C++14 implementation of C++20's std::to_address.
-// Note: This does not consider specializations of pointer_traits<>::to_address,
-// since that member function may only be present in C++20 and later.
+// Implementation of C++20's std::to_address.
+// Note: This does consider specializations of pointer_traits<>::to_address,
+// even though it's a C++20 member function, because CheckedContiguousIterator
+// specializes pointer_traits<> with a to_address() member.
//
// Reference: https://wg21.link/pointer.conversion#lib:to_address
template <typename T>
@@ -22,8 +23,14 @@
}
template <typename Ptr>
-constexpr auto to_address(const Ptr& p) noexcept {
- return to_address(p.operator->());
+constexpr auto to_address(const Ptr& p) noexcept
+ -> decltype(std::pointer_traits<Ptr>::to_address(p)) {
+ return std::pointer_traits<Ptr>::to_address(p);
+}
+
+template <typename Ptr, typename... None>
+constexpr auto to_address(const Ptr& p, None...) noexcept {
+ return gurl_base::to_address(p.operator->());
}
} // namespace base
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc
index 124a31f..157a79f 100644
--- a/base/debug/crash_logging.cc
+++ b/base/debug/crash_logging.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h
index 417d227..b4cf7bc 100644
--- a/base/debug/crash_logging.h
+++ b/base/debug/crash_logging.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/debug/leak_annotations.h b/base/debug/leak_annotations.h
index 89f47f4..506e1e0 100644
--- a/base/debug/leak_annotations.h
+++ b/base/debug/leak_annotations.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/functional/identity.h b/base/functional/identity.h
index 26af8e0..a0b66a6 100644
--- a/base/functional/identity.h
+++ b/base/functional/identity.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/functional/invoke.h b/base/functional/invoke.h
index 4399c6b..96dd088 100644
--- a/base/functional/invoke.h
+++ b/base/functional/invoke.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/functional/not_fn.h b/base/functional/not_fn.h
index 7457d03..4bf248f 100644
--- a/base/functional/not_fn.h
+++ b/base/functional/not_fn.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index c10a65d..d65ab44 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -24,7 +24,7 @@
#include "build/buildflag.h"
#if BUILDFLAG(USE_BACKUP_REF_PTR) || \
- defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+ defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under
// allocator/partition_allocator/ to be built.
#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
@@ -32,13 +32,14 @@
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "polyfills/base/base_export.h"
#endif // BUILDFLAG(USE_BACKUP_REF_PTR) ||
- // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+ // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
#include "base/allocator/partition_allocator/partition_tag.h"
+#include "base/allocator/partition_allocator/partition_tag_types.h"
#include "base/allocator/partition_allocator/tagging.h"
#include "polyfills/base/check_op.h"
-#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
#if BUILDFLAG(IS_WIN)
#include "base/win/win_handle_types.h"
@@ -59,6 +60,25 @@
// NOTE: All methods should be `ALWAYS_INLINE`. raw_ptr is meant to be a
// lightweight replacement of a raw pointer, hence performance is critical.
+// The following types are the different RawPtrType template option possible for
+// a `raw_ptr`:
+// - RawPtrMayDangle disables dangling pointers check when the object is
+// released.
+// - RawPtrBanDanglingIfSupported may enable dangling pointers check on object
+// destruction.
+//
+// We describe those types here so that they can be used outside of `raw_ptr` as
+// object markers, and their meaning might vary depending on where those markers
+// are being used. For instance, we are using those in `UnretainedWrapper` to
+// change behavior depending on RawPtrType.
+struct RawPtrMayDangle {};
+struct RawPtrBanDanglingIfSupported {};
+
+namespace raw_ptr_traits {
+template <typename T>
+struct RawPtrTypeToImpl;
+}
+
namespace internal {
// These classes/structures are part of the raw_ptr implementation.
// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
@@ -121,6 +141,12 @@
return wrapped_ptr + delta_elems;
}
+ template <typename T>
+ static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+ T* wrapped_ptr2) {
+ return wrapped_ptr1 - wrapped_ptr2;
+ }
+
// Returns a copy of a wrapped pointer, without making an assertion on whether
// memory was freed or not.
template <typename T>
@@ -134,7 +160,7 @@
static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
};
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
constexpr int kValidAddressBits = 48;
constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1;
@@ -160,12 +186,7 @@
// Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
// is responsible for handling the software MTE tag.
auto addr = partition_alloc::UntagPtr(ptr);
- // MTECheckedPtr algorithms work only when memory is
- // allocated by PartitionAlloc, from normal buckets pool.
- //
- // TODO(crbug.com/1307514): Allow direct-map buckets.
- return partition_alloc::IsManagedByPartitionAlloc(addr) &&
- partition_alloc::internal::IsManagedByNormalBuckets(addr);
+ return partition_alloc::IsManagedByPartitionAlloc(addr);
}
// Returns pointer to the tag that protects are pointed by |addr|.
@@ -202,6 +223,7 @@
static_assert(sizeof(partition_alloc::PartitionTag) * 8 <= kTagBits, "");
uintptr_t tag = *(static_cast<volatile partition_alloc::PartitionTag*>(
PartitionAllocSupport::TagPointer(addr)));
+ GURL_DCHECK(tag);
tag <<= kValidAddressBits;
addr |= tag;
@@ -277,6 +299,34 @@
return wrapped_ptr + delta_elems;
}
+ template <typename T>
+ static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+ T* wrapped_ptr2) {
+ // Ensure that both pointers come from the same allocation.
+ //
+ // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+ // class is responsible for handling the software MTE tag.
+ //
+ // MTECheckedPtr doesn't use 0 as a valid tag; depending on which
+ // subtraction operator is called, we may be getting the actual
+ // untagged T* or the wrapped pointer (passed as a T*) in one or
+ // both args. We can only check slot cohabitation when both args
+ // come with tags.
+ const uintptr_t tag1 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr1));
+ const uintptr_t tag2 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr2));
+ if (tag1 && tag2) {
+ GURL_CHECK(tag1 == tag2);
+ return wrapped_ptr1 - wrapped_ptr2;
+ }
+
+ // If one or the other arg come untagged, we have to perform the
+ // subtraction entirely without tags.
+ return reinterpret_cast<T*>(
+ ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr1))) -
+ reinterpret_cast<T*>(
+ ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr2)));
+ }
+
// Returns a copy of a wrapped pointer, without making an assertion
// on whether memory was freed or not.
template <typename T>
@@ -309,7 +359,7 @@
}
};
-#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
#if BUILDFLAG(USE_BACKUP_REF_PTR)
@@ -465,6 +515,7 @@
// rewrapped the pointer (wrapped the new pointer and unwrapped the old
// one).
uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
+ // TODO(bartekn): Consider adding support for non-BRP pool too.
if (IsSupportedAndNotNull(address))
GURL_CHECK(IsValidDelta(address, delta_elems * static_cast<Z>(sizeof(T))));
return wrapped_ptr + delta_elems;
@@ -497,6 +548,22 @@
#endif
}
+ template <typename T>
+ static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+ T* wrapped_ptr2) {
+ uintptr_t address1 = partition_alloc::UntagPtr(wrapped_ptr1);
+ uintptr_t address2 = partition_alloc::UntagPtr(wrapped_ptr2);
+ // Ensure that both pointers are within the same slot, and pool!
+ // TODO(bartekn): Consider adding support for non-BRP pool too.
+ if (IsSupportedAndNotNull(address1)) {
+ GURL_CHECK(IsSupportedAndNotNull(address2));
+ GURL_CHECK(IsValidDelta(address2, address1 - address2));
+ } else {
+ GURL_CHECK(!IsSupportedAndNotNull(address2));
+ }
+ return wrapped_ptr1 - wrapped_ptr2;
+ }
+
// Returns a copy of a wrapped pointer, without making an assertion on whether
// memory was freed or not.
// This method increments the reference count of the allocation slot.
@@ -505,6 +572,12 @@
return WrapRawPtr(wrapped_ptr);
}
+ // Report the current wrapped pointer if pointee isn't alive anymore.
+ template <typename T>
+ static ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) {
+ ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr));
+ }
+
// This is for accounting only, used by unit tests.
static ALWAYS_INLINE void IncrementSwapCountForTest() {}
static ALWAYS_INLINE void IncrementLessCountForTest() {}
@@ -520,6 +593,7 @@
static BASE_EXPORT NOINLINE void AcquireInternal(uintptr_t address);
static BASE_EXPORT NOINLINE void ReleaseInternal(uintptr_t address);
static BASE_EXPORT NOINLINE bool IsPointeeAlive(uintptr_t address);
+ static BASE_EXPORT NOINLINE void ReportIfDanglingInternal(uintptr_t address);
template <typename Z, typename = std::enable_if_t<offset_type<Z>, void>>
static ALWAYS_INLINE bool IsValidDelta(uintptr_t address, Z delta_in_bytes) {
if constexpr (std::is_signed_v<Z>)
@@ -589,6 +663,12 @@
return wrapped_ptr + delta_elems;
}
+ template <typename T>
+ static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+ T* wrapped_ptr2) {
+ return wrapped_ptr1 - wrapped_ptr2;
+ }
+
// Returns a copy of a wrapped pointer, without making an assertion on whether
// memory was freed or not.
template <typename T>
@@ -611,35 +691,37 @@
};
template <class Super>
-struct RawPtrCountingImplWrapperForTest : public Super {
+struct RawPtrCountingImplWrapperForTest
+ : public raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl {
+ using SuperImpl = typename raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl;
template <typename T>
static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
++wrap_raw_ptr_cnt;
- return Super::WrapRawPtr(ptr);
+ return SuperImpl::WrapRawPtr(ptr);
}
template <typename T>
static ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
++release_wrapped_ptr_cnt;
- Super::ReleaseWrappedPtr(ptr);
+ SuperImpl::ReleaseWrappedPtr(ptr);
}
template <typename T>
static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
++get_for_dereference_cnt;
- return Super::SafelyUnwrapPtrForDereference(wrapped_ptr);
+ return SuperImpl::SafelyUnwrapPtrForDereference(wrapped_ptr);
}
template <typename T>
static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
++get_for_extraction_cnt;
- return Super::SafelyUnwrapPtrForExtraction(wrapped_ptr);
+ return SuperImpl::SafelyUnwrapPtrForExtraction(wrapped_ptr);
}
template <typename T>
static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
++get_for_comparison_cnt;
- return Super::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
+ return SuperImpl::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
}
static ALWAYS_INLINE void IncrementSwapCountForTest() {
@@ -762,6 +844,42 @@
#undef CHROME_WINDOWS_HANDLE_TYPE
#endif
+template <typename T>
+struct RawPtrTypeToImpl {};
+
+template <typename T>
+struct RawPtrTypeToImpl<internal::RawPtrCountingImplWrapperForTest<T>> {
+ using Impl = internal::RawPtrCountingImplWrapperForTest<T>;
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrMayDangle> {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+ using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+ using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+ using Impl = internal::MTECheckedPtrImpl<
+ internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+ using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrBanDanglingIfSupported> {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+ using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/false>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+ using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+ using Impl = internal::MTECheckedPtrImpl<
+ internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+ using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
} // namespace raw_ptr_traits
// `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
@@ -790,27 +908,12 @@
// non-default move constructor/assignment. Thus, it's possible to get an error
// where the pointer is not actually dangling, and have to work around the
// compiler. We have not managed to construct such an example in Chromium yet.
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-using RawPtrMayDangle = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
-using RawPtrBanDanglingIfSupported =
- internal::BackupRefPtrImpl</*AllowDangling=*/false>;
-#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-using RawPtrMayDangle = internal::AsanBackupRefPtrImpl;
-using RawPtrBanDanglingIfSupported = internal::AsanBackupRefPtrImpl;
-#elif defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-using RawPtrMayDangle = internal::MTECheckedPtrImpl<
- internal::MTECheckedPtrImplPartitionAllocSupport>;
-using RawPtrBanDanglingIfSupported = internal::MTECheckedPtrImpl<
- internal::MTECheckedPtrImplPartitionAllocSupport>;
-#else
-using RawPtrMayDangle = internal::RawPtrNoOpImpl;
-using RawPtrBanDanglingIfSupported = internal::RawPtrNoOpImpl;
-#endif
-using DefaultRawPtrImpl = RawPtrBanDanglingIfSupported;
+using DefaultRawPtrType = RawPtrBanDanglingIfSupported;
-template <typename T, typename Impl = DefaultRawPtrImpl>
+template <typename T, typename RawPtrType = DefaultRawPtrType>
class TRIVIAL_ABI GSL_POINTER raw_ptr {
+ using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
using DanglingRawPtr = std::conditional_t<
raw_ptr_traits::IsRawPtrCountingImpl<Impl>::value,
raw_ptr<T, internal::RawPtrCountingImplWrapperForTest<RawPtrMayDangle>>,
@@ -901,7 +1004,7 @@
std::is_convertible<U*, T*>::value &&
!std::is_void<typename std::remove_cv<T>::type>::value>>
// NOLINTNEXTLINE(google-explicit-constructor)
- ALWAYS_INLINE raw_ptr(const raw_ptr<U, Impl>& ptr) noexcept
+ ALWAYS_INLINE raw_ptr(const raw_ptr<U, RawPtrType>& ptr) noexcept
: wrapped_ptr_(
Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {}
// Deliberately implicit in order to support implicit upcast.
@@ -910,7 +1013,7 @@
std::is_convertible<U*, T*>::value &&
!std::is_void<typename std::remove_cv<T>::type>::value>>
// NOLINTNEXTLINE(google-explicit-constructor)
- ALWAYS_INLINE raw_ptr(raw_ptr<U, Impl>&& ptr) noexcept
+ ALWAYS_INLINE raw_ptr(raw_ptr<U, RawPtrType>&& ptr) noexcept
: wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
#if BUILDFLAG(USE_BACKUP_REF_PTR)
ptr.wrapped_ptr_ = nullptr;
@@ -933,7 +1036,7 @@
typename Unused = std::enable_if_t<
std::is_convertible<U*, T*>::value &&
!std::is_void<typename std::remove_cv<T>::type>::value>>
- ALWAYS_INLINE raw_ptr& operator=(const raw_ptr<U, Impl>& ptr) noexcept {
+ ALWAYS_INLINE raw_ptr& operator=(const raw_ptr<U, RawPtrType>& ptr) noexcept {
// Make sure that pointer isn't assigned to itself (look at pointer address,
// not its value).
#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
@@ -949,7 +1052,7 @@
typename Unused = std::enable_if_t<
std::is_convertible<U*, T*>::value &&
!std::is_void<typename std::remove_cv<T>::type>::value>>
- ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, Impl>&& ptr) noexcept {
+ ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, RawPtrType>&& ptr) noexcept {
// Make sure that pointer isn't assigned to itself (look at pointer address,
// not its value).
#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
@@ -1012,18 +1115,37 @@
--(*this);
return result;
}
- template <typename Z,
- typename = std::enable_if_t<internal::offset_type<Z>, void>>
+ template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
ALWAYS_INLINE raw_ptr& operator+=(Z delta_elems) {
wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems);
return *this;
}
- template <typename Z,
- typename = std::enable_if_t<internal::offset_type<Z>, void>>
+ template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
ALWAYS_INLINE raw_ptr& operator-=(Z delta_elems) {
return *this += -delta_elems;
}
+ template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+ friend ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
+ raw_ptr result = p;
+ return result += delta_elems;
+ }
+ template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+ friend ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
+ raw_ptr result = p;
+ return result -= delta_elems;
+ }
+ friend ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
+ const raw_ptr& p2) {
+ return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
+ }
+ friend ALWAYS_INLINE ptrdiff_t operator-(T* p1, const raw_ptr& p2) {
+ return Impl::GetDeltaElems(p1, p2.wrapped_ptr_);
+ }
+ friend ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1, T* p2) {
+ return Impl::GetDeltaElems(p1.wrapped_ptr_, p2);
+ }
+
// Stop referencing the underlying pointer and free its memory. Compared to
// raw delete calls, this avoids the raw_ptr to be temporarily dangling
// during the free operation, which will lead to taking the slower path that
@@ -1047,6 +1169,10 @@
// NOTE, avoid using this method as it indicates an error-prone memory
// ownership pattern. If possible, use smart pointers like std::unique_ptr<>
// instead of raw_ptr<>.
+ // If you have to use it, avoid saving the return value in a long-lived
+ // variable (or worse, a field)! It's meant to be used as a temporary, to be
+ // passed into a cleanup & freeing function, and destructed at the end of the
+ // statement.
ALWAYS_INLINE DanglingRawPtr ExtractAsDangling() noexcept {
if constexpr (std::is_same_v<
typename std::remove_reference<decltype(*this)>::type,
@@ -1176,6 +1302,12 @@
perfetto::WriteIntoTracedValue(std::move(context), get());
}
+ ALWAYS_INLINE void ReportIfDangling() const noexcept {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+ Impl::ReportIfDangling(wrapped_ptr_);
+#endif
+ }
+
private:
// This getter is meant for situations where the pointer is meant to be
// dereferenced. It is allowed to crash on nullptr (it may or may not),
@@ -1238,6 +1370,15 @@
return lhs.GetForComparison() >= rhs.GetForComparison();
}
+template <typename T>
+struct IsRawPtr : std::false_type {};
+
+template <typename T, typename I>
+struct IsRawPtr<raw_ptr<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
+
// Template helpers for working with T* or raw_ptr<T>.
template <typename T>
struct IsPointer : std::false_type {};
@@ -1286,7 +1427,7 @@
// See `docs/dangling_ptr.md`
// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
-// occurrences are meant to be removed. See https://cbug.com/1291138.
+// occurrences are meant to be removed. See https://crbug.com/1291138.
using DanglingUntriaged = DisableDanglingPtrDetection;
// The following template parameters are only meaningful when `raw_ptr`
@@ -1298,7 +1439,7 @@
// When `MTECheckedPtr` is in play, we need to augment this
// implementation setting with another layer that allows the `raw_ptr`
// to degrade into the no-op version.
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
// Direct pass-through to no-op implementation.
using DegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
@@ -1323,33 +1464,47 @@
using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
DisableDanglingPtrDetection;
-#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
namespace std {
// Override so set/map lookups do not create extra raw_ptr. This also allows
// dangling pointers to be used for lookup.
-template <typename T, typename Impl>
-struct less<raw_ptr<T, Impl>> {
+template <typename T, typename RawPtrType>
+struct less<raw_ptr<T, RawPtrType>> {
+ using Impl =
+ typename gurl_base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
using is_transparent = void;
- bool operator()(const raw_ptr<T, Impl>& lhs,
- const raw_ptr<T, Impl>& rhs) const {
+ bool operator()(const raw_ptr<T, RawPtrType>& lhs,
+ const raw_ptr<T, RawPtrType>& rhs) const {
Impl::IncrementLessCountForTest();
return lhs < rhs;
}
- bool operator()(T* lhs, const raw_ptr<T, Impl>& rhs) const {
+ bool operator()(T* lhs, const raw_ptr<T, RawPtrType>& rhs) const {
Impl::IncrementLessCountForTest();
return lhs < rhs;
}
- bool operator()(const raw_ptr<T, Impl>& lhs, T* rhs) const {
+ bool operator()(const raw_ptr<T, RawPtrType>& lhs, T* rhs) const {
Impl::IncrementLessCountForTest();
return lhs < rhs;
}
};
+// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
+// This is consistent with definition of std::iterator_traits<T*>.
+// Algorithms like std::binary_search need that.
+template <typename T, typename Impl>
+struct iterator_traits<raw_ptr<T, Impl>> {
+ using difference_type = ptrdiff_t;
+ using value_type = std::remove_cv_t<T>;
+ using pointer = T*;
+ using reference = T&;
+ using iterator_category = std::random_access_iterator_tag;
+};
+
} // namespace std
#endif // BASE_MEMORY_RAW_PTR_H_
diff --git a/base/memory/raw_ptr_exclusion.h b/base/memory/raw_ptr_exclusion.h
index 37e9eac..f881c04 100644
--- a/base/memory/raw_ptr_exclusion.h
+++ b/base/memory/raw_ptr_exclusion.h
@@ -1,13 +1,14 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 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_MEMORY_RAW_PTR_EXCLUSION_H_
#define BASE_MEMORY_RAW_PTR_EXCLUSION_H_
+#include "polyfills/base/allocator/buildflags.h"
#include "build/build_config.h"
-#if defined(OFFICIAL_BUILD)
+#if defined(OFFICIAL_BUILD) && !BUILDFLAG(FORCE_ENABLE_RAW_PTR_EXCLUSION)
// The annotation changed compiler output and increased binary size so disable
// for official builds.
// TODO(crbug.com/1320670): Remove when issue is resolved.
diff --git a/base/no_destructor.h b/base/no_destructor.h
index 2f3c549..b183e4f 100644
--- a/base/no_destructor.h
+++ b/base/no_destructor.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/numerics/checked_math.h b/base/numerics/checked_math.h
new file mode 100644
index 0000000..4973f09
--- /dev/null
+++ b/base/numerics/checked_math.h
@@ -0,0 +1,381 @@
+// 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_NUMERICS_CHECKED_MATH_H_
+#define BASE_NUMERICS_CHECKED_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/checked_math_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class CheckedNumeric {
+ static_assert(std::is_arithmetic<T>::value,
+ "CheckedNumeric<T>: T must be a numeric type.");
+
+ public:
+ template <typename Src>
+ friend class CheckedNumeric;
+
+ using type = T;
+
+ constexpr CheckedNumeric() = default;
+
+ // Copy constructor.
+ template <typename Src>
+ constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
+ : state_(rhs.state_.value(), rhs.IsValid()) {}
+
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `CheckedNumeric(777)` instead of `CheckedNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(T value) : state_(value) {}
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to CheckedNumerics to make them easier to use.
+ template <typename Src>
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(Src value) : state_(value) {
+ static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
+ }
+
+ // This is not an explicit constructor because we want a seamless conversion
+ // from StrictNumeric types.
+ template <typename Src>
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(StrictNumeric<Src> value)
+ : state_(static_cast<Src>(value)) {}
+
+ // IsValid() - The public API to test if a CheckedNumeric is currently valid.
+ // A range checked destination type can be supplied using the Dst template
+ // parameter.
+ template <typename Dst = T>
+ constexpr bool IsValid() const {
+ return state_.is_valid() &&
+ IsValueInRangeForNumericType<Dst>(state_.value());
+ }
+
+ // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
+ // and is within the range supported by the destination type. Returns true if
+ // successful and false otherwise.
+ template <typename Dst>
+#if defined(__clang__) || defined(__GNUC__)
+ __attribute__((warn_unused_result))
+#elif defined(_MSC_VER)
+ _Check_return_
+#endif
+ constexpr bool
+ AssignIfValid(Dst* result) const {
+ return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+ ? ((*result = static_cast<Dst>(state_.value())), true)
+ : false;
+ }
+
+ // ValueOrDie() - The primary accessor for the underlying value. If the
+ // current state is not valid it will GURL_CHECK and crash.
+ // A range checked destination type can be supplied using the Dst template
+ // parameter, which will trigger a GURL_CHECK if the value is not in bounds for
+ // the destination.
+ // The GURL_CHECK behavior can be overridden by supplying a handler as a
+ // template parameter, for test code, etc. However, the handler cannot access
+ // the underlying value, and it is not available through other means.
+ template <typename Dst = T, class CheckHandler = CheckOnFailure>
+ constexpr StrictNumeric<Dst> ValueOrDie() const {
+ return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+ ? static_cast<Dst>(state_.value())
+ : CheckHandler::template HandleFailure<Dst>();
+ }
+
+ // ValueOrDefault(T default_value) - A convenience method that returns the
+ // current value if the state is valid, and the supplied default_value for
+ // any other state.
+ // A range checked destination type can be supplied using the Dst template
+ // parameter. WARNING: This function may fail to compile or GURL_CHECK at runtime
+ // if the supplied default_value is not within range of the destination type.
+ template <typename Dst = T, typename Src>
+ constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
+ return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+ ? static_cast<Dst>(state_.value())
+ : checked_cast<Dst>(default_value);
+ }
+
+ // Returns a checked numeric of the specified type, cast from the current
+ // CheckedNumeric. If the current state is invalid or the destination cannot
+ // represent the result then the returned CheckedNumeric will be invalid.
+ template <typename Dst>
+ constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+ return *this;
+ }
+
+ // This friend method is available solely for providing more detailed logging
+ // in the tests. Do not implement it in production code, because the
+ // underlying values may change at any time.
+ template <typename U>
+ friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
+
+ // Prototypes for the supported arithmetic operator overloads.
+ template <typename Src>
+ constexpr CheckedNumeric& operator+=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator-=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator*=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator/=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator%=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator<<=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator>>=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator&=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator|=(const Src rhs);
+ template <typename Src>
+ constexpr CheckedNumeric& operator^=(const Src rhs);
+
+ constexpr CheckedNumeric operator-() const {
+ // Use an optimized code path for a known run-time variable.
+ if (!IsConstantEvaluated() && std::is_signed<T>::value &&
+ std::is_floating_point<T>::value) {
+ return FastRuntimeNegate();
+ }
+ // The negation of two's complement int min is int min.
+ const bool is_valid =
+ IsValid() &&
+ (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
+ NegateWrapper(state_.value()) != std::numeric_limits<T>::lowest());
+ return CheckedNumeric<T>(NegateWrapper(state_.value()), is_valid);
+ }
+
+ constexpr CheckedNumeric operator~() const {
+ return CheckedNumeric<decltype(InvertWrapper(T()))>(
+ InvertWrapper(state_.value()), IsValid());
+ }
+
+ constexpr CheckedNumeric Abs() const {
+ return !IsValueNegative(state_.value()) ? *this : -*this;
+ }
+
+ template <typename U>
+ constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
+ const U rhs) const {
+ return CheckMax(*this, rhs);
+ }
+
+ template <typename U>
+ constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
+ const U rhs) const {
+ return CheckMin(*this, rhs);
+ }
+
+ // This function is available only for integral types. It returns an unsigned
+ // integer of the same width as the source type, containing the absolute value
+ // of the source, and properly handling signed min.
+ constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
+ UnsignedAbs() const {
+ return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+ SafeUnsignedAbs(state_.value()), state_.is_valid());
+ }
+
+ constexpr CheckedNumeric& operator++() {
+ *this += 1;
+ return *this;
+ }
+
+ constexpr CheckedNumeric operator++(int) {
+ CheckedNumeric value = *this;
+ *this += 1;
+ return value;
+ }
+
+ constexpr CheckedNumeric& operator--() {
+ *this -= 1;
+ return *this;
+ }
+
+ constexpr CheckedNumeric operator--(int) {
+ // TODO(pkasting): Consider std::exchange() once it's constexpr in C++20.
+ const CheckedNumeric value = *this;
+ *this -= 1;
+ return value;
+ }
+
+ // These perform the actual math operations on the CheckedNumerics.
+ // Binary arithmetic operations.
+ template <template <typename, typename, typename> class M,
+ typename L,
+ typename R>
+ static constexpr CheckedNumeric MathOp(const L lhs, const R rhs) {
+ using Math = typename MathWrapper<M, L, R>::math;
+ T result = 0;
+ const bool is_valid =
+ Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
+ Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
+ return CheckedNumeric<T>(result, is_valid);
+ }
+
+ // Assignment arithmetic operations.
+ template <template <typename, typename, typename> class M, typename R>
+ constexpr CheckedNumeric& MathOp(const R rhs) {
+ using Math = typename MathWrapper<M, T, R>::math;
+ T result = 0; // Using T as the destination saves a range check.
+ const bool is_valid =
+ state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
+ Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
+ *this = CheckedNumeric<T>(result, is_valid);
+ return *this;
+ }
+
+ private:
+ CheckedNumericState<T> state_;
+
+ CheckedNumeric FastRuntimeNegate() const {
+ T result;
+ const bool success = CheckedSubOp<T, T>::Do(T(0), state_.value(), &result);
+ return CheckedNumeric<T>(result, IsValid() && success);
+ }
+
+ template <typename Src>
+ constexpr CheckedNumeric(Src value, bool is_valid)
+ : state_(value, is_valid) {}
+
+ // These wrappers allow us to handle state the same way for both
+ // CheckedNumeric and POD arithmetic types.
+ template <typename Src>
+ struct Wrapper {
+ static constexpr bool is_valid(Src) { return true; }
+ static constexpr Src value(Src value) { return value; }
+ };
+
+ template <typename Src>
+ struct Wrapper<CheckedNumeric<Src>> {
+ static constexpr bool is_valid(const CheckedNumeric<Src> v) {
+ return v.IsValid();
+ }
+ static constexpr Src value(const CheckedNumeric<Src> v) {
+ return v.state_.value();
+ }
+ };
+
+ template <typename Src>
+ struct Wrapper<StrictNumeric<Src>> {
+ static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
+ static constexpr Src value(const StrictNumeric<Src> v) {
+ return static_cast<Src>(v);
+ }
+ };
+};
+
+// Convenience functions to avoid the ugly template disambiguator syntax.
+template <typename Dst, typename Src>
+constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
+ return value.template IsValid<Dst>();
+}
+
+template <typename Dst, typename Src>
+constexpr StrictNumeric<Dst> ValueOrDieForType(
+ const CheckedNumeric<Src> value) {
+ return value.template ValueOrDie<Dst>();
+}
+
+template <typename Dst, typename Src, typename Default>
+constexpr StrictNumeric<Dst> ValueOrDefaultForType(
+ const CheckedNumeric<Src> value,
+ const Default default_value) {
+ return value.template ValueOrDefault<Dst>(default_value);
+}
+
+// Convenience wrapper to return a new CheckedNumeric from the provided
+// arithmetic or CheckedNumericType.
+template <typename T>
+constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
+ const T value) {
+ return value;
+}
+
+// These implement the variadic wrapper for the math operations.
+template <template <typename, typename, typename> class M,
+ typename L,
+ typename R>
+constexpr CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp(
+ const L lhs,
+ const R rhs) {
+ using Math = typename MathWrapper<M, L, R>::math;
+ return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+ rhs);
+}
+
+// General purpose wrapper template for arithmetic operations.
+template <template <typename, typename, typename> class M,
+ typename L,
+ typename R,
+ typename... Args>
+constexpr auto CheckMathOp(const L lhs, const R rhs, const Args... args) {
+ return CheckMathOp<M>(CheckMathOp<M>(lhs, rhs), args...);
+}
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Or, |, |=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Xor, ^, ^=)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Max)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Min)
+
+// These are some extra StrictNumeric operators to support simple pointer
+// arithmetic with our result types. Since wrapping on a pointer is always
+// bad, we trigger the GURL_CHECK condition here.
+template <typename L, typename R>
+L* operator+(L* lhs, const StrictNumeric<R> rhs) {
+ const uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
+ CheckMul(sizeof(L), static_cast<R>(rhs)))
+ .template ValueOrDie<uintptr_t>();
+ return reinterpret_cast<L*>(result);
+}
+
+template <typename L, typename R>
+L* operator-(L* lhs, const StrictNumeric<R> rhs) {
+ const uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
+ CheckMul(sizeof(L), static_cast<R>(rhs)))
+ .template ValueOrDie<uintptr_t>();
+ return reinterpret_cast<L*>(result);
+}
+
+} // namespace internal
+
+using internal::CheckAdd;
+using internal::CheckAnd;
+using internal::CheckDiv;
+using internal::CheckedNumeric;
+using internal::CheckLsh;
+using internal::CheckMax;
+using internal::CheckMin;
+using internal::CheckMod;
+using internal::CheckMul;
+using internal::CheckOr;
+using internal::CheckRsh;
+using internal::CheckSub;
+using internal::CheckXor;
+using internal::IsValidForType;
+using internal::MakeCheckedNum;
+using internal::ValueOrDefaultForType;
+using internal::ValueOrDieForType;
+
+} // namespace base
+
+#endif // BASE_NUMERICS_CHECKED_MATH_H_
diff --git a/base/numerics/checked_math_impl.h b/base/numerics/checked_math_impl.h
new file mode 100644
index 0000000..30dd8e1
--- /dev/null
+++ b/base/numerics/checked_math_impl.h
@@ -0,0 +1,593 @@
+// 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_NUMERICS_CHECKED_MATH_IMPL_H_
+#define BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math_shared_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+constexpr bool CheckedAddImpl(T x, T y, T* result) {
+ static_assert(std::is_integral<T>::value, "Type must be integral");
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ using UnsignedDst = typename std::make_unsigned<T>::type;
+ using SignedDst = typename std::make_signed<T>::type;
+ const UnsignedDst ux = static_cast<UnsignedDst>(x);
+ const UnsignedDst uy = static_cast<UnsignedDst>(y);
+ const UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+ // Addition is valid if the sign of (x + y) is equal to either that of x or
+ // that of y.
+ if (std::is_signed<T>::value
+ ? static_cast<SignedDst>((uresult ^ ux) & (uresult ^ uy)) < 0
+ : uresult < uy) // Unsigned is either valid or underflow.
+ return false;
+ *result = static_cast<T>(uresult);
+ return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedAddOp {};
+
+template <typename T, typename U>
+struct CheckedAddOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ if constexpr (CheckedAddFastOp<T, U>::is_supported)
+ return CheckedAddFastOp<T, U>::Do(x, y, result);
+
+ // Double the underlying type up to a full machine word.
+ using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ using Promotion =
+ typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+ IntegerBitsPlusSign<intptr_t>::value),
+ typename BigEnoughPromotion<T, U>::type,
+ FastPromotion>::type;
+ // Fail if either operand is out of range for the promoted type.
+ // TODO(jschuh): This could be made to work for a broader range of values.
+ if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+ !IsValueInRangeForNumericType<Promotion>(y))) {
+ return false;
+ }
+
+ Promotion presult = {};
+ bool is_valid = true;
+ if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+ presult = static_cast<Promotion>(x) + static_cast<Promotion>(y);
+ } else {
+ is_valid = CheckedAddImpl(static_cast<Promotion>(x),
+ static_cast<Promotion>(y), &presult);
+ }
+ if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<V>(presult);
+ return true;
+ }
+};
+
+template <typename T>
+constexpr bool CheckedSubImpl(T x, T y, T* result) {
+ static_assert(std::is_integral<T>::value, "Type must be integral");
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ using UnsignedDst = typename std::make_unsigned<T>::type;
+ using SignedDst = typename std::make_signed<T>::type;
+ const UnsignedDst ux = static_cast<UnsignedDst>(x);
+ const UnsignedDst uy = static_cast<UnsignedDst>(y);
+ const UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+ // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+ // the same sign.
+ if (std::is_signed<T>::value
+ ? static_cast<SignedDst>((uresult ^ ux) & (ux ^ uy)) < 0
+ : x < y)
+ return false;
+ *result = static_cast<T>(uresult);
+ return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedSubOp {};
+
+template <typename T, typename U>
+struct CheckedSubOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ if constexpr (CheckedSubFastOp<T, U>::is_supported)
+ return CheckedSubFastOp<T, U>::Do(x, y, result);
+
+ // Double the underlying type up to a full machine word.
+ using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ using Promotion =
+ typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+ IntegerBitsPlusSign<intptr_t>::value),
+ typename BigEnoughPromotion<T, U>::type,
+ FastPromotion>::type;
+ // Fail if either operand is out of range for the promoted type.
+ // TODO(jschuh): This could be made to work for a broader range of values.
+ if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+ !IsValueInRangeForNumericType<Promotion>(y))) {
+ return false;
+ }
+
+ Promotion presult = {};
+ bool is_valid = true;
+ if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+ presult = static_cast<Promotion>(x) - static_cast<Promotion>(y);
+ } else {
+ is_valid = CheckedSubImpl(static_cast<Promotion>(x),
+ static_cast<Promotion>(y), &presult);
+ }
+ if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<V>(presult);
+ return true;
+ }
+};
+
+template <typename T>
+constexpr bool CheckedMulImpl(T x, T y, T* result) {
+ static_assert(std::is_integral<T>::value, "Type must be integral");
+ // Since the value of x*y is potentially undefined if we have a signed type,
+ // we compute it using the unsigned type of the same size.
+ using UnsignedDst = typename std::make_unsigned<T>::type;
+ using SignedDst = typename std::make_signed<T>::type;
+ const UnsignedDst ux = SafeUnsignedAbs(x);
+ const UnsignedDst uy = SafeUnsignedAbs(y);
+ const UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy);
+ const bool is_negative =
+ std::is_signed<T>::value && static_cast<SignedDst>(x ^ y) < 0;
+ // We have a fast out for unsigned identity or zero on the second operand.
+ // After that it's an unsigned overflow check on the absolute value, with
+ // a +1 bound for a negative result.
+ if (uy > UnsignedDst(!std::is_signed<T>::value || is_negative) &&
+ ux > (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy)
+ return false;
+ *result = static_cast<T>(is_negative ? 0 - uresult : uresult);
+ return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedMulOp {};
+
+template <typename T, typename U>
+struct CheckedMulOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ if constexpr (CheckedMulFastOp<T, U>::is_supported)
+ return CheckedMulFastOp<T, U>::Do(x, y, result);
+
+ using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ // Verify the destination type can hold the result (always true for 0).
+ if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+ !IsValueInRangeForNumericType<Promotion>(y)) &&
+ x && y)) {
+ return false;
+ }
+
+ Promotion presult = {};
+ bool is_valid = true;
+ if (CheckedMulFastOp<Promotion, Promotion>::is_supported) {
+ // The fast op may be available with the promoted type.
+ // The casts here are safe because of the "value in range" conditional
+ // above.
+ is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(
+ static_cast<Promotion>(x), static_cast<Promotion>(y), &presult);
+ } else if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+ presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
+ } else {
+ is_valid = CheckedMulImpl(static_cast<Promotion>(x),
+ static_cast<Promotion>(y), &presult);
+ }
+ if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<V>(presult);
+ return true;
+ }
+};
+
+// Division just requires a check for a zero denominator or an invalid negation
+// on signed min/-1.
+template <typename T, typename U, class Enable = void>
+struct CheckedDivOp {};
+
+template <typename T, typename U>
+struct CheckedDivOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ if (BASE_NUMERICS_UNLIKELY(!y))
+ return false;
+
+ // The overflow check can be compiled away if we don't have the exact
+ // combination of types needed to trigger this case.
+ using Promotion = typename BigEnoughPromotion<T, U>::type;
+ if (BASE_NUMERICS_UNLIKELY(
+ (std::is_signed<T>::value && std::is_signed<U>::value &&
+ IsTypeInRangeForNumericType<T, Promotion>::value &&
+ static_cast<Promotion>(x) ==
+ std::numeric_limits<Promotion>::lowest() &&
+ y == static_cast<U>(-1)))) {
+ return false;
+ }
+
+ // This branch always compiles away if the above branch wasn't removed.
+ if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+ !IsValueInRangeForNumericType<Promotion>(y)) &&
+ x)) {
+ return false;
+ }
+
+ const Promotion presult = Promotion(x) / Promotion(y);
+ if (!IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<V>(presult);
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedModOp {};
+
+template <typename T, typename U>
+struct CheckedModOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ if (BASE_NUMERICS_UNLIKELY(!y))
+ return false;
+
+ using Promotion = typename BigEnoughPromotion<T, U>::type;
+ if (BASE_NUMERICS_UNLIKELY(
+ (std::is_signed<T>::value && std::is_signed<U>::value &&
+ IsTypeInRangeForNumericType<T, Promotion>::value &&
+ static_cast<Promotion>(x) ==
+ std::numeric_limits<Promotion>::lowest() &&
+ y == static_cast<U>(-1)))) {
+ *result = 0;
+ return true;
+ }
+
+ const Promotion presult =
+ static_cast<Promotion>(x) % static_cast<Promotion>(y);
+ if (!IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<Promotion>(presult);
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedLshOp {};
+
+// Left shift. Shifts less than 0 or greater than or equal to the number
+// of bits in the promoted type are undefined. Shifts of negative values
+// are undefined. Otherwise it is defined when the result fits.
+template <typename T, typename U>
+struct CheckedLshOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = T;
+ template <typename V>
+ static constexpr bool Do(T x, U shift, V* result) {
+ // Disallow negative numbers and verify the shift is in bounds.
+ if (BASE_NUMERICS_LIKELY(!IsValueNegative(x) &&
+ as_unsigned(shift) <
+ as_unsigned(std::numeric_limits<T>::digits))) {
+ // Shift as unsigned to avoid undefined behavior.
+ *result = static_cast<V>(as_unsigned(x) << shift);
+ // If the shift can be reversed, we know it was valid.
+ return *result >> shift == x;
+ }
+
+ // Handle the legal corner-case of a full-width signed shift of zero.
+ if (!std::is_signed<T>::value || x ||
+ as_unsigned(shift) != as_unsigned(std::numeric_limits<T>::digits))
+ return false;
+ *result = 0;
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedRshOp {};
+
+// Right shift. Shifts less than 0 or greater than or equal to the number
+// of bits in the promoted type are undefined. Otherwise, it is always defined,
+// but a right shift of a negative value is implementation-dependent.
+template <typename T, typename U>
+struct CheckedRshOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = T;
+ template <typename V>
+ static constexpr bool Do(T x, U shift, V* result) {
+ // Use sign conversion to push negative values out of range.
+ if (BASE_NUMERICS_UNLIKELY(as_unsigned(shift) >=
+ IntegerBitsPlusSign<T>::value)) {
+ return false;
+ }
+
+ const T tmp = x >> shift;
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedAndOp {};
+
+// For simplicity we support only unsigned integer results.
+template <typename T, typename U>
+struct CheckedAndOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ const result_type tmp =
+ static_cast<result_type>(x) & static_cast<result_type>(y);
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedOrOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct CheckedOrOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ const result_type tmp =
+ static_cast<result_type>(x) | static_cast<result_type>(y);
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedXorOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct CheckedXorOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ const result_type tmp =
+ static_cast<result_type>(x) ^ static_cast<result_type>(y);
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+// Max doesn't really need to be implemented this way because it can't fail,
+// but it makes the code much cleaner to use the MathOp wrappers.
+template <typename T, typename U, class Enable = void>
+struct CheckedMaxOp {};
+
+template <typename T, typename U>
+struct CheckedMaxOp<
+ T,
+ U,
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ std::is_arithmetic<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ const result_type tmp = IsGreater<T, U>::Test(x, y)
+ ? static_cast<result_type>(x)
+ : static_cast<result_type>(y);
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+// Min doesn't really need to be implemented this way because it can't fail,
+// but it makes the code much cleaner to use the MathOp wrappers.
+template <typename T, typename U, class Enable = void>
+struct CheckedMinOp {};
+
+template <typename T, typename U>
+struct CheckedMinOp<
+ T,
+ U,
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ std::is_arithmetic<U>::value>::type> {
+ using result_type = typename LowestValuePromotion<T, U>::type;
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ const result_type tmp = IsLess<T, U>::Test(x, y)
+ ? static_cast<result_type>(x)
+ : static_cast<result_type>(y);
+ if (!IsValueInRangeForNumericType<V>(tmp))
+ return false;
+ *result = static_cast<V>(tmp);
+ return true;
+ }
+};
+
+// This is just boilerplate that wraps the standard floating point arithmetic.
+// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
+ template <typename T, typename U> \
+ struct Checked##NAME##Op< \
+ T, U, \
+ typename std::enable_if<std::is_floating_point<T>::value || \
+ std::is_floating_point<U>::value>::type> { \
+ using result_type = typename MaxExponentPromotion<T, U>::type; \
+ template <typename V> \
+ static constexpr bool Do(T x, U y, V* result) { \
+ using Promotion = typename MaxExponentPromotion<T, U>::type; \
+ const Promotion presult = x OP y; \
+ if (!IsValueInRangeForNumericType<V>(presult)) \
+ return false; \
+ *result = static_cast<V>(presult); \
+ return true; \
+ } \
+ };
+
+BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+
+#undef BASE_FLOAT_ARITHMETIC_OPS
+
+// Floats carry around their validity state with them, but integers do not. So,
+// we wrap the underlying value in a specialization in order to hide that detail
+// and expose an interface via accessors.
+enum NumericRepresentation {
+ NUMERIC_INTEGER,
+ NUMERIC_FLOATING,
+ NUMERIC_UNKNOWN
+};
+
+template <typename NumericType>
+struct GetNumericRepresentation {
+ static const NumericRepresentation value =
+ std::is_integral<NumericType>::value
+ ? NUMERIC_INTEGER
+ : (std::is_floating_point<NumericType>::value ? NUMERIC_FLOATING
+ : NUMERIC_UNKNOWN);
+};
+
+template <typename T,
+ NumericRepresentation type = GetNumericRepresentation<T>::value>
+class CheckedNumericState {};
+
+// Integrals require quite a bit of additional housekeeping to manage state.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_INTEGER> {
+ public:
+ template <typename Src = int>
+ constexpr explicit CheckedNumericState(Src value = 0, bool is_valid = true)
+ : is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)),
+ value_(WellDefinedConversionOrZero(value, is_valid_)) {
+ static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
+ }
+
+ template <typename Src>
+ constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+ : CheckedNumericState(rhs.value(), rhs.is_valid()) {}
+
+ constexpr bool is_valid() const { return is_valid_; }
+
+ constexpr T value() const { return value_; }
+
+ private:
+ // Ensures that a type conversion does not trigger undefined behavior.
+ template <typename Src>
+ static constexpr T WellDefinedConversionOrZero(Src value, bool is_valid) {
+ using SrcType = typename internal::UnderlyingType<Src>::type;
+ return (std::is_integral<SrcType>::value || is_valid)
+ ? static_cast<T>(value)
+ : 0;
+ }
+
+ // is_valid_ precedes value_ because member initializers in the constructors
+ // are evaluated in field order, and is_valid_ must be read when initializing
+ // value_.
+ bool is_valid_;
+ T value_;
+};
+
+// Floating points maintain their own validity, but need translation wrappers.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_FLOATING> {
+ public:
+ template <typename Src = double>
+ constexpr explicit CheckedNumericState(Src value = 0.0, bool is_valid = true)
+ : value_(WellDefinedConversionOrNaN(
+ value,
+ is_valid && IsValueInRangeForNumericType<T>(value))) {}
+
+ template <typename Src>
+ constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+ : CheckedNumericState(rhs.value(), rhs.is_valid()) {}
+
+ constexpr bool is_valid() const {
+ // Written this way because std::isfinite is not reliably constexpr.
+ return IsConstantEvaluated()
+ ? value_ <= std::numeric_limits<T>::max() &&
+ value_ >= std::numeric_limits<T>::lowest()
+ : std::isfinite(value_);
+ }
+
+ constexpr T value() const { return value_; }
+
+ private:
+ // Ensures that a type conversion does not trigger undefined behavior.
+ template <typename Src>
+ static constexpr T WellDefinedConversionOrNaN(Src value, bool is_valid) {
+ using SrcType = typename internal::UnderlyingType<Src>::type;
+ return (StaticDstRangeRelationToSrcRange<T, SrcType>::value ==
+ NUMERIC_RANGE_CONTAINED ||
+ is_valid)
+ ? static_cast<T>(value)
+ : std::numeric_limits<T>::quiet_NaN();
+ }
+
+ T value_;
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_CHECKED_MATH_IMPL_H_
diff --git a/base/numerics/clamped_math.h b/base/numerics/clamped_math.h
new file mode 100644
index 0000000..fe6b0fe
--- /dev/null
+++ b/base/numerics/clamped_math.h
@@ -0,0 +1,260 @@
+// 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_NUMERICS_CLAMPED_MATH_H_
+#define BASE_NUMERICS_CLAMPED_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/clamped_math_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class ClampedNumeric {
+ static_assert(std::is_arithmetic<T>::value,
+ "ClampedNumeric<T>: T must be a numeric type.");
+
+ public:
+ using type = T;
+
+ constexpr ClampedNumeric() : value_(0) {}
+
+ // Copy constructor.
+ template <typename Src>
+ constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
+ : value_(saturated_cast<T>(rhs.value_)) {}
+
+ template <typename Src>
+ friend class ClampedNumeric;
+
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `ClampedNumeric(777)` instead of `ClampedNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(T value) : value_(value) {}
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to ClampedNumerics to make them easier to use.
+ template <typename Src>
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(Src value) : value_(saturated_cast<T>(value)) {
+ static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
+ }
+
+ // This is not an explicit constructor because we want a seamless conversion
+ // from StrictNumeric types.
+ template <typename Src>
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(StrictNumeric<Src> value)
+ : value_(saturated_cast<T>(static_cast<Src>(value))) {}
+
+ // Returns a ClampedNumeric of the specified type, cast from the current
+ // ClampedNumeric, and saturated to the destination type.
+ template <typename Dst>
+ constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+ return *this;
+ }
+
+ // Prototypes for the supported arithmetic operator overloads.
+ template <typename Src>
+ constexpr ClampedNumeric& operator+=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator-=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator*=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator/=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator%=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator<<=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator>>=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator&=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator|=(const Src rhs);
+ template <typename Src>
+ constexpr ClampedNumeric& operator^=(const Src rhs);
+
+ constexpr ClampedNumeric operator-() const {
+ // The negation of two's complement int min is int min, so that's the
+ // only overflow case where we will saturate.
+ return ClampedNumeric<T>(SaturatedNegWrapper(value_));
+ }
+
+ constexpr ClampedNumeric operator~() const {
+ return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
+ }
+
+ constexpr ClampedNumeric Abs() const {
+ // The negation of two's complement int min is int min, so that's the
+ // only overflow case where we will saturate.
+ return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
+ }
+
+ template <typename U>
+ constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
+ const U rhs) const {
+ using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
+ return ClampedNumeric<result_type>(
+ ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+ }
+
+ template <typename U>
+ constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
+ const U rhs) const {
+ using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
+ return ClampedNumeric<result_type>(
+ ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+ }
+
+ // This function is available only for integral types. It returns an unsigned
+ // integer of the same width as the source type, containing the absolute value
+ // of the source, and properly handling signed min.
+ constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
+ UnsignedAbs() const {
+ return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+ SafeUnsignedAbs(value_));
+ }
+
+ constexpr ClampedNumeric& operator++() {
+ *this += 1;
+ return *this;
+ }
+
+ constexpr ClampedNumeric operator++(int) {
+ ClampedNumeric value = *this;
+ *this += 1;
+ return value;
+ }
+
+ constexpr ClampedNumeric& operator--() {
+ *this -= 1;
+ return *this;
+ }
+
+ constexpr ClampedNumeric operator--(int) {
+ ClampedNumeric value = *this;
+ *this -= 1;
+ return value;
+ }
+
+ // These perform the actual math operations on the ClampedNumerics.
+ // Binary arithmetic operations.
+ template <template <typename, typename, typename> class M,
+ typename L,
+ typename R>
+ static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
+ using Math = typename MathWrapper<M, L, R>::math;
+ return ClampedNumeric<T>(
+ Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
+ }
+
+ // Assignment arithmetic operations.
+ template <template <typename, typename, typename> class M, typename R>
+ constexpr ClampedNumeric& MathOp(const R rhs) {
+ using Math = typename MathWrapper<M, T, R>::math;
+ *this =
+ ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
+ return *this;
+ }
+
+ template <typename Dst>
+ constexpr operator Dst() const {
+ return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
+ value_);
+ }
+
+ // This method extracts the raw integer value without saturating it to the
+ // destination type as the conversion operator does. This is useful when
+ // e.g. assigning to an auto type or passing as a deduced template parameter.
+ constexpr T RawValue() const { return value_; }
+
+ private:
+ T value_;
+
+ // These wrappers allow us to handle state the same way for both
+ // ClampedNumeric and POD arithmetic types.
+ template <typename Src>
+ struct Wrapper {
+ static constexpr typename UnderlyingType<Src>::type value(Src value) {
+ return value;
+ }
+ };
+};
+
+// Convenience wrapper to return a new ClampedNumeric from the provided
+// arithmetic or ClampedNumericType.
+template <typename T>
+constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
+ const T value) {
+ return value;
+}
+
+// These implement the variadic wrapper for the math operations.
+template <template <typename, typename, typename> class M,
+ typename L,
+ typename R>
+constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
+ const L lhs,
+ const R rhs) {
+ using Math = typename MathWrapper<M, L, R>::math;
+ return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+ rhs);
+}
+
+// General purpose wrapper template for arithmetic operations.
+template <template <typename, typename, typename> class M,
+ typename L,
+ typename R,
+ typename... Args>
+constexpr auto ClampMathOp(const L lhs, const R rhs, const Args... args) {
+ return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
+}
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
+
+} // namespace internal
+
+using internal::ClampAdd;
+using internal::ClampAnd;
+using internal::ClampDiv;
+using internal::ClampedNumeric;
+using internal::ClampLsh;
+using internal::ClampMax;
+using internal::ClampMin;
+using internal::ClampMod;
+using internal::ClampMul;
+using internal::ClampOr;
+using internal::ClampRsh;
+using internal::ClampSub;
+using internal::ClampXor;
+using internal::MakeClampedNum;
+
+} // namespace base
+
+#endif // BASE_NUMERICS_CLAMPED_MATH_H_
diff --git a/base/numerics/clamped_math_impl.h b/base/numerics/clamped_math_impl.h
new file mode 100644
index 0000000..10023f0
--- /dev/null
+++ b/base/numerics/clamped_math_impl.h
@@ -0,0 +1,340 @@
+// 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_NUMERICS_CLAMPED_MATH_IMPL_H_
+#define BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math_shared_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+ return IsConstantEvaluated() || !ClampedNegFastOp<T>::is_supported
+ ? (NegateWrapper(value) != std::numeric_limits<T>::lowest()
+ ? NegateWrapper(value)
+ : std::numeric_limits<T>::max())
+ : ClampedNegFastOp<T>::Do(value);
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ !std::is_signed<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+ return T(0);
+}
+
+template <
+ typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+ return -value;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T SaturatedAbsWrapper(T value) {
+ // The calculation below is a static identity for unsigned types, but for
+ // signed integer types it provides a non-branching, saturated absolute value.
+ // This works because SafeUnsignedAbs() returns an unsigned type, which can
+ // represent the absolute value of all negative numbers of an equal-width
+ // integer type. The call to IsValueNegative() then detects overflow in the
+ // special case of numeric_limits<T>::min(), by evaluating the bit pattern as
+ // a signed integer value. If it is the overflow case, we end up subtracting
+ // one from the unsigned result, thus saturating to numeric_limits<T>::max().
+ return static_cast<T>(
+ SafeUnsignedAbs(value) -
+ IsValueNegative<T>(static_cast<T>(SafeUnsignedAbs(value))));
+}
+
+template <
+ typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T SaturatedAbsWrapper(T value) {
+ return value < 0 ? -value : value;
+}
+
+template <typename T, typename U, class Enable = void>
+struct ClampedAddOp {};
+
+template <typename T, typename U>
+struct ClampedAddOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ if (!IsConstantEvaluated() && ClampedAddFastOp<T, U>::is_supported)
+ return ClampedAddFastOp<T, U>::template Do<V>(x, y);
+
+ static_assert(std::is_same<V, result_type>::value ||
+ IsTypeInRangeForNumericType<U, V>::value,
+ "The saturation result cannot be determined from the "
+ "provided types.");
+ const V saturated = CommonMaxOrMin<V>(IsValueNegative(y));
+ V result = {};
+ return BASE_NUMERICS_LIKELY((CheckedAddOp<T, U>::Do(x, y, &result)))
+ ? result
+ : saturated;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedSubOp {};
+
+template <typename T, typename U>
+struct ClampedSubOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ if (!IsConstantEvaluated() && ClampedSubFastOp<T, U>::is_supported)
+ return ClampedSubFastOp<T, U>::template Do<V>(x, y);
+
+ static_assert(std::is_same<V, result_type>::value ||
+ IsTypeInRangeForNumericType<U, V>::value,
+ "The saturation result cannot be determined from the "
+ "provided types.");
+ const V saturated = CommonMaxOrMin<V>(!IsValueNegative(y));
+ V result = {};
+ return BASE_NUMERICS_LIKELY((CheckedSubOp<T, U>::Do(x, y, &result)))
+ ? result
+ : saturated;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMulOp {};
+
+template <typename T, typename U>
+struct ClampedMulOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ if (!IsConstantEvaluated() && ClampedMulFastOp<T, U>::is_supported)
+ return ClampedMulFastOp<T, U>::template Do<V>(x, y);
+
+ V result = {};
+ const V saturated =
+ CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
+ return BASE_NUMERICS_LIKELY((CheckedMulOp<T, U>::Do(x, y, &result)))
+ ? result
+ : saturated;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedDivOp {};
+
+template <typename T, typename U>
+struct ClampedDivOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ V result = {};
+ if (BASE_NUMERICS_LIKELY((CheckedDivOp<T, U>::Do(x, y, &result))))
+ return result;
+ // Saturation goes to max, min, or NaN (if x is zero).
+ return x ? CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y))
+ : SaturationDefaultLimits<V>::NaN();
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedModOp {};
+
+template <typename T, typename U>
+struct ClampedModOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ V result = {};
+ return BASE_NUMERICS_LIKELY((CheckedModOp<T, U>::Do(x, y, &result)))
+ ? result
+ : x;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedLshOp {};
+
+// Left shift. Non-zero values saturate in the direction of the sign. A zero
+// shifted by any value always results in zero.
+template <typename T, typename U>
+struct ClampedLshOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = T;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U shift) {
+ static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+ if (BASE_NUMERICS_LIKELY(shift < std::numeric_limits<T>::digits)) {
+ // Shift as unsigned to avoid undefined behavior.
+ V result = static_cast<V>(as_unsigned(x) << shift);
+ // If the shift can be reversed, we know it was valid.
+ if (BASE_NUMERICS_LIKELY(result >> shift == x))
+ return result;
+ }
+ return x ? CommonMaxOrMin<V>(IsValueNegative(x)) : 0;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedRshOp {};
+
+// Right shift. Negative values saturate to -1. Positive or 0 saturates to 0.
+template <typename T, typename U>
+struct ClampedRshOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = T;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U shift) {
+ static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+ // Signed right shift is odd, because it saturates to -1 or 0.
+ const V saturated = as_unsigned(V(0)) - IsValueNegative(x);
+ return BASE_NUMERICS_LIKELY(shift < IntegerBitsPlusSign<T>::value)
+ ? saturated_cast<V>(x >> shift)
+ : saturated;
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedAndOp {};
+
+template <typename T, typename U>
+struct ClampedAndOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr V Do(T x, U y) {
+ return static_cast<result_type>(x) & static_cast<result_type>(y);
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedOrOp {};
+
+// For simplicity we promote to unsigned integers.
+template <typename T, typename U>
+struct ClampedOrOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr V Do(T x, U y) {
+ return static_cast<result_type>(x) | static_cast<result_type>(y);
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedXorOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct ClampedXorOp<T,
+ U,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_integral<U>::value>::type> {
+ using result_type = typename std::make_unsigned<
+ typename MaxExponentPromotion<T, U>::type>::type;
+ template <typename V>
+ static constexpr V Do(T x, U y) {
+ return static_cast<result_type>(x) ^ static_cast<result_type>(y);
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMaxOp {};
+
+template <typename T, typename U>
+struct ClampedMaxOp<
+ T,
+ U,
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ std::is_arithmetic<U>::value>::type> {
+ using result_type = typename MaxExponentPromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ return IsGreater<T, U>::Test(x, y) ? saturated_cast<V>(x)
+ : saturated_cast<V>(y);
+ }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMinOp {};
+
+template <typename T, typename U>
+struct ClampedMinOp<
+ T,
+ U,
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ std::is_arithmetic<U>::value>::type> {
+ using result_type = typename LowestValuePromotion<T, U>::type;
+ template <typename V = result_type>
+ static constexpr V Do(T x, U y) {
+ return IsLess<T, U>::Test(x, y) ? saturated_cast<V>(x)
+ : saturated_cast<V>(y);
+ }
+};
+
+// This is just boilerplate that wraps the standard floating point arithmetic.
+// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
+ template <typename T, typename U> \
+ struct Clamped##NAME##Op< \
+ T, U, \
+ typename std::enable_if<std::is_floating_point<T>::value || \
+ std::is_floating_point<U>::value>::type> { \
+ using result_type = typename MaxExponentPromotion<T, U>::type; \
+ template <typename V = result_type> \
+ static constexpr V Do(T x, U y) { \
+ return saturated_cast<V>(x OP y); \
+ } \
+ };
+
+BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+
+#undef BASE_FLOAT_ARITHMETIC_OPS
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
diff --git a/base/numerics/math_constants.h b/base/numerics/math_constants.h
new file mode 100644
index 0000000..c406ab9
--- /dev/null
+++ b/base/numerics/math_constants.h
@@ -0,0 +1,19 @@
+// 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_NUMERICS_MATH_CONSTANTS_H_
+#define BASE_NUMERICS_MATH_CONSTANTS_H_
+
+namespace gurl_base {
+
+constexpr double kPiDouble = 3.14159265358979323846;
+constexpr float kPiFloat = 3.14159265358979323846f;
+
+// The mean acceleration due to gravity on Earth in m/s^2.
+constexpr double kMeanGravityDouble = 9.80665;
+constexpr float kMeanGravityFloat = 9.80665f;
+
+} // namespace base
+
+#endif // BASE_NUMERICS_MATH_CONSTANTS_H_
diff --git a/base/numerics/ostream_operators.h b/base/numerics/ostream_operators.h
new file mode 100644
index 0000000..100c37f
--- /dev/null
+++ b/base/numerics/ostream_operators.h
@@ -0,0 +1,35 @@
+// Copyright 2021 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_NUMERICS_OSTREAM_OPERATORS_H_
+#define BASE_NUMERICS_OSTREAM_OPERATORS_H_
+
+#include <ostream>
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class ClampedNumeric;
+template <typename T>
+class StrictNumeric;
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
+ os << static_cast<T>(value);
+ return os;
+}
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
+ os << static_cast<T>(value);
+ return os;
+}
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_OSTREAM_OPERATORS_H_
diff --git a/base/numerics/ranges.h b/base/numerics/ranges.h
new file mode 100644
index 0000000..98085eb
--- /dev/null
+++ b/base/numerics/ranges.h
@@ -0,0 +1,21 @@
+// 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_NUMERICS_RANGES_H_
+#define BASE_NUMERICS_RANGES_H_
+
+#include <cmath>
+#include <type_traits>
+
+namespace gurl_base {
+
+template <typename T>
+constexpr bool IsApproximatelyEqual(T lhs, T rhs, T tolerance) {
+ static_assert(std::is_arithmetic<T>::value, "Argument must be arithmetic");
+ return std::abs(rhs - lhs) <= tolerance;
+}
+
+} // namespace base
+
+#endif // BASE_NUMERICS_RANGES_H_
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index df84c7e..4a9494e 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -284,11 +284,17 @@
constexpr StrictNumeric(const StrictNumeric<Src>& rhs)
: value_(strict_cast<T>(rhs.value_)) {}
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `StrictNumeric(777)` instead of `StrictNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr StrictNumeric(T value) : value_(value) {}
+
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to StrictNumerics to make them easier to use.
template <typename Src>
- constexpr StrictNumeric(Src value) // NOLINT(runtime/explicit)
- : value_(strict_cast<T>(value)) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value)) {}
// If you got here from a compiler error, it's because you tried to assign
// from a source type to a destination type that has insufficient range.
diff --git a/base/numerics/safe_conversions_arm_impl.h b/base/numerics/safe_conversions_arm_impl.h
new file mode 100644
index 0000000..176af95
--- /dev/null
+++ b/base/numerics/safe_conversions_arm_impl.h
@@ -0,0 +1,51 @@
+// 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_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
+
+#include <cassert>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+// Fast saturation to a destination type.
+template <typename Dst, typename Src>
+struct SaturateFastAsmOp {
+ static constexpr bool is_supported =
+ kEnableAsmCode && std::is_signed<Src>::value &&
+ std::is_integral<Dst>::value && std::is_integral<Src>::value &&
+ IntegerBitsPlusSign<Src>::value <= IntegerBitsPlusSign<int32_t>::value &&
+ IntegerBitsPlusSign<Dst>::value <= IntegerBitsPlusSign<int32_t>::value &&
+ !IsTypeInRangeForNumericType<Dst, Src>::value;
+
+ __attribute__((always_inline)) static Dst Do(Src value) {
+ int32_t src = value;
+ typename std::conditional<std::is_signed<Dst>::value, int32_t,
+ uint32_t>::type result;
+ if (std::is_signed<Dst>::value) {
+ asm("ssat %[dst], %[shift], %[src]"
+ : [dst] "=r"(result)
+ : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value <= 32
+ ? IntegerBitsPlusSign<Dst>::value
+ : 32));
+ } else {
+ asm("usat %[dst], %[shift], %[src]"
+ : [dst] "=r"(result)
+ : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value < 32
+ ? IntegerBitsPlusSign<Dst>::value
+ : 31));
+ }
+ return static_cast<Dst>(result);
+ }
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index 07a927e..abe1706 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h
new file mode 100644
index 0000000..25d10f6
--- /dev/null
+++ b/base/numerics/safe_math.h
@@ -0,0 +1,12 @@
+// 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_NUMERICS_SAFE_MATH_H_
+#define BASE_NUMERICS_SAFE_MATH_H_
+
+#include "base/numerics/checked_math.h"
+#include "base/numerics/clamped_math.h"
+#include "base/numerics/safe_conversions.h"
+
+#endif // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/base/numerics/safe_math_arm_impl.h b/base/numerics/safe_math_arm_impl.h
new file mode 100644
index 0000000..f419773
--- /dev/null
+++ b/base/numerics/safe_math_arm_impl.h
@@ -0,0 +1,125 @@
+// 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_NUMERICS_SAFE_MATH_ARM_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
+
+#include <cassert>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T, typename U>
+struct CheckedMulFastAsmOp {
+ static const bool is_supported =
+ kEnableAsmCode && FastIntegerArithmeticPromotion<T, U>::is_contained;
+
+ // The following is not an assembler routine and is thus constexpr safe, it
+ // just emits much more efficient code than the Clang and GCC builtins for
+ // performing overflow-checked multiplication when a twice wider type is
+ // available. The below compiles down to 2-3 instructions, depending on the
+ // width of the types in use.
+ // As an example, an int32_t multiply compiles to:
+ // smull r0, r1, r0, r1
+ // cmp r1, r1, asr #31
+ // And an int16_t multiply compiles to:
+ // smulbb r1, r1, r0
+ // asr r2, r1, #16
+ // cmp r2, r1, asr #15
+ template <typename V>
+ static constexpr bool Do(T x, U y, V* result) {
+ using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ Promotion presult;
+
+ presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
+ if (!IsValueInRangeForNumericType<V>(presult))
+ return false;
+ *result = static_cast<V>(presult);
+ return true;
+ }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastAsmOp {
+ static const bool is_supported =
+ kEnableAsmCode && BigEnoughPromotion<T, U>::is_contained &&
+ IsTypeInRangeForNumericType<
+ int32_t,
+ typename BigEnoughPromotion<T, U>::type>::value;
+
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ // This will get promoted to an int, so let the compiler do whatever is
+ // clever and rely on the saturated cast to bounds check.
+ if (IsIntegerArithmeticSafe<int, T, U>::value)
+ return saturated_cast<V>(static_cast<int>(x) + static_cast<int>(y));
+
+ int32_t result;
+ int32_t x_i32 = checked_cast<int32_t>(x);
+ int32_t y_i32 = checked_cast<int32_t>(y);
+
+ asm("qadd %[result], %[first], %[second]"
+ : [result] "=r"(result)
+ : [first] "r"(x_i32), [second] "r"(y_i32));
+ return saturated_cast<V>(result);
+ }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastAsmOp {
+ static const bool is_supported =
+ kEnableAsmCode && BigEnoughPromotion<T, U>::is_contained &&
+ IsTypeInRangeForNumericType<
+ int32_t,
+ typename BigEnoughPromotion<T, U>::type>::value;
+
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ // This will get promoted to an int, so let the compiler do whatever is
+ // clever and rely on the saturated cast to bounds check.
+ if (IsIntegerArithmeticSafe<int, T, U>::value)
+ return saturated_cast<V>(static_cast<int>(x) - static_cast<int>(y));
+
+ int32_t result;
+ int32_t x_i32 = checked_cast<int32_t>(x);
+ int32_t y_i32 = checked_cast<int32_t>(y);
+
+ asm("qsub %[result], %[first], %[second]"
+ : [result] "=r"(result)
+ : [first] "r"(x_i32), [second] "r"(y_i32));
+ return saturated_cast<V>(result);
+ }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastAsmOp {
+ static const bool is_supported =
+ kEnableAsmCode && CheckedMulFastAsmOp<T, U>::is_supported;
+
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ // Use the CheckedMulFastAsmOp for full-width 32-bit values, because
+ // it's fewer instructions than promoting and then saturating.
+ if (!IsIntegerArithmeticSafe<int32_t, T, U>::value &&
+ !IsIntegerArithmeticSafe<uint32_t, T, U>::value) {
+ V result;
+ return CheckedMulFastAsmOp<T, U>::Do(x, y, &result)
+ ? result
+ : CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
+ }
+
+ assert((FastIntegerArithmeticPromotion<T, U>::is_contained));
+ using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ return saturated_cast<V>(static_cast<Promotion>(x) *
+ static_cast<Promotion>(y));
+ }
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
diff --git a/base/numerics/safe_math_clang_gcc_impl.h b/base/numerics/safe_math_clang_gcc_impl.h
new file mode 100644
index 0000000..a11ab06
--- /dev/null
+++ b/base/numerics/safe_math_clang_gcc_impl.h
@@ -0,0 +1,157 @@
+// 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_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
+
+#include <cassert>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
+#include "base/numerics/safe_math_arm_impl.h"
+#define BASE_HAS_ASSEMBLER_SAFE_MATH (1)
+#else
+#define BASE_HAS_ASSEMBLER_SAFE_MATH (0)
+#endif
+
+namespace gurl_base {
+namespace internal {
+
+// These are the non-functioning boilerplate implementations of the optimized
+// safe math routines.
+#if !BASE_HAS_ASSEMBLER_SAFE_MATH
+template <typename T, typename U>
+struct CheckedMulFastAsmOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr bool Do(T, U, V*) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<bool>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastAsmOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastAsmOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastAsmOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+#endif // BASE_HAS_ASSEMBLER_SAFE_MATH
+#undef BASE_HAS_ASSEMBLER_SAFE_MATH
+
+template <typename T, typename U>
+struct CheckedAddFastOp {
+ static const bool is_supported = true;
+ template <typename V>
+ __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+ return !__builtin_add_overflow(x, y, result);
+ }
+};
+
+template <typename T, typename U>
+struct CheckedSubFastOp {
+ static const bool is_supported = true;
+ template <typename V>
+ __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+ return !__builtin_sub_overflow(x, y, result);
+ }
+};
+
+template <typename T, typename U>
+struct CheckedMulFastOp {
+#if defined(__clang__)
+ // TODO(jschuh): Get the Clang runtime library issues sorted out so we can
+ // support full-width, mixed-sign multiply builtins.
+ // https://crbug.com/613003
+ // We can support intptr_t, uintptr_t, or a smaller common type.
+ static const bool is_supported =
+ (IsTypeInRangeForNumericType<intptr_t, T>::value &&
+ IsTypeInRangeForNumericType<intptr_t, U>::value) ||
+ (IsTypeInRangeForNumericType<uintptr_t, T>::value &&
+ IsTypeInRangeForNumericType<uintptr_t, U>::value);
+#else
+ static const bool is_supported = true;
+#endif
+ template <typename V>
+ __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+ return CheckedMulFastAsmOp<T, U>::is_supported
+ ? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
+ : !__builtin_mul_overflow(x, y, result);
+ }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastOp {
+ static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
+ }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastOp {
+ static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
+ }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastOp {
+ static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
+ template <typename V>
+ __attribute__((always_inline)) static V Do(T x, U y) {
+ return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
+ }
+};
+
+template <typename T>
+struct ClampedNegFastOp {
+ static const bool is_supported = std::is_signed<T>::value;
+ __attribute__((always_inline)) static T Do(T value) {
+ // Use this when there is no assembler path available.
+ if (!ClampedSubFastAsmOp<T, T>::is_supported) {
+ T result;
+ return !__builtin_sub_overflow(T(0), value, &result)
+ ? result
+ : std::numeric_limits<T>::max();
+ }
+
+ // Fallback to the normal subtraction path.
+ return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
+ }
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
diff --git a/base/numerics/safe_math_shared_impl.h b/base/numerics/safe_math_shared_impl.h
new file mode 100644
index 0000000..d0030fc
--- /dev/null
+++ b/base/numerics/safe_math_shared_impl.h
@@ -0,0 +1,216 @@
+// 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_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cassert>
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+#include "build/build_config.h"
+
+#if BUILDFLAG(IS_ASMJS)
+// Optimized safe math instructions are incompatible with asmjs.
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
+// Where available use builtin math overflow support on Clang and GCC.
+#elif !defined(__native_client__) && \
+ ((defined(__clang__) && \
+ ((__clang_major__ > 3) || \
+ (__clang_major__ == 3 && __clang_minor__ >= 4))) || \
+ (defined(__GNUC__) && __GNUC__ >= 5))
+#include "base/numerics/safe_math_clang_gcc_impl.h"
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (1)
+#else
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
+#endif
+
+namespace gurl_base {
+namespace internal {
+
+// These are the non-functioning boilerplate implementations of the optimized
+// safe math routines.
+#if !BASE_HAS_OPTIMIZED_SAFE_MATH
+template <typename T, typename U>
+struct CheckedAddFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr bool Do(T, U, V*) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<bool>();
+ }
+};
+
+template <typename T, typename U>
+struct CheckedSubFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr bool Do(T, U, V*) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<bool>();
+ }
+};
+
+template <typename T, typename U>
+struct CheckedMulFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr bool Do(T, U, V*) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<bool>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastOp {
+ static const bool is_supported = false;
+ template <typename V>
+ static constexpr V Do(T, U) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<V>();
+ }
+};
+
+template <typename T>
+struct ClampedNegFastOp {
+ static const bool is_supported = false;
+ static constexpr T Do(T) {
+ // Force a compile failure if instantiated.
+ return CheckOnFailure::template HandleFailure<T>();
+ }
+};
+#endif // BASE_HAS_OPTIMIZED_SAFE_MATH
+#undef BASE_HAS_OPTIMIZED_SAFE_MATH
+
+// This is used for UnsignedAbs, where we need to support floating-point
+// template instantiations even though we don't actually support the operations.
+// However, there is no corresponding implementation of e.g. SafeUnsignedAbs,
+// so the float versions will not compile.
+template <typename Numeric,
+ bool IsInteger = std::is_integral<Numeric>::value,
+ bool IsFloat = std::is_floating_point<Numeric>::value>
+struct UnsignedOrFloatForSize;
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, true, false> {
+ using type = typename std::make_unsigned<Numeric>::type;
+};
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, false, true> {
+ using type = Numeric;
+};
+
+// Wrap the unary operations to allow SFINAE when instantiating integrals versus
+// floating points. These don't perform any overflow checking. Rather, they
+// exhibit well-defined overflow semantics and rely on the caller to detect
+// if an overflow occurred.
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T NegateWrapper(T value) {
+ using UnsignedT = typename std::make_unsigned<T>::type;
+ // This will compile to a NEG on Intel, and is normal negation on ARM.
+ return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value));
+}
+
+template <
+ typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T NegateWrapper(T value) {
+ return -value;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) {
+ return ~value;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T AbsWrapper(T value) {
+ return static_cast<T>(SafeUnsignedAbs(value));
+}
+
+template <
+ typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T AbsWrapper(T value) {
+ return value < 0 ? -value : value;
+}
+
+template <template <typename, typename, typename> class M,
+ typename L,
+ typename R>
+struct MathWrapper {
+ using math = M<typename UnderlyingType<L>::type,
+ typename UnderlyingType<R>::type,
+ void>;
+ using type = typename math::result_type;
+};
+
+// The following macros are just boilerplate for the standard arithmetic
+// operator overloads and variadic function templates. A macro isn't the nicest
+// solution, but it beats rewriting these over and over again.
+#define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME) \
+ template <typename L, typename R, typename... Args> \
+ constexpr auto CL_ABBR##OP_NAME(const L lhs, const R rhs, \
+ const Args... args) { \
+ return CL_ABBR##MathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, \
+ args...); \
+ }
+
+#define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \
+ /* Binary arithmetic operator for all CLASS##Numeric operations. */ \
+ template <typename L, typename R, \
+ typename std::enable_if<Is##CLASS##Op<L, R>::value>::type* = \
+ nullptr> \
+ constexpr CLASS##Numeric< \
+ typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type> \
+ operator OP(const L lhs, const R rhs) { \
+ return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs, \
+ rhs); \
+ } \
+ /* Assignment arithmetic operator implementation from CLASS##Numeric. */ \
+ template <typename L> \
+ template <typename R> \
+ constexpr CLASS##Numeric<L>& CLASS##Numeric<L>::operator CMP_OP( \
+ const R rhs) { \
+ return MathOp<CLASS##OP_NAME##Op>(rhs); \
+ } \
+ /* Variadic arithmetic functions that return CLASS##Numeric. */ \
+ BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
diff --git a/base/ranges/algorithm.h b/base/ranges/algorithm.h
index f7a23c4..70932a8 100644
--- a/base/ranges/algorithm.h
+++ b/base/ranges/algorithm.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,11 +13,11 @@
#include "polyfills/base/check.h"
#include "base/compiler_specific.h"
+#include "base/cxx20_is_constant_evaluated.h"
#include "base/functional/identity.h"
#include "base/functional/invoke.h"
#include "base/ranges/functional.h"
#include "base/ranges/ranges.h"
-#include "base/template_util.h"
namespace gurl_base {
diff --git a/base/ranges/functional.h b/base/ranges/functional.h
index e71abab..6557a19 100644
--- a/base/ranges/functional.h
+++ b/base/ranges/functional.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/ranges/ranges.h b/base/ranges/ranges.h
index 7eef2d6..f591c6c 100644
--- a/base/ranges/ranges.h
+++ b/base/ranges/ranges.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/stl_util.h b/base/stl_util.h
index a9c627d..74ce611 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -14,7 +14,6 @@
#include "polyfills/base/check.h"
#include "base/ranges/algorithm.h"
-#include "absl/types/optional.h"
namespace gurl_base {
@@ -175,25 +174,6 @@
const typename Collection::const_iterator end_;
};
-// Helper for returning the optional value's address, or nullptr.
-template <class T>
-T* OptionalOrNullptr(absl::optional<T>& optional) {
- return optional.has_value() ? &optional.value() : nullptr;
-}
-
-template <class T>
-const T* OptionalOrNullptr(const absl::optional<T>& optional) {
- return optional.has_value() ? &optional.value() : nullptr;
-}
-
-// Helper for creating an optional<T> from a potentially nullptr T*.
-template <class T>
-absl::optional<T> OptionalFromPtr(const T* value) {
- if (value)
- return absl::optional<T>(*value);
- return absl::nullopt;
-}
-
} // namespace base
#endif // BASE_STL_UTIL_H_
diff --git a/base/strings/abseil_string_conversions.cc b/base/strings/abseil_string_conversions.cc
index 5915b53..6a12c0c 100644
--- a/base/strings/abseil_string_conversions.cc
+++ b/base/strings/abseil_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/abseil_string_conversions.h b/base/strings/abseil_string_conversions.h
index 1cee63d..ffb0688 100644
--- a/base/strings/abseil_string_conversions.h
+++ b/base/strings/abseil_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/abseil_string_conversions_unittest.cc b/base/strings/abseil_string_conversions_unittest.cc
index 6c8816d..3744035 100644
--- a/base/strings/abseil_string_conversions_unittest.cc
+++ b/base/strings/abseil_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/abseil_string_number_conversions.cc b/base/strings/abseil_string_number_conversions.cc
index aab4905..cce321f 100644
--- a/base/strings/abseil_string_number_conversions.cc
+++ b/base/strings/abseil_string_number_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/abseil_string_number_conversions.h b/base/strings/abseil_string_number_conversions.h
index c709d34..2c26752 100644
--- a/base/strings/abseil_string_number_conversions.h
+++ b/base/strings/abseil_string_number_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/abseil_string_number_conversions_unittest.cc b/base/strings/abseil_string_number_conversions_unittest.cc
index 5873e79..77a06b1 100644
--- a/base/strings/abseil_string_number_conversions_unittest.cc
+++ b/base/strings/abseil_string_number_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/escape.cc b/base/strings/escape.cc
index 5cd770d..96657a3 100644
--- a/base/strings/escape.cc
+++ b/base/strings/escape.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/escape.h b/base/strings/escape.h
index 02203be..5ae4555 100644
--- a/base/strings/escape.h
+++ b/base/strings/escape.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/escape_unittest.cc b/base/strings/escape_unittest.cc
index 182e83f..ec37ed1 100644
--- a/base/strings/escape_unittest.cc
+++ b/base/strings/escape_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/latin1_string_conversions.cc b/base/strings/latin1_string_conversions.cc
index e4b4020..43f0dc0 100644
--- a/base/strings/latin1_string_conversions.cc
+++ b/base/strings/latin1_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/latin1_string_conversions.h b/base/strings/latin1_string_conversions.h
index 7b67073..83f8ef2 100644
--- a/base/strings/latin1_string_conversions.h
+++ b/base/strings/latin1_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/no_trigraphs_unittest.cc b/base/strings/no_trigraphs_unittest.cc
index 91fbda5..6641989 100644
--- a/base/strings/no_trigraphs_unittest.cc
+++ b/base/strings/no_trigraphs_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/pattern.cc b/base/strings/pattern.cc
index 607d6d5..23644e3 100644
--- a/base/strings/pattern.cc
+++ b/base/strings/pattern.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/pattern.h b/base/strings/pattern.h
index 3d280d0..52e25a2 100644
--- a/base/strings/pattern.h
+++ b/base/strings/pattern.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/pattern_unittest.cc b/base/strings/pattern_unittest.cc
index 20383e8..4797de6 100644
--- a/base/strings/pattern_unittest.cc
+++ b/base/strings/pattern_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc
index 26a7715..5071377 100644
--- a/base/strings/safe_sprintf.cc
+++ b/base/strings/safe_sprintf.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/safe_sprintf.h b/base/strings/safe_sprintf.h
index a5b242b..de4f06a 100644
--- a/base/strings/safe_sprintf.h
+++ b/base/strings/safe_sprintf.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc
index ad1cca2..bdcc2ff 100644
--- a/base/strings/safe_sprintf_unittest.cc
+++ b/base/strings/safe_sprintf_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/strcat.cc b/base/strings/strcat.cc
index c6b8faf..24b7e8d 100644
--- a/base/strings/strcat.cc
+++ b/base/strings/strcat.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
diff --git a/base/strings/strcat.h b/base/strings/strcat.h
index 1cdd708..386d542 100644
--- a/base/strings/strcat.h
+++ b/base/strings/strcat.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
diff --git a/base/strings/strcat_internal.h b/base/strings/strcat_internal.h
index 8011946..894aac9 100644
--- a/base/strings/strcat_internal.h
+++ b/base/strings/strcat_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/strcat_unittest.cc b/base/strings/strcat_unittest.cc
index d6a68d3..0c433c9 100644
--- a/base/strings/strcat_unittest.cc
+++ b/base/strings/strcat_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
diff --git a/base/strings/strcat_win.cc b/base/strings/strcat_win.cc
index affc99e..93cb2c8 100644
--- a/base/strings/strcat_win.cc
+++ b/base/strings/strcat_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/strcat_win.h b/base/strings/strcat_win.h
index e32a7e5..d9c00e9 100644
--- a/base/strings/strcat_win.h
+++ b/base/strings/strcat_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions.cc b/base/strings/string_number_conversions.cc
index 929b650..e7c692e 100644
--- a/base/strings/string_number_conversions.cc
+++ b/base/strings/string_number_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions.h b/base/strings/string_number_conversions.h
index 7d1b0b5..71d324e 100644
--- a/base/strings/string_number_conversions.h
+++ b/base/strings/string_number_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions_fuzzer.cc b/base/strings/string_number_conversions_fuzzer.cc
index e6e5c6f..cea3d3c 100644
--- a/base/strings/string_number_conversions_fuzzer.cc
+++ b/base/strings/string_number_conversions_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions_internal.h b/base/strings/string_number_conversions_internal.h
index 7c1804c..e505a81 100644
--- a/base/strings/string_number_conversions_internal.h
+++ b/base/strings/string_number_conversions_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -275,7 +275,7 @@
// - If the first character is a space, there was leading whitespace
return !input.empty() && output != HUGE_VAL && output != -HUGE_VAL &&
static_cast<size_t>(processed_characters_count) == input.size() &&
- !IsUnicodeWhitespace(input[0]);
+ !IsWhitespace(input[0]);
}
template <typename Char, typename OutIter>
diff --git a/base/strings/string_number_conversions_unittest.cc b/base/strings/string_number_conversions_unittest.cc
index 34f811e..349e2e4 100644
--- a/base/strings/string_number_conversions_unittest.cc
+++ b/base/strings/string_number_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions_win.cc b/base/strings/string_number_conversions_win.cc
index da67ca2..6e81b2f 100644
--- a/base/strings/string_number_conversions_win.cc
+++ b/base/strings/string_number_conversions_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_number_conversions_win.h b/base/strings/string_number_conversions_win.h
index d63d2d7..1d7e7a6 100644
--- a/base/strings/string_number_conversions_win.h
+++ b/base/strings/string_number_conversions_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc
index e76e6ad..e67aa17 100644
--- a/base/strings/string_piece.cc
+++ b/base/strings/string_piece.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h
index 68d6205..a1db548 100644
--- a/base/strings/string_piece.h
+++ b/base/strings/string_piece.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -33,7 +33,8 @@
#include "polyfills/base/check.h"
#include "polyfills/base/check_op.h"
#include "base/compiler_specific.h"
-#include "base/strings/string_piece_forward.h"
+#include "base/cxx20_is_constant_evaluated.h"
+#include "base/strings/string_piece_forward.h" // IWYU pragma: export
#include "build/build_config.h"
namespace gurl_base {
diff --git a/base/strings/string_piece_forward.h b/base/strings/string_piece_forward.h
index e257528..6c391b1 100644
--- a/base/strings/string_piece_forward.h
+++ b/base/strings/string_piece_forward.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
//
diff --git a/base/strings/string_piece_rust.h b/base/strings/string_piece_rust.h
index 1542c17..0d89aa4 100644
--- a/base/strings/string_piece_rust.h
+++ b/base/strings/string_piece_rust.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_piece_rust_unittest.cc b/base/strings/string_piece_rust_unittest.cc
index bf860fb..38d50d4 100644
--- a/base/strings/string_piece_rust_unittest.cc
+++ b/base/strings/string_piece_rust_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc
index c6b1f29..fb1be66 100644
--- a/base/strings/string_piece_unittest.cc
+++ b/base/strings/string_piece_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index 24b4a21..05d4101 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split.h b/base/strings/string_split.h
index b464f08..ca16457 100644
--- a/base/strings/string_split.h
+++ b/base/strings/string_split.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split_internal.h b/base/strings/string_split_internal.h
index 4430381..8228bd6 100644
--- a/base/strings/string_split_internal.h
+++ b/base/strings/string_split_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split_unittest.cc b/base/strings/string_split_unittest.cc
index 5bafec5..dc2bc3a 100644
--- a/base/strings/string_split_unittest.cc
+++ b/base/strings/string_split_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split_win.cc b/base/strings/string_split_win.cc
index 1327769..05c0541 100644
--- a/base/strings/string_split_win.cc
+++ b/base/strings/string_split_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_split_win.h b/base/strings/string_split_win.h
index 74efb5d..08b52b2 100644
--- a/base/strings/string_split_win.h
+++ b/base/strings/string_split_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_tokenizer.h b/base/strings/string_tokenizer.h
index e85bf45..62acf43 100644
--- a/base/strings/string_tokenizer.h
+++ b/base/strings/string_tokenizer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_tokenizer_fuzzer.cc b/base/strings/string_tokenizer_fuzzer.cc
index b3b046b..a0c0788 100644
--- a/base/strings/string_tokenizer_fuzzer.cc
+++ b/base/strings/string_tokenizer_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_tokenizer_unittest.cc b/base/strings/string_tokenizer_unittest.cc
index 9cca0c1..9a5e88e 100644
--- a/base/strings/string_tokenizer_unittest.cc
+++ b/base/strings/string_tokenizer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 8623096..482bb6e 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 282d4a8..56cf483 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -14,6 +14,7 @@
#include <algorithm>
#include <initializer_list>
+#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
@@ -110,6 +111,14 @@
return MakeBasicStringPiece<wchar_t>(begin, end);
}
+// Convert a type with defined `operator<<` into a string.
+template <typename... Streamable>
+std::string StreamableToString(const Streamable&... values) {
+ std::ostringstream ss;
+ (ss << ... << values);
+ return ss.str();
+}
+
// ASCII-specific tolower. The standard library's tolower is locale sensitive,
// so we don't want to use it here.
template <typename CharT,
@@ -376,7 +385,12 @@
// library versions will change based on locale).
template <typename Char>
inline bool IsAsciiWhitespace(Char c) {
- return c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\f';
+ // kWhitespaceASCII is a null-terminated string.
+ for (const char* cur = kWhitespaceASCII; *cur; ++cur) {
+ if (*cur == c)
+ return true;
+ }
+ return false;
}
template <typename Char>
inline bool IsAsciiAlpha(Char c) {
@@ -421,17 +435,33 @@
return HexDigitToInt(static_cast<char>(c));
}
-// Returns true if it's a Unicode whitespace character.
-template <typename Char>
+// Returns whether `c` is a Unicode whitespace character.
+// This cannot be used on eight-bit characters, since if they are ASCII you
+// should call IsAsciiWhitespace(), and if they are from a UTF-8 string they may
+// be individual units of a multi-unit code point. Convert to 16- or 32-bit
+// values known to hold the full code point before calling this.
+template <typename Char, typename = std::enable_if_t<(sizeof(Char) > 1)>>
inline bool IsUnicodeWhitespace(Char c) {
- // kWhitespaceWide is a NUL-terminated string
+ // kWhitespaceWide is a null-terminated string.
for (const auto* cur = kWhitespaceWide; *cur; ++cur) {
if (static_cast<typename std::make_unsigned_t<wchar_t>>(*cur) ==
static_cast<typename std::make_unsigned_t<Char>>(c))
return true;
}
return false;
-};
+}
+
+// DANGEROUS: Assumes ASCII or not base on the size of `Char`. You should
+// probably be explicitly calling IsUnicodeWhitespace() or IsAsciiWhitespace()
+// instead!
+template <typename Char>
+inline bool IsWhitespace(Char c) {
+ if constexpr (sizeof(Char) > 1) {
+ return IsUnicodeWhitespace(c);
+ } else {
+ return IsAsciiWhitespace(c);
+ }
+}
// Return a byte string in human-readable format with a unit suffix. Not
// appropriate for use in any UI; use of FormatBytes and friends in ui/base is
diff --git a/base/strings/string_util_constants.cc b/base/strings/string_util_constants.cc
index 198cd53..fece0af 100644
--- a/base/strings/string_util_constants.cc
+++ b/base/strings/string_util_constants.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h
index cc92e0d..1d6a41e 100644
--- a/base/strings/string_util_internal.h
+++ b/base/strings/string_util_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -149,7 +149,7 @@
size_t chars_written = 0;
for (auto c : text) {
- if (IsUnicodeWhitespace(c)) {
+ if (IsWhitespace(c)) {
if (!in_whitespace) {
// Reduce all whitespace sequences to a single space.
in_whitespace = true;
diff --git a/base/strings/string_util_perftest.cc b/base/strings/string_util_perftest.cc
index 8a5d540..879c74f 100644
--- a/base/strings/string_util_perftest.cc
+++ b/base/strings/string_util_perftest.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util_posix.h b/base/strings/string_util_posix.h
index 91cf7a6..49351f9 100644
--- a/base/strings/string_util_posix.h
+++ b/base/strings/string_util_posix.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index 4d2ac71..d4326c7 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -479,23 +479,26 @@
const bool trim;
const char* output;
} collapse_cases_ascii[] = {
- {" Google Video ", false, "Google Video"},
- {"Google Video", false, "Google Video"},
- {"", false, ""},
- {" ", false, ""},
- {"\t\rTest String\n", false, "Test String"},
- {" Test \n \t String ", false, "Test String"},
- {" Test String", false, "Test String"},
- {"Test String ", false, "Test String"},
- {"Test String", false, "Test String"},
- {"", true, ""},
- {"\n", true, ""},
- {" \r ", true, ""},
- {"\nFoo", true, "Foo"},
- {"\r Foo ", true, "Foo"},
- {" Foo bar ", true, "Foo bar"},
- {" \tFoo bar \n", true, "Foo bar"},
- {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
+ {" Google Video ", false, "Google Video"},
+ {"Google Video", false, "Google Video"},
+ {"", false, ""},
+ {" ", false, ""},
+ {"\t\rTest String\n", false, "Test String"},
+ {" Test \n \t String ", false, "Test String"},
+ {" Test String", false, "Test String"},
+ {"Test String ", false, "Test String"},
+ {"Test String", false, "Test String"},
+ {"", true, ""},
+ {"\n", true, ""},
+ {" \r ", true, ""},
+ {"\nFoo", true, "Foo"},
+ {"\r Foo ", true, "Foo"},
+ {" Foo bar ", true, "Foo bar"},
+ // \u00A0 is whitespace, but not _ASCII_ whitespace, so it should not be
+ // collapsed by CollapseWhitespaceASCII().
+ {"Foo\u00A0bar", true, "Foo\u00A0bar"},
+ {" \tFoo bar \n", true, "Foo bar"},
+ {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
};
TEST(StringUtilTest, CollapseWhitespaceASCII) {
@@ -1324,6 +1327,28 @@
EXPECT_TRUE(MakeWStringPiece(baz.end(), baz.end()).empty());
}
+enum class StreamableTestEnum { kGreeting, kLocation };
+
+std::ostream& operator<<(std::ostream& os, const StreamableTestEnum& value) {
+ switch (value) {
+ case StreamableTestEnum::kGreeting:
+ return os << "hello";
+ case StreamableTestEnum::kLocation:
+ return os << "world";
+ }
+}
+
+TEST(StringUtilTest, StreamableToString) {
+ EXPECT_EQ(StreamableToString("foo"), "foo");
+ EXPECT_EQ(StreamableToString(123), "123");
+ EXPECT_EQ(StreamableToString(StreamableTestEnum::kGreeting), "hello");
+ EXPECT_EQ(StreamableToString(StreamableTestEnum::kGreeting, " ",
+ StreamableTestEnum::kLocation),
+ "hello world");
+ EXPECT_EQ(StreamableToString("42 in hex is ", std::hex, 42),
+ "42 in hex is 2a");
+}
+
TEST(StringUtilTest, RemoveChars) {
const char kRemoveChars[] = "-/+*";
std::string input = "A-+bc/d!*";
diff --git a/base/strings/string_util_win.cc b/base/strings/string_util_win.cc
index 7ab9061..f8d0243 100644
--- a/base/strings/string_util_win.cc
+++ b/base/strings/string_util_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 6b5fba3..14f08fe 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/stringize_macros.h b/base/strings/stringize_macros.h
index d4e2707..355aee3 100644
--- a/base/strings/stringize_macros.h
+++ b/base/strings/stringize_macros.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
diff --git a/base/strings/stringize_macros_unittest.cc b/base/strings/stringize_macros_unittest.cc
index d7f9e56..c3c3479 100644
--- a/base/strings/stringize_macros_unittest.cc
+++ b/base/strings/stringize_macros_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc
index 8de48f3..9509aff 100644
--- a/base/strings/stringprintf.cc
+++ b/base/strings/stringprintf.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/stringprintf.h b/base/strings/stringprintf.h
index b0d473b..b393c93 100644
--- a/base/strings/stringprintf.h
+++ b/base/strings/stringprintf.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc
index 334d0ba..c137095 100644
--- a/base/strings/stringprintf_unittest.cc
+++ b/base/strings/stringprintf_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/sys_string_conversions.h b/base/strings/sys_string_conversions.h
index d80b178..37f5455 100644
--- a/base/strings/sys_string_conversions.h
+++ b/base/strings/sys_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/sys_string_conversions_posix.cc b/base/strings/sys_string_conversions_posix.cc
index 02535ed..3aab336 100644
--- a/base/strings/sys_string_conversions_posix.cc
+++ b/base/strings/sys_string_conversions_posix.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc
index 01bceb0..0e3dfa1 100644
--- a/base/strings/sys_string_conversions_unittest.cc
+++ b/base/strings/sys_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/sys_string_conversions_win.cc b/base/strings/sys_string_conversions_win.cc
index c0b4829..da19245 100644
--- a/base/strings/sys_string_conversions_win.cc
+++ b/base/strings/sys_string_conversions_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc
index b67b6a7..f893b89 100644
--- a/base/strings/utf_offset_string_conversions.cc
+++ b/base/strings/utf_offset_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_offset_string_conversions.h b/base/strings/utf_offset_string_conversions.h
index 3b2904d..03b2e7a 100644
--- a/base/strings/utf_offset_string_conversions.h
+++ b/base/strings/utf_offset_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc
index 83bbc35..1f3e6db 100644
--- a/base/strings/utf_offset_string_conversions_unittest.cc
+++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc
index ffeeb6c..162fa36 100644
--- a/base/strings/utf_string_conversion_utils.cc
+++ b/base/strings/utf_string_conversion_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright 2009 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversion_utils.h b/base/strings/utf_string_conversion_utils.h
index 8c209a2..f5ae5b1 100644
--- a/base/strings/utf_string_conversion_utils.h
+++ b/base/strings/utf_string_conversion_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc
index 683b339..383f1a3 100644
--- a/base/strings/utf_string_conversions.cc
+++ b/base/strings/utf_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversions.h b/base/strings/utf_string_conversions.h
index 77dc194..975d29d 100644
--- a/base/strings/utf_string_conversions.h
+++ b/base/strings/utf_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversions_fuzzer.cc b/base/strings/utf_string_conversions_fuzzer.cc
index 7bae707..3cc4521 100644
--- a/base/strings/utf_string_conversions_fuzzer.cc
+++ b/base/strings/utf_string_conversions_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc
index f738da4..cc35a12 100644
--- a/base/strings/utf_string_conversions_unittest.cc
+++ b/base/strings/utf_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/template_util.h b/base/template_util.h
index 17db620..1179a99 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -93,19 +93,6 @@
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
-// Implementation of C++20's std::is_constant_evaluated.
-//
-// References:
-// - https://en.cppreference.com/w/cpp/types/is_constant_evaluated
-// - https://wg21.link/meta.const.eval
-constexpr bool is_constant_evaluated() noexcept {
-#if HAS_BUILTIN(__builtin_is_constant_evaluated)
- return __builtin_is_constant_evaluated();
-#else
- return false;
-#endif
-}
-
// Simplified implementation of C++20's std::iter_value_t.
// As opposed to std::iter_value_t, this implementation does not restrict
// the type of `Iter` and does not consider specializations of
diff --git a/base/win/win_handle_types.h b/base/win/win_handle_types.h
index d71702c..503bf6f 100644
--- a/base/win/win_handle_types.h
+++ b/base/win/win_handle_types.h
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/win/win_handle_types_list.inc b/base/win/win_handle_types_list.inc
index b1dbef6..2241211 100644
--- a/base/win/win_handle_types_list.inc
+++ b/base/win/win_handle_types_list.inc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/build/build_config.h b/build/build_config.h
index 1914750..8f90f47 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/build/buildflag.h b/build/buildflag.h
index 5776a75..6346979 100644
--- a/build/buildflag.h
+++ b/build/buildflag.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/copy.bara.sky b/copy.bara.sky
index 7ecc7c8..f9d1a2a 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -20,6 +20,7 @@
"base/containers/util.h",
"base/cxx17_backports.h",
"base/cxx20_to_address.h",
+ "base/cxx20_is_constant_evaluated.h",
"base/debug/crash_logging.cc",
"base/debug/crash_logging.h",
"base/debug/leak_annotations.h",
@@ -27,8 +28,7 @@
"base/i18n/uchar.h",
"base/memory/raw_ptr.h",
"base/memory/raw_ptr_exclusion.h",
- "base/numerics/safe_conversions.h",
- "base/numerics/safe_conversions_impl.h",
+ "base/numerics/*.h",
"base/no_destructor.h",
"base/ranges/*.h",
"base/stl_util.h",
diff --git a/polyfills/base/allocator/buildflags.h b/polyfills/base/allocator/buildflags.h
index 54e240c..c5e46c4 100644
--- a/polyfills/base/allocator/buildflags.h
+++ b/polyfills/base/allocator/buildflags.h
@@ -14,5 +14,6 @@
#define BUILDFLAG_INTERNAL_NEVER_REMOVE_FROM_BRP_POOL_BLOCKLIST() (0)
#define BUILDFLAG_INTERNAL_USE_FAKE_BINARY_EXPERIMENT() (0)
#define BUILDFLAG_INTERNAL_RECORD_ALLOC_INFO() (0)
+#define BUILDFLAG_INTERNAL_FORCE_ENABLE_RAW_PTR_EXCLUSION() (0)
#endif // POLYFILLS_BASE_ALLOCATOR_BUILDFLAGS_H_
diff --git a/url/gurl.cc b/url/gurl.cc
index 1337666..6c0429e 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/gurl.h b/url/gurl.h
index 97a60ab..919ae5c 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/gurl_abstract_tests.h b/url/gurl_abstract_tests.h
index ffe9942..d787d3e 100644
--- a/url/gurl_abstract_tests.h
+++ b/url/gurl_abstract_tests.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/gurl_fuzzer.cc b/url/gurl_fuzzer.cc
index 0c3c101..170de8a 100644
--- a/url/gurl_fuzzer.cc
+++ b/url/gurl_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc
index 24e8f94..16e3a8e 100644
--- a/url/gurl_unittest.cc
+++ b/url/gurl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/origin.cc b/url/origin.cc
index b17591d..1b416a9 100644
--- a/url/origin.cc
+++ b/url/origin.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -331,9 +331,8 @@
pickle.WriteUInt64(0);
}
- gurl_base::span<const uint8_t> data(
- static_cast<const uint8_t*>(pickle.data()),
- static_cast<const uint8_t*>(pickle.data()) + pickle.size());
+ gurl_base::span<const uint8_t> data(static_cast<const uint8_t*>(pickle.data()),
+ pickle.size());
// Base64 encode the data to make it nicer to play with.
return gurl_base::Base64Encode(data);
}
diff --git a/url/origin.h b/url/origin.h
index 6769535..0d04628 100644
--- a/url/origin.h
+++ b/url/origin.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/origin_abstract_tests.cc b/url/origin_abstract_tests.cc
index 1619eae..d48a9f5 100644
--- a/url/origin_abstract_tests.cc
+++ b/url/origin_abstract_tests.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/origin_abstract_tests.h b/url/origin_abstract_tests.h
index 4aaf495..b89f63f 100644
--- a/url/origin_abstract_tests.h
+++ b/url/origin_abstract_tests.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc
index bd9ee7e..61500a6 100644
--- a/url/origin_unittest.cc
+++ b/url/origin_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/run_all_perftests.cc b/url/run_all_perftests.cc
index be7a746..47aeae2 100644
--- a/url/run_all_perftests.cc
+++ b/url/run_all_perftests.cc
@@ -1,4 +1,4 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc
index cf408d4..0e339bd 100644
--- a/url/run_all_unittests.cc
+++ b/url/run_all_unittests.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/scheme_host_port.cc b/url/scheme_host_port.cc
index 854c6f6..db23d39 100644
--- a/url/scheme_host_port.cc
+++ b/url/scheme_host_port.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/scheme_host_port.h b/url/scheme_host_port.h
index 70df243..88013dd 100644
--- a/url/scheme_host_port.h
+++ b/url/scheme_host_port.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/scheme_host_port_unittest.cc b/url/scheme_host_port_unittest.cc
index f49bd59..49bcf25 100644
--- a/url/scheme_host_port_unittest.cc
+++ b/url/scheme_host_port_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/third_party/mozilla/url_parse.h b/url/third_party/mozilla/url_parse.h
index c3535ba..2246d53 100644
--- a/url/third_party/mozilla/url_parse.h
+++ b/url/third_party/mozilla/url_parse.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon.cc b/url/url_canon.cc
index dce7847..003165b 100644
--- a/url/url_canon.cc
+++ b/url/url_canon.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
diff --git a/url/url_canon.h b/url/url_canon.h
index cab7d29..abeea84 100644
--- a/url/url_canon.h
+++ b/url/url_canon.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -11,6 +11,7 @@
#include "polyfills/base/component_export.h"
#include "polyfills/base/export_template.h"
#include "base/memory/raw_ptr_exclusion.h"
+#include "base/numerics/clamped_math.h"
#include "url/third_party/mozilla/url_parse.h"
namespace url {
@@ -28,42 +29,33 @@
template<typename T>
class CanonOutputT {
public:
- CanonOutputT() : buffer_(nullptr), buffer_len_(0), cur_len_(0) {}
- virtual ~CanonOutputT() {
- }
+ CanonOutputT() = default;
+ virtual ~CanonOutputT() = default;
// Implemented to resize the buffer. This function should update the buffer
// pointer to point to the new buffer, and any old data up to |cur_len_| in
// the buffer must be copied over.
//
// The new size |sz| must be larger than buffer_len_.
- virtual void Resize(int sz) = 0;
+ virtual void Resize(size_t sz) = 0;
// Accessor for returning a character at a given position. The input offset
// must be in the valid range.
- inline T at(int offset) const {
- return buffer_[offset];
- }
+ inline T at(size_t offset) const { return buffer_[offset]; }
// Sets the character at the given position. The given position MUST be less
// than the length().
- inline void set(int offset, T ch) {
- buffer_[offset] = ch;
- }
+ inline void set(size_t offset, T ch) { buffer_[offset] = ch; }
// Returns the number of characters currently in the buffer.
- inline int length() const {
- return cur_len_;
- }
+ inline size_t length() const { return cur_len_; }
// Returns the current capacity of the buffer. The length() is the number of
// characters that have been declared to be written, but the capacity() is
// the number that can be written without reallocation. If the caller must
// write many characters at once, it can make sure there is enough capacity,
// write the data, then use set_size() to declare the new length().
- int capacity() const {
- return buffer_len_;
- }
+ size_t capacity() const { return buffer_len_; }
// Called by the user of this class to get the output. The output will NOT
// be NULL-terminated. Call length() to get the
@@ -81,9 +73,7 @@
// to declare the new length.
//
// This MUST NOT be used to expand the size of the buffer beyond capacity().
- void set_length(int new_len) {
- cur_len_ = new_len;
- }
+ void set_length(size_t new_len) { cur_len_ = new_len; }
// This is the most performance critical function, since it is called for
// every character.
@@ -107,28 +97,28 @@
}
// Appends the given string to the output.
- void Append(const T* str, int str_len) {
- if (cur_len_ + str_len > buffer_len_) {
- if (!Grow(cur_len_ + str_len - buffer_len_))
+ void Append(const T* str, size_t str_len) {
+ if (str_len > buffer_len_ - cur_len_) {
+ if (!Grow(str_len - (buffer_len_ - cur_len_)))
return;
}
- for (int i = 0; i < str_len; i++)
+ for (size_t i = 0; i < str_len; i++)
buffer_[cur_len_ + i] = str[i];
cur_len_ += str_len;
}
- void ReserveSizeIfNeeded(int estimated_size) {
+ void ReserveSizeIfNeeded(size_t estimated_size) {
// Reserve a bit extra to account for escaped chars.
if (estimated_size > buffer_len_)
- Resize(estimated_size + 8);
+ Resize((gurl_base::ClampedNumeric<size_t>(estimated_size) + 8).RawValue());
}
protected:
// Grows the given buffer so that it can fit at least |min_additional|
// characters. Returns true if the buffer could be resized, false on OOM.
- bool Grow(int min_additional) {
- static const int kMinBufferLen = 16;
- int new_len = (buffer_len_ == 0) ? kMinBufferLen : buffer_len_;
+ bool Grow(size_t min_additional) {
+ static const size_t kMinBufferLen = 16;
+ size_t new_len = (buffer_len_ == 0) ? kMinBufferLen : buffer_len_;
do {
if (new_len >= (1 << 30)) // Prevent overflow below.
return false;
@@ -140,11 +130,11 @@
// `buffer_` is not a raw_ptr<...> for performance reasons (based on analysis
// of sampling profiler data).
- RAW_PTR_EXCLUSION T* buffer_;
- int buffer_len_;
+ RAW_PTR_EXCLUSION T* buffer_ = nullptr;
+ size_t buffer_len_ = 0;
// Used characters in the buffer.
- int cur_len_;
+ size_t cur_len_ = 0;
};
// Simple implementation of the CanonOutput using new[]. This class
@@ -162,7 +152,7 @@
delete[] this->buffer_;
}
- void Resize(int sz) override {
+ void Resize(size_t sz) override {
T* new_buf = new T[sz];
memcpy(new_buf, this->buffer_,
sizeof(T) * (this->cur_len_ < sz ? this->cur_len_ : sz));
diff --git a/url/url_canon_etc.cc b/url/url_canon_etc.cc
index c3ebddd..e54b843 100644
--- a/url/url_canon_etc.cc
+++ b/url/url_canon_etc.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_filesystemurl.cc b/url/url_canon_filesystemurl.cc
index b36198a..0472484 100644
--- a/url/url_canon_filesystemurl.cc
+++ b/url/url_canon_filesystemurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_fileurl.cc b/url/url_canon_fileurl.cc
index b0740a2..dae5c4c 100644
--- a/url/url_canon_fileurl.cc
+++ b/url/url_canon_fileurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_host.cc b/url/url_canon_host.cc
index edc9d67..d29f7ab 100644
--- a/url/url_canon_host.cc
+++ b/url/url_canon_host.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -69,7 +69,7 @@
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',kEsc,kEsc,kEsc, 0 , 0 };
// RFC1034 maximum FQDN length.
-constexpr int kMaxHostLength = 253;
+constexpr size_t kMaxHostLength = 253;
// Generous padding to account for the fact that UTS#46 normalization can cause
// a long string to actually shrink and fit within the 253 character RFC1034
@@ -77,11 +77,11 @@
// cases: An arbitrary number of characters (e.g. U+00AD SOFT HYPHEN) can be
// removed from the input by UTS#46 processing. However, this should be
// sufficient for all normally-encountered, non-abusive hostname strings.
-constexpr int kMaxHostBufferLength = kMaxHostLength*5;
+constexpr size_t kMaxHostBufferLength = kMaxHostLength * 5;
-const int kTempHostBufferLen = 1024;
-typedef RawCanonOutputT<char, kTempHostBufferLen> StackBuffer;
-typedef RawCanonOutputT<char16_t, kTempHostBufferLen> StackBufferW;
+constexpr size_t kTempHostBufferLen = 1024;
+using StackBuffer = RawCanonOutputT<char, kTempHostBufferLen>;
+using StackBufferW = RawCanonOutputT<char16_t, kTempHostBufferLen>;
// Scans a host name and fills in the output flags according to what we find.
// |has_non_ascii| will be true if there are any non-7-bit characters, and
@@ -201,8 +201,7 @@
// Now we check the ASCII output like a normal host. It will also handle
// unescaping. Although we unescaped everything before this function call, if
// somebody does %00 as fullwidth, ICU will convert this to ASCII.
- bool success = DoSimpleHost(wide_output.data(),
- static_cast<size_t>(wide_output.length()), output,
+ bool success = DoSimpleHost(wide_output.data(), wide_output.length(), output,
&has_non_ascii);
if (has_non_ascii) {
// ICU generated something that DoSimpleHost didn't think looked like
@@ -220,8 +219,7 @@
// ASCII isn't strictly necessary, but DoSimpleHost handles this case
// anyway so we handle it/
output->set_length(original_output_len);
- AppendInvalidNarrowString(wide_output.data(), 0,
- static_cast<size_t>(wide_output.length()),
+ AppendInvalidNarrowString(wide_output.data(), 0, wide_output.length(),
output);
return false;
}
@@ -238,7 +236,7 @@
CanonOutput* output) {
// Save the current position in the output. We may write stuff and rewind it
// below, so we need to know where to rewind to.
- int begin_length = output->length();
+ size_t begin_length = output->length();
// Points to the UTF-8 data we want to convert. This will either be the
// input or the unescaped version written to |*output| if necessary.
@@ -268,7 +266,7 @@
// Save the pointer into the data was just converted (it may be appended to
// other data in the output buffer).
utf8_source = &output->data()[begin_length];
- utf8_source_len = static_cast<size_t>(output->length() - begin_length);
+ utf8_source_len = output->length() - begin_length;
} else {
// We don't need to unescape, use input for IDNization later. (We know the
// input has non-ASCII, or the simple version would have been called
@@ -287,15 +285,14 @@
for (size_t i = 0; i < utf8_source_len; i++)
utf8.push_back(utf8_source[i]);
output->set_length(begin_length);
- AppendInvalidNarrowString(utf8.data(), 0,
- static_cast<size_t>(utf8.length()), output);
+ AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output);
return false;
}
output->set_length(begin_length);
// This will call DoSimpleHost which will do normal ASCII canonicalization
// and also check for IP addresses in the outpt.
- return DoIDNHost(utf16.data(), static_cast<size_t>(utf16.length()), output) &&
+ return DoIDNHost(utf16.data(), utf16.length(), output) &&
are_all_escaped_valid;
}
@@ -324,8 +321,8 @@
// Once we convert to UTF-8, we can use the 8-bit version of the complex
// host handling code above.
- return DoComplexHost(utf8.data(), static_cast<size_t>(utf8.length()),
- has_non_ascii, has_escaped, output);
+ return DoComplexHost(utf8.data(), utf8.length(), has_non_ascii, has_escaped,
+ output);
}
// No unescaping necessary, we can safely pass the input to ICU. This
diff --git a/url/url_canon_icu.cc b/url/url_canon_icu.cc
index 3a6b9be..20c31a8 100644
--- a/url/url_canon_icu.cc
+++ b/url/url_canon_icu.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_icu.h b/url/url_canon_icu.h
index b861f7a..9a35df1 100644
--- a/url/url_canon_icu.h
+++ b/url/url_canon_icu.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_icu_unittest.cc b/url/url_canon_icu_unittest.cc
index cb74f64..0ac0fcb 100644
--- a/url/url_canon_icu_unittest.cc
+++ b/url/url_canon_icu_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -92,7 +92,7 @@
RawCanonOutput<static_size> output;
converter.ConvertFromUTF16(input.c_str(), static_cast<int>(input.length()),
&output);
- EXPECT_EQ(input.length(), static_cast<size_t>(output.length()));
+ EXPECT_EQ(input.length(), output.length());
}
}
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc
index f6b4b03..eb24cee 100644
--- a/url/url_canon_internal.cc
+++ b/url/url_canon_internal.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h
index a41a771..58ae144 100644
--- a/url/url_canon_internal.h
+++ b/url/url_canon_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -101,7 +101,7 @@
extern const char kCharToHexLookup[8];
// Assumes the input is a valid hex digit! Call IsHexChar before using this.
-inline unsigned char HexCharToValue(unsigned char c) {
+inline int HexCharToValue(unsigned char c) {
return c - kCharToHexLookup[c / 0x20];
}
@@ -136,8 +136,8 @@
inline void AppendEscapedChar(UINCHAR ch,
CanonOutputT<OUTCHAR>* output) {
output->push_back('%');
- output->push_back(kHexCharLookup[(ch >> 4) & 0xf]);
- output->push_back(kHexCharLookup[ch & 0xf]);
+ output->push_back(static_cast<OUTCHAR>(kHexCharLookup[(ch >> 4) & 0xf]));
+ output->push_back(static_cast<OUTCHAR>(kHexCharLookup[ch & 0xf]));
}
// The character we'll substitute for undecodable or invalid characters.
@@ -331,7 +331,8 @@
}
// Valid escape sequence.
- *unescaped_value = (HexCharToValue(first) << 4) + HexCharToValue(second);
+ *unescaped_value = static_cast<unsigned char>((HexCharToValue(first) << 4) +
+ HexCharToValue(second));
*begin += 2;
return true;
}
@@ -418,11 +419,11 @@
// resolver as well, so we declare them here.
bool CanonicalizePartialPathInternal(const char* spec,
const Component& path,
- int path_begin_in_output,
+ size_t path_begin_in_output,
CanonOutput* output);
bool CanonicalizePartialPathInternal(const char16_t* spec,
const Component& path,
- int path_begin_in_output,
+ size_t path_begin_in_output,
CanonOutput* output);
// Find the position of a bona fide Windows drive letter in the given path. If
diff --git a/url/url_canon_internal_file.h b/url/url_canon_internal_file.h
index 3b0a81e..c5b40a1 100644
--- a/url/url_canon_internal_file.h
+++ b/url/url_canon_internal_file.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_ip.cc b/url/url_canon_ip.cc
index f0552b5..fde31f1 100644
--- a/url/url_canon_ip.cc
+++ b/url/url_canon_ip.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_ip.h b/url/url_canon_ip.h
index 4e85466..953be0a 100644
--- a/url/url_canon_ip.h
+++ b/url/url_canon_ip.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_mailtourl.cc b/url/url_canon_mailtourl.cc
index ff62bea..e48b642 100644
--- a/url/url_canon_mailtourl.cc
+++ b/url/url_canon_mailtourl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_path.cc b/url/url_canon_path.cc
index 32cb5f3..3480517 100644
--- a/url/url_canon_path.cc
+++ b/url/url_canon_path.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,6 +6,7 @@
#include "polyfills/base/check.h"
#include "polyfills/base/check_op.h"
+#include "absl/types/optional.h"
#include "url/url_canon.h"
#include "url/url_canon_internal.h"
#include "url/url_parse_internal.h"
@@ -150,19 +151,19 @@
// because it is run only on the canonical output.
//
// The output is guaranteed to end in a slash when this function completes.
-void BackUpToPreviousSlash(int path_begin_in_output,
- CanonOutput* output) {
- GURL_DCHECK(output->length() > 0);
+void BackUpToPreviousSlash(size_t path_begin_in_output, CanonOutput* output) {
+ GURL_CHECK(output->length() > 0);
+ GURL_CHECK(path_begin_in_output < output->length());
- int i = output->length() - 1;
+ size_t i = output->length() - 1;
GURL_DCHECK(output->at(i) == '/');
if (i == path_begin_in_output)
return; // We're at the first slash, nothing to do.
// Now back up (skipping the trailing slash) until we find another slash.
- i--;
- while (output->at(i) != '/' && i > path_begin_in_output)
- i--;
+ do {
+ --i;
+ } while (output->at(i) != '/' && i > path_begin_in_output);
// Now shrink the output to just include that last slash we found.
output->set_length(i + 1);
@@ -199,9 +200,9 @@
void CheckForNestedEscapes(const CHAR* spec,
size_t next_input_index,
size_t input_len,
- int last_invalid_percent_index,
+ size_t last_invalid_percent_index,
CanonOutput* output) {
- const int length = output->length();
+ const size_t length = output->length();
const char last_unescaped_char = output->at(length - 1);
// If |output| currently looks like "%c", we need to try appending the next
@@ -220,10 +221,9 @@
}
// Now output ends like "%cc". Try to unescape this.
- size_t begin = static_cast<size_t>(last_invalid_percent_index);
+ size_t begin = last_invalid_percent_index;
unsigned char temp;
- if (DecodeEscaped(output->data(), &begin,
- static_cast<size_t>(output->length()), &temp)) {
+ if (DecodeEscaped(output->data(), &begin, output->length(), &temp)) {
// New escape sequence found. Overwrite the characters following the '%'
// with "25", and push_back() the one or two characters that were following
// the '%' when we were called.
@@ -253,7 +253,7 @@
template <typename CHAR, typename UCHAR>
bool DoPartialPathInternal(const CHAR* spec,
const Component& path,
- int path_begin_in_output,
+ size_t path_begin_in_output,
CanonOutput* output) {
if (!path.is_nonempty())
return true;
@@ -263,11 +263,10 @@
// We use this variable to minimize the amount of work done when unescaping --
// we'll only call CheckForNestedEscapes() when this points at one of the last
// couple of characters in |output|.
- int last_invalid_percent_index = INT_MIN;
+ absl::optional<size_t> last_invalid_percent_index;
bool success = true;
for (size_t i = static_cast<size_t>(path.begin); i < end; i++) {
- GURL_DCHECK_LT(last_invalid_percent_index, output->length());
UCHAR uch = static_cast<UCHAR>(spec[i]);
if (sizeof(CHAR) > 1 && uch >= 0x80) {
// We only need to test wide input for having non-ASCII characters. For
@@ -307,7 +306,7 @@
case DIRECTORY_UP:
BackUpToPreviousSlash(path_begin_in_output, output);
if (last_invalid_percent_index >= output->length()) {
- last_invalid_percent_index = INT_MIN;
+ last_invalid_percent_index = absl::nullopt;
}
i += dotlen + consumed_len - 1;
break;
@@ -339,9 +338,12 @@
// '%' from a previously-detected invalid escape sequence, we
// might have an input string with problematic nested escape
// sequences; detect and fix them.
- if (last_invalid_percent_index >= (output->length() - 3)) {
+ if (last_invalid_percent_index.has_value() &&
+ ((last_invalid_percent_index.value() + 3) >=
+ output->length())) {
CheckForNestedEscapes(spec, i + 1, end,
- last_invalid_percent_index, output);
+ last_invalid_percent_index.value(),
+ output);
}
} else {
// Either this is an invalid escaped character, or it's a valid
@@ -455,7 +457,7 @@
bool CanonicalizePartialPathInternal(const char* spec,
const Component& path,
- int path_begin_in_output,
+ size_t path_begin_in_output,
CanonOutput* output) {
return DoPartialPathInternal<char, unsigned char>(
spec, path, path_begin_in_output, output);
@@ -463,7 +465,7 @@
bool CanonicalizePartialPathInternal(const char16_t* spec,
const Component& path,
- int path_begin_in_output,
+ size_t path_begin_in_output,
CanonOutput* output) {
return DoPartialPathInternal<char16_t, char16_t>(
spec, path, path_begin_in_output, output);
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc
index d8d65f3..85983a8 100644
--- a/url/url_canon_pathurl.cc
+++ b/url/url_canon_pathurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_query.cc b/url/url_canon_query.cc
index 53699c5..4beac7a 100644
--- a/url/url_canon_query.cc
+++ b/url/url_canon_query.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_relative.cc b/url/url_canon_relative.cc
index 309f596..80588fe 100644
--- a/url/url_canon_relative.cc
+++ b/url/url_canon_relative.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -355,7 +355,7 @@
// Relative path, replace the query, and reference. We take the
// original path with the file part stripped, and append the new path.
// The canonicalizer will take care of resolving ".." and "."
- int path_begin = output->length();
+ size_t path_begin = output->length();
CopyToLastSlash(base_url, base_path_begin, base_parsed.path.end(),
output);
success &= CanonicalizePartialPathInternal(relative_url, path, path_begin,
diff --git a/url/url_canon_stdstring.cc b/url/url_canon_stdstring.cc
index c81a0a9..60e2a26 100644
--- a/url/url_canon_stdstring.cc
+++ b/url/url_canon_stdstring.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,11 +6,10 @@
namespace url {
-StdStringCanonOutput::StdStringCanonOutput(std::string* str)
- : CanonOutput(), str_(str) {
- cur_len_ = static_cast<int>(str_->size()); // Append to existing data.
- buffer_ = str_->empty() ? NULL : &(*str_)[0];
- buffer_len_ = static_cast<int>(str_->size());
+StdStringCanonOutput::StdStringCanonOutput(std::string* str) : str_(str) {
+ cur_len_ = str_->size(); // Append to existing data.
+ buffer_ = str_->empty() ? nullptr : &(*str_)[0];
+ buffer_len_ = str_->size();
}
StdStringCanonOutput::~StdStringCanonOutput() {
@@ -22,9 +21,9 @@
buffer_len_ = cur_len_;
}
-void StdStringCanonOutput::Resize(int sz) {
+void StdStringCanonOutput::Resize(size_t sz) {
str_->resize(sz);
- buffer_ = str_->empty() ? NULL : &(*str_)[0];
+ buffer_ = str_->empty() ? nullptr : &(*str_)[0];
buffer_len_ = sz;
}
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index d8b94ec..c9e2a1b 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -46,7 +46,7 @@
// Must be called after writing has completed but before the string is used.
void Complete();
- void Resize(int sz) override;
+ void Resize(size_t sz) override;
protected:
// `str_` is not a raw_ptr<...> for performance reasons (based on analysis of
diff --git a/url/url_canon_stdurl.cc b/url/url_canon_stdurl.cc
index d7e4197..da18d42 100644
--- a/url/url_canon_stdurl.cc
+++ b/url/url_canon_stdurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc
index 4fa31ec..62a5c36 100644
--- a/url/url_canon_unittest.cc
+++ b/url/url_canon_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_constants.cc b/url/url_constants.cc
index ee21a27..aa8978b 100644
--- a/url/url_constants.cc
+++ b/url/url_constants.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_constants.h b/url/url_constants.h
index 9c72569..bbcdd40 100644
--- a/url/url_constants.h
+++ b/url/url_constants.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_file.h b/url/url_file.h
index c15c8f5..114c46f 100644
--- a/url/url_file.h
+++ b/url/url_file.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -17,6 +17,9 @@
inline bool IsWindowsDriveSeparator(char16_t ch) {
return ch == ':' || ch == '|';
}
+inline bool IsWindowsDriveSeparator(char ch) {
+ return IsWindowsDriveSeparator(static_cast<char16_t>(ch));
+}
// Returns the index of the next slash in the input after the given index, or
// spec_len if the end of the input is reached.
diff --git a/url/url_idna_ascii_only.cc b/url/url_idna_ascii_only.cc
index 55e8459..2a4f0d3 100644
--- a/url/url_idna_ascii_only.cc
+++ b/url/url_idna_ascii_only.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_idna_icu.cc b/url/url_idna_icu.cc
index 381d74e..356a1cd 100644
--- a/url/url_idna_icu.cc
+++ b/url/url_idna_icu.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_parse_file.cc b/url/url_parse_file.cc
index 77a622f..582f5d3 100644
--- a/url/url_parse_file.cc
+++ b/url/url_parse_file.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_parse_internal.h b/url/url_parse_internal.h
index 4e2527a..a73f13b 100644
--- a/url/url_parse_internal.h
+++ b/url/url_parse_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,12 +15,18 @@
inline bool IsURLSlash(char16_t ch) {
return ch == '/' || ch == '\\';
}
+inline bool IsURLSlash(char ch) {
+ return IsURLSlash(static_cast<char16_t>(ch));
+}
// Returns true if we should trim this character from the URL because it is a
// space or a control character.
inline bool ShouldTrimFromURL(char16_t ch) {
return ch <= ' ';
}
+inline bool ShouldTrimFromURL(char ch) {
+ return ShouldTrimFromURL(static_cast<char16_t>(ch));
+}
// Given an already-initialized begin index and length, this shrinks the range
// to eliminate "should-be-trimmed" characters. Note that the length does *not*
diff --git a/url/url_parse_perftest.cc b/url/url_parse_perftest.cc
index 82c7693..b9b85d9 100644
--- a/url/url_parse_perftest.cc
+++ b/url/url_parse_perftest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_parse_unittest.cc b/url/url_parse_unittest.cc
index 9a8bb57..f67a445 100644
--- a/url/url_parse_unittest.cc
+++ b/url/url_parse_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_test_utils.h b/url/url_test_utils.h
index bb75c74..e1be7fc 100644
--- a/url/url_test_utils.h
+++ b/url/url_test_utils.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_util.cc b/url/url_util.cc
index ac6ffd7..872e469 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -12,6 +12,7 @@
#include "polyfills/base/check_op.h"
#include "base/compiler_specific.h"
+#include "base/containers/contains.h"
#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "url/url_canon_internal.h"
@@ -522,10 +523,7 @@
GURL_DCHECK(strlen(new_scheme) > 0);
GURL_DCHECK(strlen(handler) > 0);
GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
- GURL_DCHECK(std::find_if(schemes->begin(), schemes->end(),
- [&new_scheme](const SchemeWithHandler& scheme) {
- return scheme.scheme == new_scheme;
- }) == schemes->end());
+ GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme, &SchemeWithHandler::scheme));
schemes->push_back({new_scheme, handler});
}
@@ -534,8 +532,7 @@
GURL_DCHECK(schemes);
GURL_DCHECK(strlen(new_scheme) > 0);
GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
- GURL_DCHECK(std::find(schemes->begin(), schemes->end(), new_scheme) ==
- schemes->end());
+ GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme));
schemes->push_back(new_scheme);
}
@@ -546,10 +543,7 @@
GURL_DCHECK(schemes);
GURL_DCHECK(strlen(new_scheme) > 0);
GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
- GURL_DCHECK(std::find_if(schemes->begin(), schemes->end(),
- [&new_scheme](const SchemeWithType& scheme) {
- return scheme.scheme == new_scheme;
- }) == schemes->end());
+ GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme, &SchemeWithType::scheme));
schemes->push_back({new_scheme, type});
}
@@ -878,10 +872,9 @@
int output_initial_length = output->length();
// Convert that 8-bit to UTF-16. It's not clear IE does this at all to
// JavaScript URLs, but Firefox and Safari do.
- size_t unescaped_length = static_cast<size_t>(unescaped_chars.length());
+ size_t unescaped_length = unescaped_chars.length();
for (size_t i = 0; i < unescaped_length; i++) {
- unsigned char uch =
- static_cast<unsigned char>(unescaped_chars.at(static_cast<int>(i)));
+ unsigned char uch = static_cast<unsigned char>(unescaped_chars.at(i));
if (uch < 0x80) {
// Non-UTF-8, just append directly
output->push_back(uch);
@@ -905,7 +898,7 @@
// copy all characters from the beginning to the end of the
// identified sequence.
output->set_length(output_initial_length);
- for (int j = 0; j < unescaped_chars.length(); ++j)
+ for (size_t j = 0; j < unescaped_chars.length(); ++j)
output->push_back(static_cast<unsigned char>(unescaped_chars.at(j)));
break;
}
diff --git a/url/url_util.h b/url/url_util.h
index e622130..b489362 100644
--- a/url/url_util.h
+++ b/url/url_util.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_util_internal.h b/url/url_util_internal.h
index b2730b6..fe2a4d9 100644
--- a/url/url_util_internal.h
+++ b/url/url_util_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index 53aab7d..098dc7c 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.