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 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_ 6 #define MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_ 7 8 #include <string.h> 9 10 #include <algorithm> 11 #include <string> 12 #include <vector> 13 14 #include "mojo/public/bindings/lib/array_internal.h" 15 16 namespace mojo { 17 18 // Provides read-only access to array data. 19 template <typename T> 20 class Array { 21 public: 22 typedef internal::ArrayTraits<T, internal::TypeTraits<T>::kIsObject> Traits_; 23 typedef typename Traits_::DataType Data; 24 typedef typename Traits_::ConstRef ConstRef; 25 26 Array() : data_(NULL) { 27 } 28 29 template <typename U> 30 Array(const U& u, Buffer* buf = Buffer::current()) { 31 *this = TypeConverter<Array<T>,U>::ConvertFrom(u, buf); 32 } 33 34 template <typename U> 35 Array& operator=(const U& u) { 36 *this = TypeConverter<Array<T>,U>::ConvertFrom(u, Buffer::current()); 37 return *this; 38 } 39 40 template <typename U> 41 operator U() const { 42 return To<U>(); 43 } 44 45 template <typename U> 46 U To() const { 47 return TypeConverter<Array<T>,U>::ConvertTo(*this); 48 } 49 50 bool is_null() const { return !data_; } 51 52 size_t size() const { return data_->size(); } 53 54 ConstRef at(size_t offset) const { 55 return Traits_::ToConstRef(data_->at(offset)); 56 } 57 ConstRef operator[](size_t offset) const { return at(offset); } 58 59 // Provides a way to initialize an array element-by-element. 60 class Builder { 61 public: 62 typedef typename Array<T>::Data Data; 63 typedef typename Array<T>::Traits_ Traits_; 64 typedef typename Traits_::Ref Ref; 65 66 explicit Builder(size_t num_elements, Buffer* buf = mojo::Buffer::current()) 67 : data_(Data::New(num_elements, buf)) { 68 } 69 70 size_t size() const { return data_->size(); } 71 72 Ref at(size_t offset) { 73 return Traits_::ToRef(data_->at(offset)); 74 } 75 Ref operator[](size_t offset) { return at(offset); } 76 77 Array<T> Finish() { 78 Data* data = NULL; 79 std::swap(data, data_); 80 return internal::Wrap(data); 81 } 82 83 private: 84 Data* data_; 85 MOJO_DISALLOW_COPY_AND_ASSIGN(Builder); 86 }; 87 88 protected: 89 friend class internal::WrapperHelper<Array<T> >; 90 91 struct Wrap {}; 92 Array(Wrap, const Data* data) : data_(data) {} 93 94 const Data* data_; 95 }; 96 97 // UTF-8 encoded 98 typedef Array<char> String; 99 100 template <> 101 class TypeConverter<String, std::string> { 102 public: 103 static String ConvertFrom(const std::string& input, Buffer* buf); 104 static std::string ConvertTo(const String& input); 105 }; 106 107 template <size_t N> 108 class TypeConverter<String, char[N]> { 109 public: 110 static String ConvertFrom(const char input[N], Buffer* buf) { 111 String::Builder result(N - 1, buf); 112 memcpy(&result[0], input, N - 1); 113 return result.Finish(); 114 } 115 }; 116 117 // Appease MSVC. 118 template <size_t N> 119 class TypeConverter<String, const char[N]> { 120 public: 121 static String ConvertFrom(const char input[N], Buffer* buf) { 122 return TypeConverter<String, char[N]>::ConvertFrom(input, buf); 123 } 124 }; 125 126 template <> 127 class TypeConverter<String, const char*> { 128 public: 129 static String ConvertFrom(const char* input, Buffer* buf); 130 // NOTE: |ConvertTo| explicitly not implemented since String is not null 131 // terminated (and may have embedded null bytes). 132 }; 133 134 template <typename T, typename E> 135 class TypeConverter<Array<T>, std::vector<E> > { 136 public: 137 static Array<T> ConvertFrom(const std::vector<E>& input, Buffer* buf) { 138 typename Array<T>::Builder result(input.size(), buf); 139 for (size_t i = 0; i < input.size(); ++i) 140 result[i] = TypeConverter<T, E>::ConvertFrom(input[i], buf); 141 return result.Finish(); 142 } 143 static std::vector<E> ConvertTo(const Array<T>& input) { 144 std::vector<E> result; 145 if (!input.is_null()) { 146 result.resize(input.size()); 147 for (size_t i = 0; i < input.size(); ++i) 148 result[i] = TypeConverter<T, E>::ConvertTo(input[i]); 149 } 150 return result; 151 } 152 }; 153 154 } // namespace mojo 155 156 #endif // MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_ 157