diff options
90 files changed, 2936 insertions, 2519 deletions
diff --git a/examples/provider/curl_http_client.cc b/examples/provider/curl_http_client.cc index 2bf10f5..de8b3dd 100644 --- a/examples/provider/curl_http_client.cc +++ b/examples/provider/curl_http_client.cc @@ -4,6 +4,7 @@ #include "examples/provider/curl_http_client.h" +#include <algorithm> #include <future> #include <thread> diff --git a/file_lists.mk b/file_lists.mk index 1e78935..a018178 100644 --- a/file_lists.mk +++ b/file_lists.mk @@ -129,7 +129,6 @@ THIRD_PARTY_CHROMIUM_BASE_UNITTEST_SRC_FILES := \ third_party/chromium/base/memory/ref_counted_unittest.cc \ third_party/chromium/base/memory/scoped_ptr_unittest.cc \ third_party/chromium/base/memory/weak_ptr_unittest.cc \ - third_party/chromium/base/move_unittest.cc \ third_party/chromium/base/numerics/safe_numerics_unittest.cc \ third_party/chromium/base/observer_list_unittest.cc \ third_party/chromium/base/rand_util_unittest.cc \ diff --git a/src/backoff_entry.cc b/src/backoff_entry.cc index 6b99d79..7efc33b 100644 --- a/src/backoff_entry.cc +++ b/src/backoff_entry.cc @@ -74,7 +74,7 @@ bool BackoffEntry::CanDiscard() const { base::TimeTicks now = ImplGetTimeNow(); - int64 unused_since_ms = + int64_t unused_since_ms = (now - exponential_backoff_release_time_).InMilliseconds(); // Release time is further than now, we are managing it. @@ -152,7 +152,7 @@ base::TimeTicks BackoffEntry::CalculateReleaseTime() const { // Decide between maximum release time and calculated release time, accounting // for overflow with both. - int64 release_time_us = + int64_t release_time_us = std::min(calculated_release_time_us.ValueOrDefault(kMaxTime), maximum_release_time_us.ValueOrDefault(kMaxTime)); diff --git a/src/backoff_entry.h b/src/backoff_entry.h index 002fb8d..422ffc7 100644 --- a/src/backoff_entry.h +++ b/src/backoff_entry.h @@ -38,11 +38,11 @@ class BackoffEntry { // Maximum amount of time we are willing to delay our request, -1 // for no maximum. - int64 maximum_backoff_ms; + int64_t maximum_backoff_ms; // Time to keep an entry from being discarded even when it // has no significant state, -1 to never discard. - int64 entry_lifetime_ms; + int64_t entry_lifetime_ms; // If true, we always use a delay of initial_delay_ms, even before // we've seen num_errors_to_ignore errors. Otherwise, initial_delay_ms diff --git a/src/config.cc b/src/config.cc index 37e907c..76be205 100644 --- a/src/config.cc +++ b/src/config.cc @@ -121,10 +121,9 @@ void Config::Load() { CHECK(!settings_.model_id.empty()); CHECK(!settings_.name.empty()); CHECK(!settings_.device_id.empty()); - CHECK_EQ( - settings_.embedded_code.empty(), - std::find(settings_.pairing_modes.begin(), settings_.pairing_modes.end(), - PairingType::kEmbeddedCode) == settings_.pairing_modes.end()); + CHECK_EQ(settings_.embedded_code.empty(), + (settings_.pairing_modes.find(PairingType::kEmbeddedCode) == + settings_.pairing_modes.end())); // Values below will be generated at runtime. CHECK(settings_.cloud_id.empty()); diff --git a/third_party/chromium/base/basictypes.h b/third_party/chromium/base/basictypes.h deleted file mode 100644 index d71abd9..0000000 --- a/third_party/chromium/base/basictypes.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains definitions of our old basic integral types -// ((u)int{8,16,32,64}) and further includes. I recommend that you use the C99 -// standard types instead, and include <stdint.h>/<stddef.h>/etc. as needed. -// Note that the macros and macro-like constructs that were formerly defined in -// this file are now available separately in base/macros.h. - -#ifndef BASE_BASICTYPES_H_ -#define BASE_BASICTYPES_H_ - -#include <limits.h> // So we can set the bounds of our types. -#include <stddef.h> // For size_t. -#include <stdint.h> // For intptr_t. - -#include "base/macros.h" -#include "build/build_config.h" - -// DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>). -typedef int8_t int8; -typedef uint8_t uint8; -typedef int16_t int16; -typedef uint16_t uint16; -typedef int32_t int32; -typedef uint32_t uint32; -typedef int64_t int64; -typedef uint64_t uint64; - -// DEPRECATED: Please use std::numeric_limits (from <limits>) instead. -const uint8 kuint8max = 0xFF; -const uint16 kuint16max = 0xFFFF; -const uint32 kuint32max = 0xFFFFFFFF; -const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL; -const int8 kint8min = -0x7F - 1; -const int8 kint8max = 0x7F; -const int16 kint16min = -0x7FFF - 1; -const int16 kint16max = 0x7FFF; -const int32 kint32min = -0x7FFFFFFF - 1; -const int32 kint32max = 0x7FFFFFFF; -const int64 kint64min = -0x7FFFFFFFFFFFFFFFLL - 1; -const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL; - -#endif // BASE_BASICTYPES_H_ diff --git a/third_party/chromium/base/bind.h b/third_party/chromium/base/bind.h index 51be10d..770e457 100644 --- a/third_party/chromium/base/bind.h +++ b/third_party/chromium/base/bind.h @@ -47,49 +47,34 @@ namespace base { -template <typename Functor> -base::Callback< - typename internal::BindState< - typename internal::FunctorTraits<Functor>::RunnableType, - typename internal::FunctorTraits<Functor>::RunType, - internal::TypeList<>>::UnboundRunType> -Bind(Functor functor) { - // Typedefs for how to store and run the functor. - typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; - typedef typename internal::FunctorTraits<Functor>::RunType RunType; - - typedef internal::BindState<RunnableType, RunType, - internal::TypeList<>> BindState; - - return Callback<typename BindState::UnboundRunType>( - new BindState(internal::MakeRunnable(functor))); -} - template <typename Functor, typename... Args> base::Callback< typename internal::BindState< typename internal::FunctorTraits<Functor>::RunnableType, typename internal::FunctorTraits<Functor>::RunType, - internal::TypeList< - typename internal::CallbackParamTraits<Args>::StorageType...>> + typename internal::CallbackParamTraits<Args>::StorageType...> ::UnboundRunType> Bind(Functor functor, const Args&... args) { - // Typedefs for how to store and run the functor. - typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; - typedef typename internal::FunctorTraits<Functor>::RunType RunType; + // Type aliases for how to store and run the functor. + using RunnableType = typename internal::FunctorTraits<Functor>::RunnableType; + using RunType = typename internal::FunctorTraits<Functor>::RunType; // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual + // checks below for bound references need to know what the actual // functor is going to interpret the argument as. - typedef typename RunnableType::RunType BoundRunType; + using BoundRunType = typename RunnableType::RunType; + + using BoundArgs = + internal::TakeTypeListItem<sizeof...(Args), + internal::ExtractArgs<BoundRunType>>; // Do not allow binding a non-const reference parameter. Non-const reference // parameters are disallowed by the Google style guide. Also, binding a // non-const reference parameter can make for subtle bugs because the // invoked function will receive a reference to the stored copy of the // argument and not the original. - static_assert(!internal::HasNonConstReferenceParam<BoundRunType>::value, - "do_not_bind_functions_with_nonconst_ref"); + static_assert(!internal::HasNonConstReferenceItem<BoundArgs>::value, + "do not bind functions with nonconst ref"); const bool is_method = internal::HasIsMethodTag<RunnableType>::value; @@ -98,16 +83,14 @@ Bind(Functor functor, const Args&... args) { // methods. We also disallow binding of an array as the method's target // object. static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value, - "first_bound_argument_to_method_cannot_be_array"); + "first bound argument to method cannot be array"); static_assert( !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value, - "a_parameter_is_refcounted_type_and_needs_scoped_refptr"); + "a parameter is a refcounted type and needs scoped_refptr"); - typedef internal::BindState< + using BindState = internal::BindState< RunnableType, RunType, - internal::TypeList< - typename internal::CallbackParamTraits<Args>::StorageType...>> - BindState; + typename internal::CallbackParamTraits<Args>::StorageType...>; return Callback<typename BindState::UnboundRunType>( new BindState(internal::MakeRunnable(functor), args...)); diff --git a/third_party/chromium/base/bind_helpers.h b/third_party/chromium/base/bind_helpers.h index 5044a1c..23e2cc9 100644 --- a/third_party/chromium/base/bind_helpers.h +++ b/third_party/chromium/base/bind_helpers.h @@ -111,7 +111,7 @@ // scoped_ptr<Foo> f(new Foo()); // // // |cb| is given ownership of Foo(). |f| is now NULL. -// // You can use f.Pass() in place of &f, but it's more verbose. +// // You can use std::move(f) in place of &f, but it's more verbose. // Closure cb = Bind(&TakesOwnership, Passed(&f)); // // // Run was never called so |cb| still owns Foo() and deletes @@ -143,14 +143,18 @@ #ifndef BASE_BIND_HELPERS_H_ #define BASE_BIND_HELPERS_H_ +#include <stddef.h> + #include <map> #include <memory> +#include <type_traits> +#include <utility> #include <vector> -#include "base/basictypes.h" #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/template_util.h" +#include "build/build_config.h" namespace base { namespace internal { @@ -189,7 +193,7 @@ namespace internal { // want to probe for. Then we create a class Base that inherits from both T // (the class we wish to probe) and BaseMixin. Note that the function // signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(void). +// we are probing for; thus it's easiest to just use void(). // // Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an // ambiguous resolution between BaseMixin and T. This lets us write the @@ -226,8 +230,8 @@ namespace internal { // See http://crbug.com/82038. template <typename T> class SupportsAddRefAndRelease { - typedef char Yes[1]; - typedef char No[2]; + using Yes = char[1]; + using No = char[2]; struct BaseMixin { void AddRef(); @@ -246,7 +250,7 @@ class SupportsAddRefAndRelease { #pragma warning(pop) #endif - template <void(BaseMixin::*)(void)> struct Helper {}; + template <void(BaseMixin::*)()> struct Helper {}; template <typename C> static No& Check(Helper<&C::AddRef>*); @@ -280,8 +284,8 @@ struct UnsafeBindtoRefCountedArg<T*> template <typename T> class HasIsMethodTag { - typedef char Yes[1]; - typedef char No[2]; + using Yes = char[1]; + using No = char[2]; template <typename U> static Yes& Check(typename U::IsMethod*); @@ -363,80 +367,21 @@ class OwnedWrapper { // created when we are explicitly trying to do a destructive move. // // Two notes: -// 1) PassedWrapper supports any type that has a "Pass()" function. -// This is intentional. The whitelisting of which specific types we -// support is maintained by CallbackParamTraits<>. +// 1) PassedWrapper supports any type that has a move constructor, however +// the type will need to be specifically whitelisted in order for it to be +// bound to a Callback. We guard this explicitly at the call of Passed() +// to make for clear errors. Things not given to Passed() will be forwarded +// and stored by value which will not work for general move-only types. // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" // scoper to a Callback and allow the Callback to execute once. template <typename T> class PassedWrapper { public: - explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { - } - T Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return scoper_.Pass(); - } - - private: - mutable bool is_valid_; - mutable T scoper_; -}; - -// Specialize PassedWrapper for std::unique_ptr used by base::Passed(). -// Use std::move() to transfer the data from one storage to another. -template <typename T, typename D> -class PassedWrapper<std::unique_ptr<T, D>> { - public: - explicit PassedWrapper(std::unique_ptr<T, D> scoper) - : is_valid_(true), scoper_(std::move(scoper)) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} - - std::unique_ptr<T, D> Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return std::move(scoper_); - } - - private: - mutable bool is_valid_; - mutable std::unique_ptr<T, D> scoper_; -}; - -// Specialize PassedWrapper for std::vector<std::unique_ptr<T>>. -template <typename T, typename D, typename A> -class PassedWrapper<std::vector<std::unique_ptr<T, D>, A>> { - public: - explicit PassedWrapper(std::vector<std::unique_ptr<T, D>, A> scoper) + explicit PassedWrapper(T&& scoper) : is_valid_(true), scoper_(std::move(scoper)) {} PassedWrapper(const PassedWrapper& other) : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} - - std::vector<std::unique_ptr<T, D>, A> Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return std::move(scoper_); - } - - private: - mutable bool is_valid_; - mutable std::vector<std::unique_ptr<T, D>, A> scoper_; -}; - -// Specialize PassedWrapper for std::map<K, std::unique_ptr<T>>. -template <typename K, typename T, typename D, typename C, typename A> -class PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>> { - public: - explicit PassedWrapper(std::map<K, std::unique_ptr<T, D>, C, A> scoper) - : is_valid_(true), scoper_(std::move(scoper)) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} - - std::map<K, std::unique_ptr<T, D>, C, A> Pass() const { + T Pass() const { CHECK(is_valid_); is_valid_ = false; return std::move(scoper_); @@ -444,19 +389,19 @@ class PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>> { private: mutable bool is_valid_; - mutable std::map<K, std::unique_ptr<T, D>, C, A> scoper_; + mutable T scoper_; }; // Unwrap the stored parameters for the wrappers above. template <typename T> struct UnwrapTraits { - typedef const T& ForwardType; + using ForwardType = const T&; static ForwardType Unwrap(const T& o) { return o; } }; template <typename T> struct UnwrapTraits<UnretainedWrapper<T> > { - typedef T* ForwardType; + using ForwardType = T*; static ForwardType Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } @@ -464,7 +409,7 @@ struct UnwrapTraits<UnretainedWrapper<T> > { template <typename T> struct UnwrapTraits<ConstRefWrapper<T> > { - typedef const T& ForwardType; + using ForwardType = const T&; static ForwardType Unwrap(ConstRefWrapper<T> const_ref) { return const_ref.get(); } @@ -472,19 +417,19 @@ struct UnwrapTraits<ConstRefWrapper<T> > { template <typename T> struct UnwrapTraits<scoped_refptr<T> > { - typedef T* ForwardType; + using ForwardType = T*; static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); } }; template <typename T> struct UnwrapTraits<WeakPtr<T> > { - typedef const WeakPtr<T>& ForwardType; + using ForwardType = const WeakPtr<T>&; static ForwardType Unwrap(const WeakPtr<T>& o) { return o; } }; template <typename T> struct UnwrapTraits<OwnedWrapper<T> > { - typedef T* ForwardType; + using ForwardType = T*; static ForwardType Unwrap(const OwnedWrapper<T>& o) { return o.get(); } @@ -492,7 +437,7 @@ struct UnwrapTraits<OwnedWrapper<T> > { template <typename T> struct UnwrapTraits<PassedWrapper<T> > { - typedef T ForwardType; + using ForwardType = T; static T Unwrap(PassedWrapper<T>& o) { return o.Pass(); } @@ -520,7 +465,7 @@ struct MaybeScopedRefPtr<false, T[n], Rest...> { template <typename T, typename... Rest> struct MaybeScopedRefPtr<true, T, Rest...> { - MaybeScopedRefPtr(const T& o, const Rest&...) {} + MaybeScopedRefPtr(const T& /* o */, const Rest&...) {} }; template <typename T, typename... Rest> @@ -575,25 +520,50 @@ struct DropTypeListItemImpl<n, TypeList<T, List...>> template <typename T, typename... List> struct DropTypeListItemImpl<0, TypeList<T, List...>> { - typedef TypeList<T, List...> Type; + using Type = TypeList<T, List...>; }; template <> struct DropTypeListItemImpl<0, TypeList<>> { - typedef TypeList<> Type; + using Type = TypeList<>; }; // A type-level function that drops |n| list item from given TypeList. template <size_t n, typename List> using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type; +// Used for TakeTypeListItem implementation. +template <size_t n, typename List, typename... Accum> +struct TakeTypeListItemImpl; + +// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure. +template <size_t n, typename T, typename... List, typename... Accum> +struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...> + : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {}; + +template <typename T, typename... List, typename... Accum> +struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> { + using Type = TypeList<Accum...>; +}; + +template <typename... Accum> +struct TakeTypeListItemImpl<0, TypeList<>, Accum...> { + using Type = TypeList<Accum...>; +}; + +// A type-level function that takes first |n| list item from given TypeList. +// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to +// TypeList<A, B, C>. +template <size_t n, typename List> +using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type; + // Used for ConcatTypeLists implementation. template <typename List1, typename List2> struct ConcatTypeListsImpl; template <typename... Types1, typename... Types2> struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> { - typedef TypeList<Types1..., Types2...> Type; + using Type = TypeList<Types1..., Types2...>; }; // A type-level function that concats two TypeLists. @@ -606,7 +576,9 @@ struct MakeFunctionTypeImpl; template <typename R, typename... Args> struct MakeFunctionTypeImpl<R, TypeList<Args...>> { - typedef R(Type)(Args...); + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef R Type(Args...); }; // A type-level function that constructs a function type that has |R| as its @@ -614,6 +586,20 @@ struct MakeFunctionTypeImpl<R, TypeList<Args...>> { template <typename R, typename ArgList> using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type; +// Used for ExtractArgs. +template <typename Signature> +struct ExtractArgsImpl; + +template <typename R, typename... Args> +struct ExtractArgsImpl<R(Args...)> { + using Type = TypeList<Args...>; +}; + +// A type-level function that extracts function arguments into a TypeList. +// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>. +template <typename Signature> +using ExtractArgs = typename ExtractArgsImpl<Signature>::Type; + } // namespace internal template <typename T> @@ -631,60 +617,25 @@ static inline internal::OwnedWrapper<T> Owned(T* o) { return internal::OwnedWrapper<T>(o); } -// We offer 2 syntaxes for calling Passed(). The first takes a temporary and -// is best suited for use with the return value of a function. The second -// takes a pointer to the scoper and is just syntactic sugar to avoid having -// to write Passed(scoper.Pass()). -template <typename T> -static inline internal::PassedWrapper<T> Passed(T scoper) { - return internal::PassedWrapper<T>(scoper.Pass()); +// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and +// is best suited for use with the return value of a function or other temporary +// rvalues. The second takes a pointer to the scoper and is just syntactic sugar +// to avoid having to write Passed(std::move(scoper)). +// +// Both versions of Passed() prevent T from being an lvalue reference. The first +// via use of enable_if, and the second takes a T* which will not bind to T&. +template <typename T, + typename std::enable_if<internal::IsMoveOnlyType<T>::value && + !std::is_lvalue_reference<T>::value>::type* = + nullptr> +static inline internal::PassedWrapper<T> Passed(T&& scoper) { + return internal::PassedWrapper<T>(std::move(scoper)); } -template <typename T> +template <typename T, + typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* = + nullptr> static inline internal::PassedWrapper<T> Passed(T* scoper) { - return internal::PassedWrapper<T>(scoper->Pass()); -} - -// Overload base::Passed() for std::unique_ptr<T>. -template <typename T> -static inline internal::PassedWrapper<std::unique_ptr<T>> -Passed(std::unique_ptr<T>* scoper) { - return internal::PassedWrapper<std::unique_ptr<T>>(std::move(*scoper)); -} - -template <typename T> -static inline internal::PassedWrapper<std::unique_ptr<T>> -Passed(std::unique_ptr<T> scoper) { - return internal::PassedWrapper<std::unique_ptr<T>>(std::move(scoper)); -} - -// Overload base::Passed() for std::vector<std::unique_ptr<T>>. -template <typename T, typename D, typename A> -static inline internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>> -Passed(std::vector<std::unique_ptr<T, D>, A>* scoper) { - return internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>( - std::move(*scoper)); -} - -template <typename T, typename D, typename A> -static inline internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>> -Passed(std::vector<std::unique_ptr<T, D>, A> scoper) { - return internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>( - std::move(scoper)); -} - -// Overload base::Passed() for std::map<K, std::unique_ptr<T>>. -template <typename K, typename T, typename D, typename C, typename A> -static inline internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>> -Passed(std::map<K, std::unique_ptr<T, D>, C, A>* scoper) { - return internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>( - std::move(*scoper)); -} - -template <typename K, typename T, typename D, typename C, typename A> -static inline internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>> -Passed(std::map<K, std::unique_ptr<T, D>, C, A> scoper) { - return internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>( - std::move(scoper)); + return internal::PassedWrapper<T>(std::move(*scoper)); } template <typename T> diff --git a/third_party/chromium/base/bind_internal.h b/third_party/chromium/base/bind_internal.h index 613f7a9..50c3e24 100644 --- a/third_party/chromium/base/bind_internal.h +++ b/third_party/chromium/base/bind_internal.h @@ -5,8 +5,13 @@ #ifndef BASE_BIND_INTERNAL_H_ #define BASE_BIND_INTERNAL_H_ +#include <stddef.h> + +#include <type_traits> + #include "base/bind_helpers.h" #include "base/callback_internal.h" +#include "base/memory/raw_scoped_refptr_mismatch_checker.h" #include "base/memory/weak_ptr.h" #include "base/template_util.h" #include "base/tuple.h" @@ -36,12 +41,7 @@ namespace internal { // even if the invocation syntax differs. // RunType -- A function type (as opposed to function _pointer_ type) for // a Run() function. Usually just a convenience typedef. -// (Bound)ArgsType -- A function type that is being (ab)used to store the -// types of set of arguments. The "return" type is always -// void here. We use this hack so that we do not need -// a new type name for each arity of type. (eg., -// BindState1, BindState2). This makes forward -// declarations and friending much much easier. +// (Bound)Args -- A set of types that stores the arguments. // // Types: // RunnableAdapter<> -- Wraps the various "function" pointer types into an @@ -53,7 +53,6 @@ namespace internal { // signature adapters are applied. // MakeRunnable<> -- Takes a Functor and returns an object in the Runnable // type class that represents the underlying Functor. -// There are |O(1)| MakeRunnable types. // InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. // Handle the differing syntaxes needed for WeakPtr<> // support, and for ignoring return values. This is separate @@ -68,17 +67,17 @@ namespace internal { // |Sig| is a non-const reference. // Implementation note: This non-specialized case handles zero-arity case only. // Non-zero-arity cases should be handled by the specialization below. -template <typename Sig> -struct HasNonConstReferenceParam : std::false_type {}; +template <typename List> +struct HasNonConstReferenceItem : std::false_type {}; // Implementation note: Select true_type if the first parameter is a non-const // reference. Otherwise, skip the first parameter and check rest of parameters // recursively. -template <typename R, typename T, typename... Args> -struct HasNonConstReferenceParam<R(T, Args...)> - : SelectType<is_non_const_reference<T>::value, - std::true_type, - HasNonConstReferenceParam<R(Args...)>>::Type {}; +template <typename T, typename... Args> +struct HasNonConstReferenceItem<TypeList<T, Args...>> + : std::conditional<is_non_const_reference<T>::value, + std::true_type, + HasNonConstReferenceItem<TypeList<Args...>>>::type {}; // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw // pointer to a RefCounted type. @@ -87,6 +86,15 @@ struct HasNonConstReferenceParam<R(T, Args...)> template <typename... Args> struct HasRefCountedTypeAsRawPtr : std::false_type {}; +// Implementation note: Select true_type if the first parameter is a raw pointer +// to a RefCounted type. Otherwise, skip the first parameter and check rest of +// parameters recursively. +template <typename T, typename... Args> +struct HasRefCountedTypeAsRawPtr<T, Args...> + : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value, + std::true_type, + HasRefCountedTypeAsRawPtr<Args...>>::type {}; + // BindsArrayToFirstArg selects true_type when |is_method| is true and the first // item of |Args| is an array type. // Implementation note: This non-specialized case handles !is_method case and @@ -137,7 +145,9 @@ class RunnableAdapter; template <typename R, typename... Args> class RunnableAdapter<R(*)(Args...)> { public: - typedef R (RunType)(Args...); + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef R RunType(Args...); explicit RunnableAdapter(R(*function)(Args...)) : function_(function) { @@ -155,8 +165,10 @@ class RunnableAdapter<R(*)(Args...)> { template <typename R, typename T, typename... Args> class RunnableAdapter<R(T::*)(Args...)> { public: - typedef R (RunType)(T*, Args...); - typedef std::true_type IsMethod; + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef R RunType(T*, Args...); + using IsMethod = std::true_type; explicit RunnableAdapter(R(T::*method)(Args...)) : method_(method) { @@ -174,8 +186,8 @@ class RunnableAdapter<R(T::*)(Args...)> { template <typename R, typename T, typename... Args> class RunnableAdapter<R(T::*)(Args...) const> { public: - typedef R (RunType)(const T*, Args...); - typedef std::true_type IsMethod; + using RunType = R(const T*, Args...); + using IsMethod = std::true_type; explicit RunnableAdapter(R(T::*method)(Args...) const) : method_(method) { @@ -199,7 +211,9 @@ struct ForceVoidReturn; template <typename R, typename... Args> struct ForceVoidReturn<R(Args...)> { - typedef void(RunType)(Args...); + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef void RunType(Args...); }; @@ -208,21 +222,21 @@ struct ForceVoidReturn<R(Args...)> { // See description at top of file. template <typename T> struct FunctorTraits { - typedef RunnableAdapter<T> RunnableType; - typedef typename RunnableType::RunType RunType; + using RunnableType = RunnableAdapter<T>; + using RunType = typename RunnableType::RunType; }; template <typename T> struct FunctorTraits<IgnoreResultHelper<T>> { - typedef typename FunctorTraits<T>::RunnableType RunnableType; - typedef typename ForceVoidReturn< - typename RunnableType::RunType>::RunType RunType; + using RunnableType = typename FunctorTraits<T>::RunnableType; + using RunType = + typename ForceVoidReturn<typename RunnableType::RunType>::RunType; }; template <typename T> struct FunctorTraits<Callback<T>> { - typedef Callback<T> RunnableType; - typedef typename Callback<T>::RunType RunType; + using RunnableType = Callback<T> ; + using RunType = typename Callback<T>::RunType; }; @@ -301,8 +315,8 @@ struct InvokeHelper<true, ReturnType, Runnable, ArgsType> { // WeakCalls are only supported for functions with a void return type. // Otherwise, the function result would be undefined if the the WeakPtr<> // is invalidated. - COMPILE_ASSERT(std::is_void<ReturnType>::value, - weak_ptrs_can_only_bind_to_methods_without_return_values); + static_assert(std::is_void<ReturnType>::value, + "weak_ptrs can only bind to methods without return values"); }; #endif @@ -348,19 +362,18 @@ struct Invoker<IndexSequence<bound_indices...>, // Normally, this is the same as the RunType of the Runnable, but it can // be different if an adapter like IgnoreResult() has been used. // -// BoundArgsType contains the storage type for all the bound arguments by -// (ab)using a function type. -template <typename Runnable, typename RunType, typename BoundArgList> +// BoundArgs contains the storage type for all the bound arguments. +template <typename Runnable, typename RunType, typename... BoundArgs> struct BindState; template <typename Runnable, typename R, typename... Args, typename... BoundArgs> -struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final +struct BindState<Runnable, R(Args...), BoundArgs...> final : public BindStateBase { private: - using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>; + using StorageType = BindState<Runnable, R(Args...), BoundArgs...>; using RunnableType = Runnable; // true_type if Runnable is a method invocation and the first bound argument diff --git a/third_party/chromium/base/bind_unittest.cc b/third_party/chromium/base/bind_unittest.cc index d3cc79a..f3a1211 100644 --- a/third_party/chromium/base/bind_unittest.cc +++ b/third_party/chromium/base/bind_unittest.cc @@ -4,13 +4,18 @@ #include "base/bind.h" +#include <memory> +#include <utility> + #include <gmock/gmock.h> #include <gtest/gtest.h> #include "base/callback.h" +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "build/build_config.h" using ::testing::Mock; using ::testing::Return; @@ -25,11 +30,11 @@ class NoRef { public: NoRef() {} - MOCK_METHOD0(VoidMethod0, void(void)); - MOCK_CONST_METHOD0(VoidConstMethod0, void(void)); + MOCK_METHOD0(VoidMethod0, void()); + MOCK_CONST_METHOD0(VoidConstMethod0, void()); - MOCK_METHOD0(IntMethod0, int(void)); - MOCK_CONST_METHOD0(IntConstMethod0, int(void)); + MOCK_METHOD0(IntMethod0, int()); + MOCK_CONST_METHOD0(IntConstMethod0, int()); private: // Particularly important in this test to ensure no copies are made. @@ -40,8 +45,8 @@ class HasRef : public NoRef { public: HasRef() {} - MOCK_CONST_METHOD0(AddRef, void(void)); - MOCK_CONST_METHOD0(Release, bool(void)); + MOCK_CONST_METHOD0(AddRef, void()); + MOCK_CONST_METHOD0(Release, bool()); private: // Particularly important in this test to ensure no copies are made. @@ -58,8 +63,9 @@ static const int kChildValue = 2; class Parent { public: - void AddRef(void) const {} - void Release(void) const {} + virtual ~Parent() = default; + void AddRef() const {} + void Release() const {} virtual void VirtualSet() { value = kParentValue; } void NonVirtualSet() { value = kParentValue; } int value; @@ -67,18 +73,22 @@ class Parent { class Child : public Parent { public: + ~Child() override = default; void VirtualSet() override { value = kChildValue; } void NonVirtualSet() { value = kChildValue; } }; class NoRefParent { public: + virtual ~NoRefParent() = default; virtual void VirtualSet() { value = kParentValue; } void NonVirtualSet() { value = kParentValue; } int value; }; class NoRefChild : public NoRefParent { + public: + ~NoRefChild() override = default; void VirtualSet() override { value = kChildValue; } void NonVirtualSet() { value = kChildValue; } }; @@ -151,7 +161,7 @@ class DeleteCounter { template <typename T> T PassThru(T scoper) { - return scoper.Pass(); + return scoper; } // Some test functions that we can Bind to. @@ -160,9 +170,10 @@ T PolymorphicIdentity(T t) { return t; } -template <typename T> -void VoidPolymorphic1(T t) { -} +template <typename... Ts> +struct VoidPolymorphic { + static void Run(Ts... t) {} +}; int Identity(int n) { return n; @@ -227,11 +238,11 @@ class BindTest : public ::testing::Test { virtual ~BindTest() { } - static void VoidFunc0(void) { + static void VoidFunc0() { static_func_mock_ptr->VoidMethod0(); } - static int IntFunc0(void) { return static_func_mock_ptr->IntMethod0(); } + static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); } protected: StrictMock<NoRef> no_ref_; @@ -251,7 +262,7 @@ StrictMock<NoRef>* BindTest::static_func_mock_ptr; // Sanity check that we can instantiate a callback for each arity. TEST_F(BindTest, ArityTest) { - Callback<int(void)> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1); + Callback<int()> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1); EXPECT_EQ(63, c0.Run()); Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2); @@ -293,7 +304,7 @@ TEST_F(BindTest, CurryingTest) { Callback<int(int)> c1 = Bind(c2, 2); EXPECT_EQ(75, c1.Run(13)); - Callback<int(void)> c0 = Bind(c1, 1); + Callback<int()> c0 = Bind(c1, 1); EXPECT_EQ(63, c0.Run()); } @@ -334,7 +345,7 @@ TEST_F(BindTest, FunctionTypeSupport) { EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2); Closure normal_cb = Bind(&VoidFunc0); - Callback<NoRef*(void)> normal_non_refcounted_cb = + Callback<NoRef*()> normal_non_refcounted_cb = Bind(&PolymorphicIdentity<NoRef*>, &no_ref_); normal_cb.Run(); EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run()); @@ -376,11 +387,11 @@ TEST_F(BindTest, ReturnValues) { .WillOnce(Return(41337)) .WillOnce(Return(51337)); - Callback<int(void)> normal_cb = Bind(&IntFunc0); - Callback<int(void)> method_cb = Bind(&HasRef::IntMethod0, &has_ref_); - Callback<int(void)> const_method_nonconst_obj_cb = + Callback<int()> normal_cb = Bind(&IntFunc0); + Callback<int()> method_cb = Bind(&HasRef::IntMethod0, &has_ref_); + Callback<int()> const_method_nonconst_obj_cb = Bind(&HasRef::IntConstMethod0, &has_ref_); - Callback<int(void)> const_method_const_obj_cb = + Callback<int()> const_method_const_obj_cb = Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_); EXPECT_EQ(1337, normal_cb.Run()); EXPECT_EQ(31337, method_cb.Run()); @@ -444,46 +455,46 @@ TEST_F(BindTest, IgnoreResult) { TEST_F(BindTest, ArgumentBinding) { int n = 2; - Callback<int(void)> bind_primitive_cb = Bind(&Identity, n); + Callback<int()> bind_primitive_cb = Bind(&Identity, n); EXPECT_EQ(n, bind_primitive_cb.Run()); - Callback<int*(void)> bind_primitive_pointer_cb = + Callback<int*()> bind_primitive_pointer_cb = Bind(&PolymorphicIdentity<int*>, &n); EXPECT_EQ(&n, bind_primitive_pointer_cb.Run()); - Callback<int(void)> bind_int_literal_cb = Bind(&Identity, 3); + Callback<int()> bind_int_literal_cb = Bind(&Identity, 3); EXPECT_EQ(3, bind_int_literal_cb.Run()); - Callback<const char*(void)> bind_string_literal_cb = + Callback<const char*()> bind_string_literal_cb = Bind(&CStringIdentity, "hi"); EXPECT_STREQ("hi", bind_string_literal_cb.Run()); - Callback<int(void)> bind_template_function_cb = + Callback<int()> bind_template_function_cb = Bind(&PolymorphicIdentity<int>, 4); EXPECT_EQ(4, bind_template_function_cb.Run()); NoRefParent p; p.value = 5; - Callback<int(void)> bind_object_cb = Bind(&UnwrapNoRefParent, p); + Callback<int()> bind_object_cb = Bind(&UnwrapNoRefParent, p); EXPECT_EQ(5, bind_object_cb.Run()); IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123); - Callback<IncompleteType*(void)> bind_incomplete_ptr_cb = + Callback<IncompleteType*()> bind_incomplete_ptr_cb = Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr); EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run()); NoRefChild c; c.value = 6; - Callback<int(void)> bind_promotes_cb = Bind(&UnwrapNoRefParent, c); + Callback<int()> bind_promotes_cb = Bind(&UnwrapNoRefParent, c); EXPECT_EQ(6, bind_promotes_cb.Run()); c.value = 7; - Callback<int(void)> bind_pointer_promotes_cb = + Callback<int()> bind_pointer_promotes_cb = Bind(&UnwrapNoRefParentPtr, &c); EXPECT_EQ(7, bind_pointer_promotes_cb.Run()); c.value = 8; - Callback<int(void)> bind_const_reference_promotes_cb = + Callback<int()> bind_const_reference_promotes_cb = Bind(&UnwrapNoRefParentConstRef, c); EXPECT_EQ(8, bind_const_reference_promotes_cb.Run()); } @@ -497,17 +508,20 @@ TEST_F(BindTest, ArgumentBinding) { // - Unbound sized array. // - Unbound array-of-arrays. TEST_F(BindTest, UnboundArgumentTypeSupport) { - Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic1<int>); - Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic1<int*>); - Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic1<int&>); + Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic<int>::Run); + Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic<int*>::Run); + Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic<int&>::Run); Callback<void(const int&)> unbound_const_ref_cb = - Bind(&VoidPolymorphic1<const int&>); + Bind(&VoidPolymorphic<const int&>::Run); Callback<void(int[])> unbound_unsized_array_cb = - Bind(&VoidPolymorphic1<int[]>); + Bind(&VoidPolymorphic<int[]>::Run); Callback<void(int[2])> unbound_sized_array_cb = - Bind(&VoidPolymorphic1<int[2]>); + Bind(&VoidPolymorphic<int[2]>::Run); Callback<void(int[][2])> unbound_array_of_arrays_cb = - Bind(&VoidPolymorphic1<int[][2]>); + Bind(&VoidPolymorphic<int[][2]>::Run); + + Callback<void(int&)> unbound_ref_with_bound_arg = + Bind(&VoidPolymorphic<int, int&>::Run, 1); } // Function with unbound reference parameter. @@ -527,12 +541,12 @@ TEST_F(BindTest, ReferenceArgumentBinding) { int& ref_n = n; const int& const_ref_n = n; - Callback<int(void)> ref_copies_cb = Bind(&Identity, ref_n); + Callback<int()> ref_copies_cb = Bind(&Identity, ref_n); EXPECT_EQ(n, ref_copies_cb.Run()); n++; EXPECT_EQ(n - 1, ref_copies_cb.Run()); - Callback<int(void)> const_ref_copies_cb = Bind(&Identity, const_ref_n); + Callback<int()> const_ref_copies_cb = Bind(&Identity, const_ref_n); EXPECT_EQ(n, const_ref_copies_cb.Run()); n++; EXPECT_EQ(n - 1, const_ref_copies_cb.Run()); @@ -545,10 +559,10 @@ TEST_F(BindTest, ArrayArgumentBinding) { int array[4] = {1, 1, 1, 1}; const int (*const_array_ptr)[4] = &array; - Callback<int(void)> array_cb = Bind(&ArrayGet, array, 1); + Callback<int()> array_cb = Bind(&ArrayGet, array, 1); EXPECT_EQ(1, array_cb.Run()); - Callback<int(void)> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1); + Callback<int()> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1); EXPECT_EQ(1, const_array_cb.Run()); array[1] = 3; @@ -586,15 +600,15 @@ TEST_F(BindTest, Unretained) { EXPECT_CALL(no_ref_, VoidMethod0()); EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); - Callback<void(void)> method_cb = + Callback<void()> method_cb = Bind(&NoRef::VoidMethod0, Unretained(&no_ref_)); method_cb.Run(); - Callback<void(void)> const_method_cb = + Callback<void()> const_method_cb = Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_)); const_method_cb.Run(); - Callback<void(void)> const_method_const_ptr_cb = + Callback<void()> const_method_const_ptr_cb = Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_)); const_method_const_ptr_cb.Run(); } @@ -646,8 +660,8 @@ TEST_F(BindTest, WeakPtr) { TEST_F(BindTest, ConstRef) { int n = 1; - Callback<int(void)> copy_cb = Bind(&Identity, n); - Callback<int(void)> const_ref_cb = Bind(&Identity, ConstRef(n)); + Callback<int()> copy_cb = Bind(&Identity, n); + Callback<int()> const_ref_cb = Bind(&Identity, ConstRef(n)); EXPECT_EQ(n, copy_cb.Run()); EXPECT_EQ(n, const_ref_cb.Run()); n++; @@ -657,7 +671,7 @@ TEST_F(BindTest, ConstRef) { int copies = 0; int assigns = 0; CopyCounter counter(&copies, &assigns); - Callback<int(void)> all_const_ref_cb = + Callback<int()> all_const_ref_cb = Bind(&GetCopies, ConstRef(counter)); EXPECT_EQ(0, all_const_ref_cb.Run()); EXPECT_EQ(0, copies); @@ -674,7 +688,7 @@ TEST_F(BindTest, ScopedRefptr) { const scoped_refptr<StrictMock<HasRef> > refptr(&has_ref_); - Callback<int(void)> scoped_refptr_const_ref_cb = + Callback<int()> scoped_refptr_const_ref_cb = Bind(&FunctionWithScopedRefptrFirstParam, base::ConstRef(refptr), 1); EXPECT_EQ(1, scoped_refptr_const_ref_cb.Run()); } @@ -686,7 +700,7 @@ TEST_F(BindTest, Owned) { // If we don't capture, delete happens on Callback destruction/reset. // return the same value. - Callback<DeleteCounter*(void)> no_capture_cb = + Callback<DeleteCounter*()> no_capture_cb = Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter)); ASSERT_EQ(counter, no_capture_cb.Run()); ASSERT_EQ(counter, no_capture_cb.Run()); @@ -715,7 +729,7 @@ TEST_F(BindTest, ScopedPtr) { // Tests the Passed() function's support for pointers. scoped_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes)); - Callback<scoped_ptr<DeleteCounter>(void)> unused_callback = + Callback<scoped_ptr<DeleteCounter>()> unused_callback = Bind(&PassThru<scoped_ptr<DeleteCounter> >, Passed(&ptr)); EXPECT_FALSE(ptr.get()); EXPECT_EQ(0, deletes); @@ -727,7 +741,7 @@ TEST_F(BindTest, ScopedPtr) { // Tests the Passed() function's support for rvalues. deletes = 0; DeleteCounter* counter = new DeleteCounter(&deletes); - Callback<scoped_ptr<DeleteCounter>(void)> callback = + Callback<scoped_ptr<DeleteCounter>()> callback = Bind(&PassThru<scoped_ptr<DeleteCounter> >, Passed(scoped_ptr<DeleteCounter>(counter))); EXPECT_FALSE(ptr.get()); @@ -750,7 +764,50 @@ TEST_F(BindTest, ScopedPtr) { Callback<scoped_ptr<DeleteCounter>(scoped_ptr<DeleteCounter>)> cb_unbound = Bind(&PassThru<scoped_ptr<DeleteCounter> >); ptr.reset(new DeleteCounter(&deletes)); - cb_unbound.Run(ptr.Pass()); + cb_unbound.Run(std::move(ptr)); +} + +TEST_F(BindTest, UniquePtr) { + int deletes = 0; + + // Tests the Passed() function's support for pointers. + std::unique_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes)); + Callback<std::unique_ptr<DeleteCounter>()> unused_callback = + Bind(&PassThru<std::unique_ptr<DeleteCounter>>, Passed(&ptr)); + EXPECT_FALSE(ptr.get()); + EXPECT_EQ(0, deletes); + + // If we never invoke the Callback, it retains ownership and deletes. + unused_callback.Reset(); + EXPECT_EQ(1, deletes); + + // Tests the Passed() function's support for rvalues. + deletes = 0; + DeleteCounter* counter = new DeleteCounter(&deletes); + Callback<std::unique_ptr<DeleteCounter>()> callback = + Bind(&PassThru<std::unique_ptr<DeleteCounter>>, + Passed(std::unique_ptr<DeleteCounter>(counter))); + EXPECT_FALSE(ptr.get()); + EXPECT_EQ(0, deletes); + + // Check that ownership can be transferred back out. + std::unique_ptr<DeleteCounter> result = callback.Run(); + ASSERT_EQ(counter, result.get()); + EXPECT_EQ(0, deletes); + + // Resetting does not delete since ownership was transferred. + callback.Reset(); + EXPECT_EQ(0, deletes); + + // Ensure that we actually did get ownership. + result.reset(); + EXPECT_EQ(1, deletes); + + // Test unbound argument forwarding. + Callback<std::unique_ptr<DeleteCounter>(std::unique_ptr<DeleteCounter>)> + cb_unbound = Bind(&PassThru<std::unique_ptr<DeleteCounter>>); + ptr.reset(new DeleteCounter(&deletes)); + cb_unbound.Run(std::move(ptr)); } // Argument Copy-constructor usage for non-reference parameters. @@ -764,15 +821,15 @@ TEST_F(BindTest, ArgumentCopies) { CopyCounter counter(&copies, &assigns); - Callback<void(void)> copy_cb = - Bind(&VoidPolymorphic1<CopyCounter>, counter); + Callback<void()> copy_cb = + Bind(&VoidPolymorphic<CopyCounter>::Run, counter); EXPECT_GE(1, copies); EXPECT_EQ(0, assigns); copies = 0; assigns = 0; Callback<void(CopyCounter)> forward_cb = - Bind(&VoidPolymorphic1<CopyCounter>); + Bind(&VoidPolymorphic<CopyCounter>::Run); forward_cb.Run(counter); EXPECT_GE(1, copies); EXPECT_EQ(0, assigns); @@ -781,7 +838,7 @@ TEST_F(BindTest, ArgumentCopies) { assigns = 0; DerivedCopyCounter derived(&copies, &assigns); Callback<void(CopyCounter)> coerce_cb = - Bind(&VoidPolymorphic1<CopyCounter>); + Bind(&VoidPolymorphic<CopyCounter>::Run); coerce_cb.Run(CopyCounter(derived)); EXPECT_GE(2, copies); EXPECT_EQ(0, assigns); @@ -806,10 +863,10 @@ int __stdcall StdCallFunc(int n) { // - Can bind a __fastcall function. // - Can bind a __stdcall function. TEST_F(BindTest, WindowsCallingConventions) { - Callback<int(void)> fastcall_cb = Bind(&FastCallFunc, 1); + Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1); EXPECT_EQ(1, fastcall_cb.Run()); - Callback<int(void)> stdcall_cb = Bind(&StdCallFunc, 2); + Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2); EXPECT_EQ(2, stdcall_cb.Run()); } #endif diff --git a/third_party/chromium/base/callback.h b/third_party/chromium/base/callback.h index 00669dd..3bf0008 100644 --- a/third_party/chromium/base/callback.h +++ b/third_party/chromium/base/callback.h @@ -26,7 +26,7 @@ // much like lexical closures are used in other languages. For example, it // is used in Chromium code to schedule tasks on different MessageLoops. // -// A callback with no unbound input parameters (base::Callback<void(void)>) +// A callback with no unbound input parameters (base::Callback<void()>) // is called a base::Closure. Note that this is NOT the same as what other // languages refer to as a closure -- it does not retain a reference to its // enclosing environment. @@ -48,7 +48,7 @@ // BINDING A BARE FUNCTION // // int Return5() { return 5; } -// base::Callback<int(void)> func_cb = base::Bind(&Return5); +// base::Callback<int()> func_cb = base::Bind(&Return5); // LOG(INFO) << func_cb.Run(); // Prints 5. // // BINDING A CLASS METHOD @@ -62,7 +62,7 @@ // void PrintBye() { LOG(INFO) << "bye."; } // }; // scoped_refptr<Ref> ref = new Ref(); -// base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref); +// base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref); // LOG(INFO) << ref_cb.Run(); // Prints out 3. // // By default the object must support RefCounted or you will get a compiler @@ -104,10 +104,10 @@ // calling. // // void MyFunc(int i, const std::string& str) {} -// base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world"); +// base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world"); // cb.Run(); // -// A callback with no unbound input parameters (base::Callback<void(void)>) +// A callback with no unbound input parameters (base::Callback<void()>) // is called a base::Closure. So we could have also written: // // base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); @@ -165,7 +165,7 @@ // that doesn't expect a return value. // // int DoSomething(int arg) { cout << arg << endl; } -// base::Callback<void<int>) cb = +// base::Callback<void(int)> cb = // base::Bind(base::IgnoreResult(&DoSomething)); // // @@ -175,7 +175,7 @@ // // Bound parameters are specified as arguments to Bind() and are passed to the // function. A callback with no parameters or no unbound parameters is called a -// Closure (base::Callback<void(void)> and base::Closure are the same thing). +// Closure (base::Callback<void()> and base::Closure are the same thing). // // PASSING PARAMETERS OWNED BY THE CALLBACK // @@ -354,32 +354,30 @@ namespace base { // // If you are thinking of forward declaring Callback in your own header file, // please include "base/callback_forward.h" instead. -template <typename Sig> -class Callback; namespace internal { -template <typename Runnable, typename RunType, typename BoundArgsType> +template <typename Runnable, typename RunType, typename... BoundArgsType> struct BindState; } // namespace internal template <typename R, typename... Args> class Callback<R(Args...)> : public internal::CallbackBase { public: - typedef R(RunType)(Args...); + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef R RunType(Args...); - Callback() : CallbackBase(NULL) { } + Callback() : CallbackBase(nullptr) { } - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template <typename Runnable, typename BindRunType, typename BoundArgsType> - Callback(internal::BindState<Runnable, BindRunType, - BoundArgsType>* bind_state) + template <typename Runnable, typename BindRunType, typename... BoundArgsType> + explicit Callback( + internal::BindState<Runnable, BindRunType, BoundArgsType...>* bind_state) : CallbackBase(bind_state) { // Force the assignment to a local variable of PolymorphicInvoke // so the compiler will typecheck that the passed in Run() method has // the correct type. PolymorphicInvoke invoke_func = - &internal::BindState<Runnable, BindRunType, BoundArgsType> + &internal::BindState<Runnable, BindRunType, BoundArgsType...> ::InvokerType::Run; polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); } @@ -397,15 +395,11 @@ class Callback<R(Args...)> : public internal::CallbackBase { } private: - typedef R(*PolymorphicInvoke)( - internal::BindStateBase*, - typename internal::CallbackParamTraits<Args>::ForwardType...); + using PolymorphicInvoke = + R(*)(internal::BindStateBase*, + typename internal::CallbackParamTraits<Args>::ForwardType...); }; -// Syntactic sugar to make Callback<void(void)> easier to declare since it -// will be used in a lot of APIs with delayed execution. -typedef Callback<void(void)> Closure; - } // namespace base #endif // BASE_CALLBACK_H_ diff --git a/third_party/chromium/base/callback_forward.h b/third_party/chromium/base/callback_forward.h index 262c306..a9a263a 100644 --- a/third_party/chromium/base/callback_forward.h +++ b/third_party/chromium/base/callback_forward.h @@ -10,7 +10,9 @@ namespace base { template <typename Sig> class Callback; -typedef Callback<void(void)> Closure; +// Syntactic sugar to make Callback<void()> easier to declare since it +// will be used in a lot of APIs with delayed execution. +using Closure = Callback<void()>; } // namespace base diff --git a/third_party/chromium/base/callback_internal.h b/third_party/chromium/base/callback_internal.h index 94e4f79..6339437 100644 --- a/third_party/chromium/base/callback_internal.h +++ b/third_party/chromium/base/callback_internal.h @@ -11,6 +11,7 @@ #include <stddef.h> #include <map> #include <memory> +#include <type_traits> #include <vector> #include "base/base_export.h" @@ -19,9 +20,6 @@ #include "base/memory/scoped_ptr.h" #include "base/template_util.h" -template <typename T> -class ScopedVector; - namespace base { namespace internal { class CallbackBase; @@ -76,7 +74,7 @@ class BASE_EXPORT CallbackBase { // another type. It is not okay to use void*. We create a InvokeFuncStorage // that that can store our function pointer, and then cast it back to // the original type on usage. - typedef void(*InvokeFuncStorage)(void); + using InvokeFuncStorage = void(*)(); // Returns true if this callback equals |other|. |other| may be null. bool Equals(const CallbackBase& other) const; @@ -97,8 +95,14 @@ class BASE_EXPORT CallbackBase { }; // A helper template to determine if given type is non-const move-only-type, -// i.e. if a value of the given type should be passed via .Pass() in a -// destructive way. +// i.e. if a value of the given type should be passed via std::move() in a +// destructive way. Types are considered to be move-only if they have a +// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using +// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. +// It would be easy to generalize this trait to all move-only types... but this +// confuses template deduction in VS2013 with certain types such as +// std::unique_ptr. +// TODO(dcheng): Revisit this when Windows switches to VS2015 by default. template <typename T> struct IsMoveOnlyType { template <typename U> static YesType Test(const typename U::MoveOnlyTypeForCPP03*); @@ -110,31 +114,10 @@ template <typename T> struct IsMoveOnlyType { !std::is_const<T>::value; }; -// Mark std::unique_ptr<T> and common containers using unique_ptr as MoveOnly -// type for base::Callback, so it is stored by value and not a const reference -// inside Callback. -template<typename T, typename D> -struct IsMoveOnlyType<std::unique_ptr<T, D>> : public std::true_type {}; - -template<typename T, typename D, typename A> -struct IsMoveOnlyType<std::vector<std::unique_ptr<T, D>, A>> - : public std::true_type {}; - -template<typename K, typename T, typename D, typename C, typename A> -struct IsMoveOnlyType<std::map<K, std::unique_ptr<T, D>, C, A>> - : public std::true_type {}; - -// Returns |Then| as SelectType::Type if |condition| is true. Otherwise returns -// |Else|. -template <bool condition, typename Then, typename Else> -struct SelectType { - typedef Then Type; -}; - -template <typename Then, typename Else> -struct SelectType<false, Then, Else> { - typedef Else Type; -}; +// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered +// move-only, even without the sentinel member. +template <typename T> +struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {}; template <typename> struct CallbackParamTraitsForMoveOnlyType; @@ -159,15 +142,15 @@ struct CallbackParamTraitsForNonMoveOnlyType; // break passing of C-string literals. template <typename T> struct CallbackParamTraits - : SelectType<IsMoveOnlyType<T>::value, + : std::conditional<IsMoveOnlyType<T>::value, CallbackParamTraitsForMoveOnlyType<T>, - CallbackParamTraitsForNonMoveOnlyType<T> >::Type { + CallbackParamTraitsForNonMoveOnlyType<T>>::type { }; template <typename T> struct CallbackParamTraitsForNonMoveOnlyType { - typedef const T& ForwardType; - typedef T StorageType; + using ForwardType = const T&; + using StorageType = T; }; // The Storage should almost be impossible to trigger unless someone manually @@ -177,8 +160,8 @@ struct CallbackParamTraitsForNonMoveOnlyType { // The ForwardType should only be used for unbound arguments. template <typename T> struct CallbackParamTraitsForNonMoveOnlyType<T&> { - typedef T& ForwardType; - typedef T StorageType; + using ForwardType = T&; + using StorageType = T; }; // Note that for array types, we implicitly add a const in the conversion. This @@ -188,15 +171,15 @@ struct CallbackParamTraitsForNonMoveOnlyType<T&> { // restriction. template <typename T, size_t n> struct CallbackParamTraitsForNonMoveOnlyType<T[n]> { - typedef const T* ForwardType; - typedef const T* StorageType; + using ForwardType = const T*; + using StorageType = const T*; }; // See comment for CallbackParamTraits<T[n]>. template <typename T> struct CallbackParamTraitsForNonMoveOnlyType<T[]> { - typedef const T* ForwardType; - typedef const T* StorageType; + using ForwardType = const T*; + using StorageType = const T*; }; // Parameter traits for movable-but-not-copyable scopers. @@ -214,8 +197,8 @@ struct CallbackParamTraitsForNonMoveOnlyType<T[]> { // function or a cast would not be usable with Callback<> or Bind(). template <typename T> struct CallbackParamTraitsForMoveOnlyType { - typedef T ForwardType; - typedef T StorageType; + using ForwardType = T; + using StorageType = T; }; // CallbackForward() is a very limited simulation of C++11's std::forward() @@ -227,7 +210,7 @@ struct CallbackParamTraitsForMoveOnlyType { // default template compiles out to be a no-op. // // In C++11, std::forward would replace all uses of this function. However, it -// is impossible to implement a general std::forward with C++11 due to a lack +// is impossible to implement a general std::forward without C++11 due to a lack // of rvalue references. // // In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to @@ -243,26 +226,6 @@ typename std::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward( template <typename T> typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( T& t) { - return t.Pass(); -} - -// Overload base::internal::CallbackForward() to forward unique_ptr and common -// containers with unique_ptr by using std::move instead of default T::Pass() -// used with scoped_ptr<U>. -template <typename T, typename D> -std::unique_ptr<T, D> CallbackForward(std::unique_ptr<T, D>& t) { - return std::move(t); -} - -template <typename T, typename D, typename A> -std::vector<std::unique_ptr<T, D>, A> -CallbackForward(std::vector<std::unique_ptr<T, D>, A>& t) { - return std::move(t); -} - -template <typename K, typename T, typename D, typename C, typename A> -std::map<K, std::unique_ptr<T, D>, C, A> -CallbackForward(std::map<K, std::unique_ptr<T, D>, C, A>& t) { return std::move(t); } diff --git a/third_party/chromium/base/callback_list.h b/third_party/chromium/base/callback_list.h index aeed5f1..7d6a478 100644 --- a/third_party/chromium/base/callback_list.h +++ b/third_party/chromium/base/callback_list.h @@ -7,11 +7,11 @@ #include <list> -#include "base/basictypes.h" #include "base/callback.h" #include "base/callback_internal.h" #include "base/compiler_specific.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" // OVERVIEW: @@ -185,10 +185,10 @@ class CallbackListBase { } else { ++it; } - - if (updated && !removal_callback_.is_null()) - removal_callback_.Run(); } + + if (updated && !removal_callback_.is_null()) + removal_callback_.Run(); } private: diff --git a/third_party/chromium/base/callback_list_unittest.cc b/third_party/chromium/base/callback_list_unittest.cc index 3b50622..937910e 100644 --- a/third_party/chromium/base/callback_list_unittest.cc +++ b/third_party/chromium/base/callback_list_unittest.cc @@ -5,10 +5,11 @@ #include "base/callback_list.h" #include <gtest/gtest.h> +#include <utility> -#include "base/basictypes.h" #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" namespace base { @@ -38,7 +39,7 @@ class Remover { } void SetSubscriptionToRemove( scoped_ptr<CallbackList<void(void)>::Subscription> sub) { - removal_subscription_ = sub.Pass(); + removal_subscription_ = std::move(sub); } int total() const { return total_; } @@ -99,6 +100,19 @@ class Summer { DISALLOW_COPY_AND_ASSIGN(Summer); }; +class Counter { + public: + Counter() : value_(0) {} + + void Increment() { value_++; } + + int value() const { return value_; } + + private: + int value_; + DISALLOW_COPY_AND_ASSIGN(Counter); +}; + // Sanity check that we can instantiate a CallbackList for each arity. TEST(CallbackListTest, ArityTest) { Summer s; @@ -235,9 +249,9 @@ TEST(CallbackListTest, RemoveCallbacksDuringIteration) { cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b))); // |remover_1| will remove itself. - remover_1.SetSubscriptionToRemove(remover_1_sub.Pass()); + remover_1.SetSubscriptionToRemove(std::move(remover_1_sub)); // |remover_2| will remove a. - remover_2.SetSubscriptionToRemove(a_subscription.Pass()); + remover_2.SetSubscriptionToRemove(std::move(a_subscription)); cb_reg.Notify(); @@ -288,5 +302,37 @@ TEST(CallbackListTest, EmptyList) { cb_reg.Notify(); } +TEST(CallbackList, RemovalCallback) { + Counter remove_count; + CallbackList<void(void)> cb_reg; + cb_reg.set_removal_callback( + Bind(&Counter::Increment, Unretained(&remove_count))); + + scoped_ptr<CallbackList<void(void)>::Subscription> subscription = + cb_reg.Add(Bind(&DoNothing)); + + // Removing a subscription outside of iteration signals the callback. + EXPECT_EQ(0, remove_count.value()); + subscription.reset(); + EXPECT_EQ(1, remove_count.value()); + + // Configure two subscriptions to remove themselves. + Remover remover_1, remover_2; + scoped_ptr<CallbackList<void(void)>::Subscription> remover_1_sub = + cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, + Unretained(&remover_1))); + scoped_ptr<CallbackList<void(void)>::Subscription> remover_2_sub = + cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, + Unretained(&remover_2))); + remover_1.SetSubscriptionToRemove(std::move(remover_1_sub)); + remover_2.SetSubscriptionToRemove(std::move(remover_2_sub)); + + // The callback should be signaled exactly once. + EXPECT_EQ(1, remove_count.value()); + cb_reg.Notify(); + EXPECT_EQ(2, remove_count.value()); + EXPECT_TRUE(cb_reg.empty()); +} + } // namespace } // namespace base diff --git a/third_party/chromium/base/callback_unittest.cc b/third_party/chromium/base/callback_unittest.cc index 3630176..bf9d76f 100644 --- a/third_party/chromium/base/callback_unittest.cc +++ b/third_party/chromium/base/callback_unittest.cc @@ -16,7 +16,9 @@ namespace base { namespace { struct FakeInvoker { - typedef void(RunType)(internal::BindStateBase*); + // MSVC 2013 doesn't support Type Alias of function types. + // Revisit this after we update it to newer version. + typedef void RunType(internal::BindStateBase*); static void Run(internal::BindStateBase*) { } }; @@ -24,8 +26,6 @@ struct FakeInvoker { } // namespace namespace internal { -template <typename Runnable, typename RunType, typename BoundArgsType> -struct BindState; // White-box testpoints to inject into a Callback<> object for checking // comparators and emptiness APIs. Use a BindState that is specialized @@ -33,11 +33,11 @@ struct BindState; // chance of colliding with another instantiation and breaking the // one-definition-rule. template <> -struct BindState<void(void), void(void), void(FakeInvoker)> +struct BindState<void(), void(), FakeInvoker> : public BindStateBase { public: BindState() : BindStateBase(&Destroy) {} - typedef FakeInvoker InvokerType; + using InvokerType = FakeInvoker; private: ~BindState() {} static void Destroy(BindStateBase* self) { @@ -46,12 +46,11 @@ struct BindState<void(void), void(void), void(FakeInvoker)> }; template <> -struct BindState<void(void), void(void), - void(FakeInvoker, FakeInvoker)> +struct BindState<void(), void(), FakeInvoker, FakeInvoker> : public BindStateBase { public: BindState() : BindStateBase(&Destroy) {} - typedef FakeInvoker InvokerType; + using InvokerType = FakeInvoker; private: ~BindState() {} static void Destroy(BindStateBase* self) { @@ -62,11 +61,9 @@ struct BindState<void(void), void(void), namespace { -typedef internal::BindState<void(void), void(void), void(FakeInvoker)> - FakeBindState1; -typedef internal::BindState<void(void), void(void), - void(FakeInvoker, FakeInvoker)> - FakeBindState2; +using FakeBindState1 = internal::BindState<void(), void(), FakeInvoker>; +using FakeBindState2 = + internal::BindState<void(), void(), FakeInvoker, FakeInvoker>; class CallbackTest : public ::testing::Test { public: @@ -78,15 +75,15 @@ class CallbackTest : public ::testing::Test { ~CallbackTest() override {} protected: - Callback<void(void)> callback_a_; - const Callback<void(void)> callback_b_; // Ensure APIs work with const. - Callback<void(void)> null_callback_; + Callback<void()> callback_a_; + const Callback<void()> callback_b_; // Ensure APIs work with const. + Callback<void()> null_callback_; }; // Ensure we can create unbound callbacks. We need this to be able to store // them in class members that can be initialized later. TEST_F(CallbackTest, DefaultConstruction) { - Callback<void(void)> c0; + Callback<void()> c0; Callback<void(int)> c1; Callback<void(int,int)> c2; Callback<void(int,int,int)> c3; @@ -115,13 +112,13 @@ TEST_F(CallbackTest, Equals) { EXPECT_FALSE(callback_b_.Equals(callback_a_)); // We should compare based on instance, not type. - Callback<void(void)> callback_c(new FakeBindState1()); - Callback<void(void)> callback_a2 = callback_a_; + Callback<void()> callback_c(new FakeBindState1()); + Callback<void()> callback_a2 = callback_a_; EXPECT_TRUE(callback_a_.Equals(callback_a2)); EXPECT_FALSE(callback_a_.Equals(callback_c)); // Empty, however, is always equal to empty. - Callback<void(void)> empty2; + Callback<void()> empty2; EXPECT_TRUE(null_callback_.Equals(empty2)); } diff --git a/third_party/chromium/base/compiler_specific.h b/third_party/chromium/base/compiler_specific.h index 63297dc..339e9b7 100644 --- a/third_party/chromium/base/compiler_specific.h +++ b/third_party/chromium/base/compiler_specific.h @@ -9,6 +9,9 @@ #if defined(COMPILER_MSVC) +// For _Printf_format_string_. +#include <sal.h> + // Macros for suppressing and disabling warnings on MSVC. // // Warning numbers are enumerated at: @@ -57,6 +60,7 @@ #else // Not MSVC +#define _Printf_format_string_ #define MSVC_SUPPRESS_WARNING(n) #define MSVC_PUSH_DISABLE_WARNING(n) #define MSVC_PUSH_WARNING_LEVEL(n) @@ -68,28 +72,6 @@ #endif // COMPILER_MSVC -// The C++ standard requires that static const members have an out-of-class -// definition (in a single compilation unit), but MSVC chokes on this (when -// language extensions, which are required, are enabled). (You're only likely to -// notice the need for a definition if you take the address of the member or, -// more commonly, pass it to a function that takes it as a reference argument -- -// probably an STL function.) This macro makes MSVC do the right thing. See -// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more -// information. Use like: -// -// In .h file: -// struct Foo { -// static const int kBar = 5; -// }; -// -// In .cc file: -// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar; -#if defined(COMPILER_MSVC) -#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany) -#else -#define STATIC_CONST_MEMBER_DEFINITION -#endif - // Annotate a variable indicating it's ok if the variable is not used. // (Typically used to silence a compiler warning when the assignment // is important for some other reason.) @@ -101,7 +83,7 @@ // Annotate a typedef or function indicating it's ok if it's not used. // Use like: // typedef Foo Bar ALLOW_UNUSED_TYPE; -#if defined(COMPILER_GCC) +#if defined(COMPILER_GCC) || defined(__clang__) #define ALLOW_UNUSED_TYPE __attribute__((unused)) #else #define ALLOW_UNUSED_TYPE @@ -130,7 +112,7 @@ // Return the byte alignment of the given type (available at compile time). // Use like: -// ALIGNOF(int32) // this would be 4 +// ALIGNOF(int32_t) // this would be 4 #if defined(COMPILER_MSVC) #define ALIGNOF(type) __alignof(type) #elif defined(COMPILER_GCC) @@ -140,8 +122,9 @@ // Annotate a function indicating the caller must examine the return value. // Use like: // int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>. -#if defined(COMPILER_GCC) +// To explicitly ignore a result, see |ignore_result()| in base/macros.h. +#undef WARN_UNUSED_RESULT +#if defined(COMPILER_GCC) || defined(__clang__) #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define WARN_UNUSED_RESULT diff --git a/third_party/chromium/base/guid.h b/third_party/chromium/base/guid.h index 11fd812..1bb9ab2 100644 --- a/third_party/chromium/base/guid.h +++ b/third_party/chromium/base/guid.h @@ -5,10 +5,11 @@ #ifndef BASE_GUID_H_ #define BASE_GUID_H_ +#include <stdint.h> + #include <string> #include "base/base_export.h" -#include "base/basictypes.h" #include "build/build_config.h" namespace base { @@ -21,7 +22,7 @@ std::string GenerateGUID(); #if defined(OS_POSIX) // For unit testing purposes only. Do not use outside of tests. -std::string RandomDataToGUIDString(const uint64 bytes[2]); +std::string RandomDataToGUIDString(const uint64_t bytes[2]); #endif } // namespace base diff --git a/third_party/chromium/base/guid_posix.cc b/third_party/chromium/base/guid_posix.cc index f0fedc2..ec1ca51 100644 --- a/third_party/chromium/base/guid_posix.cc +++ b/third_party/chromium/base/guid_posix.cc @@ -4,13 +4,15 @@ #include "base/guid.h" +#include <stdint.h> + #include "base/rand_util.h" #include "base/strings/stringprintf.h" namespace base { std::string GenerateGUID() { - uint64 sixteen_bytes[2] = { base::RandUint64(), base::RandUint64() }; + uint64_t sixteen_bytes[2] = {base::RandUint64(), base::RandUint64()}; // Set the GUID to version 4 as described in RFC 4122, section 4.4. // The format of GUID version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, @@ -30,7 +32,7 @@ std::string GenerateGUID() { // TODO(cmasone): Once we're comfortable this works, migrate Windows code to // use this as well. -std::string RandomDataToGUIDString(const uint64 bytes[2]) { +std::string RandomDataToGUIDString(const uint64_t bytes[2]) { return StringPrintf("%08X-%04X-%04X-%04X-%012llX", static_cast<unsigned int>(bytes[0] >> 32), static_cast<unsigned int>((bytes[0] >> 16) & 0x0000ffff), diff --git a/third_party/chromium/base/guid_unittest.cc b/third_party/chromium/base/guid_unittest.cc index 37b4edc..acbd1a2 100644 --- a/third_party/chromium/base/guid_unittest.cc +++ b/third_party/chromium/base/guid_unittest.cc @@ -4,11 +4,14 @@ #include "base/guid.h" +#include <stdint.h> + #include <limits> #include <gtest/gtest.h> #include "base/strings/string_util.h" +#include "build/build_config.h" namespace base { @@ -53,13 +56,13 @@ bool IsGUIDv4(const std::string& guid) { } // namespace TEST(GUIDTest, GUIDGeneratesAllZeroes) { - uint64 bytes[] = { 0, 0 }; + uint64_t bytes[] = {0, 0}; std::string clientid = RandomDataToGUIDString(bytes); EXPECT_EQ("00000000-0000-0000-0000-000000000000", clientid); } TEST(GUIDTest, GUIDGeneratesCorrectly) { - uint64 bytes[] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL }; + uint64_t bytes[] = {0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL}; std::string clientid = RandomDataToGUIDString(bytes); EXPECT_EQ("01234567-89AB-CDEF-FEDC-BA9876543210", clientid); } diff --git a/third_party/chromium/base/json/json_parser.cc b/third_party/chromium/base/json/json_parser.cc index 964fcd4..304a7bd 100644 --- a/third_party/chromium/base/json/json_parser.cc +++ b/third_party/chromium/base/json/json_parser.cc @@ -7,6 +7,7 @@ #include <cmath> #include "base/logging.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -23,14 +24,14 @@ namespace { const int kStackMaxDepth = 100; -const int32 kExtendedASCIIStart = 0x80; +const int32_t kExtendedASCIIStart = 0x80; // This and the class below are used to own the JSON input string for when // string tokens are stored as StringPiece instead of std::string. This // optimization avoids about 2/3rds of string memory copies. The constructor // takes ownership of the input string. The real root value is Swap()ed into // the new instance. -class DictionaryHiddenRootValue : public base::DictionaryValue { +class DictionaryHiddenRootValue : public DictionaryValue { public: DictionaryHiddenRootValue(std::string* json, Value* root) : json_(json) { DCHECK(root->IsType(Value::TYPE_DICTIONARY)); @@ -42,7 +43,7 @@ class DictionaryHiddenRootValue : public base::DictionaryValue { // First deep copy to convert JSONStringValue to std::string and swap that // copy with |other|, which contains the new contents of |this|. - scoped_ptr<base::DictionaryValue> copy(DeepCopy()); + scoped_ptr<DictionaryValue> copy(DeepCopy()); copy->Swap(other); // Then erase the contents of the current dictionary and swap in the @@ -80,7 +81,7 @@ class DictionaryHiddenRootValue : public base::DictionaryValue { DISALLOW_COPY_AND_ASSIGN(DictionaryHiddenRootValue); }; -class ListHiddenRootValue : public base::ListValue { +class ListHiddenRootValue : public ListValue { public: ListHiddenRootValue(std::string* json, Value* root) : json_(json) { DCHECK(root->IsType(Value::TYPE_LIST)); @@ -92,7 +93,7 @@ class ListHiddenRootValue : public base::ListValue { // First deep copy to convert JSONStringValue to std::string and swap that // copy with |other|, which contains the new contents of |this|. - scoped_ptr<base::ListValue> copy(DeepCopy()); + scoped_ptr<ListValue> copy(DeepCopy()); copy->Swap(other); // Then erase the contents of the current list and swap in the new contents, @@ -129,14 +130,14 @@ class ListHiddenRootValue : public base::ListValue { // A variant on StringValue that uses StringPiece instead of copying the string // into the Value. This can only be stored in a child of hidden root (above), // otherwise the referenced string will not be guaranteed to outlive it. -class JSONStringValue : public base::Value { +class JSONStringValue : public Value { public: - explicit JSONStringValue(const base::StringPiece& piece) + explicit JSONStringValue(const StringPiece& piece) : Value(TYPE_STRING), string_piece_(piece) { } - // Overridden from base::Value: + // Overridden from Value: bool GetAsString(std::string* out_value) const override { string_piece_.CopyToString(out_value); return true; @@ -152,7 +153,7 @@ class JSONStringValue : public base::Value { private: // The location in the original input stream. - base::StringPiece string_piece_; + StringPiece string_piece_; DISALLOW_COPY_AND_ASSIGN(JSONStringValue); }; @@ -222,9 +223,9 @@ Value* JSONParser::Parse(const StringPiece& input) { // <0xEF 0xBB 0xBF>, advance the start position to avoid the // ParseNextToken function mis-treating a Unicode BOM as an invalid // character and returning NULL. - if (CanConsume(3) && static_cast<uint8>(*pos_) == 0xEF && - static_cast<uint8>(*(pos_ + 1)) == 0xBB && - static_cast<uint8>(*(pos_ + 2)) == 0xBF) { + if (CanConsume(3) && static_cast<uint8_t>(*pos_) == 0xEF && + static_cast<uint8_t>(*(pos_ + 1)) == 0xBB && + static_cast<uint8_t>(*(pos_ + 2)) == 0xBF) { NextNChars(3); } @@ -269,6 +270,14 @@ std::string JSONParser::GetErrorMessage() const { JSONReader::ErrorCodeToString(error_code_)); } +int JSONParser::error_line() const { + return error_line_; +} + +int JSONParser::error_column() const { + return error_column_; +} + // StringBuilder /////////////////////////////////////////////////////////////// JSONParser::StringBuilder::StringBuilder() @@ -608,7 +617,7 @@ bool JSONParser::ConsumeStringRaw(StringBuilder* out) { StringBuilder string(NextChar()); int length = end_pos_ - start_pos_; - int32 next_char = 0; + int32_t next_char = 0; while (CanConsume(1)) { pos_ = start_pos_ + index_; // CBU8_NEXT is postcrement. @@ -769,13 +778,19 @@ bool JSONParser::DecodeUTF16(std::string* dest_string) { return false; } - uint32 code_point = CBU16_GET_SUPPLEMENTARY(code_unit16_high, - code_unit16_low); + uint32_t code_point = + CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low); + if (!IsValidCharacter(code_point)) + return false; + offset = 0; CBU8_APPEND_UNSAFE(code_unit8, offset, code_point); } else { // Not a surrogate. DCHECK(CBU16_IS_SINGLE(code_unit16_high)); + if (!IsValidCharacter(code_unit16_high)) + return false; + CBU8_APPEND_UNSAFE(code_unit8, offset, code_unit16_high); } @@ -783,9 +798,11 @@ bool JSONParser::DecodeUTF16(std::string* dest_string) { return true; } -void JSONParser::DecodeUTF8(const int32& point, StringBuilder* dest) { +void JSONParser::DecodeUTF8(const int32_t& point, StringBuilder* dest) { + DCHECK(IsValidCharacter(point)); + // Anything outside of the basic ASCII plane will need to be decoded from - // int32 to a multi-byte sequence. + // int32_t to a multi-byte sequence. if (point < kExtendedASCIIStart) { dest->Append(static_cast<char>(point)); } else { @@ -867,7 +884,7 @@ Value* JSONParser::ConsumeNumber() { return new FundamentalValue(num_int); double num_double; - if (base::StringToDouble(num_string.as_string(), &num_double) && + if (StringToDouble(num_string.as_string(), &num_double) && std::isfinite(num_double)) { return new FundamentalValue(num_double); } diff --git a/third_party/chromium/base/json/json_parser.h b/third_party/chromium/base/json/json_parser.h index c8ed0cd..fc04594 100644 --- a/third_party/chromium/base/json/json_parser.h +++ b/third_party/chromium/base/json/json_parser.h @@ -5,20 +5,22 @@ #ifndef BASE_JSON_JSON_PARSER_H_ #define BASE_JSON_JSON_PARSER_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> #include "base/base_export.h" -#include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/json/json_reader.h" +#include "base/macros.h" #include "base/strings/string_piece.h" namespace base { + class Value; -} -namespace base { namespace internal { class JSONParserTest; @@ -41,7 +43,7 @@ class JSONParserTest; // of a token, such that the next iteration of the parser will be at the byte // immediately following the token, which would likely be the first byte of the // next token. -class BASE_EXPORT_PRIVATE JSONParser { +class BASE_EXPORT JSONParser { public: explicit JSONParser(int options); ~JSONParser(); @@ -56,6 +58,14 @@ class BASE_EXPORT_PRIVATE JSONParser { // Returns the human-friendly error message. std::string GetErrorMessage() const; + // Returns the error line number if parse error happened. Otherwise always + // returns 0. + int error_line() const; + + // Returns the error column number if parse error happened. Otherwise always + // returns 0. + int error_column() const; + private: enum Token { T_OBJECT_BEGIN, // { @@ -181,7 +191,7 @@ class BASE_EXPORT_PRIVATE JSONParser { // Helper function for ConsumeStringRaw() that takes a single code point, // decodes it into UTF-8 units, and appends it to the given builder. The // point must be valid. - void DecodeUTF8(const int32& point, StringBuilder* dest); + void DecodeUTF8(const int32_t& point, StringBuilder* dest); // Assuming that the parser is wound to the start of a valid JSON number, // this parses and converts it to either an int or double value. diff --git a/third_party/chromium/base/json/json_parser_unittest.cc b/third_party/chromium/base/json/json_parser_unittest.cc index c432eee..956e277 100644 --- a/third_party/chromium/base/json/json_parser_unittest.cc +++ b/third_party/chromium/base/json/json_parser_unittest.cc @@ -4,6 +4,8 @@ #include "base/json/json_parser.h" +#include <stddef.h> + #include <gtest/gtest.h> #include "base/json/json_reader.h" @@ -204,17 +206,16 @@ TEST_F(JSONParserTest, ErrorMessages) { // Error strings should not be modified in case of success. std::string error_message; int error_code = 0; - scoped_ptr<Value> root; - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[42]", JSON_PARSE_RFC, &error_code, &error_message)); + scoped_ptr<Value> root = JSONReader::ReadAndReturnError( + "[42]", JSON_PARSE_RFC, &error_code, &error_message); EXPECT_TRUE(error_message.empty()); EXPECT_EQ(0, error_code); // Test line and column counting const char big_json[] = "[\n0,\n1,\n2,\n3,4,5,6 7,\n8,\n9\n]"; // error here ----------------------------------^ - root.reset(JSONReader::DeprecatedReadAndReturnError( - big_json, JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError(big_json, JSON_PARSE_RFC, &error_code, + &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(5, 10, JSONReader::kSyntaxError), error_message); @@ -226,16 +227,16 @@ TEST_F(JSONParserTest, ErrorMessages) { const char big_json_crlf[] = "[\r\n0,\r\n1,\r\n2,\r\n3,4,5,6 7,\r\n8,\r\n9\r\n]"; // error here ----------------------^ - root.reset(JSONReader::DeprecatedReadAndReturnError( - big_json_crlf, JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError(big_json_crlf, JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(5, 10, JSONReader::kSyntaxError), error_message); EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code); // Test each of the error conditions - root.reset(JSONReader::DeprecatedReadAndReturnError( - "{},{}", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("{},{}", JSON_PARSE_RFC, &error_code, + &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 3, JSONReader::kUnexpectedDataAfterRoot), error_message); @@ -246,56 +247,56 @@ TEST_F(JSONParserTest, ErrorMessages) { nested_json.insert(nested_json.begin(), '['); nested_json.append(1, ']'); } - root.reset(JSONReader::DeprecatedReadAndReturnError( - nested_json, JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError(nested_json, JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 100, JSONReader::kTooMuchNesting), error_message); EXPECT_EQ(JSONReader::JSON_TOO_MUCH_NESTING, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[1,]", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("[1,]", JSON_PARSE_RFC, &error_code, + &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 4, JSONReader::kTrailingComma), error_message); EXPECT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "{foo:\"bar\"}", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("{foo:\"bar\"}", JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2, JSONReader::kUnquotedDictionaryKey), error_message); EXPECT_EQ(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "{\"foo\":\"bar\",}", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("{\"foo\":\"bar\",}", JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 14, JSONReader::kTrailingComma), error_message); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[nu]", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("[nu]", JSON_PARSE_RFC, &error_code, + &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2, JSONReader::kSyntaxError), error_message); EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[\"xxx\\xq\"]", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("[\"xxx\\xq\"]", JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape), error_message); EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[\"xxx\\uq\"]", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("[\"xxx\\uq\"]", JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape), error_message); EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code); - root.reset(JSONReader::DeprecatedReadAndReturnError( - "[\"xxx\\q\"]", JSON_PARSE_RFC, &error_code, &error_message)); + root = JSONReader::ReadAndReturnError("[\"xxx\\q\"]", JSON_PARSE_RFC, + &error_code, &error_message); EXPECT_FALSE(root.get()); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape), error_message); @@ -309,10 +310,18 @@ TEST_F(JSONParserTest, Decode4ByteUtf8Char) { "[\"😇\",[],[],[],{\"google:suggesttype\":[]}]"; std::string error_message; int error_code = 0; - scoped_ptr<Value> root(JSONReader::DeprecatedReadAndReturnError( - kUtf8Data, JSON_PARSE_RFC, &error_code, &error_message)); + scoped_ptr<Value> root = JSONReader::ReadAndReturnError( + kUtf8Data, JSON_PARSE_RFC, &error_code, &error_message); EXPECT_TRUE(root.get()) << error_message; } +TEST_F(JSONParserTest, DecodeUnicodeNonCharacter) { + // Tests Unicode code points (encoded as escaped UTF-16) that are not valid + // characters. + EXPECT_FALSE(JSONReader::Read("[\"\\ufdd0\"]")); + EXPECT_FALSE(JSONReader::Read("[\"\\ufffe\"]")); + EXPECT_FALSE(JSONReader::Read("[\"\\ud83f\\udffe\"]")); +} + } // namespace internal } // namespace base diff --git a/third_party/chromium/base/json/json_reader.cc b/third_party/chromium/base/json/json_reader.cc index edff8dc..3ab5f75 100644 --- a/third_party/chromium/base/json/json_reader.cc +++ b/third_party/chromium/base/json/json_reader.cc @@ -11,8 +11,8 @@ namespace base { // Values 1000 and above are used by JSONFileValueSerializer::JsonFileError. -COMPILE_ASSERT(JSONReader::JSON_PARSE_ERROR_COUNT < 1000, - json_reader_error_out_of_bounds); +static_assert(JSONReader::JSON_PARSE_ERROR_COUNT < 1000, + "JSONReader error out of bounds"); const char JSONReader::kInvalidEscape[] = "Invalid escape sequence."; @@ -43,41 +43,25 @@ JSONReader::~JSONReader() { } // static -Value* JSONReader::DeprecatedRead(const std::string& json) { - return Read(json).release(); -} - -// static -scoped_ptr<Value> JSONReader::Read(const std::string& json) { +scoped_ptr<Value> JSONReader::Read(const StringPiece& json) { internal::JSONParser parser(JSON_PARSE_RFC); return make_scoped_ptr(parser.Parse(json)); } // static -Value* JSONReader::DeprecatedRead(const std::string& json, int options) { - return Read(json, options).release(); -} - -// static -scoped_ptr<Value> JSONReader::Read(const std::string& json, int options) { +scoped_ptr<Value> JSONReader::Read(const StringPiece& json, int options) { internal::JSONParser parser(options); return make_scoped_ptr(parser.Parse(json)); } -// static -Value* JSONReader::DeprecatedReadAndReturnError(const std::string& json, - int options, - int* error_code_out, - std::string* error_msg_out) { - return ReadAndReturnError(json, options, error_code_out, error_msg_out) - .release(); -} // static -scoped_ptr<Value> JSONReader::ReadAndReturnError(const std::string& json, +scoped_ptr<Value> JSONReader::ReadAndReturnError(const StringPiece& json, int options, int* error_code_out, - std::string* error_msg_out) { + std::string* error_msg_out, + int* error_line_out, + int* error_column_out) { internal::JSONParser parser(options); scoped_ptr<Value> root(parser.Parse(json)); if (!root) { @@ -85,6 +69,10 @@ scoped_ptr<Value> JSONReader::ReadAndReturnError(const std::string& json, *error_code_out = parser.error_code(); if (error_msg_out) *error_msg_out = parser.GetErrorMessage(); + if (error_line_out) + *error_line_out = parser.error_line(); + if (error_column_out) + *error_column_out = parser.error_column(); } return root; diff --git a/third_party/chromium/base/json/json_reader.h b/third_party/chromium/base/json/json_reader.h index e177ab8..c6bcb52 100644 --- a/third_party/chromium/base/json/json_reader.h +++ b/third_party/chromium/base/json/json_reader.h @@ -31,8 +31,8 @@ #include <string> #include "base/base_export.h" -#include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" namespace base { @@ -93,30 +93,23 @@ class BASE_EXPORT JSONReader { // Reads and parses |json|, returning a Value. The caller owns the returned // instance. If |json| is not a properly formed JSON string, returns NULL. - static scoped_ptr<Value> Read(const std::string& json); - // TODO(estade): remove this bare pointer version. - static Value* DeprecatedRead(const std::string& json); + static scoped_ptr<Value> Read(const StringPiece& json); // Reads and parses |json|, returning a Value owned by the caller. The // parser respects the given |options|. If the input is not properly formed, // returns NULL. - static scoped_ptr<Value> Read(const std::string& json, int options); - // TODO(estade): remove this bare pointer version. - static Value* DeprecatedRead(const std::string& json, int options); + static scoped_ptr<Value> Read(const StringPiece& json, int options); // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out| // are optional. If specified and NULL is returned, they will be populated // an error code and a formatted error message (including error location if // appropriate). Otherwise, they will be unmodified. - static scoped_ptr<Value> ReadAndReturnError(const std::string& json, + static scoped_ptr<Value> ReadAndReturnError(const StringPiece& json, int options, // JSONParserOptions int* error_code_out, - std::string* error_msg_out); - // TODO(estade): remove this bare pointer version. - static Value* DeprecatedReadAndReturnError(const std::string& json, - int options, // JSONParserOptions - int* error_code_out, - std::string* error_msg_out); + std::string* error_msg_out, + int* error_line_out = nullptr, + int* error_column_out = nullptr); // Converts a JSON parse error code into a human readable message. // Returns an empty string if error_code is JSON_NO_ERROR. diff --git a/third_party/chromium/base/json/json_reader_unittest.cc b/third_party/chromium/base/json/json_reader_unittest.cc index 35becef..2bfd10e 100644 --- a/third_party/chromium/base/json/json_reader_unittest.cc +++ b/third_party/chromium/base/json/json_reader_unittest.cc @@ -4,9 +4,12 @@ #include "base/json/json_reader.h" +#include <stddef.h> + #include <gtest/gtest.h> #include "base/logging.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversion_utils.h" @@ -17,8 +20,7 @@ namespace base { TEST(JSONReaderTest, Reading) { // some whitespace checking - scoped_ptr<Value> root; - root = JSONReader().ReadToValue(" null "); + scoped_ptr<Value> root = JSONReader().ReadToValue(" null "); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_NULL)); @@ -240,61 +242,56 @@ TEST(JSONReaderTest, Reading) { EXPECT_FALSE(root.get()); // Basic array - root.reset(JSONReader::DeprecatedRead("[true, false, null]")); + root = JSONReader::Read("[true, false, null]"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_LIST)); list = static_cast<ListValue*>(root.get()); EXPECT_EQ(3U, list->GetSize()); // Test with trailing comma. Should be parsed the same as above. - scoped_ptr<Value> root2; - root2.reset(JSONReader::DeprecatedRead("[true, false, null, ]", - JSON_ALLOW_TRAILING_COMMAS)); + scoped_ptr<Value> root2 = + JSONReader::Read("[true, false, null, ]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_TRUE(root->Equals(root2.get())); // Empty array - root.reset(JSONReader::DeprecatedRead("[]")); + root = JSONReader::Read("[]"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_LIST)); list = static_cast<ListValue*>(root.get()); EXPECT_EQ(0U, list->GetSize()); // Nested arrays - root.reset( - JSONReader::DeprecatedRead("[[true], [], [false, [], [null]], null]")); + root = JSONReader::Read("[[true], [], [false, [], [null]], null]"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_LIST)); list = static_cast<ListValue*>(root.get()); EXPECT_EQ(4U, list->GetSize()); // Lots of trailing commas. - root2.reset(JSONReader::DeprecatedRead( - "[[true], [], [false, [], [null, ] , ], null,]", - JSON_ALLOW_TRAILING_COMMAS)); + root2 = JSONReader::Read("[[true], [], [false, [], [null, ] , ], null,]", + JSON_ALLOW_TRAILING_COMMAS); EXPECT_TRUE(root->Equals(root2.get())); // Invalid, missing close brace. - root.reset( - JSONReader::DeprecatedRead("[[true], [], [false, [], [null]], null")); + root = JSONReader::Read("[[true], [], [false, [], [null]], null"); EXPECT_FALSE(root.get()); // Invalid, too many commas - root.reset(JSONReader::DeprecatedRead("[true,, null]")); + root = JSONReader::Read("[true,, null]"); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("[true,, null]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[true,, null]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); // Invalid, no commas - root.reset(JSONReader::DeprecatedRead("[true null]")); + root = JSONReader::Read("[true null]"); EXPECT_FALSE(root.get()); // Invalid, trailing comma - root.reset(JSONReader::DeprecatedRead("[true,]")); + root = JSONReader::Read("[true,]"); EXPECT_FALSE(root.get()); // Valid if we set |allow_trailing_comma| to true. - root.reset(JSONReader::DeprecatedRead("[true,]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[true,]", JSON_ALLOW_TRAILING_COMMAS); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_LIST)); list = static_cast<ListValue*>(root.get()); @@ -308,25 +305,22 @@ TEST(JSONReaderTest, Reading) { // Don't allow empty elements, even if |allow_trailing_comma| is // true. - root.reset(JSONReader::DeprecatedRead("[,]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[,]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("[true,,]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[true,,]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("[,true,]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[,true,]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("[true,,false]", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("[true,,false]", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); // Test objects - root.reset(JSONReader::DeprecatedRead("{}")); + root = JSONReader::Read("{}"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); - root.reset(JSONReader::DeprecatedRead( - "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }")); + root = JSONReader::Read( + "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); DictionaryValue* dict_val = static_cast<DictionaryValue*>(root.get()); @@ -340,36 +334,36 @@ TEST(JSONReaderTest, Reading) { EXPECT_TRUE(dict_val->GetString("S", &str_val)); EXPECT_EQ("str", str_val); - root2.reset(JSONReader::DeprecatedRead( + root2 = JSONReader::Read( "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", - JSON_ALLOW_TRAILING_COMMAS)); + JSON_ALLOW_TRAILING_COMMAS); ASSERT_TRUE(root2.get()); EXPECT_TRUE(root->Equals(root2.get())); // Test newline equivalence. - root2.reset(JSONReader::DeprecatedRead( + root2 = JSONReader::Read( "{\n" " \"number\":9.87654321,\n" " \"null\":null,\n" " \"\\x53\":\"str\",\n" "}\n", - JSON_ALLOW_TRAILING_COMMAS)); + JSON_ALLOW_TRAILING_COMMAS); ASSERT_TRUE(root2.get()); EXPECT_TRUE(root->Equals(root2.get())); - root2.reset(JSONReader::DeprecatedRead( + root2 = JSONReader::Read( "{\r\n" " \"number\":9.87654321,\r\n" " \"null\":null,\r\n" " \"\\x53\":\"str\",\r\n" "}\r\n", - JSON_ALLOW_TRAILING_COMMAS)); + JSON_ALLOW_TRAILING_COMMAS); ASSERT_TRUE(root2.get()); EXPECT_TRUE(root->Equals(root2.get())); // Test nesting - root.reset(JSONReader::DeprecatedRead( - "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}")); + root = JSONReader::Read( + "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); dict_val = static_cast<DictionaryValue*>(root.get()); @@ -384,14 +378,13 @@ TEST(JSONReaderTest, Reading) { inner_dict = NULL; EXPECT_TRUE(dict_val->GetDictionary("d", &inner_dict)); - root2.reset(JSONReader::DeprecatedRead( + root2 = JSONReader::Read( "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", - JSON_ALLOW_TRAILING_COMMAS)); + JSON_ALLOW_TRAILING_COMMAS); EXPECT_TRUE(root->Equals(root2.get())); // Test keys with periods - root.reset(JSONReader::DeprecatedRead( - "{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}")); + root = JSONReader::Read("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); dict_val = static_cast<DictionaryValue*>(root.get()); @@ -408,7 +401,7 @@ TEST(JSONReaderTest, Reading) { &integer_value)); EXPECT_EQ(1, integer_value); - root.reset(JSONReader::DeprecatedRead("{\"a\":{\"b\":2},\"a.b\":1}")); + root = JSONReader::Read("{\"a\":{\"b\":2},\"a.b\":1}"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); dict_val = static_cast<DictionaryValue*>(root.get()); @@ -418,47 +411,45 @@ TEST(JSONReaderTest, Reading) { EXPECT_EQ(1, integer_value); // Invalid, no closing brace - root.reset(JSONReader::DeprecatedRead("{\"a\": true")); + root = JSONReader::Read("{\"a\": true"); EXPECT_FALSE(root.get()); // Invalid, keys must be quoted - root.reset(JSONReader::DeprecatedRead("{foo:true}")); + root = JSONReader::Read("{foo:true}"); EXPECT_FALSE(root.get()); // Invalid, trailing comma - root.reset(JSONReader::DeprecatedRead("{\"a\":true,}")); + root = JSONReader::Read("{\"a\":true,}"); EXPECT_FALSE(root.get()); // Invalid, too many commas - root.reset(JSONReader::DeprecatedRead("{\"a\":true,,\"b\":false}")); + root = JSONReader::Read("{\"a\":true,,\"b\":false}"); EXPECT_FALSE(root.get()); - root.reset(JSONReader::DeprecatedRead("{\"a\":true,,\"b\":false}", - JSON_ALLOW_TRAILING_COMMAS)); + root = + JSONReader::Read("{\"a\":true,,\"b\":false}", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); // Invalid, no separator - root.reset(JSONReader::DeprecatedRead("{\"a\" \"b\"}")); + root = JSONReader::Read("{\"a\" \"b\"}"); EXPECT_FALSE(root.get()); // Invalid, lone comma. - root.reset(JSONReader::DeprecatedRead("{,}")); + root = JSONReader::Read("{,}"); EXPECT_FALSE(root.get()); - root.reset(JSONReader::DeprecatedRead("{,}", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("{,}", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("{\"a\":true,,}", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("{\"a\":true,,}", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset( - JSONReader::DeprecatedRead("{,\"a\":true}", JSON_ALLOW_TRAILING_COMMAS)); + root = JSONReader::Read("{,\"a\":true}", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); - root.reset(JSONReader::DeprecatedRead("{\"a\":true,,\"b\":false}", - JSON_ALLOW_TRAILING_COMMAS)); + root = + JSONReader::Read("{\"a\":true,,\"b\":false}", JSON_ALLOW_TRAILING_COMMAS); EXPECT_FALSE(root.get()); // Test stack overflow std::string evil(1000000, '['); evil.append(std::string(1000000, ']')); - root.reset(JSONReader::DeprecatedRead(evil)); + root = JSONReader::Read(evil); EXPECT_FALSE(root.get()); // A few thousand adjacent lists is fine. @@ -468,7 +459,7 @@ TEST(JSONReaderTest, Reading) { not_evil.append("[],"); } not_evil.append("[]]"); - root.reset(JSONReader::DeprecatedRead(not_evil)); + root = JSONReader::Read(not_evil); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->IsType(Value::TYPE_LIST)); list = static_cast<ListValue*>(root.get()); @@ -530,20 +521,20 @@ TEST(JSONReaderTest, Reading) { } // Test literal root objects. - root.reset(JSONReader::DeprecatedRead("null")); + root = JSONReader::Read("null"); EXPECT_TRUE(root->IsType(Value::TYPE_NULL)); - root.reset(JSONReader::DeprecatedRead("true")); + root = JSONReader::Read("true"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->GetAsBoolean(&bool_value)); EXPECT_TRUE(bool_value); - root.reset(JSONReader::DeprecatedRead("10")); + root = JSONReader::Read("10"); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->GetAsInteger(&integer_value)); EXPECT_EQ(10, integer_value); - root.reset(JSONReader::DeprecatedRead("\"root\"")); + root = JSONReader::Read("\"root\""); ASSERT_TRUE(root.get()); EXPECT_TRUE(root->GetAsString(&str_val)); EXPECT_EQ("root", str_val); diff --git a/third_party/chromium/base/json/json_writer.cc b/third_party/chromium/base/json/json_writer.cc index 8bf4c6f..be19c93 100644 --- a/third_party/chromium/base/json/json_writer.cc +++ b/third_party/chromium/base/json/json_writer.cc @@ -4,13 +4,17 @@ #include "base/json/json_writer.h" +#include <stdint.h> + #include <cmath> +#include <limits> #include "base/json/string_escape.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/values.h" +#include "build/build_config.h" namespace base { @@ -79,10 +83,10 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { bool result = node.GetAsDouble(&value); DCHECK(result); if (omit_double_type_preservation_ && - value <= kint64max && - value >= kint64min && + value <= std::numeric_limits<int64_t>::max() && + value >= std::numeric_limits<int64_t>::min() && std::floor(value) == value) { - json_string_->append(Int64ToString(static_cast<int64>(value))); + json_string_->append(Int64ToString(static_cast<int64_t>(value))); return result; } std::string real = DoubleToString(value); diff --git a/third_party/chromium/base/json/json_writer.h b/third_party/chromium/base/json/json_writer.h index 5711665..ef43341 100644 --- a/third_party/chromium/base/json/json_writer.h +++ b/third_party/chromium/base/json/json_writer.h @@ -5,10 +5,12 @@ #ifndef BASE_JSON_JSON_WRITER_H_ #define BASE_JSON_JSON_WRITER_H_ +#include <stddef.h> + #include <string> #include "base/base_export.h" -#include "base/basictypes.h" +#include "base/macros.h" namespace base { diff --git a/third_party/chromium/base/json/json_writer_unittest.cc b/third_party/chromium/base/json/json_writer_unittest.cc index cb88cde..ca99f4d 100644 --- a/third_party/chromium/base/json/json_writer_unittest.cc +++ b/third_party/chromium/base/json/json_writer_unittest.cc @@ -7,6 +7,7 @@ #include <gtest/gtest.h> #include "base/values.h" +#include "build/build_config.h" namespace base { @@ -59,10 +60,10 @@ TEST(JSONWriterTest, NestedTypes) { scoped_ptr<ListValue> list(new ListValue()); scoped_ptr<DictionaryValue> inner_dict(new DictionaryValue()); inner_dict->SetInteger("inner int", 10); - list->Append(inner_dict.Pass()); + list->Append(std::move(inner_dict)); list->Append(make_scoped_ptr(new ListValue())); list->AppendBoolean(true); - root_dict.Set("list", list.Pass()); + root_dict.Set("list", std::move(list)); // Test the pretty-printer. EXPECT_TRUE(JSONWriter::Write(root_dict, &output_js)); @@ -94,7 +95,7 @@ TEST(JSONWriterTest, KeysWithPeriods) { period_dict.SetIntegerWithoutPathExpansion("c", 2); scoped_ptr<DictionaryValue> period_dict2(new DictionaryValue()); period_dict2->SetIntegerWithoutPathExpansion("g.h.i.j", 1); - period_dict.SetWithoutPathExpansion("d.e.f", period_dict2.Pass()); + period_dict.SetWithoutPathExpansion("d.e.f", std::move(period_dict2)); EXPECT_TRUE(JSONWriter::Write(period_dict, &output_js)); EXPECT_EQ("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", output_js); diff --git a/third_party/chromium/base/json/string_escape.cc b/third_party/chromium/base/json/string_escape.cc index 7ba612f..a5a38df 100644 --- a/third_party/chromium/base/json/string_escape.cc +++ b/third_party/chromium/base/json/string_escape.cc @@ -4,6 +4,10 @@ #include "base/json/string_escape.h" +#include <stddef.h> +#include <stdint.h> + +#include <limits> #include <string> #include "base/logging.h" @@ -20,15 +24,15 @@ namespace { const char kU16EscapeFormat[] = "\\u%04X"; // The code point to output for an invalid input code unit. -const uint32 kReplacementCodePoint = 0xFFFD; +const uint32_t kReplacementCodePoint = 0xFFFD; // Used below in EscapeSpecialCodePoint(). -COMPILE_ASSERT('<' == 0x3C, less_than_sign_is_0x3c); +static_assert('<' == 0x3C, "less than sign must be 0x3c"); // Try to escape the |code_point| if it is a known special character. If // successful, returns true and appends the escape sequence to |dest|. This // isn't required by the spec, but it's more readable by humans. -bool EscapeSpecialCodePoint(uint32 code_point, std::string* dest) { +bool EscapeSpecialCodePoint(uint32_t code_point, std::string* dest) { // WARNING: if you add a new case here, you need to update the reader as well. // Note: \v is in the reader, but not here since the JSON spec doesn't // allow it. @@ -59,6 +63,14 @@ bool EscapeSpecialCodePoint(uint32 code_point, std::string* dest) { case '<': dest->append("\\u003C"); break; + // Escape the "Line Separator" and "Paragraph Separator" characters, since + // they should be treated like a new line \r or \n. + case 0x2028: + dest->append("\\u2028"); + break; + case 0x2029: + dest->append("\\u2029"); + break; default: return false; } @@ -72,12 +84,13 @@ bool EscapeJSONStringImpl(const S& str, bool put_in_quotes, std::string* dest) { if (put_in_quotes) dest->push_back('"'); - // Casting is necessary because ICU uses int32. Try and do so safely. - CHECK_LE(str.length(), static_cast<size_t>(kint32max)); - const int32 length = static_cast<int32>(str.length()); + // Casting is necessary because ICU uses int32_t. Try and do so safely. + CHECK_LE(str.length(), + static_cast<size_t>(std::numeric_limits<int32_t>::max())); + const int32_t length = static_cast<int32_t>(str.length()); - for (int32 i = 0; i < length; ++i) { - uint32 code_point; + for (int32_t i = 0; i < length; ++i) { + uint32_t code_point; if (!ReadUnicodeCharacter(str.data(), length, &i, &code_point)) { code_point = kReplacementCodePoint; did_replacement = true; diff --git a/third_party/chromium/base/json/string_escape_unittest.cc b/third_party/chromium/base/json/string_escape_unittest.cc index 615acc4..586c1e7 100644 --- a/third_party/chromium/base/json/string_escape_unittest.cc +++ b/third_party/chromium/base/json/string_escape_unittest.cc @@ -5,7 +5,9 @@ #include "base/json/string_escape.h" #include <gtest/gtest.h> +#include <stddef.h> +#include "base/macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversion_utils.h" @@ -22,6 +24,8 @@ TEST(JSONStringEscapeTest, EscapeUTF8) { {"b\x0f\x7f\xf0\xff!", // \xf0\xff is not a valid UTF-8 unit. "b\\u000F\x7F\xEF\xBF\xBD\xEF\xBF\xBD!"}, {"c<>d", "c\\u003C>d"}, + {"Hello\xe2\x80\xa8world", "Hello\\u2028world"}, + {"\xe2\x80\xa9purple", "\\u2029purple"}, }; for (size_t i = 0; i < arraysize(cases); ++i) { diff --git a/third_party/chromium/base/location.h b/third_party/chromium/base/location.h index 4a38264..67a0dfd 100644 --- a/third_party/chromium/base/location.h +++ b/third_party/chromium/base/location.h @@ -5,11 +5,12 @@ #ifndef BASE_LOCATION_H_ #define BASE_LOCATION_H_ +#include <stddef.h> + #include <cassert> #include <string> #include "base/base_export.h" -#include "base/basictypes.h" namespace tracked_objects { diff --git a/third_party/chromium/base/logging.cc b/third_party/chromium/base/logging.cc index 1fd047f..6306f47 100644 --- a/third_party/chromium/base/logging.cc +++ b/third_party/chromium/base/logging.cc @@ -11,6 +11,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <unistd.h> #include <algorithm> @@ -79,6 +80,17 @@ int GetMinLogLevel() { return g_min_log_level; } +bool ShouldCreateLogMessage(int severity) { + if (severity < g_min_log_level) + return false; + + // Return true here unless we know ~LogMessage won't do anything. Note that + // ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even + // when g_logging_destination is LOG_NONE. + return g_logging_destination != LOG_NONE || log_message_handler || + severity >= kAlwaysPrintErrorLevel; +} + int GetVlogVerbosity() { return std::max(-1, LOG_INFO - GetMinLogLevel()); } @@ -121,6 +133,12 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity) Init(file, line); } +LogMessage::LogMessage(const char* file, int line, const char* condition) + : severity_(LOG_FATAL), file_(file), line_(line) { + Init(file, line); + stream_ << "Check failed: " << condition << ". "; +} + LogMessage::LogMessage(const char* file, int line, std::string* result) : severity_(LOG_FATAL), file_(file), line_(line) { Init(file, line); @@ -187,7 +205,8 @@ void LogMessage::Init(const char* file, int line) { stream_ << '['; if (g_log_timestamp) { time_t t = time(nullptr); - struct tm local_time = {0}; + struct tm local_time; + memset(&local_time, 0, sizeof(local_time)); #ifdef _MSC_VER localtime_s(&local_time, &t); #else diff --git a/third_party/chromium/base/logging.h b/third_party/chromium/base/logging.h index 339f8a6..ee10ae2 100644 --- a/third_party/chromium/base/logging.h +++ b/third_party/chromium/base/logging.h @@ -5,13 +5,16 @@ #ifndef BASE_LOGGING_H_ #define BASE_LOGGING_H_ +#include <stddef.h> + #include <cassert> -#include <string> #include <cstring> #include <sstream> +#include <string> +#include <typeinfo> #include "base/base_export.h" -#include "base/basictypes.h" +#include "base/macros.h" #include "build/build_config.h" // @@ -122,6 +125,34 @@ // There is the special severity of DFATAL, which logs FATAL in debug mode, // ERROR in normal mode. +// Note that "The behavior of a C++ program is undefined if it adds declarations +// or definitions to namespace std or to a namespace within namespace std unless +// otherwise specified." --C++11[namespace.std] +// +// We've checked that this particular definition has the intended behavior on +// our implementations, but it's prone to breaking in the future, and please +// don't imitate this in your own definitions without checking with some +// standard library experts. +namespace std { +// These functions are provided as a convenience for logging, which is where we +// use streams (it is against Google style to use streams in other places). It +// is designed to allow you to emit non-ASCII Unicode strings to the log file, +// which is normally ASCII. It is relatively slow, so try not to use it for +// common cases. Non-ASCII characters will be converted to UTF-8 by these +// operators. +BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); +inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { + return out << wstr.c_str(); +} + +template<typename T> +typename std::enable_if<std::is_enum<T>::value, std::ostream&>::type operator<<( + std::ostream& out, T value) { + return out << static_cast<typename std::underlying_type<T>::type>(value); +} + +} // namespace std + namespace logging { // Where to record logging output? A flat file and/or system debug log @@ -188,6 +219,9 @@ BASE_EXPORT void SetMinLogLevel(int level); // Gets the current log level. BASE_EXPORT int GetMinLogLevel(); +// Used by LOG_IS_ON to lazy-evaluate stream arguments. +BASE_EXPORT bool ShouldCreateLogMessage(int severity); + // Gets the VLOG default verbosity level. BASE_EXPORT int GetVlogVerbosity(); @@ -280,7 +314,7 @@ const LogSeverity LOG_DFATAL = LOG_FATAL; // LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will // always fire if they fail. #define LOG_IS_ON(severity) \ - ((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel()) + (::logging::ShouldCreateLogMessage(::logging::LOG_##severity)) // We can't do any caching tricks with VLOG_IS_ON() like the // google-glog version since it requires GCC extensions. This means @@ -331,6 +365,21 @@ const LogSeverity LOG_DFATAL = LOG_FATAL; #define EAT_STREAM_PARAMETERS \ true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL) +// Captures the result of a CHECK_EQ (for example) and facilitates testing as a +// boolean. +class CheckOpResult { + public: + // |message| must be null if and only if the check failed. + CheckOpResult(std::string* message) : message_(message) {} + // Returns true if the check succeeded. + operator bool() const { return !message_; } + // Returns the message. + std::string* message() { return message_; } + + private: + std::string* message_; +}; + // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. @@ -341,7 +390,7 @@ const LogSeverity LOG_DFATAL = LOG_FATAL; #if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID) // Make all CHECK functions discard their log strings to reduce code -// bloat for official release builds. +// bloat for official release builds (except Android). // TODO(akalin): This would be more valuable if there were some way to // remove BreakDebugger() from the backtrace, perhaps by turning it @@ -355,20 +404,25 @@ const LogSeverity LOG_DFATAL = LOG_FATAL; #else -#define CHECK(condition) \ - LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ - << "Check failed: " #condition ". " +// Do as much work as possible out of line to reduce inline code size. +#define CHECK(condition) \ + LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ + !(condition)) // Helper macro for binary operators. // Don't use this macro directly in your code, use CHECK_EQ et al below. -// -// TODO(akalin): Rewrite this so that constructs like if (...) -// CHECK_EQ(...) else { ... } work properly. -#define CHECK_OP(name, op, val1, val2) \ - if (std::string* _result = \ - logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2)) \ - logging::LogMessage(__FILE__, __LINE__, _result).stream() +// The 'switch' is used to prevent the 'else' from being ambiguous when the +// macro is used in an 'if' clause such as: +// if (a == 1) +// CHECK_EQ(2, a); +#define CHECK_OP(name, op, val1, val2) \ + switch (0) case 0: default: \ + if (logging::CheckOpResult true_if_passed = \ + logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ + ; \ + else \ + logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream() #endif @@ -430,7 +484,6 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) -#define CHECK_IMPLIES(val1, val2) CHECK(!(val1) || (val2)) #if defined(NDEBUG) #define ENABLE_DLOG 0 @@ -514,12 +567,20 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // Helper macro for binary operators. // Don't use this macro directly in your code, use DCHECK_EQ et al below. -#define DCHECK_OP(name, op, val1, val2) \ - if (DCHECK_IS_ON()) \ - if (std::string* _result = logging::Check##name##Impl( \ - (val1), (val2), #val1 " " #op " " #val2)) \ - logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, _result) \ - .stream() +// The 'switch' is used to prevent the 'else' from being ambiguous when the +// macro is used in an 'if' clause such as: +// if (a == 1) +// DCHECK_EQ(2, a); +#define DCHECK_OP(name, op, val1, val2) \ + switch (0) case 0: default: \ + if (logging::CheckOpResult true_if_passed = \ + DCHECK_IS_ON() ? \ + logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2) : nullptr) \ + ; \ + else \ + logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ + true_if_passed.message()).stream() // Equality/Inequality checks - compare two values, and log a // LOG_DCHECK message including the two values when the result is not @@ -546,7 +607,6 @@ const LogSeverity LOG_DCHECK = LOG_INFO; #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) -#define DCHECK_IMPLIES(val1, val2) DCHECK(!(val1) || (val2)) #define NOTREACHED() DCHECK(false) @@ -567,6 +627,9 @@ class BASE_EXPORT LogMessage { // Used for LOG(severity). LogMessage(const char* file, int line, LogSeverity severity); + // Used for CHECK(). Implied severity = LOG_FATAL. + LogMessage(const char* file, int line, const char* condition); + // Used for CHECK_EQ(), etc. Takes ownership of the given string. // Implied severity = LOG_FATAL. LogMessage(const char* file, int line, std::string* result); @@ -595,7 +658,7 @@ class BASE_EXPORT LogMessage { // A non-macro interface to the log facility; (useful // when the logging level is not a compile-time constant). -inline void LogAtLevel(int const log_level, std::string const &msg) { +inline void LogAtLevel(int log_level, const std::string& msg) { LogMessage(__FILE__, __LINE__, log_level).stream() << msg; } @@ -652,9 +715,9 @@ BASE_EXPORT void RawLog(int level, const char* message); #define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS #elif NOTIMPLEMENTED_POLICY == 1 // TODO, figure out how to generate a warning -#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") #elif NOTIMPLEMENTED_POLICY == 2 -#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") #elif NOTIMPLEMENTED_POLICY == 3 #define NOTIMPLEMENTED() NOTREACHED() #elif NOTIMPLEMENTED_POLICY == 4 diff --git a/third_party/chromium/base/logging_unittest.cc b/third_party/chromium/base/logging_unittest.cc index e3c84e3..d2c1177 100644 --- a/third_party/chromium/base/logging_unittest.cc +++ b/third_party/chromium/base/logging_unittest.cc @@ -7,8 +7,8 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> -#include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/macros.h" namespace logging { @@ -115,7 +115,7 @@ TEST_F(LoggingTest, LogIsOn) { EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL)); } -TEST_F(LoggingTest, LoggingIsLazy) { +TEST_F(LoggingTest, LoggingIsLazyBySeverity) { MockLogSource mock_log_source; EXPECT_CALL(mock_log_source, Log()).Times(0); @@ -136,6 +136,24 @@ TEST_F(LoggingTest, LoggingIsLazy) { DVLOG_IF(1, true) << mock_log_source.Log(); } +TEST_F(LoggingTest, LoggingIsLazyByDestination) { + MockLogSource mock_log_source; + MockLogSource mock_log_source_error; + EXPECT_CALL(mock_log_source, Log()).Times(0); + + // Severity >= ERROR is always printed to stderr. + EXPECT_CALL(mock_log_source_error, Log()).Times(1). + WillRepeatedly(Return("log message")); + + LoggingSettings settings; + settings.logging_dest = LOG_NONE; + InitLogging(settings); + + LOG(INFO) << mock_log_source.Log(); + LOG(WARNING) << mock_log_source.Log(); + LOG(ERROR) << mock_log_source_error.Log(); +} + // Official builds have CHECKs directly call BreakDebugger. #if !defined(OFFICIAL_BUILD) @@ -213,6 +231,30 @@ TEST_F(LoggingTest, DcheckReleaseBehavior) { DCHECK_EQ(some_variable, 1) << "test"; } +TEST_F(LoggingTest, DCheckEqStatements) { + bool reached = false; + if (false) + DCHECK_EQ(false, true); // Unreached. + else + DCHECK_EQ(true, reached = true); // Reached, passed. + ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached); + + if (false) + DCHECK_EQ(false, true); // Unreached. +} + +TEST_F(LoggingTest, CheckEqStatements) { + bool reached = false; + if (false) + CHECK_EQ(false, true); // Unreached. + else + CHECK_EQ(true, reached = true); // Reached, passed. + ASSERT_TRUE(reached); + + if (false) + CHECK_EQ(false, true); // Unreached. +} + } // namespace } // namespace logging diff --git a/third_party/chromium/base/macros.h b/third_party/chromium/base/macros.h index 0325e74..46ee1da 100644 --- a/third_party/chromium/base/macros.h +++ b/third_party/chromium/base/macros.h @@ -11,7 +11,6 @@ #define BASE_MACROS_H_ #include <stddef.h> // For size_t. -#include <string.h> // For memcpy. // Put this in the declarations for a class to be uncopyable. #define DISALLOW_COPY(TypeName) \ @@ -27,13 +26,6 @@ TypeName(const TypeName&); \ void operator=(const TypeName&) -// An older, deprecated, politically incorrect name for the above. -// NOTE: The usage of this macro was banned from our code base, but some -// third_party libraries are yet using it. -// TODO(tfarina): Figure out how to fix the usage of this macro in the -// third_party libraries and get rid of it. -#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName) - // A macro to disallow all the implicit constructors, namely the // default constructor, copy constructor and operator= functions. // @@ -41,13 +33,14 @@ // that wants to prevent anyone from instantiating it. This is // especially useful for classes containing only static methods. #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName(); \ + TypeName() = delete; \ DISALLOW_COPY_AND_ASSIGN(TypeName) -// The arraysize(arr) macro returns the # of elements in an array arr. -// The expression is a compile-time constant, and therefore can be -// used in defining new arrays, for example. If you use arraysize on -// a pointer by mistake, you will get a compile-time error. +// The arraysize(arr) macro returns the # of elements in an array arr. The +// expression is a compile-time constant, and therefore can be used in defining +// new arrays, for example. If you use arraysize on a pointer by mistake, you +// will get a compile-time error. For the technical details, refer to +// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx. // This template function declaration is used in defining arraysize. // Note that the function doesn't need an implementation, as we only @@ -55,110 +48,6 @@ template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #define arraysize(array) (sizeof(ArraySizeHelper(array))) - -// Use implicit_cast as a safe version of static_cast or const_cast -// for upcasting in the type hierarchy (i.e. casting a pointer to Foo -// to a pointer to SuperclassOfFoo or casting a pointer to Foo to -// a const pointer to Foo). -// When you use implicit_cast, the compiler checks that the cast is safe. -// Such explicit implicit_casts are necessary in surprisingly many -// situations where C++ demands an exact type match instead of an -// argument type convertible to a target type. -// -// The From type can be inferred, so the preferred syntax for using -// implicit_cast is the same as for static_cast etc.: -// -// implicit_cast<ToType>(expr) -// -// implicit_cast would have been part of the C++ standard library, -// but the proposal was submitted too late. It will probably make -// its way into the language in the future. -template<typename To, typename From> -inline To implicit_cast(From const &f) { - return f; -} - -// The COMPILE_ASSERT macro can be used to verify that a compile time -// expression is true. For example, you could use it to verify the -// size of a static array: -// -// COMPILE_ASSERT(arraysize(content_type_names) == CONTENT_NUM_TYPES, -// content_type_names_incorrect_size); -// -// or to make sure a struct is smaller than a certain size: -// -// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); -// -// The second argument to the macro is the name of the variable. If -// the expression is false, most compilers will issue a warning/error -// containing the name of the variable. - -#undef COMPILE_ASSERT -#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) - -// bit_cast<Dest,Source> is a template function that implements the -// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in -// very low-level functions like the protobuf library and fast math -// support. -// -// float f = 3.14159265358979; -// int i = bit_cast<int32>(f); -// // i = 0x40490fdb -// -// The classical address-casting method is: -// -// // WRONG -// float f = 3.14159265358979; // WRONG -// int i = * reinterpret_cast<int*>(&f); // WRONG -// -// The address-casting method actually produces undefined behavior -// according to ISO C++ specification section 3.10 -15 -. Roughly, this -// section says: if an object in memory has one type, and a program -// accesses it with a different type, then the result is undefined -// behavior for most values of "different type". -// -// This is true for any cast syntax, either *(int*)&f or -// *reinterpret_cast<int*>(&f). And it is particularly true for -// conversions between integral lvalues and floating-point lvalues. -// -// The purpose of 3.10 -15- is to allow optimizing compilers to assume -// that expressions with different types refer to different memory. gcc -// 4.0.1 has an optimizer that takes advantage of this. So a -// non-conforming program quietly produces wildly incorrect output. -// -// The problem is not the use of reinterpret_cast. The problem is type -// punning: holding an object in memory of one type and reading its bits -// back using a different type. -// -// The C++ standard is more subtle and complex than this, but that -// is the basic idea. -// -// Anyways ... -// -// bit_cast<> calls memcpy() which is blessed by the standard, -// especially by the example in section 3.9 . Also, of course, -// bit_cast<> wraps up the nasty logic in one place. -// -// Fortunately memcpy() is very fast. In optimized mode, with a -// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline -// code with the minimal amount of data movement. On a 32-bit system, -// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) -// compiles to two loads and two stores. -// -// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. -// -// WARNING: if Dest or Source is a non-POD type, the result of the memcpy -// is likely to surprise you. - -template <class Dest, class Source> -inline Dest bit_cast(const Source& source) { - COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); - - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; -} - // Used to explicitly mark the return value of a function as unused. If you are // really sure you don't want to do anything with the return value of a function // that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: diff --git a/third_party/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h b/third_party/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h new file mode 100644 index 0000000..33bacba --- /dev/null +++ b/third_party/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ + +#include "base/memory/ref_counted.h" +#include "base/template_util.h" +#include "base/tuple.h" +#include "build/build_config.h" + +// It is dangerous to post a task with a T* argument where T is a subtype of +// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the +// object may already have been deleted since it was not held with a +// scoped_refptr. Example: http://crbug.com/27191 +// The following set of traits are designed to generate a compile error +// whenever this antipattern is attempted. + +namespace base { + +// This is a base internal implementation file used by task.h and callback.h. +// Not for public consumption, so we wrap it in namespace internal. +namespace internal { + +template <typename T> +struct NeedsScopedRefptrButGetsRawPtr { +#if defined(OS_WIN) + enum { + value = base::false_type::value + }; +#else + enum { + // Human readable translation: you needed to be a scoped_refptr if you are a + // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) + // type. + value = (std::is_pointer<T>::value && + (std::is_convertible<T, subtle::RefCountedBase*>::value || + std::is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) + }; +#endif +}; + +template <typename Params> +struct ParamsUseScopedRefptrCorrectly { + enum { value = 0 }; +}; + +template <> +struct ParamsUseScopedRefptrCorrectly<Tuple<>> { + enum { value = 1 }; +}; + +template <typename Head, typename... Tail> +struct ParamsUseScopedRefptrCorrectly<Tuple<Head, Tail...>> { + enum { value = !NeedsScopedRefptrButGetsRawPtr<Head>::value && + ParamsUseScopedRefptrCorrectly<Tuple<Tail...>>::value }; +}; + +} // namespace internal + +} // namespace base + +#endif // BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/third_party/chromium/base/memory/ref_counted.h b/third_party/chromium/base/memory/ref_counted.h index 52e8f00..95fa565 100644 --- a/third_party/chromium/base/memory/ref_counted.h +++ b/third_party/chromium/base/memory/ref_counted.h @@ -11,8 +11,8 @@ #include "base/base_export.h" #include "base/compiler_specific.h" +#include "base/macros.h" #include "base/logging.h" -#include "base/move.h" #include "build/build_config.h" namespace base { @@ -105,7 +105,7 @@ class BASE_EXPORT RefCountedThreadSafeBase { // ~MyFoo(); // }; // -// You should always make your destructor private, to avoid any code deleting +// You should always make your destructor non-public, to avoid any code deleting // the object accidently while there are references to it. template <class T> class RefCounted : public subtle::RefCountedBase { @@ -252,7 +252,6 @@ class RefCountedData // template <class T> class scoped_refptr { - TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr) public: typedef T element_type; @@ -264,17 +263,24 @@ class scoped_refptr { AddRef(ptr_); } + // Copy constructor. scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { if (ptr_) AddRef(ptr_); } + // Copy conversion constructor. template <typename U> scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { if (ptr_) AddRef(ptr_); } + // Move constructor. This is required in addition to the conversion + // constructor below in order for clang to warn about pessimizing moves. + scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } + + // Move conversion constructor. template <typename U> scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { r.ptr_ = nullptr; @@ -318,13 +324,13 @@ class scoped_refptr { } scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { - scoped_refptr<T>(r.Pass()).swap(*this); + scoped_refptr<T>(std::move(r)).swap(*this); return *this; } template <typename U> scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { - scoped_refptr<T>(r.Pass()).swap(*this); + scoped_refptr<T>(std::move(r)).swap(*this); return *this; } diff --git a/third_party/chromium/base/memory/ref_counted_unittest.cc b/third_party/chromium/base/memory/ref_counted_unittest.cc index 9eda813..88ee981 100644 --- a/third_party/chromium/base/memory/ref_counted_unittest.cc +++ b/third_party/chromium/base/memory/ref_counted_unittest.cc @@ -169,26 +169,6 @@ TEST(RefCountedUnitTest, ConvertibleEquality) { EXPECT_EQ(p2, p1); } -TEST(RefCountedUnitTest, SelfMoveAssignment) { - ScopedRefPtrCountBase::reset_count(); - - { - ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); - scoped_refptr<ScopedRefPtrCountBase> p(raw); - EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); - EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - - p = p.Pass(); - EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); - EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - EXPECT_EQ(raw, p.get()); - - // p goes out of scope. - } - EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); - EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); -} - TEST(RefCountedUnitTest, MoveAssignment1) { ScopedRefPtrCountBase::reset_count(); @@ -201,7 +181,7 @@ TEST(RefCountedUnitTest, MoveAssignment1) { { scoped_refptr<ScopedRefPtrCountBase> p2; - p2 = p1.Pass(); + p2 = std::move(p1); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(nullptr, p1.get()); @@ -232,7 +212,7 @@ TEST(RefCountedUnitTest, MoveAssignment2) { EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - p1 = p2.Pass(); + p1 = std::move(p2); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(raw, p1.get()); @@ -263,7 +243,7 @@ TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) { EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - p1 = p2.Pass(); + p1 = std::move(p2); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(raw, p1.get()); @@ -294,7 +274,7 @@ TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) { EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - p2 = p1.Pass(); + p2 = std::move(p1); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(nullptr, p1.get()); @@ -326,7 +306,7 @@ TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) { EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); - p1 = p2.Pass(); + p1 = std::move(p2); EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(raw2, p1.get()); @@ -363,7 +343,7 @@ TEST(RefCountedUnitTest, MoveAssignmentDerived) { EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); - p1 = p2.Pass(); + p1 = std::move(p2); EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); @@ -396,7 +376,7 @@ TEST(RefCountedUnitTest, MoveConstructor) { EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); { - scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass()); + scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(nullptr, p1.get()); @@ -426,7 +406,7 @@ TEST(RefCountedUnitTest, MoveConstructorDerived) { EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); { - scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass()); + scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); diff --git a/third_party/chromium/base/memory/scoped_ptr.h b/third_party/chromium/base/memory/scoped_ptr.h index 2aa1b32..d68604e 100644 --- a/third_party/chromium/base/memory/scoped_ptr.h +++ b/third_party/chromium/base/memory/scoped_ptr.h @@ -37,42 +37,43 @@ // in that they are "movable but not copyable." You can use the scopers in // the parameter and return types of functions to signify ownership transfer // in to and out of a function. When calling a function that has a scoper -// as the argument type, it must be called with the result of an analogous -// scoper's Pass() function or another function that generates a temporary; -// passing by copy will NOT work. Here is an example using scoped_ptr: +// as the argument type, it must be called with an rvalue of a scoper, which +// can be created by using std::move(), or the result of another function that +// generates a temporary; passing by copy will NOT work. Here is an example +// using scoped_ptr: // // void TakesOwnership(scoped_ptr<Foo> arg) { -// // Do something with arg +// // Do something with arg. // } // scoped_ptr<Foo> CreateFoo() { -// // No need for calling Pass() because we are constructing a temporary -// // for the return value. +// // No need for calling std::move() for returning a move-only value, or +// // when you already have an rvalue as we do here. // return scoped_ptr<Foo>(new Foo("new")); // } // scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { -// return arg.Pass(); +// return arg; // } // // { // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay"). -// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). +// TakesOwnership(std::move(ptr)); // ptr no longer owns Foo("yay"). // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. -// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr. +// PassThru(std::move(ptr2)); // ptr2 is correspondingly nullptr. // } // -// Notice that if you do not call Pass() when returning from PassThru(), or +// Notice that if you do not call std::move() when returning from PassThru(), or // when invoking TakesOwnership(), the code will not compile because scopers // are not copyable; they only implement move semantics which require calling -// the Pass() function to signify a destructive transfer of state. CreateFoo() -// is different though because we are constructing a temporary on the return -// line and thus can avoid needing to call Pass(). +// the std::move() function to signify a destructive transfer of state. +// CreateFoo() is different though because we are constructing a temporary on +// the return line and thus can avoid needing to call std::move(). // -// Pass() properly handles upcast in initialization, i.e. you can use a -// scoped_ptr<Child> to initialize a scoped_ptr<Parent>: +// The conversion move-constructor properly handles upcast in initialization, +// i.e. you can use a scoped_ptr<Child> to initialize a scoped_ptr<Parent>: // // scoped_ptr<Foo> foo(new Foo()); -// scoped_ptr<FooParent> parent(foo.Pass()); +// scoped_ptr<FooParent> parent(std::move(foo)); #ifndef BASE_MEMORY_SCOPED_PTR_H_ #define BASE_MEMORY_SCOPED_PTR_H_ @@ -84,11 +85,13 @@ #include <stddef.h> #include <stdlib.h> -#include <algorithm> // For std::swap(). #include <iosfwd> +#include <memory> +#include <type_traits> +#include <utility> -#include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/macros.h" #include "base/move.h" #include "base/template_util.h" @@ -99,61 +102,6 @@ class RefCountedBase; class RefCountedThreadSafeBase; } // namespace subtle -// Function object which deletes its parameter, which must be a pointer. -// If C is an array type, invokes 'delete[]' on the parameter; otherwise, -// invokes 'delete'. The default deleter for scoped_ptr<T>. -template <class T> -struct DefaultDeleter { - DefaultDeleter() {} - template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) { - // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor - // if U* is implicitly convertible to T* and U is not an array type. - // - // Correct implementation should use SFINAE to disable this - // constructor. However, since there are no other 1-argument constructors, - // using a COMPILE_ASSERT() based on is_convertible<> and requiring - // complete types is simpler and will cause compile failures for equivalent - // misuses. - // - // Note, the is_convertible<U*, T*> check also ensures that U is not an - // array. T is guaranteed to be a non-array, so any U* where U is an array - // cannot convert to T*. - enum { T_must_be_complete = sizeof(T) }; - enum { U_must_be_complete = sizeof(U) }; - COMPILE_ASSERT((std::is_convertible<U*, T*>::value), - U_ptr_must_implicitly_convert_to_T_ptr); - } - inline void operator()(T* ptr) const { - enum { type_must_be_complete = sizeof(T) }; - delete ptr; - } -}; - -// Specialization of DefaultDeleter for array types. -template <class T> -struct DefaultDeleter<T[]> { - inline void operator()(T* ptr) const { - enum { type_must_be_complete = sizeof(T) }; - delete[] ptr; - } - - private: - // Disable this operator for any U != T because it is undefined to execute - // an array delete when the static type of the array mismatches the dynamic - // type. - // - // References: - // C++98 [expr.delete]p3 - // http://cplusplus.github.com/LWG/lwg-defects.html#938 - template <typename U> void operator()(U* array) const; -}; - -template <class T, int n> -struct DefaultDeleter<T[n]> { - // Never allow someone to declare something like scoped_ptr<int[10]>. - COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); -}; - // Function object which invokes 'free' on its parameter, which must be // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: // @@ -175,17 +123,6 @@ template <typename T> struct IsNotRefCounted { }; }; -template <typename T> -struct ShouldAbortOnSelfReset { - template <typename U> - static NoType Test(const typename U::AllowSelfReset*); - - template <typename U> - static YesType Test(...); - - static const bool value = sizeof(Test<T>(0)) == sizeof(YesType); -}; - // Minimal implementation of the core logic of scoped_ptr, suitable for // reuse in both scoped_ptr and its specializations. template <class T, class D> @@ -216,37 +153,28 @@ class scoped_ptr_impl { } ~scoped_ptr_impl() { - if (data_.ptr != nullptr) { - // Not using get_deleter() saves one function call in non-optimized - // builds. - static_cast<D&>(data_)(data_.ptr); - } + // Match libc++, which calls reset() in its destructor. + // Use nullptr as the new value for three reasons: + // 1. libc++ does it. + // 2. Avoids infinitely recursing into destructors if two classes are owned + // in a reference cycle (see ScopedPtrTest.ReferenceCycle). + // 3. If |this| is accessed in the future, in a use-after-free bug, attempts + // to dereference |this|'s pointer should cause either a failure or a + // segfault closer to the problem. If |this| wasn't reset to nullptr, + // the access would cause the deleted memory to be read or written + // leading to other more subtle issues. + reset(nullptr); } void reset(T* p) { - // This is a self-reset, which is no longer allowed for default deleters: - // https://crbug.com/162971 - assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr); - - // Note that running data_.ptr = p can lead to undefined behavior if - // get_deleter()(get()) deletes this. In order to prevent this, reset() - // should update the stored pointer before deleting its old value. - // - // However, changing reset() to use that behavior may cause current code to - // break in unexpected ways. If the destruction of the owned object - // dereferences the scoped_ptr when it is destroyed by a call to reset(), - // then it will incorrectly dispatch calls to |p| rather than the original - // value of |data_.ptr|. - // - // During the transition period, set the stored pointer to nullptr while - // deleting the object. Eventually, this safety check will be removed to - // prevent the scenario initially described from occuring and - // http://crbug.com/176091 can be closed. + // Match C++11's definition of unique_ptr::reset(), which requires changing + // the pointer before invoking the deleter on the old pointer. This prevents + // |this| from being accessed after the deleter is run, which may destroy + // |this|. T* old = data_.ptr; - data_.ptr = nullptr; + data_.ptr = p; if (old != nullptr) static_cast<D&>(data_)(old); - data_.ptr = p; } T* get() const { return data_.ptr; } @@ -300,25 +228,27 @@ class scoped_ptr_impl { // dereference it, you get the thread safety guarantees of T. // // The size of scoped_ptr is small. On most compilers, when using the -// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will -// increase the size proportional to whatever state they need to have. See +// std::default_delete, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters +// will increase the size proportional to whatever state they need to have. See // comments inside scoped_ptr_impl<> for details. // // Current implementation targets having a strict subset of C++11's // unique_ptr<> features. Known deficiencies include not supporting move-only // deleteres, function pointers as deleters, and deleters with reference // types. -template <class T, class D = base::DefaultDeleter<T> > +template <class T, class D = std::default_delete<T>> class scoped_ptr { - MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) + DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) - COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, - T_is_refcounted_type_and_needs_scoped_refptr); + static_assert(!std::is_array<T>::value, + "scoped_ptr doesn't support array with size"); + static_assert(base::internal::IsNotRefCounted<T>::value, + "T is a refcounted type and needs a scoped_refptr"); public: // The element and deleter types. - typedef T element_type; - typedef D deleter_type; + using element_type = T; + using deleter_type = D; // Constructor. Defaults to initializing with nullptr. scoped_ptr() : impl_(nullptr) {} @@ -330,44 +260,87 @@ class scoped_ptr { scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} // Constructor. Allows construction from a nullptr. - scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} + scoped_ptr(std::nullptr_t) : impl_(nullptr) {} + + // Move constructor. + // + // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and + // not just the conversion constructor) in order to warn on pessimizing moves. + // The requirements for the move constructor are specified in C++11 + // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As + // we don't support reference (or move-only) deleters, the post conditions are + // trivially true: we always copy construct the deleter from other's deleter. + scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - // Constructor. Allows construction from a scoped_ptr rvalue for a + // Conversion constructor. Allows construction from a scoped_ptr rvalue for a // convertible type and deleter. // - // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct - // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor - // has different post-conditions if D is a reference type. Since this - // implementation does not support deleters with reference type, - // we do not need a separate move constructor allowing us to avoid one - // use of SFINAE. You only need to care about this if you modify the - // implementation of scoped_ptr. - template <typename U, typename V> - scoped_ptr(scoped_ptr<U, V>&& other) - : impl_(&other.impl_) { - COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array); + // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only + // participate in overload resolution if all the following are true: + // - U is implicitly convertible to T: this is important for 2 reasons: + // 1. So type traits don't incorrectly return true, e.g. + // std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value + // should be false. + // 2. To make sure code like this compiles: + // void F(scoped_ptr<int>); + // void F(scoped_ptr<Base>); + // // Ambiguous since both conversion constructors match. + // F(scoped_ptr<Derived>()); + // - U is not an array type: to prevent conversions from scoped_ptr<T[]> to + // scoped_ptr<T>. + // - D is a reference type and E is the same type, or D is not a reference + // type and E is implicitly convertible to D: again, we don't support + // reference deleters, so we only worry about the latter requirement. + template <typename U, + typename E, + typename std::enable_if<!std::is_array<U>::value && + std::is_convertible<U*, T*>::value && + std::is_convertible<E, D>::value>::type* = + nullptr> + scoped_ptr(scoped_ptr<U, E>&& other) + : impl_(&other.impl_) {} + + // operator=. + // + // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to + // require a move assignment operator to trigger the pessimizing move warning: + // in this case, the warning triggers when moving a temporary. For consistency + // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3 + // defines several requirements around this: like the move constructor, the + // requirements are simplified by the fact that we don't support move-only or + // reference deleters. + scoped_ptr& operator=(scoped_ptr&& rhs) { + impl_.TakeState(&rhs.impl_); + return *this; } // operator=. Allows assignment from a scoped_ptr rvalue for a convertible // type and deleter. // // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from - // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated - // form has different requirements on for move-only Deleters. Since this - // implementation does not support move-only Deleters, we do not need a - // separate move assignment operator allowing us to avoid one use of SFINAE. - // You only need to care about this if you modify the implementation of - // scoped_ptr. - template <typename U, typename V> - scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { - COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array); + // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the + // requirement for this operator, but like the conversion constructor, the + // requirements are greatly simplified by not supporting move-only or + // reference deleters. + template <typename U, + typename E, + typename std::enable_if<!std::is_array<U>::value && + std::is_convertible<U*, T*>::value && + // Note that this really should be + // std::is_assignable, but <type_traits> + // appears to be missing this on some + // platforms. This is close enough (though + // it's not the same). + std::is_convertible<D, E>::value>::type* = + nullptr> + scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) { impl_.TakeState(&rhs.impl_); return *this; } // operator=. Allows assignment from a nullptr. Deletes the currently owned // object, if any. - scoped_ptr& operator=(decltype(nullptr)) { + scoped_ptr& operator=(std::nullptr_t) { reset(); return *this; } @@ -408,12 +381,6 @@ class scoped_ptr { return impl_.get() ? &scoped_ptr::impl_ : nullptr; } - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(const element_type* p) const { return impl_.get() == p; } - bool operator!=(const element_type* p) const { return impl_.get() != p; } - // Swap two scoped pointers. void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); @@ -434,23 +401,16 @@ class scoped_ptr { // Forbidden for API compatibility with std::unique_ptr. explicit scoped_ptr(int disallow_construction_from_null); - - // Forbid comparison of scoped_ptr types. If U != T, it totally - // doesn't make sense, and if U == T, it still doesn't make sense - // because you should never have the same object owned by two different - // scoped_ptrs. - template <class U> bool operator==(scoped_ptr<U> const& p2) const; - template <class U> bool operator!=(scoped_ptr<U> const& p2) const; }; template <class T, class D> class scoped_ptr<T[], D> { - MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) + DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) public: // The element and deleter types. - typedef T element_type; - typedef D deleter_type; + using element_type = T; + using deleter_type = D; // Constructor. Defaults to initializing with nullptr. scoped_ptr() : impl_(nullptr) {} @@ -465,13 +425,11 @@ class scoped_ptr<T[], D> { // (C++98 [expr.delete]p3). If you're doing this, fix your code. // - it cannot be const-qualified differently from T per unique_ptr spec // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting - // to work around this may use implicit_cast<const T*>(). - // However, because of the first bullet in this comment, users MUST - // NOT use implicit_cast<Base*>() to upcast the static type of the array. + // to work around this may use const_cast<const T*>(). explicit scoped_ptr(element_type* array) : impl_(array) {} // Constructor. Allows construction from a nullptr. - scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} + scoped_ptr(std::nullptr_t) : impl_(nullptr) {} // Constructor. Allows construction from a scoped_ptr rvalue. scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} @@ -484,7 +442,7 @@ class scoped_ptr<T[], D> { // operator=. Allows assignment from a nullptr. Deletes the currently owned // array, if any. - scoped_ptr& operator=(decltype(nullptr)) { + scoped_ptr& operator=(std::nullptr_t) { reset(); return *this; } @@ -515,12 +473,6 @@ class scoped_ptr<T[], D> { return impl_.get() ? &scoped_ptr::impl_ : nullptr; } - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(element_type* array) const { return impl_.get() == array; } - bool operator!=(element_type* array) const { return impl_.get() != array; } - // Swap two scoped pointers. void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); @@ -553,13 +505,6 @@ class scoped_ptr<T[], D> { // reasons as the constructor above. template <typename U> void reset(U* array); void reset(int disallow_reset_from_null); - - // Forbid comparison of scoped_ptr types. If U != T, it totally - // doesn't make sense, and if U == T, it still doesn't make sense - // because you should never have the same object owned by two different - // scoped_ptrs. - template <class U> bool operator==(scoped_ptr<U> const& p2) const; - template <class U> bool operator!=(scoped_ptr<U> const& p2) const; }; // Free functions @@ -568,14 +513,84 @@ void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) { p1.swap(p2); } +template <class T1, class D1, class T2, class D2> +bool operator==(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return p1.get() == p2.get(); +} +template <class T, class D> +bool operator==(const scoped_ptr<T, D>& p, std::nullptr_t) { + return p.get() == nullptr; +} +template <class T, class D> +bool operator==(std::nullptr_t, const scoped_ptr<T, D>& p) { + return p.get() == nullptr; +} + +template <class T1, class D1, class T2, class D2> +bool operator!=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return !(p1 == p2); +} +template <class T, class D> +bool operator!=(const scoped_ptr<T, D>& p, std::nullptr_t) { + return !(p == nullptr); +} +template <class T, class D> +bool operator!=(std::nullptr_t, const scoped_ptr<T, D>& p) { + return !(p == nullptr); +} + +template <class T1, class D1, class T2, class D2> +bool operator<(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return p1.get() < p2.get(); +} +template <class T, class D> +bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) { + auto* ptr = p.get(); + return ptr < static_cast<decltype(ptr)>(nullptr); +} +template <class T, class D> +bool operator<(std::nullptr_t, const scoped_ptr<T, D>& p) { + auto* ptr = p.get(); + return static_cast<decltype(ptr)>(nullptr) < ptr; +} + +template <class T1, class D1, class T2, class D2> +bool operator>(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return p2 < p1; +} +template <class T, class D> +bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t) { + return nullptr < p; +} +template <class T, class D> +bool operator>(std::nullptr_t, const scoped_ptr<T, D>& p) { + return p < nullptr; +} + +template <class T1, class D1, class T2, class D2> +bool operator<=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return !(p1 > p2); +} +template <class T, class D> +bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t) { + return !(p > nullptr); +} template <class T, class D> -bool operator==(T* p1, const scoped_ptr<T, D>& p2) { - return p1 == p2.get(); +bool operator<=(std::nullptr_t, const scoped_ptr<T, D>& p) { + return !(nullptr > p); } +template <class T1, class D1, class T2, class D2> +bool operator>=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { + return !(p1 < p2); +} +template <class T, class D> +bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) { + return !(p < nullptr); +} template <class T, class D> -bool operator!=(T* p1, const scoped_ptr<T, D>& p2) { - return p1 != p2.get(); +bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) { + return !(nullptr < p); } // A function to convert T* into scoped_ptr<T> diff --git a/third_party/chromium/base/memory/scoped_ptr_unittest.cc b/third_party/chromium/base/memory/scoped_ptr_unittest.cc index d4ff410..c1eb469 100644 --- a/third_party/chromium/base/memory/scoped_ptr_unittest.cc +++ b/third_party/chromium/base/memory/scoped_ptr_unittest.cc @@ -4,13 +4,16 @@ #include "base/memory/scoped_ptr.h" +#include <stddef.h> + #include <sstream> #include <gtest/gtest.h> -#include "base/basictypes.h" #include "base/bind.h" #include "base/callback.h" +#include "base/macros.h" +#include "build/build_config.h" namespace { @@ -85,7 +88,7 @@ int OverloadedNewAndDelete::g_new_count = 0; int OverloadedNewAndDelete::g_delete_count = 0; scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { - return logger.Pass(); + return logger; } void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { @@ -103,8 +106,8 @@ TEST(ScopedPtrTest, ScopedPtr) { int constructed = 0; // Ensure size of scoped_ptr<> doesn't increase unexpectedly. - COMPILE_ASSERT(sizeof(int*) >= sizeof(scoped_ptr<int>), - scoped_ptr_larger_than_raw_ptr); + static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>), + "scoped_ptr shouldn't be larger than the raw pointer"); { scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); @@ -147,25 +150,25 @@ TEST(ScopedPtrTest, ScopedPtr) { } EXPECT_EQ(0, constructed); - // Test swap(), == and != + // Test swap(). { scoped_ptr<ConDecLogger> scoper1; scoped_ptr<ConDecLogger> scoper2; - EXPECT_TRUE(scoper1 == scoper2.get()); - EXPECT_FALSE(scoper1 != scoper2.get()); + EXPECT_TRUE(scoper1.get() == scoper2.get()); + EXPECT_FALSE(scoper1.get() != scoper2.get()); ConDecLogger* logger = new ConDecLogger(&constructed); scoper1.reset(logger); EXPECT_EQ(logger, scoper1.get()); EXPECT_FALSE(scoper2.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); scoper2.swap(scoper1); EXPECT_EQ(logger, scoper2.get()); EXPECT_FALSE(scoper1.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); } EXPECT_EQ(0, constructed); } @@ -179,7 +182,7 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper.get()); - scoped_ptr<ConDecLoggerParent> scoper_parent(scoper.Pass()); + scoped_ptr<ConDecLoggerParent> scoper_parent(std::move(scoper)); EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper_parent.get()); EXPECT_FALSE(scoper.get()); @@ -197,7 +200,7 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_TRUE(scoper.get()); scoped_ptr<ConDecLoggerParent> scoper_parent; - scoper_parent = scoper.Pass(); + scoper_parent = std::move(scoper); EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper_parent.get()); EXPECT_FALSE(scoper.get()); @@ -210,7 +213,7 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper.get()); - scoped_ptr<const ConDecLogger> scoper_const(scoper.Pass()); + scoped_ptr<const ConDecLogger> scoper_const(std::move(scoper)); EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper_const.get()); EXPECT_FALSE(scoper.get()); @@ -228,7 +231,7 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_TRUE(scoper.get()); scoped_ptr<const ConDecLogger> scoper_const; - scoper_const = scoper.Pass(); + scoper_const = std::move(scoper); EXPECT_EQ(1, constructed); EXPECT_TRUE(scoper_const.get()); EXPECT_FALSE(scoper.get()); @@ -252,7 +255,7 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_EQ(0, alternate_deletes); // Test this compiles and correctly overwrites the deleter state. - scoper = scoper_child.Pass(); + scoper = std::move(scoper_child); EXPECT_TRUE(scoper); EXPECT_FALSE(scoper_child); EXPECT_EQ(1, deletes); @@ -268,7 +271,8 @@ TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { EXPECT_TRUE(scoper_child); EXPECT_EQ(1, deletes); EXPECT_EQ(1, alternate_deletes); - scoped_ptr<double, CountingDeleter> scoper_construct(scoper_child.Pass()); + scoped_ptr<double, CountingDeleter> scoper_construct( + std::move(scoper_child)); EXPECT_TRUE(scoper_construct); EXPECT_FALSE(scoper_child); EXPECT_EQ(1, deletes); @@ -328,12 +332,12 @@ TEST(ScopedPtrTest, ScopedPtrWithArray) { } EXPECT_EQ(0, constructed); - // Test swap(), ==, !=, and type-safe Boolean. + // Test swap() and type-safe Boolean. { scoped_ptr<ConDecLogger[]> scoper1; scoped_ptr<ConDecLogger[]> scoper2; - EXPECT_TRUE(scoper1 == scoper2.get()); - EXPECT_FALSE(scoper1 != scoper2.get()); + EXPECT_TRUE(scoper1.get() == scoper2.get()); + EXPECT_FALSE(scoper1.get() != scoper2.get()); ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; for (int i = 0; i < kNumLoggers; ++i) { @@ -344,14 +348,14 @@ TEST(ScopedPtrTest, ScopedPtrWithArray) { EXPECT_EQ(loggers, scoper1.get()); EXPECT_FALSE(scoper2); EXPECT_FALSE(scoper2.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); scoper2.swap(scoper1); EXPECT_EQ(loggers, scoper2.get()); EXPECT_FALSE(scoper1.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); } EXPECT_EQ(0, constructed); @@ -364,13 +368,13 @@ TEST(ScopedPtrTest, ScopedPtrWithArray) { } EXPECT_EQ(kNumLoggers, constructed); - // Test Pass() with constructor; - scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass()); + // Test moving with constructor; + scoped_ptr<ConDecLogger[]> scoper2(std::move(scoper)); EXPECT_EQ(kNumLoggers, constructed); - // Test Pass() with assignment; + // Test moving with assignment; scoped_ptr<ConDecLogger[]> scoper3; - scoper3 = scoper2.Pass(); + scoper3 = std::move(scoper2); EXPECT_EQ(kNumLoggers, constructed); EXPECT_FALSE(scoper); EXPECT_FALSE(scoper2); @@ -379,27 +383,30 @@ TEST(ScopedPtrTest, ScopedPtrWithArray) { EXPECT_EQ(0, constructed); } -TEST(ScopedPtrTest, PassBehavior) { +TEST(ScopedPtrTest, MoveBehavior) { int constructed = 0; { ConDecLogger* logger = new ConDecLogger(&constructed); scoped_ptr<ConDecLogger> scoper(logger); EXPECT_EQ(1, constructed); - // Test Pass() with constructor; - scoped_ptr<ConDecLogger> scoper2(scoper.Pass()); + // Test moving with constructor; + scoped_ptr<ConDecLogger> scoper2(std::move(scoper)); EXPECT_EQ(1, constructed); - // Test Pass() with assignment; + // Test moving with assignment; scoped_ptr<ConDecLogger> scoper3; - scoper3 = scoper2.Pass(); + scoper3 = std::move(scoper2); EXPECT_EQ(1, constructed); EXPECT_FALSE(scoper.get()); EXPECT_FALSE(scoper2.get()); EXPECT_TRUE(scoper3.get()); } - // Test uncaught Pass() does not have side effects. +#if !defined(OS_ANDROID) && !defined(OS_LINUX) + // Test uncaught Pass() does not have side effects, because Pass() + // is implemented by std::move(). + // TODO(danakj): Remove this test case when we remove Pass(). { ConDecLogger* logger = new ConDecLogger(&constructed); scoped_ptr<ConDecLogger> scoper(logger); @@ -412,6 +419,7 @@ TEST(ScopedPtrTest, PassBehavior) { EXPECT_TRUE(rvalue); } EXPECT_EQ(0, constructed); +#endif // Test that passing to function which does nothing does not leak. { @@ -420,7 +428,7 @@ TEST(ScopedPtrTest, PassBehavior) { EXPECT_EQ(1, constructed); // Should auto-destruct logger by end of scope. - GrabAndDrop(scoper.Pass()); + GrabAndDrop(std::move(scoper)); EXPECT_FALSE(scoper.get()); } EXPECT_EQ(0, constructed); @@ -435,7 +443,7 @@ TEST(ScopedPtrTest, ReturnTypeBehavior) { scoped_ptr<ConDecLogger> scoper(logger); EXPECT_EQ(1, constructed); - PassThru(scoper.Pass()); + PassThru(std::move(scoper)); EXPECT_FALSE(scoper.get()); } EXPECT_EQ(0, constructed); @@ -447,7 +455,7 @@ TEST(ScopedPtrTest, ReturnTypeBehavior) { EXPECT_EQ(1, constructed); // Should auto-destruct logger by end of scope. - PassThru(scoper.Pass()); + PassThru(std::move(scoper)); EXPECT_FALSE(scoper.get()); } EXPECT_EQ(0, constructed); @@ -538,8 +546,8 @@ TEST(ScopedPtrTest, CustomDeleter) { // Pass the second deleter through a constructor and an operator=. Then // reinitialize the empty scopers to ensure that each one is deleting // properly. - scoped_ptr<double, CountingDeleter> scoper3(scoper2.Pass()); - scoper = scoper3.Pass(); + scoped_ptr<double, CountingDeleter> scoper3(std::move(scoper2)); + scoper = std::move(scoper3); EXPECT_EQ(1, deletes); scoper2.reset(&dummy_value2); @@ -550,33 +558,33 @@ TEST(ScopedPtrTest, CustomDeleter) { EXPECT_EQ(1, deletes); EXPECT_EQ(3, alternate_deletes); - // Test swap(), ==, !=, and type-safe Boolean. + // Test swap(), and type-safe Boolean. { scoped_ptr<double, CountingDeleter> scoper1(NULL, CountingDeleter(&deletes)); scoped_ptr<double, CountingDeleter> scoper2(NULL, CountingDeleter(&deletes)); - EXPECT_TRUE(scoper1 == scoper2.get()); - EXPECT_FALSE(scoper1 != scoper2.get()); + EXPECT_TRUE(scoper1.get() == scoper2.get()); + EXPECT_FALSE(scoper1.get() != scoper2.get()); scoper1.reset(&dummy_value); EXPECT_TRUE(scoper1); EXPECT_EQ(&dummy_value, scoper1.get()); EXPECT_FALSE(scoper2); EXPECT_FALSE(scoper2.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); scoper2.swap(scoper1); EXPECT_EQ(&dummy_value, scoper2.get()); EXPECT_FALSE(scoper1.get()); - EXPECT_FALSE(scoper1 == scoper2.get()); - EXPECT_TRUE(scoper1 != scoper2.get()); + EXPECT_FALSE(scoper1.get() == scoper2.get()); + EXPECT_TRUE(scoper1.get() != scoper2.get()); } } // Sanity check test for overloaded new and delete operators. Does not do full -// coverage of reset/release/Pass() operations as that is redundant with the +// coverage of reset/release/move operations as that is redundant with the // above. TEST(ScopedPtrTest, OverloadedNewAndDelete) { { @@ -584,7 +592,7 @@ TEST(ScopedPtrTest, OverloadedNewAndDelete) { scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete()); EXPECT_TRUE(scoper.get()); - scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass()); + scoped_ptr<OverloadedNewAndDelete> scoper2(std::move(scoper)); } EXPECT_EQ(1, OverloadedNewAndDelete::delete_count()); EXPECT_EQ(1, OverloadedNewAndDelete::new_count()); @@ -633,55 +641,15 @@ TEST(ScopedPtrTest, Conversion) { scoped_ptr<Sub> sub1(new Sub); scoped_ptr<Sub> sub2(new Sub); - // Upcast with Pass() works. - scoped_ptr<Super> super1 = sub1.Pass(); - super1 = sub2.Pass(); + // Upcast with move works. + scoped_ptr<Super> super1 = std::move(sub1); + super1 = std::move(sub2); // Upcast with an rvalue works. scoped_ptr<Super> super2 = SubClassReturn(); super2 = SubClassReturn(); } -// Android death tests don't work properly with assert(). Yay. -#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) -TEST(ScopedPtrTest, SelfResetAbortsWithDefaultDeleter) { - scoped_ptr<int> x(new int); - EXPECT_DEATH(x.reset(x.get()), ""); -} - -TEST(ScopedPtrTest, SelfResetAbortsWithDefaultArrayDeleter) { - scoped_ptr<int[]> y(new int[4]); - EXPECT_DEATH(y.reset(y.get()), ""); -} - -TEST(ScopedPtrTest, SelfResetAbortsWithDefaultFreeDeleter) { - scoped_ptr<int, base::FreeDeleter> z(static_cast<int*>(malloc(sizeof(int)))); - EXPECT_DEATH(z.reset(z.get()), ""); -} - -// A custom deleter that doesn't opt out should still crash. -TEST(ScopedPtrTest, SelfResetAbortsWithCustomDeleter) { - struct CustomDeleter { - inline void operator()(int* x) { delete x; } - }; - scoped_ptr<int, CustomDeleter> x(new int); - EXPECT_DEATH(x.reset(x.get()), ""); -} -#endif - -TEST(ScopedPtrTest, SelfResetWithCustomDeleterOptOut) { - // A custom deleter should be able to opt out of self-reset abort behavior. - struct NoOpDeleter { -#if !defined(NDEBUG) - typedef void AllowSelfReset; -#endif - inline void operator()(int*) {} - }; - scoped_ptr<int> owner(new int); - scoped_ptr<int, NoOpDeleter> x(owner.get()); - x.reset(x.get()); -} - // Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean // value first. TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { @@ -694,3 +662,182 @@ TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { EXPECT_EQ(s2.str(), s1.str()); } + +TEST(ScopedPtrTest, ReferenceCycle) { + struct StructB; + struct StructA { + scoped_ptr<StructB> b; + }; + + struct StructB { + scoped_ptr<StructA> a; + }; + + // Create a reference cycle. + StructA* a = new StructA; + a->b.reset(new StructB); + a->b->a.reset(a); + + // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|) + // to be deleted before the call to reset() returns. This tests that the + // implementation of scoped_ptr::reset() doesn't access |this| after it + // deletes the underlying pointer. This behaviour is consistent with the + // definition of unique_ptr::reset in C++11. + a->b.reset(); + + // Go again, but this time, break the cycle by invoking |a|'s destructor. This + // tests that the implementation of ~scoped_ptr doesn't infinitely recurse + // into the destructors of |a| and |a->b|. Note, deleting |a| instead will + // cause |a| to be double-free'd because |a->b| owns |a| and deletes it via + // its destructor. + a = new StructA; + a->b.reset(new StructB); + a->b->a.reset(a); + a->~StructA(); +} + +TEST(ScopedPtrTest, Operators) { + struct Parent {}; + struct Child : public Parent {}; + + scoped_ptr<Parent> p(new Parent); + scoped_ptr<Parent> p2(new Parent); + scoped_ptr<Child> c(new Child); + scoped_ptr<Parent> pnull; + + // Operator==. + EXPECT_TRUE(p == p); + EXPECT_FALSE(p == c); + EXPECT_FALSE(p == p2); + EXPECT_FALSE(p == pnull); + + EXPECT_FALSE(p == nullptr); + EXPECT_FALSE(nullptr == p); + EXPECT_TRUE(pnull == nullptr); + EXPECT_TRUE(nullptr == pnull); + + // Operator!=. + EXPECT_FALSE(p != p); + EXPECT_TRUE(p != c); + EXPECT_TRUE(p != p2); + EXPECT_TRUE(p != pnull); + + EXPECT_TRUE(p != nullptr); + EXPECT_TRUE(nullptr != p); + EXPECT_FALSE(pnull != nullptr); + EXPECT_FALSE(nullptr != pnull); + + // Compare two scoped_ptr<T>. + EXPECT_EQ(p.get() < p2.get(), p < p2); + EXPECT_EQ(p.get() <= p2.get(), p <= p2); + EXPECT_EQ(p.get() > p2.get(), p > p2); + EXPECT_EQ(p.get() >= p2.get(), p >= p2); + EXPECT_EQ(p2.get() < p.get(), p2 < p); + EXPECT_EQ(p2.get() <= p.get(), p2 <= p); + EXPECT_EQ(p2.get() > p.get(), p2 > p); + EXPECT_EQ(p2.get() >= p.get(), p2 >= p); + + // And convertible scoped_ptr<T> and scoped_ptr<U>. + EXPECT_EQ(p.get() < c.get(), p < c); + EXPECT_EQ(p.get() <= c.get(), p <= c); + EXPECT_EQ(p.get() > c.get(), p > c); + EXPECT_EQ(p.get() >= c.get(), p >= c); + EXPECT_EQ(c.get() < p.get(), c < p); + EXPECT_EQ(c.get() <= p.get(), c <= p); + EXPECT_EQ(c.get() > p.get(), c > p); + EXPECT_EQ(c.get() >= p.get(), c >= p); + + // Compare to nullptr. + EXPECT_TRUE(p > nullptr); + EXPECT_FALSE(nullptr > p); + EXPECT_FALSE(pnull > nullptr); + EXPECT_FALSE(nullptr > pnull); + + EXPECT_TRUE(p >= nullptr); + EXPECT_FALSE(nullptr >= p); + EXPECT_TRUE(pnull >= nullptr); + EXPECT_TRUE(nullptr >= pnull); + + EXPECT_FALSE(p < nullptr); + EXPECT_TRUE(nullptr < p); + EXPECT_FALSE(pnull < nullptr); + EXPECT_FALSE(nullptr < pnull); + + EXPECT_FALSE(p <= nullptr); + EXPECT_TRUE(nullptr <= p); + EXPECT_TRUE(pnull <= nullptr); + EXPECT_TRUE(nullptr <= pnull); +}; + +TEST(ScopedPtrTest, ArrayOperators) { + struct Parent {}; + struct Child : public Parent {}; + + scoped_ptr<Parent[]> p(new Parent[1]); + scoped_ptr<Parent[]> p2(new Parent[1]); + scoped_ptr<Child[]> c(new Child[1]); + scoped_ptr<Parent[]> pnull; + + // Operator==. + EXPECT_TRUE(p == p); + EXPECT_FALSE(p == c); + EXPECT_FALSE(p == p2); + EXPECT_FALSE(p == pnull); + + EXPECT_FALSE(p == nullptr); + EXPECT_FALSE(nullptr == p); + EXPECT_TRUE(pnull == nullptr); + EXPECT_TRUE(nullptr == pnull); + + // Operator!=. + EXPECT_FALSE(p != p); + EXPECT_TRUE(p != c); + EXPECT_TRUE(p != p2); + EXPECT_TRUE(p != pnull); + + EXPECT_TRUE(p != nullptr); + EXPECT_TRUE(nullptr != p); + EXPECT_FALSE(pnull != nullptr); + EXPECT_FALSE(nullptr != pnull); + + // Compare two scoped_ptr<T>. + EXPECT_EQ(p.get() < p2.get(), p < p2); + EXPECT_EQ(p.get() <= p2.get(), p <= p2); + EXPECT_EQ(p.get() > p2.get(), p > p2); + EXPECT_EQ(p.get() >= p2.get(), p >= p2); + EXPECT_EQ(p2.get() < p.get(), p2 < p); + EXPECT_EQ(p2.get() <= p.get(), p2 <= p); + EXPECT_EQ(p2.get() > p.get(), p2 > p); + EXPECT_EQ(p2.get() >= p.get(), p2 >= p); + + // And convertible scoped_ptr<T> and scoped_ptr<U>. + EXPECT_EQ(p.get() < c.get(), p < c); + EXPECT_EQ(p.get() <= c.get(), p <= c); + EXPECT_EQ(p.get() > c.get(), p > c); + EXPECT_EQ(p.get() >= c.get(), p >= c); + EXPECT_EQ(c.get() < p.get(), c < p); + EXPECT_EQ(c.get() <= p.get(), c <= p); + EXPECT_EQ(c.get() > p.get(), c > p); + EXPECT_EQ(c.get() >= p.get(), c >= p); + + // Compare to nullptr. + EXPECT_TRUE(p > nullptr); + EXPECT_FALSE(nullptr > p); + EXPECT_FALSE(pnull > nullptr); + EXPECT_FALSE(nullptr > pnull); + + EXPECT_TRUE(p >= nullptr); + EXPECT_FALSE(nullptr >= p); + EXPECT_TRUE(pnull >= nullptr); + EXPECT_TRUE(nullptr >= pnull); + + EXPECT_FALSE(p < nullptr); + EXPECT_TRUE(nullptr < p); + EXPECT_FALSE(pnull < nullptr); + EXPECT_FALSE(nullptr < pnull); + + EXPECT_FALSE(p <= nullptr); + EXPECT_TRUE(nullptr <= p); + EXPECT_TRUE(pnull <= nullptr); + EXPECT_TRUE(nullptr <= pnull); +} diff --git a/third_party/chromium/base/memory/weak_ptr.h b/third_party/chromium/base/memory/weak_ptr.h index e07beeb..c1c52ee 100644 --- a/third_party/chromium/base/memory/weak_ptr.h +++ b/third_party/chromium/base/memory/weak_ptr.h @@ -16,6 +16,7 @@ // // class Controller { // public: +// Controller() : weak_factory_(this) {} // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } // void WorkComplete(const Result& result) { ... } // private: @@ -58,15 +59,20 @@ // off to other task runners, e.g. to use to post tasks back to object on the // bound sequence. // -// Invalidating the factory's WeakPtrs un-binds it from the sequence, allowing -// it to be passed for a different sequence to use or delete it. +// If all WeakPtr objects are destroyed or invalidated then the factory is +// unbound from the SequencedTaskRunner/Thread. The WeakPtrFactory may then be +// destroyed, or new WeakPtr objects may be used, from a different sequence. +// +// Thus, at least one WeakPtr object must exist and have been dereferenced on +// the correct thread to enforce that other WeakPtr objects will enforce they +// are used on the desired thread. #ifndef BASE_MEMORY_WEAK_PTR_H_ #define BASE_MEMORY_WEAK_PTR_H_ -#include "base/basictypes.h" #include "base/base_export.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/ref_counted.h" namespace base { @@ -152,8 +158,8 @@ class SupportsWeakPtrBase { static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { typedef std::is_convertible<Derived*, internal::SupportsWeakPtrBase*> convertible; - COMPILE_ASSERT(convertible::value, - AsWeakPtr_argument_inherits_from_SupportsWeakPtr); + static_assert(convertible::value, + "AsWeakPtr argument must inherit from SupportsWeakPtr"); return AsWeakPtrImpl<Derived>(t, *t); } diff --git a/third_party/chromium/base/move.h b/third_party/chromium/base/move.h index 87dc52d..24bf9d7 100644 --- a/third_party/chromium/base/move.h +++ b/third_party/chromium/base/move.h @@ -5,230 +5,53 @@ #ifndef BASE_MOVE_H_ #define BASE_MOVE_H_ +#include <utility> + #include "base/compiler_specific.h" +#include "base/macros.h" +#include "build/build_config.h" -// Macro with the boilerplate that makes a type move-only in C++03. -// -// USAGE -// -// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create -// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be -// the first line in a class declaration. -// -// A class using this macro must call .Pass() (or somehow be an r-value already) -// before it can be: -// -// * Passed as a function argument -// * Used as the right-hand side of an assignment -// * Returned from a function -// -// Each class will still need to define their own "move constructor" and "move -// operator=" to make this useful. Here's an example of the macro, the move -// constructor, and the move operator= from the scoped_ptr class: -// -// template <typename T> -// class scoped_ptr { -// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) -// public: -// scoped_ptr(RValue& other) : ptr_(other.release()) { } -// scoped_ptr& operator=(RValue& other) { -// swap(other); -// return *this; -// } -// }; -// -// Note that the constructor must NOT be marked explicit. -// -// For consistency, the second parameter to the macro should always be RValue -// unless you have a strong reason to do otherwise. It is only exposed as a -// macro parameter so that the move constructor and move operator= don't look -// like they're using a phantom type. -// -// -// HOW THIS WORKS -// -// For a thorough explanation of this technique, see: -// -// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor -// -// The summary is that we take advantage of 2 properties: -// -// 1) non-const references will not bind to r-values. -// 2) C++ can apply one user-defined conversion when initializing a -// variable. -// -// The first lets us disable the copy constructor and assignment operator -// by declaring private version of them with a non-const reference parameter. -// -// For l-values, direct initialization still fails like in -// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment -// operators are private. -// -// For r-values, the situation is different. The copy constructor and -// assignment operator are not viable due to (1), so we are trying to call -// a non-existent constructor and non-existing operator= rather than a private -// one. Since we have not committed an error quite yet, we can provide an -// alternate conversion sequence and a constructor. We add -// -// * a private struct named "RValue" -// * a user-defined conversion "operator RValue()" -// * a "move constructor" and "move operator=" that take the RValue& as -// their sole parameter. -// -// Only r-values will trigger this sequence and execute our "move constructor" -// or "move operator=." L-values will match the private copy constructor and -// operator= first giving a "private in this context" error. This combination -// gives us a move-only type. -// -// For signaling a destructive transfer of data from an l-value, we provide a -// method named Pass() which creates an r-value for the current instance -// triggering the move constructor or move operator=. -// -// Other ways to get r-values is to use the result of an expression like a -// function call. -// -// Here's an example with comments explaining what gets triggered where: -// -// class Foo { -// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue); -// -// public: -// ... API ... -// Foo(RValue other); // Move constructor. -// Foo& operator=(RValue rhs); // Move operator= -// }; -// -// Foo MakeFoo(); // Function that returns a Foo. -// -// Foo f; -// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context. -// Foo f_assign; -// f_assign = f; // ERROR: operator=(Foo&) is private in this context. -// -// -// Foo f(MakeFoo()); // R-value so alternate conversion executed. -// Foo f_copy(f.Pass()); // R-value so alternate conversion executed. -// f = f_copy.Pass(); // R-value so alternate conversion executed. -// -// -// IMPLEMENTATION SUBTLETIES WITH RValue -// -// The RValue struct is just a container for a pointer back to the original -// object. It should only ever be created as a temporary, and no external -// class should ever declare it or use it in a parameter. -// -// It is tempting to want to use the RValue type in function parameters, but -// excluding the limited usage here for the move constructor and move -// operator=, doing so would mean that the function could take both r-values -// and l-values equially which is unexpected. See COMPARED To Boost.Move for -// more details. -// -// An alternate, and incorrect, implementation of the RValue class used by -// Boost.Move makes RValue a fieldless child of the move-only type. RValue& -// is then used in place of RValue in the various operators. The RValue& is -// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal -// of never creating a temporary RValue struct even with optimizations -// disabled. Also, by virtue of inheritance you can treat the RValue -// reference as if it were the move-only type itself. Unfortunately, -// using the result of this reinterpret_cast<> is actually undefined behavior -// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer -// will generate non-working code. -// -// In optimized builds, both implementations generate the same assembly so we -// choose the one that adheres to the standard. -// +// TODO(crbug.com/566182): DEPRECATED! +// Use DISALLOW_COPY_AND_ASSIGN instead, or if your type will be used in +// Callbacks, use DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND instead. +#define MOVE_ONLY_TYPE_FOR_CPP_03(type) \ + DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) + +// A macro to disallow the copy constructor and copy assignment functions. +// This should be used in the private: declarations for a class. // -// WHY HAVE typedef void MoveOnlyTypeForCPP03 +// Use this macro instead of DISALLOW_COPY_AND_ASSIGN if you want to pass +// ownership of the type through a base::Callback without heap-allocating it +// into a scoped_ptr. The class must define a move constructor and move +// assignment operator to make this work. // -// Callback<>/Bind() needs to understand movable-but-not-copyable semantics -// to call .Pass() appropriately when it is expected to transfer the value. -// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check -// easy and automatic in helper templates for Callback<>/Bind(). +// This version of the macro adds a Pass() function and a cryptic +// MoveOnlyTypeForCPP03 typedef for the base::Callback implementation to use. // See IsMoveOnlyType template and its usage in base/callback_internal.h // for more details. -// -// -// COMPARED TO C++11 -// -// In C++11, you would implement this functionality using an r-value reference -// and our .Pass() method would be replaced with a call to std::move(). -// -// This emulation also has a deficiency where it uses up the single -// user-defined conversion allowed by C++ during initialization. This can -// cause problems in some API edge cases. For instance, in scoped_ptr, it is -// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a -// value of type scoped_ptr<Child> even if you add a constructor to -// scoped_ptr<> that would make it look like it should work. C++11 does not -// have this deficiency. -// -// -// COMPARED TO Boost.Move -// -// Our implementation similar to Boost.Move, but we keep the RValue struct -// private to the move-only type, and we don't use the reinterpret_cast<> hack. -// -// In Boost.Move, RValue is the boost::rv<> template. This type can be used -// when writing APIs like: -// -// void MyFunc(boost::rv<Foo>& f) -// -// that can take advantage of rv<> to avoid extra copies of a type. However you -// would still be able to call this version of MyFunc with an l-value: -// -// Foo f; -// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass(). -// -// unless someone is very careful to also declare a parallel override like: -// -// void MyFunc(const Foo& f) -// -// that would catch the l-values first. This was declared unsafe in C++11 and -// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot -// ensure this in C++03. -// -// Since we have no need for writing such APIs yet, our implementation keeps -// RValue private and uses a .Pass() method to do the conversion instead of -// trying to write a version of "std::move()." Writing an API like std::move() -// would require the RValue struct to be public. -// -// -// CAVEATS -// -// If you include a move-only type as a field inside a class that does not -// explicitly declare a copy constructor, the containing class's implicit -// copy constructor will change from Containing(const Containing&) to -// Containing(Containing&). This can cause some unexpected errors. -// -// http://llvm.org/bugs/show_bug.cgi?id=11528 -// -// The workaround is to explicitly declare your copy constructor. -// -#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \ - private: \ - struct rvalue_type { \ - explicit rvalue_type(type* object) : object(object) {} \ - type* object; \ - }; \ - type(type&); \ - void operator=(type&); \ - public: \ - operator rvalue_type() { return rvalue_type(this); } \ - type Pass() WARN_UNUSED_RESULT { return type(rvalue_type(this)); } \ - typedef void MoveOnlyTypeForCPP03; \ +// TODO(crbug.com/566182): Remove this macro and use DISALLOW_COPY_AND_ASSIGN +// everywhere instead. +#if defined(OS_ANDROID) || defined(OS_LINUX) +#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ + private: \ + type(const type&) = delete; \ + void operator=(const type&) = delete; \ + \ + public: \ + typedef void MoveOnlyTypeForCPP03; \ + \ private: - -#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \ - private: \ - type(const type&); \ - void operator=(const type&); \ - public: \ - type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \ - typedef void MoveOnlyTypeForCPP03; \ - private: - -#define TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \ - public: \ - type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \ +#else +#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ + private: \ + type(const type&) = delete; \ + void operator=(const type&) = delete; \ + \ + public: \ + type&& Pass() WARN_UNUSED_RESULT { return std::move(*this); } \ + typedef void MoveOnlyTypeForCPP03; \ + \ private: +#endif #endif // BASE_MOVE_H_ diff --git a/third_party/chromium/base/move_unittest.cc b/third_party/chromium/base/move_unittest.cc deleted file mode 100644 index bebcfd8..0000000 --- a/third_party/chromium/base/move_unittest.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/move.h" - -#include <gtest/gtest.h> - -namespace { - -class MoveOnly { - MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(MoveOnly) - - public: - MoveOnly() {} - - MoveOnly(MoveOnly&& other) {} - MoveOnly& operator=(MoveOnly&& other) { return *this; } -}; - -class Container { - public: - Container() = default; - Container(const Container& other) = default; - Container& operator=(const Container& other) = default; - - Container(Container&& other) { value_ = other.value_.Pass(); } - - Container& operator=(Container&& other) { - value_ = other.value_.Pass(); - return *this; - } - - private: - MoveOnly value_; -}; - -Container GetContainerRvalue() { - Container x; - return x; -} - -TEST(MoveTest, CopyableContainerCanBeMoved) { - // Container should be move-constructible and move-assignable. - Container y = GetContainerRvalue(); - y = GetContainerRvalue(); -} - -} // namespace diff --git a/third_party/chromium/base/numerics/safe_conversions.h b/third_party/chromium/base/numerics/safe_conversions.h index 5dd5191..baac188 100644 --- a/third_party/chromium/base/numerics/safe_conversions.h +++ b/third_party/chromium/base/numerics/safe_conversions.h @@ -5,7 +5,10 @@ #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ +#include <stddef.h> + #include <limits> +#include <type_traits> #include "base/logging.h" #include "base/numerics/safe_conversions_impl.h" @@ -20,6 +23,24 @@ inline bool IsValueInRangeForNumericType(Src value) { internal::RANGE_VALID; } +// Convenience function for determining if a numeric value is negative without +// throwing compiler warnings on: unsigned(value) < 0. +template <typename T> +typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type +IsValueNegative(T value) { + static_assert(std::numeric_limits<T>::is_specialized, + "Argument must be numeric."); + return value < 0; +} + +template <typename T> +typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type + IsValueNegative(T) { + static_assert(std::numeric_limits<T>::is_specialized, + "Argument must be numeric."); + return false; +} + // checked_cast<> is analogous to static_cast<> for numeric types, // except that it CHECKs that the specified numeric conversion will not // overflow or underflow. NaN source will always trigger a CHECK. @@ -29,10 +50,30 @@ inline Dst checked_cast(Src value) { return static_cast<Dst>(value); } +// HandleNaN will cause this class to CHECK(false). +struct SaturatedCastNaNBehaviorCheck { + template <typename T> + static T HandleNaN() { + CHECK(false); + return T(); + } +}; + +// HandleNaN will return 0 in this case. +struct SaturatedCastNaNBehaviorReturnZero { + template <typename T> + static T HandleNaN() { + return T(); + } +}; + // saturated_cast<> is analogous to static_cast<> for numeric types, except // that the specified numeric conversion will saturate rather than overflow or -// underflow. NaN assignment to an integral will trigger a CHECK condition. -template <typename Dst, typename Src> +// underflow. NaN assignment to an integral will defer the behavior to a +// specified class. By default, it will return 0. +template <typename Dst, + class NaNHandler = SaturatedCastNaNBehaviorReturnZero, + typename Src> inline Dst saturated_cast(Src value) { // Optimization for floating point values, which already saturate. if (std::numeric_limits<Dst>::is_iec559) @@ -50,8 +91,7 @@ inline Dst saturated_cast(Src value) { // Should fail only on attempting to assign NaN to a saturated integer. case internal::RANGE_INVALID: - CHECK(false); - return std::numeric_limits<Dst>::max(); + return NaNHandler::template HandleNaN<Dst>(); } NOTREACHED(); diff --git a/third_party/chromium/base/numerics/safe_conversions_impl.h b/third_party/chromium/base/numerics/safe_conversions_impl.h index d07221e..e1d376a 100644 --- a/third_party/chromium/base/numerics/safe_conversions_impl.h +++ b/third_party/chromium/base/numerics/safe_conversions_impl.h @@ -5,6 +5,9 @@ #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ #define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ +#include <limits.h> +#include <stdint.h> + #include <limits> namespace base { @@ -106,6 +109,55 @@ inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); } +// The following helper template addresses a corner case in range checks for +// conversion from a floating-point type to an integral type of smaller range +// but larger precision (e.g. float -> unsigned). The problem is as follows: +// 1. Integral maximum is always one less than a power of two, so it must be +// truncated to fit the mantissa of the floating point. The direction of +// rounding is implementation defined, but by default it's always IEEE +// floats, which round to nearest and thus result in a value of larger +// magnitude than the integral value. +// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX +// // is 4294967295u. +// 2. If the floating point value is equal to the promoted integral maximum +// value, a range check will erroneously pass. +// Example: (4294967296f <= 4294967295u) // This is true due to a precision +// // loss in rounding up to float. +// 3. When the floating point value is then converted to an integral, the +// resulting value is out of range for the target integral type and +// thus is implementation defined. +// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0. +// To fix this bug we manually truncate the maximum value when the destination +// type is an integral of larger precision than the source floating-point type, +// such that the resulting maximum is represented exactly as a floating point. +template <typename Dst, typename Src> +struct NarrowingRange { + typedef typename std::numeric_limits<Src> SrcLimits; + typedef typename std::numeric_limits<Dst> DstLimits; + + static Dst max() { + // The following logic avoids warnings where the max function is + // instantiated with invalid values for a bit shift (even though + // such a function can never be called). + static const int shift = + (MaxExponent<Src>::value > MaxExponent<Dst>::value && + SrcLimits::digits < DstLimits::digits && SrcLimits::is_iec559 && + DstLimits::is_integer) + ? (DstLimits::digits - SrcLimits::digits) + : 0; + + // We use UINTMAX_C below to avoid compiler warnings about shifting floating + // points. Since it's a compile time calculation, it shouldn't have any + // performance impact. + return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1); + } + + static Dst min() { + return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() + : DstLimits::min(); + } +}; + template < typename Dst, typename Src, @@ -133,7 +185,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED> { - static RangeConstraint Check(Src value) { return RANGE_VALID; } + static RangeConstraint Check(Src /* value */) { return RANGE_VALID; } }; // Signed to signed narrowing: Both the upper and lower boundaries may be @@ -145,11 +197,8 @@ struct DstRangeRelationToSrcRangeImpl<Dst, INTEGER_REPRESENTATION_SIGNED, NUMERIC_RANGE_NOT_CONTAINED> { static RangeConstraint Check(Src value) { - return std::numeric_limits<Dst>::is_iec559 - ? GetRangeConstraint((value < std::numeric_limits<Dst>::max()), - (value > -std::numeric_limits<Dst>::max())) - : GetRangeConstraint((value < std::numeric_limits<Dst>::max()), - (value > std::numeric_limits<Dst>::min())); + return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()), + (value >= NarrowingRange<Dst, Src>::min())); } }; @@ -161,7 +210,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst, INTEGER_REPRESENTATION_UNSIGNED, NUMERIC_RANGE_NOT_CONTAINED> { static RangeConstraint Check(Src value) { - return GetRangeConstraint(value < std::numeric_limits<Dst>::max(), true); + return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true); } }; @@ -176,7 +225,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst, return sizeof(Dst) > sizeof(Src) ? RANGE_VALID : GetRangeConstraint( - value < static_cast<Src>(std::numeric_limits<Dst>::max()), + value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), true); } }; @@ -193,7 +242,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst, return (MaxExponent<Dst>::value >= MaxExponent<Src>::value) ? GetRangeConstraint(true, value >= static_cast<Src>(0)) : GetRangeConstraint( - value < static_cast<Src>(std::numeric_limits<Dst>::max()), + value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), value >= static_cast<Src>(0)); } }; diff --git a/third_party/chromium/base/numerics/safe_math.h b/third_party/chromium/base/numerics/safe_math.h index a596d4b..ddffb6e 100644 --- a/third_party/chromium/base/numerics/safe_math.h +++ b/third_party/chromium/base/numerics/safe_math.h @@ -5,6 +5,8 @@ #ifndef BASE_NUMERICS_SAFE_MATH_H_ #define BASE_NUMERICS_SAFE_MATH_H_ +#include <stddef.h> + #include "base/numerics/safe_math_impl.h" namespace base { @@ -36,9 +38,8 @@ namespace internal { // CheckedNumeric<int> checked_int = untrusted_input_value; // int x = checked_int.ValueOrDefault(0) | kFlagValues; // Comparison: -// CheckedNumeric<size_t> checked_size; -// CheckedNumeric<int> checked_size = untrusted_input_value; -// checked_size = checked_size + HEADER LENGTH; +// CheckedNumeric<size_t> checked_size = untrusted_input_value; +// checked_size += HEADER LENGTH; // if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) // Do stuff... template <typename T> @@ -145,6 +146,14 @@ class CheckedNumeric { return CheckedNumeric<T>(value, validity); } + // This function is available only for integral types. It returns an unsigned + // integer of the same width as the source type, containing the absolute value + // of the source, and properly handling signed min. + CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { + return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( + CheckedUnsignedAbs(state_.value()), state_.validity()); + } + CheckedNumeric& operator++() { *this += 1; return *this; @@ -188,6 +197,16 @@ class CheckedNumeric { static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; } private: + template <typename NumericType> + struct UnderlyingType { + using type = NumericType; + }; + + template <typename NumericType> + struct UnderlyingType<CheckedNumeric<NumericType>> { + using type = NumericType; + }; + CheckedNumericState<T> state_; }; @@ -224,7 +243,8 @@ class CheckedNumeric { template <typename T> \ template <typename Src> \ CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ - *this = CheckedNumeric<T>::cast(*this) OP CheckedNumeric<Src>::cast(rhs); \ + *this = CheckedNumeric<T>::cast(*this) \ + OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ return *this; \ } \ /* Binary arithmetic operator for CheckedNumeric of different type. */ \ diff --git a/third_party/chromium/base/numerics/safe_math_impl.h b/third_party/chromium/base/numerics/safe_math_impl.h index 0ae1dfe..487b3bc 100644 --- a/third_party/chromium/base/numerics/safe_math_impl.h +++ b/third_party/chromium/base/numerics/safe_math_impl.h @@ -5,11 +5,13 @@ #ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ #define BASE_NUMERICS_SAFE_MATH_IMPL_H_ +#include <stddef.h> #include <stdint.h> #include <cmath> #include <cstdlib> #include <limits> +#include <type_traits> #include "base/numerics/safe_conversions.h" @@ -86,7 +88,27 @@ struct TwiceWiderInteger { template <typename Integer> struct PositionOfSignBit { static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, - size_t>::type value = 8 * sizeof(Integer) - 1; + size_t>::type value = + 8 * sizeof(Integer) - 1; +}; + +// This is used for UnsignedAbs, where we need to support floating-point +// template instantiations even though we don't actually support the operations. +// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, +// so the float versions will not compile. +template <typename Numeric, + bool IsInteger = std::numeric_limits<Numeric>::is_integer, + bool IsFloat = std::numeric_limits<Numeric>::is_iec559> +struct UnsignedOrFloatForSize; + +template <typename Numeric> +struct UnsignedOrFloatForSize<Numeric, true, false> { + typedef typename UnsignedIntegerForSize<Numeric>::type type; +}; + +template <typename Numeric> +struct UnsignedOrFloatForSize<Numeric, false, true> { + typedef Numeric type; }; // Helper templates for integer manipulations. @@ -159,9 +181,9 @@ CheckedSub(T x, T y, RangeConstraint* validity) { // slow case we need to manually check that the result won't be truncated by // checking with division against the appropriate bound. template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t), - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + sizeof(T) * 2 <= sizeof(uintmax_t), + T>::type CheckedMul(T x, T y, RangeConstraint* validity) { typedef typename TwiceWiderInteger<T>::type IntermediateType; IntermediateType tmp = @@ -202,9 +224,9 @@ CheckedMul(T x, T y, RangeConstraint* validity) { template <typename T> typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type + !std::numeric_limits<T>::is_signed && + (sizeof(T) * 2 > sizeof(uintmax_t)), + T>::type CheckedMul(T x, T y, RangeConstraint* validity) { *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID @@ -230,27 +252,27 @@ T CheckedDiv(T x, } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer&& std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, + T>::type CheckedMod(T x, T y, RangeConstraint* validity) { *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; return x % y; } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + T>::type CheckedMod(T x, T y, RangeConstraint* validity) { *validity = RANGE_VALID; return x % y; } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer&& std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, + T>::type CheckedNeg(T value, RangeConstraint* validity) { *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; @@ -259,9 +281,9 @@ CheckedNeg(T value, RangeConstraint* validity) { } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + T>::type CheckedNeg(T value, RangeConstraint* validity) { // The only legal unsigned negation is zero. *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; @@ -270,9 +292,9 @@ CheckedNeg(T value, RangeConstraint* validity) { } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer&& std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, + T>::type CheckedAbs(T value, RangeConstraint* validity) { *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; @@ -280,23 +302,43 @@ CheckedAbs(T value, RangeConstraint* validity) { } template <typename T> -typename std::enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + T>::type CheckedAbs(T value, RangeConstraint* validity) { - // Absolute value of a positive is just its identiy. + // T is unsigned, so |value| must already be positive. *validity = RANGE_VALID; return value; } +template <typename T> +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, + typename UnsignedIntegerForSize<T>::type>::type +CheckedUnsignedAbs(T value) { + typedef typename UnsignedIntegerForSize<T>::type UnsignedT; + return value == std::numeric_limits<T>::min() + ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 + : static_cast<UnsignedT>(std::abs(value)); +} + +template <typename T> +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + T>::type +CheckedUnsignedAbs(T value) { + // T is unsigned, so |value| must already be positive. + return value; +} + // These are the floating point stubs that the compiler needs to see. Only the // negation operation is ever called. -#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ - template <typename T> \ +#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ + template <typename T> \ typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \ - Checked##NAME(T, T, RangeConstraint*) { \ - NOTREACHED(); \ - return 0; \ + Checked##NAME(T, T, RangeConstraint*) { \ + NOTREACHED(); \ + return 0; \ } BASE_FLOAT_ARITHMETIC_STUBS(Add) @@ -399,7 +441,7 @@ class CheckedNumericState<T, NUMERIC_FLOATING> { template <typename Src> CheckedNumericState( Src value, - RangeConstraint validity, + RangeConstraint /* validity */, typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0) { switch (DstRangeRelationToSrcRange<T>(value)) { diff --git a/third_party/chromium/base/numerics/safe_numerics_unittest.cc b/third_party/chromium/base/numerics/safe_numerics_unittest.cc index 96b579a..8ac7b0c 100644 --- a/third_party/chromium/base/numerics/safe_numerics_unittest.cc +++ b/third_party/chromium/base/numerics/safe_numerics_unittest.cc @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -#include <mmintrin.h> -#endif +#include <stddef.h> #include <stdint.h> #include <limits> +#include <type_traits> #include <gtest/gtest.h> @@ -19,6 +18,8 @@ using std::numeric_limits; using base::CheckedNumeric; using base::checked_cast; +using base::IsValueInRangeForNumericType; +using base::IsValueNegative; using base::SizeT; using base::StrictNumeric; using base::saturated_cast; @@ -28,7 +29,7 @@ using base::internal::RANGE_VALID; using base::internal::RANGE_INVALID; using base::internal::RANGE_OVERFLOW; using base::internal::RANGE_UNDERFLOW; -using std::enable_if; +using base::internal::SignedIntegerForSize; // These tests deliberately cause arithmetic overflows. If the compiler is // aggressive enough, it can const fold these overflows. Disable warnings about @@ -37,6 +38,26 @@ using std::enable_if; #pragma warning(disable:4756) #endif +// This is a helper function for finding the maximum value in Src that can be +// wholy represented as the destination floating-point type. +template <typename Dst, typename Src> +Dst GetMaxConvertibleToFloat() { + typedef numeric_limits<Dst> DstLimits; + typedef numeric_limits<Src> SrcLimits; + static_assert(SrcLimits::is_specialized, "Source must be numeric."); + static_assert(DstLimits::is_specialized, "Destination must be numeric."); + CHECK(DstLimits::is_iec559); + + if (SrcLimits::digits <= DstLimits::digits && + MaxExponent<Src>::value <= MaxExponent<Dst>::value) + return SrcLimits::max(); + Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0); + while (max != static_cast<Src>(static_cast<Dst>(max))) { + max /= 2; + } + return static_cast<Dst>(max); +} + // Helper macros to wrap displaying the conversion types and line numbers. #define TEST_EXPECTED_VALIDITY(expected, actual) \ EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \ @@ -54,9 +75,9 @@ template <typename Dst> static void TestSpecializedArithmetic( const char* dst, int line, - typename enable_if< - numeric_limits<Dst>::is_integer&& numeric_limits<Dst>::is_signed, - int>::type = 0) { + typename std::enable_if<numeric_limits<Dst>::is_integer && + numeric_limits<Dst>::is_signed, + int>::type = 0) { typedef numeric_limits<Dst> DstLimits; TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, -CheckedNumeric<Dst>(DstLimits::min())); @@ -110,9 +131,9 @@ template <typename Dst> static void TestSpecializedArithmetic( const char* dst, int line, - typename enable_if< - numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed, - int>::type = 0) { + typename std::enable_if<numeric_limits<Dst>::is_integer && + !numeric_limits<Dst>::is_signed, + int>::type = 0) { typedef numeric_limits<Dst> DstLimits; TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min())); TEST_EXPECTED_VALIDITY(RANGE_VALID, @@ -123,6 +144,13 @@ static void TestSpecializedArithmetic( CheckedNumeric<Dst>(DstLimits::min()) - 1); TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2); TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2); + TEST_EXPECTED_VALIDITY(RANGE_VALID, + CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs()); + TEST_EXPECTED_VALIDITY( + RANGE_VALID, + CheckedNumeric<typename SignedIntegerForSize<Dst>::type>( + std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min()) + .UnsignedAbs()); // Modulus is legal only for integers. TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1); @@ -143,7 +171,7 @@ template <typename Dst> void TestSpecializedArithmetic( const char* dst, int line, - typename enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { + typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { typedef numeric_limits<Dst> DstLimits; TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min())); @@ -318,7 +346,6 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { "Comparison must be sign preserving and value preserving"); const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); - ; TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst); if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { @@ -371,6 +398,18 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); + if (DstLimits::is_integer) { + if (SrcLimits::digits < DstLimits::digits) { + TEST_EXPECTED_RANGE(RANGE_OVERFLOW, + static_cast<Src>(DstLimits::max())); + } else { + TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); + } + TEST_EXPECTED_RANGE( + RANGE_VALID, + static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); + TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); + } } else if (SrcLimits::is_signed) { TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1)); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); @@ -429,6 +468,18 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); + if (DstLimits::is_integer) { + if (SrcLimits::digits < DstLimits::digits) { + TEST_EXPECTED_RANGE(RANGE_OVERFLOW, + static_cast<Src>(DstLimits::max())); + } else { + TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); + } + TEST_EXPECTED_RANGE( + RANGE_VALID, + static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); + TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); + } } else { TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); } @@ -579,6 +630,18 @@ TEST(SafeNumerics, CastTests) { EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid()); EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid()); + EXPECT_TRUE(IsValueNegative(-1)); + EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min())); + EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min())); + EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max())); + EXPECT_FALSE(IsValueNegative(0)); + EXPECT_FALSE(IsValueNegative(1)); + EXPECT_FALSE(IsValueNegative(0u)); + EXPECT_FALSE(IsValueNegative(1u)); + EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max())); + EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max())); + EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max())); + // These casts and coercions will fail to compile: // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0))); // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0))); @@ -599,5 +662,120 @@ TEST(SafeNumerics, CastTests) { EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity); EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int)); EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); + + float not_a_number = std::numeric_limits<float>::infinity() - + std::numeric_limits<float>::infinity(); + EXPECT_TRUE(std::isnan(not_a_number)); + EXPECT_EQ(0, saturated_cast<int>(not_a_number)); } +#if GTEST_HAS_DEATH_TEST + +TEST(SafeNumerics, SaturatedCastChecks) { + float not_a_number = std::numeric_limits<float>::infinity() - + std::numeric_limits<float>::infinity(); + EXPECT_TRUE(std::isnan(not_a_number)); + EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>( + not_a_number)), ""); +} + +#endif // GTEST_HAS_DEATH_TEST + +TEST(SafeNumerics, IsValueInRangeForNumericType) { + EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2)); + EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff))); + EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000))); + EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001))); + EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>( + std::numeric_limits<int32_t>::min())); + EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>( + std::numeric_limits<int64_t>::min())); + + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0)); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1)); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2)); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1)); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff)); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu)); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u)); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu)); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000))); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff))); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000))); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>( + std::numeric_limits<int32_t>::min())); + EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>( + static_cast<int64_t>(std::numeric_limits<int32_t>::min()))); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>( + static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1)); + EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>( + std::numeric_limits<int64_t>::min())); + + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2)); + EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu)); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff))); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000))); + EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001))); + EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>( + std::numeric_limits<int32_t>::min())); + EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1))); + EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>( + std::numeric_limits<int64_t>::min())); + + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu)); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000))); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff))); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000))); + EXPECT_TRUE( + IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff))); + EXPECT_TRUE( + IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff))); + EXPECT_FALSE( + IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000))); + EXPECT_FALSE( + IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff))); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( + std::numeric_limits<int32_t>::min())); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( + static_cast<int64_t>(std::numeric_limits<int32_t>::min()))); + EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( + std::numeric_limits<int64_t>::min())); +} + +TEST(SafeNumerics, CompoundNumericOperations) { + CheckedNumeric<int> a = 1; + CheckedNumeric<int> b = 2; + CheckedNumeric<int> c = 3; + CheckedNumeric<int> d = 4; + a += b; + EXPECT_EQ(3, a.ValueOrDie()); + a -= c; + EXPECT_EQ(0, a.ValueOrDie()); + d /= b; + EXPECT_EQ(2, d.ValueOrDie()); + d *= d; + EXPECT_EQ(4, d.ValueOrDie()); + + CheckedNumeric<int> too_large = std::numeric_limits<int>::max(); + EXPECT_TRUE(too_large.IsValid()); + too_large += d; + EXPECT_FALSE(too_large.IsValid()); + too_large -= d; + EXPECT_FALSE(too_large.IsValid()); + too_large /= d; + EXPECT_FALSE(too_large.IsValid()); +} diff --git a/third_party/chromium/base/observer_list.h b/third_party/chromium/base/observer_list.h index 3baf910..bb76091 100644 --- a/third_party/chromium/base/observer_list.h +++ b/third_party/chromium/base/observer_list.h @@ -5,12 +5,14 @@ #ifndef BASE_OBSERVER_LIST_H_ #define BASE_OBSERVER_LIST_H_ +#include <stddef.h> + #include <algorithm> #include <limits> #include <vector> -#include "base/basictypes.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/weak_ptr.h" /////////////////////////////////////////////////////////////////////////////// @@ -152,8 +154,8 @@ ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() { template <class ObserverType> void ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) { DCHECK(obs); - if (std::find(observers_.begin(), observers_.end(), obs) - != observers_.end()) { + auto it = std::find(observers_.begin(), observers_.end(), obs); + if (it != observers_.end()) { NOTREACHED() << "Observers can only be added once!"; return; } diff --git a/third_party/chromium/base/rand_util.cc b/third_party/chromium/base/rand_util.cc index a55cdbd..c02c875 100644 --- a/third_party/chromium/base/rand_util.cc +++ b/third_party/chromium/base/rand_util.cc @@ -4,13 +4,13 @@ #include "base/rand_util.h" +#include <limits.h> #include <math.h> #include <stdint.h> #include <algorithm> #include <limits> -#include "base/basictypes.h" #include "base/logging.h" #include "base/strings/string_util.h" @@ -19,8 +19,11 @@ namespace base { int RandInt(int min, int max) { DCHECK_LE(min, max); - uint64 range = static_cast<uint64>(max) - min + 1; - int result = min + static_cast<int>(base::RandGenerator(range)); + uint64_t range = static_cast<uint64_t>(max) - min + 1; + // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range) + // is at most UINT_MAX. Hence it's safe to cast it from uint64_t to int64_t. + int result = + static_cast<int>(min + static_cast<int64_t>(base::RandGenerator(range))); DCHECK_GE(result, min); DCHECK_LE(result, max); return result; @@ -30,31 +33,32 @@ double RandDouble() { return BitsToOpenEndedUnitInterval(base::RandUint64()); } -double BitsToOpenEndedUnitInterval(uint64 bits) { +double BitsToOpenEndedUnitInterval(uint64_t bits) { // We try to get maximum precision by masking out as many bits as will fit // in the target type's mantissa, and raising it to an appropriate power to // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa // is expected to accommodate 53 bits. - COMPILE_ASSERT(std::numeric_limits<double>::radix == 2, otherwise_use_scalbn); + static_assert(std::numeric_limits<double>::radix == 2, + "otherwise use scalbn"); static const int kBits = std::numeric_limits<double>::digits; - uint64 random_bits = bits & ((UINT64_C(1) << kBits) - 1); + uint64_t random_bits = bits & ((UINT64_C(1) << kBits) - 1); double result = ldexp(static_cast<double>(random_bits), -1 * kBits); DCHECK_GE(result, 0.0); DCHECK_LT(result, 1.0); return result; } -uint64 RandGenerator(uint64 range) { +uint64_t RandGenerator(uint64_t range) { DCHECK_GT(range, 0u); // We must discard random results above this number, as they would // make the random generator non-uniform (consider e.g. if // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice // as likely as a result of 3 or 4). - uint64 max_acceptable_value = - (std::numeric_limits<uint64>::max() / range) * range - 1; + uint64_t max_acceptable_value = + (std::numeric_limits<uint64_t>::max() / range) * range - 1; - uint64 value; + uint64_t value; do { value = base::RandUint64(); } while (value > max_acceptable_value); diff --git a/third_party/chromium/base/rand_util.h b/third_party/chromium/base/rand_util.h index e29a9ce..ff52aad 100644 --- a/third_party/chromium/base/rand_util.h +++ b/third_party/chromium/base/rand_util.h @@ -5,15 +5,18 @@ #ifndef BASE_RAND_UTIL_H_ #define BASE_RAND_UTIL_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> #include "base/base_export.h" -#include "base/basictypes.h" +#include "build/build_config.h" namespace base { -// Returns a random number in range [0, kuint64max]. Thread-safe. -uint64 RandUint64(); +// Returns a random number in range [0, UINT64_MAX]. Thread-safe. +uint64_t RandUint64(); // Returns a random number between min and max (inclusive). Thread-safe. int RandInt(int min, int max); @@ -23,14 +26,14 @@ int RandInt(int min, int max); // Note that this can be used as an adapter for std::random_shuffle(): // Given a pre-populated |std::vector<int> myvector|, shuffle it as // std::random_shuffle(myvector.begin(), myvector.end(), base::RandGenerator); -uint64 RandGenerator(uint64 range); +uint64_t RandGenerator(uint64_t range); // Returns a random double in range [0, 1). Thread-safe. double RandDouble(); // Given input |bits|, convert with maximum precision to a double in // the range [0, 1). Thread-safe. -double BitsToOpenEndedUnitInterval(uint64 bits); +double BitsToOpenEndedUnitInterval(uint64_t bits); // Fills |output_length| bytes of |output| with random data. // diff --git a/third_party/chromium/base/rand_util_posix.cc b/third_party/chromium/base/rand_util_posix.cc index 76a5dab..2f51804 100644 --- a/third_party/chromium/base/rand_util_posix.cc +++ b/third_party/chromium/base/rand_util_posix.cc @@ -6,6 +6,8 @@ #include <errno.h> #include <fcntl.h> +#include <stddef.h> +#include <stdint.h> #include <unistd.h> #include "base/logging.h" @@ -44,8 +46,8 @@ bool ReadFromFD(int fd, char* buffer, size_t bytes) { namespace base { // NOTE: This function must be cryptographically secure. http://crbug.com/140076 -uint64 RandUint64() { - uint64 number; +uint64_t RandUint64() { + uint64_t number; RandBytes(&number, sizeof(number)); return number; } diff --git a/third_party/chromium/base/rand_util_unittest.cc b/third_party/chromium/base/rand_util_unittest.cc index 384125b..fc0233d 100644 --- a/third_party/chromium/base/rand_util_unittest.cc +++ b/third_party/chromium/base/rand_util_unittest.cc @@ -4,6 +4,9 @@ #include "base/rand_util.h" +#include <stddef.h> +#include <stdint.h> + #include <algorithm> #include <limits> @@ -20,10 +23,16 @@ const int kIntMax = std::numeric_limits<int>::max(); } // namespace -TEST(RandUtilTest, SameMinAndMax) { +TEST(RandUtilTest, RandInt) { EXPECT_EQ(base::RandInt(0, 0), 0); EXPECT_EQ(base::RandInt(kIntMin, kIntMin), kIntMin); EXPECT_EQ(base::RandInt(kIntMax, kIntMax), kIntMax); + + // Check that the DCHECKS in RandInt() don't fire due to internal overflow. + // There was a 50% chance of that happening, so calling it 40 times means + // the chances of this passing by accident are tiny (9e-13). + for (int i = 0; i < 40; ++i) + base::RandInt(kIntMin, kIntMax); } TEST(RandUtilTest, RandDouble) { @@ -62,7 +71,7 @@ TEST(RandUtilTest, RandBytesAsString) { TEST(RandUtilTest, RandGeneratorForRandomShuffle) { EXPECT_EQ(base::RandGenerator(1), 0U); EXPECT_LE(std::numeric_limits<ptrdiff_t>::max(), - std::numeric_limits<int64>::max()); + std::numeric_limits<int64_t>::max()); } TEST(RandUtilTest, RandGeneratorIsUniform) { @@ -78,16 +87,17 @@ TEST(RandUtilTest, RandGeneratorIsUniform) { // top half. A bit of calculus care of jar@ shows that the largest // measurable delta is when the top of the range is 3/4ths of the // way, so that's what we use in the test. - const uint64 kTopOfRange = (std::numeric_limits<uint64>::max() / 4ULL) * 3ULL; - const uint64 kExpectedAverage = kTopOfRange / 2ULL; - const uint64 kAllowedVariance = kExpectedAverage / 50ULL; // +/- 2% + const uint64_t kTopOfRange = + (std::numeric_limits<uint64_t>::max() / 4ULL) * 3ULL; + const uint64_t kExpectedAverage = kTopOfRange / 2ULL; + const uint64_t kAllowedVariance = kExpectedAverage / 50ULL; // +/- 2% const int kMinAttempts = 1000; const int kMaxAttempts = 1000000; double cumulative_average = 0.0; int count = 0; while (count < kMaxAttempts) { - uint64 value = base::RandGenerator(kTopOfRange); + uint64_t value = base::RandGenerator(kTopOfRange); cumulative_average = (count * cumulative_average + value) / (count + 1); // Don't quit too quickly for things to start converging, or we may have @@ -108,13 +118,13 @@ TEST(RandUtilTest, RandGeneratorIsUniform) { TEST(RandUtilTest, RandUint64ProducesBothValuesOfAllBits) { // This tests to see that our underlying random generator is good // enough, for some value of good enough. - uint64 kAllZeros = 0ULL; - uint64 kAllOnes = ~kAllZeros; - uint64 found_ones = kAllZeros; - uint64 found_zeros = kAllOnes; + uint64_t kAllZeros = 0ULL; + uint64_t kAllOnes = ~kAllZeros; + uint64_t found_ones = kAllZeros; + uint64_t found_zeros = kAllOnes; for (size_t i = 0; i < 1000; ++i) { - uint64 value = base::RandUint64(); + uint64_t value = base::RandUint64(); found_ones |= value; found_zeros &= value; diff --git a/third_party/chromium/base/scoped_clear_errno.h b/third_party/chromium/base/scoped_clear_errno.h index 7b972fc..585f6f7 100644 --- a/third_party/chromium/base/scoped_clear_errno.h +++ b/third_party/chromium/base/scoped_clear_errno.h @@ -7,7 +7,7 @@ #include <errno.h> -#include "base/basictypes.h" +#include "base/macros.h" namespace base { diff --git a/third_party/chromium/base/scoped_observer.h b/third_party/chromium/base/scoped_observer.h index 422701b..79bcec5 100644 --- a/third_party/chromium/base/scoped_observer.h +++ b/third_party/chromium/base/scoped_observer.h @@ -5,11 +5,13 @@ #ifndef BASE_SCOPED_OBSERVER_H_ #define BASE_SCOPED_OBSERVER_H_ +#include <stddef.h> + #include <algorithm> #include <vector> -#include "base/basictypes.h" #include "base/logging.h" +#include "base/macros.h" // ScopedObserver is used to keep track of the set of sources an object has // attached itself to as an observer. When ScopedObserver is destroyed it @@ -44,8 +46,7 @@ class ScopedObserver { } bool IsObserving(Source* source) const { - return std::find(sources_.begin(), sources_.end(), source) != - sources_.end(); + return ContainsValue(sources_, source); } bool IsObservingSources() const { return !sources_.empty(); } diff --git a/third_party/chromium/base/strings/string_number_conversions.cc b/third_party/chromium/base/strings/string_number_conversions.cc index b5463fb..ac0fd46 100644 --- a/third_party/chromium/base/strings/string_number_conversions.cc +++ b/third_party/chromium/base/strings/string_number_conversions.cc @@ -12,84 +12,44 @@ #include <limits> #include "base/logging.h" -#include "base/scoped_clear_errno.h" -#include "base/third_party/dmg_fp/dmg_fp.h" +#include "base/numerics/safe_conversions.h" +#include "base/numerics/safe_math.h" namespace base { namespace { -template <typename STR, typename INT, typename UINT, bool NEG> +template <typename STR, typename INT> struct IntToStringT { - // This is to avoid a compiler warning about unary minus on unsigned type. - // For example, say you had the following code: - // template <typename INT> - // INT abs(INT value) { return value < 0 ? -value : value; } - // Even though if INT is unsigned, it's impossible for value < 0, so the - // unary minus will never be taken, the compiler will still generate a - // warning. We do a little specialization dance... - template <typename INT2, typename UINT2, bool NEG2> - struct ToUnsignedT {}; - - template <typename INT2, typename UINT2> - struct ToUnsignedT<INT2, UINT2, false> { - static UINT2 ToUnsigned(INT2 value) { - return static_cast<UINT2>(value); - } - }; - - template <typename INT2, typename UINT2> - struct ToUnsignedT<INT2, UINT2, true> { - static UINT2 ToUnsigned(INT2 value) { - return static_cast<UINT2>(value < 0 ? -value : value); - } - }; - - // This set of templates is very similar to the above templates, but - // for testing whether an integer is negative. - template <typename INT2, bool NEG2> - struct TestNegT {}; - template <typename INT2> - struct TestNegT<INT2, false> { - static bool TestNeg(INT2 value) { - // value is unsigned, and can never be negative. - return false; - } - }; - template <typename INT2> - struct TestNegT<INT2, true> { - static bool TestNeg(INT2 value) { - return value < 0; - } - }; - static STR IntToString(INT value) { // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. // So round up to allocate 3 output characters per byte, plus 1 for '-'. - const int kOutputBufSize = 3 * sizeof(INT) + 1; + const size_t kOutputBufSize = + 3 * sizeof(INT) + std::numeric_limits<INT>::is_signed; - // Allocate the whole string right away, we will right back to front, and + // Create the string in a temporary buffer, write it back to front, and // then return the substr of what we ended up using. - STR outbuf(kOutputBufSize, 0); + using CHR = typename STR::value_type; + CHR outbuf[kOutputBufSize]; - bool is_neg = TestNegT<INT, NEG>::TestNeg(value); - // Even though is_neg will never be true when INT is parameterized as - // unsigned, even the presence of the unary operation causes a warning. - UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); + // The ValueOrDie call below can never fail, because UnsignedAbs is valid + // for all valid inputs. + auto res = CheckedNumeric<INT>(value).UnsignedAbs().ValueOrDie(); - typename STR::iterator it(outbuf.end()); + CHR* end = outbuf + kOutputBufSize; + CHR* i = end; do { - --it; - DCHECK(it != outbuf.begin()); - *it = static_cast<typename STR::value_type>((res % 10) + '0'); + --i; + DCHECK(i != outbuf); + *i = static_cast<CHR>((res % 10) + '0'); res /= 10; } while (res != 0); - if (is_neg) { - --it; - DCHECK(it != outbuf.begin()); - *it = static_cast<typename STR::value_type>('-'); + if (IsValueNegative(value)) { + --i; + DCHECK(i != outbuf); + *i = static_cast<CHR>('-'); } - return STR(it, outbuf.end()); + return STR(i, end); } }; @@ -100,9 +60,9 @@ template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { // Faster specialization for bases <= 10 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { public: - static bool Convert(CHAR c, uint8* digit) { + static bool Convert(CHAR c, uint8_t* digit) { if (c >= '0' && c < '0' + BASE) { - *digit = static_cast<uint8>(c - '0'); + *digit = static_cast<uint8_t>(c - '0'); return true; } return false; @@ -112,7 +72,7 @@ template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { // Specialization for bases where 10 < base <= 36 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { public: - static bool Convert(CHAR c, uint8* digit) { + static bool Convert(CHAR c, uint8_t* digit) { if (c >= '0' && c <= '9') { *digit = c - '0'; } else if (c >= 'a' && c < 'a' + BASE - 10) { @@ -126,14 +86,15 @@ template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { } }; -template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) { +template <int BASE, typename CHAR> +bool CharToDigit(CHAR c, uint8_t* digit) { return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit); } -// There is an IsWhitespace for wchars defined in string_util.h, but it is -// locale independent, whereas the functions we are replacing were -// locale-dependent. TBD what is desired, but for the moment let's not introduce -// a change in behaviour. +// There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it +// is locale independent, whereas the functions we are replacing were +// locale-dependent. TBD what is desired, but for the moment let's not +// introduce a change in behaviour. template<typename CHAR> class WhitespaceHelper { }; @@ -216,7 +177,7 @@ class IteratorRangeToNumber { } for (const_iterator current = begin; current != end; ++current) { - uint8 new_digit = 0; + uint8_t new_digit = 0; if (!CharToDigit<traits::kBase>(*current, &new_digit)) { return false; @@ -237,7 +198,7 @@ class IteratorRangeToNumber { class Positive : public Base<Positive> { public: - static bool CheckBounds(value_type* output, uint8 new_digit) { + static bool CheckBounds(value_type* output, uint8_t new_digit) { if (*output > static_cast<value_type>(traits::max() / traits::kBase) || (*output == static_cast<value_type>(traits::max() / traits::kBase) && new_digit > traits::max() % traits::kBase)) { @@ -246,14 +207,14 @@ class IteratorRangeToNumber { } return true; } - static void Increment(uint8 increment, value_type* output) { + static void Increment(uint8_t increment, value_type* output) { *output += increment; } }; class Negative : public Base<Negative> { public: - static bool CheckBounds(value_type* output, uint8 new_digit) { + static bool CheckBounds(value_type* output, uint8_t new_digit) { if (*output < traits::min() / traits::kBase || (*output == traits::min() / traits::kBase && new_digit > 0 - traits::min() % traits::kBase)) { @@ -262,7 +223,7 @@ class IteratorRangeToNumber { } return true; } - static void Increment(uint8 increment, value_type* output) { + static void Increment(uint8_t increment, value_type* output) { *output -= increment; } }; @@ -287,20 +248,17 @@ class BaseHexIteratorRangeToIntTraits : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { }; -template<typename ITERATOR> +template <typename ITERATOR> class BaseHexIteratorRangeToUIntTraits - : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32, 16> { -}; + : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32_t, 16> {}; -template<typename ITERATOR> +template <typename ITERATOR> class BaseHexIteratorRangeToInt64Traits - : public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> { -}; + : public BaseIteratorRangeToNumberTraits<ITERATOR, int64_t, 16> {}; -template<typename ITERATOR> +template <typename ITERATOR> class BaseHexIteratorRangeToUInt64Traits - : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> { -}; + : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64_t, 16> {}; typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> HexIteratorRangeToIntTraits; @@ -314,15 +272,15 @@ typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> HexIteratorRangeToUInt64Traits; -template<typename STR> -bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { +template <typename STR> +bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) { DCHECK_EQ(output->size(), 0u); size_t count = input.size(); if (count == 0 || (count % 2) != 0) return false; for (uintptr_t i = 0; i < count / 2; ++i) { - uint8 msb = 0; // most significant 4 bits - uint8 lsb = 0; // least significant 4 bits + uint8_t msb = 0; // most significant 4 bits + uint8_t lsb = 0; // least significant 4 bits if (!CharToDigit<16>(input[i * 2], &msb) || !CharToDigit<16>(input[i * 2 + 1], &lsb)) return false; @@ -347,32 +305,38 @@ bool StringToIntImpl(const StringPiece& input, VALUE* output) { } // namespace std::string IntToString(int value) { - return IntToStringT<std::string, int, unsigned int, true>:: - IntToString(value); + return IntToStringT<std::string, int>::IntToString(value); } std::string UintToString(unsigned int value) { - return IntToStringT<std::string, unsigned int, unsigned int, false>:: - IntToString(value); + return IntToStringT<std::string, unsigned int>::IntToString(value); } -std::string Int64ToString(int64 value) { - return IntToStringT<std::string, int64, uint64, true>::IntToString(value); +std::string Int64ToString(int64_t value) { + return IntToStringT<std::string, int64_t>::IntToString(value); } -std::string Uint64ToString(uint64 value) { - return IntToStringT<std::string, uint64, uint64, false>::IntToString(value); +std::string Uint64ToString(uint64_t value) { + return IntToStringT<std::string, uint64_t>::IntToString(value); } std::string SizeTToString(size_t value) { - return IntToStringT<std::string, size_t, size_t, false>::IntToString(value); + return IntToStringT<std::string, size_t>::IntToString(value); } std::string DoubleToString(double value) { - // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. - char buffer[32]; - dmg_fp::g_fmt(buffer, value); - return std::string(buffer); + auto ret = std::to_string(value); + // If this returned an integer, don't do anything. + if (ret.find('.') == std::string::npos) { + return ret; + } + // Otherwise, it has an annoying tendency to leave trailing zeros. + size_t len = ret.size(); + while (len >= 2 && ret[len - 1] == '0' && ret[len - 2] != '.') { + --len; + } + ret.erase(len); + return ret; } bool StringToInt(const StringPiece& input, int* output) { @@ -383,11 +347,11 @@ bool StringToUint(const StringPiece& input, unsigned* output) { return StringToIntImpl(input, output); } -bool StringToInt64(const StringPiece& input, int64* output) { +bool StringToInt64(const StringPiece& input, int64_t* output) { return StringToIntImpl(input, output); } -bool StringToUint64(const StringPiece& input, uint64* output) { +bool StringToUint64(const StringPiece& input, uint64_t* output) { return StringToIntImpl(input, output); } @@ -396,14 +360,10 @@ bool StringToSizeT(const StringPiece& input, size_t* output) { } bool StringToDouble(const std::string& input, double* output) { - // Thread-safe? It is on at least Mac, Linux, and Windows. - ScopedClearErrno clear_errno; - - char* endptr = NULL; - *output = dmg_fp::strtod(input.c_str(), &endptr); + char* endptr = nullptr; + *output = strtod(input.c_str(), &endptr); // Cases to return false: - // - If errno is ERANGE, there was an overflow or underflow. // - If the input string is empty, there was nothing to parse. // - If endptr does not point to the end of the string, there are either // characters remaining in the string after a parsed number, or the string @@ -411,10 +371,11 @@ bool StringToDouble(const std::string& input, double* output) { // expected end given the string's stated length to correctly catch cases // where the string contains embedded NUL characters. // - If the first character is a space, there was leading whitespace - return errno == 0 && - !input.empty() && + return !input.empty() && input.c_str() + input.length() == endptr && - !isspace(input[0]); + !isspace(input[0]) && + *output != std::numeric_limits<double>::infinity() && + *output != -std::numeric_limits<double>::infinity(); } // Note: if you need to add String16ToDouble, first ask yourself if it's @@ -444,22 +405,22 @@ bool HexStringToInt(const StringPiece& input, int* output) { input.begin(), input.end(), output); } -bool HexStringToUInt(const StringPiece& input, uint32* output) { +bool HexStringToUInt(const StringPiece& input, uint32_t* output) { return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke( input.begin(), input.end(), output); } -bool HexStringToInt64(const StringPiece& input, int64* output) { +bool HexStringToInt64(const StringPiece& input, int64_t* output) { return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( input.begin(), input.end(), output); } -bool HexStringToUInt64(const StringPiece& input, uint64* output) { +bool HexStringToUInt64(const StringPiece& input, uint64_t* output) { return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( input.begin(), input.end(), output); } -bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { +bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) { return HexStringToBytesT(input, output); } diff --git a/third_party/chromium/base/strings/string_number_conversions.h b/third_party/chromium/base/strings/string_number_conversions.h index c68d0af..af0faa6 100644 --- a/third_party/chromium/base/strings/string_number_conversions.h +++ b/third_party/chromium/base/strings/string_number_conversions.h @@ -5,11 +5,13 @@ #ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_ #define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> #include <vector> #include "base/base_export.h" -#include "base/basictypes.h" #include "base/strings/string_piece.h" // ---------------------------------------------------------------------------- @@ -32,12 +34,13 @@ std::string IntToString(int value); std::string UintToString(unsigned value); -std::string Int64ToString(int64 value); +std::string Int64ToString(int64_t value); -std::string Uint64ToString(uint64 value); +std::string Uint64ToString(uint64_t value); std::string SizeTToString(size_t value); +// Deprecated: prefer std::to_string(double) instead. // DoubleToString converts the double to a string format that ignores the // locale. If you want to use locale specific formatting, use ICU. std::string DoubleToString(double value); @@ -58,22 +61,27 @@ std::string DoubleToString(double value); // - No characters parseable as a number at the beginning of the string. // |*output| will be set to 0. // - Empty string. |*output| will be set to 0. +// WARNING: Will write to |output| even when returning false. +// Read the comments above carefully. bool StringToInt(const StringPiece& input, int* output); bool StringToUint(const StringPiece& input, unsigned* output); -bool StringToInt64(const StringPiece& input, int64* output); +bool StringToInt64(const StringPiece& input, int64_t* output); -bool StringToUint64(const StringPiece& input, uint64* output); +bool StringToUint64(const StringPiece& input, uint64_t* output); bool StringToSizeT(const StringPiece& input, size_t* output); +// Deprecated: prefer std::stod() instead. // For floating-point conversions, only conversions of input strings in decimal // form are defined to work. Behavior with strings representing floating-point -// numbers in hexadecimal, and strings representing non-fininte values (such as +// numbers in hexadecimal, and strings representing non-finite values (such as // NaN and inf) is undefined. Otherwise, these behave the same as the integral // variants. This expects the input string to NOT be specific to the locale. // If your input is locale specific, use ICU to read the number. +// WARNING: Will write to |output| even when returning false. +// Read the comments here and above StringToInt() carefully. bool StringToDouble(const std::string& input, double* output); // Hex encoding ---------------------------------------------------------------- @@ -95,24 +103,25 @@ bool HexStringToInt(const StringPiece& input, int* output); // Will only successful parse hex values that will fit into |output|, i.e. // 0x00000000 < |input| < 0xFFFFFFFF. // The string is not required to start with 0x. -bool HexStringToUInt(const StringPiece& input, uint32* output); +bool HexStringToUInt(const StringPiece& input, uint32_t* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // -0x8000000000000000 < |input| < 0x7FFFFFFFFFFFFFFF. -bool HexStringToInt64(const StringPiece& input, int64* output); +bool HexStringToInt64(const StringPiece& input, int64_t* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // 0x0000000000000000 < |input| < 0xFFFFFFFFFFFFFFFF. // The string is not required to start with 0x. -bool HexStringToUInt64(const StringPiece& input, uint64* output); +bool HexStringToUInt64(const StringPiece& input, uint64_t* output); // Similar to the previous functions, except that output is a vector of bytes. // |*output| will contain as many bytes as were successfully parsed prior to the // error. There is no overflow, but input.size() must be evenly divisible by 2. // Leading 0x or +/- are not allowed. -bool HexStringToBytes(const std::string& input, std::vector<uint8>* output); +bool HexStringToBytes(const std::string& input, + std::vector<uint8_t>* output); } // namespace base diff --git a/third_party/chromium/base/strings/string_number_conversions_unittest.cc b/third_party/chromium/base/strings/string_number_conversions_unittest.cc index 80d1471..1cfb2c8 100644 --- a/third_party/chromium/base/strings/string_number_conversions_unittest.cc +++ b/third_party/chromium/base/strings/string_number_conversions_unittest.cc @@ -5,6 +5,8 @@ #include "base/strings/string_number_conversions.h" #include <errno.h> +#include <limits.h> +#include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -13,6 +15,7 @@ #include <gtest/gtest.h> +#include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversion_utils.h" @@ -36,15 +39,15 @@ TEST(StringNumberConversionsTest, IntToString) { { std::numeric_limits<int>::max(), "2147483647", "2147483647" }, { std::numeric_limits<int>::min(), "-2147483648", "2147483648" }, }; - static const IntToStringTest<int64> int64_tests[] = { - { 0, "0", "0" }, - { -1, "-1", "18446744073709551615" }, - { std::numeric_limits<int64>::max(), - "9223372036854775807", - "9223372036854775807", }, - { std::numeric_limits<int64>::min(), - "-9223372036854775808", - "9223372036854775808" }, + static const IntToStringTest<int64_t> int64_tests[] = { + {0, "0", "0"}, + {-1, "-1", "18446744073709551615"}, + { + std::numeric_limits<int64_t>::max(), "9223372036854775807", + "9223372036854775807", + }, + {std::numeric_limits<int64_t>::min(), "-9223372036854775808", + "9223372036854775808"}, }; for (size_t i = 0; i < arraysize(int_tests); ++i) { @@ -53,7 +56,7 @@ TEST(StringNumberConversionsTest, IntToString) { EXPECT_EQ(UintToString(test->num), test->uexpected); } for (size_t i = 0; i < arraysize(int64_tests); ++i) { - const IntToStringTest<int64>* test = &int64_tests[i]; + const IntToStringTest<int64_t>* test = &int64_tests[i]; EXPECT_EQ(Int64ToString(test->num), test->sexpected); EXPECT_EQ(Uint64ToString(test->num), test->uexpected); } @@ -61,13 +64,13 @@ TEST(StringNumberConversionsTest, IntToString) { TEST(StringNumberConversionsTest, Uint64ToString) { static const struct { - uint64 input; + uint64_t input; std::string output; } cases[] = { - {0, "0"}, - {42, "42"}, - {INT_MAX, "2147483647"}, - {kuint64max, "18446744073709551615"}, + {0, "0"}, + {42, "42"}, + {INT_MAX, "2147483647"}, + {std::numeric_limits<uint64_t>::max(), "18446744073709551615"}, }; for (size_t i = 0; i < arraysize(cases); ++i) @@ -197,44 +200,44 @@ TEST(StringNumberConversionsTest, StringToUint) { TEST(StringNumberConversionsTest, StringToInt64) { static const struct { std::string input; - int64 output; + int64_t output; bool success; } cases[] = { - {"0", 0, true}, - {"42", 42, true}, - {"-2147483648", INT_MIN, true}, - {"2147483647", INT_MAX, true}, - {"-2147483649", INT64_C(-2147483649), true}, - {"-99999999999", INT64_C(-99999999999), true}, - {"2147483648", INT64_C(2147483648), true}, - {"99999999999", INT64_C(99999999999), true}, - {"9223372036854775807", kint64max, true}, - {"-9223372036854775808", kint64min, true}, - {"09", 9, true}, - {"-09", -9, true}, - {"", 0, false}, - {" 42", 42, false}, - {"42 ", 42, false}, - {"0x42", 0, false}, - {"\t\n\v\f\r 42", 42, false}, - {"blah42", 0, false}, - {"42blah", 42, false}, - {"blah42blah", 0, false}, - {"-273.15", -273, false}, - {"+98.6", 98, false}, - {"--123", 0, false}, - {"++123", 0, false}, - {"-+123", 0, false}, - {"+-123", 0, false}, - {"-", 0, false}, - {"-9223372036854775809", kint64min, false}, - {"-99999999999999999999", kint64min, false}, - {"9223372036854775808", kint64max, false}, - {"99999999999999999999", kint64max, false}, + {"0", 0, true}, + {"42", 42, true}, + {"-2147483648", INT_MIN, true}, + {"2147483647", INT_MAX, true}, + {"-2147483649", INT64_C(-2147483649), true}, + {"-99999999999", INT64_C(-99999999999), true}, + {"2147483648", INT64_C(2147483648), true}, + {"99999999999", INT64_C(99999999999), true}, + {"9223372036854775807", std::numeric_limits<int64_t>::max(), true}, + {"-9223372036854775808", std::numeric_limits<int64_t>::min(), true}, + {"09", 9, true}, + {"-09", -9, true}, + {"", 0, false}, + {" 42", 42, false}, + {"42 ", 42, false}, + {"0x42", 0, false}, + {"\t\n\v\f\r 42", 42, false}, + {"blah42", 0, false}, + {"42blah", 42, false}, + {"blah42blah", 0, false}, + {"-273.15", -273, false}, + {"+98.6", 98, false}, + {"--123", 0, false}, + {"++123", 0, false}, + {"-+123", 0, false}, + {"+-123", 0, false}, + {"-", 0, false}, + {"-9223372036854775809", std::numeric_limits<int64_t>::min(), false}, + {"-99999999999999999999", std::numeric_limits<int64_t>::min(), false}, + {"9223372036854775808", std::numeric_limits<int64_t>::max(), false}, + {"99999999999999999999", std::numeric_limits<int64_t>::max(), false}, }; for (size_t i = 0; i < arraysize(cases); ++i) { - int64 output = 0; + int64_t output = 0; EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output)); EXPECT_EQ(cases[i].output, output); } @@ -244,7 +247,7 @@ TEST(StringNumberConversionsTest, StringToInt64) { // interpreted as junk after the number. const char input[] = "6\06"; std::string input_string(input, arraysize(input) - 1); - int64 output; + int64_t output; EXPECT_FALSE(StringToInt64(input_string, &output)); EXPECT_EQ(6, output); } @@ -252,46 +255,46 @@ TEST(StringNumberConversionsTest, StringToInt64) { TEST(StringNumberConversionsTest, StringToUint64) { static const struct { std::string input; - uint64 output; + uint64_t output; bool success; } cases[] = { - {"0", 0, true}, - {"42", 42, true}, - {"-2147483648", 0, false}, - {"2147483647", INT_MAX, true}, - {"-2147483649", 0, false}, - {"-99999999999", 0, false}, - {"2147483648", UINT64_C(2147483648), true}, - {"99999999999", UINT64_C(99999999999), true}, - {"9223372036854775807", kint64max, true}, - {"-9223372036854775808", 0, false}, - {"09", 9, true}, - {"-09", 0, false}, - {"", 0, false}, - {" 42", 42, false}, - {"42 ", 42, false}, - {"0x42", 0, false}, - {"\t\n\v\f\r 42", 42, false}, - {"blah42", 0, false}, - {"42blah", 42, false}, - {"blah42blah", 0, false}, - {"-273.15", 0, false}, - {"+98.6", 98, false}, - {"--123", 0, false}, - {"++123", 0, false}, - {"-+123", 0, false}, - {"+-123", 0, false}, - {"-", 0, false}, - {"-9223372036854775809", 0, false}, - {"-99999999999999999999", 0, false}, - {"9223372036854775808", UINT64_C(9223372036854775808), true}, - {"99999999999999999999", kuint64max, false}, - {"18446744073709551615", kuint64max, true}, - {"18446744073709551616", kuint64max, false}, + {"0", 0, true}, + {"42", 42, true}, + {"-2147483648", 0, false}, + {"2147483647", INT_MAX, true}, + {"-2147483649", 0, false}, + {"-99999999999", 0, false}, + {"2147483648", UINT64_C(2147483648), true}, + {"99999999999", UINT64_C(99999999999), true}, + {"9223372036854775807", std::numeric_limits<int64_t>::max(), true}, + {"-9223372036854775808", 0, false}, + {"09", 9, true}, + {"-09", 0, false}, + {"", 0, false}, + {" 42", 42, false}, + {"42 ", 42, false}, + {"0x42", 0, false}, + {"\t\n\v\f\r 42", 42, false}, + {"blah42", 0, false}, + {"42blah", 42, false}, + {"blah42blah", 0, false}, + {"-273.15", 0, false}, + {"+98.6", 98, false}, + {"--123", 0, false}, + {"++123", 0, false}, + {"-+123", 0, false}, + {"+-123", 0, false}, + {"-", 0, false}, + {"-9223372036854775809", 0, false}, + {"-99999999999999999999", 0, false}, + {"9223372036854775808", UINT64_C(9223372036854775808), true}, + {"99999999999999999999", std::numeric_limits<uint64_t>::max(), false}, + {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true}, + {"18446744073709551616", std::numeric_limits<uint64_t>::max(), false}, }; for (size_t i = 0; i < arraysize(cases); ++i) { - uint64 output = 0; + uint64_t output = 0; EXPECT_EQ(cases[i].success, StringToUint64(cases[i].input, &output)); EXPECT_EQ(cases[i].output, output); } @@ -301,7 +304,7 @@ TEST(StringNumberConversionsTest, StringToUint64) { // interpreted as junk after the number. const char input[] = "6\06"; std::string input_string(input, arraysize(input) - 1); - uint64 output; + uint64_t output; EXPECT_FALSE(StringToUint64(input_string, &output)); EXPECT_EQ(6U, output); } @@ -368,7 +371,7 @@ TEST(StringNumberConversionsTest, StringToSizeT) { TEST(StringNumberConversionsTest, HexStringToInt) { static const struct { std::string input; - int64 output; + int64_t output; bool success; } cases[] = { {"0", 0, true}, @@ -420,50 +423,55 @@ TEST(StringNumberConversionsTest, HexStringToInt) { TEST(StringNumberConversionsTest, HexStringToUInt) { static const struct { std::string input; - uint32 output; + uint32_t output; bool success; } cases[] = { - {"0", 0, true}, - {"42", 0x42, true}, - {"-42", 0, false}, - {"+42", 0x42, true}, - {"7fffffff", INT_MAX, true}, - {"-80000000", 0, false}, - {"ffffffff", 0xffffffff, true}, - {"DeadBeef", 0xdeadbeef, true}, - {"0x42", 0x42, true}, - {"-0x42", 0, false}, - {"+0x42", 0x42, true}, - {"0x7fffffff", INT_MAX, true}, - {"-0x80000000", 0, false}, - {"0xffffffff", kuint32max, true}, - {"0XDeadBeef", 0xdeadbeef, true}, - {"0x7fffffffffffffff", kuint32max, false}, // Overflow test. - {"-0x8000000000000000", 0, false}, - {"0x8000000000000000", kuint32max, false}, // Overflow test. - {"-0x8000000000000001", 0, false}, - {"0xFFFFFFFFFFFFFFFF", kuint32max, false}, // Overflow test. - {"FFFFFFFFFFFFFFFF", kuint32max, false}, // Overflow test. - {"0x0000000000000000", 0, true}, - {"0000000000000000", 0, true}, - {"1FFFFFFFFFFFFFFFF", kuint32max, false}, // Overflow test. - {"0x0f", 0x0f, true}, - {"0f", 0x0f, true}, - {" 45", 0x45, false}, - {"\t\n\v\f\r 0x45", 0x45, false}, - {" 45", 0x45, false}, - {"45 ", 0x45, false}, - {"45:", 0x45, false}, - {"efgh", 0xef, false}, - {"0xefgh", 0xef, false}, - {"hgfe", 0, false}, - {"-", 0, false}, - {"", 0, false}, - {"0x", 0, false}, + {"0", 0, true}, + {"42", 0x42, true}, + {"-42", 0, false}, + {"+42", 0x42, true}, + {"7fffffff", INT_MAX, true}, + {"-80000000", 0, false}, + {"ffffffff", 0xffffffff, true}, + {"DeadBeef", 0xdeadbeef, true}, + {"0x42", 0x42, true}, + {"-0x42", 0, false}, + {"+0x42", 0x42, true}, + {"0x7fffffff", INT_MAX, true}, + {"-0x80000000", 0, false}, + {"0xffffffff", std::numeric_limits<uint32_t>::max(), true}, + {"0XDeadBeef", 0xdeadbeef, true}, + {"0x7fffffffffffffff", std::numeric_limits<uint32_t>::max(), + false}, // Overflow test. + {"-0x8000000000000000", 0, false}, + {"0x8000000000000000", std::numeric_limits<uint32_t>::max(), + false}, // Overflow test. + {"-0x8000000000000001", 0, false}, + {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(), + false}, // Overflow test. + {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(), + false}, // Overflow test. + {"0x0000000000000000", 0, true}, + {"0000000000000000", 0, true}, + {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(), + false}, // Overflow test. + {"0x0f", 0x0f, true}, + {"0f", 0x0f, true}, + {" 45", 0x45, false}, + {"\t\n\v\f\r 0x45", 0x45, false}, + {" 45", 0x45, false}, + {"45 ", 0x45, false}, + {"45:", 0x45, false}, + {"efgh", 0xef, false}, + {"0xefgh", 0xef, false}, + {"hgfe", 0, false}, + {"-", 0, false}, + {"", 0, false}, + {"0x", 0, false}, }; for (size_t i = 0; i < arraysize(cases); ++i) { - uint32 output = 0; + uint32_t output = 0; EXPECT_EQ(cases[i].success, HexStringToUInt(cases[i].input, &output)); EXPECT_EQ(cases[i].output, output); } @@ -472,7 +480,7 @@ TEST(StringNumberConversionsTest, HexStringToUInt) { // interpreted as junk after the number. const char input[] = "0xc0ffee\0" "9"; std::string input_string(input, arraysize(input) - 1); - uint32 output; + uint32_t output; EXPECT_FALSE(HexStringToUInt(input_string, &output)); EXPECT_EQ(0xc0ffeeU, output); } @@ -480,47 +488,49 @@ TEST(StringNumberConversionsTest, HexStringToUInt) { TEST(StringNumberConversionsTest, HexStringToInt64) { static const struct { std::string input; - int64 output; + int64_t output; bool success; } cases[] = { - {"0", 0, true}, - {"42", 66, true}, - {"-42", -66, true}, - {"+42", 66, true}, - {"40acd88557b", INT64_C(4444444448123), true}, - {"7fffffff", INT_MAX, true}, - {"-80000000", INT_MIN, true}, - {"ffffffff", 0xffffffff, true}, - {"DeadBeef", 0xdeadbeef, true}, - {"0x42", 66, true}, - {"-0x42", -66, true}, - {"+0x42", 66, true}, - {"0x40acd88557b", INT64_C(4444444448123), true}, - {"0x7fffffff", INT_MAX, true}, - {"-0x80000000", INT_MIN, true}, - {"0xffffffff", 0xffffffff, true}, - {"0XDeadBeef", 0xdeadbeef, true}, - {"0x7fffffffffffffff", kint64max, true}, - {"-0x8000000000000000", kint64min, true}, - {"0x8000000000000000", kint64max, false}, // Overflow test. - {"-0x8000000000000001", kint64min, false}, // Underflow test. - {"0x0f", 15, true}, - {"0f", 15, true}, - {" 45", 0x45, false}, - {"\t\n\v\f\r 0x45", 0x45, false}, - {" 45", 0x45, false}, - {"45 ", 0x45, false}, - {"45:", 0x45, false}, - {"efgh", 0xef, false}, - {"0xefgh", 0xef, false}, - {"hgfe", 0, false}, - {"-", 0, false}, - {"", 0, false}, - {"0x", 0, false}, + {"0", 0, true}, + {"42", 66, true}, + {"-42", -66, true}, + {"+42", 66, true}, + {"40acd88557b", INT64_C(4444444448123), true}, + {"7fffffff", INT_MAX, true}, + {"-80000000", INT_MIN, true}, + {"ffffffff", 0xffffffff, true}, + {"DeadBeef", 0xdeadbeef, true}, + {"0x42", 66, true}, + {"-0x42", -66, true}, + {"+0x42", 66, true}, + {"0x40acd88557b", INT64_C(4444444448123), true}, + {"0x7fffffff", INT_MAX, true}, + {"-0x80000000", INT_MIN, true}, + {"0xffffffff", 0xffffffff, true}, + {"0XDeadBeef", 0xdeadbeef, true}, + {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true}, + {"-0x8000000000000000", std::numeric_limits<int64_t>::min(), true}, + {"0x8000000000000000", std::numeric_limits<int64_t>::max(), + false}, // Overflow test. + {"-0x8000000000000001", std::numeric_limits<int64_t>::min(), + false}, // Underflow test. + {"0x0f", 15, true}, + {"0f", 15, true}, + {" 45", 0x45, false}, + {"\t\n\v\f\r 0x45", 0x45, false}, + {" 45", 0x45, false}, + {"45 ", 0x45, false}, + {"45:", 0x45, false}, + {"efgh", 0xef, false}, + {"0xefgh", 0xef, false}, + {"hgfe", 0, false}, + {"-", 0, false}, + {"", 0, false}, + {"0x", 0, false}, }; for (size_t i = 0; i < arraysize(cases); ++i) { - int64 output = 0; + int64_t output = 0; EXPECT_EQ(cases[i].success, HexStringToInt64(cases[i].input, &output)); EXPECT_EQ(cases[i].output, output); } @@ -529,7 +539,7 @@ TEST(StringNumberConversionsTest, HexStringToInt64) { // interpreted as junk after the number. const char input[] = "0xc0ffee\0" "9"; std::string input_string(input, arraysize(input) - 1); - int64 output; + int64_t output; EXPECT_FALSE(HexStringToInt64(input_string, &output)); EXPECT_EQ(0xc0ffee, output); } @@ -537,52 +547,53 @@ TEST(StringNumberConversionsTest, HexStringToInt64) { TEST(StringNumberConversionsTest, HexStringToUInt64) { static const struct { std::string input; - uint64 output; + uint64_t output; bool success; } cases[] = { - {"0", 0, true}, - {"42", 66, true}, - {"-42", 0, false}, - {"+42", 66, true}, - {"40acd88557b", INT64_C(4444444448123), true}, - {"7fffffff", INT_MAX, true}, - {"-80000000", 0, false}, - {"ffffffff", 0xffffffff, true}, - {"DeadBeef", 0xdeadbeef, true}, - {"0x42", 66, true}, - {"-0x42", 0, false}, - {"+0x42", 66, true}, - {"0x40acd88557b", INT64_C(4444444448123), true}, - {"0x7fffffff", INT_MAX, true}, - {"-0x80000000", 0, false}, - {"0xffffffff", 0xffffffff, true}, - {"0XDeadBeef", 0xdeadbeef, true}, - {"0x7fffffffffffffff", kint64max, true}, - {"-0x8000000000000000", 0, false}, - {"0x8000000000000000", UINT64_C(0x8000000000000000), true}, - {"-0x8000000000000001", 0, false}, - {"0xFFFFFFFFFFFFFFFF", kuint64max, true}, - {"FFFFFFFFFFFFFFFF", kuint64max, true}, - {"0x0000000000000000", 0, true}, - {"0000000000000000", 0, true}, - {"1FFFFFFFFFFFFFFFF", kuint64max, false}, // Overflow test. - {"0x0f", 15, true}, - {"0f", 15, true}, - {" 45", 0x45, false}, - {"\t\n\v\f\r 0x45", 0x45, false}, - {" 45", 0x45, false}, - {"45 ", 0x45, false}, - {"45:", 0x45, false}, - {"efgh", 0xef, false}, - {"0xefgh", 0xef, false}, - {"hgfe", 0, false}, - {"-", 0, false}, - {"", 0, false}, - {"0x", 0, false}, + {"0", 0, true}, + {"42", 66, true}, + {"-42", 0, false}, + {"+42", 66, true}, + {"40acd88557b", INT64_C(4444444448123), true}, + {"7fffffff", INT_MAX, true}, + {"-80000000", 0, false}, + {"ffffffff", 0xffffffff, true}, + {"DeadBeef", 0xdeadbeef, true}, + {"0x42", 66, true}, + {"-0x42", 0, false}, + {"+0x42", 66, true}, + {"0x40acd88557b", INT64_C(4444444448123), true}, + {"0x7fffffff", INT_MAX, true}, + {"-0x80000000", 0, false}, + {"0xffffffff", 0xffffffff, true}, + {"0XDeadBeef", 0xdeadbeef, true}, + {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true}, + {"-0x8000000000000000", 0, false}, + {"0x8000000000000000", UINT64_C(0x8000000000000000), true}, + {"-0x8000000000000001", 0, false}, + {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true}, + {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true}, + {"0x0000000000000000", 0, true}, + {"0000000000000000", 0, true}, + {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), + false}, // Overflow test. + {"0x0f", 15, true}, + {"0f", 15, true}, + {" 45", 0x45, false}, + {"\t\n\v\f\r 0x45", 0x45, false}, + {" 45", 0x45, false}, + {"45 ", 0x45, false}, + {"45:", 0x45, false}, + {"efgh", 0xef, false}, + {"0xefgh", 0xef, false}, + {"hgfe", 0, false}, + {"-", 0, false}, + {"", 0, false}, + {"0x", 0, false}, }; for (size_t i = 0; i < arraysize(cases); ++i) { - uint64 output = 0; + uint64_t output = 0; EXPECT_EQ(cases[i].success, HexStringToUInt64(cases[i].input, &output)); EXPECT_EQ(cases[i].output, output); } @@ -591,7 +602,7 @@ TEST(StringNumberConversionsTest, HexStringToUInt64) { // interpreted as junk after the number. const char input[] = "0xc0ffee\0" "9"; std::string input_string(input, arraysize(input) - 1); - uint64 output; + uint64_t output; EXPECT_FALSE(HexStringToUInt64(input_string, &output)); EXPECT_EQ(0xc0ffeeU, output); } @@ -624,12 +635,12 @@ TEST(StringNumberConversionsTest, HexStringToBytes) { for (size_t i = 0; i < arraysize(cases); ++i) { - std::vector<uint8> output; - std::vector<uint8> compare; + std::vector<uint8_t> output; + std::vector<uint8_t> compare; EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) << i << ": " << cases[i].input; for (size_t j = 0; j < cases[i].output_len; ++j) - compare.push_back(static_cast<uint8>(cases[i].output[j])); + compare.push_back(static_cast<uint8_t>(cases[i].output[j])); ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input; EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) << i << ": " << cases[i].input; @@ -651,8 +662,10 @@ TEST(StringNumberConversionsTest, StringToDouble) { {"2.99792458e8", 299792458.0, true}, {"149597870.691E+3", 149597870691.0, true}, {"6.", 6.0, true}, - {"9e99999999999999999999", HUGE_VAL, false}, - {"-9e99999999999999999999", -HUGE_VAL, false}, + {"9e99999999999999999999", std::numeric_limits<double>::infinity(), + false}, + {"-9e99999999999999999999", -std::numeric_limits<double>::infinity(), + false}, {"1e-2", 0.01, true}, {"42 ", 42.0, false}, {" 1e-2", 0.01, false}, @@ -675,7 +688,8 @@ TEST(StringNumberConversionsTest, StringToDouble) { for (size_t i = 0; i < arraysize(cases); ++i) { double output; errno = 1; - EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output)); + EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output)) + << "for input=" << cases[i].input << "got output=" << output; if (cases[i].success) EXPECT_EQ(1, errno) << i; // confirm that errno is unchanged. EXPECT_DOUBLE_EQ(cases[i].output, output); @@ -696,13 +710,13 @@ TEST(StringNumberConversionsTest, DoubleToString) { double input; const char* expected; } cases[] = { - {0.0, "0"}, + {0.0, "0.0"}, {1.25, "1.25"}, - {1.33518e+012, "1.33518e+12"}, - {1.33489e+012, "1.33489e+12"}, - {1.33505e+012, "1.33505e+12"}, - {1.33545e+009, "1335450000"}, - {1.33503e+009, "1335030000"}, + {1.33518e+012, "1335180000000.0"}, + {1.33489e+012, "1334890000000.0"}, + {1.33505e+012, "1335050000000.0"}, + {1.33545e+009, "1335450000.0"}, + {1.33503e+009, "1335030000.0"}, }; for (size_t i = 0; i < arraysize(cases); ++i) { @@ -713,12 +727,12 @@ TEST(StringNumberConversionsTest, DoubleToString) { const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'}; double input = 0; memcpy(&input, input_bytes, arraysize(input_bytes)); - EXPECT_EQ("1335179083776", DoubleToString(input)); + EXPECT_EQ("1335179083776.0", DoubleToString(input)); const char input_bytes2[8] = {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'}; input = 0; memcpy(&input, input_bytes2, arraysize(input_bytes2)); - EXPECT_EQ("1334890332160", DoubleToString(input)); + EXPECT_EQ("1334890332160.0", DoubleToString(input)); } TEST(StringNumberConversionsTest, HexEncode) { diff --git a/third_party/chromium/base/strings/string_piece.cc b/third_party/chromium/base/strings/string_piece.cc index aa0695d..482c9fc 100644 --- a/third_party/chromium/base/strings/string_piece.cc +++ b/third_party/chromium/base/strings/string_piece.cc @@ -5,9 +5,13 @@ #include "base/strings/string_piece.h" +#include <limits.h> + #include <algorithm> #include <ostream> +#include "base/logging.h" + namespace base { namespace { diff --git a/third_party/chromium/base/strings/string_piece.h b/third_party/chromium/base/strings/string_piece.h index 14ee635..c79d9fa 100644 --- a/third_party/chromium/base/strings/string_piece.h +++ b/third_party/chromium/base/strings/string_piece.h @@ -28,7 +28,7 @@ #include <string> #include "base/base_export.h" -#include "base/basictypes.h" +#include "base/logging.h" namespace base { @@ -112,9 +112,13 @@ template <typename STRING_TYPE> class BasicStringPiece { BasicStringPiece(const value_type* offset, size_type len) : ptr_(offset), length_(len) {} BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, - const typename STRING_TYPE::const_iterator& end) - : ptr_((end > begin) ? &(*begin) : NULL), - length_((end > begin) ? (size_type)(end - begin) : 0) {} + const typename STRING_TYPE::const_iterator& end) { + length_ = static_cast<size_t>(std::distance(begin, end)); + + // The length test before assignment is to avoid dereferencing an iterator + // that may point to the end() of a string. + ptr_ = length_ > 0 ? &*begin : nullptr; + } // data() may return a pointer to a buffer with embedded NULs, and the // returned buffer may or may not be null terminated. Therefore it is @@ -283,12 +287,12 @@ BasicStringPiece<STRING_TYPE>::npos = // MSVC doesn't like complex extern templates and DLLs. #if !defined(COMPILER_MSVC) -extern template class BasicStringPiece<std::string>; +extern template class BASE_EXPORT BasicStringPiece<std::string>; #endif // StingPiece operators -------------------------------------------------------- -bool operator==(const StringPiece& x, const StringPiece& y); +BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); inline bool operator!=(const StringPiece& x, const StringPiece& y) { return !(x == y); diff --git a/third_party/chromium/base/strings/string_piece_unittest.cc b/third_party/chromium/base/strings/string_piece_unittest.cc index 2c2b0a6..5772acd 100644 --- a/third_party/chromium/base/strings/string_piece_unittest.cc +++ b/third_party/chromium/base/strings/string_piece_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <stddef.h> + #include <string> #include <gtest/gtest.h> diff --git a/third_party/chromium/base/strings/string_util.cc b/third_party/chromium/base/strings/string_util.cc index 4042b39..eb0c546 100644 --- a/third_party/chromium/base/strings/string_util.cc +++ b/third_party/chromium/base/strings/string_util.cc @@ -4,9 +4,14 @@ #include "base/strings/string_util.h" +#include <stdint.h> +#include <limits> +#include "base/macros.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/third_party/icu/icu_utf.h" +namespace base { + namespace { typedef uintptr_t MachineWord; @@ -30,8 +35,72 @@ template<> struct NonASCIIMask<8, char> { }; } // namespace +namespace { -namespace base { +template<typename StringType> +StringType ToLowerASCIIImpl(BasicStringPiece<StringType> str) { + StringType ret; + ret.reserve(str.size()); + for (size_t i = 0; i < str.size(); i++) + ret.push_back(ToLowerASCII(str[i])); + return ret; +} + +template<typename StringType> +StringType ToUpperASCIIImpl(BasicStringPiece<StringType> str) { + StringType ret; + ret.reserve(str.size()); + for (size_t i = 0; i < str.size(); i++) + ret.push_back(ToUpperASCII(str[i])); + return ret; +} + +} // namespace + +std::string ToLowerASCII(StringPiece str) { + return ToLowerASCIIImpl<std::string>(str); +} + +std::string ToUpperASCII(StringPiece str) { + return ToUpperASCIIImpl<std::string>(str); +} + +template<class StringType> +int CompareCaseInsensitiveASCIIT(BasicStringPiece<StringType> a, + BasicStringPiece<StringType> b) { + // Find the first characters that aren't equal and compare them. If the end + // of one of the strings is found before a nonequal character, the lengths + // of the strings are compared. + size_t i = 0; + while (i < a.length() && i < b.length()) { + typename StringType::value_type lower_a = ToLowerASCII(a[i]); + typename StringType::value_type lower_b = ToLowerASCII(b[i]); + if (lower_a < lower_b) + return -1; + if (lower_a > lower_b) + return 1; + i++; + } + + // End of one string hit before finding a different character. Expect the + // common case to be "strings equal" at this point so check that first. + if (a.length() == b.length()) + return 0; + + if (a.length() < b.length()) + return -1; + return 1; +} + +int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) { + return CompareCaseInsensitiveASCIIT<std::string>(a, b); +} + +bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) { + if (a.length() != b.length()) + return false; + return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0; +} template<typename STR> bool ReplaceCharsT(const STR& input, @@ -54,7 +123,7 @@ bool ReplaceCharsT(const STR& input, } bool ReplaceChars(const std::string& input, - const base::StringPiece& replace_chars, + const StringPiece& replace_chars, const std::string& replace_with, std::string* output) { return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); @@ -97,7 +166,7 @@ TrimPositions TrimStringT(const Str& input, } bool TrimString(const std::string& input, - base::StringPiece trim_chars, + StringPiece trim_chars, std::string* output) { return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; } @@ -114,7 +183,7 @@ BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input, } StringPiece TrimString(StringPiece input, - const base::StringPiece& trim_chars, + const StringPiece& trim_chars, TrimPositions positions) { return TrimStringPieceT(input, trim_chars, positions); } @@ -161,11 +230,11 @@ bool IsStringASCII(const StringPiece& str) { bool IsStringUTF8(const StringPiece& str) { const char *src = str.data(); - int32 src_len = static_cast<int32>(str.length()); - int32 char_index = 0; + int32_t src_len = static_cast<int32_t>(str.length()); + int32_t char_index = 0; while (char_index < src_len) { - int32 code_point; + int32_t code_point; CBU8_NEXT(src, char_index, src_len, code_point); if (!IsValidCharacter(code_point)) return false; diff --git a/third_party/chromium/base/strings/string_util.h b/third_party/chromium/base/strings/string_util.h index 4b41357..d6b6e10 100644 --- a/third_party/chromium/base/strings/string_util.h +++ b/third_party/chromium/base/strings/string_util.h @@ -9,14 +9,15 @@ #include <ctype.h> #include <stdarg.h> // va_list +#include <stddef.h> +#include <stdint.h> #include <string> #include <vector> -#include "base/base_export.h" -#include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/strings/string_piece.h" // For implicit conversions. +#include "build/build_config.h" // On Android, bionic's stdio.h defines an snprintf macro when being built with // clang. Undefine it here so it won't collide with base::snprintf(). @@ -24,10 +25,10 @@ namespace base { -// C standard-library functions like "strncasecmp" and "snprintf" that aren't -// cross-platform are provided as "base::strncasecmp", and their prototypes -// are listed below. These functions are then implemented as inline calls -// to the platform-specific equivalents in the platform-specific headers. +// C standard-library functions that aren't cross-platform are provided as +// "base::...", and their prototypes are listed below. These functions are +// then implemented as inline calls to the platform-specific equivalents in the +// platform-specific headers. // Wrapper for vsnprintf that always null-terminates and always returns the // number of characters that would be in an untruncated formatted @@ -39,9 +40,14 @@ int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) // We separate the declaration from the implementation of this inline // function just so the PRINTF_FORMAT works. -inline int snprintf(char* buffer, size_t size, const char* format, ...) - PRINTF_FORMAT(3, 4); -inline int snprintf(char* buffer, size_t size, const char* format, ...) { +inline int snprintf(char* buffer, + size_t size, + _Printf_format_string_ const char* format, + ...) PRINTF_FORMAT(3, 4); +inline int snprintf(char* buffer, + size_t size, + _Printf_format_string_ const char* format, + ...) { va_list arguments; va_start(arguments, format); int result = vsnprintf(buffer, size, format, arguments); @@ -49,6 +55,59 @@ inline int snprintf(char* buffer, size_t size, const char* format, ...) { return result; } +// BSD-style safe and consistent string copy functions. +// Copies |src| to |dst|, where |dst_size| is the total allocated size of |dst|. +// Copies at most |dst_size|-1 characters, and always NULL terminates |dst|, as +// long as |dst_size| is not 0. Returns the length of |src| in characters. +// If the return value is >= dst_size, then the output was truncated. +// NOTE: All sizes are in number of characters, NOT in bytes. +size_t strlcpy(char* dst, const char* src, size_t dst_size); + +// ASCII-specific tolower. The standard library's tolower is locale sensitive, +// so we don't want to use it here. +inline char ToLowerASCII(char c) { + return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; +} + +// ASCII-specific toupper. The standard library's toupper is locale sensitive, +// so we don't want to use it here. +inline char ToUpperASCII(char c) { + return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; +} +// Converts the given string to it's ASCII-lowercase equivalent. +std::string ToLowerASCII(StringPiece str); +// Converts the given string to it's ASCII-uppercase equivalent. +std::string ToUpperASCII(StringPiece str); + +// Functor for case-insensitive ASCII comparisons for STL algorithms like +// std::search. +// +// Note that a full Unicode version of this functor is not possible to write +// because case mappings might change the number of characters, depend on +// context (combining accents), and require handling UTF-16. If you need +// proper Unicode support, use base::i18n::ToLower/FoldCase and then just +// use a normal operator== on the result. +template<typename Char> struct CaseInsensitiveCompareASCII { + public: + bool operator()(Char x, Char y) const { + return ToLowerASCII(x) == ToLowerASCII(y); + } +}; + +// Like strcasecmp for case-insensitive ASCII characters only. Returns: +// -1 (a < b) +// 0 (a == b) +// 1 (a > b) +// (unlike strcasecmp which can return values greater or less than 1/-1). For +// full Unicode support, use base::i18n::ToLower or base::i18h::FoldCase +// and then just call the normal string operators on the result. +int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b); + +// Equality for ASCII case-insensitive comparisons. For full Unicode support, +// use base::i18n::ToLower or base::i18h::FoldCase and then compare with either +// == or !=. +bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b); + // Contains the set of characters representing whitespace in the corresponding // encoding. Null-terminated. The ASCII versions are the whitespaces as defined // by HTML5, and don't include control characters. @@ -60,7 +119,7 @@ extern const char kWhitespaceASCII[]; // |replace_chars| must be null-terminated. // NOTE: Safe to use the same variable for both |input| and |output|. bool ReplaceChars(const std::string& input, - const base::StringPiece& replace_chars, + const StringPiece& replace_chars, const std::string& replace_with, std::string* output); @@ -77,32 +136,26 @@ enum TrimPositions { // It is safe to use the same variable for both |input| and |output| (this is // the normal usage to trim in-place). bool TrimString(const std::string& input, - base::StringPiece trim_chars, + StringPiece trim_chars, std::string* output); // StringPiece versions of the above. The returned pieces refer to the original // buffer. StringPiece TrimString(StringPiece input, - const base::StringPiece& trim_chars, + const StringPiece& trim_chars, TrimPositions positions); -// Trims any whitespace from either end of the input string. Returns where -// whitespace was found. -// The non-wide version has two functions: -// * TrimWhitespaceASCII() -// This function is for ASCII strings and only looks for ASCII whitespace; -// Please choose the best one according to your usage. +// Trims any whitespace from either end of the input string. +// +// The StringPiece versions return a substring referencing the input buffer. +// The ASCII versions look only for ASCII whitespace. +// +// The std::string versions return where whitespace was found. // NOTE: Safe to use the same variable for both input and output. TrimPositions TrimWhitespaceASCII(const std::string& input, TrimPositions positions, std::string* output); -// Deprecated. This function is only for backward compatibility and calls -// TrimWhitespaceASCII(). -TrimPositions TrimWhitespace(const std::string& input, - TrimPositions positions, - std::string* output); - // Returns true if the specified string matches the criteria. How can a wide // string be 8-bit or UTF8? It contains only characters that are < 256 (in the // first case) or characters that use only 8-bits and whose 8-bit diff --git a/third_party/chromium/base/strings/string_util_posix.h b/third_party/chromium/base/strings/string_util_posix.h index ccfff10..07a89e4 100644 --- a/third_party/chromium/base/strings/string_util_posix.h +++ b/third_party/chromium/base/strings/string_util_posix.h @@ -6,6 +6,7 @@ #define BASE_STRINGS_STRING_UTIL_POSIX_H_ #include <stdarg.h> +#include <stddef.h> #include <stdio.h> #include <string.h> #include <wchar.h> @@ -18,7 +19,6 @@ inline int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) { return ::vsnprintf(buffer, size, format, arguments); } - } // namespace base #endif // BASE_STRINGS_STRING_UTIL_POSIX_H_ diff --git a/third_party/chromium/base/strings/string_util_unittest.cc b/third_party/chromium/base/strings/string_util_unittest.cc index 1a75218..451fbd8 100644 --- a/third_party/chromium/base/strings/string_util_unittest.cc +++ b/third_party/chromium/base/strings/string_util_unittest.cc @@ -6,13 +6,15 @@ #include <math.h> #include <stdarg.h> +#include <stddef.h> +#include <stdint.h> #include <algorithm> #include <gmock/gmock.h> #include <gtest/gtest.h> -#include "base/basictypes.h" +#include "base/macros.h" #include "base/strings/utf_string_conversion_utils.h" using ::testing::ElementsAre; diff --git a/third_party/chromium/base/strings/stringprintf.cc b/third_party/chromium/base/strings/stringprintf.cc index 5f1ad9b..8147ed3 100644 --- a/third_party/chromium/base/strings/stringprintf.cc +++ b/third_party/chromium/base/strings/stringprintf.cc @@ -5,12 +5,13 @@ #include "base/strings/stringprintf.h" #include <errno.h> +#include <stddef.h> #include <vector> -#include "base/logging.h" #include "base/scoped_clear_errno.h" #include "base/strings/string_util.h" +#include "build/build_config.h" namespace base { diff --git a/third_party/chromium/base/strings/stringprintf.h b/third_party/chromium/base/strings/stringprintf.h index 06962b7..4c81400 100644 --- a/third_party/chromium/base/strings/stringprintf.h +++ b/third_party/chromium/base/strings/stringprintf.h @@ -11,6 +11,7 @@ #include "base/base_export.h" #include "base/compiler_specific.h" +#include "build/build_config.h" namespace base { diff --git a/third_party/chromium/base/strings/stringprintf_unittest.cc b/third_party/chromium/base/strings/stringprintf_unittest.cc index 88a9675..e70499d 100644 --- a/third_party/chromium/base/strings/stringprintf_unittest.cc +++ b/third_party/chromium/base/strings/stringprintf_unittest.cc @@ -5,10 +5,12 @@ #include "base/strings/stringprintf.h" #include <errno.h> +#include <stddef.h> #include <gtest/gtest.h> -#include "base/basictypes.h" +#include "base/macros.h" +#include "build/build_config.h" namespace base { @@ -145,10 +147,10 @@ TEST(StringPrintfTest, GrowBoundary) { EXPECT_STREQ(src, out.c_str()); } -// TODO(evanm): what's the proper cross-platform test here? #if defined(OS_WIN) -// sprintf in Visual Studio fails when given U+FFFF. This tests that the -// failure case is gracefuly handled. +// vswprintf in Visual Studio 2013 fails when given U+FFFF. This tests that the +// failure case is gracefuly handled. In Visual Studio 2015 the bad character +// is passed through. TEST(StringPrintfTest, Invalid) { wchar_t invalid[2]; invalid[0] = 0xffff; @@ -156,7 +158,11 @@ TEST(StringPrintfTest, Invalid) { std::wstring out; SStringPrintf(&out, L"%ls", invalid); +#if _MSC_VER >= 1900 + EXPECT_STREQ(invalid, out.c_str()); +#else EXPECT_STREQ(L"", out.c_str()); +#endif } #endif diff --git a/third_party/chromium/base/strings/utf_string_conversion_utils.cc b/third_party/chromium/base/strings/utf_string_conversion_utils.cc index 05bd122..3091241 100644 --- a/third_party/chromium/base/strings/utf_string_conversion_utils.cc +++ b/third_party/chromium/base/strings/utf_string_conversion_utils.cc @@ -11,15 +11,15 @@ namespace base { // ReadUnicodeCharacter -------------------------------------------------------- bool ReadUnicodeCharacter(const char* src, - int32 src_len, - int32* char_index, - uint32* code_point_out) { + int32_t src_len, + int32_t* char_index, + uint32_t* code_point_out) { // U8_NEXT expects to be able to use -1 to signal an error, so we must // use a signed type for code_point. But this function returns false // on error anyway, so code_point_out is unsigned. - int32 code_point; + int32_t code_point; CBU8_NEXT(src, *char_index, src_len, code_point); - *code_point_out = static_cast<uint32>(code_point); + *code_point_out = static_cast<uint32_t>(code_point); // The ICU macro above moves to the next char, we want to point to the last // char consumed. @@ -31,7 +31,7 @@ bool ReadUnicodeCharacter(const char* src, // WriteUnicodeCharacter ------------------------------------------------------- -size_t WriteUnicodeCharacter(uint32 code_point, std::string* output) { +size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output) { if (code_point <= 0x7f) { // Fast path the common case of one byte. output->push_back(static_cast<char>(code_point)); diff --git a/third_party/chromium/base/strings/utf_string_conversion_utils.h b/third_party/chromium/base/strings/utf_string_conversion_utils.h index d932d9f..a29b181 100644 --- a/third_party/chromium/base/strings/utf_string_conversion_utils.h +++ b/third_party/chromium/base/strings/utf_string_conversion_utils.h @@ -9,12 +9,14 @@ // This should only be used by the various UTF string conversion files. +#include <stddef.h> +#include <stdint.h> + #include "base/base_export.h" -#include "base/basictypes.h" namespace base { -inline bool IsValidCodepoint(uint32 code_point) { +inline bool IsValidCodepoint(uint32_t code_point) { // Excludes the surrogate code points ([0xD800, 0xDFFF]) and // codepoints larger than 0x10FFFF (the highest codepoint allowed). // Non-characters and unassigned codepoints are allowed. @@ -22,7 +24,7 @@ inline bool IsValidCodepoint(uint32 code_point) { (code_point >= 0xE000u && code_point <= 0x10FFFFu); } -inline bool IsValidCharacter(uint32 code_point) { +inline bool IsValidCharacter(uint32_t code_point) { // Excludes non-characters (U+FDD0..U+FDEF, and all codepoints ending in // 0xFFFE or 0xFFFF) from the set of valid code points. return code_point < 0xD800u || (code_point >= 0xE000u && @@ -40,16 +42,16 @@ inline bool IsValidCharacter(uint32 code_point) { // // Returns true on success. On false, |*code_point| will be invalid. bool ReadUnicodeCharacter(const char* src, - int32 src_len, - int32* char_index, - uint32* code_point_out); + int32_t src_len, + int32_t* char_index, + uint32_t* code_point_out); #if defined(WCHAR_T_IS_UTF32) // Reads UTF-32 character. The usage is the same as the 8-bit version above. bool ReadUnicodeCharacter(const wchar_t* src, - int32 src_len, - int32* char_index, - uint32* code_point); + int32_t src_len, + int32_t* char_index, + uint32_t* code_point); #endif // defined(WCHAR_T_IS_UTF32) // WriteUnicodeCharacter ------------------------------------------------------- @@ -57,12 +59,12 @@ bool ReadUnicodeCharacter(const wchar_t* src, // Appends a UTF-8 character to the given 8-bit string. Returns the number of // bytes written. // TODO(brettw) Bug 79631: This function should not be exposed. -size_t WriteUnicodeCharacter(uint32 code_point, std::string* output); +size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output); #if defined(WCHAR_T_IS_UTF32) // Appends the given UTF-32 character to the given 32-bit string. Returns the // number of 32-bit values written. -inline size_t WriteUnicodeCharacter(uint32 code_point, std::wstring* output) { +inline size_t WriteUnicodeCharacter(uint32_t code_point, std::wstring* output) { // This is the easy case, just append the character. output->push_back(code_point); return 1; diff --git a/third_party/chromium/base/template_util.h b/third_party/chromium/base/template_util.h index 4b1c808..7b61d24 100644 --- a/third_party/chromium/base/template_util.h +++ b/third_party/chromium/base/template_util.h @@ -5,7 +5,7 @@ #ifndef BASE_TEMPLATE_UTIL_H_ #define BASE_TEMPLATE_UTIL_H_ -#include <cstddef> // For size_t. +#include <stddef.h> #include <type_traits> #include "build/build_config.h" diff --git a/third_party/chromium/base/template_util_unittest.cc b/third_party/chromium/base/template_util_unittest.cc index 7c86355..ce029af 100644 --- a/third_party/chromium/base/template_util_unittest.cc +++ b/third_party/chromium/base/template_util_unittest.cc @@ -6,7 +6,6 @@ #include <gtest/gtest.h> -#include "base/basictypes.h" namespace base { namespace { @@ -26,23 +25,24 @@ using std::is_class; using std::is_member_function_pointer; // is_pointer<Type> -COMPILE_ASSERT(!is_pointer<int>::value, IsPointer); -COMPILE_ASSERT(!is_pointer<int&>::value, IsPointer); -COMPILE_ASSERT(is_pointer<int*>::value, IsPointer); -COMPILE_ASSERT(is_pointer<const int*>::value, IsPointer); +static_assert(!is_pointer<int>::value, "IsPointer"); +static_assert(!is_pointer<int&>::value, "IsPointer"); +static_assert(is_pointer<int*>::value, "IsPointer"); +static_assert(is_pointer<const int*>::value, "IsPointer"); // is_array<Type> -COMPILE_ASSERT(!is_array<int>::value, IsArray); -COMPILE_ASSERT(!is_array<int*>::value, IsArray); -COMPILE_ASSERT(!is_array<int(*)[3]>::value, IsArray); -COMPILE_ASSERT(is_array<int[]>::value, IsArray); -COMPILE_ASSERT(is_array<const int[]>::value, IsArray); -COMPILE_ASSERT(is_array<int[3]>::value, IsArray); +static_assert(!is_array<int>::value, "IsArray"); +static_assert(!is_array<int*>::value, "IsArray"); +static_assert(!is_array<int (*)[3]>::value, "IsArray"); +static_assert(is_array<int[]>::value, "IsArray"); +static_assert(is_array<const int[]>::value, "IsArray"); +static_assert(is_array<int[3]>::value, "IsArray"); // is_non_const_reference<Type> -COMPILE_ASSERT(!is_non_const_reference<int>::value, IsNonConstReference); -COMPILE_ASSERT(!is_non_const_reference<const int&>::value, IsNonConstReference); -COMPILE_ASSERT(is_non_const_reference<int&>::value, IsNonConstReference); +static_assert(!is_non_const_reference<int>::value, "IsNonConstReference"); +static_assert(!is_non_const_reference<const int&>::value, + "IsNonConstReference"); +static_assert(is_non_const_reference<int&>::value, "IsNonConstReference"); // is_convertible<From, To> @@ -52,66 +52,64 @@ COMPILE_ASSERT(is_non_const_reference<int&>::value, IsNonConstReference); // (is_convertible < Child), (Parent > ::value) // // Silly C++. -COMPILE_ASSERT( (is_convertible<Child, Parent>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<Parent, Child>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<Parent, AStruct>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int, double>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int*, void*>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<void*, int*>::value), IsConvertible); +static_assert((is_convertible<Child, Parent>::value), "IsConvertible"); +static_assert(!(is_convertible<Parent, Child>::value), "IsConvertible"); +static_assert(!(is_convertible<Parent, AStruct>::value), "IsConvertible"); +static_assert((is_convertible<int, double>::value), "IsConvertible"); +static_assert((is_convertible<int*, void*>::value), "IsConvertible"); +static_assert(!(is_convertible<void*, int*>::value), "IsConvertible"); // Array types are an easy corner case. Make sure to test that // it does indeed compile. -COMPILE_ASSERT(!(is_convertible<int[10], double>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<double, int[10]>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int[10], int*>::value), IsConvertible); +static_assert(!(is_convertible<int[10], double>::value), "IsConvertible"); +static_assert(!(is_convertible<double, int[10]>::value), "IsConvertible"); +static_assert((is_convertible<int[10], int*>::value), "IsConvertible"); // is_same<Type1, Type2> -COMPILE_ASSERT(!(is_same<Child, Parent>::value), IsSame); -COMPILE_ASSERT(!(is_same<Parent, Child>::value), IsSame); -COMPILE_ASSERT( (is_same<Parent, Parent>::value), IsSame); -COMPILE_ASSERT( (is_same<int*, int*>::value), IsSame); -COMPILE_ASSERT( (is_same<int, int>::value), IsSame); -COMPILE_ASSERT( (is_same<void, void>::value), IsSame); -COMPILE_ASSERT(!(is_same<int, double>::value), IsSame); - +static_assert(!(is_same<Child, Parent>::value), "IsSame"); +static_assert(!(is_same<Parent, Child>::value), "IsSame"); +static_assert((is_same<Parent, Parent>::value), "IsSame"); +static_assert((is_same<int*, int*>::value), "IsSame"); +static_assert((is_same<int, int>::value), "IsSame"); +static_assert((is_same<void, void>::value), "IsSame"); +static_assert(!(is_same<int, double>::value), "IsSame"); // is_class<Type> -COMPILE_ASSERT(is_class<AStruct>::value, IsClass); -COMPILE_ASSERT(is_class<AClass>::value, IsClass); -COMPILE_ASSERT(!is_class<AnEnum>::value, IsClass); -COMPILE_ASSERT(!is_class<int>::value, IsClass); -COMPILE_ASSERT(!is_class<char*>::value, IsClass); -COMPILE_ASSERT(!is_class<int&>::value, IsClass); -COMPILE_ASSERT(!is_class<char[3]>::value, IsClass); - - -COMPILE_ASSERT(!is_member_function_pointer<int>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<void*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<AStruct>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<AStruct*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<void(*)()>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int(*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int(*)(int, int)>::value, - IsMemberFunctionPointer); - -COMPILE_ASSERT(is_member_function_pointer<void (AStruct::*)()>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<void (AStruct::*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int) const>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int, int)>::value, - IsMemberFunctionPointer); +static_assert(is_class<AStruct>::value, "IsClass"); +static_assert(is_class<AClass>::value, "IsClass"); +static_assert(!is_class<AnEnum>::value, "IsClass"); +static_assert(!is_class<int>::value, "IsClass"); +static_assert(!is_class<char*>::value, "IsClass"); +static_assert(!is_class<int&>::value, "IsClass"); +static_assert(!is_class<char[3]>::value, "IsClass"); + +static_assert(!is_member_function_pointer<int>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<void*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<AStruct>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<AStruct*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<void (*)()>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int (*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int (*)(int, int)>::value, + "IsMemberFunctionPointer"); + +static_assert(is_member_function_pointer<void (AStruct::*)()>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<void (AStruct::*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int) const>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int, int)>::value, + "IsMemberFunctionPointer"); } // namespace } // namespace base diff --git a/third_party/chromium/base/third_party/icu/icu_utf.cc b/third_party/chromium/base/third_party/icu/icu_utf.cc index b47c8ac..3c877b3 100644 --- a/third_party/chromium/base/third_party/icu/icu_utf.cc +++ b/third_party/chromium/base/third_party/icu/icu_utf.cc @@ -74,7 +74,7 @@ namespace base_icu { * lead bytes above 0xf4 are illegal. * We keep them in this table for skipping long ISO 10646-UTF-8 sequences. */ -const uint8 +const uint8_t utf8_countTrailBytes[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -134,11 +134,15 @@ utf8_errorValue[6]={ * Note that a UBool is the same as an int8_t. */ UChar32 -utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c, UBool strict) { - int32 i=*pi; - uint8 count=CBU8_COUNT_TRAIL_BYTES(c); +utf8_nextCharSafeBody(const uint8_t *s, + int32_t *pi, + int32_t length, + UChar32 c, + UBool strict) { + int32_t i=*pi; + uint8_t count=CBU8_COUNT_TRAIL_BYTES(c); if((i)+count<=(length)) { - uint8 trail, illegal=0; + uint8_t trail, illegal=0; CBU8_MASK_LEAD_BYTE((c), count); /* count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff */ @@ -192,7 +196,7 @@ utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c, UBool /* illegal is also set if count>=4 */ if(illegal || (c)<utf8_minLegal[count] || (CBU_IS_SURROGATE(c) && strict!=-2)) { /* error handling */ - uint8 errorCount=count; + uint8_t errorCount=count; /* don't go beyond this sequence */ i=*pi; while(count>0 && CBU8_IS_TRAIL(s[i])) { @@ -210,7 +214,7 @@ utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c, UBool } } else /* too few bytes left */ { /* error handling */ - int32 i0=i; + int32_t i0=i; /* don't just set (i)=(length) in case there is an illegal sequence */ while((i)<(length) && CBU8_IS_TRAIL(s[i])) { ++(i); diff --git a/third_party/chromium/base/third_party/icu/icu_utf.h b/third_party/chromium/base/third_party/icu/icu_utf.h index 2b993b0..e50cdab 100644 --- a/third_party/chromium/base/third_party/icu/icu_utf.h +++ b/third_party/chromium/base/third_party/icu/icu_utf.h @@ -17,13 +17,13 @@ #ifndef BASE_THIRD_PARTY_ICU_ICU_UTF_H_ #define BASE_THIRD_PARTY_ICU_ICU_UTF_H_ -#include "base/basictypes.h" +#include <stdint.h> namespace base_icu { -typedef int32 UChar32; -typedef uint16 UChar; -typedef int8 UBool; +typedef int32_t UChar32; +typedef uint16_t UChar; +typedef int8_t UBool; // General --------------------------------------------------------------------- // from utf.h @@ -56,8 +56,8 @@ typedef int8 UBool; */ #define CBU_IS_UNICODE_NONCHAR(c) \ ((c)>=0xfdd0 && \ - ((uint32)(c)<=0xfdef || ((c)&0xfffe)==0xfffe) && \ - (uint32)(c)<=0x10ffff) + ((uint32_t)(c)<=0xfdef || ((c)&0xfffe)==0xfffe) && \ + (uint32_t)(c)<=0x10ffff) /** * Is c a Unicode code point value (0..U+10ffff) @@ -77,9 +77,9 @@ typedef int8 UBool; * @stable ICU 2.4 */ #define CBU_IS_UNICODE_CHAR(c) \ - ((uint32)(c)<0xd800 || \ - ((uint32)(c)>0xdfff && \ - (uint32)(c)<=0x10ffff && \ + ((uint32_t)(c)<0xd800 || \ + ((uint32_t)(c)>0xdfff && \ + (uint32_t)(c)<=0x10ffff && \ !CBU_IS_UNICODE_NONCHAR(c))) /** @@ -103,13 +103,13 @@ typedef int8 UBool; // UTF-8 macros ---------------------------------------------------------------- // from utf8.h -extern const uint8 utf8_countTrailBytes[256]; +extern const uint8_t utf8_countTrailBytes[256]; /** * Count the trail bytes for a UTF-8 lead byte. * @internal */ -#define CBU8_COUNT_TRAIL_BYTES(leadByte) (base_icu::utf8_countTrailBytes[(uint8)leadByte]) +#define CBU8_COUNT_TRAIL_BYTES(leadByte) (base_icu::utf8_countTrailBytes[(uint8_t)leadByte]) /** * Mask a UTF-8 lead byte, leave only the lower bits that form part of the code point value. @@ -131,7 +131,7 @@ extern const uint8 utf8_countTrailBytes[256]; * @return TRUE or FALSE * @stable ICU 2.4 */ -#define CBU8_IS_LEAD(c) ((uint8)((c)-0xc0)<0x3e) +#define CBU8_IS_LEAD(c) ((uint8_t)((c)-0xc0)<0x3e) /** * Is this code unit (byte) a UTF-8 trail byte? @@ -149,11 +149,11 @@ extern const uint8 utf8_countTrailBytes[256]; * @stable ICU 2.4 */ #define CBU8_LENGTH(c) \ - ((uint32)(c)<=0x7f ? 1 : \ - ((uint32)(c)<=0x7ff ? 2 : \ - ((uint32)(c)<=0xd7ff ? 3 : \ - ((uint32)(c)<=0xdfff || (uint32)(c)>0x10ffff ? 0 : \ - ((uint32)(c)<=0xffff ? 3 : 4)\ + ((uint32_t)(c)<=0x7f ? 1 : \ + ((uint32_t)(c)<=0x7ff ? 2 : \ + ((uint32_t)(c)<=0xd7ff ? 3 : \ + ((uint32_t)(c)<=0xdfff || (uint32_t)(c)>0x10ffff ? 0 : \ + ((uint32_t)(c)<=0xffff ? 3 : 4)\ ) \ ) \ ) \ @@ -170,7 +170,7 @@ extern const uint8 utf8_countTrailBytes[256]; * Function for handling "next code point" with error-checking. * @internal */ -UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c, UBool strict); +UChar32 utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c, UBool strict); /** * Get a code point from a string at a code point boundary offset, @@ -183,7 +183,7 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c * If the offset points to a trail byte or an illegal UTF-8 sequence, then * c is set to a negative value. * - * @param s const uint8 * string + * @param s const uint8_t * string * @param i string offset, i<length * @param length string length * @param c output UChar32 variable, set to <0 in case of an error @@ -192,9 +192,9 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c */ #define CBU8_NEXT(s, i, length, c) { \ (c)=(s)[(i)++]; \ - if(((uint8)(c))>=0x80) { \ + if(((uint8_t)(c))>=0x80) { \ if(CBU8_IS_LEAD(c)) { \ - (c)=base_icu::utf8_nextCharSafeBody((const uint8 *)s, &(i), (int32)(length), c, -1); \ + (c)=base_icu::utf8_nextCharSafeBody((const uint8_t *)s, &(i), (int32_t)(length), c, -1); \ } else { \ (c)=CBU_SENTINEL; \ } \ @@ -208,28 +208,28 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c * "Unsafe" macro, assumes a valid code point and sufficient space in the string. * Otherwise, the result is undefined. * - * @param s const uint8 * string buffer + * @param s const uint8_t * string buffer * @param i string offset * @param c code point to append * @see CBU8_APPEND * @stable ICU 2.4 */ #define CBU8_APPEND_UNSAFE(s, i, c) { \ - if((uint32)(c)<=0x7f) { \ - (s)[(i)++]=(uint8)(c); \ + if((uint32_t)(c)<=0x7f) { \ + (s)[(i)++]=(uint8_t)(c); \ } else { \ - if((uint32)(c)<=0x7ff) { \ - (s)[(i)++]=(uint8)(((c)>>6)|0xc0); \ + if((uint32_t)(c)<=0x7ff) { \ + (s)[(i)++]=(uint8_t)(((c)>>6)|0xc0); \ } else { \ - if((uint32)(c)<=0xffff) { \ - (s)[(i)++]=(uint8)(((c)>>12)|0xe0); \ + if((uint32_t)(c)<=0xffff) { \ + (s)[(i)++]=(uint8_t)(((c)>>12)|0xe0); \ } else { \ - (s)[(i)++]=(uint8)(((c)>>18)|0xf0); \ - (s)[(i)++]=(uint8)((((c)>>12)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)(((c)>>18)|0xf0); \ + (s)[(i)++]=(uint8_t)((((c)>>12)&0x3f)|0x80); \ } \ - (s)[(i)++]=(uint8)((((c)>>6)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)((((c)>>6)&0x3f)|0x80); \ } \ - (s)[(i)++]=(uint8)(((c)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \ } \ } @@ -325,7 +325,7 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c * @return 1 or 2 * @stable ICU 2.4 */ -#define CBU16_LENGTH(c) ((uint32)(c)<=0xffff ? 1 : 2) +#define CBU16_LENGTH(c) ((uint32_t)(c)<=0xffff ? 1 : 2) /** * The maximum number of 16-bit code units per Unicode code point (U+0000..U+10ffff). @@ -356,7 +356,7 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c #define CBU16_NEXT(s, i, length, c) { \ (c)=(s)[(i)++]; \ if(CBU16_IS_LEAD(c)) { \ - uint16 __c2; \ + uint16_t __c2; \ if((i)<(length) && CBU16_IS_TRAIL(__c2=(s)[(i)])) { \ ++(i); \ (c)=CBU16_GET_SUPPLEMENTARY((c), __c2); \ @@ -378,11 +378,11 @@ UChar32 utf8_nextCharSafeBody(const uint8 *s, int32 *pi, int32 length, UChar32 c * @stable ICU 2.4 */ #define CBU16_APPEND_UNSAFE(s, i, c) { \ - if((uint32)(c)<=0xffff) { \ - (s)[(i)++]=(uint16)(c); \ + if((uint32_t)(c)<=0xffff) { \ + (s)[(i)++]=(uint16_t)(c); \ } else { \ - (s)[(i)++]=(uint16)(((c)>>10)+0xd7c0); \ - (s)[(i)++]=(uint16)(((c)&0x3ff)|0xdc00); \ + (s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \ + (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ } \ } diff --git a/third_party/chromium/base/time/time.cc b/third_party/chromium/base/time/time.cc index 7006407..0dc892a 100644 --- a/third_party/chromium/base/time/time.cc +++ b/third_party/chromium/base/time/time.cc @@ -11,6 +11,7 @@ #include <sstream> #include "base/logging.h" +#include "base/macros.h" #include "base/strings/stringprintf.h" namespace base { @@ -19,7 +20,7 @@ namespace base { // static TimeDelta TimeDelta::Max() { - return TimeDelta(std::numeric_limits<int64>::max()); + return TimeDelta(std::numeric_limits<int64_t>::max()); } int TimeDelta::InDays() const { @@ -54,10 +55,10 @@ double TimeDelta::InSecondsF() const { return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; } -int64 TimeDelta::InSeconds() const { +int64_t TimeDelta::InSeconds() const { if (is_max()) { // Preserve max to prevent overflow. - return std::numeric_limits<int64>::max(); + return std::numeric_limits<int64_t>::max(); } return delta_ / Time::kMicrosecondsPerSecond; } @@ -70,46 +71,46 @@ double TimeDelta::InMillisecondsF() const { return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; } -int64 TimeDelta::InMilliseconds() const { +int64_t TimeDelta::InMilliseconds() const { if (is_max()) { // Preserve max to prevent overflow. - return std::numeric_limits<int64>::max(); + return std::numeric_limits<int64_t>::max(); } return delta_ / Time::kMicrosecondsPerMillisecond; } -int64 TimeDelta::InMillisecondsRoundedUp() const { +int64_t TimeDelta::InMillisecondsRoundedUp() const { if (is_max()) { // Preserve max to prevent overflow. - return std::numeric_limits<int64>::max(); + return std::numeric_limits<int64_t>::max(); } return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / Time::kMicrosecondsPerMillisecond; } -int64 TimeDelta::InMicroseconds() const { +int64_t TimeDelta::InMicroseconds() const { if (is_max()) { // Preserve max to prevent overflow. - return std::numeric_limits<int64>::max(); + return std::numeric_limits<int64_t>::max(); } return delta_; } namespace time_internal { -int64 SaturatedAdd(TimeDelta delta, int64 value) { - CheckedNumeric<int64> rv(delta.delta_); +int64_t SaturatedAdd(TimeDelta delta, int64_t value) { + CheckedNumeric<int64_t> rv(delta.delta_); rv += value; return FromCheckedNumeric(rv); } -int64 SaturatedSub(TimeDelta delta, int64 value) { - CheckedNumeric<int64> rv(delta.delta_); +int64_t SaturatedSub(TimeDelta delta, int64_t value) { + CheckedNumeric<int64_t> rv(delta.delta_); rv -= value; return FromCheckedNumeric(rv); } -int64 FromCheckedNumeric(const CheckedNumeric<int64> value) { +int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value) { if (value.IsValid()) return value.ValueUnsafe(); @@ -117,7 +118,7 @@ int64 FromCheckedNumeric(const CheckedNumeric<int64> value) { // is. Instead, return max/(-max), which is something that clients can reason // about. // TODO(rvargas) crbug.com/332611: don't use internal values. - int64 limit = std::numeric_limits<int64>::max(); + int64_t limit = std::numeric_limits<int64_t>::max(); if (value.validity() == internal::RANGE_UNDERFLOW) limit = -limit; return value.ValueOrDefault(limit); @@ -133,7 +134,7 @@ std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { // static Time Time::Max() { - return Time(std::numeric_limits<int64>::max()); + return Time(std::numeric_limits<int64_t>::max()); } // static @@ -142,7 +143,7 @@ Time Time::FromTimeT(time_t tt) { return Time(); // Preserve 0 so we can tell it doesn't exist. if (tt == std::numeric_limits<time_t>::max()) return Max(); - return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset); + return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt); } time_t Time::ToTimeT() const { @@ -152,7 +153,7 @@ time_t Time::ToTimeT() const { // Preserve max without offset to prevent overflow. return std::numeric_limits<time_t>::max(); } - if (std::numeric_limits<int64>::max() - kTimeTToMicrosecondsOffset <= us_) { + if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) { DLOG(WARNING) << "Overflow when converting base::Time with internal " << "value " << us_ << " to time_t."; return std::numeric_limits<time_t>::max(); @@ -164,11 +165,7 @@ time_t Time::ToTimeT() const { Time Time::FromDoubleT(double dt) { if (dt == 0 || std::isnan(dt)) return Time(); // Preserve 0 so we can tell it doesn't exist. - if (dt == std::numeric_limits<double>::infinity()) - return Max(); - return Time(static_cast<int64>((dt * - static_cast<double>(kMicrosecondsPerSecond)) + - kTimeTToMicrosecondsOffset)); + return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt); } double Time::ToDoubleT() const { @@ -195,10 +192,8 @@ Time Time::FromTimeSpec(const timespec& ts) { Time Time::FromJsTime(double ms_since_epoch) { // The epoch is a valid time, so this constructor doesn't interpret // 0 as the null time. - if (ms_since_epoch == std::numeric_limits<double>::infinity()) - return Max(); - return Time(static_cast<int64>(ms_since_epoch * kMicrosecondsPerMillisecond) + - kTimeTToMicrosecondsOffset); + return Time(kTimeTToMicrosecondsOffset) + + TimeDelta::FromMillisecondsD(ms_since_epoch); } double Time::ToJsTime() const { @@ -214,14 +209,14 @@ double Time::ToJsTime() const { kMicrosecondsPerMillisecond); } -int64 Time::ToJavaTime() const { +int64_t Time::ToJavaTime() const { if (is_null()) { // Preserve 0 so the invalid result doesn't depend on the platform. return 0; } if (is_max()) { // Preserve max without offset to prevent overflow. - return std::numeric_limits<int64>::max(); + return std::numeric_limits<int64_t>::max(); } return ((us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerMillisecond); @@ -301,11 +296,6 @@ std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) { return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds"; } -std::ostream& operator<<(std::ostream& os, TraceTicks trace_ticks) { - const TimeDelta as_time_delta = trace_ticks - TraceTicks(); - return os << as_time_delta.InMicroseconds() << " bogo-trace-microseconds"; -} - // Time::Exploded ------------------------------------------------------------- inline bool is_in_range(int value, int lo, int hi) { diff --git a/third_party/chromium/base/time/time.h b/third_party/chromium/base/time/time.h index 1fe1b85..9456cc7 100644 --- a/third_party/chromium/base/time/time.h +++ b/third_party/chromium/base/time/time.h @@ -13,13 +13,13 @@ // TimeDelta represents a duration of time, internally represented in // microseconds. // -// TimeTicks, ThreadTicks, and TraceTicks represent an abstract time that is -// most of the time incrementing, for use in measuring time durations. -// Internally, they are represented in microseconds. They can not be converted -// to a human-readable time, but are guaranteed not to decrease (unlike the Time -// class). Note that TimeTicks may "stand still" (e.g., if the computer is -// suspended), and ThreadTicks will "stand still" whenever the thread has been -// de-scheduled by the operating system. +// TimeTicks and ThreadTicks represent an abstract time that is most of the time +// incrementing, for use in measuring time durations. Internally, they are +// represented in microseconds. They can not be converted to a human-readable +// time, but are guaranteed not to decrease (unlike the Time class). Note that +// TimeTicks may "stand still" (e.g., if the computer is suspended), and +// ThreadTicks will "stand still" whenever the thread has been de-scheduled by +// the operating system. // // All time classes are copyable, assignable, and occupy 64-bits per // instance. Thus, they can be efficiently passed by-value (as opposed to @@ -45,22 +45,17 @@ // // ThreadTicks: Benchmarking how long the current thread has been doing actual // work. -// -// TraceTicks: This is only meant to be used by the event tracing -// infrastructure, and by outside code modules in special -// circumstances. Please be sure to consult a -// base/trace_event/OWNER before committing any new code that -// uses this. #ifndef BASE_TIME_TIME_H_ #define BASE_TIME_TIME_H_ +#include <stdint.h> #include <time.h> #include <iosfwd> +#include <limits> #include "base/base_export.h" -#include "base/basictypes.h" #include "base/numerics/safe_math.h" #include "build/build_config.h" @@ -79,9 +74,9 @@ // For FILETIME in FromFileTime, until it moves to a new converter class. // See TODO(iyengar) below. #include <windows.h> -#endif -#include <limits> +#include "base/gtest_prod_util.h" +#endif namespace base { @@ -92,14 +87,14 @@ class TimeDelta; // time classes instead. namespace time_internal { -// Add or subtract |value| from a TimeDelta. The int64 argument and return value -// are in terms of a microsecond timebase. -BASE_EXPORT int64 SaturatedAdd(TimeDelta delta, int64 value); -BASE_EXPORT int64 SaturatedSub(TimeDelta delta, int64 value); +// Add or subtract |value| from a TimeDelta. The int64_t argument and return +// value are in terms of a microsecond timebase. +BASE_EXPORT int64_t SaturatedAdd(TimeDelta delta, int64_t value); +BASE_EXPORT int64_t SaturatedSub(TimeDelta delta, int64_t value); -// Clamp |value| on overflow and underflow conditions. The int64 argument and +// Clamp |value| on overflow and underflow conditions. The int64_t argument and // return value are in terms of a microsecond timebase. -BASE_EXPORT int64 FromCheckedNumeric(const CheckedNumeric<int64> value); +BASE_EXPORT int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value); } // namespace time_internal @@ -114,11 +109,11 @@ class BASE_EXPORT TimeDelta { static TimeDelta FromDays(int days); static TimeDelta FromHours(int hours); static TimeDelta FromMinutes(int minutes); - static TimeDelta FromSeconds(int64 secs); - static TimeDelta FromMilliseconds(int64 ms); + static TimeDelta FromSeconds(int64_t secs); + static TimeDelta FromMilliseconds(int64_t ms); static TimeDelta FromSecondsD(double secs); static TimeDelta FromMillisecondsD(double ms); - static TimeDelta FromMicroseconds(int64 us); + static TimeDelta FromMicroseconds(int64_t us); #if defined(OS_WIN) static TimeDelta FromQPCValue(LONGLONG qpc_value); #endif @@ -127,9 +122,7 @@ class BASE_EXPORT TimeDelta { // when deserializing a |TimeDelta| structure, using a value known to be // compatible. It is not provided as a constructor because the integer type // may be unclear from the perspective of a caller. - static TimeDelta FromInternalValue(int64 delta) { - return TimeDelta(delta); - } + static TimeDelta FromInternalValue(int64_t delta) { return TimeDelta(delta); } // Returns the maximum time delta, which should be greater than any reasonable // time delta we might compare it to. Adding or subtracting the maximum time @@ -140,16 +133,14 @@ class BASE_EXPORT TimeDelta { // use this and do arithmetic on it, as it is more error prone than using the // provided operators. // For serializing, use FromInternalValue to reconstitute. - int64 ToInternalValue() const { - return delta_; - } + int64_t ToInternalValue() const { return delta_; } // Returns the magnitude (absolute value) of this TimeDelta. TimeDelta magnitude() const { // Some toolchains provide an incomplete C++11 implementation and lack an - // int64 overload for std::abs(). The following is a simple branchless + // int64_t overload for std::abs(). The following is a simple branchless // implementation: - const int64 mask = delta_ >> (sizeof(delta_) * 8 - 1); + const int64_t mask = delta_ >> (sizeof(delta_) * 8 - 1); return TimeDelta((delta_ + mask) ^ mask); } @@ -159,9 +150,7 @@ class BASE_EXPORT TimeDelta { } // Returns true if the time delta is the maximum time delta. - bool is_max() const { - return delta_ == std::numeric_limits<int64>::max(); - } + bool is_max() const { return delta_ == std::numeric_limits<int64_t>::max(); } #if defined(OS_POSIX) struct timespec ToTimeSpec() const; @@ -176,11 +165,11 @@ class BASE_EXPORT TimeDelta { int InHours() const; int InMinutes() const; double InSecondsF() const; - int64 InSeconds() const; + int64_t InSeconds() const; double InMillisecondsF() const; - int64 InMilliseconds() const; - int64 InMillisecondsRoundedUp() const; - int64 InMicroseconds() const; + int64_t InMilliseconds() const; + int64_t InMillisecondsRoundedUp() const; + int64_t InMicroseconds() const; TimeDelta& operator=(TimeDelta other) { delta_ = other.delta_; @@ -208,13 +197,13 @@ class BASE_EXPORT TimeDelta { // Computations with numeric types. template<typename T> TimeDelta operator*(T a) const { - CheckedNumeric<int64> rv(delta_); + CheckedNumeric<int64_t> rv(delta_); rv *= a; return TimeDelta(time_internal::FromCheckedNumeric(rv)); } template<typename T> TimeDelta operator/(T a) const { - CheckedNumeric<int64> rv(delta_); + CheckedNumeric<int64_t> rv(delta_); rv /= a; return TimeDelta(time_internal::FromCheckedNumeric(rv)); } @@ -227,9 +216,7 @@ class BASE_EXPORT TimeDelta { return *this = (*this / a); } - int64 operator/(TimeDelta a) const { - return delta_ / a.delta_; - } + int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } TimeDelta operator%(TimeDelta a) const { return TimeDelta(delta_ % a.delta_); } @@ -255,17 +242,19 @@ class BASE_EXPORT TimeDelta { } private: - friend int64 time_internal::SaturatedAdd(TimeDelta delta, int64 value); - friend int64 time_internal::SaturatedSub(TimeDelta delta, int64 value); + friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value); + friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value); // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use // FromSeconds, FromMilliseconds, etc. instead. - explicit TimeDelta(int64 delta_us) : delta_(delta_us) { - } + explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} + + // Private method to build a delta from a double. + static TimeDelta FromDouble(double value); // Delta in microseconds. - int64 delta_; + int64_t delta_; }; template<typename T> @@ -290,20 +279,21 @@ namespace time_internal { template<class TimeClass> class TimeBase { public: - static const int64 kHoursPerDay = 24; - static const int64 kMillisecondsPerSecond = 1000; - static const int64 kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * - kHoursPerDay; - static const int64 kMicrosecondsPerMillisecond = 1000; - static const int64 kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * - kMillisecondsPerSecond; - static const int64 kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; - static const int64 kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay; - static const int64 kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; - static const int64 kNanosecondsPerMicrosecond = 1000; - static const int64 kNanosecondsPerSecond = kNanosecondsPerMicrosecond * - kMicrosecondsPerSecond; + static const int64_t kHoursPerDay = 24; + static const int64_t kMillisecondsPerSecond = 1000; + static const int64_t kMillisecondsPerDay = + kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; + static const int64_t kMicrosecondsPerMillisecond = 1000; + static const int64_t kMicrosecondsPerSecond = + kMicrosecondsPerMillisecond * kMillisecondsPerSecond; + static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; + static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; + static const int64_t kMicrosecondsPerDay = + kMicrosecondsPerHour * kHoursPerDay; + static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; + static const int64_t kNanosecondsPerMicrosecond = 1000; + static const int64_t kNanosecondsPerSecond = + kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; // Returns true if this object has not been initialized. // @@ -315,16 +305,12 @@ class TimeBase { } // Returns true if this object represents the maximum time. - bool is_max() const { - return us_ == std::numeric_limits<int64>::max(); - } + bool is_max() const { return us_ == std::numeric_limits<int64_t>::max(); } // For serializing only. Use FromInternalValue() to reconstitute. Please don't // use this and do arithmetic on it, as it is more error prone than using the // provided operators. - int64 ToInternalValue() const { - return us_; - } + int64_t ToInternalValue() const { return us_; } TimeClass& operator=(TimeClass other) { us_ = other.us_; @@ -376,16 +362,13 @@ class TimeBase { // when deserializing a |TimeClass| structure, using a value known to be // compatible. It is not provided as a constructor because the integer type // may be unclear from the perspective of a caller. - static TimeClass FromInternalValue(int64 us) { - return TimeClass(us); - } + static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); } protected: - explicit TimeBase(int64 us) : us_(us) { - } + explicit TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. - int64 us_; + int64_t us_; }; } // namespace time_internal @@ -403,7 +386,7 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> { public: // The representation of Jan 1, 1970 UTC in microseconds since the // platform-dependent epoch. - static const int64 kTimeTToMicrosecondsOffset; + static const int64_t kTimeTToMicrosecondsOffset; #if !defined(OS_WIN) // On Mac & Linux, this value is the delta from the Windows epoch of 1601 to @@ -411,12 +394,12 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> { // 1970-based epochs to the new 1601-based ones. It should be removed from // this global header and put in the platform-specific ones when we remove the // migration code. - static const int64 kWindowsEpochDeltaMicroseconds; + static const int64_t kWindowsEpochDeltaMicroseconds; #else // To avoid overflow in QPC to Microseconds calculations, since we multiply // by kMicrosecondsPerSecond, then the QPC value should not exceed // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. - static const int64 kQPCOverflowThreshold = 0x8637BD05AF7; + enum : int64_t{kQPCOverflowThreshold = 0x8637BD05AF7}; #endif // Represents an exploded time that can be formatted nicely. This is kind of @@ -491,7 +474,7 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> { // Converts to Java convention for times, a number of // milliseconds since the epoch. - int64 ToJavaTime() const; + int64_t ToJavaTime() const; #if defined(OS_POSIX) static Time FromTimeVal(struct timeval t); @@ -555,8 +538,7 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> { private: friend class time_internal::TimeBase<Time>; - explicit Time(int64 us) : TimeBase(us) { - } + explicit Time(int64_t us) : TimeBase(us) {} // Explodes the given time to either local time |is_local = true| or UTC // |is_local = false|. @@ -571,7 +553,6 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> { // static inline TimeDelta TimeDelta::FromDays(int days) { - // Preserve max to prevent overflow. if (days == std::numeric_limits<int>::max()) return Max(); return TimeDelta(days * Time::kMicrosecondsPerDay); @@ -579,7 +560,6 @@ inline TimeDelta TimeDelta::FromDays(int days) { // static inline TimeDelta TimeDelta::FromHours(int hours) { - // Preserve max to prevent overflow. if (hours == std::numeric_limits<int>::max()) return Max(); return TimeDelta(hours * Time::kMicrosecondsPerHour); @@ -587,52 +567,47 @@ inline TimeDelta TimeDelta::FromHours(int hours) { // static inline TimeDelta TimeDelta::FromMinutes(int minutes) { - // Preserve max to prevent overflow. if (minutes == std::numeric_limits<int>::max()) return Max(); return TimeDelta(minutes * Time::kMicrosecondsPerMinute); } // static -inline TimeDelta TimeDelta::FromSeconds(int64 secs) { - // Preserve max to prevent overflow. - if (secs == std::numeric_limits<int64>::max()) - return Max(); - return TimeDelta(secs * Time::kMicrosecondsPerSecond); +inline TimeDelta TimeDelta::FromSeconds(int64_t secs) { + return TimeDelta(secs) * Time::kMicrosecondsPerSecond; } // static -inline TimeDelta TimeDelta::FromMilliseconds(int64 ms) { - // Preserve max to prevent overflow. - if (ms == std::numeric_limits<int64>::max()) - return Max(); - return TimeDelta(ms * Time::kMicrosecondsPerMillisecond); +inline TimeDelta TimeDelta::FromMilliseconds(int64_t ms) { + return TimeDelta(ms) * Time::kMicrosecondsPerMillisecond; } // static inline TimeDelta TimeDelta::FromSecondsD(double secs) { - // Preserve max to prevent overflow. - if (secs == std::numeric_limits<double>::infinity()) - return Max(); - return TimeDelta(static_cast<int64>(secs * Time::kMicrosecondsPerSecond)); + return FromDouble(secs * Time::kMicrosecondsPerSecond); } // static inline TimeDelta TimeDelta::FromMillisecondsD(double ms) { - // Preserve max to prevent overflow. - if (ms == std::numeric_limits<double>::infinity()) - return Max(); - return TimeDelta(static_cast<int64>(ms * Time::kMicrosecondsPerMillisecond)); + return FromDouble(ms * Time::kMicrosecondsPerMillisecond); } // static -inline TimeDelta TimeDelta::FromMicroseconds(int64 us) { - // Preserve max to prevent overflow. - if (us == std::numeric_limits<int64>::max()) - return Max(); +inline TimeDelta TimeDelta::FromMicroseconds(int64_t us) { return TimeDelta(us); } +// static +inline TimeDelta TimeDelta::FromDouble(double value) { + double max_magnitude = std::numeric_limits<int64_t>::max(); + TimeDelta delta = TimeDelta(static_cast<int64_t>(value)); + if (value > max_magnitude) + delta = Max(); + else if (value < -max_magnitude) + delta = -Max(); + return delta; +} + // For logging use only. BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time); @@ -663,12 +638,14 @@ class TimeTicks : public time_internal::TimeBase<TimeTicks> { static TimeTicks FromQPCValue(LONGLONG qpc_value); #endif - // Get the TimeTick value at the time of the UnixEpoch. This is useful when - // you need to relate the value of TimeTicks to a real time and date. - // Note: Upon first invocation, this function takes a snapshot of the realtime - // clock to establish a reference point. This function will return the same - // value for the duration of the application, but will be different in future - // application runs. + // Get an estimate of the TimeTick value at the time of the UnixEpoch. Because + // Time and TimeTicks respond differently to user-set time and NTP + // adjustments, this number is only an estimate. Nevertheless, this can be + // useful when you need to relate the value of TimeTicks to a real time and + // date. Note: Upon first invocation, this function takes a snapshot of the + // realtime clock to establish a reference point. This function will return + // the same value for the duration of the application, but will be different + // in future application runs. static TimeTicks UnixEpoch(); // Returns |this| snapped to the next tick, given a |tick_phase| and @@ -688,8 +665,7 @@ class TimeTicks : public time_internal::TimeBase<TimeTicks> { // Please use Now() to create a new object. This is for internal use // and testing. - explicit TimeTicks(int64 us) : TimeBase(us) { - } + explicit TimeTicks(int64_t us) : TimeBase(us) {} }; // For logging use only. @@ -709,16 +685,28 @@ class ThreadTicks : public time_internal::TimeBase<ThreadTicks> { #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID) return true; +#elif defined(OS_WIN) + return IsSupportedWin(); #else return false; #endif } + // Waits until the initialization is completed. Needs to be guarded with a + // call to IsSupported(). + static void WaitUntilInitialized() { +#if defined(OS_WIN) + WaitUntilInitializedWin(); +#endif + } + // Returns thread-specific CPU-time on systems that support this feature. // Needs to be guarded with a call to IsSupported(). Use this timer // to (approximately) measure how much time the calling thread spent doing // actual work vs. being de-scheduled. May return bogus results if the thread - // migrates to another CPU between two calls. + // migrates to another CPU between two calls. Returns an empty ThreadTicks + // object until the initialization is completed. If a clock reading is + // absolutely needed, call WaitUntilInitialized() before this method. static ThreadTicks Now(); private: @@ -726,58 +714,12 @@ class ThreadTicks : public time_internal::TimeBase<ThreadTicks> { // Please use Now() to create a new object. This is for internal use // and testing. - explicit ThreadTicks(int64 us) : TimeBase(us) { - } -}; - -// For logging use only. -std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks); - -// TraceTicks ---------------------------------------------------------------- - -// Represents high-resolution system trace clock time. -class TraceTicks : public time_internal::TimeBase<TraceTicks> { - public: - // We define this even without OS_CHROMEOS for seccomp sandbox testing. -#if defined(OS_LINUX) - // Force definition of the system trace clock; it is a chromeos-only api - // at the moment and surfacing it in the right place requires mucking - // with glibc et al. - static const clockid_t kClockSystemTrace = 11; -#endif - - TraceTicks() : TimeBase(0) { - } - - // Returns the current system trace time or, if not available on this - // platform, a high-resolution time value; or a low-resolution time value if - // neither are avalable. On systems where a global trace clock is defined, - // timestamping TraceEvents's with this value guarantees synchronization - // between events collected inside chrome and events collected outside - // (e.g. kernel, X server). - // - // On some platforms, the clock source used for tracing can vary depending on - // hardware and/or kernel support. Do not make any assumptions without - // consulting the documentation for this functionality in the time_win.cc, - // time_posix.cc, etc. files. - // - // NOTE: This is only meant to be used by the event tracing infrastructure, - // and by outside code modules in special circumstances. Please be sure to - // consult a base/trace_event/OWNER before committing any new code that uses - // this. - static TraceTicks Now(); + explicit ThreadTicks(int64_t us) : TimeBase(us) {} - private: - friend class time_internal::TimeBase<TraceTicks>; - - // Please use Now() to create a new object. This is for internal use - // and testing. - explicit TraceTicks(int64 us) : TimeBase(us) { - } }; // For logging use only. -std::ostream& operator<<(std::ostream& os, TraceTicks time_ticks); +std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks); } // namespace base diff --git a/third_party/chromium/base/time/time_posix.cc b/third_party/chromium/base/time/time_posix.cc index e8e56c2..4b37b4a 100644 --- a/third_party/chromium/base/time/time_posix.cc +++ b/third_party/chromium/base/time/time_posix.cc @@ -15,7 +15,6 @@ #include <limits> #include <ostream> -#include "base/basictypes.h" #include "base/logging.h" #include "build/build_config.h" @@ -60,8 +59,8 @@ void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { } #endif // OS_ANDROID -int64 ConvertTimespecToMicros(const struct timespec& ts) { - base::CheckedNumeric<int64> result(ts.tv_sec); +int64_t ConvertTimespecToMicros(const struct timespec& ts) { + base::CheckedNumeric<int64_t> result(ts.tv_sec); result *= base::Time::kMicrosecondsPerSecond; result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); return result.ValueOrDie(); @@ -74,7 +73,7 @@ int64 ConvertTimespecToMicros(const struct timespec& ts) { #if (defined(OS_POSIX) && \ defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \ defined(OS_BSD) || defined(OS_ANDROID) -int64 ClockNow(clockid_t clk_id) { +int64_t ClockNow(clockid_t clk_id) { struct timespec ts; if (clock_gettime(clk_id, &ts) != 0) { NOTREACHED() << "clock_gettime(" << clk_id << ") failed."; @@ -92,7 +91,7 @@ int64 ClockNow(clockid_t clk_id) { namespace base { struct timespec TimeDelta::ToTimeSpec() const { - int64 microseconds = InMicroseconds(); + int64_t microseconds = InMicroseconds(); time_t seconds = 0; if (microseconds >= Time::kMicrosecondsPerSecond) { seconds = InSeconds(); @@ -117,16 +116,16 @@ struct timespec TimeDelta::ToTimeSpec() const { // => Thu Jan 01 00:00:00 UTC 1970 // irb(main):011:0> Time.at(-11644473600).getutc() // => Mon Jan 01 00:00:00 UTC 1601 -static const int64 kWindowsEpochDeltaSeconds = 11644473600ll; +static const int64_t kWindowsEpochDeltaSeconds = 11644473600ll; // static -const int64 Time::kWindowsEpochDeltaMicroseconds = +const int64_t Time::kWindowsEpochDeltaMicroseconds = kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; // Some functions in time.cc use time_t directly, so we provide an offset // to convert from time_t (Unix epoch) and internal (Windows epoch). // static -const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; +const int64_t Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; // static Time Time::Now() { @@ -156,9 +155,9 @@ void Time::Explode(bool is_local, Exploded* exploded) const { // Time stores times with microsecond resolution, but Exploded only carries // millisecond resolution, so begin by being lossy. Adjust from Windows // epoch (1601) to Unix epoch (1970); - int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; + int64_t microseconds = us_ - kWindowsEpochDeltaMicroseconds; // The following values are all rounded towards -infinity. - int64 milliseconds; // Milliseconds since epoch. + int64_t milliseconds; // Milliseconds since epoch. SysTime seconds; // Seconds since epoch. int millisecond; // Exploded millisecond value (0-999). if (microseconds >= 0) { @@ -208,8 +207,7 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore #endif - - int64 milliseconds; + int64_t milliseconds; SysTime seconds; // Certain exploded dates do not really exist due to daylight saving times, @@ -227,11 +225,11 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { // to UTC 00:00:00 that isn't -1. timestruct = timestruct0; timestruct.tm_isdst = 0; - int64 seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local); + int64_t seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local); timestruct = timestruct0; timestruct.tm_isdst = 1; - int64 seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local); + int64_t seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local); // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones. // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'. @@ -264,14 +262,14 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { // 999ms to avoid the time being less than any other possible value that // this function can return. - // On Android, SysTime is int64, special care must be taken to avoid + // On Android, SysTime is int64_t, special care must be taken to avoid // overflows. - const int64 min_seconds = (sizeof(SysTime) < sizeof(int64)) - ? std::numeric_limits<SysTime>::min() - : std::numeric_limits<int32_t>::min(); - const int64 max_seconds = (sizeof(SysTime) < sizeof(int64)) - ? std::numeric_limits<SysTime>::max() - : std::numeric_limits<int32_t>::max(); + const int64_t min_seconds = (sizeof(SysTime) < sizeof(int64_t)) + ? std::numeric_limits<SysTime>::min() + : std::numeric_limits<int32_t>::min(); + const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t)) + ? std::numeric_limits<SysTime>::max() + : std::numeric_limits<int32_t>::max(); if (exploded.year < 1969) { milliseconds = min_seconds * kMillisecondsPerSecond; } else { @@ -309,27 +307,6 @@ ThreadTicks ThreadTicks::Now() { #endif } -// Use the Chrome OS specific system-wide clock. -#if defined(OS_CHROMEOS) -// static -TraceTicks TraceTicks::Now() { - struct timespec ts; - if (clock_gettime(kClockSystemTrace, &ts) != 0) { - // NB: fall-back for a chrome os build running on linux - return TraceTicks(ClockNow(CLOCK_MONOTONIC)); - } - return TraceTicks(ConvertTimespecToMicros(ts)); -} - -#else // !defined(OS_CHROMEOS) - -// static -TraceTicks TraceTicks::Now() { - return TraceTicks(ClockNow(CLOCK_MONOTONIC)); -} - -#endif // defined(OS_CHROMEOS) - #endif // !OS_MACOSX // static @@ -341,10 +318,8 @@ Time Time::FromTimeVal(struct timeval t) { if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 && t.tv_sec == std::numeric_limits<time_t>::max()) return Max(); - return Time( - (static_cast<int64>(t.tv_sec) * Time::kMicrosecondsPerSecond) + - t.tv_usec + - kTimeTToMicrosecondsOffset); + return Time((static_cast<int64_t>(t.tv_sec) * Time::kMicrosecondsPerSecond) + + t.tv_usec + kTimeTToMicrosecondsOffset); } struct timeval Time::ToTimeVal() const { @@ -359,7 +334,7 @@ struct timeval Time::ToTimeVal() const { result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; return result; } - int64 us = us_ - kTimeTToMicrosecondsOffset; + int64_t us = us_ - kTimeTToMicrosecondsOffset; result.tv_sec = us / Time::kMicrosecondsPerSecond; result.tv_usec = us % Time::kMicrosecondsPerSecond; return result; diff --git a/third_party/chromium/base/time/time_unittest.cc b/third_party/chromium/base/time/time_unittest.cc index 737796c..c471a76 100644 --- a/third_party/chromium/base/time/time_unittest.cc +++ b/third_party/chromium/base/time/time_unittest.cc @@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" +#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" @@ -289,52 +290,6 @@ TEST_F(TimeTest, ExplodeBeforeUnixEpoch) { EXPECT_EQ(1, exploded.millisecond); } -TEST_F(TimeTest, TimeDeltaMax) { - TimeDelta max = TimeDelta::Max(); - EXPECT_TRUE(max.is_max()); - EXPECT_EQ(max, TimeDelta::Max()); - EXPECT_GT(max, TimeDelta::FromDays(100 * 365)); - EXPECT_GT(max, TimeDelta()); -} - -TEST_F(TimeTest, TimeDeltaMaxConversions) { - TimeDelta t = TimeDelta::Max(); - EXPECT_EQ(std::numeric_limits<int64>::max(), t.ToInternalValue()); - - EXPECT_EQ(std::numeric_limits<int>::max(), t.InDays()); - EXPECT_EQ(std::numeric_limits<int>::max(), t.InHours()); - EXPECT_EQ(std::numeric_limits<int>::max(), t.InMinutes()); - EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InSecondsF()); - EXPECT_EQ(std::numeric_limits<int64>::max(), t.InSeconds()); - EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InMillisecondsF()); - EXPECT_EQ(std::numeric_limits<int64>::max(), t.InMilliseconds()); - EXPECT_EQ(std::numeric_limits<int64>::max(), t.InMillisecondsRoundedUp()); - - t = TimeDelta::FromDays(std::numeric_limits<int>::max()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromHours(std::numeric_limits<int>::max()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromMinutes(std::numeric_limits<int>::max()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromSeconds(std::numeric_limits<int64>::max()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromMilliseconds(std::numeric_limits<int64>::max()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromSecondsD(std::numeric_limits<double>::infinity()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromMillisecondsD(std::numeric_limits<double>::infinity()); - EXPECT_TRUE(t.is_max()); - - t = TimeDelta::FromMicroseconds(std::numeric_limits<int64>::max()); - EXPECT_TRUE(t.is_max()); -} - TEST_F(TimeTest, Max) { Time max = Time::Max(); EXPECT_TRUE(max.is_max()); @@ -345,7 +300,7 @@ TEST_F(TimeTest, Max) { TEST_F(TimeTest, MaxConversions) { Time t = Time::Max(); - EXPECT_EQ(std::numeric_limits<int64>::max(), t.ToInternalValue()); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.ToInternalValue()); t = Time::FromDoubleT(std::numeric_limits<double>::infinity()); EXPECT_TRUE(t.is_max()); @@ -392,7 +347,7 @@ TEST_F(TimeTest, MaxConversions) { #if defined(OS_MACOSX) TEST_F(TimeTest, TimeTOverflow) { - Time t = Time::FromInternalValue(std::numeric_limits<int64>::max() - 1); + Time t = Time::FromInternalValue(std::numeric_limits<int64_t>::max() - 1); EXPECT_FALSE(t.is_max()); EXPECT_EQ(std::numeric_limits<time_t>::max(), t.ToTimeT()); } @@ -461,12 +416,6 @@ TEST(TimeTicks, HighRes) { HighResClockTest(&TimeTicks::Now); } -TEST(TraceTicks, NowFromSystemTraceTime) { - // Re-use HighRes test for now since clock properties are identical. - using NowFunction = TimeTicks (*)(void); - HighResClockTest(reinterpret_cast<NowFunction>(&TraceTicks::Now)); -} - TEST(TimeTicks, SnappedToNextTickBasic) { base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000); base::TimeDelta interval = base::TimeDelta::FromMicroseconds(1000); @@ -546,6 +495,7 @@ TEST(TimeDelta, FromAndIn) { EXPECT_EQ(13, TimeDelta::FromMillisecondsD(13.3).InMilliseconds()); EXPECT_EQ(13.3, TimeDelta::FromMillisecondsD(13.3).InMillisecondsF()); EXPECT_EQ(13, TimeDelta::FromMicroseconds(13).InMicroseconds()); + EXPECT_EQ(3.456, TimeDelta::FromMillisecondsD(3.45678).InMillisecondsF()); } #if defined(OS_POSIX) @@ -600,25 +550,102 @@ std::string AnyToString(Any any) { } TEST(TimeDelta, Magnitude) { - const int64 zero = 0; + const int64_t zero = 0; EXPECT_EQ(TimeDelta::FromMicroseconds(zero), TimeDelta::FromMicroseconds(zero).magnitude()); - const int64 one = 1; - const int64 negative_one = -1; + const int64_t one = 1; + const int64_t negative_one = -1; EXPECT_EQ(TimeDelta::FromMicroseconds(one), TimeDelta::FromMicroseconds(one).magnitude()); EXPECT_EQ(TimeDelta::FromMicroseconds(one), TimeDelta::FromMicroseconds(negative_one).magnitude()); - const int64 max_int64_minus_one = std::numeric_limits<int64>::max() - 1; - const int64 min_int64_plus_two = std::numeric_limits<int64>::min() + 2; + const int64_t max_int64_minus_one = std::numeric_limits<int64_t>::max() - 1; + const int64_t min_int64_plus_two = std::numeric_limits<int64_t>::min() + 2; EXPECT_EQ(TimeDelta::FromMicroseconds(max_int64_minus_one), TimeDelta::FromMicroseconds(max_int64_minus_one).magnitude()); EXPECT_EQ(TimeDelta::FromMicroseconds(max_int64_minus_one), TimeDelta::FromMicroseconds(min_int64_plus_two).magnitude()); } +TEST(TimeDelta, Max) { + TimeDelta max = TimeDelta::Max(); + EXPECT_TRUE(max.is_max()); + EXPECT_EQ(max, TimeDelta::Max()); + EXPECT_GT(max, TimeDelta::FromDays(100 * 365)); + EXPECT_GT(max, TimeDelta()); +} + +bool IsMin(TimeDelta delta) { + return (-delta).is_max(); +} + +TEST(TimeDelta, MaxConversions) { + TimeDelta t = TimeDelta::Max(); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.ToInternalValue()); + + EXPECT_EQ(std::numeric_limits<int>::max(), t.InDays()); + EXPECT_EQ(std::numeric_limits<int>::max(), t.InHours()); + EXPECT_EQ(std::numeric_limits<int>::max(), t.InMinutes()); + EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InSecondsF()); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.InSeconds()); + EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InMillisecondsF()); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.InMilliseconds()); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.InMillisecondsRoundedUp()); + + t = TimeDelta::FromDays(std::numeric_limits<int>::max()); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromHours(std::numeric_limits<int>::max()); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromMinutes(std::numeric_limits<int>::max()); + EXPECT_TRUE(t.is_max()); + + int64_t max_int = std::numeric_limits<int64_t>::max(); + + t = TimeDelta::FromSeconds(max_int / Time::kMicrosecondsPerSecond + 1); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromMilliseconds(max_int / Time::kMillisecondsPerSecond + 1); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromMicroseconds(max_int); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromSeconds(-max_int / Time::kMicrosecondsPerSecond - 1); + EXPECT_TRUE(IsMin(t)); + + t = TimeDelta::FromMilliseconds(-max_int / Time::kMillisecondsPerSecond - 1); + EXPECT_TRUE(IsMin(t)); + + t = TimeDelta::FromMicroseconds(-max_int); + EXPECT_TRUE(IsMin(t)); + + t = -TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::min()); + EXPECT_FALSE(IsMin(t)); + + t = TimeDelta::FromSecondsD(std::numeric_limits<double>::infinity()); + EXPECT_TRUE(t.is_max()); + + double max_d = max_int; + + t = TimeDelta::FromSecondsD(max_d / Time::kMicrosecondsPerSecond + 1); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromMillisecondsD(std::numeric_limits<double>::infinity()); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromMillisecondsD(max_d / Time::kMillisecondsPerSecond * 2); + EXPECT_TRUE(t.is_max()); + + t = TimeDelta::FromSecondsD(-max_d / Time::kMicrosecondsPerSecond - 1); + EXPECT_TRUE(IsMin(t)); + + t = TimeDelta::FromMillisecondsD(-max_d / Time::kMillisecondsPerSecond * 2); + EXPECT_TRUE(IsMin(t)); +} TEST(TimeDelta, NumericOperators) { double d = 0.5; @@ -645,7 +672,6 @@ TEST(TimeDelta, NumericOperators) { EXPECT_EQ(TimeDelta::FromMilliseconds(500), f * TimeDelta::FromMilliseconds(1000)); - int i = 2; EXPECT_EQ(TimeDelta::FromMilliseconds(2000), TimeDelta::FromMilliseconds(1000) * i); @@ -670,7 +696,6 @@ TEST(TimeDelta, NumericOperators) { EXPECT_EQ(TimeDelta::FromMilliseconds(2000), i64 * TimeDelta::FromMilliseconds(1000)); - EXPECT_EQ(TimeDelta::FromMilliseconds(500), TimeDelta::FromMilliseconds(1000) * 0.5); EXPECT_EQ(TimeDelta::FromMilliseconds(2000), @@ -694,10 +719,6 @@ TEST(TimeDelta, NumericOperators) { 2 * TimeDelta::FromMilliseconds(1000)); } -bool IsMin(TimeDelta delta) { - return (-delta).is_max(); -} - TEST(TimeDelta, Overflows) { // Some sanity checks. EXPECT_TRUE(TimeDelta::Max().is_max()); diff --git a/third_party/chromium/base/tuple.h b/third_party/chromium/base/tuple.h index ef51d85..e5872cc 100644 --- a/third_party/chromium/base/tuple.h +++ b/third_party/chromium/base/tuple.h @@ -28,7 +28,10 @@ #ifndef BASE_TUPLE_H_ #define BASE_TUPLE_H_ +#include <stddef.h> + #include "base/bind_helpers.h" +#include "build/build_config.h" namespace base { @@ -150,7 +153,7 @@ template <size_t N, typename T> struct TupleLeaf; template <typename... Ts> -struct Tuple : TupleBase<Ts...> { +struct Tuple final : TupleBase<Ts...> { Tuple() : TupleBase<Ts...>() {} explicit Tuple(typename TupleTraits<Ts>::ParamType... args) : TupleBase<Ts...>(args...) {} @@ -158,7 +161,7 @@ struct Tuple : TupleBase<Ts...> { // Avoids ambiguity between Tuple's two constructors. template <> -struct Tuple<> {}; +struct Tuple<> final {}; template <size_t... Ns, typename... Ts> struct TupleBaseImpl<IndexSequence<Ns...>, Ts...> : TupleLeaf<Ns, Ts>... { @@ -241,11 +244,6 @@ inline Tuple<Ts&...> MakeRefTuple(Ts&... arg) { // Non-Static Dispatchers with no out params. -template <typename ObjT, typename Method, typename A> -inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { - (obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg)); -} - template <typename ObjT, typename Method, typename... Ts, size_t... Ns> inline void DispatchToMethodImpl(ObjT* obj, Method method, @@ -263,11 +261,6 @@ inline void DispatchToMethod(ObjT* obj, // Static Dispatchers with no out params. -template <typename Function, typename A> -inline void DispatchToMethod(Function function, const A& arg) { - (*function)(base::internal::UnwrapTraits<A>::Unwrap(arg)); -} - template <typename Function, typename... Ts, size_t... Ns> inline void DispatchToFunctionImpl(Function function, const Tuple<Ts...>& arg, @@ -284,29 +277,6 @@ inline void DispatchToFunction(Function function, const Tuple<Ts...>& arg) { template <typename ObjT, typename Method, - typename In, - typename... OutTs, - size_t... OutNs> -inline void DispatchToMethodImpl(ObjT* obj, - Method method, - const In& in, - Tuple<OutTs...>* out, - IndexSequence<OutNs...>) { - (obj->*method)(base::internal::UnwrapTraits<In>::Unwrap(in), - &get<OutNs>(*out)...); -} - -template <typename ObjT, typename Method, typename In, typename... OutTs> -inline void DispatchToMethod(ObjT* obj, - Method method, - const In& in, - Tuple<OutTs...>* out) { - DispatchToMethodImpl(obj, method, in, out, - MakeIndexSequence<sizeof...(OutTs)>()); -} - -template <typename ObjT, - typename Method, typename... InTs, typename... OutTs, size_t... InNs, diff --git a/third_party/chromium/base/values.cc b/third_party/chromium/base/values.cc index 689fdd7..55719da 100644 --- a/third_party/chromium/base/values.cc +++ b/third_party/chromium/base/values.cc @@ -9,6 +9,7 @@ #include <algorithm> #include <cmath> #include <ostream> +#include <utility> #include "base/json/json_writer.h" #include "base/logging.h" @@ -32,7 +33,7 @@ scoped_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) { if (child_copy) { if (!copy) copy.reset(new ListValue); - copy->Append(child_copy.Pass()); + copy->Append(std::move(child_copy)); } } return copy; @@ -46,7 +47,7 @@ scoped_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( if (child_copy) { if (!copy) copy.reset(new DictionaryValue); - copy->SetWithoutPathExpansion(it.key(), child_copy.Pass()); + copy->SetWithoutPathExpansion(it.key(), std::move(child_copy)); } } return copy; @@ -92,23 +93,23 @@ scoped_ptr<Value> Value::CreateNullValue() { return make_scoped_ptr(new Value(TYPE_NULL)); } -bool Value::GetAsBinary(const BinaryValue** out_value) const { +bool Value::GetAsBinary(const BinaryValue** /* out_value */) const { return false; } -bool Value::GetAsBoolean(bool* out_value) const { +bool Value::GetAsBoolean(bool* /* out_value */) const { return false; } -bool Value::GetAsInteger(int* out_value) const { +bool Value::GetAsInteger(int* /* out_value */) const { return false; } -bool Value::GetAsDouble(double* out_value) const { +bool Value::GetAsDouble(double* /* out_value */) const { return false; } -bool Value::GetAsString(std::string* out_value) const { +bool Value::GetAsString(std::string* /* out_value */) const { return false; } @@ -116,19 +117,19 @@ bool Value::GetAsString(const StringValue** out_value) const { return false; } -bool Value::GetAsList(ListValue** out_value) { +bool Value::GetAsList(ListValue** /* out_value */) { return false; } -bool Value::GetAsList(const ListValue** out_value) const { +bool Value::GetAsList(const ListValue** /* out_value */) const { return false; } -bool Value::GetAsDictionary(DictionaryValue** out_value) { +bool Value::GetAsDictionary(DictionaryValue** /* out_value */) { return false; } -bool Value::GetAsDictionary(const DictionaryValue** out_value) const { +bool Value::GetAsDictionary(const DictionaryValue** /* out_value */) const { return false; } @@ -298,10 +299,7 @@ BinaryValue::BinaryValue() } BinaryValue::BinaryValue(scoped_ptr<char[]> buffer, size_t size) - : Value(TYPE_BINARY), - buffer_(buffer.Pass()), - size_(size) { -} + : Value(TYPE_BINARY), buffer_(std::move(buffer)), size_(size) {} BinaryValue::~BinaryValue() { } @@ -312,7 +310,7 @@ BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer, char* buffer_copy = new char[size]; memcpy(buffer_copy, buffer, size); scoped_ptr<char[]> scoped_buffer_copy(buffer_copy); - return new BinaryValue(scoped_buffer_copy.Pass(), size); + return new BinaryValue(std::move(scoped_buffer_copy), size); } bool BinaryValue::GetAsBinary(const BinaryValue** out_value) const { @@ -336,6 +334,16 @@ bool BinaryValue::Equals(const Value* other) const { ///////////////////// DictionaryValue //////////////////// +// static +scoped_ptr<DictionaryValue> DictionaryValue::From(scoped_ptr<Value> value) { + DictionaryValue* out; + if (value && value->GetAsDictionary(&out)) { + ignore_result(value.release()); + return make_scoped_ptr(out); + } + return nullptr; +} + DictionaryValue::DictionaryValue() : Value(TYPE_DICTIONARY) { } @@ -394,7 +402,8 @@ void DictionaryValue::Set(const std::string& path, scoped_ptr<Value> in_value) { current_path.erase(0, delimiter_position + 1); } - current_dictionary->SetWithoutPathExpansion(current_path, in_value.Pass()); + current_dictionary->SetWithoutPathExpansion(current_path, + std::move(in_value)); } void DictionaryValue::Set(const std::string& path, Value* in_value) { @@ -457,27 +466,30 @@ void DictionaryValue::SetStringWithoutPathExpansion( SetWithoutPathExpansion(path, new StringValue(in_value)); } -bool DictionaryValue::Get(const std::string& path, +bool DictionaryValue::Get(StringPiece path, const Value** out_value) const { DCHECK(IsStringUTF8(path)); - std::string current_path(path); + StringPiece current_path(path); const DictionaryValue* current_dictionary = this; for (size_t delimiter_position = current_path.find('.'); delimiter_position != std::string::npos; delimiter_position = current_path.find('.')) { const DictionaryValue* child_dictionary = NULL; - if (!current_dictionary->GetDictionary( - current_path.substr(0, delimiter_position), &child_dictionary)) + if (!current_dictionary->GetDictionaryWithoutPathExpansion( + current_path.substr(0, delimiter_position).as_string(), + &child_dictionary)) { return false; + } current_dictionary = child_dictionary; - current_path.erase(0, delimiter_position + 1); + current_path = current_path.substr(delimiter_position + 1); } - return current_dictionary->GetWithoutPathExpansion(current_path, out_value); + return current_dictionary->GetWithoutPathExpansion(current_path.as_string(), + out_value); } -bool DictionaryValue::Get(const std::string& path, Value** out_value) { +bool DictionaryValue::Get(StringPiece path, Value** out_value) { return static_cast<const DictionaryValue&>(*this).Get( path, const_cast<const Value**>(out_value)); @@ -554,7 +566,7 @@ bool DictionaryValue::GetBinary(const std::string& path, const_cast<const BinaryValue**>(out_value)); } -bool DictionaryValue::GetDictionary(const std::string& path, +bool DictionaryValue::GetDictionary(StringPiece path, const DictionaryValue** out_value) const { const Value* value; bool result = Get(path, &value); @@ -567,7 +579,7 @@ bool DictionaryValue::GetDictionary(const std::string& path, return true; } -bool DictionaryValue::GetDictionary(const std::string& path, +bool DictionaryValue::GetDictionary(StringPiece path, DictionaryValue** out_value) { return static_cast<const DictionaryValue&>(*this).GetDictionary( path, @@ -824,6 +836,16 @@ bool DictionaryValue::Equals(const Value* other) const { ///////////////////// ListValue //////////////////// +// static +scoped_ptr<ListValue> ListValue::From(scoped_ptr<Value> value) { + ListValue* out; + if (value && value->GetAsList(&out)) { + ignore_result(value.release()); + return make_scoped_ptr(out); + } + return nullptr; +} + ListValue::ListValue() : Value(TYPE_LIST) { } diff --git a/third_party/chromium/base/values.h b/third_party/chromium/base/values.h index 7ae52a9..25d2a79 100644 --- a/third_party/chromium/base/values.h +++ b/third_party/chromium/base/values.h @@ -9,7 +9,7 @@ // JavaScript. As such, it is NOT a generalized variant type, since only the // types supported by JavaScript/JSON are supported. // -// IN PARTICULAR this means that there is no support for int64 or unsigned +// IN PARTICULAR this means that there is no support for int64_t or unsigned // numbers. Writing JSON with such types would violate the spec. If you need // something like this, either use a double or make a string value containing // the number you want. @@ -18,6 +18,7 @@ #define BASE_VALUES_H_ #include <stddef.h> +#include <stdint.h> #include <iosfwd> #include <map> @@ -26,9 +27,10 @@ #include <vector> #include "base/base_export.h" -#include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" namespace base { @@ -202,6 +204,9 @@ class BASE_EXPORT BinaryValue : public Value { // are |std::string|s and should be UTF-8 encoded. class BASE_EXPORT DictionaryValue : public Value { public: + // Returns |value| if it is a dictionary, nullptr otherwise. + static scoped_ptr<DictionaryValue> From(scoped_ptr<Value> value); + DictionaryValue(); ~DictionaryValue() override; @@ -261,8 +266,8 @@ class BASE_EXPORT DictionaryValue : public Value { // Otherwise, it will return false and |out_value| will be untouched. // Note that the dictionary always owns the value that's returned. // |out_value| is optional and will only be set if non-NULL. - bool Get(const std::string& path, const Value** out_value) const; - bool Get(const std::string& path, Value** out_value); + bool Get(StringPiece path, const Value** out_value) const; + bool Get(StringPiece path, Value** out_value); // These are convenience forms of Get(). The value will be retrieved // and the return value will be true if the path is valid and the value at @@ -277,9 +282,9 @@ class BASE_EXPORT DictionaryValue : public Value { bool GetStringASCII(const std::string& path, std::string* out_value) const; bool GetBinary(const std::string& path, const BinaryValue** out_value) const; bool GetBinary(const std::string& path, BinaryValue** out_value); - bool GetDictionary(const std::string& path, + bool GetDictionary(StringPiece path, const DictionaryValue** out_value) const; - bool GetDictionary(const std::string& path, DictionaryValue** out_value); + bool GetDictionary(StringPiece path, DictionaryValue** out_value); bool GetList(const std::string& path, const ListValue** out_value) const; bool GetList(const std::string& path, ListValue** out_value); @@ -374,6 +379,9 @@ class BASE_EXPORT ListValue : public Value { typedef ValueVector::iterator iterator; typedef ValueVector::const_iterator const_iterator; + // Returns |value| if it is a list, nullptr otherwise. + static scoped_ptr<ListValue> From(scoped_ptr<Value> value); + ListValue(); ~ListValue() override; diff --git a/third_party/chromium/base/values_unittest.cc b/third_party/chromium/base/values_unittest.cc index d246691..b5e47dd 100644 --- a/third_party/chromium/base/values_unittest.cc +++ b/third_party/chromium/base/values_unittest.cc @@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <stddef.h> + #include <limits> +#include <utility> #include <gtest/gtest.h> @@ -34,13 +37,13 @@ TEST(ValuesTest, Basic) { settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks)); scoped_ptr<ListValue> new_toolbar_bookmarks(new ListValue); - settings.Set("global.toolbar.bookmarks", new_toolbar_bookmarks.Pass()); + settings.Set("global.toolbar.bookmarks", std::move(new_toolbar_bookmarks)); ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks)); scoped_ptr<DictionaryValue> new_bookmark(new DictionaryValue); new_bookmark->SetString("name", "Froogle"); new_bookmark->SetString("url", "http://froogle.com"); - toolbar_bookmarks->Append(new_bookmark.Pass()); + toolbar_bookmarks->Append(std::move(new_bookmark)); ListValue* bookmark_list; ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &bookmark_list)); @@ -114,7 +117,7 @@ TEST(ValuesTest, BinaryValue) { // Test the common case of a non-empty buffer scoped_ptr<char[]> buffer(new char[15]); char* original_buffer = buffer.get(); - binary.reset(new BinaryValue(buffer.Pass(), 15)); + binary.reset(new BinaryValue(std::move(buffer), 15)); ASSERT_TRUE(binary.get()); ASSERT_TRUE(binary->GetBuffer()); ASSERT_EQ(original_buffer, binary->GetBuffer()); @@ -236,7 +239,7 @@ TEST(ValuesTest, ListRemoval) { ListValue list; scoped_ptr<DeletionTestValue> value(new DeletionTestValue(&deletion_flag)); DeletionTestValue* original_value = value.get(); - list.Append(value.Pass()); + list.Append(std::move(value)); EXPECT_FALSE(deletion_flag); size_t index = 0; list.Remove(*original_value, &index); @@ -379,41 +382,41 @@ TEST(ValuesTest, DeepCopy) { DictionaryValue original_dict; scoped_ptr<Value> scoped_null = Value::CreateNullValue(); Value* original_null = scoped_null.get(); - original_dict.Set("null", scoped_null.Pass()); + original_dict.Set("null", std::move(scoped_null)); scoped_ptr<FundamentalValue> scoped_bool(new FundamentalValue(true)); FundamentalValue* original_bool = scoped_bool.get(); - original_dict.Set("bool", scoped_bool.Pass()); + original_dict.Set("bool", std::move(scoped_bool)); scoped_ptr<FundamentalValue> scoped_int(new FundamentalValue(42)); FundamentalValue* original_int = scoped_int.get(); - original_dict.Set("int", scoped_int.Pass()); + original_dict.Set("int", std::move(scoped_int)); scoped_ptr<FundamentalValue> scoped_double(new FundamentalValue(3.14)); FundamentalValue* original_double = scoped_double.get(); - original_dict.Set("double", scoped_double.Pass()); + original_dict.Set("double", std::move(scoped_double)); scoped_ptr<StringValue> scoped_string(new StringValue("hello")); StringValue* original_string = scoped_string.get(); - original_dict.Set("string", scoped_string.Pass()); + original_dict.Set("string", std::move(scoped_string)); scoped_ptr<char[]> original_buffer(new char[42]); memset(original_buffer.get(), '!', 42); scoped_ptr<BinaryValue> scoped_binary( - new BinaryValue(original_buffer.Pass(), 42)); + new BinaryValue(std::move(original_buffer), 42)); BinaryValue* original_binary = scoped_binary.get(); - original_dict.Set("binary", scoped_binary.Pass()); + original_dict.Set("binary", std::move(scoped_binary)); scoped_ptr<ListValue> scoped_list(new ListValue()); Value* original_list = scoped_list.get(); scoped_ptr<FundamentalValue> scoped_list_element_0(new FundamentalValue(0)); Value* original_list_element_0 = scoped_list_element_0.get(); - scoped_list->Append(scoped_list_element_0.Pass()); + scoped_list->Append(std::move(scoped_list_element_0)); scoped_ptr<FundamentalValue> scoped_list_element_1(new FundamentalValue(1)); Value* original_list_element_1 = scoped_list_element_1.get(); - scoped_list->Append(scoped_list_element_1.Pass()); - original_dict.Set("list", scoped_list.Pass()); + scoped_list->Append(std::move(scoped_list_element_1)); + original_dict.Set("list", std::move(scoped_list)); scoped_ptr<DictionaryValue> scoped_nested_dictionary(new DictionaryValue()); Value* original_nested_dictionary = scoped_nested_dictionary.get(); scoped_nested_dictionary->SetString("key", "value"); - original_dict.Set("dictionary", scoped_nested_dictionary.Pass()); + original_dict.Set("dictionary", std::move(scoped_nested_dictionary)); scoped_ptr<DictionaryValue> copy_dict = original_dict.CreateDeepCopy(); ASSERT_TRUE(copy_dict.get()); @@ -534,9 +537,9 @@ TEST(ValuesTest, Equals) { list->Append(make_scoped_ptr(new DictionaryValue)); scoped_ptr<Value> list_copy(list->CreateDeepCopy()); - dv.Set("f", list.Pass()); + dv.Set("f", std::move(list)); EXPECT_FALSE(dv.Equals(copy.get())); - copy->Set("f", list_copy.Pass()); + copy->Set("f", std::move(list_copy)); EXPECT_TRUE(dv.Equals(copy.get())); original_list->Append(make_scoped_ptr(new FundamentalValue(true))); @@ -577,34 +580,34 @@ TEST(ValuesTest, DeepCopyCovariantReturnTypes) { DictionaryValue original_dict; scoped_ptr<Value> scoped_null(Value::CreateNullValue()); Value* original_null = scoped_null.get(); - original_dict.Set("null", scoped_null.Pass()); + original_dict.Set("null", std::move(scoped_null)); scoped_ptr<FundamentalValue> scoped_bool(new FundamentalValue(true)); Value* original_bool = scoped_bool.get(); - original_dict.Set("bool", scoped_bool.Pass()); + original_dict.Set("bool", std::move(scoped_bool)); scoped_ptr<FundamentalValue> scoped_int(new FundamentalValue(42)); Value* original_int = scoped_int.get(); - original_dict.Set("int", scoped_int.Pass()); + original_dict.Set("int", std::move(scoped_int)); scoped_ptr<FundamentalValue> scoped_double(new FundamentalValue(3.14)); Value* original_double = scoped_double.get(); - original_dict.Set("double", scoped_double.Pass()); + original_dict.Set("double", std::move(scoped_double)); scoped_ptr<StringValue> scoped_string(new StringValue("hello")); Value* original_string = scoped_string.get(); - original_dict.Set("string", scoped_string.Pass()); + original_dict.Set("string", std::move(scoped_string)); scoped_ptr<char[]> original_buffer(new char[42]); memset(original_buffer.get(), '!', 42); scoped_ptr<BinaryValue> scoped_binary( - new BinaryValue(original_buffer.Pass(), 42)); + new BinaryValue(std::move(original_buffer), 42)); Value* original_binary = scoped_binary.get(); - original_dict.Set("binary", scoped_binary.Pass()); + original_dict.Set("binary", std::move(scoped_binary)); scoped_ptr<ListValue> scoped_list(new ListValue()); Value* original_list = scoped_list.get(); scoped_ptr<FundamentalValue> scoped_list_element_0(new FundamentalValue(0)); - scoped_list->Append(scoped_list_element_0.Pass()); + scoped_list->Append(std::move(scoped_list_element_0)); scoped_ptr<FundamentalValue> scoped_list_element_1(new FundamentalValue(1)); - scoped_list->Append(scoped_list_element_1.Pass()); - original_dict.Set("list", scoped_list.Pass()); + scoped_list->Append(std::move(scoped_list_element_1)); + original_dict.Set("list", std::move(scoped_list)); scoped_ptr<Value> copy_dict = original_dict.CreateDeepCopy(); scoped_ptr<Value> copy_null = original_null->CreateDeepCopy(); @@ -657,7 +660,7 @@ TEST(ValuesTest, RemoveEmptyChildren) { scoped_ptr<DictionaryValue> inner(new DictionaryValue); inner->Set("empty_dict", make_scoped_ptr(new DictionaryValue)); inner->Set("empty_list", make_scoped_ptr(new ListValue)); - root->Set("dict_with_empty_children", inner.Pass()); + root->Set("dict_with_empty_children", std::move(inner)); root = root->DeepCopyWithoutEmptyChildren(); EXPECT_EQ(2U, root->size()); } @@ -665,7 +668,7 @@ TEST(ValuesTest, RemoveEmptyChildren) { scoped_ptr<ListValue> inner(new ListValue); inner->Append(make_scoped_ptr(new DictionaryValue)); inner->Append(make_scoped_ptr(new ListValue)); - root->Set("list_with_empty_children", inner.Pass()); + root->Set("list_with_empty_children", std::move(inner)); root = root->DeepCopyWithoutEmptyChildren(); EXPECT_EQ(2U, root->size()); } @@ -675,11 +678,11 @@ TEST(ValuesTest, RemoveEmptyChildren) { scoped_ptr<ListValue> inner(new ListValue()); inner->Append(make_scoped_ptr(new DictionaryValue)); inner->Append(make_scoped_ptr(new ListValue)); - root->Set("list_with_empty_children", inner.Pass()); + root->Set("list_with_empty_children", std::move(inner)); scoped_ptr<DictionaryValue> inner2(new DictionaryValue); inner2->Set("empty_dict", make_scoped_ptr(new DictionaryValue)); inner2->Set("empty_list", make_scoped_ptr(new ListValue)); - root->Set("dict_with_empty_children", inner2.Pass()); + root->Set("dict_with_empty_children", std::move(inner2)); root = root->DeepCopyWithoutEmptyChildren(); EXPECT_EQ(2U, root->size()); } @@ -690,8 +693,8 @@ TEST(ValuesTest, RemoveEmptyChildren) { scoped_ptr<ListValue> inner2(new ListValue); inner2->Append(make_scoped_ptr(new StringValue("hello"))); inner->Append(make_scoped_ptr(new DictionaryValue)); - inner->Append(inner2.Pass()); - root->Set("list_with_empty_children", inner.Pass()); + inner->Append(std::move(inner2)); + root->Set("list_with_empty_children", std::move(inner)); root = root->DeepCopyWithoutEmptyChildren(); EXPECT_EQ(3U, root->size()); @@ -710,7 +713,7 @@ TEST(ValuesTest, MergeDictionary) { scoped_ptr<DictionaryValue> base_sub_dict(new DictionaryValue); base_sub_dict->SetString("sub_base_key", "sub_base_key_value_base"); base_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_base"); - base->Set("sub_dict_key", base_sub_dict.Pass()); + base->Set("sub_dict_key", std::move(base_sub_dict)); scoped_ptr<DictionaryValue> merge(new DictionaryValue); merge->SetString("merge_key", "merge_key_value_merge"); @@ -718,7 +721,7 @@ TEST(ValuesTest, MergeDictionary) { scoped_ptr<DictionaryValue> merge_sub_dict(new DictionaryValue); merge_sub_dict->SetString("sub_merge_key", "sub_merge_key_value_merge"); merge_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_merge"); - merge->Set("sub_dict_key", merge_sub_dict.Pass()); + merge->Set("sub_dict_key", std::move(merge_sub_dict)); base->MergeDictionary(merge.get()); @@ -759,7 +762,7 @@ TEST(ValuesTest, MergeDictionaryDeepCopy) { EXPECT_EQ("value", value); scoped_ptr<DictionaryValue> base(new DictionaryValue); - base->Set("dict", child.Pass()); + base->Set("dict", std::move(child)); EXPECT_EQ(1U, base->size()); DictionaryValue* ptr; diff --git a/third_party/chromium/crypto/p224.cc b/third_party/chromium/crypto/p224.cc index 81bce3a..ce3b7ee 100644 --- a/third_party/chromium/crypto/p224.cc +++ b/third_party/chromium/crypto/p224.cc @@ -11,17 +11,14 @@ #include <string.h> -namespace crypto { -namespace p224 { - namespace { -inline uint32 ByteSwap(uint32 x) { +inline uint32_t ByteSwap(uint32_t x) { return ((x & 0x000000fful) << 24) | ((x & 0x0000ff00ul) << 8) | ((x & 0x00ff0000ul) >> 8) | ((x & 0xff000000ul) >> 24); } -inline uint32 HostToNet32(uint32 x) { +inline uint32_t HostToNet32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return ByteSwap(x); #else @@ -29,7 +26,7 @@ inline uint32 HostToNet32(uint32 x) { #endif } -inline uint32 NetToHost32(uint32 x) { +inline uint32_t NetToHost32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return ByteSwap(x); #else @@ -42,13 +39,15 @@ inline uint32 NetToHost32(uint32 x) { // The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. // // Field elements are represented by a FieldElement, which is a typedef to an -// array of 8 uint32's. The value of a FieldElement, a, is: +// array of 8 uint32_t's. The value of a FieldElement, a, is: // a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] // // Using 28-bit limbs means that there's only 4 bits of headroom, which is less // than we would really like. But it has the useful feature that we hit 2**224 // exactly, making the reflections during a reduce much nicer. +using crypto::p224::FieldElement; + // kP is the P224 prime. const FieldElement kP = { 1, 0, 0, 268431360, @@ -58,12 +57,12 @@ const FieldElement kP = { void Contract(FieldElement* inout); // IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise. -uint32 IsZero(const FieldElement& a) { +uint32_t IsZero(const FieldElement& a) { FieldElement minimal; memcpy(&minimal, &a, sizeof(minimal)); Contract(&minimal); - uint32 is_zero = 0, is_p = 0; + uint32_t is_zero = 0, is_p = 0; for (unsigned i = 0; i < 8; i++) { is_zero |= minimal[i]; is_p |= minimal[i] - kP[i]; @@ -85,7 +84,7 @@ uint32 IsZero(const FieldElement& a) { // For is_zero and is_p, the LSB is 0 iff all the bits are zero. is_zero &= is_p & 1; is_zero = (~is_zero) << 31; - is_zero = static_cast<int32>(is_zero) >> 31; + is_zero = static_cast<int32_t>(is_zero) >> 31; return is_zero; } @@ -98,9 +97,9 @@ void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) { } } -static const uint32 kTwo31p3 = (1u << 31) + (1u << 3); -static const uint32 kTwo31m3 = (1u << 31) - (1u << 3); -static const uint32 kTwo31m15m3 = (1u << 31) - (1u << 15) - (1u << 3); +static const uint32_t kTwo31p3 = (1u << 31) + (1u << 3); +static const uint32_t kTwo31m3 = (1u << 31) - (1u << 3); +static const uint32_t kTwo31m15m3 = (1u << 31) - (1u << 15) - (1u << 3); // kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can // subtract smaller amounts without underflow. See the section "Subtraction" in // [1] for why. @@ -120,22 +119,22 @@ void Subtract(FieldElement* out, const FieldElement& a, const FieldElement& b) { } } -static const uint64 kTwo63p35 = (1ull<<63) + (1ull<<35); -static const uint64 kTwo63m35 = (1ull<<63) - (1ull<<35); -static const uint64 kTwo63m35m19 = (1ull<<63) - (1ull<<35) - (1ull<<19); +static const uint64_t kTwo63p35 = (1ull << 63) + (1ull << 35); +static const uint64_t kTwo63m35 = (1ull << 63) - (1ull << 35); +static const uint64_t kTwo63m35m19 = (1ull << 63) - (1ull << 35) - (1ull << 19); // kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section // "Subtraction" in [1] for why. -static const uint64 kZero63ModP[8] = { - kTwo63p35, kTwo63m35, kTwo63m35, kTwo63m35, - kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35, +static const uint64_t kZero63ModP[8] = { + kTwo63p35, kTwo63m35, kTwo63m35, kTwo63m35, + kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35, }; -static const uint32 kBottom28Bits = 0xfffffff; +static const uint32_t kBottom28Bits = 0xfffffff; // LargeFieldElement also represents an element of the field. The limbs are // still spaced 28-bits apart and in little-endian order. So the limbs are at // 0, 28, 56, ..., 392 bits, each 64-bits wide. -typedef uint64 LargeFieldElement[15]; +typedef uint64_t LargeFieldElement[15]; // ReduceLarge converts a LargeFieldElement to a FieldElement. // @@ -170,21 +169,21 @@ void ReduceLarge(FieldElement* out, LargeFieldElement* inptr) { // 32-bit operations. for (int i = 1; i < 8; i++) { in[i+1] += in[i] >> 28; - (*out)[i] = static_cast<uint32>(in[i] & kBottom28Bits); + (*out)[i] = static_cast<uint32_t>(in[i] & kBottom28Bits); } // Eliminate the term at 2*224 that we introduced while keeping the same // value mod p. in[0] -= in[8]; // reflection off the "+1" term of p. - (*out)[3] += static_cast<uint32>(in[8] & 0xffff) << 12; // "-2**96" term - (*out)[4] += static_cast<uint32>(in[8] >> 16); // rest of "-2**96" term + (*out)[3] += static_cast<uint32_t>(in[8] & 0xffff) << 12; // "-2**96" term + (*out)[4] += static_cast<uint32_t>(in[8] >> 16); // rest of "-2**96" term // in[0] < 2**64 // out[3] < 2**29 // out[4] < 2**29 // out[1,2,5..7] < 2**28 - (*out)[0] = static_cast<uint32>(in[0] & kBottom28Bits); - (*out)[1] += static_cast<uint32>((in[0] >> 28) & kBottom28Bits); - (*out)[2] += static_cast<uint32>(in[0] >> 56); + (*out)[0] = static_cast<uint32_t>(in[0] & kBottom28Bits); + (*out)[1] += static_cast<uint32_t>((in[0] >> 28) & kBottom28Bits); + (*out)[2] += static_cast<uint32_t>(in[0] >> 56); // out[0] < 2**28 // out[1..4] < 2**29 // out[5..7] < 2**28 @@ -206,7 +205,7 @@ void Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { - tmp[i+j] += static_cast<uint64>(a[i]) * static_cast<uint64>(b[j]); + tmp[i + j] += static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(b[j]); } } @@ -223,7 +222,7 @@ void Square(FieldElement* out, const FieldElement& a) { for (int i = 0; i < 8; i++) { for (int j = 0; j <= i; j++) { - uint64 r = static_cast<uint64>(a[i]) * static_cast<uint64>(a[j]); + uint64_t r = static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(a[j]); if (i == j) { tmp[i+j] += r; } else { @@ -246,16 +245,16 @@ void Reduce(FieldElement* in_out) { a[i+1] += a[i] >> 28; a[i] &= kBottom28Bits; } - uint32 top = a[7] >> 28; + uint32_t top = a[7] >> 28; a[7] &= kBottom28Bits; // top < 2**4 // Constant-time: mask = (top != 0) ? 0xffffffff : 0 - uint32 mask = top; + uint32_t mask = top; mask |= mask >> 2; mask |= mask >> 1; mask <<= 31; - mask = static_cast<uint32>(static_cast<int32>(mask) >> 31); + mask = static_cast<uint32_t>(static_cast<int32_t>(mask) >> 31); // Eliminate top while maintaining the same value mod p. a[0] -= top; @@ -332,7 +331,7 @@ void Contract(FieldElement* inout) { out[i+1] += out[i] >> 28; out[i] &= kBottom28Bits; } - uint32 top = out[7] >> 28; + uint32_t top = out[7] >> 28; out[7] &= kBottom28Bits; // Eliminate top while maintaining the same value mod p. @@ -343,7 +342,7 @@ void Contract(FieldElement* inout) { // out[0] negative then we know that out[3] is sufficiently positive // because we just added to it. for (int i = 0; i < 3; i++) { - uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31); + uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31); out[i] += (1 << 28) & mask; out[i+1] -= 1 & mask; } @@ -376,7 +375,7 @@ void Contract(FieldElement* inout) { // As before, if we made out[0] negative then we know that out[3] is // sufficiently positive. for (int i = 0; i < 3; i++) { - uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31); + uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31); out[i] += (1 << 28) & mask; out[i+1] -= 1 & mask; } @@ -388,7 +387,7 @@ void Contract(FieldElement* inout) { // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones // ends up with any zero bits in the bottom 28 bits, then this wasn't // true. - uint32 top_4_all_ones = 0xffffffffu; + uint32_t top_4_all_ones = 0xffffffffu; for (int i = 4; i < 8; i++) { top_4_all_ones &= out[i]; } @@ -400,37 +399,39 @@ void Contract(FieldElement* inout) { top_4_all_ones &= top_4_all_ones >> 2; top_4_all_ones &= top_4_all_ones >> 1; top_4_all_ones = - static_cast<uint32>(static_cast<int32>(top_4_all_ones << 31) >> 31); + static_cast<uint32_t>(static_cast<int32_t>(top_4_all_ones << 31) >> 31); // Now we test whether the bottom three limbs are non-zero. - uint32 bottom_3_non_zero = out[0] | out[1] | out[2]; + uint32_t bottom_3_non_zero = out[0] | out[1] | out[2]; bottom_3_non_zero |= bottom_3_non_zero >> 16; bottom_3_non_zero |= bottom_3_non_zero >> 8; bottom_3_non_zero |= bottom_3_non_zero >> 4; bottom_3_non_zero |= bottom_3_non_zero >> 2; bottom_3_non_zero |= bottom_3_non_zero >> 1; bottom_3_non_zero = - static_cast<uint32>(static_cast<int32>(bottom_3_non_zero) >> 31); + static_cast<uint32_t>(static_cast<int32_t>(bottom_3_non_zero) >> 31); // Everything depends on the value of out[3]. // If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p // If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0, // then the whole value is >= p // If it's < 0xffff000, then the whole value is < p - uint32 n = out[3] - 0xffff000; - uint32 out_3_equal = n; + uint32_t n = out[3] - 0xffff000; + uint32_t out_3_equal = n; out_3_equal |= out_3_equal >> 16; out_3_equal |= out_3_equal >> 8; out_3_equal |= out_3_equal >> 4; out_3_equal |= out_3_equal >> 2; out_3_equal |= out_3_equal >> 1; out_3_equal = - ~static_cast<uint32>(static_cast<int32>(out_3_equal << 31) >> 31); + ~static_cast<uint32_t>(static_cast<int32_t>(out_3_equal << 31) >> 31); // If out[3] > 0xffff000 then n's MSB will be zero. - uint32 out_3_gt = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31); + uint32_t out_3_gt = + ~static_cast<uint32_t>(static_cast<int32_t>(n << 31) >> 31); - uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt); + uint32_t mask = + top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt); out[0] -= 1 & mask; out[3] -= 0xffff000 & mask; out[4] -= 0xfffffff & mask; @@ -445,13 +446,15 @@ void Contract(FieldElement* inout) { // These functions deal with group elements. The group is an elliptic curve // group with a = -3 defined in FIPS 186-3, section D.2.2. +using crypto::p224::Point; + // kB is parameter of the elliptic curve. const FieldElement kB = { 55967668, 11768882, 265861671, 185302395, 39211076, 180311059, 84673715, 188764328, }; -void CopyConditional(Point* out, const Point& a, uint32 mask); +void CopyConditional(Point* out, const Point& a, uint32_t mask); void DoubleJacobian(Point* out, const Point& a); // AddJacobian computes *out = a+b where a != b. @@ -461,8 +464,8 @@ void AddJacobian(Point *out, // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v; - uint32 z1_is_zero = IsZero(a.z); - uint32 z2_is_zero = IsZero(b.z); + uint32_t z1_is_zero = IsZero(a.z); + uint32_t z2_is_zero = IsZero(b.z); // Z1Z1 = Z1² Square(&z1z1, a.z); @@ -487,7 +490,7 @@ void AddJacobian(Point *out, // H = U2-U1 Subtract(&h, u2, u1); Reduce(&h); - uint32 x_equal = IsZero(h); + uint32_t x_equal = IsZero(h); // I = (2*H)² for (int k = 0; k < 8; k++) { @@ -501,7 +504,7 @@ void AddJacobian(Point *out, // r = 2*(S2-S1) Subtract(&r, s2, s1); Reduce(&r); - uint32 y_equal = IsZero(r); + uint32_t y_equal = IsZero(r); if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { // The two input points are the same therefore we must use the dedicated @@ -608,9 +611,7 @@ void DoubleJacobian(Point* out, const Point& a) { // CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of // 0xffffffff. -void CopyConditional(Point* out, - const Point& a, - uint32 mask) { +void CopyConditional(Point* out, const Point& a, uint32_t mask) { for (int i = 0; i < 8; i++) { out->x[i] ^= mask & (a.x[i] ^ out->x[i]); out->y[i] ^= mask & (a.y[i] ^ out->y[i]); @@ -620,15 +621,17 @@ void CopyConditional(Point* out, // ScalarMult calculates *out = a*scalar where scalar is a big-endian number of // length scalar_len and != 0. -void ScalarMult(Point* out, const Point& a, - const uint8* scalar, size_t scalar_len) { +void ScalarMult(Point* out, + const Point& a, + const uint8_t* scalar, + size_t scalar_len) { memset(out, 0, sizeof(*out)); Point tmp; for (size_t i = 0; i < scalar_len; i++) { for (unsigned int bit_num = 0; bit_num < 8; bit_num++) { DoubleJacobian(out, *out); - uint32 bit = static_cast<uint32>(static_cast<int32>( + uint32_t bit = static_cast<uint32_t>(static_cast<int32_t>( (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31)); AddJacobian(&tmp, a, *out); CopyConditional(out, tmp, bit); @@ -638,7 +641,7 @@ void ScalarMult(Point* out, const Point& a, // Get224Bits reads 7 words from in and scatters their contents in // little-endian form into 8 words at out, 28 bits per output word. -void Get224Bits(uint32* out, const uint32* in) { +void Get224Bits(uint32_t* out, const uint32_t* in) { out[0] = NetToHost32(in[6]) & kBottom28Bits; out[1] = ((NetToHost32(in[5]) << 4) | (NetToHost32(in[6]) >> 28)) & kBottom28Bits; @@ -658,7 +661,7 @@ void Get224Bits(uint32* out, const uint32* in) { // Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from // each of 8 input words and writing them in big-endian order to 7 words at // out. -void Put224Bits(uint32* out, const uint32* in) { +void Put224Bits(uint32_t* out, const uint32_t* in) { out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28)); out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24)); out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20)); @@ -670,10 +673,14 @@ void Put224Bits(uint32* out, const uint32* in) { } // anonymous namespace -bool Point::SetFromString(const std::string& in) { +namespace crypto { + +namespace p224 { + +bool Point::SetFromString(const base::StringPiece& in) { if (in.size() != 2*28) return false; - const uint32* inwords = reinterpret_cast<const uint32*>(in.data()); + const uint32_t* inwords = reinterpret_cast<const uint32_t*>(in.data()); Get224Bits(x, inwords); Get224Bits(y, inwords + 7); memset(&z, 0, sizeof(z)); @@ -696,7 +703,7 @@ bool Point::SetFromString(const std::string& in) { Subtract(&rhs, rhs, three_x); Reduce(&rhs); - Add(&rhs, rhs, kB); + ::Add(&rhs, rhs, kB); Contract(&rhs); return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; } @@ -719,27 +726,27 @@ std::string Point::ToString() const { Contract(&xx); Contract(&yy); - uint32 outwords[14]; + uint32_t outwords[14]; Put224Bits(outwords, xx); Put224Bits(outwords + 7, yy); return std::string(reinterpret_cast<const char*>(outwords), sizeof(outwords)); } -void ScalarMult(const Point& in, const uint8* scalar, Point* out) { - ScalarMult(out, in, scalar, 28); +void ScalarMult(const Point& in, const uint8_t* scalar, Point* out) { + ::ScalarMult(out, in, scalar, 28); } // kBasePoint is the base point (generator) of the elliptic curve group. static const Point kBasePoint = { {22813985, 52956513, 34677300, 203240812, - 12143107, 133374265, 225162431, 191946955}, + 12143107, 133374265, 225162431, 191946955}, {83918388, 223877528, 122119236, 123340192, - 266784067, 263504429, 146143011, 198407736}, + 266784067, 263504429, 146143011, 198407736}, {1, 0, 0, 0, 0, 0, 0, 0}, }; -void ScalarBaseMult(const uint8* scalar, Point* out) { - ScalarMult(out, kBasePoint, scalar, 28); +void ScalarBaseMult(const uint8_t* scalar, Point* out) { + ::ScalarMult(out, kBasePoint, scalar, 28); } void Add(const Point& a, const Point& b, Point* out) { @@ -765,4 +772,5 @@ void Negate(const Point& in, Point* out) { } } // namespace p224 + } // namespace crypto diff --git a/third_party/chromium/crypto/p224.h b/third_party/chromium/crypto/p224.h index 7574389..e9976e6 100644 --- a/third_party/chromium/crypto/p224.h +++ b/third_party/chromium/crypto/p224.h @@ -5,9 +5,12 @@ #ifndef LIBWEAVE_THIRD_PARTY_CHROMIUM_P224_H_ #define LIBWEAVE_THIRD_PARTY_CHROMIUM_P224_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> -#include <base/basictypes.h> +#include "base/strings/string_piece.h" namespace crypto { @@ -17,14 +20,14 @@ namespace p224 { // An element of the field (ℤ/pℤ) is represented with 8, 28-bit limbs in // little endian order. -typedef uint32 FieldElement[8]; +typedef uint32_t FieldElement[8]; struct Point { // SetFromString the value of the point from the 56 byte, external // representation. The external point representation is an (x, y) pair of a // point on the curve. Each field element is represented as a big-endian // number < p. - bool SetFromString(const std::string& in); + bool SetFromString(const base::StringPiece& in); // ToString returns an external representation of the Point. std::string ToString() const; @@ -39,11 +42,11 @@ static const size_t kScalarBytes = 28; // ScalarMult computes *out = in*scalar where scalar is a 28-byte, big-endian // number. -void ScalarMult(const Point& in, const uint8* scalar, Point* out); +void ScalarMult(const Point& in, const uint8_t* scalar, Point* out); // ScalarBaseMult computes *out = g*scalar where g is the base point of the // curve and scalar is a 28-byte, big-endian number. -void ScalarBaseMult(const uint8* scalar, Point* out); +void ScalarBaseMult(const uint8_t* scalar, Point* out); // Add computes *out = a+b. void Add(const Point& a, const Point& b, Point* out); @@ -52,6 +55,7 @@ void Add(const Point& a, const Point& b, Point* out); void Negate(const Point& a, Point* out); } // namespace p224 + } // namespace crypto #endif // LIBWEAVE_THIRD_PARTY_CHROMIUM_P224_H_ diff --git a/third_party/chromium/crypto/p224_spake.cc b/third_party/chromium/crypto/p224_spake.cc index 6d82322..d55d2a7 100644 --- a/third_party/chromium/crypto/p224_spake.cc +++ b/third_party/chromium/crypto/p224_spake.cc @@ -14,8 +14,6 @@ #include "third_party/chromium/crypto/p224.h" -namespace crypto { - namespace { // The following two points (M and N in the protocol) are verifiable random @@ -79,19 +77,19 @@ namespace { // return 0; // } -const p224::Point kM = { +const crypto::p224::Point kM = { {174237515, 77186811, 235213682, 33849492, - 33188520, 48266885, 177021753, 81038478}, + 33188520, 48266885, 177021753, 81038478}, {104523827, 245682244, 266509668, 236196369, - 28372046, 145351378, 198520366, 113345994}, + 28372046, 145351378, 198520366, 113345994}, {1, 0, 0, 0, 0, 0, 0, 0}, }; -const p224::Point kN = { +const crypto::p224::Point kN = { {136176322, 263523628, 251628795, 229292285, - 5034302, 185981975, 171998428, 11653062}, + 5034302, 185981975, 171998428, 11653062}, {197567436, 51226044, 60372156, 175772188, - 42075930, 8083165, 160827401, 65097570}, + 42075930, 8083165, 160827401, 65097570}, {1, 0, 0, 0, 0, 0, 0, 0}, }; @@ -114,9 +112,12 @@ bool SecureMemEqual(const uint8_t* s1_ptr, const uint8_t* s2_ptr, size_t n) { } // anonymous namespace -P224EncryptedKeyExchange::P224EncryptedKeyExchange(PeerType peer_type, - const std::string& password) - : state_(kStateInitial), is_server_(peer_type == kPeerTypeServer) { +namespace crypto { + +P224EncryptedKeyExchange::P224EncryptedKeyExchange( + PeerType peer_type, const base::StringPiece& password) + : state_(kStateInitial), + is_server_(peer_type == kPeerTypeServer) { memset(&x_, 0, sizeof(x_)); memset(&expected_authenticator_, 0, sizeof(expected_authenticator_)); @@ -163,7 +164,7 @@ const std::string& P224EncryptedKeyExchange::GetNextMessage() { } P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage( - const std::string& message) { + const base::StringPiece& message) { if (state_ == kStateRecvHash) { // This is the final state of the protocol: we are reading the peer's // authentication hash and checking that it matches the one that we expect. @@ -210,23 +211,23 @@ P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage( std::string client_masked_dh, server_masked_dh; if (is_server_) { - client_masked_dh = message; + client_masked_dh = message.as_string(); server_masked_dh = next_message_; } else { client_masked_dh = next_message_; - server_masked_dh = message; + server_masked_dh = message.as_string(); } // Now we calculate the hashes that each side will use to prove to the other // that they derived the correct value for K. - uint8 client_hash[kSHA256Length], server_hash[kSHA256Length]; + uint8_t client_hash[kSHA256Length], server_hash[kSHA256Length]; CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_, client_hash); CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_, server_hash); - const uint8* my_hash = is_server_ ? server_hash : client_hash; - const uint8* their_hash = is_server_ ? client_hash : server_hash; + const uint8_t* my_hash = is_server_ ? server_hash : client_hash; + const uint8_t* their_hash = is_server_ ? client_hash : server_hash; next_message_ = std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length); @@ -240,7 +241,7 @@ void P224EncryptedKeyExchange::CalculateHash( const std::string& client_masked_dh, const std::string& server_masked_dh, const std::string& k, - uint8* out_digest) { + uint8_t* out_digest) { std::string hash_contents; if (peer_type == kPeerTypeServer) { diff --git a/third_party/chromium/crypto/p224_spake.h b/third_party/chromium/crypto/p224_spake.h index dcfd0fe..122ea46 100644 --- a/third_party/chromium/crypto/p224_spake.h +++ b/third_party/chromium/crypto/p224_spake.h @@ -3,10 +3,12 @@ // found in the LICENSE file. #ifndef LIBWEAVE_THIRD_PARTY_CHROMIUM_P224_SPAKE_H_ +#define LIBWEAVE_THIRD_PARTY_CHROMIUM_P224_SPAKE_H_ -#include <string> +#include <stdint.h> #include <base/gtest_prod_util.h> +#include <base/strings/string_piece.h> #include "third_party/chromium/crypto/p224.h" #include "third_party/chromium/crypto/sha2.h" @@ -53,7 +55,8 @@ class P224EncryptedKeyExchange { // password: secret session password. Both parties to the // authentication must pass the same value. For the case of a // TLS connection, see RFC 5705. - P224EncryptedKeyExchange(PeerType peer_type, const std::string& password); + P224EncryptedKeyExchange(PeerType peer_type, + const base::StringPiece& password); // GetNextMessage returns a byte string which must be passed to the other // party in the authentication. @@ -61,7 +64,7 @@ class P224EncryptedKeyExchange { // ProcessMessage processes a message which must have been generated by a // call to GetNextMessage() by the other party. - Result ProcessMessage(const std::string& message); + Result ProcessMessage(const base::StringPiece& message); // In the event that ProcessMessage() returns kResultFailed, error will // return a human readable error message. @@ -101,22 +104,21 @@ class P224EncryptedKeyExchange { // CalculateHash computes the verification hash for the given peer and writes // |kSHA256Length| bytes at |out_digest|. - void CalculateHash( - PeerType peer_type, - const std::string& client_masked_dh, - const std::string& server_masked_dh, - const std::string& k, - uint8* out_digest); + void CalculateHash(PeerType peer_type, + const std::string& client_masked_dh, + const std::string& server_masked_dh, + const std::string& k, + uint8_t* out_digest); // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc // file). - uint8 x_[p224::kScalarBytes]; - // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32, + uint8_t x_[p224::kScalarBytes]; + // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32_t, // big-endian length prefix (see paper referenced in .cc file). - uint8 pw_[p224::kScalarBytes]; + uint8_t pw_[p224::kScalarBytes]; // expected_authenticator_ is used to store the hash value expected from the // other party. - uint8 expected_authenticator_[kSHA256Length]; + uint8_t expected_authenticator_[kSHA256Length]; std::string key_; }; diff --git a/third_party/chromium/crypto/p224_spake_unittest.cc b/third_party/chromium/crypto/p224_spake_unittest.cc index 9a9f9d2..373bb28 100644 --- a/third_party/chromium/crypto/p224_spake_unittest.cc +++ b/third_party/chromium/crypto/p224_spake_unittest.cc @@ -4,6 +4,9 @@ #include "third_party/chromium/crypto/p224_spake.h" +#include <stddef.h> +#include <stdint.h> + #include <string> #include <base/logging.h> @@ -125,7 +128,7 @@ TEST(MutualAuth, Fuzz) { // We'll only be testing small values of i, but we don't want that to bias // the test coverage. So we disperse the value of i by multiplying by the // FNV, 32-bit prime, producing a poor-man's PRNG. - const uint32 rand = i * 16777619; + const uint32_t rand = i * 16777619; for (unsigned round = 0;; round++) { std::string client_message, server_message; diff --git a/third_party/chromium/crypto/p224_unittest.cc b/third_party/chromium/crypto/p224_unittest.cc index 0540dbb..331fc3c 100644 --- a/third_party/chromium/crypto/p224_unittest.cc +++ b/third_party/chromium/crypto/p224_unittest.cc @@ -4,9 +4,12 @@ #include "third_party/chromium/crypto/p224.h" +#include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <string.h> +#include "base/macros.h" #include <gtest/gtest.h> namespace crypto { @@ -14,22 +17,20 @@ namespace crypto { using p224::Point; // kBasePointExternal is the P224 base point in external representation. -static const uint8 kBasePointExternal[56] = { - 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, - 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, - 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, - 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, - 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, - 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, - 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, +static const uint8_t kBasePointExternal[56] = { + 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, + 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, + 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, }; // TestVector represents a test of scalar multiplication of the base point. // |scalar| is a big-endian scalar and |affine| is the external representation // of g*scalar. struct TestVector { - uint8 scalar[28]; - uint8 affine[28*2]; + uint8_t scalar[28]; + uint8_t affine[28 * 2]; }; static const int kNumNISTTestVectors = 52; @@ -770,15 +771,15 @@ static const TestVector kNISTTestVectors[kNumNISTTestVectors] = { TEST(P224, ExternalToInternalAndBack) { Point point; - EXPECT_TRUE(point.SetFromString( - std::string(reinterpret_cast<const char*>(kBasePointExternal), - sizeof(kBasePointExternal)))); + EXPECT_TRUE(point.SetFromString(base::StringPiece( + reinterpret_cast<const char *>(kBasePointExternal), + sizeof(kBasePointExternal)))); const std::string external = point.ToString(); ASSERT_EQ(external.size(), 56u); - EXPECT_EQ(0, memcmp(external.data(), kBasePointExternal, - sizeof(kBasePointExternal))); + EXPECT_TRUE(memcmp(external.data(), kBasePointExternal, + sizeof(kBasePointExternal)) == 0); } TEST(P224, ScalarBaseMult) { @@ -788,22 +789,22 @@ TEST(P224, ScalarBaseMult) { p224::ScalarBaseMult(kNISTTestVectors[i].scalar, &point); const std::string external = point.ToString(); ASSERT_EQ(external.size(), 56u); - EXPECT_EQ(0, memcmp(external.data(), kNISTTestVectors[i].affine, - external.size())); + EXPECT_TRUE(memcmp(external.data(), kNISTTestVectors[i].affine, + external.size()) == 0); } } TEST(P224, Addition) { Point a, b, minus_b, sum, a_again; - ASSERT_TRUE(a.SetFromString(std::string( - reinterpret_cast<const char*>(kNISTTestVectors[10].affine), 56))); - ASSERT_TRUE(b.SetFromString(std::string( - reinterpret_cast<const char*>(kNISTTestVectors[11].affine), 56))); + ASSERT_TRUE(a.SetFromString(base::StringPiece( + reinterpret_cast<const char *>(kNISTTestVectors[10].affine), 56))); + ASSERT_TRUE(b.SetFromString(base::StringPiece( + reinterpret_cast<const char *>(kNISTTestVectors[11].affine), 56))); p224::Negate(b, &minus_b); p224::Add(a, b, &sum); - EXPECT_NE(0, memcmp(&sum, &a, sizeof(sum))); + EXPECT_TRUE(memcmp(&sum, &a, sizeof(sum)) != 0); p224::Add(minus_b, sum, &a_again); EXPECT_TRUE(a_again.ToString() == a.ToString()); } @@ -814,8 +815,8 @@ TEST(P224, Infinity) { // Test that x^0 = ∞. Point a; - p224::ScalarBaseMult(reinterpret_cast<const uint8*>(zeros), &a); - EXPECT_EQ(0, memcmp(zeros, a.ToString().data(), sizeof(zeros))); + p224::ScalarBaseMult(reinterpret_cast<const uint8_t*>(zeros), &a); + EXPECT_TRUE(memcmp(zeros, a.ToString().data(), sizeof(zeros)) == 0); // We shouldn't allow ∞ to be imported. EXPECT_FALSE(a.SetFromString(std::string(zeros, sizeof(zeros)))); diff --git a/third_party/chromium/crypto/sha2_unittest.cc b/third_party/chromium/crypto/sha2_unittest.cc index 0c30f45..42dffb5 100644 --- a/third_party/chromium/crypto/sha2_unittest.cc +++ b/third_party/chromium/crypto/sha2_unittest.cc @@ -4,7 +4,6 @@ #include "third_party/chromium/crypto/sha2.h" -#include <base/basictypes.h> #include <gtest/gtest.h> namespace weave { @@ -21,12 +20,12 @@ TEST(Sha256Test, Test1) { 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }; - uint8 output1[crypto::kSHA256Length]; + uint8_t output1[crypto::kSHA256Length]; crypto::SHA256HashString(input1, output1, sizeof(output1)); for (size_t i = 0; i < crypto::kSHA256Length; i++) EXPECT_EQ(expected1[i], static_cast<int>(output1[i])); - uint8 output_truncated1[4]; // 4 bytes == 32 bits + uint8_t output_truncated1[4]; // 4 bytes == 32 bits crypto::SHA256HashString(input1, output_truncated1, sizeof(output_truncated1)); for (size_t i = 0; i < sizeof(output_truncated1); i++) @@ -49,7 +48,7 @@ TEST(Sha256Test, Test1_String) { std::string output1 = crypto::SHA256HashString(input1); ASSERT_EQ(crypto::kSHA256Length, output1.size()); for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected1[i], static_cast<uint8>(output1[i])); + EXPECT_EQ(expected1[i], static_cast<uint8_t>(output1[i])); } TEST(Sha256Test, Test2) { @@ -65,12 +64,12 @@ TEST(Sha256Test, Test2) { 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }; - uint8 output2[crypto::kSHA256Length]; + uint8_t output2[crypto::kSHA256Length]; crypto::SHA256HashString(input2, output2, sizeof(output2)); for (size_t i = 0; i < crypto::kSHA256Length; i++) EXPECT_EQ(expected2[i], static_cast<int>(output2[i])); - uint8 output_truncated2[6]; + uint8_t output_truncated2[6]; crypto::SHA256HashString(input2, output_truncated2, sizeof(output_truncated2)); for (size_t i = 0; i < sizeof(output_truncated2); i++) @@ -89,12 +88,12 @@ TEST(Sha256Test, Test3) { 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 }; - uint8 output3[crypto::kSHA256Length]; + uint8_t output3[crypto::kSHA256Length]; crypto::SHA256HashString(input3, output3, sizeof(output3)); for (size_t i = 0; i < crypto::kSHA256Length; i++) EXPECT_EQ(expected3[i], static_cast<int>(output3[i])); - uint8 output_truncated3[12]; + uint8_t output_truncated3[12]; crypto::SHA256HashString(input3, output_truncated3, sizeof(output_truncated3)); for (size_t i = 0; i < sizeof(output_truncated3); i++) |