| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ |
| 7 | 7 |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "mojo/public/cpp/bindings/lib/array_internal.h" | 14 #include "mojo/public/cpp/bindings/lib/array_internal.h" |
| 15 #include "mojo/public/cpp/bindings/lib/template_util.h" |
| 15 #include "mojo/public/cpp/bindings/type_converter.h" | 16 #include "mojo/public/cpp/bindings/type_converter.h" |
| 16 | 17 |
| 17 namespace mojo { | 18 namespace mojo { |
| 18 | 19 |
| 19 // Provides read-only access to array data. | 20 // Provides read-only access to array data. |
| 20 template <typename T> | 21 template <typename T> |
| 21 class Array { | 22 class Array { |
| 23 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(Array, RValue) |
| 22 public: | 24 public: |
| 23 typedef internal::ArrayTraits<T, | 25 typedef internal::ArrayTraits<T, internal::IsMoveOnlyType<T>::value> |
| 24 internal::TypeTraits<T>::kIsObject, | 26 Traits; |
| 25 internal::TypeTraits<T>::kIsHandle> Traits_; | 27 typedef typename Traits::ConstRefType ConstRefType; |
| 26 typedef typename Traits_::DataType Data; | 28 typedef typename Traits::RefType RefType; |
| 27 typedef typename Traits_::ConstRef ConstRef; | 29 typedef typename Traits::StorageType StorageType; |
| 28 | 30 |
| 29 Array() : data_(NULL) { | 31 Array() : is_null_(true) {} |
| 32 explicit Array(size_t size) : vec_(size), is_null_(false) { |
| 33 Traits::Initialize(&vec_); |
| 34 } |
| 35 ~Array() { Traits::Finalize(&vec_); } |
| 36 |
| 37 Array(RValue other) : is_null_(true) { Take(other.object); } |
| 38 Array& operator=(RValue other) { |
| 39 Take(other.object); |
| 40 return *this; |
| 41 } |
| 42 |
| 43 static Array New(size_t size) { |
| 44 return Array(size).Pass(); |
| 30 } | 45 } |
| 31 | 46 |
| 32 template <typename U> | 47 template <typename U> |
| 33 Array(const U& u, Buffer* buf = Buffer::current()) { | 48 static Array From(const U& other) { |
| 34 TypeConverter<Array<T>,U>::AssertAllowImplicitTypeConversion(); | 49 return TypeConverter<Array, U>::ConvertFrom(other); |
| 35 *this = TypeConverter<Array<T>,U>::ConvertFrom(u, buf); | |
| 36 } | 50 } |
| 37 | 51 |
| 38 template <typename U> | 52 template <typename U> |
| 39 Array& operator=(const U& u) { | 53 const U& To() const { |
| 40 TypeConverter<Array<T>,U>::AssertAllowImplicitTypeConversion(); | 54 return TypeConverter<Array, U>::ConvertTo(*this); |
| 41 *this = TypeConverter<Array<T>,U>::ConvertFrom(u, Buffer::current()); | |
| 42 return *this; | |
| 43 } | 55 } |
| 44 | 56 |
| 45 template <typename U> | 57 void reset() { |
| 46 operator U() const { | 58 if (!vec_.empty()) { |
| 47 TypeConverter<Array<T>,U>::AssertAllowImplicitTypeConversion(); | 59 Traits::Finalize(&vec_); |
| 48 return To<U>(); | 60 vec_.clear(); |
| 61 } |
| 62 is_null_ = true; |
| 49 } | 63 } |
| 50 | 64 |
| 51 template <typename U> | 65 bool is_null() const { return is_null_; } |
| 52 U To() const { | 66 |
| 53 return TypeConverter<Array<T>,U>::ConvertTo(*this); | 67 size_t size() const { return vec_.size(); } |
| 68 |
| 69 ConstRefType at(size_t offset) const { return Traits::at(&vec_, offset); } |
| 70 ConstRefType operator[](size_t offset) const { return at(offset); } |
| 71 |
| 72 RefType at(size_t offset) { return Traits::at(&vec_, offset); } |
| 73 RefType operator[](size_t offset) { return at(offset); } |
| 74 |
| 75 const std::vector<StorageType>& storage() const { |
| 76 return vec_; |
| 77 } |
| 78 operator const std::vector<StorageType>&() const { |
| 79 return vec_; |
| 54 } | 80 } |
| 55 | 81 |
| 56 template <typename U> | 82 void Swap(Array* other) { |
| 57 static Array From(const U& u, Buffer* buf = Buffer::current()) { | 83 std::swap(is_null_, other->is_null_); |
| 58 return TypeConverter<Array<T>,U>::ConvertFrom(u, buf); | 84 vec_.swap(other->vec_); |
| 85 } |
| 86 void Swap(std::vector<StorageType>* other) { |
| 87 is_null_ = false; |
| 88 vec_.swap(*other); |
| 59 } | 89 } |
| 60 | 90 |
| 61 bool is_null() const { return !data_; } | 91 private: |
| 92 typedef std::vector<StorageType> Array::*Testable; |
| 62 | 93 |
| 63 size_t size() const { return data_->size(); } | 94 public: |
| 95 operator Testable() const { return is_null_ ? 0 : &Array::vec_; } |
| 64 | 96 |
| 65 ConstRef at(size_t offset) const { | 97 private: |
| 66 return Traits_::ToConstRef(data_->at(offset)); | 98 void Take(Array* other) { |
| 67 } | 99 reset(); |
| 68 ConstRef operator[](size_t offset) const { return at(offset); } | 100 Swap(other); |
| 69 | |
| 70 // Provides a way to initialize an array element-by-element. | |
| 71 class Builder { | |
| 72 public: | |
| 73 typedef typename Array<T>::Data Data; | |
| 74 typedef typename Array<T>::Traits_ Traits_; | |
| 75 typedef typename Traits_::Ref Ref; | |
| 76 | |
| 77 explicit Builder(size_t num_elements, Buffer* buf = mojo::Buffer::current()) | |
| 78 : data_(Data::New(num_elements, buf, Traits_::GetDestructor())) { | |
| 79 } | |
| 80 | |
| 81 size_t size() const { return data_->size(); } | |
| 82 | |
| 83 Ref at(size_t offset) { | |
| 84 return Traits_::ToRef(data_->at(offset)); | |
| 85 } | |
| 86 Ref operator[](size_t offset) { return at(offset); } | |
| 87 | |
| 88 Array<T> Finish() { | |
| 89 Data* data = NULL; | |
| 90 std::swap(data, data_); | |
| 91 return internal::Wrap(data); | |
| 92 } | |
| 93 | |
| 94 private: | |
| 95 Data* data_; | |
| 96 MOJO_DISALLOW_COPY_AND_ASSIGN(Builder); | |
| 97 }; | |
| 98 | |
| 99 protected: | |
| 100 friend class internal::WrapperHelper<Array<T> >; | |
| 101 | |
| 102 struct Wrap {}; | |
| 103 Array(Wrap, const Data* data) : data_(data) {} | |
| 104 | |
| 105 const Data* data_; | |
| 106 }; | |
| 107 | |
| 108 // UTF-8 encoded | |
| 109 typedef Array<char> String; | |
| 110 | |
| 111 template <> | |
| 112 class TypeConverter<String, std::string> { | |
| 113 public: | |
| 114 static String ConvertFrom(const std::string& input, Buffer* buf); | |
| 115 static std::string ConvertTo(const String& input); | |
| 116 | |
| 117 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); | |
| 118 }; | |
| 119 | |
| 120 template <size_t N> | |
| 121 class TypeConverter<String, char[N]> { | |
| 122 public: | |
| 123 static String ConvertFrom(const char input[N], Buffer* buf) { | |
| 124 String::Builder result(N - 1, buf); | |
| 125 memcpy(&result[0], input, N - 1); | |
| 126 return result.Finish(); | |
| 127 } | 101 } |
| 128 | 102 |
| 129 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); | 103 std::vector<StorageType> vec_; |
| 130 }; | 104 bool is_null_; |
| 131 | |
| 132 // Appease MSVC. | |
| 133 template <size_t N> | |
| 134 class TypeConverter<String, const char[N]> { | |
| 135 public: | |
| 136 static String ConvertFrom(const char input[N], Buffer* buf) { | |
| 137 return TypeConverter<String, char[N]>::ConvertFrom(input, buf); | |
| 138 } | |
| 139 | |
| 140 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); | |
| 141 }; | |
| 142 | |
| 143 template <> | |
| 144 class TypeConverter<String, const char*> { | |
| 145 public: | |
| 146 static String ConvertFrom(const char* input, Buffer* buf); | |
| 147 // NOTE: |ConvertTo| explicitly not implemented since String is not null | |
| 148 // terminated (and may have embedded null bytes). | |
| 149 | |
| 150 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); | |
| 151 }; | 105 }; |
| 152 | 106 |
| 153 template <typename T, typename E> | 107 template <typename T, typename E> |
| 154 class TypeConverter<Array<T>, std::vector<E> > { | 108 class TypeConverter<Array<T>, std::vector<E> > { |
| 155 public: | 109 public: |
| 156 static Array<T> ConvertFrom(const std::vector<E>& input, Buffer* buf) { | 110 static Array<T> ConvertFrom(const std::vector<E>& input) { |
| 157 typename Array<T>::Builder result(input.size(), buf); | 111 Array<T> result(input.size()); |
| 158 for (size_t i = 0; i < input.size(); ++i) | 112 for (size_t i = 0; i < input.size(); ++i) |
| 159 result[i] = TypeConverter<T, E>::ConvertFrom(input[i], buf); | 113 result[i] = TypeConverter<T, E>::ConvertFrom(input[i]); |
| 160 return result.Finish(); | 114 return result.Pass(); |
| 161 } | 115 } |
| 162 static std::vector<E> ConvertTo(const Array<T>& input) { | 116 static std::vector<E> ConvertTo(const Array<T>& input) { |
| 163 std::vector<E> result; | 117 std::vector<E> result; |
| 164 if (!input.is_null()) { | 118 if (!input.is_null()) { |
| 165 result.resize(input.size()); | 119 result.resize(input.size()); |
| 166 for (size_t i = 0; i < input.size(); ++i) | 120 for (size_t i = 0; i < input.size(); ++i) |
| 167 result[i] = TypeConverter<T, E>::ConvertTo(input[i]); | 121 result[i] = TypeConverter<T, E>::ConvertTo(input[i]); |
| 168 } | 122 } |
| 169 return result; | 123 return result; |
| 170 } | 124 } |
| 171 | |
| 172 MOJO_INHERIT_IMPLICIT_TYPE_CONVERSION(T, E); | |
| 173 }; | 125 }; |
| 174 | 126 |
| 175 } // namespace mojo | 127 } // namespace mojo |
| 176 | 128 |
| 177 #endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ | 129 #endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ |
| OLD | NEW |