Revert "Roll chromium_revision e1ef7d4b6b..b47e7752c6 (568794:569173)"

This reverts commit fd2457b10fc2713bfd5d86952216cf89b6283a90.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> Roll chromium_revision e1ef7d4b6b..b47e7752c6 (568794:569173)
> 
> Change log: e1ef7d4b6b..b47e7752c6
> Full diff: e1ef7d4b6b..b47e7752c6
> 
> Roll chromium third_party ab9fbe29c9..630af48a96
> Change log: ab9fbe29c9..630af48a96
> 
> Changed dependencies:
> * src/base: 03e1bc561f..6070b24b9f
> * src/build: bb306be407..511e258eee
> * src/ios: 48697bf3a1..ce1db7deb1
> * src/testing: 6440c4ea3a..80a4cfaab7
> * src/third_party/catapult: https://chromium.googlesource.com/catapult.git/+log/f153b902be..f3c454475a
> * src/third_party/depot_tools: 1cabdc4643..a28b14f122
> * src/tools: 66f1089d0c..f6bb2a6fb4
> DEPS diff: e1ef7d4b6b..b47e7752c6/DEPS
> 
> No update to Clang.
> 
> TBR=buildbot@webrtc.org,
> BUG=None
> CQ_INCLUDE_TRYBOTS=master.internal.tryserver.corp.webrtc:linux_internal
> NO_AUTOIMPORT_DEPS_CHECK=true
> 
> Change-Id: I7553549111225f2c5bc769dec114cd058ae699d5
> Reviewed-on: https://webrtc-review.googlesource.com/84600
> Reviewed-by: WebRTC Buildbot <buildbot@webrtc.org>
> Commit-Queue: WebRTC Buildbot <buildbot@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#23692}

TBR=buildbot@webrtc.org

Change-Id: I7d136553622fe4c4e49dbd9c60406811a8b11bd8
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: None
Cq-Include-Trybots: master.internal.tryserver.corp.webrtc:linux_internal
Reviewed-on: https://webrtc-review.googlesource.com/84720
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23708}
This commit is contained in:
Artem Titov 2018-06-21 12:53:29 +00:00 committed by Commit Bot
parent 0bc58cf876
commit cb76c70534
49 changed files with 463 additions and 4828 deletions

18
DEPS
View File

@ -10,7 +10,7 @@ vars = {
'checkout_configuration': 'default',
'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
'webrtc_git': 'https://webrtc.googlesource.com',
'chromium_revision': 'b47e7752c62752e9f97cd658c7aa9532ef688c11',
'chromium_revision': 'e1ef7d4b6ba51e51817556f44f71b95d0c64f106',
'boringssl_git': 'https://boringssl.googlesource.com',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling swarming_client
@ -27,7 +27,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling catapult
# and whatever else without interference from each other.
'catapult_revision': 'f3c454475aeea9450e3f90de9e9430a335795496',
'catapult_revision': 'f153b902bec3811dd5faa9e807240b059e7bbc8c',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libFuzzer
# and whatever else without interference from each other.
@ -43,15 +43,15 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Chromium third_party
# and whatever else without interference from each other.
'chromium_third_party_revision': '630af48a96cff39e916a4fe8407a416ced2f903d',
'chromium_third_party_revision': 'ab9fbe29c97f030a4787abf517e4902895c757f1',
}
deps = {
# TODO(kjellander): Move this to be Android-only once the libevent dependency
# in base/third_party/libevent is solved.
'src/base':
Var('chromium_git') + '/chromium/src/base' + '@' + '6070b24b9f085d50c902f49117813f7f88f9df3a',
Var('chromium_git') + '/chromium/src/base' + '@' + '03e1bc561f08357987d0a3b1a6306b378cd61c04',
'src/build':
Var('chromium_git') + '/chromium/src/build' + '@' + '511e258eee11fe61e6da8ea709bd9f6d0d5724a9',
Var('chromium_git') + '/chromium/src/build' + '@' + 'bb306be4076914cdd287517d8480851a410d7788',
'src/buildtools':
Var('chromium_git') + '/chromium/buildtools.git' + '@' + '5941c1b3df96c1db756a2834343533335c394c4a',
# Gradle 4.3-rc4. Used for testing Android Studio project generation for WebRTC.
@ -61,11 +61,11 @@ deps = {
'condition': 'checkout_android',
},
'src/ios': {
'url': Var('chromium_git') + '/chromium/src/ios' + '@' + 'ce1db7deb10ab0338f08fa987802fed7643e2f72',
'url': Var('chromium_git') + '/chromium/src/ios' + '@' + '48697bf3a10f61dbd71c30722640efbbec82d3e2',
'condition': 'checkout_ios',
},
'src/testing':
Var('chromium_git') + '/chromium/src/testing' + '@' + '80a4cfaab736971e0bf001e16af6dfd625e48955',
Var('chromium_git') + '/chromium/src/testing' + '@' + '6440c4ea3ae95d9142ae72fdd55c6406ad0df00b',
# This entry is used for chromium third_party rolling into webrtc third_party only.
'src/third_party_chromium': {
'url': Var('chromium_git') + '/chromium/src/third_party' + '@' + Var('chromium_third_party_revision'),
@ -94,7 +94,7 @@ deps = {
'src/third_party/colorama/src':
Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
'src/third_party/depot_tools':
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a28b14f122463a6d73c623e77c9dea4e228322dc',
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1cabdc464313eee47fdc52a95b3f8e028680000d',
'src/third_party/errorprone/lib': {
'url': Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '980d49e839aa4984015efed34b0134d4b2c9b6d7',
'condition': 'checkout_android',
@ -185,7 +185,7 @@ deps = {
'src/third_party/yasm/source/patched-yasm':
Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc',
'src/tools':
Var('chromium_git') + '/chromium/src/tools' + '@' + 'f6bb2a6fb4184f9078751592a7174cb389b94fef',
Var('chromium_git') + '/chromium/src/tools' + '@' + '66f1089d0cd8b57081b77d828ee6f6c46a64a0c0',
'src/tools/swarming_client':
Var('chromium_git') + '/infra/luci/client-py.git' + '@' + Var('swarming_revision'),

View File

@ -4,7 +4,7 @@ URL: https://github.com/abseil/abseil-cpp
License: Apache 2.0
License File: LICENSE
Version: 0
Revision: bd40a41cc142b36c73b881099d08a9d83f7f4780
Revision: e5be80532b5d998813f9db952d2cc5401b1532df
Security Critical: yes
Description:

View File

@ -1,13 +1,13 @@
workspace(name = "com_google_absl")
# Bazel toolchains
http_archive(
name = "bazel_toolchains",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/2cec6c9f6d12224e93d9b3f337b24e41602de3ba.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/2cec6c9f6d12224e93d9b3f337b24e41602de3ba.tar.gz",
],
strip_prefix = "bazel-toolchains-2cec6c9f6d12224e93d9b3f337b24e41602de3ba",
sha256 = "9b8d85b61d8945422e86ac31e4d4d2d967542c080d1da1b45364da7fd6bdd638",
name = "bazel_toolchains",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/f8847f64e6950e8ab9fde1c0aba768550b0d9ab2.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/f8847f64e6950e8ab9fde1c0aba768550b0d9ab2.tar.gz",
],
strip_prefix = "bazel-toolchains-f8847f64e6950e8ab9fde1c0aba768550b0d9ab2",
sha256 = "794366f51fea224b3656a0b0f8f1518e739748646523a572fcd3d68614a0e670",
)
# GoogleTest/GoogleMock framework. Used by most unit-tests.
@ -15,7 +15,6 @@ http_archive(
name = "com_google_googletest",
urls = ["https://github.com/google/googletest/archive/4e4df226fc197c0dda6e37f5c8c3845ca1e73a49.zip"],
strip_prefix = "googletest-4e4df226fc197c0dda6e37f5c8c3845ca1e73a49",
sha256 = "d4179caf54410968d1fff0b869e7d74803dd30209ee6645ccf1ca65ab6cf5e5a",
)
# Google benchmark.
@ -23,7 +22,6 @@ http_archive(
name = "com_github_google_benchmark",
urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
)
# RE2 regular-expression framework. Used by some unit-tests.
@ -31,5 +29,4 @@ http_archive(
name = "com_googlesource_code_re2",
urls = ["https://github.com/google/re2/archive/6cf8ccd82dbaab2668e9b13596c68183c9ecd13f.zip"],
strip_prefix = "re2-6cf8ccd82dbaab2668e9b13596c68183c9ecd13f",
sha256 = "279a852219dbfc504501775596089d30e9c0b29664ce4128b0ac4c841471a16a",
)

View File

@ -1,13 +0,0 @@
# Long Term Support (LTS) Branches
This repository contains periodic snapshots of the Abseil codebase that are
Long Term Support (LTS) branches. An LTS branch allows you to use a known
version of Abseil without interfering with other projects which may also, in
turn, use Abseil. (For more information about our releases, see the
[Abseil Release Management](https://abseil.io/about/releases) guide.
## LTS Branches
The following lists LTS branches and the date they have been released:
* [LTS Branch June 18, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_18/)

View File

@ -371,6 +371,11 @@ cc_test(
size = "small",
srcs = ["internal/sysinfo_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
],
deps = [
":base",
"//absl/synchronization",

View File

@ -27,7 +27,7 @@ struct identity {
template <typename T>
using identity_t = typename identity<T>::type;
} // namespace internal
} // namespace absl
} // namespace internal
} // namespace absl
#endif // ABSL_BASE_INTERNAL_IDENTITY_H_

View File

@ -84,7 +84,7 @@ inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,
inline void absl::base_internal::SpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode) {
base_internal::SchedulingMode scheduling_mode) {
AbslInternalSpinLockDelay(w, value, loop, scheduling_mode);
}

View File

@ -194,9 +194,8 @@ enum LinkerInitialized {
#if defined(NDEBUG)
#define ABSL_ASSERT(expr) (false ? (void)(expr) : (void)0)
#else
#define ABSL_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? (void)0 \
: [] { assert(false && #expr); }()) // NOLINT
#define ABSL_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? (void)0 : [] { assert(false && #expr); }())
#endif
#endif // ABSL_BASE_MACROS_H_

View File

@ -63,34 +63,18 @@ void BM_StdVectorFill(benchmark::State& state) {
}
BENCHMARK(BM_StdVectorFill)->Range(0, 1024);
// The purpose of the next two benchmarks is to verify that
// absl::InlinedVector is efficient when moving is more efficent than
// copying. To do so, we use strings that are larger than the short
// std::string optimization.
bool StringRepresentedInline(std::string s) {
const char* chars = s.data();
std::string s1 = std::move(s);
return s1.data() != chars;
}
int GetNonShortStringOptimizationSize() {
for (int i = 24; i <= 192; i *= 2) {
if (!StringRepresentedInline(std::string(i, 'A'))) {
return i;
}
}
ABSL_RAW_LOG(
FATAL,
"Failed to find a std::string larger than the short std::string optimization");
return -1;
}
void BM_InlinedVectorFillString(benchmark::State& state) {
const int len = state.range(0);
const int no_sso = GetNonShortStringOptimizationSize();
std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
std::string(no_sso, 'C'), std::string(no_sso, 'D')};
std::string strings[4] = {"a quite long string",
"another long string",
"012345678901234567",
"to cause allocation"};
for (auto _ : state) {
absl::InlinedVector<std::string, 8> v;
for (int i = 0; i < len; i++) {
@ -103,10 +87,10 @@ BENCHMARK(BM_InlinedVectorFillString)->Range(0, 1024);
void BM_StdVectorFillString(benchmark::State& state) {
const int len = state.range(0);
const int no_sso = GetNonShortStringOptimizationSize();
std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
std::string(no_sso, 'C'), std::string(no_sso, 'D')};
std::string strings[4] = {"a quite long string",
"another long string",
"012345678901234567",
"to cause allocation"};
for (auto _ : state) {
std::vector<std::string> v;
for (int i = 0; i < len; i++) {
@ -114,6 +98,11 @@ void BM_StdVectorFillString(benchmark::State& state) {
}
}
state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
// The purpose of the benchmark is to verify that inlined vector is
// efficient when moving is more efficent than copying. To do so, we
// use strings that are larger than the small std::string optimization.
ABSL_RAW_CHECK(!StringRepresentedInline(strings[0]),
"benchmarked with strings that are too small");
}
BENCHMARK(BM_StdVectorFillString)->Range(0, 1024);

View File

@ -18,7 +18,6 @@ load(
"//absl:copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
)
package(default_visibility = ["//visibility:public"])
@ -46,16 +45,3 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "memory_exception_safety_test",
srcs = [
"memory_exception_safety_test.cc",
],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
deps = [
":memory",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
)

View File

@ -49,23 +49,4 @@ absl_test(
)
# test memory_exception_safety_test
set(MEMORY_EXCEPTION_SAFETY_TEST_SRC "memory_exception_safety_test.cc")
set(MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
absl::memory
absl_base_internal_exception_safety_testing
)
absl_test(
TARGET
memory_exception_safety_test
SOURCES
${MEMORY_EXCEPTION_SAFETY_TEST_SRC}
PUBLIC_LIBRARIES
${MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
PRIVATE_COMPILE_FLAGS
${ABSL_EXCEPTIONS_FLAG}
)

View File

@ -1,49 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/memory/memory.h"
#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
namespace {
using Thrower = ::testing::ThrowingValue<>;
TEST(MakeUnique, CheckForLeaks) {
constexpr int kValue = 321;
constexpr size_t kLength = 10;
auto tester = testing::MakeExceptionSafetyTester()
.WithInitialValue(Thrower(kValue))
// Ensures make_unique does not modify the input. The real
// test, though, is ConstructorTracker checking for leaks.
.WithInvariants(testing::strong_guarantee);
EXPECT_TRUE(tester.Test([](Thrower* thrower) {
static_cast<void>(absl::make_unique<Thrower>(*thrower));
}));
EXPECT_TRUE(tester.Test([](Thrower* thrower) {
static_cast<void>(absl::make_unique<Thrower>(std::move(*thrower)));
}));
// Test T[n] overload
EXPECT_TRUE(tester.Test([&](Thrower*) {
static_cast<void>(absl::make_unique<Thrower[]>(kLength));
}));
}
} // namespace
} // namespace absl

View File

@ -32,12 +32,7 @@ cc_library(
name = "strings",
srcs = [
"ascii.cc",
"charconv.cc",
"escaping.cc",
"internal/charconv_bigint.cc",
"internal/charconv_bigint.h",
"internal/charconv_parse.cc",
"internal/charconv_parse.h",
"internal/memutil.cc",
"internal/memutil.h",
"internal/stl_type_traits.h",
@ -53,7 +48,6 @@ cc_library(
],
hdrs = [
"ascii.h",
"charconv.h",
"escaping.h",
"match.h",
"numbers.h",
@ -150,6 +144,11 @@ cc_test(
size = "small",
srcs = ["ascii_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
],
visibility = ["//visibility:private"],
deps = [
":strings",
@ -399,6 +398,12 @@ cc_test(
"numbers_test.cc",
],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
"no_test_loonix",
],
visibility = ["//visibility:private"],
deps = [
":strings",
@ -424,6 +429,11 @@ cc_test(
name = "char_map_test",
srcs = ["internal/char_map_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
],
deps = [
":internal",
"@com_google_googletest//:gtest_main",
@ -440,55 +450,3 @@ cc_test(
"@com_github_google_benchmark//:benchmark_main",
],
)
cc_test(
name = "charconv_test",
srcs = ["charconv_test.cc"],
copts = ABSL_TEST_COPTS,
deps = [
":strings",
"//absl/base",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "charconv_parse_test",
srcs = [
"internal/charconv_parse.h",
"internal/charconv_parse_test.cc",
],
copts = ABSL_TEST_COPTS,
deps = [
":strings",
"//absl/base",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "charconv_bigint_test",
srcs = [
"internal/charconv_bigint.h",
"internal/charconv_bigint_test.cc",
"internal/charconv_parse.h",
],
copts = ABSL_TEST_COPTS,
deps = [
":strings",
"//absl/base",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "charconv_benchmark",
srcs = [
"charconv_benchmark.cc",
],
deps = [
":strings",
"//absl/base",
"@com_github_google_benchmark//:benchmark_main",
],
)

View File

@ -22,12 +22,7 @@ source_set("strings") {
public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
sources = [
"ascii.cc",
"charconv.cc",
"escaping.cc",
"internal/charconv_bigint.cc",
"internal/charconv_bigint.h",
"internal/charconv_parse.cc",
"internal/charconv_parse.h",
"internal/memutil.cc",
"internal/memutil.h",
"internal/stl_type_traits.h",
@ -43,7 +38,6 @@ source_set("strings") {
]
public = [
"ascii.h",
"charconv.h",
"escaping.h",
"match.h",
"numbers.h",

View File

@ -17,7 +17,6 @@
list(APPEND STRINGS_PUBLIC_HEADERS
"ascii.h"
"charconv.h"
"escaping.h"
"match.h"
"numbers.h"
@ -34,8 +33,6 @@ list(APPEND STRINGS_PUBLIC_HEADERS
list(APPEND STRINGS_INTERNAL_HEADERS
"internal/bits.h"
"internal/char_map.h"
"internal/charconv_bigint.h"
"internal/charconv_parse.h"
"internal/memutil.h"
"internal/ostringstream.h"
"internal/resize_uninitialized.h"
@ -50,10 +47,7 @@ list(APPEND STRINGS_INTERNAL_HEADERS
# add string library
list(APPEND STRINGS_SRC
"ascii.cc"
"charconv.cc"
"escaping.cc"
"internal/charconv_bigint.cc"
"internal/charconv_parse.cc"
"internal/memutil.cc"
"internal/memutil.h"
"internal/utf8.cc"
@ -307,43 +301,5 @@ absl_test(
)
# test charconv_test
set(CHARCONV_TEST_SRC "charconv_test.cc")
set(CHARCONV_TEST_PUBLIC_LIBRARIES absl::strings)
absl_test(
TARGET
charconv_test
SOURCES
${CHARCONV_TEST_SRC}
PUBLIC_LIBRARIES
${CHARCONV_TEST_PUBLIC_LIBRARIES}
)
# test charconv_parse_test
set(CHARCONV_PARSE_TEST_SRC "internal/charconv_parse_test.cc")
set(CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES absl::strings)
absl_test(
TARGET
charconv_parse_test
SOURCES
${CHARCONV_PARSE_TEST_SRC}
PUBLIC_LIBRARIES
${CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES}
)
# test charconv_bigint_test
set(CHARCONV_BIGINT_TEST_SRC "internal/charconv_bigint_test.cc")
set(CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES absl::strings)
absl_test(
TARGET
charconv_bigint_test
SOURCES
${CHARCONV_BIGINT_TEST_SRC}
PUBLIC_LIBRARIES
${CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES}
)

View File

@ -1,982 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/charconv.h"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include "absl/base/casts.h"
#include "absl/numeric/int128.h"
#include "absl/strings/internal/bits.h"
#include "absl/strings/internal/charconv_bigint.h"
#include "absl/strings/internal/charconv_parse.h"
// The macro ABSL_BIT_PACK_FLOATS is defined on x86-64, where IEEE floating
// point numbers have the same endianness in memory as a bitfield struct
// containing the corresponding parts.
//
// When set, we replace calls to ldexp() with manual bit packing, which is
// faster and is unaffected by floating point environment.
#ifdef ABSL_BIT_PACK_FLOATS
#error ABSL_BIT_PACK_FLOATS cannot be directly set
#elif defined(__x86_64__) || defined(_M_X64)
#define ABSL_BIT_PACK_FLOATS 1
#endif
// A note about subnormals:
//
// The code below talks about "normals" and "subnormals". A normal IEEE float
// has a fixed-width mantissa and power of two exponent. For example, a normal
// `double` has a 53-bit mantissa. Because the high bit is always 1, it is not
// stored in the representation. The implicit bit buys an extra bit of
// resolution in the datatype.
//
// The downside of this scheme is that there is a large gap between DBL_MIN and
// zero. (Large, at least, relative to the different between DBL_MIN and the
// next representable number). This gap is softened by the "subnormal" numbers,
// which have the same power-of-two exponent as DBL_MIN, but no implicit 53rd
// bit. An all-bits-zero exponent in the encoding represents subnormals. (Zero
// is represented as a subnormal with an all-bits-zero mantissa.)
//
// The code below, in calculations, represents the mantissa as a uint64_t. The
// end result normally has the 53rd bit set. It represents subnormals by using
// narrower mantissas.
namespace absl {
namespace {
template <typename FloatType>
struct FloatTraits;
template <>
struct FloatTraits<double> {
// The number of mantissa bits in the given float type. This includes the
// implied high bit.
static constexpr int kTargetMantissaBits = 53;
// The largest supported IEEE exponent, in our integral mantissa
// representation.
//
// If `m` is the largest possible int kTargetMantissaBits bits wide, then
// m * 2**kMaxExponent is exactly equal to DBL_MAX.
static constexpr int kMaxExponent = 971;
// The smallest supported IEEE normal exponent, in our integral mantissa
// representation.
//
// If `m` is the smallest possible int kTargetMantissaBits bits wide, then
// m * 2**kMinNormalExponent is exactly equal to DBL_MIN.
static constexpr int kMinNormalExponent = -1074;
static double MakeNan(const char* tagp) {
// Support nan no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
using namespace std; // NOLINT
return nan(tagp);
}
// Builds a nonzero floating point number out of the provided parts.
//
// This is intended to do the same operation as ldexp(mantissa, exponent),
// but using purely integer math, to avoid -ffastmath and floating
// point environment issues. Using type punning is also faster. We fall back
// to ldexp on a per-platform basis for portability.
//
// `exponent` must be between kMinNormalExponent and kMaxExponent.
//
// `mantissa` must either be exactly kTargetMantissaBits wide, in which case
// a normal value is made, or it must be less narrow than that, in which case
// `exponent` must be exactly kMinNormalExponent, and a subnormal value is
// made.
static double Make(uint64_t mantissa, int exponent, bool sign) {
#ifndef ABSL_BIT_PACK_FLOATS
// Support ldexp no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
using namespace std; // NOLINT
return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent);
#else
constexpr uint64_t kMantissaMask =
(uint64_t(1) << (kTargetMantissaBits - 1)) - 1;
uint64_t dbl = static_cast<uint64_t>(sign) << 63;
if (mantissa > kMantissaMask) {
// Normal value.
// Adjust by 1023 for the exponent representation bias, and an additional
// 52 due to the implied decimal point in the IEEE mantissa represenation.
dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52;
mantissa &= kMantissaMask;
} else {
// subnormal value
assert(exponent == kMinNormalExponent);
}
dbl += mantissa;
return absl::bit_cast<double>(dbl);
#endif // ABSL_BIT_PACK_FLOATS
}
};
// Specialization of floating point traits for the `float` type. See the
// FloatTraits<double> specialization above for meaning of each of the following
// members and methods.
template <>
struct FloatTraits<float> {
static constexpr int kTargetMantissaBits = 24;
static constexpr int kMaxExponent = 104;
static constexpr int kMinNormalExponent = -149;
static float MakeNan(const char* tagp) {
// Support nanf no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
using namespace std; // NOLINT
return nanf(tagp);
}
static float Make(uint32_t mantissa, int exponent, bool sign) {
#ifndef ABSL_BIT_PACK_FLOATS
// Support ldexpf no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
using namespace std; // NOLINT
return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent);
#else
constexpr uint32_t kMantissaMask =
(uint32_t(1) << (kTargetMantissaBits - 1)) - 1;
uint32_t flt = static_cast<uint32_t>(sign) << 31;
if (mantissa > kMantissaMask) {
// Normal value.
// Adjust by 127 for the exponent representation bias, and an additional
// 23 due to the implied decimal point in the IEEE mantissa represenation.
flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23;
mantissa &= kMantissaMask;
} else {
// subnormal value
assert(exponent == kMinNormalExponent);
}
flt += mantissa;
return absl::bit_cast<float>(flt);
#endif // ABSL_BIT_PACK_FLOATS
}
};
// Decimal-to-binary conversions require coercing powers of 10 into a mantissa
// and a power of 2. The two helper functions Power10Mantissa(n) and
// Power10Exponent(n) perform this task. Together, these represent a hand-
// rolled floating point value which is equal to or just less than 10**n.
//
// The return values satisfy two range guarantees:
//
// Power10Mantissa(n) * 2**Power10Exponent(n) <= 10**n
// < (Power10Mantissa(n) + 1) * 2**Power10Exponent(n)
//
// 2**63 <= Power10Mantissa(n) < 2**64.
//
// Lookups into the power-of-10 table must first check the Power10Overflow() and
// Power10Underflow() functions, to avoid out-of-bounds table access.
//
// Indexes into these tables are biased by -kPower10TableMin, and the table has
// values in the range [kPower10TableMin, kPower10TableMax].
extern const uint64_t kPower10MantissaTable[];
extern const int16_t kPower10ExponentTable[];
// The smallest allowed value for use with the Power10Mantissa() and
// Power10Exponent() functions below. (If a smaller exponent is needed in
// calculations, the end result is guaranteed to underflow.)
constexpr int kPower10TableMin = -342;
// The largest allowed value for use with the Power10Mantissa() and
// Power10Exponent() functions below. (If a smaller exponent is needed in
// calculations, the end result is guaranteed to overflow.)
constexpr int kPower10TableMax = 308;
uint64_t Power10Mantissa(int n) {
return kPower10MantissaTable[n - kPower10TableMin];
}
int Power10Exponent(int n) {
return kPower10ExponentTable[n - kPower10TableMin];
}
// Returns true if n is large enough that 10**n always results in an IEEE
// overflow.
bool Power10Overflow(int n) { return n > kPower10TableMax; }
// Returns true if n is small enough that 10**n times a ParsedFloat mantissa
// always results in an IEEE underflow.
bool Power10Underflow(int n) { return n < kPower10TableMin; }
// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal
// to 10**n numerically. Put another way, this returns true if there is no
// truncation error in Power10Mantissa(n).
bool Power10Exact(int n) { return n >= 0 && n <= 27; }
// Sentinel exponent values for representing numbers too large or too close to
// zero to represent in a double.
constexpr int kOverflow = 99999;
constexpr int kUnderflow = -99999;
// Struct representing the calculated conversion result of a positive (nonzero)
// floating point number.
//
// The calculated number is mantissa * 2**exponent (mantissa is treated as an
// integer.) `mantissa` is chosen to be the correct width for the IEEE float
// representation being calculated. (`mantissa` will always have the same bit
// width for normal values, and narrower bit widths for subnormals.)
//
// If the result of conversion was an underflow or overflow, exponent is set
// to kUnderflow or kOverflow.
struct CalculatedFloat {
uint64_t mantissa = 0;
int exponent = 0;
};
// Returns the bit width of the given uint128. (Equivalently, returns 128
// minus the number of leading zero bits.)
int BitWidth(uint128 value) {
if (Uint128High64(value) == 0) {
return 64 - strings_internal::CountLeadingZeros64(Uint128Low64(value));
}
return 128 - strings_internal::CountLeadingZeros64(Uint128High64(value));
}
// Calculates how far to the right a mantissa needs to be shifted to create a
// properly adjusted mantissa for an IEEE floating point number.
//
// `mantissa_width` is the bit width of the mantissa to be shifted, and
// `binary_exponent` is the exponent of the number before the shift.
//
// This accounts for subnormal values, and will return a larger-than-normal
// shift if binary_exponent would otherwise be too low.
template <typename FloatType>
int NormalizedShiftSize(int mantissa_width, int binary_exponent) {
const int normal_shift =
mantissa_width - FloatTraits<FloatType>::kTargetMantissaBits;
const int minimum_shift =
FloatTraits<FloatType>::kMinNormalExponent - binary_exponent;
return std::max(normal_shift, minimum_shift);
}
// Right shifts a uint128 so that it has the requested bit width. (The
// resulting value will have 128 - bit_width leading zeroes.) The initial
// `value` must be wider than the requested bit width.
//
// Returns the number of bits shifted.
int TruncateToBitWidth(int bit_width, uint128* value) {
const int current_bit_width = BitWidth(*value);
const int shift = current_bit_width - bit_width;
*value >>= shift;
return shift;
}
// Checks if the given ParsedFloat represents one of the edge cases that are
// not dependent on number base: zero, infinity, or NaN. If so, sets *value
// the appropriate double, and returns true.
template <typename FloatType>
bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
FloatType* value) {
if (input.type == strings_internal::FloatType::kNan) {
// A bug in both clang and gcc would cause the compiler to optimize away the
// buffer we are building below. Declaring the buffer volatile avoids the
// issue, and has no measurable performance impact in microbenchmarks.
//
// https://bugs.llvm.org/show_bug.cgi?id=37778
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113
constexpr ptrdiff_t kNanBufferSize = 128;
volatile char n_char_sequence[kNanBufferSize];
if (input.subrange_begin == nullptr) {
n_char_sequence[0] = '\0';
} else {
ptrdiff_t nan_size = input.subrange_end - input.subrange_begin;
nan_size = std::min(nan_size, kNanBufferSize - 1);
std::copy_n(input.subrange_begin, nan_size, n_char_sequence);
n_char_sequence[nan_size] = '\0';
}
char* nan_argument = const_cast<char*>(n_char_sequence);
*value = negative ? -FloatTraits<FloatType>::MakeNan(nan_argument)
: FloatTraits<FloatType>::MakeNan(nan_argument);
return true;
}
if (input.type == strings_internal::FloatType::kInfinity) {
*value = negative ? -std::numeric_limits<FloatType>::infinity()
: std::numeric_limits<FloatType>::infinity();
return true;
}
if (input.mantissa == 0) {
*value = negative ? -0.0 : 0.0;
return true;
}
return false;
}
// Given a CalculatedFloat result of a from_chars conversion, generate the
// correct output values.
//
// CalculatedFloat can represent an underflow or overflow, in which case the
// error code in *result is set. Otherwise, the calculated floating point
// number is stored in *value.
template <typename FloatType>
void EncodeResult(const CalculatedFloat& calculated, bool negative,
absl::from_chars_result* result, FloatType* value) {
if (calculated.exponent == kOverflow) {
result->ec = std::errc::result_out_of_range;
*value = negative ? -std::numeric_limits<FloatType>::max()
: std::numeric_limits<FloatType>::max();
return;
} else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) {
result->ec = std::errc::result_out_of_range;
*value = negative ? -0.0 : 0.0;
return;
}
*value = FloatTraits<FloatType>::Make(calculated.mantissa,
calculated.exponent, negative);
}
// Returns the given uint128 shifted to the right by `shift` bits, and rounds
// the remaining bits using round_to_nearest logic. The value is returned as a
// uint64_t, since this is the type used by this library for storing calculated
// floating point mantissas.
//
// It is expected that the width of the input value shifted by `shift` will
// be the correct bit-width for the target mantissa, which is strictly narrower
// than a uint64_t.
//
// If `input_exact` is false, then a nonzero error epsilon is assumed. For
// rounding purposes, the true value being rounded is strictly greater than the
// input value. The error may represent a single lost carry bit.
//
// When input_exact, shifted bits of the form 1000000... represent a tie, which
// is broken by rounding to even -- the rounding direction is chosen so the low
// bit of the returned value is 0.
//
// When !input_exact, shifted bits of the form 10000000... represent a value
// strictly greater than one half (due to the error epsilon), and so ties are
// always broken by rounding up.
//
// When !input_exact, shifted bits of the form 01111111... are uncertain;
// the true value may or may not be greater than 10000000..., due to the
// possible lost carry bit. The correct rounding direction is unknown. In this
// case, the result is rounded down, and `output_exact` is set to false.
//
// Zero and negative values of `shift` are accepted, in which case the word is
// shifted left, as necessary.
uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,
bool* output_exact) {
if (shift <= 0) {
*output_exact = input_exact;
return static_cast<uint64_t>(value << -shift);
}
if (shift >= 128) {
// Exponent is so small that we are shifting away all significant bits.
// Answer will not be representable, even as a subnormal, so return a zero
// mantissa (which represents underflow).
*output_exact = true;
return 0;
}
*output_exact = true;
const uint128 shift_mask = (uint128(1) << shift) - 1;
const uint128 halfway_point = uint128(1) << (shift - 1);
const uint128 shifted_bits = value & shift_mask;
value >>= shift;
if (shifted_bits > halfway_point) {
// Shifted bits greater than 10000... require rounding up.
return static_cast<uint64_t>(value + 1);
}
if (shifted_bits == halfway_point) {
// In exact mode, shifted bits of 10000... mean we're exactly halfway
// between two numbers, and we must round to even. So only round up if
// the low bit of `value` is set.
//
// In inexact mode, the nonzero error means the actual value is greater
// than the halfway point and we must alway round up.
if ((value & 1) == 1 || !input_exact) {
++value;
}
return static_cast<uint64_t>(value);
}
if (!input_exact && shifted_bits == halfway_point - 1) {
// Rounding direction is unclear, due to error.
*output_exact = false;
}
// Otherwise, round down.
return static_cast<uint64_t>(value);
}
// Checks if a floating point guess needs to be rounded up, using high precision
// math.
//
// `guess_mantissa` and `guess_exponent` represent a candidate guess for the
// number represented by `parsed_decimal`.
//
// The exact number represented by `parsed_decimal` must lie between the two
// numbers:
// A = `guess_mantissa * 2**guess_exponent`
// B = `(guess_mantissa + 1) * 2**guess_exponent`
//
// This function returns false if `A` is the better guess, and true if `B` is
// the better guess, with rounding ties broken by rounding to even.
bool MustRoundUp(uint64_t guess_mantissa, int guess_exponent,
const strings_internal::ParsedFloat& parsed_decimal) {
// 768 is the number of digits needed in the worst case. We could determine a
// better limit dynamically based on the value of parsed_decimal.exponent.
// This would optimize pathological input cases only. (Sane inputs won't have
// hundreds of digits of mantissa.)
absl::strings_internal::BigUnsigned<84> exact_mantissa;
int exact_exponent = exact_mantissa.ReadFloatMantissa(parsed_decimal, 768);
// Adjust the `guess` arguments to be halfway between A and B.
guess_mantissa = guess_mantissa * 2 + 1;
guess_exponent -= 1;
// In our comparison:
// lhs = exact = exact_mantissa * 10**exact_exponent
// = exact_mantissa * 5**exact_exponent * 2**exact_exponent
// rhs = guess = guess_mantissa * 2**guess_exponent
//
// Because we are doing integer math, we can't directly deal with negative
// exponents. We instead move these to the other side of the inequality.
absl::strings_internal::BigUnsigned<84>& lhs = exact_mantissa;
int comparison;
if (exact_exponent >= 0) {
lhs.MultiplyByFiveToTheNth(exact_exponent);
absl::strings_internal::BigUnsigned<84> rhs(guess_mantissa);
// There are powers of 2 on both sides of the inequality; reduce this to
// a single bit-shift.
if (exact_exponent > guess_exponent) {
lhs.ShiftLeft(exact_exponent - guess_exponent);
} else {
rhs.ShiftLeft(guess_exponent - exact_exponent);
}
comparison = Compare(lhs, rhs);
} else {
// Move the power of 5 to the other side of the equation, giving us:
// lhs = exact_mantissa * 2**exact_exponent
// rhs = guess_mantissa * 5**(-exact_exponent) * 2**guess_exponent
absl::strings_internal::BigUnsigned<84> rhs =
absl::strings_internal::BigUnsigned<84>::FiveToTheNth(-exact_exponent);
rhs.MultiplyBy(guess_mantissa);
if (exact_exponent > guess_exponent) {
lhs.ShiftLeft(exact_exponent - guess_exponent);
} else {
rhs.ShiftLeft(guess_exponent - exact_exponent);
}
comparison = Compare(lhs, rhs);
}
if (comparison < 0) {
return false;
} else if (comparison > 0) {
return true;
} else {
// When lhs == rhs, the decimal input is exactly between A and B.
// Round towards even -- round up only if the low bit of the initial
// `guess_mantissa` was a 1. We shifted guess_mantissa left 1 bit at
// the beginning of this function, so test the 2nd bit here.
return (guess_mantissa & 2) == 2;
}
}
// Constructs a CalculatedFloat from a given mantissa and exponent, but
// with the following normalizations applied:
//
// If rounding has caused mantissa to increase just past the allowed bit
// width, shift and adjust exponent.
//
// If exponent is too high, sets kOverflow.
//
// If mantissa is zero (representing a non-zero value not representable, even
// as a subnormal), sets kUnderflow.
template <typename FloatType>
CalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) {
CalculatedFloat result;
if (mantissa == uint64_t(1) << FloatTraits<FloatType>::kTargetMantissaBits) {
mantissa >>= 1;
exponent += 1;
}
if (exponent > FloatTraits<FloatType>::kMaxExponent) {
result.exponent = kOverflow;
} else if (mantissa == 0) {
result.exponent = kUnderflow;
} else {
result.exponent = exponent;
result.mantissa = mantissa;
}
return result;
}
template <typename FloatType>
CalculatedFloat CalculateFromParsedHexadecimal(
const strings_internal::ParsedFloat& parsed_hex) {
uint64_t mantissa = parsed_hex.mantissa;
int exponent = parsed_hex.exponent;
int mantissa_width = 64 - strings_internal::CountLeadingZeros64(mantissa);
const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
bool result_exact;
exponent += shift;
mantissa = ShiftRightAndRound(mantissa, shift,
/* input exact= */ true, &result_exact);
// ParseFloat handles rounding in the hexadecimal case, so we don't have to
// check `result_exact` here.
return CalculatedFloatFromRawValues<FloatType>(mantissa, exponent);
}
template <typename FloatType>
CalculatedFloat CalculateFromParsedDecimal(
const strings_internal::ParsedFloat& parsed_decimal) {
CalculatedFloat result;
// Large or small enough decimal exponents will always result in overflow
// or underflow.
if (Power10Underflow(parsed_decimal.exponent)) {
result.exponent = kUnderflow;
return result;
} else if (Power10Overflow(parsed_decimal.exponent)) {
result.exponent = kOverflow;
return result;
}
// Otherwise convert our power of 10 into a power of 2 times an integer
// mantissa, and multiply this by our parsed decimal mantissa.
uint128 wide_binary_mantissa = parsed_decimal.mantissa;
wide_binary_mantissa *= Power10Mantissa(parsed_decimal.exponent);
int binary_exponent = Power10Exponent(parsed_decimal.exponent);
// Discard bits that are inaccurate due to truncation error. The magic
// `mantissa_width` constants below are justified in charconv_algorithm.md.
// They represent the number of bits in `wide_binary_mantissa` that are
// guaranteed to be unaffected by error propagation.
bool mantissa_exact;
int mantissa_width;
if (parsed_decimal.subrange_begin) {
// Truncated mantissa
mantissa_width = 58;
mantissa_exact = false;
binary_exponent +=
TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
} else if (!Power10Exact(parsed_decimal.exponent)) {
// Exact mantissa, truncated power of ten
mantissa_width = 63;
mantissa_exact = false;
binary_exponent +=
TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
} else {
// Product is exact
mantissa_width = BitWidth(wide_binary_mantissa);
mantissa_exact = true;
}
// Shift into an FloatType-sized mantissa, and round to nearest.
const int shift =
NormalizedShiftSize<FloatType>(mantissa_width, binary_exponent);
bool result_exact;
binary_exponent += shift;
uint64_t binary_mantissa = ShiftRightAndRound(wide_binary_mantissa, shift,
mantissa_exact, &result_exact);
if (!result_exact) {
// We could not determine the rounding direction using int128 math. Use
// full resolution math instead.
if (MustRoundUp(binary_mantissa, binary_exponent, parsed_decimal)) {
binary_mantissa += 1;
}
}
return CalculatedFloatFromRawValues<FloatType>(binary_mantissa,
binary_exponent);
}
template <typename FloatType>
from_chars_result FromCharsImpl(const char* first, const char* last,
FloatType& value, chars_format fmt_flags) {
from_chars_result result;
result.ptr = first; // overwritten on successful parse
result.ec = std::errc();
bool negative = false;
if (first != last && *first == '-') {
++first;
negative = true;
}
// If the `hex` flag is *not* set, then we will accept a 0x prefix and try
// to parse a hexadecimal float.
if ((fmt_flags & chars_format::hex) == chars_format{} && last - first >= 2 &&
*first == '0' && (first[1] == 'x' || first[1] == 'X')) {
const char* hex_first = first + 2;
strings_internal::ParsedFloat hex_parse =
strings_internal::ParseFloat<16>(hex_first, last, fmt_flags);
if (hex_parse.end == nullptr ||
hex_parse.type != strings_internal::FloatType::kNumber) {
// Either we failed to parse a hex float after the "0x", or we read
// "0xinf" or "0xnan" which we don't want to match.
//
// However, a std::string that begins with "0x" also begins with "0", which
// is normally a valid match for the number zero. So we want these
// strings to match zero unless fmt_flags is `scientific`. (This flag
// means an exponent is required, which the std::string "0" does not have.)
if (fmt_flags == chars_format::scientific) {
result.ec = std::errc::invalid_argument;
} else {
result.ptr = first + 1;
value = negative ? -0.0 : 0.0;
}
return result;
}
// We matched a value.
result.ptr = hex_parse.end;
if (HandleEdgeCase(hex_parse, negative, &value)) {
return result;
}
CalculatedFloat calculated =
CalculateFromParsedHexadecimal<FloatType>(hex_parse);
EncodeResult(calculated, negative, &result, &value);
return result;
}
// Otherwise, we choose the number base based on the flags.
if ((fmt_flags & chars_format::hex) == chars_format::hex) {
strings_internal::ParsedFloat hex_parse =
strings_internal::ParseFloat<16>(first, last, fmt_flags);
if (hex_parse.end == nullptr) {
result.ec = std::errc::invalid_argument;
return result;
}
result.ptr = hex_parse.end;
if (HandleEdgeCase(hex_parse, negative, &value)) {
return result;
}
CalculatedFloat calculated =
CalculateFromParsedHexadecimal<FloatType>(hex_parse);
EncodeResult(calculated, negative, &result, &value);
return result;
} else {
strings_internal::ParsedFloat decimal_parse =
strings_internal::ParseFloat<10>(first, last, fmt_flags);
if (decimal_parse.end == nullptr) {
result.ec = std::errc::invalid_argument;
return result;
}
result.ptr = decimal_parse.end;
if (HandleEdgeCase(decimal_parse, negative, &value)) {
return result;
}
CalculatedFloat calculated =
CalculateFromParsedDecimal<FloatType>(decimal_parse);
EncodeResult(calculated, negative, &result, &value);
return result;
}
return result;
}
} // namespace
from_chars_result from_chars(const char* first, const char* last, double& value,
chars_format fmt) {
return FromCharsImpl(first, last, value, fmt);
}
from_chars_result from_chars(const char* first, const char* last, float& value,
chars_format fmt) {
return FromCharsImpl(first, last, value, fmt);
}
namespace {
// Table of powers of 10, from kPower10TableMin to kPower10TableMax.
//
// kPower10MantissaTable[i - kPower10TableMin] stores the 64-bit mantissa (high
// bit always on), and kPower10ExponentTable[i - kPower10TableMin] stores the
// power-of-two exponent. For a given number i, this gives the unique mantissa
// and exponent such that mantissa * 2**exponent <= 10**i < (mantissa + 1) *
// 2**exponent.
const uint64_t kPower10MantissaTable[] = {
0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U,
0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U,
0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU,
0xde8b2b66b3bc4723U, 0x8b16fb203055ac76U, 0xaddcb9e83c6b1793U,
0xd953e8624b85dd78U, 0x87d4713d6f33aa6bU, 0xa9c98d8ccb009506U,
0xd43bf0effdc0ba48U, 0x84a57695fe98746dU, 0xa5ced43b7e3e9188U,
0xcf42894a5dce35eaU, 0x818995ce7aa0e1b2U, 0xa1ebfb4219491a1fU,
0xca66fa129f9b60a6U, 0xfd00b897478238d0U, 0x9e20735e8cb16382U,
0xc5a890362fddbc62U, 0xf712b443bbd52b7bU, 0x9a6bb0aa55653b2dU,
0xc1069cd4eabe89f8U, 0xf148440a256e2c76U, 0x96cd2a865764dbcaU,
0xbc807527ed3e12bcU, 0xeba09271e88d976bU, 0x93445b8731587ea3U,
0xb8157268fdae9e4cU, 0xe61acf033d1a45dfU, 0x8fd0c16206306babU,
0xb3c4f1ba87bc8696U, 0xe0b62e2929aba83cU, 0x8c71dcd9ba0b4925U,
0xaf8e5410288e1b6fU, 0xdb71e91432b1a24aU, 0x892731ac9faf056eU,
0xab70fe17c79ac6caU, 0xd64d3d9db981787dU, 0x85f0468293f0eb4eU,
0xa76c582338ed2621U, 0xd1476e2c07286faaU, 0x82cca4db847945caU,
0xa37fce126597973cU, 0xcc5fc196fefd7d0cU, 0xff77b1fcbebcdc4fU,
0x9faacf3df73609b1U, 0xc795830d75038c1dU, 0xf97ae3d0d2446f25U,
0x9becce62836ac577U, 0xc2e801fb244576d5U, 0xf3a20279ed56d48aU,
0x9845418c345644d6U, 0xbe5691ef416bd60cU, 0xedec366b11c6cb8fU,
0x94b3a202eb1c3f39U, 0xb9e08a83a5e34f07U, 0xe858ad248f5c22c9U,
0x91376c36d99995beU, 0xb58547448ffffb2dU, 0xe2e69915b3fff9f9U,
0x8dd01fad907ffc3bU, 0xb1442798f49ffb4aU, 0xdd95317f31c7fa1dU,
0x8a7d3eef7f1cfc52U, 0xad1c8eab5ee43b66U, 0xd863b256369d4a40U,
0x873e4f75e2224e68U, 0xa90de3535aaae202U, 0xd3515c2831559a83U,
0x8412d9991ed58091U, 0xa5178fff668ae0b6U, 0xce5d73ff402d98e3U,
0x80fa687f881c7f8eU, 0xa139029f6a239f72U, 0xc987434744ac874eU,
0xfbe9141915d7a922U, 0x9d71ac8fada6c9b5U, 0xc4ce17b399107c22U,
0xf6019da07f549b2bU, 0x99c102844f94e0fbU, 0xc0314325637a1939U,
0xf03d93eebc589f88U, 0x96267c7535b763b5U, 0xbbb01b9283253ca2U,
0xea9c227723ee8bcbU, 0x92a1958a7675175fU, 0xb749faed14125d36U,
0xe51c79a85916f484U, 0x8f31cc0937ae58d2U, 0xb2fe3f0b8599ef07U,
0xdfbdcece67006ac9U, 0x8bd6a141006042bdU, 0xaecc49914078536dU,
0xda7f5bf590966848U, 0x888f99797a5e012dU, 0xaab37fd7d8f58178U,
0xd5605fcdcf32e1d6U, 0x855c3be0a17fcd26U, 0xa6b34ad8c9dfc06fU,
0xd0601d8efc57b08bU, 0x823c12795db6ce57U, 0xa2cb1717b52481edU,
0xcb7ddcdda26da268U, 0xfe5d54150b090b02U, 0x9efa548d26e5a6e1U,
0xc6b8e9b0709f109aU, 0xf867241c8cc6d4c0U, 0x9b407691d7fc44f8U,
0xc21094364dfb5636U, 0xf294b943e17a2bc4U, 0x979cf3ca6cec5b5aU,
0xbd8430bd08277231U, 0xece53cec4a314ebdU, 0x940f4613ae5ed136U,
0xb913179899f68584U, 0xe757dd7ec07426e5U, 0x9096ea6f3848984fU,
0xb4bca50b065abe63U, 0xe1ebce4dc7f16dfbU, 0x8d3360f09cf6e4bdU,
0xb080392cc4349decU, 0xdca04777f541c567U, 0x89e42caaf9491b60U,
0xac5d37d5b79b6239U, 0xd77485cb25823ac7U, 0x86a8d39ef77164bcU,
0xa8530886b54dbdebU, 0xd267caa862a12d66U, 0x8380dea93da4bc60U,
0xa46116538d0deb78U, 0xcd795be870516656U, 0x806bd9714632dff6U,
0xa086cfcd97bf97f3U, 0xc8a883c0fdaf7df0U, 0xfad2a4b13d1b5d6cU,
0x9cc3a6eec6311a63U, 0xc3f490aa77bd60fcU, 0xf4f1b4d515acb93bU,
0x991711052d8bf3c5U, 0xbf5cd54678eef0b6U, 0xef340a98172aace4U,
0x9580869f0e7aac0eU, 0xbae0a846d2195712U, 0xe998d258869facd7U,
0x91ff83775423cc06U, 0xb67f6455292cbf08U, 0xe41f3d6a7377eecaU,
0x8e938662882af53eU, 0xb23867fb2a35b28dU, 0xdec681f9f4c31f31U,
0x8b3c113c38f9f37eU, 0xae0b158b4738705eU, 0xd98ddaee19068c76U,
0x87f8a8d4cfa417c9U, 0xa9f6d30a038d1dbcU, 0xd47487cc8470652bU,
0x84c8d4dfd2c63f3bU, 0xa5fb0a17c777cf09U, 0xcf79cc9db955c2ccU,
0x81ac1fe293d599bfU, 0xa21727db38cb002fU, 0xca9cf1d206fdc03bU,
0xfd442e4688bd304aU, 0x9e4a9cec15763e2eU, 0xc5dd44271ad3cdbaU,
0xf7549530e188c128U, 0x9a94dd3e8cf578b9U, 0xc13a148e3032d6e7U,
0xf18899b1bc3f8ca1U, 0x96f5600f15a7b7e5U, 0xbcb2b812db11a5deU,
0xebdf661791d60f56U, 0x936b9fcebb25c995U, 0xb84687c269ef3bfbU,
0xe65829b3046b0afaU, 0x8ff71a0fe2c2e6dcU, 0xb3f4e093db73a093U,
0xe0f218b8d25088b8U, 0x8c974f7383725573U, 0xafbd2350644eeacfU,
0xdbac6c247d62a583U, 0x894bc396ce5da772U, 0xab9eb47c81f5114fU,
0xd686619ba27255a2U, 0x8613fd0145877585U, 0xa798fc4196e952e7U,
0xd17f3b51fca3a7a0U, 0x82ef85133de648c4U, 0xa3ab66580d5fdaf5U,
0xcc963fee10b7d1b3U, 0xffbbcfe994e5c61fU, 0x9fd561f1fd0f9bd3U,
0xc7caba6e7c5382c8U, 0xf9bd690a1b68637bU, 0x9c1661a651213e2dU,
0xc31bfa0fe5698db8U, 0xf3e2f893dec3f126U, 0x986ddb5c6b3a76b7U,
0xbe89523386091465U, 0xee2ba6c0678b597fU, 0x94db483840b717efU,
0xba121a4650e4ddebU, 0xe896a0d7e51e1566U, 0x915e2486ef32cd60U,
0xb5b5ada8aaff80b8U, 0xe3231912d5bf60e6U, 0x8df5efabc5979c8fU,
0xb1736b96b6fd83b3U, 0xddd0467c64bce4a0U, 0x8aa22c0dbef60ee4U,
0xad4ab7112eb3929dU, 0xd89d64d57a607744U, 0x87625f056c7c4a8bU,
0xa93af6c6c79b5d2dU, 0xd389b47879823479U, 0x843610cb4bf160cbU,
0xa54394fe1eedb8feU, 0xce947a3da6a9273eU, 0x811ccc668829b887U,
0xa163ff802a3426a8U, 0xc9bcff6034c13052U, 0xfc2c3f3841f17c67U,
0x9d9ba7832936edc0U, 0xc5029163f384a931U, 0xf64335bcf065d37dU,
0x99ea0196163fa42eU, 0xc06481fb9bcf8d39U, 0xf07da27a82c37088U,
0x964e858c91ba2655U, 0xbbe226efb628afeaU, 0xeadab0aba3b2dbe5U,
0x92c8ae6b464fc96fU, 0xb77ada0617e3bbcbU, 0xe55990879ddcaabdU,
0x8f57fa54c2a9eab6U, 0xb32df8e9f3546564U, 0xdff9772470297ebdU,
0x8bfbea76c619ef36U, 0xaefae51477a06b03U, 0xdab99e59958885c4U,
0x88b402f7fd75539bU, 0xaae103b5fcd2a881U, 0xd59944a37c0752a2U,
0x857fcae62d8493a5U, 0xa6dfbd9fb8e5b88eU, 0xd097ad07a71f26b2U,
0x825ecc24c873782fU, 0xa2f67f2dfa90563bU, 0xcbb41ef979346bcaU,
0xfea126b7d78186bcU, 0x9f24b832e6b0f436U, 0xc6ede63fa05d3143U,
0xf8a95fcf88747d94U, 0x9b69dbe1b548ce7cU, 0xc24452da229b021bU,
0xf2d56790ab41c2a2U, 0x97c560ba6b0919a5U, 0xbdb6b8e905cb600fU,
0xed246723473e3813U, 0x9436c0760c86e30bU, 0xb94470938fa89bceU,
0xe7958cb87392c2c2U, 0x90bd77f3483bb9b9U, 0xb4ecd5f01a4aa828U,
0xe2280b6c20dd5232U, 0x8d590723948a535fU, 0xb0af48ec79ace837U,
0xdcdb1b2798182244U, 0x8a08f0f8bf0f156bU, 0xac8b2d36eed2dac5U,
0xd7adf884aa879177U, 0x86ccbb52ea94baeaU, 0xa87fea27a539e9a5U,
0xd29fe4b18e88640eU, 0x83a3eeeef9153e89U, 0xa48ceaaab75a8e2bU,
0xcdb02555653131b6U, 0x808e17555f3ebf11U, 0xa0b19d2ab70e6ed6U,
0xc8de047564d20a8bU, 0xfb158592be068d2eU, 0x9ced737bb6c4183dU,
0xc428d05aa4751e4cU, 0xf53304714d9265dfU, 0x993fe2c6d07b7fabU,
0xbf8fdb78849a5f96U, 0xef73d256a5c0f77cU, 0x95a8637627989aadU,
0xbb127c53b17ec159U, 0xe9d71b689dde71afU, 0x9226712162ab070dU,
0xb6b00d69bb55c8d1U, 0xe45c10c42a2b3b05U, 0x8eb98a7a9a5b04e3U,
0xb267ed1940f1c61cU, 0xdf01e85f912e37a3U, 0x8b61313bbabce2c6U,
0xae397d8aa96c1b77U, 0xd9c7dced53c72255U, 0x881cea14545c7575U,
0xaa242499697392d2U, 0xd4ad2dbfc3d07787U, 0x84ec3c97da624ab4U,
0xa6274bbdd0fadd61U, 0xcfb11ead453994baU, 0x81ceb32c4b43fcf4U,
0xa2425ff75e14fc31U, 0xcad2f7f5359a3b3eU, 0xfd87b5f28300ca0dU,
0x9e74d1b791e07e48U, 0xc612062576589ddaU, 0xf79687aed3eec551U,
0x9abe14cd44753b52U, 0xc16d9a0095928a27U, 0xf1c90080baf72cb1U,
0x971da05074da7beeU, 0xbce5086492111aeaU, 0xec1e4a7db69561a5U,
0x9392ee8e921d5d07U, 0xb877aa3236a4b449U, 0xe69594bec44de15bU,
0x901d7cf73ab0acd9U, 0xb424dc35095cd80fU, 0xe12e13424bb40e13U,
0x8cbccc096f5088cbU, 0xafebff0bcb24aafeU, 0xdbe6fecebdedd5beU,
0x89705f4136b4a597U, 0xabcc77118461cefcU, 0xd6bf94d5e57a42bcU,
0x8637bd05af6c69b5U, 0xa7c5ac471b478423U, 0xd1b71758e219652bU,
0x83126e978d4fdf3bU, 0xa3d70a3d70a3d70aU, 0xccccccccccccccccU,
0x8000000000000000U, 0xa000000000000000U, 0xc800000000000000U,
0xfa00000000000000U, 0x9c40000000000000U, 0xc350000000000000U,
0xf424000000000000U, 0x9896800000000000U, 0xbebc200000000000U,
0xee6b280000000000U, 0x9502f90000000000U, 0xba43b74000000000U,
0xe8d4a51000000000U, 0x9184e72a00000000U, 0xb5e620f480000000U,
0xe35fa931a0000000U, 0x8e1bc9bf04000000U, 0xb1a2bc2ec5000000U,
0xde0b6b3a76400000U, 0x8ac7230489e80000U, 0xad78ebc5ac620000U,
0xd8d726b7177a8000U, 0x878678326eac9000U, 0xa968163f0a57b400U,
0xd3c21bcecceda100U, 0x84595161401484a0U, 0xa56fa5b99019a5c8U,
0xcecb8f27f4200f3aU, 0x813f3978f8940984U, 0xa18f07d736b90be5U,
0xc9f2c9cd04674edeU, 0xfc6f7c4045812296U, 0x9dc5ada82b70b59dU,
0xc5371912364ce305U, 0xf684df56c3e01bc6U, 0x9a130b963a6c115cU,
0xc097ce7bc90715b3U, 0xf0bdc21abb48db20U, 0x96769950b50d88f4U,
0xbc143fa4e250eb31U, 0xeb194f8e1ae525fdU, 0x92efd1b8d0cf37beU,
0xb7abc627050305adU, 0xe596b7b0c643c719U, 0x8f7e32ce7bea5c6fU,
0xb35dbf821ae4f38bU, 0xe0352f62a19e306eU, 0x8c213d9da502de45U,
0xaf298d050e4395d6U, 0xdaf3f04651d47b4cU, 0x88d8762bf324cd0fU,
0xab0e93b6efee0053U, 0xd5d238a4abe98068U, 0x85a36366eb71f041U,
0xa70c3c40a64e6c51U, 0xd0cf4b50cfe20765U, 0x82818f1281ed449fU,
0xa321f2d7226895c7U, 0xcbea6f8ceb02bb39U, 0xfee50b7025c36a08U,
0x9f4f2726179a2245U, 0xc722f0ef9d80aad6U, 0xf8ebad2b84e0d58bU,
0x9b934c3b330c8577U, 0xc2781f49ffcfa6d5U, 0xf316271c7fc3908aU,
0x97edd871cfda3a56U, 0xbde94e8e43d0c8ecU, 0xed63a231d4c4fb27U,
0x945e455f24fb1cf8U, 0xb975d6b6ee39e436U, 0xe7d34c64a9c85d44U,
0x90e40fbeea1d3a4aU, 0xb51d13aea4a488ddU, 0xe264589a4dcdab14U,
0x8d7eb76070a08aecU, 0xb0de65388cc8ada8U, 0xdd15fe86affad912U,
0x8a2dbf142dfcc7abU, 0xacb92ed9397bf996U, 0xd7e77a8f87daf7fbU,
0x86f0ac99b4e8dafdU, 0xa8acd7c0222311bcU, 0xd2d80db02aabd62bU,
0x83c7088e1aab65dbU, 0xa4b8cab1a1563f52U, 0xcde6fd5e09abcf26U,
0x80b05e5ac60b6178U, 0xa0dc75f1778e39d6U, 0xc913936dd571c84cU,
0xfb5878494ace3a5fU, 0x9d174b2dcec0e47bU, 0xc45d1df942711d9aU,
0xf5746577930d6500U, 0x9968bf6abbe85f20U, 0xbfc2ef456ae276e8U,
0xefb3ab16c59b14a2U, 0x95d04aee3b80ece5U, 0xbb445da9ca61281fU,
0xea1575143cf97226U, 0x924d692ca61be758U, 0xb6e0c377cfa2e12eU,
0xe498f455c38b997aU, 0x8edf98b59a373fecU, 0xb2977ee300c50fe7U,
0xdf3d5e9bc0f653e1U, 0x8b865b215899f46cU, 0xae67f1e9aec07187U,
0xda01ee641a708de9U, 0x884134fe908658b2U, 0xaa51823e34a7eedeU,
0xd4e5e2cdc1d1ea96U, 0x850fadc09923329eU, 0xa6539930bf6bff45U,
0xcfe87f7cef46ff16U, 0x81f14fae158c5f6eU, 0xa26da3999aef7749U,
0xcb090c8001ab551cU, 0xfdcb4fa002162a63U, 0x9e9f11c4014dda7eU,
0xc646d63501a1511dU, 0xf7d88bc24209a565U, 0x9ae757596946075fU,
0xc1a12d2fc3978937U, 0xf209787bb47d6b84U, 0x9745eb4d50ce6332U,
0xbd176620a501fbffU, 0xec5d3fa8ce427affU, 0x93ba47c980e98cdfU,
0xb8a8d9bbe123f017U, 0xe6d3102ad96cec1dU, 0x9043ea1ac7e41392U,
0xb454e4a179dd1877U, 0xe16a1dc9d8545e94U, 0x8ce2529e2734bb1dU,
0xb01ae745b101e9e4U, 0xdc21a1171d42645dU, 0x899504ae72497ebaU,
0xabfa45da0edbde69U, 0xd6f8d7509292d603U, 0x865b86925b9bc5c2U,
0xa7f26836f282b732U, 0xd1ef0244af2364ffU, 0x8335616aed761f1fU,
0xa402b9c5a8d3a6e7U, 0xcd036837130890a1U, 0x802221226be55a64U,
0xa02aa96b06deb0fdU, 0xc83553c5c8965d3dU, 0xfa42a8b73abbf48cU,
0x9c69a97284b578d7U, 0xc38413cf25e2d70dU, 0xf46518c2ef5b8cd1U,
0x98bf2f79d5993802U, 0xbeeefb584aff8603U, 0xeeaaba2e5dbf6784U,
0x952ab45cfa97a0b2U, 0xba756174393d88dfU, 0xe912b9d1478ceb17U,
0x91abb422ccb812eeU, 0xb616a12b7fe617aaU, 0xe39c49765fdf9d94U,
0x8e41ade9fbebc27dU, 0xb1d219647ae6b31cU, 0xde469fbd99a05fe3U,
0x8aec23d680043beeU, 0xada72ccc20054ae9U, 0xd910f7ff28069da4U,
0x87aa9aff79042286U, 0xa99541bf57452b28U, 0xd3fa922f2d1675f2U,
0x847c9b5d7c2e09b7U, 0xa59bc234db398c25U, 0xcf02b2c21207ef2eU,
0x8161afb94b44f57dU, 0xa1ba1ba79e1632dcU, 0xca28a291859bbf93U,
0xfcb2cb35e702af78U, 0x9defbf01b061adabU, 0xc56baec21c7a1916U,
0xf6c69a72a3989f5bU, 0x9a3c2087a63f6399U, 0xc0cb28a98fcf3c7fU,
0xf0fdf2d3f3c30b9fU, 0x969eb7c47859e743U, 0xbc4665b596706114U,
0xeb57ff22fc0c7959U, 0x9316ff75dd87cbd8U, 0xb7dcbf5354e9beceU,
0xe5d3ef282a242e81U, 0x8fa475791a569d10U, 0xb38d92d760ec4455U,
0xe070f78d3927556aU, 0x8c469ab843b89562U, 0xaf58416654a6babbU,
0xdb2e51bfe9d0696aU, 0x88fcf317f22241e2U, 0xab3c2fddeeaad25aU,
0xd60b3bd56a5586f1U, 0x85c7056562757456U, 0xa738c6bebb12d16cU,
0xd106f86e69d785c7U, 0x82a45b450226b39cU, 0xa34d721642b06084U,
0xcc20ce9bd35c78a5U, 0xff290242c83396ceU, 0x9f79a169bd203e41U,
0xc75809c42c684dd1U, 0xf92e0c3537826145U, 0x9bbcc7a142b17ccbU,
0xc2abf989935ddbfeU, 0xf356f7ebf83552feU, 0x98165af37b2153deU,
0xbe1bf1b059e9a8d6U, 0xeda2ee1c7064130cU, 0x9485d4d1c63e8be7U,
0xb9a74a0637ce2ee1U, 0xe8111c87c5c1ba99U, 0x910ab1d4db9914a0U,
0xb54d5e4a127f59c8U, 0xe2a0b5dc971f303aU, 0x8da471a9de737e24U,
0xb10d8e1456105dadU, 0xdd50f1996b947518U, 0x8a5296ffe33cc92fU,
0xace73cbfdc0bfb7bU, 0xd8210befd30efa5aU, 0x8714a775e3e95c78U,
0xa8d9d1535ce3b396U, 0xd31045a8341ca07cU, 0x83ea2b892091e44dU,
0xa4e4b66b68b65d60U, 0xce1de40642e3f4b9U, 0x80d2ae83e9ce78f3U,
0xa1075a24e4421730U, 0xc94930ae1d529cfcU, 0xfb9b7cd9a4a7443cU,
0x9d412e0806e88aa5U, 0xc491798a08a2ad4eU, 0xf5b5d7ec8acb58a2U,
0x9991a6f3d6bf1765U, 0xbff610b0cc6edd3fU, 0xeff394dcff8a948eU,
0x95f83d0a1fb69cd9U, 0xbb764c4ca7a4440fU, 0xea53df5fd18d5513U,
0x92746b9be2f8552cU, 0xb7118682dbb66a77U, 0xe4d5e82392a40515U,
0x8f05b1163ba6832dU, 0xb2c71d5bca9023f8U, 0xdf78e4b2bd342cf6U,
0x8bab8eefb6409c1aU, 0xae9672aba3d0c320U, 0xda3c0f568cc4f3e8U,
0x8865899617fb1871U, 0xaa7eebfb9df9de8dU, 0xd51ea6fa85785631U,
0x8533285c936b35deU, 0xa67ff273b8460356U, 0xd01fef10a657842cU,
0x8213f56a67f6b29bU, 0xa298f2c501f45f42U, 0xcb3f2f7642717713U,
0xfe0efb53d30dd4d7U, 0x9ec95d1463e8a506U, 0xc67bb4597ce2ce48U,
0xf81aa16fdc1b81daU, 0x9b10a4e5e9913128U, 0xc1d4ce1f63f57d72U,
0xf24a01a73cf2dccfU, 0x976e41088617ca01U, 0xbd49d14aa79dbc82U,
0xec9c459d51852ba2U, 0x93e1ab8252f33b45U, 0xb8da1662e7b00a17U,
0xe7109bfba19c0c9dU, 0x906a617d450187e2U, 0xb484f9dc9641e9daU,
0xe1a63853bbd26451U, 0x8d07e33455637eb2U, 0xb049dc016abc5e5fU,
0xdc5c5301c56b75f7U, 0x89b9b3e11b6329baU, 0xac2820d9623bf429U,
0xd732290fbacaf133U, 0x867f59a9d4bed6c0U, 0xa81f301449ee8c70U,
0xd226fc195c6a2f8cU, 0x83585d8fd9c25db7U, 0xa42e74f3d032f525U,
0xcd3a1230c43fb26fU, 0x80444b5e7aa7cf85U, 0xa0555e361951c366U,
0xc86ab5c39fa63440U, 0xfa856334878fc150U, 0x9c935e00d4b9d8d2U,
0xc3b8358109e84f07U, 0xf4a642e14c6262c8U, 0x98e7e9cccfbd7dbdU,
0xbf21e44003acdd2cU, 0xeeea5d5004981478U, 0x95527a5202df0ccbU,
0xbaa718e68396cffdU, 0xe950df20247c83fdU, 0x91d28b7416cdd27eU,
0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU,
};
const int16_t kPower10ExponentTable[] = {
-1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166,
-1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130,
-1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093,
-1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057,
-1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020,
-1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984,
-980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947,
-944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911,
-907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874,
-871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838,
-834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801,
-798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764,
-761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728,
-725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
-688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655,
-651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618,
-615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582,
-578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545,
-542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509,
-505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472,
-469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436,
-432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399,
-396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362,
-359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326,
-323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289,
-286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
-250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216,
-213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180,
-176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143,
-140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107,
-103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70,
-67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34,
-30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3,
6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39,
43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76,
79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113,
116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149,
152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186,
189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222,
226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295,
299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332,
335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368,
372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405,
408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441,
445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478,
481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515,
518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551,
554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588,
591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624,
627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661,
664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697,
701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734,
737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807,
810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843,
847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880,
883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916,
920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953,
956, 960,
};
} // namespace
} // namespace absl

View File

@ -1,115 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_CHARCONV_H_
#define ABSL_STRINGS_CHARCONV_H_
#include <system_error> // NOLINT(build/c++11)
namespace absl {
// Workalike compatibilty version of std::chars_format from C++17.
//
// This is an bitfield enumerator which can be passed to absl::from_chars to
// configure the std::string-to-float conversion.
enum class chars_format {
scientific = 1,
fixed = 2,
hex = 4,
general = fixed | scientific,
};
// The return result of a std::string-to-number conversion.
//
// `ec` will be set to `invalid_argument` if a well-formed number was not found
// at the start of the input range, `result_out_of_range` if a well-formed
// number was found, but it was out of the representable range of the requested
// type, or to std::errc() otherwise.
//
// If a well-formed number was found, `ptr` is set to one past the sequence of
// characters that were successfully parsed. If none was found, `ptr` is set
// to the `first` argument to from_chars.
struct from_chars_result {
const char* ptr;
std::errc ec;
};
// Workalike compatibilty version of std::from_chars from C++17. Currently
// this only supports the `double` and `float` types.
//
// This interface incorporates the proposed resolutions for library issues
// DR 3800 and DR 3801. If these are adopted with different wording,
// Abseil's behavior will change to match the standard. (The behavior most
// likely to change is for DR 3801, which says what `value` will be set to in
// the case of overflow and underflow. Code that wants to avoid possible
// breaking changes in this area should not depend on `value` when the returned
// from_chars_result indicates a range error.)
//
// Searches the range [first, last) for the longest matching pattern beginning
// at `first` that represents a floating point number. If one is found, store
// the result in `value`.
//
// The matching pattern format is almost the same as that of strtod(), except
// that C locale is not respected, and an initial '+' character in the input
// range will never be matched.
//
// If `fmt` is set, it must be one of the enumerator values of the chars_format.
// (This is despite the fact that chars_format is a bitmask type.) If set to
// `scientific`, a matching number must contain an exponent. If set to `fixed`,
// then an exponent will never match. (For example, the std::string "1e5" will be
// parsed as "1".) If set to `hex`, then a hexadecimal float is parsed in the
// format that strtod() accepts, except that a "0x" prefix is NOT matched.
// (In particular, in `hex` mode, the input "0xff" results in the largest
// matching pattern "0".)
absl::from_chars_result from_chars(const char* first, const char* last,
double& value, // NOLINT
chars_format fmt = chars_format::general);
absl::from_chars_result from_chars(const char* first, const char* last,
float& value, // NOLINT
chars_format fmt = chars_format::general);
// std::chars_format is specified as a bitmask type, which means the following
// operations must be provided:
inline constexpr chars_format operator&(chars_format lhs, chars_format rhs) {
return static_cast<chars_format>(static_cast<int>(lhs) &
static_cast<int>(rhs));
}
inline constexpr chars_format operator|(chars_format lhs, chars_format rhs) {
return static_cast<chars_format>(static_cast<int>(lhs) |
static_cast<int>(rhs));
}
inline constexpr chars_format operator^(chars_format lhs, chars_format rhs) {
return static_cast<chars_format>(static_cast<int>(lhs) ^
static_cast<int>(rhs));
}
inline constexpr chars_format operator~(chars_format arg) {
return static_cast<chars_format>(~static_cast<int>(arg));
}
inline chars_format& operator&=(chars_format& lhs, chars_format rhs) {
lhs = lhs & rhs;
return lhs;
}
inline chars_format& operator|=(chars_format& lhs, chars_format rhs) {
lhs = lhs | rhs;
return lhs;
}
inline chars_format& operator^=(chars_format& lhs, chars_format rhs) {
lhs = lhs ^ rhs;
return lhs;
}
} // namespace absl
#endif // ABSL_STRINGS_CHARCONV_H_

View File

@ -1,204 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/charconv.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include "benchmark/benchmark.h"
namespace {
void BM_Strtod_Pi(benchmark::State& state) {
const char* pi = "3.14159";
for (auto s : state) {
benchmark::DoNotOptimize(pi);
benchmark::DoNotOptimize(strtod(pi, nullptr));
}
}
BENCHMARK(BM_Strtod_Pi);
void BM_Absl_Pi(benchmark::State& state) {
const char* pi = "3.14159";
const char* pi_end = pi + strlen(pi);
for (auto s : state) {
benchmark::DoNotOptimize(pi);
double v;
absl::from_chars(pi, pi_end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_Pi);
void BM_Strtod_Pi_float(benchmark::State& state) {
const char* pi = "3.14159";
for (auto s : state) {
benchmark::DoNotOptimize(pi);
benchmark::DoNotOptimize(strtof(pi, nullptr));
}
}
BENCHMARK(BM_Strtod_Pi_float);
void BM_Absl_Pi_float(benchmark::State& state) {
const char* pi = "3.14159";
const char* pi_end = pi + strlen(pi);
for (auto s : state) {
benchmark::DoNotOptimize(pi);
float v;
absl::from_chars(pi, pi_end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_Pi_float);
void BM_Strtod_HardLarge(benchmark::State& state) {
const char* num = "272104041512242479.e200";
for (auto s : state) {
benchmark::DoNotOptimize(num);
benchmark::DoNotOptimize(strtod(num, nullptr));
}
}
BENCHMARK(BM_Strtod_HardLarge);
void BM_Absl_HardLarge(benchmark::State& state) {
const char* numstr = "272104041512242479.e200";
const char* numstr_end = numstr + strlen(numstr);
for (auto s : state) {
benchmark::DoNotOptimize(numstr);
double v;
absl::from_chars(numstr, numstr_end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_HardLarge);
void BM_Strtod_HardSmall(benchmark::State& state) {
const char* num = "94080055902682397.e-242";
for (auto s : state) {
benchmark::DoNotOptimize(num);
benchmark::DoNotOptimize(strtod(num, nullptr));
}
}
BENCHMARK(BM_Strtod_HardSmall);
void BM_Absl_HardSmall(benchmark::State& state) {
const char* numstr = "94080055902682397.e-242";
const char* numstr_end = numstr + strlen(numstr);
for (auto s : state) {
benchmark::DoNotOptimize(numstr);
double v;
absl::from_chars(numstr, numstr_end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_HardSmall);
void BM_Strtod_HugeMantissa(benchmark::State& state) {
std::string huge(200, '3');
const char* num = huge.c_str();
for (auto s : state) {
benchmark::DoNotOptimize(num);
benchmark::DoNotOptimize(strtod(num, nullptr));
}
}
BENCHMARK(BM_Strtod_HugeMantissa);
void BM_Absl_HugeMantissa(benchmark::State& state) {
std::string huge(200, '3');
const char* num = huge.c_str();
const char* num_end = num + 200;
for (auto s : state) {
benchmark::DoNotOptimize(num);
double v;
absl::from_chars(num, num_end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_HugeMantissa);
std::string MakeHardCase(int length) {
// The number 1.1521...e-297 is exactly halfway between 12345 * 2**-1000 and
// the next larger representable number. The digits of this number are in
// the std::string below.
const std::string digits =
"1."
"152113937042223790993097181572444900347587985074226836242307364987727724"
"831384300183638649152607195040591791364113930628852279348613864894524591"
"272746490313676832900762939595690019745859128071117417798540258114233761"
"012939937017879509401007964861774960297319002612457273148497158989073482"
"171377406078223015359818300988676687994537274548940612510414856761641652"
"513434981938564294004070500716200446656421722229202383105446378511678258"
"370570631774499359748259931676320916632111681001853983492795053244971606"
"922718923011680846577744433974087653954904214152517799883551075537146316"
"168973685866425605046988661997658648354773076621610279716804960009043764"
"038392994055171112475093876476783502487512538082706095923790634572014823"
"78877699375152587890625" +
std::string(5000, '0');
// generate the hard cases on either side for the given length.
// Lengths between 3 and 1000 are reasonable.
return digits.substr(0, length) + "1e-297";
}
void BM_Strtod_Big_And_Difficult(benchmark::State& state) {
std::string testcase = MakeHardCase(state.range(0));
const char* begin = testcase.c_str();
for (auto s : state) {
benchmark::DoNotOptimize(begin);
benchmark::DoNotOptimize(strtod(begin, nullptr));
}
}
BENCHMARK(BM_Strtod_Big_And_Difficult)->Range(3, 5000);
void BM_Absl_Big_And_Difficult(benchmark::State& state) {
std::string testcase = MakeHardCase(state.range(0));
const char* begin = testcase.c_str();
const char* end = begin + testcase.size();
for (auto s : state) {
benchmark::DoNotOptimize(begin);
double v;
absl::from_chars(begin, end, v);
benchmark::DoNotOptimize(v);
}
}
BENCHMARK(BM_Absl_Big_And_Difficult)->Range(3, 5000);
} // namespace
// ------------------------------------------------------------------------
// Benchmark Time CPU Iterations
// ------------------------------------------------------------------------
// BM_Strtod_Pi 96 ns 96 ns 6337454
// BM_Absl_Pi 35 ns 35 ns 20031996
// BM_Strtod_Pi_float 91 ns 91 ns 7745851
// BM_Absl_Pi_float 35 ns 35 ns 20430298
// BM_Strtod_HardLarge 133 ns 133 ns 5288341
// BM_Absl_HardLarge 181 ns 181 ns 3855615
// BM_Strtod_HardSmall 279 ns 279 ns 2517243
// BM_Absl_HardSmall 287 ns 287 ns 2458744
// BM_Strtod_HugeMantissa 433 ns 433 ns 1604293
// BM_Absl_HugeMantissa 160 ns 160 ns 4403671
// BM_Strtod_Big_And_Difficult/3 236 ns 236 ns 2942496
// BM_Strtod_Big_And_Difficult/8 232 ns 232 ns 2983796
// BM_Strtod_Big_And_Difficult/64 437 ns 437 ns 1591951
// BM_Strtod_Big_And_Difficult/512 1738 ns 1738 ns 402519
// BM_Strtod_Big_And_Difficult/4096 3943 ns 3943 ns 176128
// BM_Strtod_Big_And_Difficult/5000 4397 ns 4397 ns 157878
// BM_Absl_Big_And_Difficult/3 39 ns 39 ns 17799583
// BM_Absl_Big_And_Difficult/8 43 ns 43 ns 16096859
// BM_Absl_Big_And_Difficult/64 550 ns 550 ns 1259717
// BM_Absl_Big_And_Difficult/512 4167 ns 4167 ns 171414
// BM_Absl_Big_And_Difficult/4096 9160 ns 9159 ns 76297
// BM_Absl_Big_And_Difficult/5000 9738 ns 9738 ns 70140

View File

@ -1,766 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/charconv.h"
#include <cstdlib>
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
#ifdef _MSC_FULL_VER
#define ABSL_COMPILER_DOES_EXACT_ROUNDING 0
#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 0
#else
#define ABSL_COMPILER_DOES_EXACT_ROUNDING 1
#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 1
#endif
namespace {
#if ABSL_COMPILER_DOES_EXACT_ROUNDING
// Tests that the given std::string is accepted by absl::from_chars, and that it
// converts exactly equal to the given number.
void TestDoubleParse(absl::string_view str, double expected_number) {
SCOPED_TRACE(str);
double actual_number = 0.0;
absl::from_chars_result result =
absl::from_chars(str.data(), str.data() + str.length(), actual_number);
EXPECT_EQ(result.ec, std::errc());
EXPECT_EQ(result.ptr, str.data() + str.length());
EXPECT_EQ(actual_number, expected_number);
}
void TestFloatParse(absl::string_view str, float expected_number) {
SCOPED_TRACE(str);
float actual_number = 0.0;
absl::from_chars_result result =
absl::from_chars(str.data(), str.data() + str.length(), actual_number);
EXPECT_EQ(result.ec, std::errc());
EXPECT_EQ(result.ptr, str.data() + str.length());
EXPECT_EQ(actual_number, expected_number);
}
// Tests that the given double or single precision floating point literal is
// parsed correctly by absl::from_chars.
//
// These convenience macros assume that the C++ compiler being used also does
// fully correct decimal-to-binary conversions.
#define FROM_CHARS_TEST_DOUBLE(number) \
{ \
TestDoubleParse(#number, number); \
TestDoubleParse("-" #number, -number); \
}
#define FROM_CHARS_TEST_FLOAT(number) \
{ \
TestFloatParse(#number, number##f); \
TestFloatParse("-" #number, -number##f); \
}
TEST(FromChars, NearRoundingCases) {
// Cases from "A Program for Testing IEEE Decimal-Binary Conversion"
// by Vern Paxson.
// Forms that should round towards zero. (These are the hardest cases for
// each decimal mantissa size.)
FROM_CHARS_TEST_DOUBLE(5.e125);
FROM_CHARS_TEST_DOUBLE(69.e267);
FROM_CHARS_TEST_DOUBLE(999.e-026);
FROM_CHARS_TEST_DOUBLE(7861.e-034);
FROM_CHARS_TEST_DOUBLE(75569.e-254);
FROM_CHARS_TEST_DOUBLE(928609.e-261);
FROM_CHARS_TEST_DOUBLE(9210917.e080);
FROM_CHARS_TEST_DOUBLE(84863171.e114);
FROM_CHARS_TEST_DOUBLE(653777767.e273);
FROM_CHARS_TEST_DOUBLE(5232604057.e-298);
FROM_CHARS_TEST_DOUBLE(27235667517.e-109);
FROM_CHARS_TEST_DOUBLE(653532977297.e-123);
FROM_CHARS_TEST_DOUBLE(3142213164987.e-294);
FROM_CHARS_TEST_DOUBLE(46202199371337.e-072);
FROM_CHARS_TEST_DOUBLE(231010996856685.e-073);
FROM_CHARS_TEST_DOUBLE(9324754620109615.e212);
FROM_CHARS_TEST_DOUBLE(78459735791271921.e049);
FROM_CHARS_TEST_DOUBLE(272104041512242479.e200);
FROM_CHARS_TEST_DOUBLE(6802601037806061975.e198);
FROM_CHARS_TEST_DOUBLE(20505426358836677347.e-221);
FROM_CHARS_TEST_DOUBLE(836168422905420598437.e-234);
FROM_CHARS_TEST_DOUBLE(4891559871276714924261.e222);
FROM_CHARS_TEST_FLOAT(5.e-20);
FROM_CHARS_TEST_FLOAT(67.e14);
FROM_CHARS_TEST_FLOAT(985.e15);
FROM_CHARS_TEST_FLOAT(7693.e-42);
FROM_CHARS_TEST_FLOAT(55895.e-16);
FROM_CHARS_TEST_FLOAT(996622.e-44);
FROM_CHARS_TEST_FLOAT(7038531.e-32);
FROM_CHARS_TEST_FLOAT(60419369.e-46);
FROM_CHARS_TEST_FLOAT(702990899.e-20);
FROM_CHARS_TEST_FLOAT(6930161142.e-48);
FROM_CHARS_TEST_FLOAT(25933168707.e-13);
FROM_CHARS_TEST_FLOAT(596428896559.e20);
// Similarly, forms that should round away from zero.
FROM_CHARS_TEST_DOUBLE(9.e-265);
FROM_CHARS_TEST_DOUBLE(85.e-037);
FROM_CHARS_TEST_DOUBLE(623.e100);
FROM_CHARS_TEST_DOUBLE(3571.e263);
FROM_CHARS_TEST_DOUBLE(81661.e153);
FROM_CHARS_TEST_DOUBLE(920657.e-023);
FROM_CHARS_TEST_DOUBLE(4603285.e-024);
FROM_CHARS_TEST_DOUBLE(87575437.e-309);
FROM_CHARS_TEST_DOUBLE(245540327.e122);
FROM_CHARS_TEST_DOUBLE(6138508175.e120);
FROM_CHARS_TEST_DOUBLE(83356057653.e193);
FROM_CHARS_TEST_DOUBLE(619534293513.e124);
FROM_CHARS_TEST_DOUBLE(2335141086879.e218);
FROM_CHARS_TEST_DOUBLE(36167929443327.e-159);
FROM_CHARS_TEST_DOUBLE(609610927149051.e-255);
FROM_CHARS_TEST_DOUBLE(3743626360493413.e-165);
FROM_CHARS_TEST_DOUBLE(94080055902682397.e-242);
FROM_CHARS_TEST_DOUBLE(899810892172646163.e283);
FROM_CHARS_TEST_DOUBLE(7120190517612959703.e120);
FROM_CHARS_TEST_DOUBLE(25188282901709339043.e-252);
FROM_CHARS_TEST_DOUBLE(308984926168550152811.e-052);
FROM_CHARS_TEST_DOUBLE(6372891218502368041059.e064);
FROM_CHARS_TEST_FLOAT(3.e-23);
FROM_CHARS_TEST_FLOAT(57.e18);
FROM_CHARS_TEST_FLOAT(789.e-35);
FROM_CHARS_TEST_FLOAT(2539.e-18);
FROM_CHARS_TEST_FLOAT(76173.e28);
FROM_CHARS_TEST_FLOAT(887745.e-11);
FROM_CHARS_TEST_FLOAT(5382571.e-37);
FROM_CHARS_TEST_FLOAT(82381273.e-35);
FROM_CHARS_TEST_FLOAT(750486563.e-38);
FROM_CHARS_TEST_FLOAT(3752432815.e-39);
FROM_CHARS_TEST_FLOAT(75224575729.e-45);
FROM_CHARS_TEST_FLOAT(459926601011.e15);
}
#undef FROM_CHARS_TEST_DOUBLE
#undef FROM_CHARS_TEST_FLOAT
#endif
float ToFloat(absl::string_view s) {
float f;
absl::from_chars(s.data(), s.data() + s.size(), f);
return f;
}
double ToDouble(absl::string_view s) {
double d;
absl::from_chars(s.data(), s.data() + s.size(), d);
return d;
}
// A duplication of the test cases in "NearRoundingCases" above, but with
// expected values expressed with integers, using ldexp/ldexpf. These test
// cases will work even on compilers that do not accurately round floating point
// literals.
TEST(FromChars, NearRoundingCasesExplicit) {
EXPECT_EQ(ToDouble("5.e125"), ldexp(6653062250012735, 365));
EXPECT_EQ(ToDouble("69.e267"), ldexp(4705683757438170, 841));
EXPECT_EQ(ToDouble("999.e-026"), ldexp(6798841691080350, -129));
EXPECT_EQ(ToDouble("7861.e-034"), ldexp(8975675289889240, -153));
EXPECT_EQ(ToDouble("75569.e-254"), ldexp(6091718967192243, -880));
EXPECT_EQ(ToDouble("928609.e-261"), ldexp(7849264900213743, -900));
EXPECT_EQ(ToDouble("9210917.e080"), ldexp(8341110837370930, 236));
EXPECT_EQ(ToDouble("84863171.e114"), ldexp(4625202867375927, 353));
EXPECT_EQ(ToDouble("653777767.e273"), ldexp(5068902999763073, 884));
EXPECT_EQ(ToDouble("5232604057.e-298"), ldexp(5741343011915040, -1010));
EXPECT_EQ(ToDouble("27235667517.e-109"), ldexp(6707124626673586, -380));
EXPECT_EQ(ToDouble("653532977297.e-123"), ldexp(7078246407265384, -422));
EXPECT_EQ(ToDouble("3142213164987.e-294"), ldexp(8219991337640559, -988));
EXPECT_EQ(ToDouble("46202199371337.e-072"), ldexp(5224462102115359, -246));
EXPECT_EQ(ToDouble("231010996856685.e-073"), ldexp(5224462102115359, -247));
EXPECT_EQ(ToDouble("9324754620109615.e212"), ldexp(5539753864394442, 705));
EXPECT_EQ(ToDouble("78459735791271921.e049"), ldexp(8388176519442766, 166));
EXPECT_EQ(ToDouble("272104041512242479.e200"), ldexp(5554409530847367, 670));
EXPECT_EQ(ToDouble("6802601037806061975.e198"), ldexp(5554409530847367, 668));
EXPECT_EQ(ToDouble("20505426358836677347.e-221"),
ldexp(4524032052079546, -722));
EXPECT_EQ(ToDouble("836168422905420598437.e-234"),
ldexp(5070963299887562, -760));
EXPECT_EQ(ToDouble("4891559871276714924261.e222"),
ldexp(6452687840519111, 757));
EXPECT_EQ(ToFloat("5.e-20"), ldexpf(15474250, -88));
EXPECT_EQ(ToFloat("67.e14"), ldexpf(12479722, 29));
EXPECT_EQ(ToFloat("985.e15"), ldexpf(14333636, 36));
EXPECT_EQ(ToFloat("7693.e-42"), ldexpf(10979816, -150));
EXPECT_EQ(ToFloat("55895.e-16"), ldexpf(12888509, -61));
EXPECT_EQ(ToFloat("996622.e-44"), ldexpf(14224264, -150));
EXPECT_EQ(ToFloat("7038531.e-32"), ldexpf(11420669, -107));
EXPECT_EQ(ToFloat("60419369.e-46"), ldexpf(8623340, -150));
EXPECT_EQ(ToFloat("702990899.e-20"), ldexpf(16209866, -61));
EXPECT_EQ(ToFloat("6930161142.e-48"), ldexpf(9891056, -150));
EXPECT_EQ(ToFloat("25933168707.e-13"), ldexpf(11138211, -32));
EXPECT_EQ(ToFloat("596428896559.e20"), ldexpf(12333860, 82));
EXPECT_EQ(ToDouble("9.e-265"), ldexp(8168427841980010, -930));
EXPECT_EQ(ToDouble("85.e-037"), ldexp(6360455125664090, -169));
EXPECT_EQ(ToDouble("623.e100"), ldexp(6263531988747231, 289));
EXPECT_EQ(ToDouble("3571.e263"), ldexp(6234526311072170, 833));
EXPECT_EQ(ToDouble("81661.e153"), ldexp(6696636728760206, 472));
EXPECT_EQ(ToDouble("920657.e-023"), ldexp(5975405561110124, -109));
EXPECT_EQ(ToDouble("4603285.e-024"), ldexp(5975405561110124, -110));
EXPECT_EQ(ToDouble("87575437.e-309"), ldexp(8452160731874668, -1053));
EXPECT_EQ(ToDouble("245540327.e122"), ldexp(4985336549131723, 381));
EXPECT_EQ(ToDouble("6138508175.e120"), ldexp(4985336549131723, 379));
EXPECT_EQ(ToDouble("83356057653.e193"), ldexp(5986732817132056, 625));
EXPECT_EQ(ToDouble("619534293513.e124"), ldexp(4798406992060657, 399));
EXPECT_EQ(ToDouble("2335141086879.e218"), ldexp(5419088166961646, 713));
EXPECT_EQ(ToDouble("36167929443327.e-159"), ldexp(8135819834632444, -536));
EXPECT_EQ(ToDouble("609610927149051.e-255"), ldexp(4576664294594737, -850));
EXPECT_EQ(ToDouble("3743626360493413.e-165"), ldexp(6898586531774201, -549));
EXPECT_EQ(ToDouble("94080055902682397.e-242"), ldexp(6273271706052298, -800));
EXPECT_EQ(ToDouble("899810892172646163.e283"), ldexp(7563892574477827, 947));
EXPECT_EQ(ToDouble("7120190517612959703.e120"), ldexp(5385467232557565, 409));
EXPECT_EQ(ToDouble("25188282901709339043.e-252"),
ldexp(5635662608542340, -825));
EXPECT_EQ(ToDouble("308984926168550152811.e-052"),
ldexp(5644774693823803, -157));
EXPECT_EQ(ToDouble("6372891218502368041059.e064"),
ldexp(4616868614322430, 233));
EXPECT_EQ(ToFloat("3.e-23"), ldexpf(9507380, -98));
EXPECT_EQ(ToFloat("57.e18"), ldexpf(12960300, 42));
EXPECT_EQ(ToFloat("789.e-35"), ldexpf(10739312, -130));
EXPECT_EQ(ToFloat("2539.e-18"), ldexpf(11990089, -72));
EXPECT_EQ(ToFloat("76173.e28"), ldexpf(9845130, 86));
EXPECT_EQ(ToFloat("887745.e-11"), ldexpf(9760860, -40));
EXPECT_EQ(ToFloat("5382571.e-37"), ldexpf(11447463, -124));
EXPECT_EQ(ToFloat("82381273.e-35"), ldexpf(8554961, -113));
EXPECT_EQ(ToFloat("750486563.e-38"), ldexpf(9975678, -120));
EXPECT_EQ(ToFloat("3752432815.e-39"), ldexpf(9975678, -121));
EXPECT_EQ(ToFloat("75224575729.e-45"), ldexpf(13105970, -137));
EXPECT_EQ(ToFloat("459926601011.e15"), ldexpf(12466336, 65));
}
// Common test logic for converting a std::string which lies exactly halfway between
// two target floats.
//
// mantissa and exponent represent the precise value between two floating point
// numbers, `expected_low` and `expected_high`. The floating point
// representation to parse in `StrCat(mantissa, "e", exponent)`.
//
// This function checks that an input just slightly less than the exact value
// is rounded down to `expected_low`, and an input just slightly greater than
// the exact value is rounded up to `expected_high`.
//
// The exact value should round to `expected_half`, which must be either
// `expected_low` or `expected_high`.
template <typename FloatType>
void TestHalfwayValue(const std::string& mantissa, int exponent,
FloatType expected_low, FloatType expected_high,
FloatType expected_half) {
std::string low_rep = mantissa;
low_rep[low_rep.size() - 1] -= 1;
absl::StrAppend(&low_rep, std::string(1000, '9'), "e", exponent);
FloatType actual_low = 0;
absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);
EXPECT_EQ(expected_low, actual_low);
std::string high_rep = absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
FloatType actual_high = 0;
absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),
actual_high);
EXPECT_EQ(expected_high, actual_high);
std::string halfway_rep = absl::StrCat(mantissa, "e", exponent);
FloatType actual_half = 0;
absl::from_chars(halfway_rep.data(), halfway_rep.data() + halfway_rep.size(),
actual_half);
EXPECT_EQ(expected_half, actual_half);
}
TEST(FromChars, DoubleRounding) {
const double zero = 0.0;
const double first_subnormal = nextafter(zero, 1.0);
const double second_subnormal = nextafter(first_subnormal, 1.0);
const double first_normal = DBL_MIN;
const double last_subnormal = nextafter(first_normal, 0.0);
const double second_normal = nextafter(first_normal, 1.0);
const double last_normal = DBL_MAX;
const double penultimate_normal = nextafter(last_normal, 0.0);
// Various test cases for numbers between two representable floats. Each
// call to TestHalfwayValue tests a number just below and just above the
// halfway point, as well as the number exactly between them.
// Test between zero and first_subnormal. Round-to-even tie rounds down.
TestHalfwayValue(
"2."
"470328229206232720882843964341106861825299013071623822127928412503377536"
"351043759326499181808179961898982823477228588654633283551779698981993873"
"980053909390631503565951557022639229085839244910518443593180284993653615"
"250031937045767824921936562366986365848075700158576926990370631192827955"
"855133292783433840935197801553124659726357957462276646527282722005637400"
"648549997709659947045402082816622623785739345073633900796776193057750674"
"017632467360096895134053553745851666113422376667860416215968046191446729"
"184030053005753084904876539171138659164623952491262365388187963623937328"
"042389101867234849766823508986338858792562830275599565752445550725518931"
"369083625477918694866799496832404970582102851318545139621383772282614543"
"7693412532098591327667236328125",
-324, zero, first_subnormal, zero);
// first_subnormal and second_subnormal. Round-to-even tie rounds up.
TestHalfwayValue(
"7."
"410984687618698162648531893023320585475897039214871466383785237510132609"
"053131277979497545424539885696948470431685765963899850655339096945981621"
"940161728171894510697854671067917687257517734731555330779540854980960845"
"750095811137303474765809687100959097544227100475730780971111893578483867"
"565399878350301522805593404659373979179073872386829939581848166016912201"
"945649993128979841136206248449867871357218035220901702390328579173252022"
"052897402080290685402160661237554998340267130003581248647904138574340187"
"552090159017259254714629617513415977493871857473787096164563890871811984"
"127167305601704549300470526959016576377688490826798697257336652176556794"
"107250876433756084600398490497214911746308553955635418864151316847843631"
"3080237596295773983001708984375",
-324, first_subnormal, second_subnormal, second_subnormal);
// last_subnormal and first_normal. Round-to-even tie rounds up.
TestHalfwayValue(
"2."
"225073858507201136057409796709131975934819546351645648023426109724822222"
"021076945516529523908135087914149158913039621106870086438694594645527657"
"207407820621743379988141063267329253552286881372149012981122451451889849"
"057222307285255133155755015914397476397983411801999323962548289017107081"
"850690630666655994938275772572015763062690663332647565300009245888316433"
"037779791869612049497390377829704905051080609940730262937128958950003583"
"799967207254304360284078895771796150945516748243471030702609144621572289"
"880258182545180325707018860872113128079512233426288368622321503775666622"
"503982534335974568884423900265498198385487948292206894721689831099698365"
"846814022854243330660339850886445804001034933970427567186443383770486037"
"86162277173854562306587467901408672332763671875",
-308, last_subnormal, first_normal, first_normal);
// first_normal and second_normal. Round-to-even tie rounds down.
TestHalfwayValue(
"2."
"225073858507201630123055637955676152503612414573018013083228724049586647"
"606759446192036794116886953213985520549032000903434781884412325572184367"
"563347617020518175998922941393629966742598285899994830148971433555578567"
"693279306015978183162142425067962460785295885199272493577688320732492479"
"924816869232247165964934329258783950102250973957579510571600738343645738"
"494324192997092179207389919761694314131497173265255020084997973676783743"
"155205818804439163810572367791175177756227497413804253387084478193655533"
"073867420834526162513029462022730109054820067654020201547112002028139700"
"141575259123440177362244273712468151750189745559978653234255886219611516"
"335924167958029604477064946470184777360934300451421683607013647479513962"
"13837722826145437693412532098591327667236328125",
-308, first_normal, second_normal, first_normal);
// penultimate_normal and last_normal. Round-to-even rounds down.
TestHalfwayValue(
"1."
"797693134862315608353258760581052985162070023416521662616611746258695532"
"672923265745300992879465492467506314903358770175220871059269879629062776"
"047355692132901909191523941804762171253349609463563872612866401980290377"
"995141836029815117562837277714038305214839639239356331336428021390916694"
"57927874464075218944",
308, penultimate_normal, last_normal, penultimate_normal);
}
// Same test cases as DoubleRounding, now with new and improved Much Smaller
// Precision!
TEST(FromChars, FloatRounding) {
const float zero = 0.0;
const float first_subnormal = nextafterf(zero, 1.0);
const float second_subnormal = nextafterf(first_subnormal, 1.0);
const float first_normal = FLT_MIN;
const float last_subnormal = nextafterf(first_normal, 0.0);
const float second_normal = nextafterf(first_normal, 1.0);
const float last_normal = FLT_MAX;
const float penultimate_normal = nextafterf(last_normal, 0.0);
// Test between zero and first_subnormal. Round-to-even tie rounds down.
TestHalfwayValue(
"7."
"006492321624085354618647916449580656401309709382578858785341419448955413"
"42930300743319094181060791015625",
-46, zero, first_subnormal, zero);
// first_subnormal and second_subnormal. Round-to-even tie rounds up.
TestHalfwayValue(
"2."
"101947696487225606385594374934874196920392912814773657635602425834686624"
"028790902229957282543182373046875",
-45, first_subnormal, second_subnormal, second_subnormal);
// last_subnormal and first_normal. Round-to-even tie rounds up.
TestHalfwayValue(
"1."
"175494280757364291727882991035766513322858992758990427682963118425003064"
"9651730385585324256680905818939208984375",
-38, last_subnormal, first_normal, first_normal);
// first_normal and second_normal. Round-to-even tie rounds down.
TestHalfwayValue(
"1."
"175494420887210724209590083408724842314472120785184615334540294131831453"
"9442813071445925743319094181060791015625",
-38, first_normal, second_normal, first_normal);
// penultimate_normal and last_normal. Round-to-even rounds down.
TestHalfwayValue("3.40282336497324057985868971510891282432", 38,
penultimate_normal, last_normal, penultimate_normal);
}
TEST(FromChars, Underflow) {
// Check that underflow is handled correctly, according to the specification
// in DR 3081.
double d;
float f;
absl::from_chars_result result;
std::string negative_underflow = "-1e-1000";
const char* begin = negative_underflow.data();
const char* end = begin + negative_underflow.size();
d = 100.0;
result = absl::from_chars(begin, end, d);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_TRUE(std::signbit(d)); // negative
EXPECT_GE(d, -std::numeric_limits<double>::min());
f = 100.0;
result = absl::from_chars(begin, end, f);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_TRUE(std::signbit(f)); // negative
EXPECT_GE(f, -std::numeric_limits<float>::min());
std::string positive_underflow = "1e-1000";
begin = positive_underflow.data();
end = begin + positive_underflow.size();
d = -100.0;
result = absl::from_chars(begin, end, d);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_FALSE(std::signbit(d)); // positive
EXPECT_LE(d, std::numeric_limits<double>::min());
f = -100.0;
result = absl::from_chars(begin, end, f);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_FALSE(std::signbit(f)); // positive
EXPECT_LE(f, std::numeric_limits<float>::min());
}
TEST(FromChars, Overflow) {
// Check that overflow is handled correctly, according to the specification
// in DR 3081.
double d;
float f;
absl::from_chars_result result;
std::string negative_overflow = "-1e1000";
const char* begin = negative_overflow.data();
const char* end = begin + negative_overflow.size();
d = 100.0;
result = absl::from_chars(begin, end, d);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_TRUE(std::signbit(d)); // negative
EXPECT_EQ(d, -std::numeric_limits<double>::max());
f = 100.0;
result = absl::from_chars(begin, end, f);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_TRUE(std::signbit(f)); // negative
EXPECT_EQ(f, -std::numeric_limits<float>::max());
std::string positive_overflow = "1e1000";
begin = positive_overflow.data();
end = begin + positive_overflow.size();
d = -100.0;
result = absl::from_chars(begin, end, d);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_FALSE(std::signbit(d)); // positive
EXPECT_EQ(d, std::numeric_limits<double>::max());
f = -100.0;
result = absl::from_chars(begin, end, f);
EXPECT_EQ(result.ptr, end);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_FALSE(std::signbit(f)); // positive
EXPECT_EQ(f, std::numeric_limits<float>::max());
}
TEST(FromChars, ReturnValuePtr) {
// Check that `ptr` points one past the number scanned, even if that number
// is not representable.
double d;
absl::from_chars_result result;
std::string normal = "3.14@#$%@#$%";
result = absl::from_chars(normal.data(), normal.data() + normal.size(), d);
EXPECT_EQ(result.ec, std::errc());
EXPECT_EQ(result.ptr - normal.data(), 4);
std::string overflow = "1e1000@#$%@#$%";
result = absl::from_chars(overflow.data(),
overflow.data() + overflow.size(), d);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_EQ(result.ptr - overflow.data(), 6);
std::string garbage = "#$%@#$%";
result = absl::from_chars(garbage.data(),
garbage.data() + garbage.size(), d);
EXPECT_EQ(result.ec, std::errc::invalid_argument);
EXPECT_EQ(result.ptr - garbage.data(), 0);
}
// Check for a wide range of inputs that strtod() and absl::from_chars() exactly
// agree on the conversion amount.
//
// This test assumes the platform's strtod() uses perfect round_to_nearest
// rounding.
TEST(FromChars, TestVersusStrtod) {
for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) {
for (int exponent = -300; exponent < 300; ++exponent) {
std::string candidate = absl::StrCat(mantissa, "e", exponent);
double strtod_value = strtod(candidate.c_str(), nullptr);
double absl_value = 0;
absl::from_chars(candidate.data(), candidate.data() + candidate.size(),
absl_value);
ASSERT_EQ(strtod_value, absl_value) << candidate;
}
}
}
// Check for a wide range of inputs that strtof() and absl::from_chars() exactly
// agree on the conversion amount.
//
// This test assumes the platform's strtof() uses perfect round_to_nearest
// rounding.
TEST(FromChars, TestVersusStrtof) {
for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) {
for (int exponent = -43; exponent < 32; ++exponent) {
std::string candidate = absl::StrCat(mantissa, "e", exponent);
float strtod_value = strtof(candidate.c_str(), nullptr);
float absl_value = 0;
absl::from_chars(candidate.data(), candidate.data() + candidate.size(),
absl_value);
ASSERT_EQ(strtod_value, absl_value) << candidate;
}
}
}
// Tests if two floating point values have identical bit layouts. (EXPECT_EQ
// is not suitable for NaN testing, since NaNs are never equal.)
template <typename Float>
bool Identical(Float a, Float b) {
return 0 == memcmp(&a, &b, sizeof(Float));
}
// Check that NaNs are parsed correctly. The spec requires that
// std::from_chars on "NaN(123abc)" return the same value as std::nan("123abc").
// How such an n-char-sequence affects the generated NaN is unspecified, so we
// just test for symmetry with std::nan and strtod here.
//
// (In Linux, this parses the value as a number and stuffs that number into the
// free bits of a quiet NaN.)
TEST(FromChars, NaNDoubles) {
for (std::string n_char_sequence :
{"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000",
"8000000000000", "abc123", "legal_but_unexpected",
"99999999999999999999999", "_"}) {
std::string input = absl::StrCat("nan(", n_char_sequence, ")");
SCOPED_TRACE(input);
double from_chars_double;
absl::from_chars(input.data(), input.data() + input.size(),
from_chars_double);
double std_nan_double = std::nan(n_char_sequence.c_str());
EXPECT_TRUE(Identical(from_chars_double, std_nan_double));
// Also check that we match strtod()'s behavior. This test assumes that the
// platform has a compliant strtod().
#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY
double strtod_double = strtod(input.c_str(), nullptr);
EXPECT_TRUE(Identical(from_chars_double, strtod_double));
#endif // ABSL_STRTOD_HANDLES_NAN_CORRECTLY
// Check that we can parse a negative NaN
std::string negative_input = "-" + input;
double negative_from_chars_double;
absl::from_chars(negative_input.data(),
negative_input.data() + negative_input.size(),
negative_from_chars_double);
EXPECT_TRUE(std::signbit(negative_from_chars_double));
EXPECT_FALSE(Identical(negative_from_chars_double, from_chars_double));
from_chars_double = std::copysign(from_chars_double, -1.0);
EXPECT_TRUE(Identical(negative_from_chars_double, from_chars_double));
}
}
TEST(FromChars, NaNFloats) {
for (std::string n_char_sequence :
{"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000",
"8000000000000", "abc123", "legal_but_unexpected",
"99999999999999999999999", "_"}) {
std::string input = absl::StrCat("nan(", n_char_sequence, ")");
SCOPED_TRACE(input);
float from_chars_float;
absl::from_chars(input.data(), input.data() + input.size(),
from_chars_float);
float std_nan_float = std::nanf(n_char_sequence.c_str());
EXPECT_TRUE(Identical(from_chars_float, std_nan_float));
// Also check that we match strtof()'s behavior. This test assumes that the
// platform has a compliant strtof().
#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY
float strtof_float = strtof(input.c_str(), nullptr);
EXPECT_TRUE(Identical(from_chars_float, strtof_float));
#endif // ABSL_STRTOD_HANDLES_NAN_CORRECTLY
// Check that we can parse a negative NaN
std::string negative_input = "-" + input;
float negative_from_chars_float;
absl::from_chars(negative_input.data(),
negative_input.data() + negative_input.size(),
negative_from_chars_float);
EXPECT_TRUE(std::signbit(negative_from_chars_float));
EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float));
from_chars_float = std::copysign(from_chars_float, -1.0);
EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float));
}
}
// Returns an integer larger than step. The values grow exponentially.
int NextStep(int step) {
return step + (step >> 2) + 1;
}
// Test a conversion on a family of input strings, checking that the calculation
// is correct for in-bounds values, and that overflow and underflow are done
// correctly for out-of-bounds values.
//
// input_generator maps from an integer index to a std::string to test.
// expected_generator maps from an integer index to an expected Float value.
// from_chars conversion of input_generator(i) should result in
// expected_generator(i).
//
// lower_bound and upper_bound denote the smallest and largest values for which
// the conversion is expected to succeed.
template <typename Float>
void TestOverflowAndUnderflow(
const std::function<std::string(int)>& input_generator,
const std::function<Float(int)>& expected_generator, int lower_bound,
int upper_bound) {
// test legal values near lower_bound
int index, step;
for (index = lower_bound, step = 1; index < upper_bound;
index += step, step = NextStep(step)) {
std::string input = input_generator(index);
SCOPED_TRACE(input);
Float expected = expected_generator(index);
Float actual;
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc());
EXPECT_EQ(expected, actual);
}
// test legal values near upper_bound
for (index = upper_bound, step = 1; index > lower_bound;
index -= step, step = NextStep(step)) {
std::string input = input_generator(index);
SCOPED_TRACE(input);
Float expected = expected_generator(index);
Float actual;
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc());
EXPECT_EQ(expected, actual);
}
// Test underflow values below lower_bound
for (index = lower_bound - 1, step = 1; index > -1000000;
index -= step, step = NextStep(step)) {
std::string input = input_generator(index);
SCOPED_TRACE(input);
Float actual;
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_LT(actual, 1.0); // check for underflow
}
// Test overflow values above upper_bound
for (index = upper_bound + 1, step = 1; index < 1000000;
index += step, step = NextStep(step)) {
std::string input = input_generator(index);
SCOPED_TRACE(input);
Float actual;
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc::result_out_of_range);
EXPECT_GT(actual, 1.0); // check for overflow
}
}
// Check that overflow and underflow are caught correctly for hex doubles.
//
// The largest representable double is 0x1.fffffffffffffp+1023, and the
// smallest representable subnormal is 0x0.0000000000001p-1022, which equals
// 0x1p-1074. Therefore 1023 and -1074 are the limits of acceptable exponents
// in this test.
TEST(FromChars, HexdecimalDoubleLimits) {
auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); };
auto expected_gen = [](int index) { return std::ldexp(1.0, index); };
TestOverflowAndUnderflow<double>(input_gen, expected_gen, -1074, 1023);
}
// Check that overflow and underflow are caught correctly for hex floats.
//
// The largest representable float is 0x1.fffffep+127, and the smallest
// representable subnormal is 0x0.000002p-126, which equals 0x1p-149.
// Therefore 127 and -149 are the limits of acceptable exponents in this test.
TEST(FromChars, HexdecimalFloatLimits) {
auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); };
auto expected_gen = [](int index) { return std::ldexp(1.0f, index); };
TestOverflowAndUnderflow<float>(input_gen, expected_gen, -149, 127);
}
// Check that overflow and underflow are caught correctly for decimal doubles.
//
// The largest representable double is about 1.8e308, and the smallest
// representable subnormal is about 5e-324. '1e-324' therefore rounds away from
// the smallest representable positive value. -323 and 308 are the limits of
// acceptable exponents in this test.
TEST(FromChars, DecimalDoubleLimits) {
auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
auto expected_gen = [](int index) { return std::pow(10.0, index); };
TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308);
}
// Check that overflow and underflow are caught correctly for decimal floats.
//
// The largest representable float is about 3.4e38, and the smallest
// representable subnormal is about 1.45e-45. '1e-45' therefore rounds towards
// the smallest representable positive value. -45 and 38 are the limits of
// acceptable exponents in this test.
TEST(FromChars, DecimalFloatLimits) {
auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
auto expected_gen = [](int index) { return std::pow(10.0, index); };
TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38);
}
} // namespace

View File

@ -1,357 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/internal/charconv_bigint.h"
#include <algorithm>
#include <cassert>
#include <string>
namespace absl {
namespace strings_internal {
namespace {
// Table containing some large powers of 5, for fast computation.
// Constant step size for entries in the kLargePowersOfFive table. Each entry
// is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep
// (or 5**27).
//
// In other words, the Nth entry in the table is 5**(27*N).
//
// 5**27 is the largest power of 5 that fits in 64 bits.
constexpr int kLargePowerOfFiveStep = 27;
// The largest legal index into the kLargePowersOfFive table.
//
// In other words, the largest precomputed power of 5 is 5**(27*20).
constexpr int kLargestPowerOfFiveIndex = 20;
// Table of powers of (5**27), up to (5**27)**20 == 5**540.
//
// Used to generate large powers of 5 while limiting the number of repeated
// multiplications required.
//
// clang-format off
const uint32_t kLargePowersOfFive[] = {
// 5**27 (i=1), start=0, end=2
0xfa10079dU, 0x6765c793U,
// 5**54 (i=2), start=2, end=6
0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U,
// 5**81 (i=3), start=6, end=12
0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U,
// 5**108 (i=4), start=12, end=20
0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU,
0x20d3846fU, 0x06d00f73U,
// 5**135 (i=5), start=20, end=30
0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U,
0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU,
// 5**162 (i=6), start=30, end=42
0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU,
0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU,
// 5**189 (i=7), start=42, end=56
0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U,
0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U,
0x94151217U, 0x0072e9f7U,
// 5**216 (i=8), start=56, end=72
0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU,
0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU,
0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U,
// 5**243 (i=9), start=72, end=90
0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U,
0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U,
0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U,
// 5**270 (i=10), start=90, end=110
0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U,
0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U,
0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U,
0x0d39e796U, 0x00079250U,
// 5**297 (i=11), start=110, end=132
0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U,
0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U,
0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U,
0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U,
// 5**324 (i=12), start=132, end=156
0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U,
0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU,
0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U,
0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U,
// 5**351 (i=13), start=156, end=182
0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU,
0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U,
0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U,
0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU,
0x859a4940U, 0x00007fb6U,
// 5**378 (i=14), start=182, end=210
0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U,
0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU,
0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU,
0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U,
0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U,
// 5**405 (i=15), start=210, end=240
0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U,
0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U,
0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U,
0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU,
0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U,
// 5**432 (i=16), start=240, end=272
0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU,
0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U,
0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U,
0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU,
0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U,
0x3364ea62U, 0x0000086aU,
// 5**459 (i=17), start=272, end=306
0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU,
0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U,
0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U,
0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U,
0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU,
0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U,
// 5**486 (i=18), start=306, end=342
0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU,
0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U,
0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU,
0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U,
0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU,
0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU,
// 5**513 (i=19), start=342, end=380
0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U,
0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU,
0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU,
0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U,
0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U,
0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU,
0xf0046d27U, 0x0000008dU,
// 5**540 (i=20), start=380, end=420
0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU,
0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U,
0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U,
0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U,
0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U,
0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU,
0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U,
};
// clang-format on
// Returns a pointer to the big integer data for (5**27)**i. i must be
// between 1 and 20, inclusive.
const uint32_t* LargePowerOfFiveData(int i) {
return kLargePowersOfFive + i * (i - 1);
}
// Returns the size of the big integer data for (5**27)**i, in words. i must be
// between 1 and 20, inclusive.
int LargePowerOfFiveSize(int i) { return 2 * i; }
} // namespace
const uint32_t kFiveToNth[14] = {
1, 5, 25, 125, 625, 3125, 15625,
78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
};
const uint32_t kTenToNth[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
};
template <int max_words>
int BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp,
int significant_digits) {
SetToZero();
assert(fp.type == FloatType::kNumber);
if (fp.subrange_begin == nullptr) {
// We already exactly parsed the mantissa, so no more work is necessary.
words_[0] = fp.mantissa & 0xffffffffu;
words_[1] = fp.mantissa >> 32;
if (words_[1]) {
size_ = 2;
} else if (words_[0]) {
size_ = 1;
}
return fp.exponent;
}
int exponent_adjust =
ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits);
return fp.literal_exponent + exponent_adjust;
}
template <int max_words>
int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
int significant_digits) {
assert(significant_digits <= Digits10() + 1);
SetToZero();
bool after_decimal_point = false;
// Discard any leading zeroes before the decimal point
while (begin < end && *begin == '0') {
++begin;
}
int dropped_digits = 0;
// Discard any trailing zeroes. These may or may not be after the decimal
// point.
while (begin < end && *std::prev(end) == '0') {
--end;
++dropped_digits;
}
if (begin < end && *std::prev(end) == '.') {
// If the std::string ends in '.', either before or after dropping zeroes, then
// drop the decimal point and look for more digits to drop.
dropped_digits = 0;
--end;
while (begin < end && *std::prev(end) == '0') {
--end;
++dropped_digits;
}
} else if (dropped_digits) {
// We dropped digits, and aren't sure if they're before or after the decimal
// point. Figure that out now.
const char* dp = std::find(begin, end, '.');
if (dp != end) {
// The dropped trailing digits were after the decimal point, so don't
// count them.
dropped_digits = 0;
}
}
// Any non-fraction digits we dropped need to be accounted for in our exponent
// adjustment.
int exponent_adjust = dropped_digits;
uint32_t queued = 0;
int digits_queued = 0;
for (; begin != end && significant_digits > 0; ++begin) {
if (*begin == '.') {
after_decimal_point = true;
continue;
}
if (after_decimal_point) {
// For each fractional digit we emit in our parsed integer, adjust our
// decimal exponent to compensate.
--exponent_adjust;
}
int digit = (*begin - '0');
--significant_digits;
if (significant_digits == 0 && std::next(begin) != end &&
(digit == 0 || digit == 5)) {
// If this is the very last significant digit, but insignificant digits
// remain, we know that the last of those remaining significant digits is
// nonzero. (If it wasn't, we would have stripped it before we got here.)
// So if this final digit is a 0 or 5, adjust it upward by 1.
//
// This adjustment is what allows incredibly large mantissas ending in
// 500000...000000000001 to correctly round up, rather than to nearest.
++digit;
}
queued = 10 * queued + digit;
++digits_queued;
if (digits_queued == kMaxSmallPowerOfTen) {
MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);
AddWithCarry(0, queued);
queued = digits_queued = 0;
}
}
// Encode any remaining digits.
if (digits_queued) {
MultiplyBy(kTenToNth[digits_queued]);
AddWithCarry(0, queued);
}
// If any insignificant digits remain, we will drop them. But if we have not
// yet read the decimal point, then we have to adjust the exponent to account
// for the dropped digits.
if (begin < end && !after_decimal_point) {
// This call to std::find will result in a pointer either to the decimal
// point, or to the end of our buffer if there was none.
//
// Either way, [begin, decimal_point) will contain the set of dropped digits
// that require an exponent adjustment.
const char* decimal_point = std::find(begin, end, '.');
exponent_adjust += (decimal_point - begin);
}
return exponent_adjust;
}
template <int max_words>
/* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth(
int n) {
BigUnsigned answer(1u);
// Seed from the table of large powers, if possible.
bool first_pass = true;
while (n >= kLargePowerOfFiveStep) {
int big_power =
std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex);
if (first_pass) {
// just copy, rather than multiplying by 1
std::copy(
LargePowerOfFiveData(big_power),
LargePowerOfFiveData(big_power) + LargePowerOfFiveSize(big_power),
answer.words_);
answer.size_ = LargePowerOfFiveSize(big_power);
first_pass = false;
} else {
answer.MultiplyBy(LargePowerOfFiveSize(big_power),
LargePowerOfFiveData(big_power));
}
n -= kLargePowerOfFiveStep * big_power;
}
answer.MultiplyByFiveToTheNth(n);
return answer;
}
template <int max_words>
void BigUnsigned<max_words>::MultiplyStep(int original_size,
const uint32_t* other_words,
int other_size, int step) {
int this_i = std::min(original_size - 1, step);
int other_i = step - this_i;
uint64_t this_word = 0;
uint64_t carry = 0;
for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) {
uint64_t product = words_[this_i];
product *= other_words[other_i];
this_word += product;
carry += (this_word >> 32);
this_word &= 0xffffffff;
}
AddWithCarry(step + 1, carry);
words_[step] = this_word & 0xffffffff;
if (this_word > 0 && size_ <= step) {
size_ = step + 1;
}
}
template <int max_words>
std::string BigUnsigned<max_words>::ToString() const {
BigUnsigned<max_words> copy = *this;
std::string result;
// Build result in reverse order
while (copy.size() > 0) {
int next_digit = copy.DivMod<10>();
result.push_back('0' + next_digit);
}
if (result.empty()) {
result.push_back('0');
}
std::reverse(result.begin(), result.end());
return result;
}
template class BigUnsigned<4>;
template class BigUnsigned<84>;
} // namespace strings_internal
} // namespace absl

View File

@ -1,426 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <string>
#include "absl/strings/ascii.h"
#include "absl/strings/internal/charconv_parse.h"
#include "absl/strings/string_view.h"
namespace absl {
namespace strings_internal {
// The largest power that 5 that can be raised to, and still fit in a uint32_t.
constexpr int kMaxSmallPowerOfFive = 13;
// The largest power that 10 that can be raised to, and still fit in a uint32_t.
constexpr int kMaxSmallPowerOfTen = 9;
extern const uint32_t kFiveToNth[kMaxSmallPowerOfFive + 1];
extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
// Large, fixed-width unsigned integer.
//
// Exact rounding for decimal-to-binary floating point conversion requires very
// large integer math, but a design goal of absl::from_chars is to avoid
// allocating memory. The integer precision needed for decimal-to-binary
// conversions is large but bounded, so a huge fixed-width integer class
// suffices.
//
// This is an intentionally limited big integer class. Only needed operations
// are implemented. All storage lives in an array data member, and all
// arithmetic is done in-place, to avoid requiring separate storage for operand
// and result.
//
// This is an internal class. Some methods live in the .cc file, and are
// instantiated only for the values of max_words we need.
template <int max_words>
class BigUnsigned {
public:
static_assert(max_words == 4 || max_words == 84,
"unsupported max_words value");
BigUnsigned() : size_(0), words_{} {}
explicit BigUnsigned(uint32_t v) : size_(v > 0 ? 1 : 0), words_{v} {}
explicit BigUnsigned(uint64_t v)
: size_(0),
words_{static_cast<uint32_t>(v & 0xffffffff),
static_cast<uint32_t>(v >> 32)} {
if (words_[1]) {
size_ = 2;
} else if (words_[0]) {
size_ = 1;
}
}
// Constructs a BigUnsigned from the given string_view containing a decimal
// value. If the input std::string is not a decimal integer, constructs a 0
// instead.
explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
// Check for valid input, returning a 0 otherwise. This is reasonable
// behavior only because this constructor is for unit tests.
if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
sv.empty()) {
return;
}
int exponent_adjust =
ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
if (exponent_adjust > 0) {
MultiplyByTenToTheNth(exponent_adjust);
}
}
// Loads the mantissa value of a previously-parsed float.
//
// Returns the associated decimal exponent. The value of the parsed float is
// exactly *this * 10**exponent.
int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
// Returns the number of decimal digits of precision this type provides. All
// numbers with this many decimal digits or fewer are representable by this
// type.
//
// Analagous to std::numeric_limits<BigUnsigned>::digits10.
static constexpr int Digits10() {
// 9975007/1035508 is very slightly less than log10(2**32).
return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
}
// Shifts left by the given number of bits.
void ShiftLeft(int count) {
if (count > 0) {
const int word_shift = count / 32;
if (word_shift >= max_words) {
SetToZero();
return;
}
size_ = std::min(size_ + word_shift, max_words);
count %= 32;
if (count == 0) {
std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
} else {
for (int i = std::min(size_, max_words - 1); i > word_shift; --i) {
words_[i] = (words_[i - word_shift] << count) |
(words_[i - word_shift - 1] >> (32 - count));
}
words_[word_shift] = words_[0] << count;
// Grow size_ if necessary.
if (size_ < max_words && words_[size_]) {
++size_;
}
}
std::fill(words_, words_ + word_shift, 0u);
}
}
// Multiplies by v in-place.
void MultiplyBy(uint32_t v) {
if (size_ == 0 || v == 1) {
return;
}
if (v == 0) {
SetToZero();
return;
}
const uint64_t factor = v;
uint64_t window = 0;
for (int i = 0; i < size_; ++i) {
window += factor * words_[i];
words_[i] = window & 0xffffffff;
window >>= 32;
}
// If carry bits remain and there's space for them, grow size_.
if (window && size_ < max_words) {
words_[size_] = window & 0xffffffff;
++size_;
}
}
void MultiplyBy(uint64_t v) {
uint32_t words[2];
words[0] = static_cast<uint32_t>(v);
words[1] = static_cast<uint32_t>(v >> 32);
if (words[1] == 0) {
MultiplyBy(words[0]);
} else {
MultiplyBy(2, words);
}
}
// Multiplies in place by 5 to the power of n. n must be non-negative.
void MultiplyByFiveToTheNth(int n) {
while (n >= kMaxSmallPowerOfFive) {
MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
n -= kMaxSmallPowerOfFive;
}
if (n > 0) {
MultiplyBy(kFiveToNth[n]);
}
}
// Multiplies in place by 10 to the power of n. n must be non-negative.
void MultiplyByTenToTheNth(int n) {
if (n > kMaxSmallPowerOfTen) {
// For large n, raise to a power of 5, then shift left by the same amount.
// (10**n == 5**n * 2**n.) This requires fewer multiplications overall.
MultiplyByFiveToTheNth(n);
ShiftLeft(n);
} else if (n > 0) {
// We can do this more quickly for very small N by using a single
// multiplication.
MultiplyBy(kTenToNth[n]);
}
}
// Returns the value of 5**n, for non-negative n. This implementation uses
// a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
// MultiplyByFiveToTheNth().
static BigUnsigned FiveToTheNth(int n);
// Multiplies by another BigUnsigned, in-place.
template <int M>
void MultiplyBy(const BigUnsigned<M>& other) {
MultiplyBy(other.size(), other.words());
}
void SetToZero() {
std::fill(words_, words_ + size_, 0u);
size_ = 0;
}
// Returns the value of the nth word of this BigUnsigned. This is
// range-checked, and returns 0 on out-of-bounds accesses.
uint32_t GetWord(int index) const {
if (index < 0 || index >= size_) {
return 0;
}
return words_[index];
}
// Returns this integer as a decimal std::string. This is not used in the decimal-
// to-binary conversion; it is intended to aid in testing.
std::string ToString() const;
int size() const { return size_; }
const uint32_t* words() const { return words_; }
private:
// Reads the number between [begin, end), possibly containing a decimal point,
// into this BigUnsigned.
//
// Callers are required to ensure [begin, end) contains a valid number, with
// one or more decimal digits and at most one decimal point. This routine
// will behave unpredictably if these preconditions are not met.
//
// Only the first `significant_digits` digits are read. Digits beyond this
// limit are "sticky": If the final significant digit is 0 or 5, and if any
// dropped digit is nonzero, then that final significant digit is adjusted up
// to 1 or 6. This adjustment allows for precise rounding.
//
// Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
// account for the decimal point and for dropped significant digits. After
// this function returns,
// actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
int ReadDigits(const char* begin, const char* end, int significant_digits);
// Performs a step of big integer multiplication. This computes the full
// (64-bit-wide) values that should be added at the given index (step), and
// adds to that location in-place.
//
// Because our math all occurs in place, we must multiply starting from the
// highest word working downward. (This is a bit more expensive due to the
// extra carries involved.)
//
// This must be called in steps, for each word to be calculated, starting from
// the high end and working down to 0. The first value of `step` should be
// `std::min(original_size + other.size_ - 2, max_words - 1)`.
// The reason for this expression is that multiplying the i'th word from one
// multiplicand and the j'th word of another multiplicand creates a
// two-word-wide value to be stored at the (i+j)'th element. The highest
// word indices we will access are `original_size - 1` from this object, and
// `other.size_ - 1` from our operand. Therefore,
// `original_size + other.size_ - 2` is the first step we should calculate,
// but limited on an upper bound by max_words.
// Working from high-to-low ensures that we do not overwrite the portions of
// the initial value of *this which are still needed for later steps.
//
// Once called with step == 0, *this contains the result of the
// multiplication.
//
// `original_size` is the size_ of *this before the first call to
// MultiplyStep(). `other_words` and `other_size` are the contents of our
// operand. `step` is the step to perform, as described above.
void MultiplyStep(int original_size, const uint32_t* other_words,
int other_size, int step);
void MultiplyBy(int other_size, const uint32_t* other_words) {
const int original_size = size_;
const int first_step =
std::min(original_size + other_size - 2, max_words - 1);
for (int step = first_step; step >= 0; --step) {
MultiplyStep(original_size, other_words, other_size, step);
}
}
// Adds a 32-bit value to the index'th word, with carry.
void AddWithCarry(int index, uint32_t value) {
if (value) {
while (index < max_words && value > 0) {
words_[index] += value;
// carry if we overflowed in this word:
if (value > words_[index]) {
value = 1;
++index;
} else {
value = 0;
}
}
size_ = std::min(max_words, std::max(index + 1, size_));
}
}
void AddWithCarry(int index, uint64_t value) {
if (value && index < max_words) {
uint32_t high = value >> 32;
uint32_t low = value & 0xffffffff;
words_[index] += low;
if (words_[index] < low) {
++high;
if (high == 0) {
// Carry from the low word caused our high word to overflow.
// Short circuit here to do the right thing.
AddWithCarry(index + 2, static_cast<uint32_t>(1));
return;
}
}
if (high > 0) {
AddWithCarry(index + 1, high);
} else {
// Normally 32-bit AddWithCarry() sets size_, but since we don't call
// it when `high` is 0, do it ourselves here.
size_ = std::min(max_words, std::max(index + 1, size_));
}
}
}
// Divide this in place by a constant divisor. Returns the remainder of the
// division.
template <uint32_t divisor>
uint32_t DivMod() {
uint64_t accumulator = 0;
for (int i = size_ - 1; i >= 0; --i) {
accumulator <<= 32;
accumulator += words_[i];
// accumulator / divisor will never overflow an int32_t in this loop
words_[i] = static_cast<uint32_t>(accumulator / divisor);
accumulator = accumulator % divisor;
}
while (size_ > 0 && words_[size_ - 1] == 0) {
--size_;
}
return static_cast<uint32_t>(accumulator);
}
// The number of elements in words_ that may carry significant values.
// All elements beyond this point are 0.
//
// When size_ is 0, this BigUnsigned stores the value 0.
// When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
// nonzero. This can occur due to overflow truncation.
// In particular, x.size_ != y.size_ does *not* imply x != y.
int size_;
uint32_t words_[max_words];
};
// Compares two big integer instances.
//
// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
template <int N, int M>
int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
int limit = std::max(lhs.size(), rhs.size());
for (int i = limit - 1; i >= 0; --i) {
const uint32_t lhs_word = lhs.GetWord(i);
const uint32_t rhs_word = rhs.GetWord(i);
if (lhs_word < rhs_word) {
return -1;
} else if (lhs_word > rhs_word) {
return 1;
}
}
return 0;
}
template <int N, int M>
bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
int limit = std::max(lhs.size(), rhs.size());
for (int i = 0; i < limit; ++i) {
if (lhs.GetWord(i) != rhs.GetWord(i)) {
return false;
}
}
return true;
}
template <int N, int M>
bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
return !(lhs == rhs);
}
template <int N, int M>
bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
return Compare(lhs, rhs) == -1;
}
template <int N, int M>
bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
return rhs < lhs;
}
template <int N, int M>
bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
return !(rhs < lhs);
}
template <int N, int M>
bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
return !(lhs < rhs);
}
// Output operator for BigUnsigned, for testing purposes only.
template <int N>
std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
return os << num.ToString();
}
// Explicit instantiation declarations for the sizes of BigUnsigned that we
// are using.
//
// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
// still bigger than an int128, and 84 is a large value we will want to use
// in the from_chars implementation.
//
// Comments justifying the use of 84 belong in the from_chars implementation,
// and will be added in a follow-up CL.
extern template class BigUnsigned<4>;
extern template class BigUnsigned<84>;
} // namespace strings_internal
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_

View File

@ -1,203 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/internal/charconv_bigint.h"
#include <string>
#include "gtest/gtest.h"
namespace absl {
namespace strings_internal {
TEST(BigUnsigned, ShiftLeft) {
{
// Check that 3 * 2**100 is calculated correctly
BigUnsigned<4> num(3u);
num.ShiftLeft(100);
EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128"));
}
{
// Test that overflow is truncated properly.
// 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint.
// Shifting left by 125 bits should truncate off the high bit, so that
// 15 << 125 == 7 << 125
// after truncation.
BigUnsigned<4> a(15u);
BigUnsigned<4> b(7u);
BigUnsigned<4> c(3u);
a.ShiftLeft(125);
b.ShiftLeft(125);
c.ShiftLeft(125);
EXPECT_EQ(a, b);
EXPECT_NE(a, c);
}
{
// Same test, larger bigint:
BigUnsigned<84> a(15u);
BigUnsigned<84> b(7u);
BigUnsigned<84> c(3u);
a.ShiftLeft(84 * 32 - 3);
b.ShiftLeft(84 * 32 - 3);
c.ShiftLeft(84 * 32 - 3);
EXPECT_EQ(a, b);
EXPECT_NE(a, c);
}
{
// Check that incrementally shifting has the same result as doing it all at
// once (attempting to capture corner cases.)
const std::string seed = "1234567890123456789012345678901234567890";
BigUnsigned<84> a(seed);
for (int i = 1; i <= 84 * 32; ++i) {
a.ShiftLeft(1);
BigUnsigned<84> b(seed);
b.ShiftLeft(i);
EXPECT_EQ(a, b);
}
// And we should have fully rotated all bits off by now:
EXPECT_EQ(a, BigUnsigned<84>(0u));
}
}
TEST(BigUnsigned, MultiplyByUint32) {
const BigUnsigned<84> factorial_100(
"933262154439441526816992388562667004907159682643816214685929638952175999"
"932299156089414639761565182862536979208272237582511852109168640000000000"
"00000000000000");
BigUnsigned<84> a(1u);
for (uint32_t i = 1; i <= 100; ++i) {
a.MultiplyBy(i);
}
EXPECT_EQ(a, BigUnsigned<84>(factorial_100));
}
TEST(BigUnsigned, MultiplyByBigUnsigned) {
{
// Put the terms of factorial_200 into two bigints, and multiply them
// together.
const BigUnsigned<84> factorial_200(
"7886578673647905035523632139321850622951359776871732632947425332443594"
"4996340334292030428401198462390417721213891963883025764279024263710506"
"1926624952829931113462857270763317237396988943922445621451664240254033"
"2918641312274282948532775242424075739032403212574055795686602260319041"
"7032406235170085879617892222278962370389737472000000000000000000000000"
"0000000000000000000000000");
BigUnsigned<84> evens(1u);
BigUnsigned<84> odds(1u);
for (uint32_t i = 1; i < 200; i += 2) {
odds.MultiplyBy(i);
evens.MultiplyBy(i + 1);
}
evens.MultiplyBy(odds);
EXPECT_EQ(evens, factorial_200);
}
{
// Multiply various powers of 10 together.
for (int a = 0 ; a < 700; a += 25) {
SCOPED_TRACE(a);
BigUnsigned<84> a_value("3" + std::string(a, '0'));
for (int b = 0; b < (700 - a); b += 25) {
SCOPED_TRACE(b);
BigUnsigned<84> b_value("2" + std::string(b, '0'));
BigUnsigned<84> expected_product("6" + std::string(a + b, '0'));
b_value.MultiplyBy(a_value);
EXPECT_EQ(b_value, expected_product);
}
}
}
}
TEST(BigUnsigned, MultiplyByOverflow) {
{
// Check that multiplcation overflow predictably truncates.
// A big int with all bits on.
BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
// Modulo 2**128, this is equal to -1. Therefore the square of this,
// modulo 2**128, should be 1.
all_bits_on.MultiplyBy(all_bits_on);
EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u));
}
{
// Try multiplying a large bigint by 2**50, and compare the result to
// shifting.
BigUnsigned<4> value_1("12345678901234567890123456789012345678");
BigUnsigned<4> value_2("12345678901234567890123456789012345678");
BigUnsigned<4> two_to_fiftieth(1u);
two_to_fiftieth.ShiftLeft(50);
value_1.ShiftLeft(50);
value_2.MultiplyBy(two_to_fiftieth);
EXPECT_EQ(value_1, value_2);
}
}
TEST(BigUnsigned, FiveToTheNth) {
{
// Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to
// and including overflow.
for (int i = 0; i < 1160; ++i) {
SCOPED_TRACE(i);
BigUnsigned<84> value_1(123u);
BigUnsigned<84> value_2(123u);
value_1.MultiplyByFiveToTheNth(i);
for (int j = 0; j < i; j++) {
value_2.MultiplyBy(5u);
}
EXPECT_EQ(value_1, value_2);
}
}
{
// Check that the faster, table-lookup-based static method returns the same
// result that multiplying in-place would return, up to and including
// overflow.
for (int i = 0; i < 1160; ++i) {
SCOPED_TRACE(i);
BigUnsigned<84> value_1(1u);
value_1.MultiplyByFiveToTheNth(i);
BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i);
EXPECT_EQ(value_1, value_2);
}
}
}
TEST(BigUnsigned, TenToTheNth) {
{
// Sanity check MultiplyByTenToTheNth.
for (int i = 0; i < 800; ++i) {
SCOPED_TRACE(i);
BigUnsigned<84> value_1(123u);
BigUnsigned<84> value_2(123u);
value_1.MultiplyByTenToTheNth(i);
for (int j = 0; j < i; j++) {
value_2.MultiplyBy(10u);
}
EXPECT_EQ(value_1, value_2);
}
}
{
// Alternate testing approach, taking advantage of the decimal parser.
for (int i = 0; i < 200; ++i) {
SCOPED_TRACE(i);
BigUnsigned<84> value_1(135u);
value_1.MultiplyByTenToTheNth(i);
BigUnsigned<84> value_2("135" + std::string(i, '0'));
EXPECT_EQ(value_1, value_2);
}
}
}
} // namespace strings_internal
} // namespace absl

View File

@ -1,496 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/internal/charconv_parse.h"
#include "absl/strings/charconv.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include "absl/strings/internal/memutil.h"
namespace absl {
namespace {
// ParseFloat<10> will read the first 19 significant digits of the mantissa.
// This number was chosen for multiple reasons.
//
// (a) First, for whatever integer type we choose to represent the mantissa, we
// want to choose the largest possible number of decimal digits for that integer
// type. We are using uint64_t, which can express any 19-digit unsigned
// integer.
//
// (b) Second, we need to parse enough digits that the binary value of any
// mantissa we capture has more bits of resolution than the mantissa
// representation in the target float. Our algorithm requires at least 3 bits
// of headway, but 19 decimal digits give a little more than that.
//
// The following static assertions verify the above comments:
constexpr int kDecimalMantissaDigitsMax = 19;
static_assert(std::numeric_limits<uint64_t>::digits10 ==
kDecimalMantissaDigitsMax,
"(a) above");
// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.
static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed");
static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact");
static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
// The lowest valued 19-digit decimal mantissa we can read still contains
// sufficient information to reconstruct a binary mantissa.
static_assert(1000000000000000000u > (uint64_t(1) << (53 + 3)), "(b) above");
// ParseFloat<16> will read the first 15 significant digits of the mantissa.
//
// Because a base-16-to-base-2 conversion can be done exactly, we do not need
// to maximize the number of scanned hex digits to improve our conversion. What
// is required is to scan two more bits than the mantissa can represent, so that
// we always round correctly.
//
// (One extra bit does not suffice to perform correct rounding, since a number
// exactly halfway between two representable floats has unique rounding rules,
// so we need to differentiate between a "halfway between" number and a "closer
// to the larger value" number.)
constexpr int kHexadecimalMantissaDigitsMax = 15;
// The minimum number of significant bits that will be read from
// kHexadecimalMantissaDigitsMax hex digits. We must subtract by three, since
// the most significant digit can be a "1", which only contributes a single
// significant bit.
constexpr int kGuaranteedHexadecimalMantissaBitPrecision =
4 * kHexadecimalMantissaDigitsMax - 3;
static_assert(kGuaranteedHexadecimalMantissaBitPrecision >
std::numeric_limits<double>::digits + 2,
"kHexadecimalMantissaDigitsMax too small");
// We also impose a limit on the number of significant digits we will read from
// an exponent, to avoid having to deal with integer overflow. We use 9 for
// this purpose.
//
// If we read a 9 digit exponent, the end result of the conversion will
// necessarily be infinity or zero, depending on the sign of the exponent.
// Therefore we can just drop extra digits on the floor without any extra
// logic.
constexpr int kDecimalExponentDigitsMax = 9;
static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,
"int type too small");
// To avoid incredibly large inputs causing integer overflow for our exponent,
// we impose an arbitrary but very large limit on the number of significant
// digits we will accept. The implementation refuses to match a std::string with
// more consecutive significant mantissa digits than this.
constexpr int kDecimalDigitLimit = 50000000;
// Corresponding limit for hexadecimal digit inputs. This is one fourth the
// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires
// a binary exponent adjustment of 4.
constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;
// The largest exponent we can read is 999999999 (per
// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get
// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these
// comfortably fits in an integer.
//
// We count kDecimalDigitLimit twice because there are independent limits for
// numbers before and after the decimal point. (In the case where there are no
// significant digits before the decimal point, there are independent limits for
// post-decimal-point leading zeroes and for significant digits.)
static_assert(999999999 + 2 * kDecimalDigitLimit <
std::numeric_limits<int>::max(),
"int type too small");
static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <
std::numeric_limits<int>::max(),
"int type too small");
// Returns true if the provided bitfield allows parsing an exponent value
// (e.g., "1.5e100").
bool AllowExponent(chars_format flags) {
bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
bool scientific =
(flags & chars_format::scientific) == chars_format::scientific;
return scientific || !fixed;
}
// Returns true if the provided bitfield requires an exponent value be present.
bool RequireExponent(chars_format flags) {
bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
bool scientific =
(flags & chars_format::scientific) == chars_format::scientific;
return scientific && !fixed;
}
const int8_t kAsciiToInt[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1};
// Returns true if `ch` is a digit in the given base
template <int base>
bool IsDigit(char ch);
// Converts a valid `ch` to its digit value in the given base.
template <int base>
unsigned ToDigit(char ch);
// Returns true if `ch` is the exponent delimiter for the given base.
template <int base>
bool IsExponentCharacter(char ch);
// Returns the maximum number of significant digits we will read for a float
// in the given base.
template <int base>
constexpr int MantissaDigitsMax();
// Returns the largest consecutive run of digits we will accept when parsing a
// number in the given base.
template <int base>
constexpr int DigitLimit();
// Returns the amount the exponent must be adjusted by for each dropped digit.
// (For decimal this is 1, since the digits are in base 10 and the exponent base
// is also 10, but for hexadecimal this is 4, since the digits are base 16 but
// the exponent base is 2.)
template <int base>
constexpr int DigitMagnitude();
template <>
bool IsDigit<10>(char ch) {
return ch >= '0' && ch <= '9';
}
template <>
bool IsDigit<16>(char ch) {
return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;
}
template <>
unsigned ToDigit<10>(char ch) {
return ch - '0';
}
template <>
unsigned ToDigit<16>(char ch) {
return kAsciiToInt[static_cast<unsigned char>(ch)];
}
template <>
bool IsExponentCharacter<10>(char ch) {
return ch == 'e' || ch == 'E';
}
template <>
bool IsExponentCharacter<16>(char ch) {
return ch == 'p' || ch == 'P';
}
template <>
constexpr int MantissaDigitsMax<10>() {
return kDecimalMantissaDigitsMax;
}
template <>
constexpr int MantissaDigitsMax<16>() {
return kHexadecimalMantissaDigitsMax;
}
template <>
constexpr int DigitLimit<10>() {
return kDecimalDigitLimit;
}
template <>
constexpr int DigitLimit<16>() {
return kHexadecimalDigitLimit;
}
template <>
constexpr int DigitMagnitude<10>() {
return 1;
}
template <>
constexpr int DigitMagnitude<16>() {
return 4;
}
// Reads decimal digits from [begin, end) into *out. Returns the number of
// digits consumed.
//
// After max_digits has been read, keeps consuming characters, but no longer
// adjusts *out. If a nonzero digit is dropped this way, *dropped_nonzero_digit
// is set; otherwise, it is left unmodified.
//
// If no digits are matched, returns 0 and leaves *out unchanged.
//
// ConsumeDigits does not protect against overflow on *out; max_digits must
// be chosen with respect to type T to avoid the possibility of overflow.
template <int base, typename T>
std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
T* out, bool* dropped_nonzero_digit) {
if (base == 10) {
assert(max_digits <= std::numeric_limits<T>::digits10);
} else if (base == 16) {
assert(max_digits * 4 <= std::numeric_limits<T>::digits);
}
const char* const original_begin = begin;
T accumulator = *out;
const char* significant_digits_end =
(end - begin > max_digits) ? begin + max_digits : end;
while (begin < significant_digits_end && IsDigit<base>(*begin)) {
// Do not guard against *out overflow; max_digits was chosen to avoid this.
// Do assert against it, to detect problems in debug builds.
auto digit = static_cast<T>(ToDigit<base>(*begin));
assert(accumulator * base >= accumulator);
accumulator *= base;
assert(accumulator + digit >= accumulator);
accumulator += digit;
++begin;
}
bool dropped_nonzero = false;
while (begin < end && IsDigit<base>(*begin)) {
dropped_nonzero = dropped_nonzero || (*begin != '0');
++begin;
}
if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
*dropped_nonzero_digit = true;
}
*out = accumulator;
return begin - original_begin;
}
// Returns true if `v` is one of the chars allowed inside parentheses following
// a NaN.
bool IsNanChar(char v) {
return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||
(v >= 'A' && v <= 'Z');
}
// Checks the range [begin, end) for a strtod()-formatted infinity or NaN. If
// one is found, sets `out` appropriately and returns true.
bool ParseInfinityOrNan(const char* begin, const char* end,
strings_internal::ParsedFloat* out) {
if (end - begin < 3) {
return false;
}
switch (*begin) {
case 'i':
case 'I': {
// An infinity std::string consists of the characters "inf" or "infinity",
// case insensitive.
if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
return false;
}
out->type = strings_internal::FloatType::kInfinity;
if (end - begin >= 8 &&
strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) {
out->end = begin + 8;
} else {
out->end = begin + 3;
}
return true;
}
case 'n':
case 'N': {
// A NaN consists of the characters "nan", case insensitive, optionally
// followed by a parenthesized sequence of zero or more alphanumeric
// characters and/or underscores.
if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) {
return false;
}
out->type = strings_internal::FloatType::kNan;
out->end = begin + 3;
// NaN is allowed to be followed by a parenthesized std::string, consisting of
// only the characters [a-zA-Z0-9_]. Match that if it's present.
begin += 3;
if (begin < end && *begin == '(') {
const char* nan_begin = begin + 1;
while (nan_begin < end && IsNanChar(*nan_begin)) {
++nan_begin;
}
if (nan_begin < end && *nan_begin == ')') {
// We found an extra NaN specifier range
out->subrange_begin = begin + 1;
out->subrange_end = nan_begin;
out->end = nan_begin + 1;
}
}
return true;
}
default:
return false;
}
}
} // namespace
namespace strings_internal {
template <int base>
strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
chars_format format_flags) {
strings_internal::ParsedFloat result;
// Exit early if we're given an empty range.
if (begin == end) return result;
// Handle the infinity and NaN cases.
if (ParseInfinityOrNan(begin, end, &result)) {
return result;
}
const char* const mantissa_begin = begin;
while (begin < end && *begin == '0') {
++begin; // skip leading zeros
}
uint64_t mantissa = 0;
int exponent_adjustment = 0;
bool mantissa_is_inexact = false;
std::size_t pre_decimal_digits = ConsumeDigits<base>(
begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
begin += pre_decimal_digits;
int digits_left;
if (pre_decimal_digits >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
} else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
// We dropped some non-fraction digits on the floor. Adjust our exponent
// to compensate.
exponent_adjustment =
static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
digits_left = 0;
} else {
digits_left =
static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
}
if (begin < end && *begin == '.') {
++begin;
if (mantissa == 0) {
// If we haven't seen any nonzero digits yet, keep skipping zeros. We
// have to adjust the exponent to reflect the changed place value.
const char* begin_zeros = begin;
while (begin < end && *begin == '0') {
++begin;
}
std::size_t zeros_skipped = begin - begin_zeros;
if (zeros_skipped >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
}
exponent_adjustment -= static_cast<int>(zeros_skipped);
}
std::size_t post_decimal_digits = ConsumeDigits<base>(
begin, end, digits_left, &mantissa, &mantissa_is_inexact);
begin += post_decimal_digits;
// Since `mantissa` is an integer, each significant digit we read after
// the decimal point requires an adjustment to the exponent. "1.23e0" will
// be stored as `mantissa` == 123 and `exponent` == -2 (that is,
// "123e-2").
if (post_decimal_digits >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
} else if (post_decimal_digits > digits_left) {
exponent_adjustment -= digits_left;
} else {
exponent_adjustment -= post_decimal_digits;
}
}
// If we've found no mantissa whatsoever, this isn't a number.
if (mantissa_begin == begin) {
return result;
}
// A bare "." doesn't count as a mantissa either.
if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
return result;
}
if (mantissa_is_inexact) {
// We dropped significant digits on the floor. Handle this appropriately.
if (base == 10) {
// If we truncated significant decimal digits, store the full range of the
// mantissa for future big integer math for exact rounding.
result.subrange_begin = mantissa_begin;
result.subrange_end = begin;
} else if (base == 16) {
// If we truncated hex digits, reflect this fact by setting the low
// ("sticky") bit. This allows for correct rounding in all cases.
mantissa |= 1;
}
}
result.mantissa = mantissa;
const char* const exponent_begin = begin;
result.literal_exponent = 0;
bool found_exponent = false;
if (AllowExponent(format_flags) && begin < end &&
IsExponentCharacter<base>(*begin)) {
bool negative_exponent = false;
++begin;
if (begin < end && *begin == '-') {
negative_exponent = true;
++begin;
} else if (begin < end && *begin == '+') {
++begin;
}
const char* const exponent_digits_begin = begin;
// Exponent is always expressed in decimal, even for hexadecimal floats.
begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
&result.literal_exponent, nullptr);
if (begin == exponent_digits_begin) {
// there were no digits where we expected an exponent. We failed to read
// an exponent and should not consume the 'e' after all. Rewind 'begin'.
found_exponent = false;
begin = exponent_begin;
} else {
found_exponent = true;
if (negative_exponent) {
result.literal_exponent = -result.literal_exponent;
}
}
}
if (!found_exponent && RequireExponent(format_flags)) {
// Provided flags required an exponent, but none was found. This results
// in a failure to scan.
return result;
}
// Success!
result.type = strings_internal::FloatType::kNumber;
if (result.mantissa > 0) {
result.exponent = result.literal_exponent +
(DigitMagnitude<base>() * exponent_adjustment);
} else {
result.exponent = 0;
}
result.end = begin;
return result;
}
template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
chars_format format_flags);
template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
chars_format format_flags);
} // namespace strings_internal
} // namespace absl

View File

@ -1,96 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
#define ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
#include <cstdint>
#include "absl/strings/charconv.h"
namespace absl {
namespace strings_internal {
// Enum indicating whether a parsed float is a number or special value.
enum class FloatType { kNumber, kInfinity, kNan };
// The decomposed parts of a parsed `float` or `double`.
struct ParsedFloat {
// Representation of the parsed mantissa, with the decimal point adjusted to
// make it an integer.
//
// During decimal scanning, this contains 19 significant digits worth of
// mantissa value. If digits beyond this point are found, they
// are truncated, and if any of these dropped digits are nonzero, then
// `mantissa` is inexact, and the full mantissa is stored in [subrange_begin,
// subrange_end).
//
// During hexadecimal scanning, this contains 15 significant hex digits worth
// of mantissa value. Digits beyond this point are sticky -- they are
// truncated, but if any dropped digits are nonzero, the low bit of mantissa
// will be set. (This allows for precise rounding, and avoids the need
// to store the full mantissa in [subrange_begin, subrange_end).)
uint64_t mantissa = 0;
// Floating point expontent. This reflects any decimal point adjustments and
// any truncated digits from the mantissa. The absolute value of the parsed
// number is represented by mantissa * (base ** exponent), where base==10 for
// decimal floats, and base==2 for hexadecimal floats.
int exponent = 0;
// The literal exponent value scanned from the input, or 0 if none was
// present. This does not reflect any adjustments applied to mantissa.
int literal_exponent = 0;
// The type of number scanned.
FloatType type = FloatType::kNumber;
// When non-null, [subrange_begin, subrange_end) marks a range of characters
// that require further processing. The meaning is dependent on float type.
// If type == kNumber and this is set, this is a "wide input": the input
// mantissa contained more than 19 digits. The range contains the full
// mantissa. It plus `literal_exponent` need to be examined to find the best
// floating point match.
// If type == kNan and this is set, the range marks the contents of a
// matched parenthesized character region after the NaN.
const char* subrange_begin = nullptr;
const char* subrange_end = nullptr;
// One-past-the-end of the successfully parsed region, or nullptr if no
// matching pattern was found.
const char* end = nullptr;
};
// Read the floating point number in the provided range, and populate
// ParsedFloat accordingly.
//
// format_flags is a bitmask value specifying what patterns this API will match.
// `scientific` and `fixed` are honored per std::from_chars rules
// ([utility.from.chars], C++17): if exactly one of these bits is set, then an
// exponent is required, or dislallowed, respectively.
//
// Template parameter `base` must be either 10 or 16. For base 16, a "0x" is
// *not* consumed. The `hex` bit from format_flags is ignored by ParseFloat.
template <int base>
ParsedFloat ParseFloat(const char* begin, const char* end,
absl::chars_format format_flags);
extern template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
absl::chars_format format_flags);
extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
absl::chars_format format_flags);
} // namespace strings_internal
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_

View File

@ -1,357 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/internal/charconv_parse.h"
#include <string>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/str_cat.h"
using absl::chars_format;
using absl::strings_internal::FloatType;
using absl::strings_internal::ParsedFloat;
using absl::strings_internal::ParseFloat;
namespace {
// Check that a given std::string input is parsed to the expected mantissa and
// exponent.
//
// Input std::string `s` must contain a '$' character. It marks the end of the
// characters that should be consumed by the match. It is stripped from the
// input to ParseFloat.
//
// If input std::string `s` contains '[' and ']' characters, these mark the region
// of characters that should be marked as the "subrange". For NaNs, this is
// the location of the extended NaN std::string. For numbers, this is the location
// of the full, over-large mantissa.
template <int base>
void ExpectParsedFloat(std::string s, absl::chars_format format_flags,
FloatType expected_type, uint64_t expected_mantissa,
int expected_exponent,
int expected_literal_exponent = -999) {
SCOPED_TRACE(s);
int begin_subrange = -1;
int end_subrange = -1;
// If s contains '[' and ']', then strip these characters and set the subrange
// indices appropriately.
std::string::size_type open_bracket_pos = s.find('[');
if (open_bracket_pos != std::string::npos) {
begin_subrange = static_cast<int>(open_bracket_pos);
s.replace(open_bracket_pos, 1, "");
std::string::size_type close_bracket_pos = s.find(']');
ABSL_RAW_CHECK(close_bracket_pos != absl::string_view::npos,
"Test input contains [ without matching ]");
end_subrange = static_cast<int>(close_bracket_pos);
s.replace(close_bracket_pos, 1, "");
}
const std::string::size_type expected_characters_matched = s.find('$');
ABSL_RAW_CHECK(expected_characters_matched != std::string::npos,
"Input std::string must contain $");
s.replace(expected_characters_matched, 1, "");
ParsedFloat parsed =
ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);
EXPECT_NE(parsed.end, nullptr);
if (parsed.end == nullptr) {
return; // The following tests are not useful if we fully failed to parse
}
EXPECT_EQ(parsed.type, expected_type);
if (begin_subrange == -1) {
EXPECT_EQ(parsed.subrange_begin, nullptr);
EXPECT_EQ(parsed.subrange_end, nullptr);
} else {
EXPECT_EQ(parsed.subrange_begin, s.data() + begin_subrange);
EXPECT_EQ(parsed.subrange_end, s.data() + end_subrange);
}
if (parsed.type == FloatType::kNumber) {
EXPECT_EQ(parsed.mantissa, expected_mantissa);
EXPECT_EQ(parsed.exponent, expected_exponent);
if (expected_literal_exponent != -999) {
EXPECT_EQ(parsed.literal_exponent, expected_literal_exponent);
}
}
auto characters_matched = static_cast<int>(parsed.end - s.data());
EXPECT_EQ(characters_matched, expected_characters_matched);
}
// Check that a given std::string input is parsed to the expected mantissa and
// exponent.
//
// Input std::string `s` must contain a '$' character. It marks the end of the
// characters that were consumed by the match.
template <int base>
void ExpectNumber(std::string s, absl::chars_format format_flags,
uint64_t expected_mantissa, int expected_exponent,
int expected_literal_exponent = -999) {
ExpectParsedFloat<base>(std::move(s), format_flags, FloatType::kNumber,
expected_mantissa, expected_exponent,
expected_literal_exponent);
}
// Check that a given std::string input is parsed to the given special value.
//
// This tests against both number bases, since infinities and NaNs have
// identical representations in both modes.
void ExpectSpecial(const std::string& s, absl::chars_format format_flags,
FloatType type) {
ExpectParsedFloat<10>(s, format_flags, type, 0, 0);
ExpectParsedFloat<16>(s, format_flags, type, 0, 0);
}
// Check that a given input std::string is not matched by Float.
template <int base>
void ExpectFailedParse(absl::string_view s, absl::chars_format format_flags) {
ParsedFloat parsed =
ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);
EXPECT_EQ(parsed.end, nullptr);
}
TEST(ParseFloat, SimpleValue) {
// Test that various forms of floating point numbers all parse correctly.
ExpectNumber<10>("1.23456789e5$", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e+5$", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789E5$", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e05$", chars_format::general, 123456789, -3);
ExpectNumber<10>("123.456789e3$", chars_format::general, 123456789, -3);
ExpectNumber<10>("0.000123456789e9$", chars_format::general, 123456789, -3);
ExpectNumber<10>("123456.789$", chars_format::general, 123456789, -3);
ExpectNumber<10>("123456789e-3$", chars_format::general, 123456789, -3);
ExpectNumber<16>("1.234abcdefp28$", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1.234abcdefp+28$", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1.234ABCDEFp28$", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1.234AbCdEfP0028$", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("123.4abcdefp20$", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("0.0001234abcdefp44$", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("1234abcd.ef$", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1234abcdefp-8$", chars_format::general, 0x1234abcdef, -8);
// ExpectNumber does not attempt to drop trailing zeroes.
ExpectNumber<10>("0001.2345678900e005$", chars_format::general, 12345678900,
-5);
ExpectNumber<16>("0001.234abcdef000p28$", chars_format::general,
0x1234abcdef000, -20);
// Ensure non-matching characters after a number are ignored, even when they
// look like potentially matching characters.
ExpectNumber<10>("1.23456789e5$ ", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e5$e5e5", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e5$.25", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e5$-", chars_format::general, 123456789, -3);
ExpectNumber<10>("1.23456789e5$PUPPERS!!!", chars_format::general, 123456789,
-3);
ExpectNumber<10>("123456.789$efghij", chars_format::general, 123456789, -3);
ExpectNumber<10>("123456.789$e", chars_format::general, 123456789, -3);
ExpectNumber<10>("123456.789$p5", chars_format::general, 123456789, -3);
ExpectNumber<10>("123456.789$.10", chars_format::general, 123456789, -3);
ExpectNumber<16>("1.234abcdefp28$ ", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("1.234abcdefp28$p28", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("1.234abcdefp28$.125", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("1.234abcdefp28$-", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1.234abcdefp28$KITTEHS!!!", chars_format::general,
0x1234abcdef, -8);
ExpectNumber<16>("1234abcd.ef$ghijk", chars_format::general, 0x1234abcdef,
-8);
ExpectNumber<16>("1234abcd.ef$p", chars_format::general, 0x1234abcdef, -8);
ExpectNumber<16>("1234abcd.ef$.10", chars_format::general, 0x1234abcdef, -8);
// Ensure we can read a full resolution mantissa without overflow.
ExpectNumber<10>("9999999999999999999$", chars_format::general,
9999999999999999999u, 0);
ExpectNumber<16>("fffffffffffffff$", chars_format::general,
0xfffffffffffffffu, 0);
// Check that zero is consistently read.
ExpectNumber<10>("0$", chars_format::general, 0, 0);
ExpectNumber<16>("0$", chars_format::general, 0, 0);
ExpectNumber<10>("000000000000000000000000000000000000000$",
chars_format::general, 0, 0);
ExpectNumber<16>("000000000000000000000000000000000000000$",
chars_format::general, 0, 0);
ExpectNumber<10>("0000000000000000000000.000000000000000000$",
chars_format::general, 0, 0);
ExpectNumber<16>("0000000000000000000000.000000000000000000$",
chars_format::general, 0, 0);
ExpectNumber<10>("0.00000000000000000000000000000000e123456$",
chars_format::general, 0, 0);
ExpectNumber<16>("0.00000000000000000000000000000000p123456$",
chars_format::general, 0, 0);
}
TEST(ParseFloat, LargeDecimalMantissa) {
// After 19 significant decimal digits in the mantissa, ParsedFloat will
// truncate additional digits. We need to test that:
// 1) the truncation to 19 digits happens
// 2) the returned exponent reflects the dropped significant digits
// 3) a correct literal_exponent is set
//
// If and only if a significant digit is found after 19 digits, then the
// entirety of the mantissa in case the exact value is needed to make a
// rounding decision. The [ and ] characters below denote where such a
// subregion was marked by by ParseFloat. They are not part of the input.
// Mark a capture group only if a dropped digit is significant (nonzero).
ExpectNumber<10>("100000000000000000000000000$", chars_format::general,
1000000000000000000,
/* adjusted exponent */ 8);
ExpectNumber<10>("123456789123456789100000000$", chars_format::general,
1234567891234567891,
/* adjusted exponent */ 8);
ExpectNumber<10>("[123456789123456789123456789]$", chars_format::general,
1234567891234567891,
/* adjusted exponent */ 8,
/* literal exponent */ 0);
ExpectNumber<10>("[123456789123456789100000009]$", chars_format::general,
1234567891234567891,
/* adjusted exponent */ 8,
/* literal exponent */ 0);
ExpectNumber<10>("[123456789123456789120000000]$", chars_format::general,
1234567891234567891,
/* adjusted exponent */ 8,
/* literal exponent */ 0);
// Leading zeroes should not count towards the 19 significant digit limit
ExpectNumber<10>("[00000000123456789123456789123456789]$",
chars_format::general, 1234567891234567891,
/* adjusted exponent */ 8,
/* literal exponent */ 0);
ExpectNumber<10>("00000000123456789123456789100000000$",
chars_format::general, 1234567891234567891,
/* adjusted exponent */ 8);
// Truncated digits after the decimal point should not cause a further
// exponent adjustment.
ExpectNumber<10>("1.234567891234567891e123$", chars_format::general,
1234567891234567891, 105);
ExpectNumber<10>("[1.23456789123456789123456789]e123$", chars_format::general,
1234567891234567891,
/* adjusted exponent */ 105,
/* literal exponent */ 123);
// Ensure we truncate, and not round. (The from_chars algorithm we use
// depends on our guess missing low, if it misses, so we need the rounding
// error to be downward.)
ExpectNumber<10>("[1999999999999999999999]$", chars_format::general,
1999999999999999999,
/* adjusted exponent */ 3,
/* literal exponent */ 0);
}
TEST(ParseFloat, LargeHexadecimalMantissa) {
// After 15 significant hex digits in the mantissa, ParsedFloat will treat
// additional digits as sticky, We need to test that:
// 1) The truncation to 15 digits happens
// 2) The returned exponent reflects the dropped significant digits
// 3) If a nonzero digit is dropped, the low bit of mantissa is set.
ExpectNumber<16>("123456789abcdef123456789abcdef$", chars_format::general,
0x123456789abcdef, 60);
// Leading zeroes should not count towards the 15 significant digit limit
ExpectNumber<16>("000000123456789abcdef123456789abcdef$",
chars_format::general, 0x123456789abcdef, 60);
// Truncated digits after the radix point should not cause a further
// exponent adjustment.
ExpectNumber<16>("1.23456789abcdefp100$", chars_format::general,
0x123456789abcdef, 44);
ExpectNumber<16>("1.23456789abcdef123456789abcdefp100$",
chars_format::general, 0x123456789abcdef, 44);
// test sticky digit behavior. The low bit should be set iff any dropped
// digit is nonzero.
ExpectNumber<16>("123456789abcdee123456789abcdee$", chars_format::general,
0x123456789abcdef, 60);
ExpectNumber<16>("123456789abcdee000000000000001$", chars_format::general,
0x123456789abcdef, 60);
ExpectNumber<16>("123456789abcdee000000000000000$", chars_format::general,
0x123456789abcdee, 60);
}
TEST(ParseFloat, ScientificVsFixed) {
// In fixed mode, an exponent is never matched (but the remainder of the
// number will be matched.)
ExpectNumber<10>("1.23456789$e5", chars_format::fixed, 123456789, -8);
ExpectNumber<10>("123456.789$", chars_format::fixed, 123456789, -3);
ExpectNumber<16>("1.234abcdef$p28", chars_format::fixed, 0x1234abcdef, -36);
ExpectNumber<16>("1234abcd.ef$", chars_format::fixed, 0x1234abcdef, -8);
// In scientific mode, numbers don't match *unless* they have an exponent.
ExpectNumber<10>("1.23456789e5$", chars_format::scientific, 123456789, -3);
ExpectFailedParse<10>("-123456.789$", chars_format::scientific);
ExpectNumber<16>("1.234abcdefp28$", chars_format::scientific, 0x1234abcdef,
-8);
ExpectFailedParse<16>("1234abcd.ef$", chars_format::scientific);
}
TEST(ParseFloat, Infinity) {
ExpectFailedParse<10>("in", chars_format::general);
ExpectFailedParse<16>("in", chars_format::general);
ExpectFailedParse<10>("inx", chars_format::general);
ExpectFailedParse<16>("inx", chars_format::general);
ExpectSpecial("inf$", chars_format::general, FloatType::kInfinity);
ExpectSpecial("Inf$", chars_format::general, FloatType::kInfinity);
ExpectSpecial("INF$", chars_format::general, FloatType::kInfinity);
ExpectSpecial("inf$inite", chars_format::general, FloatType::kInfinity);
ExpectSpecial("iNfInItY$", chars_format::general, FloatType::kInfinity);
ExpectSpecial("infinity$!!!", chars_format::general, FloatType::kInfinity);
}
TEST(ParseFloat, NaN) {
ExpectFailedParse<10>("na", chars_format::general);
ExpectFailedParse<16>("na", chars_format::general);
ExpectFailedParse<10>("nah", chars_format::general);
ExpectFailedParse<16>("nah", chars_format::general);
ExpectSpecial("nan$", chars_format::general, FloatType::kNan);
ExpectSpecial("NaN$", chars_format::general, FloatType::kNan);
ExpectSpecial("nAn$", chars_format::general, FloatType::kNan);
ExpectSpecial("NAN$", chars_format::general, FloatType::kNan);
ExpectSpecial("NaN$aNaNaNaNaBatman!", chars_format::general, FloatType::kNan);
// A parenthesized sequence of the characters [a-zA-Z0-9_] is allowed to
// appear after an NaN. Check that this is allowed, and that the correct
// characters are grouped.
//
// (The characters [ and ] in the pattern below delimit the expected matched
// subgroup; they are not part of the input passed to ParseFloat.)
ExpectSpecial("nan([0xabcdef])$", chars_format::general, FloatType::kNan);
ExpectSpecial("nan([0xabcdef])$...", chars_format::general, FloatType::kNan);
ExpectSpecial("nan([0xabcdef])$)...", chars_format::general, FloatType::kNan);
ExpectSpecial("nan([])$", chars_format::general, FloatType::kNan);
ExpectSpecial("nan([aAzZ09_])$", chars_format::general, FloatType::kNan);
// If the subgroup contains illegal characters, don't match it at all.
ExpectSpecial("nan$(bad-char)", chars_format::general, FloatType::kNan);
// Also cope with a missing close paren.
ExpectSpecial("nan$(0xabcdef", chars_format::general, FloatType::kNan);
}
} // namespace

View File

@ -32,7 +32,6 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/ascii.h"
#include "absl/strings/charconv.h"
#include "absl/strings/internal/bits.h"
#include "absl/strings/internal/memutil.h"
#include "absl/strings/str_cat.h"
@ -41,54 +40,51 @@ namespace absl {
bool SimpleAtof(absl::string_view str, float* value) {
*value = 0.0;
str = StripAsciiWhitespace(str);
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
if (str.empty()) return false;
char buf[32];
std::unique_ptr<char[]> bigbuf;
char* ptr = buf;
if (str.size() > sizeof(buf) - 1) {
bigbuf.reset(new char[str.size() + 1]);
ptr = bigbuf.get();
}
auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
if (result.ec == std::errc::invalid_argument) {
return false;
memcpy(ptr, str.data(), str.size());
ptr[str.size()] = '\0';
char* endptr;
*value = strtof(ptr, &endptr);
if (endptr != ptr) {
while (absl::ascii_isspace(*endptr)) ++endptr;
}
if (result.ptr != str.data() + str.size()) {
// not all non-whitespace characters consumed
return false;
}
// from_chars() with DR 3801's current wording will return max() on
// overflow. SimpleAtof returns infinity instead.
if (result.ec == std::errc::result_out_of_range) {
if (*value > 1.0) {
*value = std::numeric_limits<float>::infinity();
} else if (*value < -1.0) {
*value = -std::numeric_limits<float>::infinity();
}
}
return true;
// Ignore range errors from strtod/strtof.
// The values it returns on underflow and
// overflow are the right fallback in a
// robust setting.
return *ptr != '\0' && *endptr == '\0';
}
bool SimpleAtod(absl::string_view str, double* value) {
*value = 0.0;
str = StripAsciiWhitespace(str);
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
if (str.empty()) return false;
char buf[32];
std::unique_ptr<char[]> bigbuf;
char* ptr = buf;
if (str.size() > sizeof(buf) - 1) {
bigbuf.reset(new char[str.size() + 1]);
ptr = bigbuf.get();
}
auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
if (result.ec == std::errc::invalid_argument) {
return false;
memcpy(ptr, str.data(), str.size());
ptr[str.size()] = '\0';
char* endptr;
*value = strtod(ptr, &endptr);
if (endptr != ptr) {
while (absl::ascii_isspace(*endptr)) ++endptr;
}
if (result.ptr != str.data() + str.size()) {
// not all non-whitespace characters consumed
return false;
}
// from_chars() with DR 3801's current wording will return max() on
// overflow. SimpleAtod returns infinity instead.
if (result.ec == std::errc::result_out_of_range) {
if (*value > 1.0) {
*value = std::numeric_limits<double>::infinity();
} else if (*value < -1.0) {
*value = -std::numeric_limits<double>::infinity();
}
}
return true;
// Ignore range errors from strtod. The values it
// returns on underflow and overflow are the right
// fallback in a robust setting.
return *ptr != '\0' && *endptr == '\0';
}
namespace {

View File

@ -149,6 +149,12 @@ cc_test(
size = "large",
srcs = ["mutex_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
"no_test_loonix", # Too slow.
],
deps = [
":synchronization",
":thread_pool",

View File

@ -44,7 +44,6 @@ cc_library(
"//absl/base",
"//absl/base:core_headers",
"//absl/numeric:int128",
"//absl/strings",
"//absl/time/internal/cctz:civil_time",
"//absl/time/internal/cctz:time_zone",
],
@ -81,6 +80,9 @@ cc_test(
"time_zone_test.cc",
],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_loonix",
],
deps = [
":test_util",
":time",

View File

@ -37,7 +37,6 @@ source_set("time") {
"../base",
"../base:core_headers",
"../numeric:int128",
"../strings",
"../time/internal/cctz:civil_time",
"../time/internal/cctz:time_zone",
]

View File

@ -53,7 +53,7 @@ list(APPEND TIME_SRC
${TIME_PUBLIC_HEADERS}
${TIME_INTERNAL_HEADERS}
)
set(TIME_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::int128 absl::strings)
set(TIME_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::int128)
absl_library(
TARGET

View File

@ -896,7 +896,8 @@ bool ParseDuration(const std::string& dur_string, Duration* d) {
return true;
}
bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
// TODO(absl-team): Remove once dependencies are removed.
bool ParseFlag(const std::string& text, Duration* dst, std::string* /* err */) {
return ParseDuration(text, dst);
}

View File

@ -129,6 +129,7 @@ bool ParseTime(const std::string& format, const std::string& input, absl::TimeZo
return b;
}
// TODO(absl-team): Remove once dependencies are removed.
// Functions required to support absl::Time flags.
bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {
return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);

View File

@ -64,7 +64,6 @@
#include <utility>
#include "absl/base/port.h" // Needed for string vs std::string
#include "absl/strings/string_view.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
@ -492,6 +491,9 @@ inline std::ostream& operator<<(std::ostream& os, Duration d) {
// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
bool ParseDuration(const std::string& dur_string, Duration* d);
// Flag Support
// TODO(absl-team): Remove once dependencies are removed.
// ParseFlag()
//
bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
@ -991,6 +993,8 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
Time* time, std::string* err);
// TODO(absl-team): Remove once dependencies are removed.
// ParseFlag()
// UnparseFlag()
//

View File

@ -247,19 +247,6 @@ cc_test(
],
)
cc_test(
name = "variant_benchmark",
srcs = [
"variant_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
deps = [
":variant",
"//absl/utility",
"@com_github_google_benchmark//:benchmark_main",
],
)
cc_test(
name = "variant_exception_safety_test",
size = "small",

View File

@ -19,19 +19,15 @@
#ifndef ABSL_TYPES_variant_internal_H_
#define ABSL_TYPES_variant_internal_H_
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/base/internal/identity.h"
#include "absl/base/internal/inline_variable.h"
#include "absl/base/internal/invoke.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/meta/type_traits.h"
#include "absl/types/bad_variant_access.h"
@ -123,8 +119,6 @@ using GiveQualsToT = typename GiveQualsTo<T, U>::type;
template <std::size_t I>
using SizeT = std::integral_constant<std::size_t, I>;
using NPos = SizeT<variant_npos>;
template <class Variant, class T, class = void>
struct IndexOfConstructedType {};
@ -254,270 +248,19 @@ struct MakeVisitationMatrix<ReturnType, FunctionObject,
ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
struct UnreachableSwitchCase {
template <class Op>
[[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run(
Op&& /*ignored*/) {
#if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \
(defined(__GNUC__) && !defined(__clang__))
__builtin_unreachable();
#elif defined(_MSC_VER)
__assume(false);
#else
// Try to use assert of false being identified as an unreachable intrinsic.
// NOTE: We use assert directly to increase chances of exploiting an assume
// intrinsic.
assert(false); // NOLINT
// Hack to silence potential no return warning -- cause an infinite loop.
return Run(absl::forward<Op>(op));
#endif // Checks for __builtin_unreachable
}
};
template <class Op, std::size_t I>
struct ReachableSwitchCase {
static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
return absl::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>());
}
};
// The number 33 is just a guess at a reasonable maximum to our switch. It is
// not based on any analysis. The reason it is a power of 2 plus 1 instead of a
// power of 2 is because the number was picked to correspond to a power of 2
// amount of "normal" alternatives, plus one for the possibility of the user
// providing "monostate" in addition to the more natural alternatives.
ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
// Note: The default-definition is for unreachable cases.
template <bool IsReachable>
struct PickCaseImpl {
template <class Op, std::size_t I>
using Apply = UnreachableSwitchCase;
};
template <>
struct PickCaseImpl</*IsReachable =*/true> {
template <class Op, std::size_t I>
using Apply = ReachableSwitchCase<Op, I>;
};
// Note: This form of dance with template aliases is to make sure that we
// instantiate a number of templates proportional to the number of variant
// alternatives rather than a number of templates proportional to our
// maximum unrolled amount of visitation cases (aliases are effectively
// "free" whereas other template instantiations are costly).
template <class Op, std::size_t I, std::size_t EndIndex>
using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
template <std::size_t... EndIndices, class Op, class... SizeT>
VisitIndicesResultT<Op, SizeT...> visit_indices(Op&& op, SizeT... indices) {
return AccessSimpleArray(
MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
index_sequence<(EndIndices + 1)...>>::Run(),
(indices + 1)...)(absl::forward<Op>(op));
}
template <class ReturnType>
[[noreturn]] ReturnType TypedThrowBadVariantAccess() {
absl::variant_internal::ThrowBadVariantAccess();
}
// Given N variant sizes, determine the number of cases there would need to be
// in a single switch-statement that would cover every possibility in the
// corresponding N-ary visit operation.
template <std::size_t... NumAlternatives>
struct NumCasesOfSwitch;
template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
static constexpr std::size_t value =
(HeadNumAlternatives + 1) *
NumCasesOfSwitch<TailNumAlternatives...>::value;
};
template <>
struct NumCasesOfSwitch<> {
static constexpr std::size_t value = 1;
};
// A switch statement optimizes better than the table of function pointers.
template <std::size_t EndIndex>
struct VisitIndicesSwitch {
static_assert(EndIndex <= MaxUnrolledVisitCases,
"Maximum unrolled switch size exceeded.");
template <class Op>
static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
switch (i) {
case 0:
return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op));
case 1:
return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op));
case 2:
return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op));
case 3:
return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op));
case 4:
return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op));
case 5:
return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op));
case 6:
return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op));
case 7:
return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op));
case 8:
return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op));
case 9:
return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op));
case 10:
return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op));
case 11:
return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op));
case 12:
return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op));
case 13:
return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op));
case 14:
return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op));
case 15:
return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op));
case 16:
return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op));
case 17:
return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op));
case 18:
return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op));
case 19:
return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op));
case 20:
return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op));
case 21:
return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op));
case 22:
return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op));
case 23:
return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op));
case 24:
return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op));
case 25:
return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op));
case 26:
return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op));
case 27:
return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op));
case 28:
return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op));
case 29:
return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op));
case 30:
return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op));
case 31:
return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op));
case 32:
return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op));
default:
ABSL_ASSERT(i == variant_npos);
return absl::base_internal::Invoke(absl::forward<Op>(op), NPos());
}
}
};
template <std::size_t... EndIndices>
struct VisitIndicesFallback {
template <class Op, class... SizeT>
static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
return AccessSimpleArray(
MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
index_sequence<(EndIndices + 1)...>>::Run(),
(indices + 1)...)(absl::forward<Op>(op));
}
};
// Take an N-dimensional series of indices and convert them into a single index
// without loss of information. The purpose of this is to be able to convert an
// N-ary visit operation into a single switch statement.
template <std::size_t...>
struct FlattenIndices;
template <std::size_t HeadSize, std::size_t... TailSize>
struct FlattenIndices<HeadSize, TailSize...> {
template<class... SizeType>
static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
}
};
template <>
struct FlattenIndices<> {
static constexpr std::size_t Run() { return 0; }
};
// Take a single "flattened" index (flattened by FlattenIndices) and determine
// the value of the index of one of the logically represented dimensions.
template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
std::size_t... TailSize>
struct UnflattenIndex {
static constexpr std::size_t value =
UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
};
template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
static constexpr std::size_t value = (I % HeadSize);
};
// The backend for converting an N-ary visit operation into a unary visit.
template <class IndexSequence, std::size_t... EndIndices>
struct VisitIndicesVariadicImpl;
template <std::size_t... N, std::size_t... EndIndices>
struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
// A type that can take an N-ary function object and converts it to a unary
// function object that takes a single, flattened index, and "unflattens" it
// into its individual dimensions when forwarding to the wrapped object.
template <class Op>
struct FlattenedOp {
template <std::size_t I>
VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
SizeT<I> /*index*/) && {
return base_internal::Invoke(
absl::forward<Op>(op),
SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
std::size_t{1}>()...);
}
Op&& op;
};
template <class Op, class... SizeType>
static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
Op&& op, SizeType... i) {
return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
FlattenedOp<Op>{absl::forward<Op>(op)},
FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
(i + std::size_t{1})...));
}
};
template <std::size_t... EndIndices>
struct VisitIndicesVariadic
: VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>,
EndIndices...> {};
// This implementation will flatten N-ary visit operations into a single switch
// statement when the number of cases would be less than our maximum specified
// switch-statement size.
// TODO(calabrese)
// Based on benchmarks, determine whether the function table approach actually
// does optimize better than a chain of switch statements and possibly update
// the implementation accordingly. Also consider increasing the maximum switch
// size.
template <std::size_t... EndIndices>
struct VisitIndices
: absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
MaxUnrolledVisitCases),
VisitIndicesVariadic<EndIndices...>,
VisitIndicesFallback<EndIndices...>> {};
template <std::size_t EndIndex>
struct VisitIndices<EndIndex>
: absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
VisitIndicesSwitch<EndIndex>,
VisitIndicesFallback<EndIndex>> {};
// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
// below is returning the address of a temporary or local object.
#ifdef _MSC_VER
@ -527,10 +270,8 @@ struct VisitIndices<EndIndex>
// TODO(calabrese) std::launder
// TODO(calabrese) constexpr
// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
template <class Self, std::size_t I>
inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
return reinterpret_cast<VariantAccessResult<I, Self>>(self);
}
@ -572,7 +313,7 @@ struct VariantCoreAccess {
template <class Variant>
static void InitFrom(Variant& self, Variant&& other) { // NOLINT
VisitIndices<absl::variant_size<Variant>::value>::Run(
variant_internal::visit_indices<absl::variant_size<Variant>::value>(
InitFromVisitor<Variant, Variant&&>{&self,
std::forward<Variant>(other)},
other.index());
@ -1308,7 +1049,9 @@ class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
VariantStateBaseDestructorNontrivial* self;
};
void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
void destroy() {
variant_internal::visit_indices<sizeof...(T)>(Destroyer{this}, index_);
}
~VariantStateBaseDestructorNontrivial() { destroy(); }
@ -1344,7 +1087,8 @@ class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
: Base(NoopConstructorTag()) {
VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
variant_internal::visit_indices<sizeof...(T)>(Construct{this, &other},
other.index_);
index_ = other.index_;
}
@ -1387,7 +1131,8 @@ class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
: Base(NoopConstructorTag()) {
VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
variant_internal::visit_indices<sizeof...(T)>(Construct{this, &other},
other.index_);
index_ = other.index_;
}
@ -1421,7 +1166,7 @@ class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
absl::conjunction<std::is_nothrow_move_constructible<T>...,
std::is_nothrow_move_assignable<T>...>::value) {
VisitIndices<sizeof...(T)>::Run(
variant_internal::visit_indices<sizeof...(T)>(
VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
return *this;
}
@ -1450,7 +1195,7 @@ class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
VariantCopyAssignBaseNontrivial& operator=(
const VariantCopyAssignBaseNontrivial& other) {
VisitIndices<sizeof...(T)>::Run(
variant_internal::visit_indices<sizeof...(T)>(
VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
return *this;
}
@ -1591,7 +1336,7 @@ struct Swap {
template <std::size_t Wi>
void operator()(SizeT<Wi> /*w_i*/) {
if (v->index() == Wi) {
VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
visit_indices<sizeof...(Types)>(SwapSameIndex<Types...>{v, w}, Wi);
} else {
generic_swap();
}
@ -1625,10 +1370,11 @@ struct VariantHashBase<Variant,
if (var.valueless_by_exception()) {
return 239799884;
}
size_t result = VisitIndices<variant_size<Variant>::value>::Run(
PerformVisitation<VariantHashVisitor, const Variant&>{
std::forward_as_tuple(var), VariantHashVisitor{}},
var.index());
size_t result =
variant_internal::visit_indices<variant_size<Variant>::value>(
PerformVisitation<VariantHashVisitor, const Variant&>{
std::forward_as_tuple(var), VariantHashVisitor{}},
var.index());
// Combine the index and the hash result in order to distinguish
// std::variant<int, int> holding the same value as different alternative.
return result ^ var.index();

View File

@ -48,7 +48,7 @@ using std::optional;
using std::make_optional;
using std::nullopt_t;
using std::nullopt;
} // namespace absl
}
#else // ABSL_HAVE_STD_OPTIONAL

View File

@ -416,12 +416,12 @@ constexpr absl::add_pointer_t<const T> get_if(
template <typename Visitor, typename... Variants>
variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
Variants&&... vars) {
return variant_internal::
VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run(
variant_internal::PerformVisitation<Visitor, Variants...>{
std::forward_as_tuple(absl::forward<Variants>(vars)...),
absl::forward<Visitor>(vis)},
vars.index()...);
return variant_internal::visit_indices<
variant_size<absl::decay_t<Variants>>::value...>(
variant_internal::PerformVisitation<Visitor, Variants...>{
std::forward_as_tuple(absl::forward<Variants>(vars)...),
absl::forward<Visitor>(vis)},
vars.index()...);
}
// monostate
@ -573,7 +573,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
variant& operator=(T&& t) noexcept(
std::is_nothrow_assignable<Tj&, T>::value&&
std::is_nothrow_constructible<Tj, T>::value) {
variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
variant_internal::visit_indices<sizeof...(Tn) + 1>(
variant_internal::VariantCoreAccess::MakeConversionAssignVisitor(
this, absl::forward<T>(t)),
index());
@ -682,7 +682,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
// true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
void swap(variant& rhs) noexcept(
absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
return variant_internal::visit_indices<sizeof...(Tn) + 1>(
variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
}
};
@ -722,7 +722,7 @@ template <typename... Types>
constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() == b.index()) &&
variant_internal::VisitIndices<sizeof...(Types)>::Run(
variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
}
@ -731,7 +731,7 @@ template <typename... Types>
constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() != b.index()) ||
variant_internal::VisitIndices<sizeof...(Types)>::Run(
variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
}
@ -741,7 +741,7 @@ constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() != b.index())
? (a.index() + 1) < (b.index() + 1)
: variant_internal::VisitIndices<sizeof...(Types)>::Run(
: variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
}
@ -751,7 +751,7 @@ constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() != b.index())
? (a.index() + 1) > (b.index() + 1)
: variant_internal::VisitIndices<sizeof...(Types)>::Run(
: variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::GreaterThanOp<Types...>{&a, &b},
a.index());
}
@ -762,7 +762,7 @@ constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() != b.index())
? (a.index() + 1) < (b.index() + 1)
: variant_internal::VisitIndices<sizeof...(Types)>::Run(
: variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
a.index());
}
@ -773,7 +773,7 @@ constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
operator>=(const variant<Types...>& a, const variant<Types...>& b) {
return (a.index() != b.index())
? (a.index() + 1) > (b.index() + 1)
: variant_internal::VisitIndices<sizeof...(Types)>::Run(
: variant_internal::visit_indices<sizeof...(Types)>(
variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
a.index());
}

View File

@ -1,220 +0,0 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Unit tests for the variant template. The 'is' and 'IsEmpty' methods
// of variant are not explicitly tested because they are used repeatedly
// in building other tests. All other public variant methods should have
// explicit tests.
#include "absl/types/variant.h"
#include <cstddef>
#include <cstdlib>
#include <string>
#include <tuple>
#include "benchmark/benchmark.h"
#include "absl/utility/utility.h"
namespace absl {
namespace {
template <std::size_t I>
struct VariantAlternative {
char member;
};
template <class Indices>
struct VariantOfAlternativesImpl;
template <std::size_t... Indices>
struct VariantOfAlternativesImpl<absl::index_sequence<Indices...>> {
using type = absl::variant<VariantAlternative<Indices>...>;
};
template <std::size_t NumAlternatives>
using VariantOfAlternatives = typename VariantOfAlternativesImpl<
absl::make_index_sequence<NumAlternatives>>::type;
struct Empty {};
template <class... T>
void Ignore(T...) noexcept {}
template <class T>
Empty DoNotOptimizeAndReturnEmpty(T&& arg) noexcept {
benchmark::DoNotOptimize(arg);
return {};
}
struct VisitorApplier {
struct Visitor {
template <class... T>
void operator()(T&&... args) const noexcept {
Ignore(DoNotOptimizeAndReturnEmpty(args)...);
}
};
template <class... Vars>
void operator()(const Vars&... vars) const noexcept {
absl::visit(Visitor(), vars...);
}
};
template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1>
struct MakeWithIndex {
using Variant = VariantOfAlternatives<NumIndices>;
static Variant Run(std::size_t index) {
return index == CurrIndex
? Variant(absl::in_place_index_t<CurrIndex>())
: MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index);
}
};
template <std::size_t NumIndices>
struct MakeWithIndex<NumIndices, 0> {
using Variant = VariantOfAlternatives<NumIndices>;
static Variant Run(std::size_t /*index*/) { return Variant(); }
};
template <std::size_t NumIndices, class Dimensions>
struct MakeVariantTuple;
template <class T, std::size_t /*I*/>
using always_t = T;
template <std::size_t NumIndices>
VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension,
std::size_t index) {
return dimension == 0
? MakeWithIndex<NumIndices>::Run(index % NumIndices)
: MakeVariant<NumIndices>(dimension - 1, index / NumIndices);
}
template <std::size_t NumIndices, std::size_t... Dimensions>
struct MakeVariantTuple<NumIndices, absl::index_sequence<Dimensions...>> {
using VariantTuple =
std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>;
static VariantTuple Run(int index) {
return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...);
}
};
constexpr std::size_t integral_pow(std::size_t base, std::size_t power) {
return power == 0 ? 1 : base * integral_pow(base, power - 1);
}
template <std::size_t End, std::size_t I = 0>
struct VisitTestBody {
template <class Vars, class State>
static bool Run(Vars& vars, State& state) {
if (state.KeepRunning()) {
absl::apply(VisitorApplier(), vars[I]);
return VisitTestBody<End, I + 1>::Run(vars, state);
}
return false;
}
};
template <std::size_t End>
struct VisitTestBody<End, End> {
template <class Vars, class State>
static bool Run(Vars& /*vars*/, State& /*state*/) {
return true;
}
};
// Visit operations where branch prediction is likely to give a boost.
template <std::size_t NumIndices, std::size_t NumDimensions = 1>
void BM_RedundantVisit(benchmark::State& state) {
auto vars =
MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>::
Run(static_cast<std::size_t>(state.range(0)));
for (auto _ : state) { // NOLINT
benchmark::DoNotOptimize(vars);
absl::apply(VisitorApplier(), vars);
}
}
// Visit operations where branch prediction is unlikely to give a boost.
template <std::size_t NumIndices, std::size_t NumDimensions = 1>
void BM_Visit(benchmark::State& state) {
constexpr std::size_t num_possibilities =
integral_pow(NumIndices, NumDimensions);
using VariantTupleMaker =
MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>;
using Tuple = typename VariantTupleMaker::VariantTuple;
Tuple vars[num_possibilities];
for (std::size_t i = 0; i < num_possibilities; ++i)
vars[i] = VariantTupleMaker::Run(i);
while (VisitTestBody<num_possibilities>::Run(vars, state)) {
}
}
// Visitation
// Each visit is on a different variant with a different active alternative)
// Unary visit
BENCHMARK_TEMPLATE(BM_Visit, 1);
BENCHMARK_TEMPLATE(BM_Visit, 2);
BENCHMARK_TEMPLATE(BM_Visit, 3);
BENCHMARK_TEMPLATE(BM_Visit, 4);
BENCHMARK_TEMPLATE(BM_Visit, 5);
BENCHMARK_TEMPLATE(BM_Visit, 6);
BENCHMARK_TEMPLATE(BM_Visit, 7);
BENCHMARK_TEMPLATE(BM_Visit, 8);
BENCHMARK_TEMPLATE(BM_Visit, 16);
BENCHMARK_TEMPLATE(BM_Visit, 32);
BENCHMARK_TEMPLATE(BM_Visit, 64);
// Binary visit
BENCHMARK_TEMPLATE(BM_Visit, 1, 2);
BENCHMARK_TEMPLATE(BM_Visit, 2, 2);
BENCHMARK_TEMPLATE(BM_Visit, 3, 2);
BENCHMARK_TEMPLATE(BM_Visit, 4, 2);
BENCHMARK_TEMPLATE(BM_Visit, 5, 2);
// Ternary visit
BENCHMARK_TEMPLATE(BM_Visit, 1, 3);
BENCHMARK_TEMPLATE(BM_Visit, 2, 3);
BENCHMARK_TEMPLATE(BM_Visit, 3, 3);
// Quaternary visit
BENCHMARK_TEMPLATE(BM_Visit, 1, 4);
BENCHMARK_TEMPLATE(BM_Visit, 2, 4);
// Redundant Visitation
// Each visit consistently has the same alternative active
// Unary visit
BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0);
BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1);
BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7);
// Binary visit
BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0);
BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2)
->DenseRange(0, integral_pow(2, 2) - 1);
BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2)
->DenseRange(0, integral_pow(4, 2) - 1);
} // namespace
} // namespace absl

View File

@ -21,6 +21,7 @@ chrome.bluetoothPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingEventType
*/
chrome.bluetoothPrivate.PairingEventType = {
REQUEST_PINCODE: 'requestPincode',
@ -35,6 +36,7 @@ chrome.bluetoothPrivate.PairingEventType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-ConnectResultType
*/
chrome.bluetoothPrivate.ConnectResultType = {
ALREADY_CONNECTED: 'alreadyConnected',
@ -51,6 +53,7 @@ chrome.bluetoothPrivate.ConnectResultType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingResponse
*/
chrome.bluetoothPrivate.PairingResponse = {
CONFIRM: 'confirm',
@ -60,6 +63,7 @@ chrome.bluetoothPrivate.PairingResponse = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-TransportType
*/
chrome.bluetoothPrivate.TransportType = {
LE: 'le',
@ -75,6 +79,7 @@ chrome.bluetoothPrivate.TransportType = {
* passkey: (number|undefined),
* enteredKey: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingEvent
*/
chrome.bluetoothPrivate.PairingEvent;
@ -84,6 +89,7 @@ chrome.bluetoothPrivate.PairingEvent;
* powered: (boolean|undefined),
* discoverable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-NewAdapterState
*/
chrome.bluetoothPrivate.NewAdapterState;
@ -94,6 +100,7 @@ chrome.bluetoothPrivate.NewAdapterState;
* pincode: (string|undefined),
* passkey: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-SetPairingResponseOptions
*/
chrome.bluetoothPrivate.SetPairingResponseOptions;
@ -104,6 +111,7 @@ chrome.bluetoothPrivate.SetPairingResponseOptions;
* rssi: (number|undefined),
* pathloss: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#type-DiscoveryFilter
*/
chrome.bluetoothPrivate.DiscoveryFilter;
@ -111,12 +119,14 @@ chrome.bluetoothPrivate.DiscoveryFilter;
* Changes the state of the Bluetooth adapter.
* @param {!chrome.bluetoothPrivate.NewAdapterState} adapterState
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setAdapterState
*/
chrome.bluetoothPrivate.setAdapterState = function(adapterState, callback) {};
/**
* @param {!chrome.bluetoothPrivate.SetPairingResponseOptions} options
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setPairingResponse
*/
chrome.bluetoothPrivate.setPairingResponse = function(options, callback) {};
@ -124,6 +134,7 @@ chrome.bluetoothPrivate.setPairingResponse = function(options, callback) {};
* Tears down all connections to the given device.
* @param {string} deviceAddress
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-disconnectAll
*/
chrome.bluetoothPrivate.disconnectAll = function(deviceAddress, callback) {};
@ -131,6 +142,7 @@ chrome.bluetoothPrivate.disconnectAll = function(deviceAddress, callback) {};
* Forgets the given device.
* @param {string} deviceAddress
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-forgetDevice
*/
chrome.bluetoothPrivate.forgetDevice = function(deviceAddress, callback) {};
@ -138,6 +150,7 @@ chrome.bluetoothPrivate.forgetDevice = function(deviceAddress, callback) {};
* Set or clear discovery filter.
* @param {!chrome.bluetoothPrivate.DiscoveryFilter} discoveryFilter
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setDiscoveryFilter
*/
chrome.bluetoothPrivate.setDiscoveryFilter = function(discoveryFilter, callback) {};
@ -147,6 +160,7 @@ chrome.bluetoothPrivate.setDiscoveryFilter = function(discoveryFilter, callback)
* succeed and invoke |callback| with ConnectResultType.
* @param {string} deviceAddress
* @param {function(!chrome.bluetoothPrivate.ConnectResultType):void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-connect
*/
chrome.bluetoothPrivate.connect = function(deviceAddress, callback) {};
@ -154,11 +168,13 @@ chrome.bluetoothPrivate.connect = function(deviceAddress, callback) {};
* Pairs the given device.
* @param {string} deviceAddress
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/bluetoothPrivate#method-pair
*/
chrome.bluetoothPrivate.pair = function(deviceAddress, callback) {};
/**
* Fired when a pairing event occurs.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/bluetoothPrivate#event-onPairing
*/
chrome.bluetoothPrivate.onPairing;

View File

@ -18,6 +18,7 @@ chrome.developerPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ItemType
*/
chrome.developerPrivate.ItemType = {
HOSTED_APP: 'hosted_app',
@ -35,6 +36,7 @@ chrome.developerPrivate.ItemType = {
* incognito: boolean,
* generatedBackgroundPage: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ItemInspectView
*/
chrome.developerPrivate.ItemInspectView;
@ -45,6 +47,7 @@ chrome.developerPrivate.ItemInspectView;
* render_view_id: (string|number),
* incognito: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-InspectOptions
*/
chrome.developerPrivate.InspectOptions;
@ -52,11 +55,13 @@ chrome.developerPrivate.InspectOptions;
* @typedef {{
* message: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-InstallWarning
*/
chrome.developerPrivate.InstallWarning;
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionType
*/
chrome.developerPrivate.ExtensionType = {
HOSTED_APP: 'HOSTED_APP',
@ -69,6 +74,7 @@ chrome.developerPrivate.ExtensionType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-Location
*/
chrome.developerPrivate.Location = {
FROM_STORE: 'FROM_STORE',
@ -79,6 +85,7 @@ chrome.developerPrivate.Location = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ViewType
*/
chrome.developerPrivate.ViewType = {
APP_WINDOW: 'APP_WINDOW',
@ -93,6 +100,7 @@ chrome.developerPrivate.ViewType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ErrorType
*/
chrome.developerPrivate.ErrorType = {
MANIFEST: 'MANIFEST',
@ -101,6 +109,7 @@ chrome.developerPrivate.ErrorType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ErrorLevel
*/
chrome.developerPrivate.ErrorLevel = {
LOG: 'LOG',
@ -110,6 +119,7 @@ chrome.developerPrivate.ErrorLevel = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionState
*/
chrome.developerPrivate.ExtensionState = {
ENABLED: 'ENABLED',
@ -120,6 +130,7 @@ chrome.developerPrivate.ExtensionState = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-CommandScope
*/
chrome.developerPrivate.CommandScope = {
GLOBAL: 'GLOBAL',
@ -131,6 +142,7 @@ chrome.developerPrivate.CommandScope = {
* isEnabled: boolean,
* isActive: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-AccessModifier
*/
chrome.developerPrivate.AccessModifier;
@ -141,6 +153,7 @@ chrome.developerPrivate.AccessModifier;
* url: string,
* functionName: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-StackFrame
*/
chrome.developerPrivate.StackFrame;
@ -155,6 +168,7 @@ chrome.developerPrivate.StackFrame;
* manifestKey: string,
* manifestSpecific: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ManifestError
*/
chrome.developerPrivate.ManifestError;
@ -174,6 +188,7 @@ chrome.developerPrivate.ManifestError;
* canInspect: boolean,
* stackTrace: !Array<!chrome.developerPrivate.StackFrame>
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-RuntimeError
*/
chrome.developerPrivate.RuntimeError;
@ -183,6 +198,7 @@ chrome.developerPrivate.RuntimeError;
* corruptInstall: boolean,
* updateRequired: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-DisableReasons
*/
chrome.developerPrivate.DisableReasons;
@ -191,6 +207,7 @@ chrome.developerPrivate.DisableReasons;
* openInTab: boolean,
* url: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-OptionsPage
*/
chrome.developerPrivate.OptionsPage;
@ -199,6 +216,7 @@ chrome.developerPrivate.OptionsPage;
* url: string,
* specified: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-HomePage
*/
chrome.developerPrivate.HomePage;
@ -211,11 +229,13 @@ chrome.developerPrivate.HomePage;
* isIframe: boolean,
* type: !chrome.developerPrivate.ViewType
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionView
*/
chrome.developerPrivate.ExtensionView;
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ControllerType
*/
chrome.developerPrivate.ControllerType = {
POLICY: 'POLICY',
@ -228,6 +248,7 @@ chrome.developerPrivate.ControllerType = {
* type: !chrome.developerPrivate.ControllerType,
* text: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ControlledInfo
*/
chrome.developerPrivate.ControlledInfo;
@ -240,6 +261,7 @@ chrome.developerPrivate.ControlledInfo;
* scope: !chrome.developerPrivate.CommandScope,
* isExtensionAction: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-Command
*/
chrome.developerPrivate.Command;
@ -248,6 +270,7 @@ chrome.developerPrivate.Command;
* id: string,
* name: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-DependentExtension
*/
chrome.developerPrivate.DependentExtension;
@ -256,6 +279,7 @@ chrome.developerPrivate.DependentExtension;
* message: string,
* submessages: !Array<string>
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-Permission
*/
chrome.developerPrivate.Permission;
@ -297,6 +321,7 @@ chrome.developerPrivate.Permission;
* views: !Array<!chrome.developerPrivate.ExtensionView>,
* webStoreUrl: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionInfo
*/
chrome.developerPrivate.ExtensionInfo;
@ -309,6 +334,7 @@ chrome.developerPrivate.ExtensionInfo;
* isIncognitoAvailable: boolean,
* isSupervised: boolean
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ProfileInfo
*/
chrome.developerPrivate.ProfileInfo;
@ -342,6 +368,7 @@ chrome.developerPrivate.ProfileInfo;
* offline_enabled: boolean,
* views: !Array<!chrome.developerPrivate.ItemInspectView>
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ItemInfo
*/
chrome.developerPrivate.ItemInfo;
@ -350,6 +377,7 @@ chrome.developerPrivate.ItemInfo;
* includeDisabled: (boolean|undefined),
* includeTerminated: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-GetExtensionsInfoOptions
*/
chrome.developerPrivate.GetExtensionsInfoOptions;
@ -361,6 +389,7 @@ chrome.developerPrivate.GetExtensionsInfoOptions;
* errorCollection: (boolean|undefined),
* runOnAllUrls: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionConfigurationUpdate
*/
chrome.developerPrivate.ExtensionConfigurationUpdate;
@ -368,6 +397,7 @@ chrome.developerPrivate.ExtensionConfigurationUpdate;
* @typedef {{
* inDeveloperMode: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ProfileConfigurationUpdate
*/
chrome.developerPrivate.ProfileConfigurationUpdate;
@ -378,6 +408,7 @@ chrome.developerPrivate.ProfileConfigurationUpdate;
* scope: (!chrome.developerPrivate.CommandScope|undefined),
* keybinding: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionCommandUpdate
*/
chrome.developerPrivate.ExtensionCommandUpdate;
@ -386,6 +417,7 @@ chrome.developerPrivate.ExtensionCommandUpdate;
* failQuietly: (boolean|undefined),
* populateErrorForUnpacked: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ReloadOptions
*/
chrome.developerPrivate.ReloadOptions;
@ -396,11 +428,13 @@ chrome.developerPrivate.ReloadOptions;
* retryGuid: (string|undefined),
* useDraggedPath: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-LoadUnpackedOptions
*/
chrome.developerPrivate.LoadUnpackedOptions;
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-PackStatus
*/
chrome.developerPrivate.PackStatus = {
SUCCESS: 'SUCCESS',
@ -410,6 +444,7 @@ chrome.developerPrivate.PackStatus = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-FileType
*/
chrome.developerPrivate.FileType = {
LOAD: 'LOAD',
@ -418,6 +453,7 @@ chrome.developerPrivate.FileType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-SelectType
*/
chrome.developerPrivate.SelectType = {
FILE: 'FILE',
@ -426,6 +462,7 @@ chrome.developerPrivate.SelectType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/developerPrivate#type-EventType
*/
chrome.developerPrivate.EventType = {
INSTALLED: 'INSTALLED',
@ -450,6 +487,7 @@ chrome.developerPrivate.EventType = {
* override_flags: number,
* status: !chrome.developerPrivate.PackStatus
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-PackDirectoryResponse
*/
chrome.developerPrivate.PackDirectoryResponse;
@ -457,6 +495,7 @@ chrome.developerPrivate.PackDirectoryResponse;
* @typedef {{
* name: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ProjectInfo
*/
chrome.developerPrivate.ProjectInfo;
@ -466,6 +505,7 @@ chrome.developerPrivate.ProjectInfo;
* item_id: string,
* extensionInfo: (!chrome.developerPrivate.ExtensionInfo|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-EventData
*/
chrome.developerPrivate.EventData;
@ -475,6 +515,7 @@ chrome.developerPrivate.EventData;
* highlight: string,
* afterHighlight: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ErrorFileSource
*/
chrome.developerPrivate.ErrorFileSource;
@ -485,6 +526,7 @@ chrome.developerPrivate.ErrorFileSource;
* source: (!chrome.developerPrivate.ErrorFileSource|undefined),
* retryGuid: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-LoadError
*/
chrome.developerPrivate.LoadError;
@ -497,6 +539,7 @@ chrome.developerPrivate.LoadError;
* manifestSpecific: (string|undefined),
* lineNumber: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-RequestFileSourceProperties
*/
chrome.developerPrivate.RequestFileSourceProperties;
@ -508,6 +551,7 @@ chrome.developerPrivate.RequestFileSourceProperties;
* title: string,
* message: string
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-RequestFileSourceResponse
*/
chrome.developerPrivate.RequestFileSourceResponse;
@ -521,6 +565,7 @@ chrome.developerPrivate.RequestFileSourceResponse;
* lineNumber: (number|undefined),
* columnNumber: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-OpenDevToolsProperties
*/
chrome.developerPrivate.OpenDevToolsProperties;
@ -530,12 +575,14 @@ chrome.developerPrivate.OpenDevToolsProperties;
* errorIds: (!Array<number>|undefined),
* type: (!chrome.developerPrivate.ErrorType|undefined)
* }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-DeleteExtensionErrorsProperties
*/
chrome.developerPrivate.DeleteExtensionErrorsProperties;
/**
* Runs auto update for extensions and apps immediately.
* @param {function():void=} callback Called after update check completes.
* @see https://developer.chrome.com/extensions/developerPrivate#method-autoUpdate
*/
chrome.developerPrivate.autoUpdate = function(callback) {};
@ -545,6 +592,7 @@ chrome.developerPrivate.autoUpdate = function(callback) {};
* to restrict the items returned.
* @param {function(!Array<!chrome.developerPrivate.ExtensionInfo>):void=}
* callback Called with extensions info.
* @see https://developer.chrome.com/extensions/developerPrivate#method-getExtensionsInfo
*/
chrome.developerPrivate.getExtensionsInfo = function(options, callback) {};
@ -553,6 +601,7 @@ chrome.developerPrivate.getExtensionsInfo = function(options, callback) {};
* @param {string} id The id of the extension.
* @param {function(!chrome.developerPrivate.ExtensionInfo):void=} callback
* Called with the result.
* @see https://developer.chrome.com/extensions/developerPrivate#method-getExtensionInfo
*/
chrome.developerPrivate.getExtensionInfo = function(id, callback) {};
@ -560,6 +609,7 @@ chrome.developerPrivate.getExtensionInfo = function(id, callback) {};
* Returns the size of a particular extension on disk (already formatted).
* @param {string} id The id of the extension.
* @param {function(string):void} callback Called with the result.
* @see https://developer.chrome.com/extensions/developerPrivate#method-getExtensionSize
*/
chrome.developerPrivate.getExtensionSize = function(id, callback) {};
@ -570,12 +620,14 @@ chrome.developerPrivate.getExtensionSize = function(id, callback) {};
* @param {function(!Array<!chrome.developerPrivate.ItemInfo>):void} callback
* Called with items info.
* @deprecated Use getExtensionsInfo
* @see https://developer.chrome.com/extensions/developerPrivate#method-getItemsInfo
*/
chrome.developerPrivate.getItemsInfo = function(includeDisabled, includeTerminated, callback) {};
/**
* Returns the current profile's configuration.
* @param {function(!chrome.developerPrivate.ProfileInfo):void} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-getProfileConfiguration
*/
chrome.developerPrivate.getProfileConfiguration = function(callback) {};
@ -585,6 +637,7 @@ chrome.developerPrivate.getProfileConfiguration = function(callback) {};
* parameters for updating the profile's configuration. Any properties
* omitted from |update| will not be changed.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-updateProfileConfiguration
*/
chrome.developerPrivate.updateProfileConfiguration = function(update, callback) {};
@ -592,6 +645,7 @@ chrome.developerPrivate.updateProfileConfiguration = function(update, callback)
* Opens a permissions dialog.
* @param {string} extensionId The id of the extension to show permissions for.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-showPermissionsDialog
*/
chrome.developerPrivate.showPermissionsDialog = function(extensionId, callback) {};
@ -602,6 +656,7 @@ chrome.developerPrivate.showPermissionsDialog = function(extensionId, callback)
* configuration parameters.
* @param {function((!chrome.developerPrivate.LoadError|undefined)):void=}
* callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-reload
*/
chrome.developerPrivate.reload = function(extensionId, options, callback) {};
@ -611,6 +666,7 @@ chrome.developerPrivate.reload = function(extensionId, options, callback) {};
* parameters for updating the extension's configuration. Any properties
* omitted from |update| will not be changed.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-updateExtensionConfiguration
*/
chrome.developerPrivate.updateExtensionConfiguration = function(update, callback) {};
@ -620,18 +676,21 @@ chrome.developerPrivate.updateExtensionConfiguration = function(update, callback
* configuration parameters.
* @param {function((!chrome.developerPrivate.LoadError|undefined)):void=}
* callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-loadUnpacked
*/
chrome.developerPrivate.loadUnpacked = function(options, callback) {};
/**
* Installs the file that was dragged and dropped onto the associated page.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-installDroppedFile
*/
chrome.developerPrivate.installDroppedFile = function(callback) {};
/**
* Notifies the browser that a user began a drag in order to install an
* extension.
* @see https://developer.chrome.com/extensions/developerPrivate#method-notifyDragInstallInProgress
*/
chrome.developerPrivate.notifyDragInstallInProgress = function() {};
@ -639,6 +698,7 @@ chrome.developerPrivate.notifyDragInstallInProgress = function() {};
* Loads an extension / app.
* @param {Object} directory The directory to load the extension from.
* @param {function(string):void} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-loadDirectory
*/
chrome.developerPrivate.loadDirectory = function(directory, callback) {};
@ -650,6 +710,7 @@ chrome.developerPrivate.loadDirectory = function(directory, callback) {};
* example, pem type is for private key and load type is for an unpacked
* item.
* @param {function(string):void} callback called with selected item's path.
* @see https://developer.chrome.com/extensions/developerPrivate#method-choosePath
*/
chrome.developerPrivate.choosePath = function(selectType, fileType, callback) {};
@ -660,12 +721,14 @@ chrome.developerPrivate.choosePath = function(selectType, fileType, callback) {}
* @param {number=} flags Special flags to apply to the loading process, if any.
* @param {function(!chrome.developerPrivate.PackDirectoryResponse):void=}
* callback called with the success result string.
* @see https://developer.chrome.com/extensions/developerPrivate#method-packDirectory
*/
chrome.developerPrivate.packDirectory = function(path, privateKeyPath, flags, callback) {};
/**
* Returns true if the profile is managed.
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-isProfileManaged
*/
chrome.developerPrivate.isProfileManaged = function(callback) {};
@ -675,6 +738,7 @@ chrome.developerPrivate.isProfileManaged = function(callback) {};
* @param {!chrome.developerPrivate.RequestFileSourceProperties} properties
* @param {function(!chrome.developerPrivate.RequestFileSourceResponse):void}
* callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-requestFileSource
*/
chrome.developerPrivate.requestFileSource = function(properties, callback) {};
@ -682,6 +746,7 @@ chrome.developerPrivate.requestFileSource = function(properties, callback) {};
* Open the developer tools to focus on a particular error.
* @param {!chrome.developerPrivate.OpenDevToolsProperties} properties
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-openDevTools
*/
chrome.developerPrivate.openDevTools = function(properties, callback) {};
@ -690,6 +755,7 @@ chrome.developerPrivate.openDevTools = function(properties, callback) {};
* @param {!chrome.developerPrivate.DeleteExtensionErrorsProperties} properties
* The properties specifying the errors to remove.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-deleteExtensionErrors
*/
chrome.developerPrivate.deleteExtensionErrors = function(properties, callback) {};
@ -697,6 +763,7 @@ chrome.developerPrivate.deleteExtensionErrors = function(properties, callback) {
* Repairs the extension specified.
* @param {string} extensionId The id of the extension to repair.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-repairExtension
*/
chrome.developerPrivate.repairExtension = function(extensionId, callback) {};
@ -705,6 +772,7 @@ chrome.developerPrivate.repairExtension = function(extensionId, callback) {};
* @param {string} extensionId The id of the extension to show the options page
* for.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-showOptions
*/
chrome.developerPrivate.showOptions = function(extensionId, callback) {};
@ -712,6 +780,7 @@ chrome.developerPrivate.showOptions = function(extensionId, callback) {};
* Shows the path of the extension specified.
* @param {string} extensionId The id of the extension to show the path for.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-showPath
*/
chrome.developerPrivate.showPath = function(extensionId, callback) {};
@ -720,6 +789,7 @@ chrome.developerPrivate.showPath = function(extensionId, callback) {};
* @param {boolean} isSuspended Whether or not shortcut handling should be
* suspended.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-setShortcutHandlingSuspended
*/
chrome.developerPrivate.setShortcutHandlingSuspended = function(isSuspended, callback) {};
@ -728,6 +798,7 @@ chrome.developerPrivate.setShortcutHandlingSuspended = function(isSuspended, cal
* @param {!chrome.developerPrivate.ExtensionCommandUpdate} update The
* parameters for updating the extension command.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-updateExtensionCommand
*/
chrome.developerPrivate.updateExtensionCommand = function(update, callback) {};
@ -737,6 +808,7 @@ chrome.developerPrivate.updateExtensionCommand = function(update, callback) {};
* @param {string} extensionId The id of the extension to modify.
* @param {string} host The host to add.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-addHostPermission
*/
chrome.developerPrivate.addHostPermission = function(extensionId, host, callback) {};
@ -746,6 +818,7 @@ chrome.developerPrivate.addHostPermission = function(extensionId, host, callback
* @param {string} extensionId The id of the extension to modify.
* @param {string} host The host to remove.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/developerPrivate#method-removeHostPermission
*/
chrome.developerPrivate.removeHostPermission = function(extensionId, host, callback) {};
@ -754,6 +827,7 @@ chrome.developerPrivate.removeHostPermission = function(extensionId, host, callb
* @param {boolean} enabled
* @param {function():void=} callback
* @deprecated Use management.setEnabled
* @see https://developer.chrome.com/extensions/developerPrivate#method-enable
*/
chrome.developerPrivate.enable = function(id, enabled, callback) {};
@ -762,6 +836,7 @@ chrome.developerPrivate.enable = function(id, enabled, callback) {};
* @param {boolean} allow
* @param {function():void=} callback
* @deprecated Use updateExtensionConfiguration
* @see https://developer.chrome.com/extensions/developerPrivate#method-allowIncognito
*/
chrome.developerPrivate.allowIncognito = function(extensionId, allow, callback) {};
@ -770,6 +845,7 @@ chrome.developerPrivate.allowIncognito = function(extensionId, allow, callback)
* @param {boolean} allow
* @param {function():void=} callback
* @deprecated Use updateExtensionConfiguration
* @see https://developer.chrome.com/extensions/developerPrivate#method-allowFileAccess
*/
chrome.developerPrivate.allowFileAccess = function(extensionId, allow, callback) {};
@ -777,17 +853,20 @@ chrome.developerPrivate.allowFileAccess = function(extensionId, allow, callback)
* @param {!chrome.developerPrivate.InspectOptions} options
* @param {function():void=} callback
* @deprecated Use openDevTools
* @see https://developer.chrome.com/extensions/developerPrivate#method-inspect
*/
chrome.developerPrivate.inspect = function(options, callback) {};
/**
* Fired when a item state is changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/developerPrivate#event-onItemStateChanged
*/
chrome.developerPrivate.onItemStateChanged;
/**
* Fired when the profile's state has changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/developerPrivate#event-onProfileStateChanged
*/
chrome.developerPrivate.onProfileStateChanged;

View File

@ -22,6 +22,7 @@ chrome.inputMethodPrivate = {};
* isPhysicalKeyboardAutocorrectEnabled: boolean,
* isImeMenuActivated: boolean
* }):void} callback Callback which is called with the config object.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-getInputMethodConfig
*/
chrome.inputMethodPrivate.getInputMethodConfig = function(callback) {};
@ -32,6 +33,7 @@ chrome.inputMethodPrivate.getInputMethodConfig = function(callback) {};
* name: string,
* indicator: string
* }>):void} callback Callback which is called with the input method objects.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-getInputMethods
*/
chrome.inputMethodPrivate.getInputMethods = function(callback) {};
@ -39,6 +41,7 @@ chrome.inputMethodPrivate.getInputMethods = function(callback) {};
* Gets the current input method.
* @param {function(string):void} callback Callback which is called with the
* current input method.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-getCurrentInputMethod
*/
chrome.inputMethodPrivate.getCurrentInputMethod = function(callback) {};
@ -48,6 +51,7 @@ chrome.inputMethodPrivate.getCurrentInputMethod = function(callback) {};
* method.
* @param {function():void=} callback Callback which is called once the current
* input method is set. If unsuccessful $(ref:runtime.lastError) is set.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-setCurrentInputMethod
*/
chrome.inputMethodPrivate.setCurrentInputMethod = function(inputMethodId, callback) {};
@ -55,6 +59,7 @@ chrome.inputMethodPrivate.setCurrentInputMethod = function(inputMethodId, callba
* Fetches a list of all the words currently in the dictionary.
* @param {function(!Array<string>):void} callback Callback which is called once
* the list of dictionary words are ready.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-fetchAllDictionaryWords
*/
chrome.inputMethodPrivate.fetchAllDictionaryWords = function(callback) {};
@ -63,6 +68,7 @@ chrome.inputMethodPrivate.fetchAllDictionaryWords = function(callback) {};
* @param {string} word A new word to add to the dictionary.
* @param {function():void=} callback Callback which is called once the word is
* added. If unsuccessful $(ref:runtime.lastError) is set.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-addWordToDictionary
*/
chrome.inputMethodPrivate.addWordToDictionary = function(word, callback) {};
@ -70,6 +76,7 @@ chrome.inputMethodPrivate.addWordToDictionary = function(word, callback) {};
* Gets whether the encrypt sync is enabled.
* @param {function(boolean):void=} callback Callback which is called to provide
* the result.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-getEncryptSyncEnabled
*/
chrome.inputMethodPrivate.getEncryptSyncEnabled = function(callback) {};
@ -78,35 +85,41 @@ chrome.inputMethodPrivate.getEncryptSyncEnabled = function(callback) {};
* @param {string} xkb_name The XKB layout name.
* @param {function():void=} callback Callback which is called when the layout
* is set.
* @see https://developer.chrome.com/extensions/inputMethodPrivate#method-setXkbLayout
*/
chrome.inputMethodPrivate.setXkbLayout = function(xkb_name, callback) {};
/**
* Fired when the input method is changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/inputMethodPrivate#event-onChanged
*/
chrome.inputMethodPrivate.onChanged;
/**
* Fired when the composition bounds or cursor bounds are changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/inputMethodPrivate#event-onCompositionBoundsChanged
*/
chrome.inputMethodPrivate.onCompositionBoundsChanged;
/**
* Fired when the custom spelling dictionary is loaded.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/inputMethodPrivate#event-onDictionaryLoaded
*/
chrome.inputMethodPrivate.onDictionaryLoaded;
/**
* Fired when words are added or removed from the custom spelling dictionary.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/inputMethodPrivate#event-onDictionaryChanged
*/
chrome.inputMethodPrivate.onDictionaryChanged;
/**
* Fired when the IME menu is activated or deactivated.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/inputMethodPrivate#event-onImeMenuActivationChanged
*/
chrome.inputMethodPrivate.onImeMenuActivationChanged;

View File

@ -18,6 +18,7 @@ chrome.languageSettingsPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-MoveType
*/
chrome.languageSettingsPrivate.MoveType = {
TOP: 'TOP',
@ -36,6 +37,7 @@ chrome.languageSettingsPrivate.MoveType = {
* supportsTranslate: (boolean|undefined),
* isAllowedUILocale: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-Language
*/
chrome.languageSettingsPrivate.Language;
@ -46,6 +48,7 @@ chrome.languageSettingsPrivate.Language;
* isDownloading: (boolean|undefined),
* downloadFailed: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-SpellcheckDictionaryStatus
*/
chrome.languageSettingsPrivate.SpellcheckDictionaryStatus;
@ -57,6 +60,7 @@ chrome.languageSettingsPrivate.SpellcheckDictionaryStatus;
* enabled: (boolean|undefined),
* hasOptionsPage: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-InputMethod
*/
chrome.languageSettingsPrivate.InputMethod;
@ -65,6 +69,7 @@ chrome.languageSettingsPrivate.InputMethod;
* componentExtensionImes: !Array<!chrome.languageSettingsPrivate.InputMethod>,
* thirdPartyExtensionImes: !Array<!chrome.languageSettingsPrivate.InputMethod>
* }}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-InputMethodLists
*/
chrome.languageSettingsPrivate.InputMethodLists;
@ -72,6 +77,7 @@ chrome.languageSettingsPrivate.InputMethodLists;
* Gets languages available for translate, spell checking, input and locale.
* @param {function(!Array<!chrome.languageSettingsPrivate.Language>):void}
* callback
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getLanguageList
*/
chrome.languageSettingsPrivate.getLanguageList = function(callback) {};
@ -79,12 +85,14 @@ chrome.languageSettingsPrivate.getLanguageList = function(callback) {};
* Enables a language, adding it to the Accept-Language list (used to decide
* which languages to translate, generate the Accept-Language header, etc.).
* @param {string} languageCode
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-enableLanguage
*/
chrome.languageSettingsPrivate.enableLanguage = function(languageCode) {};
/**
* Disables a language, removing it from the Accept-Language list.
* @param {string} languageCode
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-disableLanguage
*/
chrome.languageSettingsPrivate.disableLanguage = function(languageCode) {};
@ -92,6 +100,7 @@ chrome.languageSettingsPrivate.disableLanguage = function(languageCode) {};
* Enables or disables translation for a given language.
* @param {string} languageCode
* @param {boolean} enable
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-setEnableTranslationForLanguage
*/
chrome.languageSettingsPrivate.setEnableTranslationForLanguage = function(languageCode, enable) {};
@ -99,6 +108,7 @@ chrome.languageSettingsPrivate.setEnableTranslationForLanguage = function(langua
* Moves a language inside the language list.
* @param {string} languageCode
* @param {!chrome.languageSettingsPrivate.MoveType} moveType
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-moveLanguage
*/
chrome.languageSettingsPrivate.moveLanguage = function(languageCode, moveType) {};
@ -106,30 +116,35 @@ chrome.languageSettingsPrivate.moveLanguage = function(languageCode, moveType) {
* Gets the current status of the chosen spell check dictionaries.
* @param {function(!Array<!chrome.languageSettingsPrivate.SpellcheckDictionaryStatus>):void}
* callback
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getSpellcheckDictionaryStatuses
*/
chrome.languageSettingsPrivate.getSpellcheckDictionaryStatuses = function(callback) {};
/**
* Gets the custom spell check words, in sorted order.
* @param {function(!Array<string>):void} callback
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getSpellcheckWords
*/
chrome.languageSettingsPrivate.getSpellcheckWords = function(callback) {};
/**
* Adds a word to the custom dictionary.
* @param {string} word
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-addSpellcheckWord
*/
chrome.languageSettingsPrivate.addSpellcheckWord = function(word) {};
/**
* Removes a word from the custom dictionary.
* @param {string} word
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-removeSpellcheckWord
*/
chrome.languageSettingsPrivate.removeSpellcheckWord = function(word) {};
/**
* Gets the translate target language (in most cases, the display locale).
* @param {function(string):void} callback
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getTranslateTargetLanguage
*/
chrome.languageSettingsPrivate.getTranslateTargetLanguage = function(callback) {};
@ -137,6 +152,7 @@ chrome.languageSettingsPrivate.getTranslateTargetLanguage = function(callback) {
* Gets all supported input methods, including third-party IMEs. Chrome OS only.
* @param {function(!chrome.languageSettingsPrivate.InputMethodLists):void}
* callback
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getInputMethodLists
*/
chrome.languageSettingsPrivate.getInputMethodLists = function(callback) {};
@ -144,6 +160,7 @@ chrome.languageSettingsPrivate.getInputMethodLists = function(callback) {};
* Adds the input method to the current user's list of enabled input methods,
* enabling the input method for the current user. Chrome OS only.
* @param {string} inputMethodId
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-addInputMethod
*/
chrome.languageSettingsPrivate.addInputMethod = function(inputMethodId) {};
@ -151,12 +168,14 @@ chrome.languageSettingsPrivate.addInputMethod = function(inputMethodId) {};
* Removes the input method from the current user's list of enabled input
* methods, disabling the input method for the current user. Chrome OS only.
* @param {string} inputMethodId
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-removeInputMethod
*/
chrome.languageSettingsPrivate.removeInputMethod = function(inputMethodId) {};
/**
* Tries to download the dictionary after a failed download.
* @param {string} languageCode
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-retryDownloadDictionary
*/
chrome.languageSettingsPrivate.retryDownloadDictionary = function(languageCode) {};
@ -164,6 +183,7 @@ chrome.languageSettingsPrivate.retryDownloadDictionary = function(languageCode)
* Called when the pref for the dictionaries used for spell checking changes or
* the status of one of the spell check dictionaries changes.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#event-onSpellcheckDictionariesChanged
*/
chrome.languageSettingsPrivate.onSpellcheckDictionariesChanged;
@ -171,17 +191,20 @@ chrome.languageSettingsPrivate.onSpellcheckDictionariesChanged;
* Called when words are added to and/or removed from the custom spell check
* dictionary.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#event-onCustomDictionaryChanged
*/
chrome.languageSettingsPrivate.onCustomDictionaryChanged;
/**
* Called when an input method is added.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#event-onInputMethodAdded
*/
chrome.languageSettingsPrivate.onInputMethodAdded;
/**
* Called when an input method is removed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/languageSettingsPrivate#event-onInputMethodRemoved
*/
chrome.languageSettingsPrivate.onInputMethodRemoved;
chrome.languageSettingsPrivate.onInputMethodRemoved;

View File

@ -18,6 +18,7 @@ chrome.metricsPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/metricsPrivate#type-MetricTypeType
*/
chrome.metricsPrivate.MetricTypeType = {
HISTOGRAM_LOG: 'histogram-log',
@ -33,12 +34,14 @@ chrome.metricsPrivate.MetricTypeType = {
* max: number,
* buckets: number
* }}
* @see https://developer.chrome.com/extensions/metricsPrivate#type-MetricType
*/
chrome.metricsPrivate.MetricType;
/**
* Returns true if the user opted in to sending crash reports.
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/metricsPrivate#method-getIsCrashReportingEnabled
*/
chrome.metricsPrivate.getIsCrashReportingEnabled = function(callback) {};
@ -47,6 +50,7 @@ chrome.metricsPrivate.getIsCrashReportingEnabled = function(callback) {};
* trial does not exist or is not enabled.
* @param {string} name
* @param {function(string):void} callback
* @see https://developer.chrome.com/extensions/metricsPrivate#method-getFieldTrial
*/
chrome.metricsPrivate.getFieldTrial = function(name, callback) {};
@ -55,12 +59,14 @@ chrome.metricsPrivate.getFieldTrial = function(name, callback) {};
* otherwise.
* @param {string} name
* @param {function((Object|undefined)):void} callback
* @see https://developer.chrome.com/extensions/metricsPrivate#method-getVariationParams
*/
chrome.metricsPrivate.getVariationParams = function(name, callback) {};
/**
* Records an action performed by the user.
* @param {string} name
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordUserAction
*/
chrome.metricsPrivate.recordUserAction = function(name) {};
@ -68,6 +74,7 @@ chrome.metricsPrivate.recordUserAction = function(name) {};
* Records a percentage value from 1 to 100.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordPercentage
*/
chrome.metricsPrivate.recordPercentage = function(metricName, value) {};
@ -75,6 +82,7 @@ chrome.metricsPrivate.recordPercentage = function(metricName, value) {};
* Records a value than can range from 1 to 1,000,000.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordCount
*/
chrome.metricsPrivate.recordCount = function(metricName, value) {};
@ -82,6 +90,7 @@ chrome.metricsPrivate.recordCount = function(metricName, value) {};
* Records a value than can range from 1 to 100.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordSmallCount
*/
chrome.metricsPrivate.recordSmallCount = function(metricName, value) {};
@ -89,6 +98,7 @@ chrome.metricsPrivate.recordSmallCount = function(metricName, value) {};
* Records a value than can range from 1 to 10,000.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordMediumCount
*/
chrome.metricsPrivate.recordMediumCount = function(metricName, value) {};
@ -97,6 +107,7 @@ chrome.metricsPrivate.recordMediumCount = function(metricName, value) {};
* specified in milliseconds.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordTime
*/
chrome.metricsPrivate.recordTime = function(metricName, value) {};
@ -105,6 +116,7 @@ chrome.metricsPrivate.recordTime = function(metricName, value) {};
* specified in milliseconds.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordMediumTime
*/
chrome.metricsPrivate.recordMediumTime = function(metricName, value) {};
@ -113,6 +125,7 @@ chrome.metricsPrivate.recordMediumTime = function(metricName, value) {};
* specified in milliseconds.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordLongTime
*/
chrome.metricsPrivate.recordLongTime = function(metricName, value) {};
@ -121,6 +134,7 @@ chrome.metricsPrivate.recordLongTime = function(metricName, value) {};
* histogram defined by the |metricName|.
* @param {string} metricName
* @param {string} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordSparseHashable
*/
chrome.metricsPrivate.recordSparseHashable = function(metricName, value) {};
@ -129,6 +143,7 @@ chrome.metricsPrivate.recordSparseHashable = function(metricName, value) {};
* by the |metricName|.
* @param {string} metricName
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordSparseValue
*/
chrome.metricsPrivate.recordSparseValue = function(metricName, value) {};
@ -136,6 +151,7 @@ chrome.metricsPrivate.recordSparseValue = function(metricName, value) {};
* Adds a value to the given metric.
* @param {!chrome.metricsPrivate.MetricType} metric
* @param {number} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordValue
*/
chrome.metricsPrivate.recordValue = function(metric, value) {};
@ -144,6 +160,7 @@ chrome.metricsPrivate.recordValue = function(metric, value) {};
* base::UmaHistogramBoolean().
* @param {string} metricName
* @param {boolean} value
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordBoolean
*/
chrome.metricsPrivate.recordBoolean = function(metricName, value) {};
@ -154,5 +171,6 @@ chrome.metricsPrivate.recordBoolean = function(metricName, value) {};
* @param {string} metricName
* @param {number} value
* @param {number} enumSize
* @see https://developer.chrome.com/extensions/metricsPrivate#method-recordEnumerationValue
*/
chrome.metricsPrivate.recordEnumerationValue = function(metricName, value, enumSize) {};

View File

@ -18,6 +18,7 @@ chrome.networkingPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ActivationStateType
*/
chrome.networkingPrivate.ActivationStateType = {
ACTIVATED: 'Activated',
@ -28,6 +29,7 @@ chrome.networkingPrivate.ActivationStateType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CaptivePortalStatus
*/
chrome.networkingPrivate.CaptivePortalStatus = {
UNKNOWN: 'Unknown',
@ -39,6 +41,7 @@ chrome.networkingPrivate.CaptivePortalStatus = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ConnectionStateType
*/
chrome.networkingPrivate.ConnectionStateType = {
CONNECTED: 'Connected',
@ -48,6 +51,7 @@ chrome.networkingPrivate.ConnectionStateType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-DeviceStateType
*/
chrome.networkingPrivate.DeviceStateType = {
UNINITIALIZED: 'Uninitialized',
@ -59,6 +63,7 @@ chrome.networkingPrivate.DeviceStateType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-IPConfigType
*/
chrome.networkingPrivate.IPConfigType = {
DHCP: 'DHCP',
@ -67,6 +72,7 @@ chrome.networkingPrivate.IPConfigType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkType
*/
chrome.networkingPrivate.NetworkType = {
ALL: 'All',
@ -81,6 +87,7 @@ chrome.networkingPrivate.NetworkType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ProxySettingsType
*/
chrome.networkingPrivate.ProxySettingsType = {
DIRECT: 'Direct',
@ -100,6 +107,7 @@ chrome.networkingPrivate.ProxySettingsType = {
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedBoolean
*/
chrome.networkingPrivate.ManagedBoolean;
@ -114,6 +122,7 @@ chrome.networkingPrivate.ManagedBoolean;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedLong
*/
chrome.networkingPrivate.ManagedLong;
@ -128,6 +137,7 @@ chrome.networkingPrivate.ManagedLong;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedDOMString
*/
chrome.networkingPrivate.ManagedDOMString;
@ -142,6 +152,7 @@ chrome.networkingPrivate.ManagedDOMString;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedDOMStringList
*/
chrome.networkingPrivate.ManagedDOMStringList;
@ -156,6 +167,7 @@ chrome.networkingPrivate.ManagedDOMStringList;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedIPConfigType
*/
chrome.networkingPrivate.ManagedIPConfigType;
@ -170,6 +182,7 @@ chrome.networkingPrivate.ManagedIPConfigType;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedProxySettingsType
*/
chrome.networkingPrivate.ManagedProxySettingsType;
@ -183,6 +196,7 @@ chrome.networkingPrivate.ManagedProxySettingsType;
* Password: (string|undefined),
* Username: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-APNProperties
*/
chrome.networkingPrivate.APNProperties;
@ -196,6 +210,7 @@ chrome.networkingPrivate.APNProperties;
* Password: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* Username: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedAPNProperties
*/
chrome.networkingPrivate.ManagedAPNProperties;
@ -210,6 +225,7 @@ chrome.networkingPrivate.ManagedAPNProperties;
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedAPNList
*/
chrome.networkingPrivate.ManagedAPNList;
@ -219,6 +235,7 @@ chrome.networkingPrivate.ManagedAPNList;
* Code: string,
* Country: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularProviderProperties
*/
chrome.networkingPrivate.CellularProviderProperties;
@ -228,6 +245,7 @@ chrome.networkingPrivate.CellularProviderProperties;
* currentPin: string,
* newPin: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularSimState
*/
chrome.networkingPrivate.CellularSimState;
@ -238,6 +256,7 @@ chrome.networkingPrivate.CellularSimState;
* Organization: (string|undefined),
* OrganizationalUnit: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-IssuerSubjectPattern
*/
chrome.networkingPrivate.IssuerSubjectPattern;
@ -248,6 +267,7 @@ chrome.networkingPrivate.IssuerSubjectPattern;
* Organization: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* OrganizationalUnit: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedIssuerSubjectPattern
*/
chrome.networkingPrivate.ManagedIssuerSubjectPattern;
@ -258,6 +278,7 @@ chrome.networkingPrivate.ManagedIssuerSubjectPattern;
* IssuerCARef: (!Array<string>|undefined),
* Subject: (!chrome.networkingPrivate.IssuerSubjectPattern|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CertificatePattern
*/
chrome.networkingPrivate.CertificatePattern;
@ -268,6 +289,7 @@ chrome.networkingPrivate.CertificatePattern;
* IssuerCARef: (!chrome.networkingPrivate.ManagedDOMStringList|undefined),
* Subject: (!chrome.networkingPrivate.ManagedIssuerSubjectPattern|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedCertificatePattern
*/
chrome.networkingPrivate.ManagedCertificatePattern;
@ -290,6 +312,7 @@ chrome.networkingPrivate.ManagedCertificatePattern;
* UseProactiveKeyCaching: (boolean|undefined),
* UseSystemCAs: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-EAPProperties
*/
chrome.networkingPrivate.EAPProperties;
@ -312,6 +335,7 @@ chrome.networkingPrivate.EAPProperties;
* UseProactiveKeyCaching: (!chrome.networkingPrivate.ManagedBoolean|undefined),
* UseSystemCAs: (!chrome.networkingPrivate.ManagedBoolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedEAPProperties
*/
chrome.networkingPrivate.ManagedEAPProperties;
@ -323,6 +347,7 @@ chrome.networkingPrivate.ManagedEAPProperties;
* ShortName: (string|undefined),
* LongName: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-FoundNetworkProperties
*/
chrome.networkingPrivate.FoundNetworkProperties;
@ -335,6 +360,7 @@ chrome.networkingPrivate.FoundNetworkProperties;
* Type: (string|undefined),
* WebProxyAutoDiscoveryUrl: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-IPConfigProperties
*/
chrome.networkingPrivate.IPConfigProperties;
@ -347,6 +373,7 @@ chrome.networkingPrivate.IPConfigProperties;
* Type: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* WebProxyAutoDiscoveryUrl: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedIPConfigProperties
*/
chrome.networkingPrivate.ManagedIPConfigProperties;
@ -356,6 +383,7 @@ chrome.networkingPrivate.ManagedIPConfigProperties;
* SaveCredentials: (boolean|undefined),
* Username: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-XAUTHProperties
*/
chrome.networkingPrivate.XAUTHProperties;
@ -365,6 +393,7 @@ chrome.networkingPrivate.XAUTHProperties;
* SaveCredentials: (!chrome.networkingPrivate.ManagedBoolean|undefined),
* Username: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedXAUTHProperties
*/
chrome.networkingPrivate.ManagedXAUTHProperties;
@ -384,6 +413,7 @@ chrome.networkingPrivate.ManagedXAUTHProperties;
* ServerCARefs: (!Array<string>|undefined),
* XAUTH: (!chrome.networkingPrivate.XAUTHProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-IPSecProperties
*/
chrome.networkingPrivate.IPSecProperties;
@ -403,6 +433,7 @@ chrome.networkingPrivate.IPSecProperties;
* ServerCARefs: (!chrome.networkingPrivate.ManagedDOMStringList|undefined),
* XAUTH: (!chrome.networkingPrivate.ManagedXAUTHProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedIPSecProperties
*/
chrome.networkingPrivate.ManagedIPSecProperties;
@ -413,6 +444,7 @@ chrome.networkingPrivate.ManagedIPSecProperties;
* SaveCredentials: (boolean|undefined),
* Username: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-L2TPProperties
*/
chrome.networkingPrivate.L2TPProperties;
@ -423,6 +455,7 @@ chrome.networkingPrivate.L2TPProperties;
* SaveCredentials: (!chrome.networkingPrivate.ManagedBoolean|undefined),
* Username: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedL2TPProperties
*/
chrome.networkingPrivate.ManagedL2TPProperties;
@ -432,6 +465,7 @@ chrome.networkingPrivate.ManagedL2TPProperties;
* PostData: (string|undefined),
* Url: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-PaymentPortal
*/
chrome.networkingPrivate.PaymentPortal;
@ -440,6 +474,7 @@ chrome.networkingPrivate.PaymentPortal;
* Host: string,
* Port: number
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ProxyLocation
*/
chrome.networkingPrivate.ProxyLocation;
@ -448,6 +483,7 @@ chrome.networkingPrivate.ProxyLocation;
* Host: !chrome.networkingPrivate.ManagedDOMString,
* Port: !chrome.networkingPrivate.ManagedLong
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedProxyLocation
*/
chrome.networkingPrivate.ManagedProxyLocation;
@ -458,6 +494,7 @@ chrome.networkingPrivate.ManagedProxyLocation;
* FTPProxy: (!chrome.networkingPrivate.ProxyLocation|undefined),
* SOCKS: (!chrome.networkingPrivate.ProxyLocation|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManualProxySettings
*/
chrome.networkingPrivate.ManualProxySettings;
@ -468,6 +505,7 @@ chrome.networkingPrivate.ManualProxySettings;
* FTPProxy: (!chrome.networkingPrivate.ManagedProxyLocation|undefined),
* SOCKS: (!chrome.networkingPrivate.ManagedProxyLocation|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedManualProxySettings
*/
chrome.networkingPrivate.ManagedManualProxySettings;
@ -478,6 +516,7 @@ chrome.networkingPrivate.ManagedManualProxySettings;
* ExcludeDomains: (!Array<string>|undefined),
* PAC: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ProxySettings
*/
chrome.networkingPrivate.ProxySettings;
@ -488,6 +527,7 @@ chrome.networkingPrivate.ProxySettings;
* ExcludeDomains: (!chrome.networkingPrivate.ManagedDOMStringList|undefined),
* PAC: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedProxySettings
*/
chrome.networkingPrivate.ManagedProxySettings;
@ -496,6 +536,7 @@ chrome.networkingPrivate.ManagedProxySettings;
* Name: (string|undefined),
* Type: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-VerifyX509
*/
chrome.networkingPrivate.VerifyX509;
@ -504,6 +545,7 @@ chrome.networkingPrivate.VerifyX509;
* Name: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* Type: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedVerifyX509
*/
chrome.networkingPrivate.ManagedVerifyX509;
@ -548,6 +590,7 @@ chrome.networkingPrivate.ManagedVerifyX509;
* VerifyHash: (string|undefined),
* VerifyX509: (!chrome.networkingPrivate.VerifyX509|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-OpenVPNProperties
*/
chrome.networkingPrivate.OpenVPNProperties;
@ -592,6 +635,7 @@ chrome.networkingPrivate.OpenVPNProperties;
* VerifyHash: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* VerifyX509: (!chrome.networkingPrivate.ManagedVerifyX509|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedOpenVPNProperties
*/
chrome.networkingPrivate.ManagedOpenVPNProperties;
@ -601,6 +645,7 @@ chrome.networkingPrivate.ManagedOpenVPNProperties;
* LockEnabled: boolean,
* RetriesLeft: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-SIMLockStatus
*/
chrome.networkingPrivate.SIMLockStatus;
@ -609,6 +654,7 @@ chrome.networkingPrivate.SIMLockStatus;
* ExtensionID: string,
* ProviderName: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ThirdPartyVPNProperties
*/
chrome.networkingPrivate.ThirdPartyVPNProperties;
@ -617,6 +663,7 @@ chrome.networkingPrivate.ThirdPartyVPNProperties;
* ExtensionID: !chrome.networkingPrivate.ManagedDOMString,
* ProviderName: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedThirdPartyVPNProperties
*/
chrome.networkingPrivate.ManagedThirdPartyVPNProperties;
@ -655,6 +702,7 @@ chrome.networkingPrivate.ManagedThirdPartyVPNProperties;
* SupportNetworkScan: (boolean|undefined),
* SupportedCarriers: (!Array<string>|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularProperties
*/
chrome.networkingPrivate.CellularProperties;
@ -693,6 +741,7 @@ chrome.networkingPrivate.CellularProperties;
* SupportNetworkScan: (boolean|undefined),
* SupportedCarriers: (!Array<string>|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedCellularProperties
*/
chrome.networkingPrivate.ManagedCellularProperties;
@ -705,6 +754,7 @@ chrome.networkingPrivate.ManagedCellularProperties;
* SIMPresent: (boolean|undefined),
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularStateProperties
*/
chrome.networkingPrivate.CellularStateProperties;
@ -714,6 +764,7 @@ chrome.networkingPrivate.CellularStateProperties;
* Authentication: (string|undefined),
* EAP: (!chrome.networkingPrivate.EAPProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-EthernetProperties
*/
chrome.networkingPrivate.EthernetProperties;
@ -723,6 +774,7 @@ chrome.networkingPrivate.EthernetProperties;
* Authentication: (!chrome.networkingPrivate.ManagedDOMString|undefined),
* EAP: (!chrome.networkingPrivate.ManagedEAPProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedEthernetProperties
*/
chrome.networkingPrivate.ManagedEthernetProperties;
@ -730,6 +782,7 @@ chrome.networkingPrivate.ManagedEthernetProperties;
* @typedef {{
* Authentication: string
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-EthernetStateProperties
*/
chrome.networkingPrivate.EthernetStateProperties;
@ -740,6 +793,7 @@ chrome.networkingPrivate.EthernetStateProperties;
* HasConnectedToHost: boolean,
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-TetherProperties
*/
chrome.networkingPrivate.TetherProperties;
@ -753,6 +807,7 @@ chrome.networkingPrivate.TetherProperties;
* ThirdPartyVPN: (!chrome.networkingPrivate.ThirdPartyVPNProperties|undefined),
* Type: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-VPNProperties
*/
chrome.networkingPrivate.VPNProperties;
@ -766,6 +821,7 @@ chrome.networkingPrivate.VPNProperties;
* ThirdPartyVPN: (!chrome.networkingPrivate.ManagedThirdPartyVPNProperties|undefined),
* Type: (!chrome.networkingPrivate.ManagedDOMString|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedVPNProperties
*/
chrome.networkingPrivate.ManagedVPNProperties;
@ -775,6 +831,7 @@ chrome.networkingPrivate.ManagedVPNProperties;
* IPsec: (!chrome.networkingPrivate.IPSecProperties|undefined),
* ThirdPartyVPN: (!chrome.networkingPrivate.ThirdPartyVPNProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-VPNStateProperties
*/
chrome.networkingPrivate.VPNStateProperties;
@ -795,6 +852,7 @@ chrome.networkingPrivate.VPNStateProperties;
* Security: (string|undefined),
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-WiFiProperties
*/
chrome.networkingPrivate.WiFiProperties;
@ -815,6 +873,7 @@ chrome.networkingPrivate.WiFiProperties;
* Security: !chrome.networkingPrivate.ManagedDOMString,
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedWiFiProperties
*/
chrome.networkingPrivate.ManagedWiFiProperties;
@ -827,6 +886,7 @@ chrome.networkingPrivate.ManagedWiFiProperties;
* SignalStrength: (number|undefined),
* SSID: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-WiFiStateProperties
*/
chrome.networkingPrivate.WiFiStateProperties;
@ -836,6 +896,7 @@ chrome.networkingPrivate.WiFiStateProperties;
* EAP: (!chrome.networkingPrivate.EAPProperties|undefined),
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-WiMAXProperties
*/
chrome.networkingPrivate.WiMAXProperties;
@ -845,6 +906,7 @@ chrome.networkingPrivate.WiMAXProperties;
* EAP: (!chrome.networkingPrivate.ManagedEAPProperties|undefined),
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedWiMAXProperties
*/
chrome.networkingPrivate.ManagedWiMAXProperties;
@ -852,6 +914,7 @@ chrome.networkingPrivate.ManagedWiMAXProperties;
* @typedef {{
* SignalStrength: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-WiMAXStateProperties
*/
chrome.networkingPrivate.WiMAXStateProperties;
@ -871,6 +934,7 @@ chrome.networkingPrivate.WiMAXStateProperties;
* WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
* WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkConfigProperties
*/
chrome.networkingPrivate.NetworkConfigProperties;
@ -899,6 +963,7 @@ chrome.networkingPrivate.NetworkConfigProperties;
* WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
* WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkProperties
*/
chrome.networkingPrivate.NetworkProperties;
@ -927,6 +992,7 @@ chrome.networkingPrivate.NetworkProperties;
* WiFi: (!chrome.networkingPrivate.ManagedWiFiProperties|undefined),
* WiMAX: (!chrome.networkingPrivate.ManagedWiMAXProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-ManagedProperties
*/
chrome.networkingPrivate.ManagedProperties;
@ -947,6 +1013,7 @@ chrome.networkingPrivate.ManagedProperties;
* WiFi: (!chrome.networkingPrivate.WiFiStateProperties|undefined),
* WiMAX: (!chrome.networkingPrivate.WiMAXStateProperties|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkStateProperties
*/
chrome.networkingPrivate.NetworkStateProperties;
@ -958,6 +1025,7 @@ chrome.networkingPrivate.NetworkStateProperties;
* State: !chrome.networkingPrivate.DeviceStateType,
* Type: !chrome.networkingPrivate.NetworkType
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-DeviceStateProperties
*/
chrome.networkingPrivate.DeviceStateProperties;
@ -972,6 +1040,7 @@ chrome.networkingPrivate.DeviceStateProperties;
* deviceSsid: string,
* deviceBssid: string
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-VerificationProperties
*/
chrome.networkingPrivate.VerificationProperties;
@ -982,6 +1051,7 @@ chrome.networkingPrivate.VerificationProperties;
* configured: (boolean|undefined),
* limit: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkFilter
*/
chrome.networkingPrivate.NetworkFilter;
@ -990,6 +1060,7 @@ chrome.networkingPrivate.NetworkFilter;
* AllowOnlyPolicyNetworksToAutoconnect: (boolean|undefined),
* AllowOnlyPolicyNetworksToConnect: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-GlobalPolicy
*/
chrome.networkingPrivate.GlobalPolicy;
@ -1002,6 +1073,7 @@ chrome.networkingPrivate.GlobalPolicy;
* PKCS11Id: (string|undefined),
* hardwareBacked: boolean
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-Certificate
*/
chrome.networkingPrivate.Certificate;
@ -1010,6 +1082,7 @@ chrome.networkingPrivate.Certificate;
* serverCaCertificates: !Array<!chrome.networkingPrivate.Certificate>,
* userCertificates: !Array<!chrome.networkingPrivate.Certificate>
* }}
* @see https://developer.chrome.com/extensions/networkingPrivate#type-CertificateLists
*/
chrome.networkingPrivate.CertificateLists;
@ -1019,6 +1092,7 @@ chrome.networkingPrivate.CertificateLists;
* @param {string} networkGuid The GUID of the network to get properties for.
* @param {function(!chrome.networkingPrivate.NetworkProperties):void} callback
* Called with the network properties when received.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getProperties
*/
chrome.networkingPrivate.getProperties = function(networkGuid, callback) {};
@ -1029,6 +1103,7 @@ chrome.networkingPrivate.getProperties = function(networkGuid, callback) {};
* @param {string} networkGuid The GUID of the network to get properties for.
* @param {function(!chrome.networkingPrivate.ManagedProperties):void} callback
* Called with the managed network properties when received.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getManagedProperties
*/
chrome.networkingPrivate.getManagedProperties = function(networkGuid, callback) {};
@ -1043,6 +1118,7 @@ chrome.networkingPrivate.getManagedProperties = function(networkGuid, callback)
* @param {string} networkGuid The GUID of the network to get properties for.
* @param {function(!chrome.networkingPrivate.NetworkStateProperties):void}
* callback Called immediately with the network state properties.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getState
*/
chrome.networkingPrivate.getState = function(networkGuid, callback) {};
@ -1054,6 +1130,7 @@ chrome.networkingPrivate.getState = function(networkGuid, callback) {};
* @param {!chrome.networkingPrivate.NetworkConfigProperties} properties The
* properties to set.
* @param {function():void=} callback Called when the operation has completed.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-setProperties
*/
chrome.networkingPrivate.setProperties = function(networkGuid, properties, callback) {};
@ -1067,6 +1144,7 @@ chrome.networkingPrivate.setProperties = function(networkGuid, properties, callb
* properties to configure the new network with.
* @param {function(string):void=} callback Called with the GUID for the new
* network configuration once the network has been created.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-createNetwork
*/
chrome.networkingPrivate.createNetwork = function(shared, properties, callback) {};
@ -1077,6 +1155,7 @@ chrome.networkingPrivate.createNetwork = function(shared, properties, callback)
* configuration exists, an error will be set and the operation will fail.
* @param {string} networkGuid The GUID of the network to forget.
* @param {function():void=} callback Called when the operation has completed.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-forgetNetwork
*/
chrome.networkingPrivate.forgetNetwork = function(networkGuid, callback) {};
@ -1091,6 +1170,7 @@ chrome.networkingPrivate.forgetNetwork = function(networkGuid, callback) {};
* @param {function(!Array<!chrome.networkingPrivate.NetworkStateProperties>):void}
* callback Called with a dictionary of networks and their state
* properties when received.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getNetworks
*/
chrome.networkingPrivate.getNetworks = function(filter, callback) {};
@ -1101,6 +1181,7 @@ chrome.networkingPrivate.getNetworks = function(filter, callback) {};
* @param {function(!Array<!chrome.networkingPrivate.NetworkStateProperties>):void}
* callback
* @deprecated Use getNetworks.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getVisibleNetworks
*/
chrome.networkingPrivate.getVisibleNetworks = function(networkType, callback) {};
@ -1109,6 +1190,7 @@ chrome.networkingPrivate.getVisibleNetworks = function(networkType, callback) {}
* @param {function(!Array<!chrome.networkingPrivate.NetworkType>):void}
* callback
* @deprecated Use getDeviceStates.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getEnabledNetworkTypes
*/
chrome.networkingPrivate.getEnabledNetworkTypes = function(callback) {};
@ -1116,6 +1198,7 @@ chrome.networkingPrivate.getEnabledNetworkTypes = function(callback) {};
* Returns a list of $(ref:networkingPrivate.DeviceStateProperties) objects.
* @param {function(!Array<!chrome.networkingPrivate.DeviceStateProperties>):void}
* callback Called with a list of devices and their state.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getDeviceStates
*/
chrome.networkingPrivate.getDeviceStates = function(callback) {};
@ -1124,6 +1207,7 @@ chrome.networkingPrivate.getDeviceStates = function(callback) {};
* represent multiple network types (e.g. 'Wireless').
* @param {!chrome.networkingPrivate.NetworkType} networkType The type of
* network to enable.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-enableNetworkType
*/
chrome.networkingPrivate.enableNetworkType = function(networkType) {};
@ -1132,6 +1216,7 @@ chrome.networkingPrivate.enableNetworkType = function(networkType) {};
* $(ref:networkingPrivate.enableNetworkType).
* @param {!chrome.networkingPrivate.NetworkType} networkType The type of
* network to disable.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-disableNetworkType
*/
chrome.networkingPrivate.disableNetworkType = function(networkType) {};
@ -1143,6 +1228,7 @@ chrome.networkingPrivate.disableNetworkType = function(networkType) {};
* @param {!chrome.networkingPrivate.NetworkType=} networkType If provided,
* requests a scan specific to the type. For Cellular a mobile network
* scan will be requested if supported.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-requestNetworkScan
*/
chrome.networkingPrivate.requestNetworkScan = function(networkType) {};
@ -1155,6 +1241,7 @@ chrome.networkingPrivate.requestNetworkScan = function(networkType) {};
* If the connect request immediately failed (e.g. the network is
* unconfigured), $(ref:runtime.lastError) will be set with a failure
* reason.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-startConnect
*/
chrome.networkingPrivate.startConnect = function(networkGuid, callback) {};
@ -1163,6 +1250,7 @@ chrome.networkingPrivate.startConnect = function(networkGuid, callback) {};
* @param {string} networkGuid The GUID of the network to disconnect from.
* @param {function():void=} callback Called when the disconnect request has
* been sent. See note for $(ref:startConnect).
* @see https://developer.chrome.com/extensions/networkingPrivate#method-startDisconnect
*/
chrome.networkingPrivate.startDisconnect = function(networkGuid, callback) {};
@ -1175,6 +1263,7 @@ chrome.networkingPrivate.startDisconnect = function(networkGuid, callback) {};
* @param {string=} carrier Optional name of carrier to activate.
* @param {function():void=} callback Called when the activation request has
* been sent. See note for $(ref:startConnect).
* @see https://developer.chrome.com/extensions/networkingPrivate#method-startActivate
*/
chrome.networkingPrivate.startActivate = function(networkGuid, carrier, callback) {};
@ -1186,6 +1275,7 @@ chrome.networkingPrivate.startActivate = function(networkGuid, carrier, callback
* @param {function(boolean):void} callback A callback function that indicates
* whether or not the device is a trusted device.
* @deprecated Use networking.castPrivate API.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyDestination
*/
chrome.networkingPrivate.verifyDestination = function(properties, callback) {};
@ -1199,6 +1289,7 @@ chrome.networkingPrivate.verifyDestination = function(properties, callback) {};
* @param {function(string):void} callback A callback function that receives
* base64-encoded encrypted credential data to send to a trusted device.
* @deprecated Use networking.castPrivate API.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyAndEncryptCredentials
*/
chrome.networkingPrivate.verifyAndEncryptCredentials = function(properties, networkGuid, callback) {};
@ -1212,6 +1303,7 @@ chrome.networkingPrivate.verifyAndEncryptCredentials = function(properties, netw
* @param {function(string):void} callback A callback function that receives
* base64-encoded encrypted data to send to a trusted device.
* @deprecated Use networking.castPrivate API.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyAndEncryptData
*/
chrome.networkingPrivate.verifyAndEncryptData = function(properties, data, callback) {};
@ -1227,6 +1319,7 @@ chrome.networkingPrivate.verifyAndEncryptData = function(properties, data, callb
* indicates that the lookup timed out. Otherwise a valid status is
* returned (see $(ref:getWifiTDLSStatus)).
* @deprecated Use networking.castPrivate API.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-setWifiTDLSEnabledState
*/
chrome.networkingPrivate.setWifiTDLSEnabledState = function(ip_or_mac_address, enabled, callback) {};
@ -1237,6 +1330,7 @@ chrome.networkingPrivate.setWifiTDLSEnabledState = function(ip_or_mac_address, e
* string with the current TDLS status which can be 'Connected',
* 'Disabled', 'Disconnected', 'Nonexistent', or 'Unknown'.
* @deprecated Use networking.castPrivate API.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getWifiTDLSStatus
*/
chrome.networkingPrivate.getWifiTDLSStatus = function(ip_or_mac_address, callback) {};
@ -1247,6 +1341,7 @@ chrome.networkingPrivate.getWifiTDLSStatus = function(ip_or_mac_address, callbac
* @param {function(!chrome.networkingPrivate.CaptivePortalStatus):void}
* callback A callback function that returns the results of the query for
* network captive portal status.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getCaptivePortalStatus
*/
chrome.networkingPrivate.getCaptivePortalStatus = function(networkGuid, callback) {};
@ -1261,6 +1356,7 @@ chrome.networkingPrivate.getCaptivePortalStatus = function(networkGuid, callback
* @param {string} pin The current SIM PIN, or the new PIN if PUK is provided.
* @param {string=} puk The operator provided PUK for unblocking a blocked SIM.
* @param {function():void=} callback Called when the operation has completed.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-unlockCellularSim
*/
chrome.networkingPrivate.unlockCellularSim = function(networkGuid, pin, puk, callback) {};
@ -1277,6 +1373,7 @@ chrome.networkingPrivate.unlockCellularSim = function(networkGuid, pin, puk, cal
* @param {!chrome.networkingPrivate.CellularSimState} simState The SIM state to
* set.
* @param {function():void=} callback Called when the operation has completed.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-setCellularSimState
*/
chrome.networkingPrivate.setCellularSimState = function(networkGuid, simState, callback) {};
@ -1288,6 +1385,7 @@ chrome.networkingPrivate.setCellularSimState = function(networkGuid, simState, c
* network for. If empty, the default cellular device will be used.
* @param {string} networkId The networkId to select.
* @param {function():void=} callback Called when the operation has completed.
* @see https://developer.chrome.com/extensions/networkingPrivate#method-selectCellularMobileNetwork
*/
chrome.networkingPrivate.selectCellularMobileNetwork = function(networkGuid, networkId, callback) {};
@ -1295,12 +1393,14 @@ chrome.networkingPrivate.selectCellularMobileNetwork = function(networkGuid, net
* Gets the global policy properties. These properties are not expected to
* change during a session.
* @param {function(!chrome.networkingPrivate.GlobalPolicy):void} callback
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getGlobalPolicy
*/
chrome.networkingPrivate.getGlobalPolicy = function(callback) {};
/**
* Gets the lists of certificates available for network configuration.
* @param {function(!chrome.networkingPrivate.CertificateLists):void} callback
* @see https://developer.chrome.com/extensions/networkingPrivate#method-getCertificateLists
*/
chrome.networkingPrivate.getCertificateLists = function(callback) {};
@ -1308,6 +1408,7 @@ chrome.networkingPrivate.getCertificateLists = function(callback) {};
* Fired when the properties change on any of the networks. Sends a list of
* GUIDs for networks whose properties have changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/networkingPrivate#event-onNetworksChanged
*/
chrome.networkingPrivate.onNetworksChanged;
@ -1315,6 +1416,7 @@ chrome.networkingPrivate.onNetworksChanged;
* Fired when the list of networks has changed. Sends a complete list of GUIDs
* for all the current networks.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/networkingPrivate#event-onNetworkListChanged
*/
chrome.networkingPrivate.onNetworkListChanged;
@ -1322,6 +1424,7 @@ chrome.networkingPrivate.onNetworkListChanged;
* Fired when the list of devices has changed or any device state properties
* have changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/networkingPrivate#event-onDeviceStateListChanged
*/
chrome.networkingPrivate.onDeviceStateListChanged;
@ -1329,11 +1432,13 @@ chrome.networkingPrivate.onDeviceStateListChanged;
* Fired when a portal detection for a network completes. Sends the guid of the
* network and the corresponding captive portal status.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/networkingPrivate#event-onPortalDetectionCompleted
*/
chrome.networkingPrivate.onPortalDetectionCompleted;
/**
* Fired when any certificate list has changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/networkingPrivate#event-onCertificateListsChanged
*/
chrome.networkingPrivate.onCertificateListsChanged;

View File

@ -18,6 +18,7 @@ chrome.passwordsPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-ExportProgressStatus
*/
chrome.passwordsPrivate.ExportProgressStatus = {
NOT_STARTED: 'NOT_STARTED',
@ -33,6 +34,7 @@ chrome.passwordsPrivate.ExportProgressStatus = {
* shown: string,
* link: string
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-UrlCollection
*/
chrome.passwordsPrivate.UrlCollection;
@ -41,6 +43,7 @@ chrome.passwordsPrivate.UrlCollection;
* urls: !chrome.passwordsPrivate.UrlCollection,
* username: string
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-LoginPair
*/
chrome.passwordsPrivate.LoginPair;
@ -51,6 +54,7 @@ chrome.passwordsPrivate.LoginPair;
* federationText: (string|undefined),
* index: number
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-PasswordUiEntry
*/
chrome.passwordsPrivate.PasswordUiEntry;
@ -59,6 +63,7 @@ chrome.passwordsPrivate.PasswordUiEntry;
* index: number,
* plaintextPassword: string
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-PlaintextPasswordEventParameters
*/
chrome.passwordsPrivate.PlaintextPasswordEventParameters;
@ -67,6 +72,7 @@ chrome.passwordsPrivate.PlaintextPasswordEventParameters;
* urls: !chrome.passwordsPrivate.UrlCollection,
* index: number
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-ExceptionEntry
*/
chrome.passwordsPrivate.ExceptionEntry;
@ -75,6 +81,7 @@ chrome.passwordsPrivate.ExceptionEntry;
* status: !chrome.passwordsPrivate.ExportProgressStatus,
* message: (string|undefined),
* }}
* @see https://developer.chrome.com/extensions/passwordsPrivate#type-PasswordExportProgress
*/
chrome.passwordsPrivate.PasswordExportProgress;
@ -82,6 +89,7 @@ chrome.passwordsPrivate.PasswordExportProgress;
* Removes the saved password corresponding to |loginPair|. If no saved password
* for this pair exists, this function is a no-op.
* @param {number} index The index for the password entry being removed.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-removeSavedPassword
*/
chrome.passwordsPrivate.removeSavedPassword = function(index) {};
@ -89,11 +97,13 @@ chrome.passwordsPrivate.removeSavedPassword = function(index) {};
* Removes the saved password exception corresponding to |exceptionUrl|. If no
* exception with this URL exists, this function is a no-op.
* @param {number} index The index for the exception url entry being removed.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-removePasswordException
*/
chrome.passwordsPrivate.removePasswordException = function(index) {};
/**
* Undoes the last removal of a saved password or exception.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-undoRemoveSavedPasswordOrException
*/
chrome.passwordsPrivate.undoRemoveSavedPasswordOrException = function() {};
@ -104,6 +114,7 @@ chrome.passwordsPrivate.undoRemoveSavedPasswordOrException = function() {};
* onPlaintextPasswordRetrieved event. TODO(hcarmona): Investigate using a
* callback for consistency.
* @param {number} index The index for the password entry being being retrieved.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-requestPlaintextPassword
*/
chrome.passwordsPrivate.requestPlaintextPassword = function(index) {};
@ -111,6 +122,7 @@ chrome.passwordsPrivate.requestPlaintextPassword = function(index) {};
* Returns the list of saved passwords.
* @param {function(!Array<!chrome.passwordsPrivate.PasswordUiEntry>):void}
* callback Called with the list of saved passwords.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-getSavedPasswordList
*/
chrome.passwordsPrivate.getSavedPasswordList = function(callback) {};
@ -118,11 +130,13 @@ chrome.passwordsPrivate.getSavedPasswordList = function(callback) {};
* Returns the list of password exceptions.
* @param {function(!Array<!chrome.passwordsPrivate.ExceptionEntry>):void}
* callback Called with the list of password exceptions.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-getPasswordExceptionList
*/
chrome.passwordsPrivate.getPasswordExceptionList = function(callback) {};
/**
* Triggers the Password Manager password import functionality.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-importPasswords
*/
chrome.passwordsPrivate.importPasswords = function() {};
@ -132,11 +146,13 @@ chrome.passwordsPrivate.importPasswords = function() {};
* callback Called with no error, if the new export request was accepted and
* started. If rejected, <code>chrome.runtime.lastError</code> will be
* set to 'in-progress'.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-exportPasswords
*/
chrome.passwordsPrivate.exportPasswords = function(callback) {};
/**
* Triggers the cancelling of a password export flow.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-cancelExportPasswords
*/
chrome.passwordsPrivate.cancelExportPasswords = function() {};
@ -144,6 +160,7 @@ chrome.passwordsPrivate.cancelExportPasswords = function() {};
* Triggers the Password Manager password export status query functionality.
* @param {function(!chrome.passwordsPrivate.ExportProgressStatus):void}
* callback Called with the status of the current export.
* @see https://developer.chrome.com/extensions/passwordsPrivate#method-requestExportProgressStatus
*/
chrome.passwordsPrivate.requestExportProgressStatus = function(callback) {};
@ -151,6 +168,7 @@ chrome.passwordsPrivate.requestExportProgressStatus = function(callback) {};
* Fired when the saved passwords list has changed, meaning that an entry has
* been added or removed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/passwordsPrivate#event-onSavedPasswordsListChanged
*/
chrome.passwordsPrivate.onSavedPasswordsListChanged;
@ -158,6 +176,7 @@ chrome.passwordsPrivate.onSavedPasswordsListChanged;
* Fired when the password exceptions list has changed, meaning that an entry
* has been added or removed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/passwordsPrivate#event-onPasswordExceptionsListChanged
*/
chrome.passwordsPrivate.onPasswordExceptionsListChanged;
@ -165,6 +184,7 @@ chrome.passwordsPrivate.onPasswordExceptionsListChanged;
* Fired when a plaintext password has been fetched in response to a call to
* chrome.passwordsPrivate.requestPlaintextPassword().
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/passwordsPrivate#event-onPlaintextPasswordRetrieved
*/
chrome.passwordsPrivate.onPlaintextPasswordRetrieved;
@ -172,5 +192,6 @@ chrome.passwordsPrivate.onPlaintextPasswordRetrieved;
/**
* Fired when status of the export has progressed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/passwordsPrivate#event-onPasswordsExportCompleted
*/
chrome.passwordsPrivate.onPasswordsFileExportProgress;

View File

@ -21,11 +21,13 @@ chrome.quickUnlockPrivate = {};
* token: string,
* lifetimeSeconds: number
* }}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-TokenInfo
*/
chrome.quickUnlockPrivate.TokenInfo;
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-QuickUnlockMode
*/
chrome.quickUnlockPrivate.QuickUnlockMode = {
PIN: 'PIN',
@ -33,6 +35,7 @@ chrome.quickUnlockPrivate.QuickUnlockMode = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialProblem
*/
chrome.quickUnlockPrivate.CredentialProblem = {
TOO_SHORT: 'TOO_SHORT',
@ -46,6 +49,7 @@ chrome.quickUnlockPrivate.CredentialProblem = {
* errors: !Array<!chrome.quickUnlockPrivate.CredentialProblem>,
* warnings: !Array<!chrome.quickUnlockPrivate.CredentialProblem>
* }}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialCheck
*/
chrome.quickUnlockPrivate.CredentialCheck;
@ -54,6 +58,7 @@ chrome.quickUnlockPrivate.CredentialCheck;
* minLength: number,
* maxLength: number
* }}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialRequirements
*/
chrome.quickUnlockPrivate.CredentialRequirements;
@ -62,6 +67,7 @@ chrome.quickUnlockPrivate.CredentialRequirements;
* seconds until the token expires.
* @param {string} accountPassword The account password for the logged in user.
* @param {function(!chrome.quickUnlockPrivate.TokenInfo):void} onComplete
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getAuthToken
*/
chrome.quickUnlockPrivate.getAuthToken = function(accountPassword, onComplete) {};
@ -73,6 +79,7 @@ chrome.quickUnlockPrivate.getAuthToken = function(accountPassword, onComplete) {
* @param {string} token The token returned by $(ref:getAuthToken).
* @param {boolean} enabled
* @param {function():void=} onComplete
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setLockScreenEnabled
*/
chrome.quickUnlockPrivate.setLockScreenEnabled = function(token, enabled, onComplete) {};
@ -81,6 +88,7 @@ chrome.quickUnlockPrivate.setLockScreenEnabled = function(token, enabled, onComp
* Some quick unlock modes may be disabled by policy.
* @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void}
* onComplete
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getAvailableModes
*/
chrome.quickUnlockPrivate.getAvailableModes = function(onComplete) {};
@ -89,6 +97,7 @@ chrome.quickUnlockPrivate.getAvailableModes = function(onComplete) {};
* lock screen.
* @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void}
* onComplete
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getActiveModes
*/
chrome.quickUnlockPrivate.getActiveModes = function(onComplete) {};
@ -101,6 +110,7 @@ chrome.quickUnlockPrivate.getActiveModes = function(onComplete) {};
* @param {function(!chrome.quickUnlockPrivate.CredentialCheck):void} onComplete
* Called with a list of warnings and errors the given |credential| has
* (or an empty list if there are none).
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-checkCredential
*/
chrome.quickUnlockPrivate.checkCredential = function(mode, credential, onComplete) {};
@ -111,6 +121,7 @@ chrome.quickUnlockPrivate.checkCredential = function(mode, credential, onComplet
* @param {function(!chrome.quickUnlockPrivate.CredentialRequirements):void}
* onComplete Called with the credential requirements of the given
* |mode|.
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getCredentialRequirements
*/
chrome.quickUnlockPrivate.getCredentialRequirements = function(mode, onComplete) {};
@ -125,11 +136,13 @@ chrome.quickUnlockPrivate.getCredentialRequirements = function(mode, onComplete)
* @param {function():void} onComplete Called with true if the quick unlock
* state was updated, false otherwise. The update is treated as a single
* atomic operation.
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setModes
*/
chrome.quickUnlockPrivate.setModes = function(token, modes, credentials, onComplete) {};
/**
* Called after the active set of quick unlock modes has changed.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/quickUnlockPrivate#event-onActiveModesChanged
*/
chrome.quickUnlockPrivate.onActiveModesChanged;

View File

@ -22,6 +22,7 @@ chrome.safeBrowsingPrivate = {};
* userName: string,
* isPhishing: boolean
* }}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#type-PolicySpecifiedPasswordReuse
*/
chrome.safeBrowsingPrivate.PolicySpecifiedPasswordReuse;
@ -32,6 +33,7 @@ chrome.safeBrowsingPrivate.PolicySpecifiedPasswordReuse;
* sha256: string,
* userName: (string|undefined)
* }}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#type-DangerousDownloadInfo
*/
chrome.safeBrowsingPrivate.DangerousDownloadInfo;
@ -41,35 +43,41 @@ chrome.safeBrowsingPrivate.DangerousDownloadInfo;
* reason: string,
* netErrorCode: (number|undefined)
* }}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#type-InterstitialInfo
*/
chrome.safeBrowsingPrivate.InterstitialInfo;
/**
* Fired when Chrome detects a reuse of a policy specified password.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#event-onPolicySpecifiedPasswordReuseDetected
*/
chrome.safeBrowsingPrivate.onPolicySpecifiedPasswordReuseDetected;
/**
* Fired when the user changed their policy specified password.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#event-onPolicySpecifiedPasswordChanged
*/
chrome.safeBrowsingPrivate.onPolicySpecifiedPasswordChanged;
/**
* Fired when the user opened a dangerous download.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#event-onDangerousDownloadOpened
*/
chrome.safeBrowsingPrivate.onDangerousDownloadOpened;
/**
* Fired when a security interstitial is shown to the user.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#event-onInterstitialShown
*/
chrome.safeBrowsingPrivate.onInterstitialShown;
/**
* Fired when the user clicked-through a security interstitial.
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/safeBrowsingPrivate#event-onInterstitialProceeded
*/
chrome.safeBrowsingPrivate.onInterstitialProceeded;

View File

@ -18,6 +18,7 @@ chrome.settingsPrivate = {};
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/settingsPrivate#type-PrefType
*/
chrome.settingsPrivate.PrefType = {
BOOLEAN: 'BOOLEAN',
@ -30,6 +31,7 @@ chrome.settingsPrivate.PrefType = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/settingsPrivate#type-ControlledBy
*/
chrome.settingsPrivate.ControlledBy = {
DEVICE_POLICY: 'DEVICE_POLICY',
@ -41,6 +43,7 @@ chrome.settingsPrivate.ControlledBy = {
/**
* @enum {string}
* @see https://developer.chrome.com/extensions/settingsPrivate#type-Enforcement
*/
chrome.settingsPrivate.Enforcement = {
ENFORCED: 'ENFORCED',
@ -59,6 +62,7 @@ chrome.settingsPrivate.Enforcement = {
* extensionId: (string|undefined),
* extensionCanBeDisabled: (boolean|undefined)
* }}
* @see https://developer.chrome.com/extensions/settingsPrivate#type-PrefObject
*/
chrome.settingsPrivate.PrefObject;
@ -69,12 +73,14 @@ chrome.settingsPrivate.PrefObject;
* @param {string} pageId The user metrics identifier or null.
* @param {function(boolean):void} callback The callback for whether the pref
* was set or not.
* @see https://developer.chrome.com/extensions/settingsPrivate#method-setPref
*/
chrome.settingsPrivate.setPref = function(name, value, pageId, callback) {};
/**
* Gets an array of all the prefs.
* @param {function(!Array<!chrome.settingsPrivate.PrefObject>):void} callback
* @see https://developer.chrome.com/extensions/settingsPrivate#method-getAllPrefs
*/
chrome.settingsPrivate.getAllPrefs = function(callback) {};
@ -82,6 +88,7 @@ chrome.settingsPrivate.getAllPrefs = function(callback) {};
* Gets the value of a specific pref.
* @param {string} name
* @param {function(!chrome.settingsPrivate.PrefObject):void} callback
* @see https://developer.chrome.com/extensions/settingsPrivate#method-getPref
*/
chrome.settingsPrivate.getPref = function(name, callback) {};
@ -89,6 +96,7 @@ chrome.settingsPrivate.getPref = function(name, callback) {};
* Gets the default page zoom factor. Possible values are currently between 0.25
* and 5. For a full list, see zoom::kPresetZoomFactors.
* @param {function(number):void} callback
* @see https://developer.chrome.com/extensions/settingsPrivate#method-getDefaultZoom
*/
chrome.settingsPrivate.getDefaultZoom = function(callback) {};
@ -97,6 +105,7 @@ chrome.settingsPrivate.getDefaultZoom = function(callback) {};
* zoom::kPresetZoomFactors.
* @param {number} zoom
* @param {function(boolean):void=} callback
* @see https://developer.chrome.com/extensions/settingsPrivate#method-setDefaultZoom
*/
chrome.settingsPrivate.setDefaultZoom = function(zoom, callback) {};
@ -104,5 +113,6 @@ chrome.settingsPrivate.setDefaultZoom = function(zoom, callback) {};
* <p>Fired when a set of prefs has changed.</p><p>|prefs| The prefs that
* changed.</p>
* @type {!ChromeEvent}
* @see https://developer.chrome.com/extensions/settingsPrivate#event-onPrefsChanged
*/
chrome.settingsPrivate.onPrefsChanged;

View File

@ -25,12 +25,14 @@ chrome.usersPrivate = {};
* isSupervised: boolean,
* isChild: boolean
* }}
* @see https://developer.chrome.com/extensions/usersPrivate#type-User
*/
chrome.usersPrivate.User;
/**
* Gets a list of the currently whitelisted users.
* @param {function(!Array<!chrome.usersPrivate.User>):void} callback
* @see https://developer.chrome.com/extensions/usersPrivate#method-getWhitelistedUsers
*/
chrome.usersPrivate.getWhitelistedUsers = function(callback) {};
@ -40,6 +42,7 @@ chrome.usersPrivate.getWhitelistedUsers = function(callback) {};
* because the user was already present, or the current user isn't the owner).
* @param {string} email
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/usersPrivate#method-addWhitelistedUser
*/
chrome.usersPrivate.addWhitelistedUser = function(email, callback) {};
@ -50,17 +53,20 @@ chrome.usersPrivate.addWhitelistedUser = function(email, callback) {};
* owner).
* @param {string} email
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/usersPrivate#method-removeWhitelistedUser
*/
chrome.usersPrivate.removeWhitelistedUser = function(email, callback) {};
/**
* Whether the whitelist is managed by enterprise.
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/usersPrivate#method-isWhitelistManaged
*/
chrome.usersPrivate.isWhitelistManaged = function(callback) {};
/**
* Returns the current user.
* @param {function(!chrome.usersPrivate.User):void} callback
* @see https://developer.chrome.com/extensions/usersPrivate#method-getCurrentUser
*/
chrome.usersPrivate.getCurrentUser = function(callback) {};