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.