libchromeos: Move Any from Buffet to libchromeos.
Move the Any class from Buffet to libchromeos and
changed its namespace from buffet:: to chromeos::
Updated the rest of Buffet code to with the changes
to the class's namespace and header file location.
Also, now that move constructors are officially allowed by
Google C++ coding style for project with C++11 feature
support, added back the move constructor to Any as
per http://crbug.com/387902
BUG=chromium:405714,chromium:387902
TEST=USE=buffet ./build_packages
Change-Id: Id007f51b874934e4f6428fe90674495edeb79107
Reviewed-on: https://chromium-review.googlesource.com/213831
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/any.cc b/buffet/any.cc
deleted file mode 100644
index 9ce0ce2..0000000
--- a/buffet/any.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium OS 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 "buffet/any.h"
-
-#include <algorithm>
-
-namespace buffet {
-
-Any::Any(const Any& rhs) : data_buffer_(rhs.data_buffer_) {
-}
-
-Any::~Any() {
-}
-
-Any& Any::operator=(const Any& rhs) {
- data_buffer_ = rhs.data_buffer_;
- return *this;
-}
-
-const std::type_info& Any::GetType() const {
- if (!IsEmpty())
- return data_buffer_.GetDataPtr()->GetType();
-
- struct NullType {}; // Special helper type representing an empty variant.
- return typeid(NullType);
-}
-
-void Any::Swap(Any& other) {
- std::swap(data_buffer_, other.data_buffer_);
-}
-
-bool Any::IsEmpty() const {
- return data_buffer_.IsEmpty();
-}
-
-void Any::Clear() {
- data_buffer_.Clear();
-}
-
-bool Any::IsConvertibleToInteger() const {
- return !IsEmpty() && data_buffer_.GetDataPtr()->IsConvertibleToInteger();
-}
-
-intmax_t Any::GetAsInteger() const {
- CHECK(!IsEmpty()) << "Must not be called on an empty Any";
- return data_buffer_.GetDataPtr()->GetAsInteger();
-}
-
-} // namespace buffet
diff --git a/buffet/any.h b/buffet/any.h
deleted file mode 100644
index 5ab249c..0000000
--- a/buffet/any.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2014 The Chromium OS 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 is an implementation of a "true" variant class in C++.
-// The buffet::Any class can hold any C++ type, but both the setter and
-// getter sites need to know the actual type of data.
-// Note that C-style arrays when stored in Any are reduced to simple
-// data pointers. Any will not copy a contents of the array.
-// const int data[] = [1,2,3];
-// Any v(data); // stores const int*, effectively "Any v(&data[0]);"
-
-// buffet::Any is a value type. Which means, the data is copied into it
-// and Any owns it. The owned object (stored by value) will be destroyed
-// when Any is cleared or reassigned. The contained value type must be
-// copy-constructible. You can also store pointers and references to objects.
-// Storing pointers is trivial. In order to store a reference, you can
-// use helper functions std::ref() and std::cref() to create non-const and
-// const references respectively. In such a case, the type of contained data
-// will be std::reference_wrapper<T>. See 'References' unit tests in
-// any_unittest.cc for examples.
-
-#ifndef BUFFET_ANY_H_
-#define BUFFET_ANY_H_
-
-#include "buffet/any_internal_impl.h"
-
-#include <algorithm>
-
-namespace buffet {
-
-class Any final {
- public:
- Any() = default;
- // Standard copy constructor. This is a value-class container
- // that must be copy-constructible and movable. The copy constructors
- // should not be marked as explicit.
- Any(const Any& rhs);
- // Typed constructor that stores a value of type T in the Any.
- template<class T>
- Any(T value) { // NOLINT(runtime/explicit)
- data_buffer_.Assign(std::move(value));
- }
-
- // Not declaring the destructor as virtual since this is a sealed class
- // and there is no need to introduce a virtual table to it.
- ~Any();
-
- // Assignment operators.
- Any& operator=(const Any& rhs);
- template<class T>
- Any& operator=(T value) {
- data_buffer_.Assign(std::move(value));
- return *this;
- }
-
- // Checks if the given type DestType can be obtained from the Any.
- // For example, to check if Any has a 'double' value in it:
- // any.IsTypeCompatible<double>()
- template<typename DestType>
- bool IsTypeCompatible() const {
- // Make sure the requested type DestType conforms to the storage
- // requirements of Any. We always store the data by value, which means we
- // strip away any references as well as cv-qualifiers. So, if the user
- // stores "const int&", we actually store just an "int".
- // When calling IsTypeCompatible, we need to do a similar "type cleansing"
- // to make sure the requested type matches the type of data actually stored,
- // so this "canonical" type is used for type checking below.
- using CanonicalDestType = typename std::decay<DestType>::type;
- const std::type_info& ContainedTypeId = GetType();
- if (typeid(CanonicalDestType) == ContainedTypeId)
- return true;
-
- if (!std::is_pointer<CanonicalDestType>::value)
- return false;
-
- // If asking for a const pointer from a variant containing non-const
- // pointer, still satisfy the request. So, we need to remove the pointer
- // specification first, then strip the const/volatile qualifiers, then
- // re-add the pointer back, so "const int*" would become "int*".
- using NonPointer = typename std::remove_pointer<CanonicalDestType>::type;
- using CanonicalDestTypeNoConst = typename std::add_pointer<
- typename std::remove_const<NonPointer>::type>::type;
- using CanonicalDestTypeNoVolatile = typename std::add_pointer<
- typename std::remove_volatile<NonPointer>::type>::type;
- using CanonicalDestTypeNoConstOrVolatile = typename std::add_pointer<
- typename std::remove_cv<NonPointer>::type>::type;
-
- return typeid(CanonicalDestTypeNoConst) == ContainedTypeId ||
- typeid(CanonicalDestTypeNoVolatile) == ContainedTypeId ||
- typeid(CanonicalDestTypeNoConstOrVolatile) == ContainedTypeId;
- }
-
- // Returns immutable data contained in Any.
- // Aborts if Any doesn't contain a value of type T, or trivially
- // convertible to/compatible with it.
- template<typename T>
- const T& Get() const {
- CHECK(IsTypeCompatible<T>()) << "Requesting value of type "
- << typeid(T).name()
- << " from variant containing "
- << GetType().name();
- return data_buffer_.GetData<T>();
- }
-
- // Returns a pointer to mutable value of type T contained within Any.
- // No data copying is made, the data pointed to is still owned by Any.
- // If Any doesn't contain a value of type T, or trivially
- // convertible/compatible to/with it, then it returns nullptr.
- template<typename T>
- T* GetPtr() {
- if (!IsTypeCompatible<T>())
- return nullptr;
- return &(data_buffer_.GetData<T>());
- }
-
- // Returns immutable data contained in Any.
- // If the Any doesn't contain a compatible value, the provided default
- // |def_val| is returned instead.
- template<typename T>
- const T& TryGet(typename std::decay<T>::type const& def_val) const {
- if (!IsTypeCompatible<T>())
- return def_val;
- return data_buffer_.GetData<T>();
- }
-
- // A convenience specialization of the above function where the default
- // value of type T is returned in case the underlying Get() fails.
- template<typename T>
- const T& TryGet() const {
- return TryGet<T>(typename std::decay<T>::type());
- }
-
-
- // Returns the type information about the contained data. For most cases,
- // instead of using this function, you should be calling IsTypeCompatible<>().
- const std::type_info& GetType() const;
- // Swaps the value of this object with that of |other|.
- void Swap(Any& other);
- // Checks if Any is empty, that is, not containing a value of any type.
- bool IsEmpty() const;
- // Clears the Any and destroys any contained object. Makes it empty.
- void Clear();
- // Checks if Any contains a type convertible to integer.
- // Any type that match std::is_integral<T> and std::is_enum<T> is accepted.
- // That includes signed and unsigned char, short, int, long, etc as well as
- // 'bool' and enumerated types.
- // For 'integer' type, you can call GetAsInteger to do implicit type
- // conversion to intmax_t.
- bool IsConvertibleToInteger() const;
- // For integral types and enums contained in the Any, get the integer value
- // of data. This is a useful function to obtain an integer value when
- // any can possibly have unspecified integer, such as 'short', 'unsigned long'
- // and so on.
- intmax_t GetAsInteger() const;
-
- private:
- // The data buffer for contained object.
- internal_details::Buffer data_buffer_;
-};
-
-} // namespace buffet
-
-namespace std {
-
-// Specialize std::swap() algorithm for buffet::Any class.
-inline void swap(buffet::Any& lhs, buffet::Any& rhs) {
- lhs.Swap(rhs);
-}
-
-} // namespace std
-
-#endif // BUFFET_ANY_H_
-
diff --git a/buffet/any_internal_impl.h b/buffet/any_internal_impl.h
deleted file mode 100644
index d875e3b..0000000
--- a/buffet/any_internal_impl.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Internal implementation of buffet::Any class.
-
-#ifndef BUFFET_ANY_INTERNAL_IMPL_H_
-#define BUFFET_ANY_INTERNAL_IMPL_H_
-
-#include <type_traits>
-#include <typeinfo>
-#include <utility>
-
-#include <base/logging.h>
-
-namespace buffet {
-
-namespace internal_details {
-
-// An extension to std::is_convertible to allow conversion from an enum to
-// an integral type which std::is_convertible does not indicate as supported.
-template <typename From, typename To>
-struct IsConvertible : public std::integral_constant<bool,
- std::is_convertible<From, To>::value ||
- (std::is_enum<From>::value && std::is_integral<To>::value)> {
-};
-// TryConvert is a helper function that does a safe compile-time conditional
-// type cast between data types that may not be always convertible.
-// From and To are the source and destination types.
-// The function returns true if conversion was possible/successful.
-template <typename From, typename To>
-inline typename std::enable_if<IsConvertible<From, To>::value, bool>::type
-TryConvert(const From& in, To* out) {
- *out = static_cast<To>(in);
- return true;
-}
-template <typename From, typename To>
-inline typename std::enable_if<!IsConvertible<From, To>::value, bool>::type
-TryConvert(const From& in, To* out) {
- return false;
-}
-
-class Buffer; // Forward declaration of data buffer container.
-
-// Abstract base class for contained variant data.
-struct Data {
- virtual ~Data() {}
- // Returns the type information for the contained data.
- virtual const std::type_info& GetType() const = 0;
- // Copies the contained data to the output |buffer|.
- virtual void CopyTo(Buffer* buffer) const = 0;
- // Checks if the contained data is an integer type (not necessarily an 'int').
- virtual bool IsConvertibleToInteger() const = 0;
- // Gets the contained integral value as an integer.
- virtual intmax_t GetAsInteger() const = 0;
-};
-
-// Concrete implementation of variant data of type T.
-template<typename T>
-struct TypedData : public Data {
- explicit TypedData(const T& value) : value_(value) {}
-
- const std::type_info& GetType() const override { return typeid(T); }
- void CopyTo(Buffer* buffer) const override;
- bool IsConvertibleToInteger() const override {
- return std::is_integral<T>::value || std::is_enum<T>::value;
- }
- intmax_t GetAsInteger() const override {
- intmax_t int_val = 0;
- bool converted = TryConvert(value_, &int_val);
- CHECK(converted) << "Unable to convert value of type " << typeid(T).name()
- << " to integer";
- return int_val;
- }
- // Special method to copy data of the same type
- // without reallocating the buffer.
- void FastAssign(const T& source) { value_ = source; }
-
- T value_;
-};
-
-// Buffer class that stores the contained variant data.
-// To improve performance and reduce memory fragmentation, small variants
-// are stored in pre-allocated memory buffers that are part of the Any class.
-// If the memory requirements are larger than the set limit or the type is
-// non-trivially copyable, then the contained class is allocated in a separate
-// memory block and the pointer to that memory is contained within this memory
-// buffer class.
-class Buffer {
- public:
- enum StorageType { kExternal, kContained };
- Buffer() : external_ptr_(nullptr), storage_(kExternal) {}
- ~Buffer() {
- Clear();
- }
-
- Buffer(const Buffer& rhs) : Buffer() {
- rhs.CopyTo(this);
- }
- Buffer& operator=(const Buffer& rhs) {
- rhs.CopyTo(this);
- return *this;
- }
-
- // Returns the underlying pointer to contained data. Uses either the pointer
- // or the raw data depending on |storage_| type.
- inline Data* GetDataPtr() {
- return (storage_ == kExternal) ?
- external_ptr_ : reinterpret_cast<Data*>(contained_buffer_);
- }
- inline const Data* GetDataPtr() const {
- return (storage_ == kExternal) ?
- external_ptr_ : reinterpret_cast<const Data*>(contained_buffer_);
- }
-
- // Destroys the contained object (and frees memory if needed).
- void Clear() {
- Data* data = GetDataPtr();
- if (storage_ == kExternal) {
- delete data;
- } else {
- // Call the destructor manually, since the object was constructed inline
- // in the pre-allocated buffer. We still need to call the destructor
- // to free any associated resources, but we can't call delete |data| here.
- data->~Data();
- }
- external_ptr_ = nullptr;
- storage_ = kExternal;
- }
-
- // Stores a value of type T.
- template<typename T>
- void Assign(T value) {
- using Type = typename std::decay<T>::type;
- using DataType = TypedData<Type>;
- Data* ptr = GetDataPtr();
- if (ptr && ptr->GetType() == typeid(Type)) {
- // We assign the data to the variant container, which already
- // has the data of the same type. Do fast copy with no memory
- // reallocation.
- DataType* typed_ptr = static_cast<DataType*>(ptr);
- typed_ptr->FastAssign(value);
- } else {
- Clear();
- // TODO(avakulenko): [see crbug.com/379833]
- // Unfortunately, GCC doesn't support std::is_trivially_copyable<T> yet,
- // so using std::is_trivial instead, which is a bit more restrictive.
- // Once GCC has support for is_trivially_copyable, update the following.
- if (!std::is_trivial<Type>::value ||
- sizeof(DataType) > sizeof(contained_buffer_)) {
- // If it is too big or not trivially copyable, allocate it separately.
- external_ptr_ = new DataType(value);
- storage_ = kExternal;
- } else {
- // Otherwise just use the pre-allocated buffer.
- DataType* address = reinterpret_cast<DataType*>(contained_buffer_);
- // Make sure we still call the copy constructor.
- // Call the constructor manually by using placement 'new'.
- new (address) DataType(value);
- storage_ = kContained;
- }
- }
- }
-
- // Helper methods to retrieve a reference to contained data.
- // These assume that type checking has already been performed by Any
- // so the type cast is valid and will succeed.
- template<typename T>
- const T& GetData() const {
- using DataType = internal_details::TypedData<typename std::decay<T>::type>;
- return static_cast<const DataType*>(GetDataPtr())->value_;
- }
- template<typename T>
- T& GetData() {
- using DataType = internal_details::TypedData<typename std::decay<T>::type>;
- return static_cast<DataType*>(GetDataPtr())->value_;
- }
-
- // Returns true if the buffer has no contained data.
- bool IsEmpty() const {
- return (storage_ == kExternal && external_ptr_ == nullptr);
- }
-
- // Copies the data from the current buffer into the |destination|.
- void CopyTo(Buffer* destination) const {
- if (IsEmpty()) {
- destination->Clear();
- } else {
- GetDataPtr()->CopyTo(destination);
- }
- }
-
- union {
- // |external_ptr_| is a pointer to a larger object allocated in
- // a separate memory block.
- Data* external_ptr_;
- // |contained_buffer_| is a pre-allocated buffer for smaller/simple objects.
- // Pre-allocate enough memory to store objects as big as "double".
- unsigned char contained_buffer_[sizeof(TypedData<double>)];
- };
- // Depending on a value of |storage_|, either |external_ptr_| or
- // |contained_buffer_| above is used to get a pointer to memory containing
- // the variant data.
- StorageType storage_; // Declare after the union to eliminate member padding.
-};
-
-template<typename T>
-void TypedData<T>::CopyTo(Buffer* buffer) const { buffer->Assign(value_); }
-
-} // namespace internal_details
-
-} // namespace buffet
-
-#endif // BUFFET_ANY_INTERNAL_IMPL_H_
-
diff --git a/buffet/any_internal_impl_unittest.cc b/buffet/any_internal_impl_unittest.cc
deleted file mode 100644
index 8c2fa58..0000000
--- a/buffet/any_internal_impl_unittest.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2014 The Chromium OS 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 <string>
-
-#include <gtest/gtest.h>
-
-#include "buffet/any.h"
-
-using buffet::internal_details::Buffer;
-
-TEST(Buffer, Empty) {
- Buffer buffer;
- EXPECT_TRUE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kExternal, buffer.storage_);
- EXPECT_EQ(nullptr, buffer.GetDataPtr());
-}
-
-TEST(Buffer, Store_Int) {
- Buffer buffer;
- buffer.Assign(2);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(int), buffer.GetDataPtr()->GetType());
-}
-
-TEST(Buffer, Store_Double) {
- Buffer buffer;
- buffer.Assign(2.3);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(double), buffer.GetDataPtr()->GetType());
-}
-
-TEST(Buffer, Store_Pointers) {
- Buffer buffer;
- // nullptr
- buffer.Assign(nullptr);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(std::nullptr_t), buffer.GetDataPtr()->GetType());
-
- // char *
- buffer.Assign("abcd");
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(const char*), buffer.GetDataPtr()->GetType());
-
- // pointer to non-trivial object
- class NonTrivial {
- public:
- virtual ~NonTrivial() {}
- } non_trivial;
- buffer.Assign(&non_trivial);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(NonTrivial*), buffer.GetDataPtr()->GetType());
-}
-
-TEST(Buffer, Store_NonTrivialObjects) {
- class NonTrivial {
- public:
- virtual ~NonTrivial() {}
- } non_trivial;
- Buffer buffer;
- buffer.Assign(non_trivial);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kExternal, buffer.storage_);
- EXPECT_EQ(typeid(NonTrivial), buffer.GetDataPtr()->GetType());
-}
-
-TEST(Buffer, Store_Objects) {
- Buffer buffer;
-
- struct Small {
- double d;
- } small = {};
- buffer.Assign(small);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_EQ(typeid(Small), buffer.GetDataPtr()->GetType());
-
- struct Large {
- char c[10];
- } large = {};
- buffer.Assign(large);
- EXPECT_FALSE(buffer.IsEmpty());
- EXPECT_EQ(Buffer::kExternal, buffer.storage_);
- EXPECT_EQ(typeid(Large), buffer.GetDataPtr()->GetType());
-}
-
-TEST(Buffer, Copy) {
- Buffer buffer1;
- Buffer buffer2;
-
- buffer1.Assign(30);
- buffer1.CopyTo(&buffer2);
- EXPECT_FALSE(buffer1.IsEmpty());
- EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_EQ(typeid(int), buffer1.GetDataPtr()->GetType());
- EXPECT_EQ(typeid(int), buffer2.GetDataPtr()->GetType());
- EXPECT_EQ(30, buffer1.GetData<int>());
- EXPECT_EQ(30, buffer2.GetData<int>());
-
- buffer1.Assign(std::string("abc"));
- buffer1.CopyTo(&buffer2);
- EXPECT_FALSE(buffer1.IsEmpty());
- EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_EQ(typeid(std::string), buffer1.GetDataPtr()->GetType());
- EXPECT_EQ(typeid(std::string), buffer2.GetDataPtr()->GetType());
- EXPECT_EQ("abc", buffer1.GetData<std::string>());
- EXPECT_EQ("abc", buffer2.GetData<std::string>());
-}
diff --git a/buffet/any_unittest.cc b/buffet/any_unittest.cc
deleted file mode 100644
index eaf3ce1..0000000
--- a/buffet/any_unittest.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2014 The Chromium OS 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 <algorithm>
-#include <functional>
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "buffet/any.h"
-
-using buffet::Any;
-
-TEST(Any, Empty) {
- Any val;
- EXPECT_TRUE(val.IsEmpty());
-
- Any val2 = val;
- EXPECT_TRUE(val.IsEmpty());
- EXPECT_TRUE(val2.IsEmpty());
-}
-
-TEST(Any, SimpleTypes) {
- Any val(20);
- EXPECT_FALSE(val.IsEmpty());
- EXPECT_TRUE(val.IsTypeCompatible<int>());
- EXPECT_EQ(20, val.Get<int>());
-
- Any val2(3.1415926);
- EXPECT_FALSE(val2.IsEmpty());
- EXPECT_TRUE(val2.IsTypeCompatible<double>());
- EXPECT_FALSE(val2.IsTypeCompatible<int>());
- EXPECT_DOUBLE_EQ(3.1415926, val2.Get<double>());
-
- Any val3(std::string("blah"));
- EXPECT_TRUE(val3.IsTypeCompatible<std::string>());
- EXPECT_EQ("blah", val3.Get<std::string>());
-}
-
-TEST(Any, Clear) {
- Any val('x');
- EXPECT_FALSE(val.IsEmpty());
- EXPECT_EQ('x', val.Get<char>());
-
- val.Clear();
- EXPECT_TRUE(val.IsEmpty());
-}
-
-TEST(Any, Assignments) {
- Any val(20);
- EXPECT_EQ(20, val.Get<int>());
-
- val = 3.1415926;
- EXPECT_FALSE(val.IsEmpty());
- EXPECT_TRUE(val.IsTypeCompatible<double>());
- EXPECT_DOUBLE_EQ(3.1415926, val.Get<double>());
-
- val = std::string("blah");
- EXPECT_EQ("blah", val.Get<std::string>());
-
- Any val2;
- EXPECT_TRUE(val2.IsEmpty());
- val2 = val;
- EXPECT_FALSE(val.IsEmpty());
- EXPECT_FALSE(val2.IsEmpty());
- EXPECT_EQ("blah", val.Get<std::string>());
- EXPECT_EQ("blah", val2.Get<std::string>());
- val.Clear();
- EXPECT_TRUE(val.IsEmpty());
- EXPECT_EQ("blah", val2.Get<std::string>());
- val2.Clear();
- EXPECT_TRUE(val2.IsEmpty());
-
- val = std::vector<int>{100, 20, 3};
- auto v = val.Get<std::vector<int>>();
- EXPECT_EQ(100, v[0]);
- EXPECT_EQ(20, v[1]);
- EXPECT_EQ(3, v[2]);
-}
-
-TEST(Any, Enums) {
- enum class Dummy { foo, bar, baz };
- Any val(Dummy::bar);
- EXPECT_FALSE(val.IsEmpty());
- EXPECT_TRUE(val.IsConvertibleToInteger());
- EXPECT_EQ(Dummy::bar, val.Get<Dummy>());
- EXPECT_EQ(1, val.GetAsInteger());
-
- val = Dummy::baz;
- EXPECT_EQ(2, val.GetAsInteger());
-
- val = Dummy::foo;
- EXPECT_EQ(0, val.GetAsInteger());
-}
-
-TEST(Any, Integers) {
- Any val(14);
- EXPECT_TRUE(val.IsConvertibleToInteger());
- EXPECT_EQ(14, val.Get<int>());
- EXPECT_EQ(14, val.GetAsInteger());
-
- val = '\x40';
- EXPECT_TRUE(val.IsConvertibleToInteger());
- EXPECT_EQ(64, val.Get<char>());
- EXPECT_EQ(64, val.GetAsInteger());
-
- val = static_cast<uint16_t>(65535);
- EXPECT_TRUE(val.IsConvertibleToInteger());
- EXPECT_EQ(65535, val.Get<uint16_t>());
- EXPECT_EQ(65535, val.GetAsInteger());
-
- val = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL);
- EXPECT_TRUE(val.IsConvertibleToInteger());
- EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, val.Get<uint64_t>());
- EXPECT_EQ(-1, val.GetAsInteger());
-
- val = "abc";
- EXPECT_FALSE(val.IsConvertibleToInteger());
-
- int a = 5;
- val = &a;
- EXPECT_FALSE(val.IsConvertibleToInteger());
-}
-
-TEST(Any, Pointers) {
- Any val("abc"); // const char*
- EXPECT_FALSE(val.IsTypeCompatible<char*>());
- EXPECT_TRUE(val.IsTypeCompatible<const char*>());
- EXPECT_FALSE(val.IsTypeCompatible<volatile char*>());
- EXPECT_TRUE(val.IsTypeCompatible<volatile const char*>());
- EXPECT_STREQ("abc", val.Get<const char*>());
-
- int a = 10;
- val = &a;
- EXPECT_TRUE(val.IsTypeCompatible<int*>());
- EXPECT_TRUE(val.IsTypeCompatible<const int*>());
- EXPECT_TRUE(val.IsTypeCompatible<volatile int*>());
- EXPECT_TRUE(val.IsTypeCompatible<volatile const int*>());
- EXPECT_EQ(10, *val.Get<const int*>());
- *val.Get<int*>() = 3;
- EXPECT_EQ(3, a);
-}
-
-TEST(Any, Arrays) {
- // The following test are here to validate the array-to-pointer decay rules.
- // Since Any does not store the contents of a C-style array, just a pointer
- // to the data, putting array data into Any could be dangerous.
- // Make sure the array's lifetime exceeds that of an Any containing the
- // pointer to the array data.
- // If you want to store the array with data, use corresponding value types
- // such as std::vector or a struct containing C-style array as a member.
-
- int int_array[] = {1, 2, 3}; // int*
- Any val = int_array;
- EXPECT_TRUE(val.IsTypeCompatible<int*>());
- EXPECT_TRUE(val.IsTypeCompatible<const int*>());
- EXPECT_TRUE(val.IsTypeCompatible<int[]>());
- EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
- EXPECT_EQ(3, val.Get<int*>()[2]);
-
- const int const_int_array[] = {10, 20, 30}; // const int*
- val = const_int_array;
- EXPECT_FALSE(val.IsTypeCompatible<int*>());
- EXPECT_TRUE(val.IsTypeCompatible<const int*>());
- EXPECT_FALSE(val.IsTypeCompatible<int[]>());
- EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
- EXPECT_EQ(30, val.Get<const int*>()[2]);
-}
-
-TEST(Any, References) {
- // Passing references to object via Any might be error-prone or the
- // semantics could be unfamiliar to other developers. In many cases,
- // using pointers instead of references are more conventional and easier
- // to understand. Even though the cases of passing references are quite
- // explicit on both storing and retrieving ends, you might want to
- // use pointers instead anyway.
-
- int a = 5;
- Any val(std::ref(a)); // int&
- EXPECT_EQ(5, val.Get<std::reference_wrapper<int>>().get());
- val.Get<std::reference_wrapper<int>>().get() = 7;
- EXPECT_EQ(7, val.Get<std::reference_wrapper<int>>().get());
- EXPECT_EQ(7, a);
-
- Any val2(std::cref(a)); // const int&
- EXPECT_EQ(7, val2.Get<std::reference_wrapper<const int>>().get());
-
- a = 10;
- EXPECT_EQ(10, val.Get<std::reference_wrapper<int>>().get());
- EXPECT_EQ(10, val2.Get<std::reference_wrapper<const int>>().get());
-}
-
-TEST(Any, CustomTypes) {
- struct Person {
- std::string name;
- int age;
- };
- Any val(Person{"Jack", 40});
- Any val2 = val;
- EXPECT_EQ("Jack", val.Get<Person>().name);
- val.GetPtr<Person>()->name = "Joe";
- val.GetPtr<Person>()->age /= 2;
- EXPECT_EQ("Joe", val.Get<Person>().name);
- EXPECT_EQ(20, val.Get<Person>().age);
- EXPECT_EQ("Jack", val2.Get<Person>().name);
- EXPECT_EQ(40, val2.Get<Person>().age);
-}
-
-TEST(Any, Swap) {
- Any val(12);
- Any val2(2.7);
- EXPECT_EQ(12, val.Get<int>());
- EXPECT_EQ(2.7, val2.Get<double>());
-
- val.Swap(val2);
- EXPECT_EQ(2.7, val.Get<double>());
- EXPECT_EQ(12, val2.Get<int>());
-
- std::swap(val, val2);
- EXPECT_EQ(12, val.Get<int>());
- EXPECT_EQ(2.7, val2.Get<double>());
-}
-
-TEST(Any, TypeMismatch) {
- Any val(12);
- EXPECT_DEATH(val.Get<double>(),
- "Requesting value of type \\w+ from variant containing \\w+");
-
- val = std::string("123");
- EXPECT_DEATH(val.GetAsInteger(),
- "Unable to convert value of type \\w+ to integer");
-
- Any empty;
- EXPECT_DEATH(empty.GetAsInteger(), "Must not be called on an empty Any");
-}
-
-TEST(Any, TryGet) {
- Any val(12);
- Any empty;
- EXPECT_EQ("dummy", val.TryGet<std::string>("dummy"));
- EXPECT_EQ(12, val.TryGet<int>(17));
- EXPECT_EQ(17, empty.TryGet<int>(17));
-}
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index 74c1564..f02e494 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -15,7 +15,6 @@
'target_name': 'buffet_common',
'type': 'static_library',
'sources': [
- 'any.cc',
'commands/command_definition.cc',
'commands/command_dictionary.cc',
'commands/command_instance.cc',
@@ -76,8 +75,6 @@
},
'includes': ['../common-mk/common_test.gypi'],
'sources': [
- 'any_unittest.cc',
- 'any_internal_impl_unittest.cc',
'buffet_testrunner.cc',
'commands/command_definition_unittest.cc',
'commands/command_dictionary_unittest.cc',
diff --git a/buffet/commands/prop_types.cc b/buffet/commands/prop_types.cc
index 694d74e..f4de059 100644
--- a/buffet/commands/prop_types.cc
+++ b/buffet/commands/prop_types.cc
@@ -11,6 +11,7 @@
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/values.h>
+#include <chromeos/any.h>
#include <chromeos/string_utils.h>
#include "buffet/commands/object_schema.h"
@@ -149,7 +150,7 @@
return val->FromJson(value, error) && ValidateConstraints(*val, error);
}
-bool PropType::ValidateValue(const Any& value,
+bool PropType::ValidateValue(const chromeos::Any& value,
chromeos::ErrorPtr* error) const {
std::shared_ptr<PropValue> val = CreateValue(value);
CHECK(val) << "Failed to create value object";
diff --git a/buffet/commands/prop_types.h b/buffet/commands/prop_types.h
index 506c822..86a2960 100644
--- a/buffet/commands/prop_types.h
+++ b/buffet/commands/prop_types.h
@@ -13,6 +13,7 @@
#include <utility>
#include <vector>
+#include <chromeos/any.h>
#include <chromeos/error.h>
#include "buffet/commands/prop_constraints.h"
@@ -81,7 +82,8 @@
// Creates an instance of associated value object, using the parameter
// type as a factory class.
virtual std::shared_ptr<PropValue> CreateValue() const = 0;
- virtual std::shared_ptr<PropValue> CreateValue(const Any& val) const = 0;
+ virtual std::shared_ptr<PropValue> CreateValue(
+ const chromeos::Any& val) const = 0;
// Saves the parameter type definition as a JSON object.
// If |full_schema| is set to true, the full type definition is saved,
@@ -122,7 +124,8 @@
bool ValidateValue(const base::Value* value, chromeos::ErrorPtr* error) const;
// Similar to the above method, but uses Any as the value container.
- bool ValidateValue(const Any& value, chromeos::ErrorPtr* error) const;
+ bool ValidateValue(const chromeos::Any& value,
+ chromeos::ErrorPtr* error) const;
// Additional helper static methods to help with converting a type enum
// value into a string and back.
@@ -186,7 +189,8 @@
std::shared_ptr<PropValue> CreateValue() const override {
return std::make_shared<Value>(this);
}
- std::shared_ptr<PropValue> CreateValue(const Any& v) const override {
+ std::shared_ptr<PropValue> CreateValue(
+ const chromeos::Any& v) const override {
auto value = std::make_shared<Value>(this);
value->SetValue(v.Get<T>());
return std::move(value);
diff --git a/buffet/commands/prop_values.h b/buffet/commands/prop_values.h
index f568dd8..106ab1d 100644
--- a/buffet/commands/prop_values.h
+++ b/buffet/commands/prop_values.h
@@ -9,9 +9,9 @@
#include <memory>
#include <string>
+#include <chromeos/any.h>
#include <chromeos/error.h>
-#include "buffet/any.h"
#include "buffet/commands/schema_utils.h"
namespace base {
@@ -103,7 +103,7 @@
chromeos::ErrorPtr* error) = 0;
// Returns the contained C++ value as Any.
- virtual Any GetValueAsAny() const = 0;
+ virtual chromeos::Any GetValueAsAny() const = 0;
// Return the type definition of this value.
const PropType* GetPropType() const { return type_; }
@@ -149,7 +149,7 @@
}
// Helper methods to get and set the C++ representation of the value.
- Any GetValueAsAny() const override { return value_; }
+ chromeos::Any GetValueAsAny() const override { return value_; }
const T& GetValue() const { return value_; }
void SetValue(T value) { value_ = std::move(value); }