Sync googleurl with the Chromium upstream Updates up to the version 62ea163d27b1472e3d4fb01cbef18529917c17da from Thu Jul 6 04:19:31 2023 +0000 Change-Id: I39a8b29812eff97ddc23525f261013a8882df1dd
diff --git a/AUTHORS b/AUTHORS index d4f7c9d..365f616 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -41,6 +41,7 @@ Adrià Vilanova Martínez <me@avm99963.com> Ahmed Elwasefi <a.m.elwasefi@gmail.com> Ahmet Emir Ercin <ahmetemiremir@gmail.com> +Aiden Grossman <aidengrossmanpso@gmail.com> Ajay Berwal <a.berwal@samsung.com> Ajay Berwal <ajay.berwal@samsung.com> Ajith Kumar V <ajith.v@samsung.com> @@ -116,6 +117,7 @@ Andrew Tulloch <andrew@tullo.ch> Andriy Rysin <arysin@gmail.com> Anish Patankar <anish.p@samsung.com> +Ankit Kiran <sahuankit453@gmail.com> Ankit Kumar <ankit2.kumar@samsung.com> Ankur Verma <ankur1.verma@samsung.com> Anna Henningsen <anna@addaleax.net> @@ -150,6 +152,7 @@ Arunprasad Rajkumar <ararunprasad@gmail.com> Arunprasad Rajkumar <arurajku@cisco.com> Arup Barua <arup.barua@samsung.com> +Aryan Kaushik <aryankaushik2023@gmail.com> Asami Doi <d0iasm.pub@gmail.com> Ashish Kumar Gupta <guptaag@amazon.com> Ashlin Joseph <ashlin.j@samsung.com> @@ -213,6 +216,7 @@ Calvin Watford <watfordcalvin@gmail.com> Cameron Gutman <aicommander@gmail.com> Camille Viot <viot.camille@outlook.com> +Can Liu <peter.can.liu@gmail.com> Carlos Santa <carlos.santa@intel.com> Catalin Badea <badea@adobe.com> Cathie Chen <cathiechen@tencent.com> @@ -249,7 +253,7 @@ Chris Tserng <tserng@amazon.com> Chris Vasselli <clindsay@gmail.com> Chris Ye <hawkoyates@gmail.com> -Christoph Durschang <christoph142@gmx.com> +Christoph Staengle <christoph142@gmx.com> Christophe Dumez <ch.dumez@samsung.com> Christopher Dale <chrelad@gmail.com> Chunbo Hua <chunbo.hua@intel.com> @@ -308,6 +312,7 @@ David Spellman <dspell@amazon.com> David Valachovic <adenflorian@gmail.com> Dax Kelson <dkelson@gurulabs.com> +Dean Leitersdorf <dean.leitersdorf@gmail.com> Debadree Chatterjee <debadree333@gmail.com> Debashish Samantaray <d.samantaray@samsung.com> Debug Wang <debugwang@tencent.com> @@ -322,7 +327,6 @@ Devlin Cronin <rdevlin.cronin@gmail.com> Dhi Aurrahman <dio@rockybars.com> Di Wu <meetwudi@gmail.com> -Di Zhang <dizhangg@chromium.org> Diana Suvorova <diana.suvorova@gmail.com> Diego Fernández Santos <agujaydedal@gmail.com> Diego Ferreiro Val <elfogris@gmail.com> @@ -474,6 +478,7 @@ Horia Olaru <horia.olaru@gmail.com> Horia Olaru <olaru@adobe.com> Hosung You <hosung.you@samsung.com> +Huai Wang <gkvjwa@gmail.com> Huapeng Li <huapengl@amazon.com> Huayong Xu <huayong.xu@samsung.com> Hung Ngo <ngotienhung195@gmail.com> @@ -481,6 +486,7 @@ Hui Wang <wanghui07050707@gmail.com> Hui Wang <wanghui210@huawei.com> Huiwon Jo <jhwon0415@gmail.com> +Hunseop Jeong <hs85jeong@gmail.com> Huy Duong <huy.duongdinh@gmail.com> Hwanseung Lee <hs1217.lee@gmail.com> Hwanseung Lee <hs1217.lee@samsung.com> @@ -504,6 +510,7 @@ Ibrar Ahmed <ibrar.ahmad@gmail.com> Ilia Demianenko <ilia.demianenko@gmail.com> Ilia K <ki.stfu@gmail.com> +Ilwoo Lee <ilwoo905.lee@samsung.com> Ilya Konstantinov <ilya.konstantinov@gmail.com> Imam Mohammad Bokhary <imam.bokhary@samsung.com> Imranur Rahman <i.rahman@samsung.com> @@ -675,6 +682,7 @@ Justin Ribeiro <justin@justinribeiro.com> Jüri Valdmann <juri.valdmann@qt.io> Juyoung Kim <chattank05@gmail.com> +Jing Peiyang <jingpeiyang@eswincomputing.com> Kai Jiang <jiangkai@gmail.com> Kai Köhne <kai.koehne@qt.io> Kai Uwe Broulik <kde@privat.broulik.de> @@ -700,6 +708,7 @@ Keita Suzuki <keitasuzuki.park@gmail.com> Keita Yoshimoto <y073k3@gmail.com> Keith Chen <keitchen@amazon.com> +Keith Cirkel <chromium@keithcirkel.co.uk> Kenneth Rohde Christiansen <kenneth.r.christiansen@intel.com> Kenneth Strickland <ken.strickland@gmail.com> Kenneth Zhou <knthzh@gmail.com> @@ -710,6 +719,7 @@ Kevin Gibbons <bakkot@gmail.com> Kevin Lee Helpingstine <sig11@reprehensible.net> Kevin M. McCormick <mckev@amazon.com> +Keyou <qqkillyou@gmail.com> Khasim Syed Mohammed <khasim.mohammed@linaro.org> Khem Raj <raj.khem@gmail.com> Kihong Kwon <kihong.kwon@samsung.com> @@ -853,6 +863,7 @@ Max Vujovic <mvujovic@adobe.com> Mayank Gupta <mayank.g1@samsung.com> Mayur Kankanwadi <mayurk.vk@samsung.com> +Mc Zeng <zengmcong@gmail.com> Md Abdullah Al Alamin <a.alamin.cse@gmail.com> Md. Hasanur Rashid <hasanur.r@samsung.com> Md Jobed Hossain <jobed.h@samsung.com> @@ -917,6 +928,7 @@ Nagarjuna Atluri <nagarjuna.a@samsung.com> Naiem Shaik <naiem.shaik@gmail.com> Naoki Takano <takano.naoki@gmail.com> +Naoto Ono <onoto1998@gmail.com> Nathan Mitchell <nathaniel.v.mitchell@gmail.com> Naveen Bobbili <naveenbobbili@motorola.com> Naveen Bobbili <qghc36@motorola.com> @@ -954,6 +966,7 @@ Parag Radke <nrqv63@motorola.com> Paritosh Kumar <paritosh.in@samsung.com> Patrasciuc Sorin Cristian <cristian.patrasciuc@gmail.com> +Patricija Cerkaite <cer.patricija@gmail.com> Patrick Chan <chanpatorikku@gmail.com> Patrick Kettner <patrickkettner@gmail.com> Patrick Riordan <patrickriordan177@gmail.com> @@ -1008,6 +1021,7 @@ Prashant Hiremath <prashhir@cisco.com> Prashant Nevase <prashant.n@samsung.com> Prashant Patil <prashant.patil@imgtec.com> +Pratham <prathamIN@proton.me> Praveen Akkiraju <praveen.anp@samsung.com> Preeti Nayak <preeti.nayak@samsung.com> Pritam Nikam <pritam.nikam@samsung.com> @@ -1053,6 +1067,7 @@ Richard Smith <happyercat@gmail.com> Rijubrata Bhaumik <rijubrata.bhaumik@intel.com> Riku Voipio <riku.voipio@linaro.org> +Ritesh Saharan <r.saharan@samsung.com> Rob Buis <rob.buis@samsung.com> Rob Wu <rob@robwu.nl> Robert Bear Travis <bear.travis@gmail.com> @@ -1091,6 +1106,7 @@ Ryuan Choi <ryuan.choi@samsung.com> Saikrishna Arcot <saiarcot895@gmail.com> Sajal Khandelwal <skhandelwa22@bloomberg.net> +Sajeesh Sidharthan <sajeesh.sidharthan@amd.corp-partner.google.com> Saksham Mittal <gotlouemail@gmail.com> Salvatore Iovene <salvatore.iovene@intel.com> Sam James <sam@gentoo.org> @@ -1182,7 +1198,6 @@ Simon La Macchia <smacchia@amazon.com> Siva Kumar Gunturi <siva.gunturi@samsung.com> Slava Aseev <nullptrnine@gmail.com> -Sohan Jyoti Ghosh <sohanjg@chromium.org> Sohom Datta <sohom.datta@learner.manipal.edu> Sohom Datta <dattasohom1@gmail.com> Song Fangzhen <songfangzhen@bytedance.com> @@ -1217,6 +1232,7 @@ Sundoo Kim <0xd00d00b@gmail.com> Suneel Kota <suneel.kota@samsung.com> Sungguk Lim <limasdf@gmail.com> +Sunghyeok Kang <sh0528.kang@samsung.com> Sungmann Cho <sungmann.cho@gmail.com> Sungmann Cho <sungmann.cho@navercorp.com> Sunil Ratnu <sunil.ratnu@samsung.com> @@ -1252,6 +1268,7 @@ Takeshi Kurosawa <taken.spc@gmail.com> Tanay Chowdhury <tanay.c@samsung.com> Tanvir Rizvi <tanvir.rizvi@samsung.com> +Tao Wang <tao.wang.2261@gmail.com> Tapu Kumar Ghose <ghose.tapu@gmail.com> Taylor Price <trprice@gmail.com> Ted Kim <neot0000@gmail.com> @@ -1267,6 +1284,7 @@ Tiago Vignatti <tiago.vignatti@intel.com> Tibor Dusnoki <tibor.dusnoki.91@gmail.com> Tibor Dusnoki <tdusnoki@inf.u-szeged.hu> +Tien Hock Loh <tienhock.loh@starfivetech.com> Tim Ansell <mithro@mithis.com> Tim Niederhausen <tim@rnc-ag.de> Tim Steiner <twsteiner@gmail.com> @@ -1281,6 +1299,7 @@ Tom Callaway <tcallawa@redhat.com> Tom Harwood <tfh@skip.org> Tomas Popela <tomas.popela@gmail.com> +Tony Shen <legendmastertony@gmail.com> Torsten Kurbad <google@tk-webart.de> Toshihito Kikuchi <leamovret@gmail.com> Toshiaki Tanaka <zokutyou2@gmail.com> @@ -1322,6 +1341,8 @@ Waihung Fu <fufranci@amazon.com> wafuwafu13 <mariobaske@i.softbank.jp> Wojciech Bielawski <wojciech.bielawski@gmail.com> +Wang Chen <wangchen20@iscas.ac.cn> +Wang Chen <unicornxw@gmail.com> Wang Weiwei <wangww@dingdao.com> Wangyang Dai <jludwy@gmail.com> Wanming Lin <wanming.lin@intel.com> @@ -1332,6 +1353,7 @@ Wesley Lancel <wesleylancel@gmail.com> Wei Wang <wei4.wang@intel.com> Wei Wen <wenwei.wenwei@bytedance.com> +Weidong Liu <liuwd8@gmail.com> Wesley Wigham <wwigham@gmail.com> Will Cohen <wwcohen@gmail.com> Will Hirsch <chromium@willhirsch.co.uk> @@ -1355,6 +1377,7 @@ Xu Samuel <samuel.xu@intel.com> Xu Xing <xing.xu@intel.com> Xuefei Ren <xrenishere@gmail.com> +Xuefu Zhang <xuefu.sh@gmail.com> Xuehui Xie <xuehui.xxh@alibaba-inc.com> Xueqing Huang <huangxueqing@xiaomi.com> Xun Sun <xun.sun@intel.com> @@ -1364,6 +1387,7 @@ Yan Wang <yan0422.wang@samsung.com> Yang Gu <yang.gu@intel.com> Yang Liu <jd9668954@gmail.com> +Yannay Hammer <yannayha@gmail.com> Yannic Bonenberger <yannic.bonenberger@gmail.com> Yarin Kaul <yarin.kaul@gmail.com> Yash Joshi <yashjoshimail@gmail.com> @@ -1417,6 +1441,7 @@ Zachary Capalbo <zach.geek@gmail.com> Zeno Albisser <zeno.albisser@digia.com> Zeqin Chen <talonchen@tencent.com> +Zhanbang He <hezhanbang@gmail.com> Zhang Hao <zhanghao.m@bytedance.com> Zhang Hao <15686357310a@gmail.com> Zhaoming Jiang <zhaoming.jiang@intel.com> @@ -1437,6 +1462,7 @@ Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> Zoltan Kuscsik <zoltan.kuscsik@linaro.org> Zoru Lee <donzoru@gmail.com> +Zuckjet <zuckjet@gmail.com> Zsolt Borbely <zsborbely.u-szeged@partner.samsung.com> 方觉 (Fang Jue) <fangjue23303@gmail.com> 迷渡 <justjavac@gmail.com> @@ -1457,18 +1483,15 @@ Code Aurora Forum <*@codeaurora.org> CodeWeavers, Inc. <*@codeweavers.com> Collabora Limited <*@collabora.com> -Comodo CA Limited -CoSMo Software pvt ltd <*@cosmosoftware.io> +Comodo CA Limited CoSMo Software pvt ltd <*@cosmosoftware.io> Cosium <*@cosium.com> Dell Technologies Inc. <*@dell.corp-partner.google.com> Ding (Beijing) Intelligent Technology Co. Ltd <*@dingdao.com> +Dropbox, Inc. <*@dropbox.com> Duck Duck Go, Inc. <*@duckduckgo.com> Endless Mobile, Inc. <*@endlessm.com> EngFlow, Inc. <*@engflow.com> Estimote, Inc. <*@estimote.com> -Meta Platforms, Inc. <*@fb.com> -Meta Platforms, Inc. <*@meta.com> -Meta Platforms, Inc. <*@oculus.com> Google Inc. <*@google.com> Grammarly, Inc. <*@grammarly.com> Hewlett-Packard Development Company, L.P. <*@hp.com> @@ -1479,13 +1502,16 @@ Imagination Technologies Limited <*@imagination.corp-partner.google.com> Impossible Dreams Network <*@impossibledreams.net> Intel Corporation <*@intel.com> +Island Technology, Inc. <*@island.io> LG Electronics, Inc. <*@lge.com> Loongson Technology Corporation Limited. <*@loongson.cn> Macadamian <*@macadamian.com> Mail.ru Group <*@corp.mail.ru> Make Positive Provar Limited <*@provartesting.com> -Mc Zeng <zengmcong@gmail.com> Mediatek <*@mediatek.com> +Meta Platforms, Inc. <*@fb.com> +Meta Platforms, Inc. <*@meta.com> +Meta Platforms, Inc. <*@oculus.com> Microsoft <*@microsoft.com> MIPS Technologies, Inc. <*@mips.com> Mobica Limited <*@mobica.com> @@ -1502,7 +1528,6 @@ Rakuten Kobo Inc. <*@kobo.com> Rakuten Kobo Inc. <*@rakuten.com> Red Hat Inc. <*@redhat.com> -Sajeesh Sidharthan <sajeesh.sidharthan@amd.corp-partner.google.com> Semihalf <*@semihalf.com> Seznam.cz, a.s. <*@firma.seznam.cz> Slack Technologies Inc. <*@slack-corp.com> @@ -1515,9 +1540,7 @@ 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> +Torchmobile Inc. Upwork <*@cloud.upwork.com> Venture 3 Systems LLC <*@venture3systems.com> Vewd Software AS <*@vewd.com> Vivaldi Technologies AS <*@vivaldi.com> @@ -1525,6 +1548,5 @@ Whist Technologies <*@whist.com> Xperi Corporation <*@xperi.com> Yandex LLC <*@yandex-team.ru> -Zuckjet <zuckjet@gmail.com> # Please DO NOT APPEND here. See comments at the top of the file. # END organizations section.
diff --git a/base/BUILD b/base/BUILD index 5f36123..1d1efd2 100644 --- a/base/BUILD +++ b/base/BUILD
@@ -8,11 +8,11 @@ name = "base", srcs = [ "debug/crash_logging.cc", - "strings/string_piece.cc", "strings/string_util.cc", "strings/string_util_constants.cc", "strings/utf_string_conversion_utils.cc", "strings/utf_string_conversions.cc", + "strings/utf_ostream_operators.cc", ] + select({ "//build_config:windows_x86_64": ["strings/string_util_win.cc"], "//conditions:default": [], @@ -25,7 +25,6 @@ "containers/contiguous_iterator.h", "containers/span.h", "containers/util.h", - "cxx17_backports.h", "cxx20_is_constant_evaluated.h", "cxx20_to_address.h", "debug/crash_logging.h", @@ -51,6 +50,7 @@ "ranges/ranges.h", "stl_util.h", "template_util.h", + "types/always_false.h", "strings/string_piece_forward.h", "strings/string_piece.h", "strings/string_util.h", @@ -58,6 +58,7 @@ "strings/string_util_internal.h", "strings/string_number_conversions.h", "strings/utf_string_conversions.h", + "strings/utf_ostream_operators.h", "strings/utf_string_conversion_utils.h", "win/win_handle_types.h", ] + build_config.strings_hdrs,
diff --git a/base/bits.h b/base/bits.h index ea011ad..3f1541a 100644 --- a/base/bits.h +++ b/base/bits.h
@@ -7,7 +7,6 @@ #ifndef BASE_BITS_H_ #define BASE_BITS_H_ -#include <limits.h> #include <stddef.h> #include <stdint.h> @@ -134,7 +133,7 @@ static_assert(std::is_integral<T>::value, "This function can only be used with integral types."); T one(1u); - return one << ((CHAR_BIT * sizeof(T) - 1)); + return one << (8 * sizeof(T) - 1); } } // namespace bits
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index b2d4024..e85da5c 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -414,4 +414,25 @@ #define LOGICALLY_CONST #endif +// preserve_most clang's calling convention. Reduces register pressure for the +// caller and as such can be used for cold calls. Support for the +// "preserve_most" attribute is limited: +// - 32-bit platforms do not implement it, +// - component builds fail because _dl_runtime_resolve() clobbers registers, +// - there are crashes on arm64 on Windows (https://crbug.com/v8/14065), which +// can hopefully be fixed in the future. +// Additionally, the initial implementation in clang <= 16 overwrote the return +// register(s) in the epilogue of a preserve_most function, so we only use +// preserve_most in clang >= 17 (see https://reviews.llvm.org/D143425). +// See https://clang.llvm.org/docs/AttributeReference.html#preserve-most for +// more details. +#if defined(ARCH_CPU_64_BITS) && \ + !(BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)) && \ + !defined(COMPONENT_BUILD) && defined(__clang__) && \ + __clang_major__ >= 17 && HAS_ATTRIBUTE(preserve_most) +#define PRESERVE_MOST __attribute__((preserve_most)) +#else +#define PRESERVE_MOST +#endif + #endif // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h index 0cd2832..18f1006 100644 --- a/base/containers/checked_iterators.h +++ b/base/containers/checked_iterators.h
@@ -24,6 +24,9 @@ using pointer = T*; using reference = T&; using iterator_category = std::random_access_iterator_tag; +#if defined(__cpp_lib_ranges) + using iterator_concept = std::contiguous_iterator_tag; +#endif // Required for converting constructor below. template <typename U> @@ -31,10 +34,8 @@ // Required for certain libc++ algorithm optimizations that are not available // for NaCl. -#if defined(_LIBCPP_VERSION) && !BUILDFLAG(IS_NACL) template <typename Ptr> friend struct std::pointer_traits; -#endif constexpr CheckedContiguousIterator() = default; @@ -147,6 +148,12 @@ return it; } + constexpr friend CheckedContiguousIterator operator+( + difference_type lhs, + const CheckedContiguousIterator& rhs) { + return rhs + lhs; + } + constexpr CheckedContiguousIterator& operator-=(difference_type rhs) { if (rhs < 0) { GURL_CHECK_LE(-rhs, end_ - current_); @@ -224,7 +231,6 @@ } // namespace base -#if defined(_LIBCPP_VERSION) && !BUILDFLAG(IS_NACL) // Specialize both std::__is_cpp17_contiguous_iterator and std::pointer_traits // for CCI in case we compile with libc++ outside of NaCl. The former is // required to enable certain algorithm optimizations (e.g. std::copy can be a @@ -242,13 +248,35 @@ // [1] https://wg21.link/iterator.concept.contiguous // [2] https://wg21.link/std.iterator.tags // [3] https://wg21.link/pointer.traits.optmem -namespace std { +#if defined(_LIBCPP_VERSION) + +// TODO(crbug.com/1284275): Remove when C++20 is on by default, as the use +// of `iterator_concept` above should suffice. +_LIBCPP_BEGIN_NAMESPACE_STD + +// TODO(crbug.com/1449299): https://reviews.llvm.org/D150801 renamed this from +// `__is_cpp17_contiguous_iterator` to `__libcpp_is_contiguous_iterator`. Clean +// up the old spelling after libc++ rolls. +template <typename T> +struct __is_cpp17_contiguous_iterator; template <typename T> struct __is_cpp17_contiguous_iterator<::gurl_base::CheckedContiguousIterator<T>> : true_type {}; template <typename T> +struct __libcpp_is_contiguous_iterator; +template <typename T> +struct __libcpp_is_contiguous_iterator<::gurl_base::CheckedContiguousIterator<T>> + : true_type {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif + +namespace std { + +template <typename T> struct pointer_traits<::gurl_base::CheckedContiguousIterator<T>> { using pointer = ::gurl_base::CheckedContiguousIterator<T>; using element_type = T; @@ -267,6 +295,5 @@ }; } // namespace std -#endif #endif // BASE_CONTAINERS_CHECKED_ITERATORS_H_
diff --git a/base/containers/span.h b/base/containers/span.h index 578f3b6..a218045 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -19,6 +19,7 @@ #include "base/containers/checked_iterators.h" #include "base/containers/contiguous_iterator.h" #include "base/cxx20_to_address.h" +#include "polyfills/base/memory/raw_ptr_exclusion.h" #include "base/numerics/safe_math.h" namespace gurl_base { @@ -452,7 +453,9 @@ } private: - T* data_; + // This field is not a raw_ptr<> because it was filtered by the rewriter + // for: #constexpr-ctor-field-initializer, #global-scope, #union + RAW_PTR_EXCLUSION T* data_; }; // span<T, Extent>::extent can not be declared inline prior to C++17, hence this
diff --git a/base/cxx17_backports.h b/base/cxx17_backports.h deleted file mode 100644 index a784f84..0000000 --- a/base/cxx17_backports.h +++ /dev/null
@@ -1,18 +0,0 @@ -// 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_CXX17_BACKPORTS_H_ -#define BASE_CXX17_BACKPORTS_H_ - -#include <algorithm> - -namespace gurl_base { - -// TODO(crbug.com/1373621): Rewrite all uses of gurl_base::clamp as std::clamp and -// remove this file. -using std::clamp; - -} // namespace base - -#endif // BASE_CXX17_BACKPORTS_H_
diff --git a/base/numerics/math_constants.h b/base/numerics/math_constants.h index c406ab9..2819606 100644 --- a/base/numerics/math_constants.h +++ b/base/numerics/math_constants.h
@@ -10,6 +10,18 @@ constexpr double kPiDouble = 3.14159265358979323846; constexpr float kPiFloat = 3.14159265358979323846f; +// pi/180 and 180/pi. These are correctly rounded from the true +// mathematical value, unlike what you'd get from e.g. +// 180.0f / kPiFloat. +constexpr double kDegToRadDouble = 0.017453292519943295769; +constexpr float kDegToRadFloat = 0.017453292519943295769f; +constexpr double kRadToDegDouble = 57.295779513082320876798; +constexpr float kRadToDegFloat = 57.295779513082320876798f; + +// sqrt(1/2) = 1/sqrt(2). +constexpr double kSqrtHalfDouble = 0.70710678118654752440; +constexpr float kSqrtHalfFloat = 0.70710678118654752440f; + // The mean acceleration due to gravity on Earth in m/s^2. constexpr double kMeanGravityDouble = 9.80665; constexpr float kMeanGravityFloat = 9.80665f;
diff --git a/base/ranges/algorithm.h b/base/ranges/algorithm.h index 70932a8..fe09c74 100644 --- a/base/ranges/algorithm.h +++ b/base/ranges/algorithm.h
@@ -16,6 +16,7 @@ #include "base/cxx20_is_constant_evaluated.h" #include "base/functional/identity.h" #include "base/functional/invoke.h" +#include "polyfills/base/memory/raw_ptr_exclusion.h" #include "base/ranges/functional.h" #include "base/ranges/ranges.h" @@ -108,9 +109,15 @@ } private: - Pred& pred_; - Proj1& proj1_; - Proj2& proj2_; + // This field is not a raw_ref<> because it was filtered by the rewriter for: + // #constexpr-ctor-field-initializer + RAW_PTR_EXCLUSION Pred& pred_; + // This field is not a raw_ref<> because it was filtered by the rewriter for: + // #constexpr-ctor-field-initializer + RAW_PTR_EXCLUSION Proj1& proj1_; + // This field is not a raw_ref<> because it was filtered by the rewriter for: + // #constexpr-ctor-field-initializer + RAW_PTR_EXCLUSION Proj2& proj2_; }; // Small wrappers around BinaryPredicateProjector to make the calling side more
diff --git a/base/strings/string_number_conversions_internal.h b/base/strings/string_number_conversions_internal.h index e505a81..6649046 100644 --- a/base/strings/string_number_conversions_internal.h +++ b/base/strings/string_number_conversions_internal.h
@@ -5,10 +5,8 @@ #ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_INTERNAL_H_ #define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_INTERNAL_H_ -#include <ctype.h> #include <errno.h> #include <stdlib.h> -#include <wctype.h> #include <limits> @@ -72,32 +70,6 @@ return absl::nullopt; } -// There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it -// is locale independent, whereas the functions we are replacing were -// locale-dependent. TBD what is desired, but for the moment let's not -// introduce a change in behaviour. -template <typename CHAR> -class WhitespaceHelper {}; - -template <> -class WhitespaceHelper<char> { - public: - static bool Invoke(char c) { - return 0 != isspace(static_cast<unsigned char>(c)); - } -}; - -template <> -class WhitespaceHelper<char16_t> { - public: - static bool Invoke(char16_t c) { return 0 != iswspace(c); } -}; - -template <typename CHAR> -bool LocalIsWhitespace(CHAR c) { - return WhitespaceHelper<CHAR>::Invoke(c); -} - template <typename Number, int kBase> class StringToNumberParser { public: @@ -188,7 +160,7 @@ auto begin = input.begin(); auto end = input.end(); - while (begin != end && LocalIsWhitespace(*begin)) { + while (begin != end && IsAsciiWhitespace(*begin)) { has_leading_whitespace = true; ++begin; } @@ -272,7 +244,11 @@ // - If the entire string was not processed, there are either characters // remaining in the string after a parsed number, or the string does not // begin with a parseable number. - // - If the first character is a space, there was leading whitespace + // - If the first character is a space, there was leading whitespace. Note + // that this checks using IsWhitespace(), which behaves differently for + // wide and narrow characters -- that is intentional and matches the + // behavior of the double_conversion library's whitespace-skipping + // algorithm. return !input.empty() && output != HUGE_VAL && output != -HUGE_VAL && static_cast<size_t>(processed_characters_count) == input.size() && !IsWhitespace(input[0]);
diff --git a/base/strings/string_number_conversions_win.cc b/base/strings/string_number_conversions_win.cc index 6e81b2f..9857dd4 100644 --- a/base/strings/string_number_conversions_win.cc +++ b/base/strings/string_number_conversions_win.cc
@@ -39,16 +39,6 @@ return internal::DoubleToStringT<std::wstring>(value); } -namespace internal { - -template <> -class WhitespaceHelper<wchar_t> { - public: - static bool Invoke(wchar_t c) { return 0 != iswspace(c); } -}; - -} // namespace internal - bool StringToInt(WStringPiece input, int* output) { return internal::StringToIntImpl(input, *output); }
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc deleted file mode 100644 index e67aa17..0000000 --- a/base/strings/string_piece.cc +++ /dev/null
@@ -1,301 +0,0 @@ -// 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. - -#include "base/strings/string_piece.h" - -#include <algorithm> -#include <climits> -#include <limits> -#include <ostream> -#include <string> - -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" - -namespace gurl_base { -namespace { - -// For each character in characters_wanted, sets the index corresponding -// to the ASCII code of that character to 1 in table. This is used by -// the find_.*_of methods below to tell whether or not a character is in -// the lookup table in constant time. -// The argument `table' must be an array that is large enough to hold all -// the possible values of an unsigned char. Thus it should be be declared -// as follows: -// bool table[UCHAR_MAX + 1] -inline void BuildLookupTable(StringPiece characters_wanted, bool* table) { - const size_t length = characters_wanted.length(); - const char* const data = characters_wanted.data(); - for (size_t i = 0; i < length; ++i) { - table[static_cast<unsigned char>(data[i])] = true; - } -} - -} // namespace - -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) -template class BasicStringPiece<char>; -template class BasicStringPiece<char16_t>; -template class BasicStringPiece<wchar_t>; -#endif - -std::ostream& operator<<(std::ostream& o, StringPiece piece) { - o.write(piece.data(), static_cast<std::streamsize>(piece.size())); - return o; -} - -std::ostream& operator<<(std::ostream& o, StringPiece16 piece) { - return o << UTF16ToUTF8(piece); -} - -std::ostream& operator<<(std::ostream& o, WStringPiece piece) { - return o << WideToUTF8(piece); -} - -namespace internal { - -template <typename T, typename CharT = typename T::value_type> -size_t findT(T self, T s, size_t pos) { - if (pos > self.size()) - return BasicStringPiece<CharT>::npos; - - typename BasicStringPiece<CharT>::const_iterator result = - std::search(self.begin() + pos, self.end(), s.begin(), s.end()); - const size_t xpos = - static_cast<size_t>(result - self.begin()); - return xpos + s.size() <= self.size() ? xpos : BasicStringPiece<CharT>::npos; -} - -size_t find(StringPiece self, StringPiece s, size_t pos) { - return findT(self, s, pos); -} - -size_t find(StringPiece16 self, StringPiece16 s, size_t pos) { - return findT(self, s, pos); -} - -template <typename T, typename CharT = typename T::value_type> -size_t rfindT(T self, T s, size_t pos) { - if (self.size() < s.size()) - return BasicStringPiece<CharT>::npos; - - if (s.empty()) - return std::min(self.size(), pos); - - typename BasicStringPiece<CharT>::const_iterator last = - self.begin() + std::min(self.size() - s.size(), pos) + s.size(); - typename BasicStringPiece<CharT>::const_iterator result = - std::find_end(self.begin(), last, s.begin(), s.end()); - return result != last ? static_cast<size_t>(result - self.begin()) - : BasicStringPiece<CharT>::npos; -} - -size_t rfind(StringPiece self, StringPiece s, size_t pos) { - return rfindT(self, s, pos); -} - -size_t rfind(StringPiece16 self, StringPiece16 s, size_t pos) { - return rfindT(self, s, pos); -} - -// 8-bit version using lookup table. -size_t find_first_of(StringPiece self, StringPiece s, size_t pos) { - if (self.size() == 0 || s.size() == 0) - return StringPiece::npos; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return self.find(s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = pos; i < self.size(); ++i) { - if (lookup[static_cast<unsigned char>(self.data()[i])]) { - return i; - } - } - return StringPiece::npos; -} - -// Generic brute force version. -template <typename T, typename CharT = typename T::value_type> -size_t find_first_ofT(T self, T s, size_t pos) { - // Use the faster std::find() if searching for a single character. - typename BasicStringPiece<CharT>::const_iterator found = - s.size() == 1 ? std::find(self.begin() + pos, self.end(), s[0]) - : std::find_first_of(self.begin() + pos, self.end(), - s.begin(), s.end()); - if (found == self.end()) - return BasicStringPiece<CharT>::npos; - return static_cast<size_t>(found - self.begin()); -} - -size_t find_first_of(StringPiece16 self, StringPiece16 s, size_t pos) { - return find_first_ofT(self, s, pos); -} - -// 8-bit version using lookup table. -size_t find_first_not_of(StringPiece self, StringPiece s, size_t pos) { - if (pos >= self.size()) - return StringPiece::npos; - - if (s.size() == 0) - return pos; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return self.find_first_not_of(s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = pos; i < self.size(); ++i) { - if (!lookup[static_cast<unsigned char>(self.data()[i])]) { - return i; - } - } - return StringPiece::npos; -} - -// Generic brute-force version. -template <typename T, typename CharT = typename T::value_type> -size_t find_first_not_ofT(T self, T s, size_t pos) { - if (self.size() == 0) - return BasicStringPiece<CharT>::npos; - - for (size_t self_i = pos; self_i < self.size(); ++self_i) { - bool found = false; - for (auto c : s) { - if (self[self_i] == c) { - found = true; - break; - } - } - if (!found) - return self_i; - } - return BasicStringPiece<CharT>::npos; -} - -size_t find_first_not_of(StringPiece16 self, StringPiece16 s, size_t pos) { - return find_first_not_ofT(self, s, pos); -} - -// 8-bit version using lookup table. -size_t find_last_of(StringPiece self, StringPiece s, size_t pos) { - if (self.size() == 0 || s.size() == 0) - return StringPiece::npos; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return self.rfind(s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = std::min(pos, self.size() - 1); ; --i) { - if (lookup[static_cast<unsigned char>(self.data()[i])]) - return i; - if (i == 0) - break; - } - return StringPiece::npos; -} - -// Generic brute-force version. -template <typename T, typename CharT = typename T::value_type> -size_t find_last_ofT(T self, T s, size_t pos) { - if (self.size() == 0) - return BasicStringPiece<CharT>::npos; - - for (size_t self_i = std::min(pos, self.size() - 1); ; - --self_i) { - for (auto c : s) { - if (self.data()[self_i] == c) - return self_i; - } - if (self_i == 0) - break; - } - return BasicStringPiece<CharT>::npos; -} - -size_t find_last_of(StringPiece16 self, StringPiece16 s, size_t pos) { - return find_last_ofT(self, s, pos); -} - -// 8-bit version using lookup table. -size_t find_last_not_of(StringPiece self, StringPiece s, size_t pos) { - if (self.size() == 0) - return StringPiece::npos; - - size_t i = std::min(pos, self.size() - 1); - if (s.size() == 0) - return i; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return self.find_last_not_of(s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (; ; --i) { - if (!lookup[static_cast<unsigned char>(self.data()[i])]) - return i; - if (i == 0) - break; - } - return StringPiece::npos; -} - -// Generic brute-force version. -template <typename T, typename CharT = typename T::value_type> -size_t find_last_not_ofT(T self, T s, size_t pos) { - if (self.size() == 0) - return StringPiece::npos; - - for (size_t self_i = std::min(pos, self.size() - 1); ; --self_i) { - bool found = false; - for (auto c : s) { - if (self.data()[self_i] == c) { - found = true; - break; - } - } - if (!found) - return self_i; - if (self_i == 0) - break; - } - return BasicStringPiece<CharT>::npos; -} - -size_t find_last_not_of(StringPiece16 self, StringPiece16 s, size_t pos) { - return find_last_not_ofT(self, s, pos); -} - -size_t find(WStringPiece self, WStringPiece s, size_t pos) { - return findT(self, s, pos); -} - -size_t rfind(WStringPiece self, WStringPiece s, size_t pos) { - return rfindT(self, s, pos); -} - -size_t find_first_of(WStringPiece self, WStringPiece s, size_t pos) { - return find_first_ofT(self, s, pos); -} - -size_t find_first_not_of(WStringPiece self, WStringPiece s, size_t pos) { - return find_first_not_ofT(self, s, pos); -} - -size_t find_last_of(WStringPiece self, WStringPiece s, size_t pos) { - return find_last_ofT(self, s, pos); -} - -size_t find_last_not_of(WStringPiece self, WStringPiece s, size_t pos) { - return find_last_not_ofT(self, s, pos); -} -} // namespace internal -} // namespace base
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index d5f51ad..6e4ea0f 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -2,647 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// A string-like object that points to a sized piece of memory. +// This header is deprecated. `gurl_base::StringPiece` is now `std::string_view`. +// Use it and <string_view> instead. // -// You can use StringPiece as a function or method parameter. A StringPiece -// parameter can receive a double-quoted string literal argument, a "const -// char*" argument, a string argument, or a StringPiece argument with no data -// copying. Systematic use of StringPiece for arguments reduces data -// copies and strlen() calls. -// -// Prefer passing StringPieces by value: -// void MyFunction(StringPiece arg); -// If circumstances require, you may also pass by const reference: -// void MyFunction(const StringPiece& arg); // not preferred -// Both of these have the same lifetime semantics. Passing by value -// generates slightly smaller code. For more discussion, Googlers can see -// the thread go/stringpiecebyvalue on c-users. +// TODO(crbug.com/691162): Remove uses of this header. #ifndef BASE_STRINGS_STRING_PIECE_H_ #define BASE_STRINGS_STRING_PIECE_H_ -#include <stddef.h> -#include <stdint.h> +#include <functional> -#include <algorithm> -#include <iosfwd> -#include <limits> -#include <string> -#include <string_view> -#include <type_traits> - +// Many files including this header rely on these being included due to IWYU +// violations. Preserve the includes for now. As code is migrated away from this +// header, we can incrementally fix the IWYU violations. #include "polyfills/base/base_export.h" #include "polyfills/base/check.h" #include "polyfills/base/check_op.h" #include "base/compiler_specific.h" #include "base/cxx20_is_constant_evaluated.h" -#include "base/strings/string_piece_forward.h" // IWYU pragma: export +#include "base/strings/string_piece_forward.h" +#include "base/strings/utf_ostream_operators.h" #include "build/build_config.h" namespace gurl_base { -// internal -------------------------------------------------------------------- - -// Many of the StringPiece functions use different implementations for the -// 8-bit and 16-bit versions, and we don't want lots of template expansions in -// this (very common) header that will slow down compilation. -// -// So here we define overloaded functions called by the StringPiece template. -// For those that share an implementation, the two versions will expand to a -// template internal to the .cc file. -namespace internal { - -BASE_EXPORT size_t find(StringPiece self, StringPiece s, size_t pos); -BASE_EXPORT size_t find(StringPiece16 self, StringPiece16 s, size_t pos); - -BASE_EXPORT size_t rfind(StringPiece self, StringPiece s, size_t pos); -BASE_EXPORT size_t rfind(StringPiece16 self, StringPiece16 s, size_t pos); - -BASE_EXPORT size_t find_first_of(StringPiece self, StringPiece s, size_t pos); -BASE_EXPORT size_t find_first_of(StringPiece16 self, - StringPiece16 s, - size_t pos); - -BASE_EXPORT size_t find_first_not_of(StringPiece self, - StringPiece s, - size_t pos); -BASE_EXPORT size_t find_first_not_of(StringPiece16 self, - StringPiece16 s, - size_t pos); - -BASE_EXPORT size_t find_last_of(StringPiece self, StringPiece s, size_t pos); -BASE_EXPORT size_t find_last_of(StringPiece16 self, - StringPiece16 s, - size_t pos); - -BASE_EXPORT size_t find_last_not_of(StringPiece self, - StringPiece s, - size_t pos); -BASE_EXPORT size_t find_last_not_of(StringPiece16 self, - StringPiece16 s, - size_t pos); - -BASE_EXPORT size_t find(WStringPiece self, WStringPiece s, size_t pos); -BASE_EXPORT size_t rfind(WStringPiece self, WStringPiece s, size_t pos); -BASE_EXPORT size_t find_first_of(WStringPiece self, WStringPiece s, size_t pos); -BASE_EXPORT size_t find_first_not_of(WStringPiece self, - WStringPiece s, - size_t pos); -BASE_EXPORT size_t find_last_of(WStringPiece self, WStringPiece s, size_t pos); -BASE_EXPORT size_t find_last_not_of(WStringPiece self, - WStringPiece s, - size_t pos); - -} // namespace internal - -// BasicStringPiece ------------------------------------------------------------ - -// Mirrors the C++17 version of std::basic_string_view<> as closely as possible, -// except where noted below. -template <typename CharT, typename Traits> -class GSL_POINTER BasicStringPiece { - public: - using traits_type = Traits; - using value_type = CharT; - using pointer = CharT*; - using const_pointer = const CharT*; - using reference = CharT&; - using const_reference = const CharT&; - using const_iterator = const CharT*; - using iterator = const_iterator; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - - constexpr BasicStringPiece() noexcept : ptr_(nullptr), length_(0) {} - constexpr BasicStringPiece(const BasicStringPiece& other) noexcept = default; - constexpr BasicStringPiece& operator=(const BasicStringPiece& view) noexcept = - default; - constexpr BasicStringPiece(const CharT* s, size_t count) - : ptr_(s), length_(count) { - // Intentional STL deviation: Check the string length fits in - // `difference_type`. No valid buffer can exceed this type, otherwise - // pointer arithmetic would not be defined. This helps avoid bugs where - // `count` was computed from an underflow or negative sentinel value. - GURL_CHECK(length_ <= size_t{PTRDIFF_MAX}); - } - // NOLINTNEXTLINE(google-explicit-constructor) - constexpr BasicStringPiece(const CharT* s) - : ptr_(s), length_(s ? traits_type::length(s) : 0) { - // Intentional STL deviation: Null-check instead of UB. - GURL_CHECK(s); - } - // Explicitly disallow construction from nullptr. Note that this does not - // catch construction from runtime strings that might be null. - // Note: The following is just a more elaborate way of spelling - // `BasicStringPiece(nullptr_t) = delete`, but unfortunately the terse form is - // not supported by the PNaCl toolchain. - template <class T, class = std::enable_if_t<std::is_null_pointer<T>::value>> - // NOLINTNEXTLINE(google-explicit-constructor) - BasicStringPiece(T) { - static_assert(sizeof(T) == 0, // Always false. - "StringPiece does not support construction from nullptr, use " - "the default constructor instead."); - } - - // These are necessary because std::basic_string provides construction from - // (an object convertible to) a std::basic_string_view, as well as an explicit - // cast operator to a std::basic_string_view, but (obviously) not from/to a - // BasicStringPiece. - // NOLINTNEXTLINE(google-explicit-constructor) - BasicStringPiece(const std::basic_string<CharT>& str) - : ptr_(str.data()), length_(str.size()) {} - explicit operator std::basic_string<CharT>() const { - return std::basic_string<CharT>(data(), size()); - } - - // Provide implicit conversions from/to the STL version, for interoperability - // with non-Chromium code. - // TODO(crbug.com/691162): These will be moot when BasicStringPiece is - // replaced with std::basic_string_view. - // NOLINTNEXTLINE(google-explicit-constructor) - constexpr BasicStringPiece(std::basic_string_view<CharT> str) - : ptr_(str.data()), length_(str.size()) {} - // NOLINTNEXTLINE(google-explicit-constructor) - constexpr operator std::basic_string_view<CharT>() const { - return std::basic_string_view<CharT>(data(), size()); - } - - constexpr const_iterator begin() const noexcept { return ptr_; } - constexpr const_iterator cbegin() const noexcept { return ptr_; } - constexpr const_iterator end() const noexcept { return ptr_ + length_; } - constexpr const_iterator cend() const noexcept { return ptr_ + length_; } - constexpr const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(ptr_ + length_); - } - constexpr const_reverse_iterator crbegin() const noexcept { - return const_reverse_iterator(ptr_ + length_); - } - constexpr const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(ptr_); - } - constexpr const_reverse_iterator crend() const noexcept { - return const_reverse_iterator(ptr_); - } - - constexpr const_reference operator[](size_type pos) const { - // Intentional STL deviation: Bounds-check instead of UB. - return at(pos); - } - constexpr const_reference at(size_type pos) const { - GURL_CHECK_LT(pos, size()); - return data()[pos]; - } - - constexpr const_reference front() const { return operator[](0); } - - constexpr const_reference back() const { return operator[](size() - 1); } - - constexpr const_pointer data() const noexcept { return ptr_; } - - constexpr size_type size() const noexcept { return length_; } - constexpr size_type length() const noexcept { return length_; } - - constexpr size_type max_size() const { - return std::numeric_limits<size_type>::max() / sizeof(CharT); - } - - [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } - - constexpr void remove_prefix(size_type n) { - // Intentional STL deviation: Bounds-check instead of UB. - GURL_CHECK_LE(n, size()); - ptr_ += n; - length_ -= n; - } - - constexpr void remove_suffix(size_type n) { - // Intentional STL deviation: Bounds-check instead of UB. - GURL_CHECK_LE(n, size()); - length_ -= n; - } - - constexpr void swap(BasicStringPiece& v) noexcept { - // Note: Cannot use std::swap() since it is not constexpr until C++20. - const const_pointer ptr = ptr_; - ptr_ = v.ptr_; - v.ptr_ = ptr; - const size_type length = length_; - length_ = v.length_; - v.length_ = length; - } - - constexpr size_type copy(CharT* dest, - size_type count, - size_type pos = 0) const { - GURL_CHECK_LE(pos, size()); - const size_type rcount = std::min(count, size() - pos); - traits_type::copy(dest, data() + pos, rcount); - return rcount; - } - - constexpr BasicStringPiece substr(size_type pos = 0, - size_type count = npos) const { - GURL_CHECK_LE(pos, size()); - const size_type rcount = std::min(count, size() - pos); - return {data() + pos, rcount}; - } - - constexpr int compare(BasicStringPiece v) const noexcept { - const size_type rlen = std::min(size(), v.size()); - const int result = traits_type::compare(data(), v.data(), rlen); - if (result != 0) - return result; - if (size() == v.size()) - return 0; - return size() < v.size() ? -1 : 1; - } - constexpr int compare(size_type pos1, - size_type count1, - BasicStringPiece v) const { - return substr(pos1, count1).compare(v); - } - constexpr int compare(size_type pos1, - size_type count1, - BasicStringPiece v, - size_type pos2, - size_type count2) const { - return substr(pos1, count1).compare(v.substr(pos2, count2)); - } - constexpr int compare(const CharT* s) const { - return compare(BasicStringPiece(s)); - } - constexpr int compare(size_type pos1, - size_type count1, - const CharT* s) const { - return substr(pos1, count1).compare(BasicStringPiece(s)); - } - constexpr int compare(size_type pos1, - size_type count1, - const CharT* s, - size_type count2) const { - return substr(pos1, count1).compare(BasicStringPiece(s, count2)); - } - - constexpr size_type find(BasicStringPiece v, - size_type pos = 0) const noexcept { - if (is_constant_evaluated()) { - if (v.size() > size()) - return npos; - for (size_type p = pos; p <= size() - v.size(); ++p) { - if (!compare(p, v.size(), v)) - return p; - } - return npos; - } - - return internal::find(*this, v, pos); - } - constexpr size_type find(CharT ch, size_type pos = 0) const noexcept { - if (pos >= size()) - return npos; - - const const_pointer result = - traits_type::find(data() + pos, size() - pos, ch); - return result ? static_cast<size_type>(result - data()) : npos; - } - constexpr size_type find(const CharT* s, - size_type pos, - size_type count) const { - return find(BasicStringPiece(s, count), pos); - } - constexpr size_type find(const CharT* s, size_type pos = 0) const { - return find(BasicStringPiece(s), pos); - } - - constexpr size_type rfind(BasicStringPiece v, - size_type pos = npos) const noexcept { - if (is_constant_evaluated()) { - if (v.size() > size()) - return npos; - for (size_type p = std::min(size() - v.size(), pos);; --p) { - if (!compare(p, v.size(), v)) - return p; - if (!p) - break; - } - return npos; - } - - return internal::rfind(*this, v, pos); - } - constexpr size_type rfind(CharT c, size_type pos = npos) const noexcept { - if (empty()) - return npos; - - for (size_t i = std::min(pos, size() - 1);; --i) { - if (data()[i] == c) - return i; - - if (i == 0) - break; - } - return npos; - } - constexpr size_type rfind(const CharT* s, - size_type pos, - size_type count) const { - return rfind(BasicStringPiece(s, count), pos); - } - constexpr size_type rfind(const CharT* s, size_type pos = npos) const { - return rfind(BasicStringPiece(s), pos); - } - - constexpr size_type find_first_of(BasicStringPiece v, - size_type pos = 0) const noexcept { - if (is_constant_evaluated()) { - if (empty() || v.empty()) - return npos; - for (size_type p = pos; p < size(); ++p) { - if (v.find(data()[p]) != npos) - return p; - } - return npos; - } - - return internal::find_first_of(*this, v, pos); - } - constexpr size_type find_first_of(CharT c, size_type pos = 0) const noexcept { - return find(c, pos); - } - constexpr size_type find_first_of(const CharT* s, - size_type pos, - size_type count) const { - return find_first_of(BasicStringPiece(s, count), pos); - } - constexpr size_type find_first_of(const CharT* s, size_type pos = 0) const { - return find_first_of(BasicStringPiece(s), pos); - } - - constexpr size_type find_last_of(BasicStringPiece v, - size_type pos = npos) const noexcept { - if (is_constant_evaluated()) { - if (empty() || v.empty()) - return npos; - for (size_type p = std::min(pos, size() - 1);; --p) { - if (v.find(data()[p]) != npos) - return p; - if (!p) - break; - } - return npos; - } - - return internal::find_last_of(*this, v, pos); - } - constexpr size_type find_last_of(CharT c, - size_type pos = npos) const noexcept { - return rfind(c, pos); - } - constexpr size_type find_last_of(const CharT* s, - size_type pos, - size_type count) const { - return find_last_of(BasicStringPiece(s, count), pos); - } - constexpr size_type find_last_of(const CharT* s, size_type pos = npos) const { - return find_last_of(BasicStringPiece(s), pos); - } - - constexpr size_type find_first_not_of(BasicStringPiece v, - size_type pos = 0) const noexcept { - if (is_constant_evaluated()) { - if (empty()) - return npos; - for (size_type p = pos; p < size(); ++p) { - if (v.find(data()[p]) == npos) - return p; - } - return npos; - } - - return internal::find_first_not_of(*this, v, pos); - } - constexpr size_type find_first_not_of(CharT c, - size_type pos = 0) const noexcept { - if (empty()) - return npos; - - for (; pos < size(); ++pos) { - if (data()[pos] != c) - return pos; - } - return npos; - } - constexpr size_type find_first_not_of(const CharT* s, - size_type pos, - size_type count) const { - return find_first_not_of(BasicStringPiece(s, count), pos); - } - constexpr size_type find_first_not_of(const CharT* s, - size_type pos = 0) const { - return find_first_not_of(BasicStringPiece(s), pos); - } - - constexpr size_type find_last_not_of(BasicStringPiece v, - size_type pos = npos) const noexcept { - if (is_constant_evaluated()) { - if (empty()) - return npos; - for (size_type p = std::min(pos, size() - 1);; --p) { - if (v.find(data()[p]) == npos) - return p; - if (!p) - break; - } - return npos; - } - - return internal::find_last_not_of(*this, v, pos); - } - constexpr size_type find_last_not_of(CharT c, - size_type pos = npos) const noexcept { - if (empty()) - return npos; - - for (size_t i = std::min(pos, size() - 1);; --i) { - if (data()[i] != c) - return i; - if (i == 0) - break; - } - return npos; - } - constexpr size_type find_last_not_of(const CharT* s, - size_type pos, - size_type count) const { - return find_last_not_of(BasicStringPiece(s, count), pos); - } - constexpr size_type find_last_not_of(const CharT* s, - size_type pos = npos) const { - return find_last_not_of(BasicStringPiece(s), pos); - } - - static constexpr size_type npos = size_type(-1); - - protected: - const_pointer ptr_; - size_type length_; -}; - -// static -template <typename CharT, typename Traits> -const typename BasicStringPiece<CharT, Traits>::size_type - BasicStringPiece<CharT, Traits>::npos; - -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) -extern template class BASE_EXPORT BasicStringPiece<char>; -extern template class BASE_EXPORT BasicStringPiece<char16_t>; -#endif - -template <typename CharT, typename Traits> -constexpr bool operator==(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; -} -// Here and below we make use of std::common_type_t to emulate -// std::type_identity (part of C++20). This creates a non-deduced context, so -// that we can compare StringPieces with types that implicitly convert to -// StringPieces. See https://wg21.link/n3766 for details. -// Furthermore, we require dummy template parameters for these overloads to work -// around a name mangling issue on Windows. -template <typename CharT, typename Traits, int = 1> -constexpr bool operator==( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; -} -template <typename CharT, typename Traits, int = 2> -constexpr bool operator==( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; -} - -template <typename CharT, typename Traits> -constexpr bool operator!=(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(lhs == rhs); -} -template <typename CharT, typename Traits, int = 1> -constexpr bool operator!=( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return !(lhs == rhs); -} -template <typename CharT, typename Traits, int = 2> -constexpr bool operator!=( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(lhs == rhs); -} - -template <typename CharT, typename Traits> -constexpr bool operator<(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return lhs.compare(rhs) < 0; -} -template <typename CharT, typename Traits, int = 1> -constexpr bool operator<( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return lhs.compare(rhs) < 0; -} - -template <typename CharT, typename Traits, int = 2> -constexpr bool operator<( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return lhs.compare(rhs) < 0; -} - -template <typename CharT, typename Traits> -constexpr bool operator>(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return rhs < lhs; -} -template <typename CharT, typename Traits, int = 1> -constexpr bool operator>( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return rhs < lhs; -} -template <typename CharT, typename Traits, int = 2> -constexpr bool operator>( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return rhs < lhs; -} - -template <typename CharT, typename Traits> -constexpr bool operator<=(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(rhs < lhs); -} -template <typename CharT, typename Traits, int = 1> -constexpr bool operator<=( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return !(rhs < lhs); -} -template <typename CharT, typename Traits, int = 2> -constexpr bool operator<=( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(rhs < lhs); -} - -template <typename CharT, typename Traits> -constexpr bool operator>=(BasicStringPiece<CharT, Traits> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(lhs < rhs); -} -template <typename CharT, typename Traits, int = 1> -constexpr bool operator>=( - BasicStringPiece<CharT, Traits> lhs, - std::common_type_t<BasicStringPiece<CharT, Traits>> rhs) noexcept { - return !(lhs < rhs); -} -template <typename CharT, typename Traits, int = 2> -constexpr bool operator>=( - std::common_type_t<BasicStringPiece<CharT, Traits>> lhs, - BasicStringPiece<CharT, Traits> rhs) noexcept { - return !(lhs < rhs); -} - -BASE_EXPORT std::ostream& operator<<(std::ostream& o, StringPiece piece); -// Not in the STL: convenience functions to output non-UTF-8 strings to an -// 8-bit-width stream. -BASE_EXPORT std::ostream& operator<<(std::ostream& o, StringPiece16 piece); -BASE_EXPORT std::ostream& operator<<(std::ostream& o, WStringPiece piece); - -// Intentionally omitted (since Chromium does not use character literals): -// operator""sv. - -// Stand-ins for the STL's std::hash<> specializations. -template <typename StringPieceType> -struct StringPieceHashImpl { - using is_transparent = void; // to allow for heterogenous lookup - - // This is a custom hash function. We don't use the ones already defined for - // string and std::u16string directly because it would require the string - // constructors to be called, which we don't want. - size_t operator()(StringPieceType sp) const { - size_t result = 0; - for (auto c : sp) - result = (result * 131) + static_cast<size_t>(c); - return result; - } -}; -using StringPieceHash = StringPieceHashImpl<StringPiece>; -using StringPiece16Hash = StringPieceHashImpl<StringPiece16>; -using WStringPieceHash = StringPieceHashImpl<WStringPiece>; +// Historically, `std::hash` did not support `gurl_base::StringPiece`. Now +// `gurl_base::StringPiece` is `std::string_view`, so this is no longer necessary. +// Replace uses of this type with the default hasher. +using StringPieceHash = std::hash<StringPiece>; } // namespace base
diff --git a/base/strings/string_piece_forward.h b/base/strings/string_piece_forward.h index 6c391b1..9138f3f 100644 --- a/base/strings/string_piece_forward.h +++ b/base/strings/string_piece_forward.h
@@ -2,20 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Forward declaration of StringPiece types from base/strings/string_piece.h. +// This header is deprecated. `gurl_base::StringPiece` is now `std::string_view`. +// Use it and <string_view> instead. +// +// TODO(crbug.com/691162): Remove uses of this header. #ifndef BASE_STRINGS_STRING_PIECE_FORWARD_H_ #define BASE_STRINGS_STRING_PIECE_FORWARD_H_ -#include <iosfwd> +#include <string_view> namespace gurl_base { template <typename CharT, typename Traits = std::char_traits<CharT>> -class BasicStringPiece; -using StringPiece = BasicStringPiece<char>; -using StringPiece16 = BasicStringPiece<char16_t>; -using WStringPiece = BasicStringPiece<wchar_t>; +using BasicStringPiece = std::basic_string_view<CharT, Traits>; +using StringPiece = std::string_view; +using StringPiece16 = std::u16string_view; +using WStringPiece = std::wstring_view; } // namespace base
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc index 35ea795..b77edbd 100644 --- a/base/strings/string_piece_unittest.cc +++ b/base/strings/string_piece_unittest.cc
@@ -518,7 +518,7 @@ std::basic_string<TypeParam> s1(TestFixture::as_string("123")); s1 += static_cast<TypeParam>('\0'); s1 += TestFixture::as_string("456"); - BasicStringPiece<TypeParam> b(s1); + [[maybe_unused]] BasicStringPiece<TypeParam> b(s1); BasicStringPiece<TypeParam> e; std::basic_string<TypeParam> s2; @@ -565,7 +565,7 @@ std::string s1("123"); s1 += '\0'; s1 += "456"; - StringPiece b(s1); + [[maybe_unused]] StringPiece b(s1); StringPiece e; std::string s2;
diff --git a/base/strings/string_util.h b/base/strings/string_util.h index 082e42d..d40c11b 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h
@@ -421,6 +421,28 @@ } template <typename Char> +inline bool IsAsciiControl(Char c) { + if constexpr (std::is_signed_v<Char>) { + if (c < 0) { + return false; + } + } + return c <= 0x1f || c == 0x7f; +} + +template <typename Char> +inline bool IsUnicodeControl(Char c) { + return IsAsciiControl(c) || + // C1 control characters: http://unicode.org/charts/PDF/U0080.pdf + (c >= 0x80 && c <= 0x9F); +} + +template <typename Char> +inline bool IsAsciiPunctuation(Char c) { + return c > 0x20 && c < 0x7f && !IsAsciiAlphaNumeric(c); +} + +template <typename Char> inline bool IsHexDigit(Char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
diff --git a/base/strings/string_util_impl_helpers.h b/base/strings/string_util_impl_helpers.h index 9578477..fb15c87 100644 --- a/base/strings/string_util_impl_helpers.h +++ b/base/strings/string_util_impl_helpers.h
@@ -481,12 +481,12 @@ auto iter = parts.begin(); GURL_DCHECK(iter != parts.end()); - result.append(iter->data(), iter->size()); + result.append(*iter); ++iter; for (; iter != parts.end(); ++iter) { - result.append(sep.data(), sep.size()); - result.append(iter->data(), iter->size()); + result.append(sep); + result.append(*iter); } // Sanity-check that we pre-allocated correctly.
diff --git a/base/strings/to_string.h b/base/strings/to_string.h new file mode 100644 index 0000000..78691a0 --- /dev/null +++ b/base/strings/to_string.h
@@ -0,0 +1,117 @@ +// Copyright 2023 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_STRINGS_TO_STRING_H_ +#define BASE_STRINGS_TO_STRING_H_ + +#include <ios> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +#include "base/template_util.h" +#include "base/types/supports_ostream_operator.h" + +namespace gurl_base { + +namespace internal { + +template <typename T, typename = void> +struct SupportsToString : std::false_type {}; +template <typename T> +struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))> + : std::true_type {}; + +// I/O manipulators are function pointers, but should be sent directly to the +// `ostream` instead of being cast to `const void*` like other function +// pointers. +template <typename T, typename = void> +constexpr bool IsIomanip = false; +template <typename T> +constexpr bool + IsIomanip<T&(T&), std::enable_if_t<std::is_base_of_v<std::ios_base, T>>> = + true; + +// Function pointers implicitly convert to `bool`, so use this to avoid printing +// function pointers as 1 or 0. +template <typename T, typename = void> +constexpr bool WillBeIncorrectlyStreamedAsBool = false; +template <typename T> +constexpr bool WillBeIncorrectlyStreamedAsBool< + T, + std::enable_if_t<std::is_function_v<std::remove_pointer_t<T>> && + !IsIomanip<std::remove_pointer_t<T>>>> = true; + +// Fallback case when there is no better representation. +template <typename T, typename = void> +struct ToStringHelper { + static void Stringify(const T& v, std::ostringstream& ss) { + ss << "[" << sizeof(v) << "-byte object at 0x" << std::addressof(v) << "]"; + } +}; + +// Most streamables. +template <typename T> +struct ToStringHelper< + T, + std::enable_if_t<SupportsOstreamOperator<const T&>::value && + !WillBeIncorrectlyStreamedAsBool<T>>> { + static void Stringify(const T& v, std::ostringstream& ss) { ss << v; } +}; + +// Functions and function pointers. +template <typename T> +struct ToStringHelper< + T, + std::enable_if_t<SupportsOstreamOperator<const T&>::value && + WillBeIncorrectlyStreamedAsBool<T>>> { + static void Stringify(const T& v, std::ostringstream& ss) { + ToStringHelper<const void*>::Stringify(reinterpret_cast<const void*>(v), + ss); + } +}; + +// Non-streamables that have a `ToString` member. +template <typename T> +struct ToStringHelper< + T, + std::enable_if_t<!SupportsOstreamOperator<const T&>::value && + SupportsToString<const T&>::value>> { + static void Stringify(const T& v, std::ostringstream& ss) { + // .ToString() may not return a std::string, e.g. blink::WTF::String. + ToStringHelper<decltype(v.ToString())>::Stringify(v.ToString(), ss); + } +}; + +// Non-streamable enums (i.e. scoped enums where no `operator<<` overload was +// declared). +template <typename T> +struct ToStringHelper< + T, + std::enable_if_t<!SupportsOstreamOperator<const T&>::value && + std::is_enum_v<T>>> { + static void Stringify(const T& v, std::ostringstream& ss) { + using UT = typename std::underlying_type_t<T>; + ToStringHelper<UT>::Stringify(static_cast<UT>(v), ss); + } +}; + +} // namespace internal + +// Converts any type to a string, preferring defined operator<<() or ToString() +// methods if they exist. +template <typename... Ts> +std::string ToString(const Ts&... values) { + std::ostringstream ss; + (internal::ToStringHelper<remove_cvref_t<decltype(values)>>::Stringify(values, + ss), + ...); + return ss.str(); +} + +} // namespace base + +#endif // BASE_STRINGS_TO_STRING_H_
diff --git a/base/strings/to_string_test.cc b/base/strings/to_string_test.cc new file mode 100644 index 0000000..87d021f --- /dev/null +++ b/base/strings/to_string_test.cc
@@ -0,0 +1,115 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/to_string.h" + +#include <ios> +#include <ostream> +#include <string> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace gurl_base { +namespace { + +class NotStringifiable {}; +class HasToString { + public: + std::string ToString() const { return "yay!"; } +}; + +// .ToString() support on structs. +static_assert(!internal::SupportsToString<NotStringifiable>::value, + "value without ToString() shouldn't be marked SupportsToString"); +static_assert(!internal::SupportsToString<const NotStringifiable&>::value, + "const& without ToString() shouldn't be marked SupportsToString"); +static_assert(internal::SupportsToString<HasToString>::value, + "value with ToString() should be marked SupportsToString"); +static_assert(internal::SupportsToString<const HasToString&>::value, + "const& with ToString() should be marked SupportsToString"); + +TEST(ToStringTest, Streamable) { + // Types with built-in <<. + EXPECT_EQ(ToString("foo"), "foo"); + EXPECT_EQ(ToString(123), "123"); +} + +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(ToStringTest, UserDefinedStreamable) { + // Type with user-defined <<. + EXPECT_EQ(ToString(StreamableTestEnum::kGreeting), "hello"); + EXPECT_EQ(ToString(StreamableTestEnum::kGreeting, " ", + StreamableTestEnum::kLocation), + "hello world"); +} + +TEST(ToStringTest, UserDefinedToString) { + // Type with user-defined ToString(). + EXPECT_EQ(ToString(HasToString()), "yay!"); +} + +class UnusualToString { + public: + HasToString ToString() const { return HasToString(); } +}; + +TEST(ToStringTest, ToStringReturnsNonStdString) { + // Types with a ToString() that does not directly return a std::string should + // still work. + EXPECT_EQ(ToString(UnusualToString()), "yay!"); +} + +enum class NonStreamableTestEnum { kGreeting = 0, kLocation }; + +TEST(ToStringTest, ScopedEnum) { + // Scoped enums without a defined << should print as their underlying type. + EXPECT_EQ(ToString(NonStreamableTestEnum::kLocation), "1"); +} + +TEST(ToStringTest, IoManip) { + // I/O manipulators should have their expected effect, not be printed as + // function pointers. + EXPECT_EQ(ToString("42 in hex is ", std::hex, 42), "42 in hex is 2a"); +} + +void Func() {} + +TEST(ToStringTest, FunctionPointer) { + // We don't care about the actual address, but a function pointer should not + // be implicitly converted to bool. + EXPECT_NE(ToString(&Func), ToString(true)); + + // Functions should be treated like function pointers. + EXPECT_EQ(ToString(Func), ToString(&Func)); +} + +class OverloadsAddressOp { + public: + OverloadsAddressOp* operator&() { return nullptr; } + const OverloadsAddressOp* operator&() const { return nullptr; } +}; + +TEST(ToStringTest, NonStringifiable) { + // Non-stringifiable types should be printed using a fallback. + EXPECT_NE(ToString(NotStringifiable()).find("-byte object at 0x"), + std::string::npos); + + // Non-stringifiable types which overload operator& should print their real + // address. + EXPECT_NE(ToString(OverloadsAddressOp()), + ToString(static_cast<OverloadsAddressOp*>(nullptr))); +} + +} // namespace +} // namespace base
diff --git a/base/strings/utf_ostream_operators.cc b/base/strings/utf_ostream_operators.cc new file mode 100644 index 0000000..2f60140 --- /dev/null +++ b/base/strings/utf_ostream_operators.cc
@@ -0,0 +1,31 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/utf_ostream_operators.h" + +#include "base/strings/utf_string_conversions.h" + +std::ostream& std::operator<<(std::ostream& out, const wchar_t* wstr) { + return out << (wstr ? std::wstring_view(wstr) : std::wstring_view()); +} + +std::ostream& std::operator<<(std::ostream& out, std::wstring_view wstr) { + return out << gurl_base::WideToUTF8(wstr); +} + +std::ostream& std::operator<<(std::ostream& out, const std::wstring& wstr) { + return out << std::wstring_view(wstr); +} + +std::ostream& std::operator<<(std::ostream& out, const char16_t* str16) { + return out << (str16 ? std::u16string_view(str16) : std::u16string_view()); +} + +std::ostream& std::operator<<(std::ostream& out, std::u16string_view str16) { + return out << gurl_base::UTF16ToUTF8(str16); +} + +std::ostream& std::operator<<(std::ostream& out, const std::u16string& str16) { + return out << std::u16string_view(str16); +}
diff --git a/base/strings/utf_ostream_operators.h b/base/strings/utf_ostream_operators.h new file mode 100644 index 0000000..6fca090 --- /dev/null +++ b/base/strings/utf_ostream_operators.h
@@ -0,0 +1,45 @@ +// Copyright 2023 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_STRINGS_UTF_OSTREAM_OPERATORS_H_ +#define BASE_STRINGS_UTF_OSTREAM_OPERATORS_H_ + +#include <iosfwd> +#include <string_view> + +#include "polyfills/base/base_export.h" + +// Note that "The behavior of a C++ program is undefined if it adds declarations +// or definitions to namespace std or to a namespace within namespace std unless +// otherwise specified." --C++11[namespace.std] +// +// We've checked that this particular definition has the intended behavior on +// our implementations, but it's prone to breaking in the future, and please +// don't imitate this in your own definitions without checking with some +// standard library experts. +namespace std { +// These functions are provided as a convenience for logging, which is where we +// use streams (it is against Google style to use streams in other places). It +// is designed to allow you to emit non-ASCII Unicode strings to the log file, +// which is normally ASCII. It is relatively slow, so try not to use it for +// common cases. Non-ASCII characters will be converted to UTF-8 by these +// operators. +// +// The `std::basic_string<T>` overloads are necessary to allow logging types +// which are implicitly convertible to `std::basic_string<T>`. Simply taking +// `std::basic_string_view<T>` would not work because C++ only allows one +// implicit conversion. +BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); +BASE_EXPORT std::ostream& operator<<(std::ostream& out, std::wstring_view wstr); +BASE_EXPORT std::ostream& operator<<(std::ostream& out, + const std::wstring& wstr); + +BASE_EXPORT std::ostream& operator<<(std::ostream& out, const char16_t* str16); +BASE_EXPORT std::ostream& operator<<(std::ostream& out, + std::u16string_view str16); +BASE_EXPORT std::ostream& operator<<(std::ostream& out, + const std::u16string& str16); +} // namespace std + +#endif // BASE_STRINGS_UTF_OSTREAM_OPERATORS_H_
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc index 162fa36..149a6ee 100644 --- a/base/strings/utf_string_conversion_utils.cc +++ b/base/strings/utf_string_conversion_utils.cc
@@ -9,6 +9,21 @@ namespace gurl_base { +// CountUnicodeCharacters ------------------------------------------------------ + +absl::optional<size_t> CountUnicodeCharacters(const char16_t* src, + size_t src_len, + size_t limit) { + base_icu::UChar32 unused = 0; + size_t count = 0; + for (size_t index = 0; count < limit && index < src_len; ++count, ++index) { + if (!ReadUnicodeCharacter(src, src_len, &index, &unused)) { + return absl::nullopt; + } + } + return count; +} + // ReadUnicodeCharacter -------------------------------------------------------- bool ReadUnicodeCharacter(const char* src,
diff --git a/base/strings/utf_string_conversion_utils.h b/base/strings/utf_string_conversion_utils.h index f5ae5b1..638a59f 100644 --- a/base/strings/utf_string_conversion_utils.h +++ b/base/strings/utf_string_conversion_utils.h
@@ -16,6 +16,7 @@ #include "polyfills/base/base_export.h" #include "base/third_party/icu/icu_utf.h" #include "build/build_config.h" +#include "absl/types/optional.h" namespace gurl_base { @@ -39,6 +40,15 @@ (code_point & 0xFFFE) != 0xFFFE); } +// CountUnicodeCharacters ------------------------------------------------------ + +// Returns the number of Unicode characters in `text`, up to the supplied +// `limit`, if `text` contains valid UTF-16. Returns `nullopt` otherwise. +BASE_EXPORT absl::optional<size_t> CountUnicodeCharacters( + const char16_t* src, + size_t src_len, + size_t limit = std::numeric_limits<size_t>::max()); + // ReadUnicodeCharacter -------------------------------------------------------- // Reads a UTF-8 stream, placing the next code point into the given output
diff --git a/base/strings/utf_string_conversion_utils_unittest.cc b/base/strings/utf_string_conversion_utils_unittest.cc new file mode 100644 index 0000000..4e700dc --- /dev/null +++ b/base/strings/utf_string_conversion_utils_unittest.cc
@@ -0,0 +1,32 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/utf_string_conversion_utils.h" + +#include <string> + +#include "base/strings/string_piece.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gurl_base { + +TEST(UtfStringConversionUtilsTest, CountUnicodeCharacters) { + struct TestCase { + std::u16string value; + size_t limit; + absl::optional<size_t> count; + } test_cases[] = { + {u"", 0, 0}, {u"abc", 1, 1}, + {u"abc", 3, 3}, {u"abc", 0, 0}, + {u"abc", 4, 3}, {u"abc\U0001F4A9", 4, 4}, + {u"\U0001F4A9", 1, 1}, {{1, 0xD801u}, 5, absl::nullopt}, + }; + for (const auto& test_case : test_cases) { + EXPECT_EQ(CountUnicodeCharacters(test_case.value.data(), + test_case.value.length(), test_case.limit), + test_case.count); + } +} + +} // namespace base
diff --git a/base/strings/utf_string_conversions.h b/base/strings/utf_string_conversions.h index 975d29d..1ee702c 100644 --- a/base/strings/utf_string_conversions.h +++ b/base/strings/utf_string_conversions.h
@@ -11,6 +11,7 @@ #include "polyfills/base/base_export.h" #include "base/strings/string_piece.h" +#include "base/types/always_false.h" #include "build/build_config.h" namespace gurl_base { @@ -70,19 +71,22 @@ // compile time. template <size_t N> std::u16string WideToUTF16(const wchar_t (&str)[N]) { - static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); + static_assert(AlwaysFalse<decltype(N)>, + "Error: Use the u\"...\" prefix instead."); return std::u16string(); } template <size_t N> std::u16string UTF8ToUTF16(const char (&str)[N]) { - static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); + static_assert(AlwaysFalse<decltype(N)>, + "Error: Use the u\"...\" prefix instead."); return std::u16string(); } template <size_t N> std::u16string ASCIIToUTF16(const char (&str)[N]) { - static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); + static_assert(AlwaysFalse<decltype(N)>, + "Error: Use the u\"...\" prefix instead."); return std::u16string(); }
diff --git a/base/template_util.h b/base/template_util.h index 93b7c31..480eaca 100644 --- a/base/template_util.h +++ b/base/template_util.h
@@ -18,12 +18,6 @@ namespace internal { -template <typename T, typename = void> -struct SupportsToString : std::false_type {}; -template <typename T> -struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))> - : std::true_type {}; - // Used to detech whether the given type is an iterator. This is normally used // with std::enable_if to provide disambiguation for functions that take // templatzed iterators as input.
diff --git a/base/types/always_false.h b/base/types/always_false.h new file mode 100644 index 0000000..7f43695 --- /dev/null +++ b/base/types/always_false.h
@@ -0,0 +1,48 @@ +// 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_TYPES_ALWAYS_FALSE_H_ +#define BASE_TYPES_ALWAYS_FALSE_H_ + +namespace gurl_base { + +// A helper that can be used with a static_assert() that must always fail (e.g. +// for an undesirable template instantiation). Such a static_assert() cannot +// simply be written as static_assert(false, ...) because that would always fail +// to compile, even if the template was never instantiated. Instead, a common +// idiom is to force the static_assert() to depend on a template parameter so +// that it is only evaluated when the template is instantiated: +// +// template <typename U = T> +// void SomeDangerousMethodThatShouldNeverCompile() { +// static_assert(gurl_base::AlwaysFalse<U>, "explanatory message here"); +// } +// +// +// The issue of not being able to use static_assert(false, ...) in a +// non-instantiated template was fixed in C++23. When Chromium switches to +// building with C++23, remove this file and use false directly, and search +// across the Chromium codebase for "AlwaysFalse", as there are other +// implementations in places that cannot depend on this file. +// +// References: +// - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html +// - https://github.com/cplusplus/papers/issues/1251 + +namespace internal { + +template <typename... Args> +struct AlwaysFalseHelper { + static constexpr bool kValue = false; +}; + +} // namespace internal + +template <typename... Args> +inline constexpr bool AlwaysFalse = + internal::AlwaysFalseHelper<Args...>::kValue; + +} // namespace base + +#endif // BASE_TYPES_ALWAYS_FALSE_H_
diff --git a/build/build_config.h b/build/build_config.h index 6db5d9b..2484703 100644 --- a/build/build_config.h +++ b/build/build_config.h
@@ -33,13 +33,13 @@ // COMPILER_MSVC / COMPILER_GCC // // Processor: -// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_LOONG32 / ARCH_CPU_LOONG64 / -// ARCH_CPU_MIPS / ARCH_CPU_MIPS64 / ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / -// ARCH_CPU_PPC64 / ARCH_CPU_S390 / ARCH_CPU_S390X / ARCH_CPU_X86 / -// ARCH_CPU_X86_64 / ARCH_CPU_RISCV64 +// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_LOONGARCH32 / +// ARCH_CPU_LOONGARCH64 / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 / +// ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 / +// ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_RISCV64 // Processor family: // ARCH_CPU_ARM_FAMILY: ARMEL or ARM64 -// ARCH_CPU_LOONG_FAMILY: LOONG32 or LOONG64 +// ARCH_CPU_LOONGARCH_FAMILY: LOONGARCH32 or LOONGARCH64 // ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS // ARCH_CPU_PPC64_FAMILY: PPC64 // ARCH_CPU_S390_FAMILY: S390 or S390X @@ -335,16 +335,16 @@ #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_BIG_ENDIAN 1 #endif -#elif defined(__loongarch32) -#define ARCH_CPU_LOONG_FAMILY 1 -#define ARCH_CPU_LOONG32 1 -#define ARCH_CPU_32_BITS 1 +#elif defined(__loongarch__) +#define ARCH_CPU_LOONGARCH_FAMILY 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__loongarch64) -#define ARCH_CPU_LOONG_FAMILY 1 -#define ARCH_CPU_LOONG64 1 +#if __loongarch_grlen == 64 +#define ARCH_CPU_LOONGARCH64 1 #define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 +#else +#define ARCH_CPU_LOONGARCH32 1 +#define ARCH_CPU_32_BITS 1 +#endif #elif defined(__riscv) && (__riscv_xlen == 64) #define ARCH_CPU_RISCV_FAMILY 1 #define ARCH_CPU_RISCV64 1
diff --git a/copy.bara.sky b/copy.bara.sky index 7f21a09..9020cbf 100644 --- a/copy.bara.sky +++ b/copy.bara.sky
@@ -37,6 +37,7 @@ "base/strings/*.cc", "base/strings/*.h", "base/template_util.h", + "base/types/always_false.h", "base/third_party/icu/**", "base/win/win_handle_types.h", "base/win/win_handle_types_list.inc", @@ -106,6 +107,7 @@ # iOS version of url_idna is ASCII-only, but it uses .mm extension; rename # it to a .cc file. core.move("url/url_idna_icu_alternatives_ios.mm", "url/url_idna_ascii_only.cc"), + core.replace("!defined(__has_feature) || !__has_feature(objc_arc)", "false"), # Fix some Perfetto includes. core.replace("base/trace_event/base_tracing.h", "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h"),
diff --git a/polyfills/base/base_export.h b/polyfills/base/base_export.h index 209e910..e02383e 100644 --- a/polyfills/base/base_export.h +++ b/polyfills/base/base_export.h
@@ -5,6 +5,9 @@ #ifndef POLYFILLS_BASE_BASE_EXPORT_H_ #define POLYFILLS_BASE_BASE_EXPORT_H_ +// Required to get some of the headers to compile. +#include <limits> + #define BASE_EXPORT #endif /* POLYFILLS_BASE_BASE_EXPORT_H_ */
diff --git a/polyfills/base/feature_list.h b/polyfills/base/feature_list.h index b687509..8ad7a08 100644 --- a/polyfills/base/feature_list.h +++ b/polyfills/base/feature_list.h
@@ -30,6 +30,8 @@ static bool IsEnabled(const Feature& feature) { return feature.default_state == FEATURE_ENABLED_BY_DEFAULT; } + + static FeatureList* GetInstance() { return nullptr; } }; } // namespace gurl_base
diff --git a/polyfills/base/logging.h b/polyfills/base/logging.h index 3d7aadc..42a5068 100644 --- a/polyfills/base/logging.h +++ b/polyfills/base/logging.h
@@ -36,6 +36,6 @@ #define GURL_DCHECK(statement) GurlFakeLogSink({statement}) #define GURL_DLOG(severity) GurlFakeLogSink(true) #define GURL_LOG(severity) GurlFakeLogSink(true) -#define GURL_NOTREACHED() +#define GURL_NOTREACHED() GurlFakeLogSink(true) #endif /* POLYFILLS_BASE_LOGGING_H_ */
diff --git a/url/gurl.cc b/url/gurl.cc index 73e1070..dea8c7a 100644 --- a/url/gurl.cc +++ b/url/gurl.cc
@@ -13,6 +13,7 @@ #include "polyfills/base/check_op.h" #include "base/no_destructor.h" +#include "polyfills/base/notreached.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" @@ -158,7 +159,9 @@ if (is_valid_ || spec_.empty()) return spec_; - GURL_DCHECK(false) << "Trying to get the spec of an invalid URL!"; + // TODO(crbug.com/851128): Make sure this no longer hits before making + // NOTREACHED_NORETURN(); + GURL_NOTREACHED() << "Trying to get the spec of an invalid URL!"; return gurl_base::EmptyString(); }
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc index dd19af2..da0fb68 100644 --- a/url/url_canon_internal.cc +++ b/url/url_canon_internal.cc
@@ -81,10 +81,11 @@ } for (; i < length; i++) { if (static_cast<UCHAR>(source[i]) >= 0x80) { - // ReadChar will fill the code point with kUnicodeReplacementCharacter - // when the input is invalid, which is what we want. + // ReadUTFCharLossy will fill the code point with + // kUnicodeReplacementCharacter when the input is invalid, which is what + // we want. base_icu::UChar32 code_point; - ReadUTFChar(source, &i, length, &code_point); + ReadUTFCharLossy(source, &i, length, &code_point); AppendUTF8EscapedValue(code_point, output); } else { // Just append the 7-bit character, possibly escaping it. @@ -312,24 +313,22 @@ DoAppendStringOfType<char16_t, char16_t>(source, length, type, output); } -bool ReadUTFChar(const char* str, - size_t* begin, - size_t length, - base_icu::UChar32* code_point_out) { - if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out) || - !gurl_base::IsValidCharacter(*code_point_out)) { +bool ReadUTFCharLossy(const char* str, + size_t* begin, + size_t length, + base_icu::UChar32* code_point_out) { + if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out)) { *code_point_out = kUnicodeReplacementCharacter; return false; } return true; } -bool ReadUTFChar(const char16_t* str, - size_t* begin, - size_t length, - base_icu::UChar32* code_point_out) { - if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out) || - !gurl_base::IsValidCharacter(*code_point_out)) { +bool ReadUTFCharLossy(const char16_t* str, + size_t* begin, + size_t length, + base_icu::UChar32* code_point_out) { + if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out)) { *code_point_out = kUnicodeReplacementCharacter; return false; } @@ -356,7 +355,7 @@ bool success = true; for (size_t i = 0; i < input_len; i++) { base_icu::UChar32 code_point; - success &= ReadUTFChar(input, &i, input_len, &code_point); + success &= ReadUTFCharLossy(input, &i, input_len, &code_point); AppendUTF8Value(code_point, output); } return success; @@ -368,7 +367,7 @@ bool success = true; for (size_t i = 0; i < input_len; i++) { base_icu::UChar32 code_point; - success &= ReadUTFChar(input, &i, input_len, &code_point); + success &= ReadUTFCharLossy(input, &i, input_len, &code_point); AppendUTF16Value(code_point, output); } return success;
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h index b9ac5bf..199a8b7 100644 --- a/url/url_canon_internal.h +++ b/url/url_canon_internal.h
@@ -144,19 +144,19 @@ // UTF-8 functions ------------------------------------------------------------ -// Reads one character in UTF-8 starting at |*begin| in |str| and places -// the decoded value into |*code_point|. If the character is valid, we will -// return true. If invalid, we'll return false and put the -// kUnicodeReplacementCharacter into |*code_point|. +// Reads one character in UTF-8 starting at |*begin| in |str|, places +// the decoded value into |*code_point|, and returns true on success. +// Otherwise, we'll return false and put the kUnicodeReplacementCharacter +// into |*code_point|. // // |*begin| will be updated to point to the last character consumed so it // can be incremented in a loop and will be ready for the next character. // (for a single-byte ASCII character, it will not be changed). COMPONENT_EXPORT(URL) -bool ReadUTFChar(const char* str, - size_t* begin, - size_t length, - base_icu::UChar32* code_point_out); +bool ReadUTFCharLossy(const char* str, + size_t* begin, + size_t length, + base_icu::UChar32* code_point_out); // Generic To-UTF-8 converter. This will call the given append method for each // character that should be appended, with the given output method. Wrappers @@ -216,19 +216,19 @@ // UTF-16 functions ----------------------------------------------------------- -// Reads one character in UTF-16 starting at |*begin| in |str| and places -// the decoded value into |*code_point|. If the character is valid, we will -// return true. If invalid, we'll return false and put the -// kUnicodeReplacementCharacter into |*code_point|. +// Reads one character in UTF-16 starting at |*begin| in |str|, places +// the decoded value into |*code_point|, and returns true on success. +// Otherwise, we'll return false and put the kUnicodeReplacementCharacter +// into |*code_point|. // // |*begin| will be updated to point to the last character consumed so it // can be incremented in a loop and will be ready for the next character. // (for a single-16-bit-word character, it will not be changed). COMPONENT_EXPORT(URL) -bool ReadUTFChar(const char16_t* str, - size_t* begin, - size_t length, - base_icu::UChar32* code_point_out); +bool ReadUTFCharLossy(const char16_t* str, + size_t* begin, + size_t length, + base_icu::UChar32* code_point_out); // Equivalent to U16_APPEND_UNSAFE in ICU but uses our output method. inline void AppendUTF16Value(base_icu::UChar32 code_point, @@ -266,11 +266,11 @@ size_t* begin, size_t length, CanonOutput* output) { - // UTF-16 input. ReadUTFChar will handle invalid characters for us and give - // us the kUnicodeReplacementCharacter, so we don't have to do special + // UTF-16 input. ReadUTFCharLossy will handle invalid characters for us and + // give us the kUnicodeReplacementCharacter, so we don't have to do special // checking after failure, just pass through the failure to the caller. base_icu::UChar32 char_value; - bool success = ReadUTFChar(str, begin, length, &char_value); + bool success = ReadUTFCharLossy(str, begin, length, &char_value); AppendUTF8EscapedValue(char_value, output); return success; } @@ -280,11 +280,11 @@ size_t* begin, size_t length, CanonOutput* output) { - // ReadUTF8Char will handle invalid characters for us and give us the + // ReadUTFCharLossy will handle invalid characters for us and give us the // kUnicodeReplacementCharacter, so we don't have to do special checking // after failure, just pass through the failure to the caller. base_icu::UChar32 ch; - bool success = ReadUTFChar(str, begin, length, &ch); + bool success = ReadUTFCharLossy(str, begin, length, &ch); AppendUTF8EscapedValue(ch, output); return success; }
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index db875a8..e927f74 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -335,13 +335,10 @@ L"bar.com", "www.foo.bar.com", Component(0, 15), CanonHostInfo::NEUTRAL, -1, ""}, // Invalid unicode characters should fail... - // ...In wide input, ICU will barf and we'll end up with the input as - // escaped UTF-8 (the invalid character should be replaced with the - // replacement character). - {"\xef\xb7\x90zyx.com", L"\xfdd0zyx.com", "%EF%BF%BDzyx.com", + {"\xef\xb7\x90zyx.com", L"\xfdd0zyx.com", "%EF%B7%90zyx.com", Component(0, 16), CanonHostInfo::BROKEN, -1, ""}, // ...This is the same as previous but with with escaped. - {"%ef%b7%90zyx.com", L"%ef%b7%90zyx.com", "%EF%BF%BDzyx.com", + {"%ef%b7%90zyx.com", L"%ef%b7%90zyx.com", "%EF%B7%90zyx.com", Component(0, 16), CanonHostInfo::BROKEN, -1, ""}, // Test name prepping, fullwidth input should be converted to ASCII and // NOT @@ -1083,7 +1080,7 @@ test_utils::TruncateWStringToUTF16(L"\xfdd0zyx.com").c_str(), Component(0, 8), &output)); output.Complete(); - EXPECT_EQ("%EF%BF%BDzyx.com", out_str); + EXPECT_EQ("%EF%B7%90zyx.com", out_str); } // Should return true for empty input strings. @@ -1325,10 +1322,9 @@ {"/\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd", L"/\x4f60\x597d\x4f60\x597d", "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD", Component(0, 37), true}, - // Invalid unicode characters should fail. We only do validation on - // UTF-16 input, so this doesn't happen on 8-bit. + // Unicode Noncharacter (U+FDD0) should not fail. {"/\xef\xb7\x90zyx", nullptr, "/%EF%B7%90zyx", Component(0, 13), true}, - {nullptr, L"/\xfdd0zyx", "/%EF%BF%BDzyx", Component(0, 13), false}, + {nullptr, L"/\xfdd0zyx", "/%EF%B7%90zyx", Component(0, 13), true}, }; typedef bool (*CanonFunc8Bit)(const char*, @@ -1507,7 +1503,7 @@ {"\xc2", nullptr, "#%EF%BF%BD", Component(1, 9), true}, {nullptr, L"\xd800\x597d", "#%EF%BF%BD%E5%A5%BD", Component(1, 18), true}, // Test a Unicode invalid character. - {"a\xef\xb7\x90", L"a\xfdd0", "#a%EF%BF%BD", Component(1, 10), true}, + {"a\xef\xb7\x90", L"a\xfdd0", "#a%EF%B7%90", Component(1, 10), true}, // Refs can have # signs and we should preserve them. {"asdf#qwer", L"asdf#qwer", "#asdf#qwer", Component(1, 9), true}, {"#asdf", L"#asdf", "##asdf", Component(1, 5), true}, @@ -2129,9 +2125,9 @@ {"JavaScript:Foo", "javascript:Foo"}, {"Foo:\":This /is interesting;?#", "foo:\":This /is interesting;?#"}, - // Validation errors should not cause failure. See + // Unicode invalid characters should not cause failure. See // https://crbug.com/925614. - {"javascript:\uFFFF", "javascript:%EF%BF%BD"}, + {"javascript:\uFFFF", "javascript:%EF%BF%BF"}, }; for (size_t i = 0; i < std::size(path_cases); i++) { @@ -2169,7 +2165,7 @@ {"Foo", L"Foo", "Foo"}, {"\":This /is interesting;?#", L"\":This /is interesting;?#", "\":This /is interesting;?#"}, - {"\uFFFF", L"\uFFFF", "%EF%BF%BD"}, + {"\uFFFF", L"\uFFFF", "%EF%BF%BF"}, }; for (size_t i = 0; i < std::size(path_cases); i++) {
diff --git a/url/url_features.cc b/url/url_features.cc index b82afd7..3602bdd 100644 --- a/url/url_features.cc +++ b/url/url_features.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "url/url_features.h" +#include "polyfills/base/feature_list.h" namespace url { @@ -25,6 +26,13 @@ gurl_base::FEATURE_ENABLED_BY_DEFAULT); bool IsUsingIDNA2008NonTransitional() { + // If the FeatureList isn't available yet, fall back to the feature's default + // state. This may happen during early startup, see crbug.com/1441956. + if (!gurl_base::FeatureList::GetInstance()) { + return kUseIDNA2008NonTransitional.default_state == + gurl_base::FEATURE_ENABLED_BY_DEFAULT; + } + return gurl_base::FeatureList::IsEnabled(kUseIDNA2008NonTransitional); }
diff --git a/url/url_idna_ascii_only.cc b/url/url_idna_ascii_only.cc index 2a4f0d3..921858a 100644 --- a/url/url_idna_ascii_only.cc +++ b/url/url_idna_ascii_only.cc
@@ -12,6 +12,10 @@ #include "base/strings/utf_string_conversions.h" #include "url/url_canon_internal.h" +#if false +#error "This file requires ARC support." +#endif + namespace url { // Only allow ASCII to avoid ICU dependency. Use NSString+IDN
diff --git a/url/url_util.cc b/url/url_util.cc index 705ec2e..1fb663e 100644 --- a/url/url_util.cc +++ b/url/url_util.cc
@@ -885,8 +885,8 @@ // character. size_t next_character = i; base_icu::UChar32 code_point; - if (ReadUTFChar(unescaped_chars.data(), &next_character, unescaped_length, - &code_point)) { + if (ReadUTFCharLossy(unescaped_chars.data(), &next_character, + unescaped_length, &code_point)) { // Valid UTF-8 character, convert to UTF-16. AppendUTF16Value(code_point, output); i = next_character;
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc index a220af9..b052c3d 100644 --- a/url/url_util_unittest.cc +++ b/url/url_util_unittest.cc
@@ -247,6 +247,13 @@ {"%70%71%72%73%74%75%76%77%78%79%7a%7B%7C%7D%7e%7f/", "pqrstuvwxyz{|}~\x7f/"}, {"%e4%bd%a0%e5%a5%bd", "\xe4\xbd\xa0\xe5\xa5\xbd"}, + // U+FFFF (Noncharacter) should not be replaced with U+FFFD (Replacement + // Character) (http://crbug.com/1416021) + {"%ef%bf%bf", "\xef\xbf\xbf"}, + // U+FDD0 (Noncharacter) + {"%ef%b7%90", "\xef\xb7\x90"}, + // U+FFFD (Replacement Character) + {"%ef%bf%bd", "\xef\xbf\xbd"}, }; for (size_t i = 0; i < std::size(decode_cases); i++) {