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_(true) { | |
yzshen1
2014/05/22 17:13:53
nit: 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 |