// 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. #ifndef MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_ #define MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_ #include <string.h> #include <algorithm> #include <string> #include <vector> #include "mojo/public/bindings/lib/array_internal.h" namespace mojo { // Provides read-only access to array data. template <typename T> class Array { public: typedef internal::ArrayTraits<T, internal::TypeTraits<T>::kIsObject> Traits_; typedef typename Traits_::DataType Data; typedef typename Traits_::ConstRef ConstRef; Array() : data_(NULL) { } template <typename U> Array(const U& u, Buffer* buf = Buffer::current()) { *this = TypeConverter<Array<T>,U>::ConvertFrom(u, buf); } template <typename U> Array& operator=(const U& u) { *this = TypeConverter<Array<T>,U>::ConvertFrom(u, Buffer::current()); return *this; } template <typename U> operator U() const { return To<U>(); } template <typename U> U To() const { return TypeConverter<Array<T>,U>::ConvertTo(*this); } bool is_null() const { return !data_; } size_t size() const { return data_->size(); } ConstRef at(size_t offset) const { return Traits_::ToConstRef(data_->at(offset)); } ConstRef operator[](size_t offset) const { return at(offset); } // Provides a way to initialize an array element-by-element. class Builder { public: typedef typename Array<T>::Data Data; typedef typename Array<T>::Traits_ Traits_; typedef typename Traits_::Ref Ref; explicit Builder(size_t num_elements, Buffer* buf = mojo::Buffer::current()) : data_(Data::New(num_elements, buf)) { } size_t size() const { return data_->size(); } Ref at(size_t offset) { return Traits_::ToRef(data_->at(offset)); } Ref operator[](size_t offset) { return at(offset); } Array<T> Finish() { Data* data = NULL; std::swap(data, data_); return internal::Wrap(data); } private: Data* data_; MOJO_DISALLOW_COPY_AND_ASSIGN(Builder); }; protected: friend class internal::WrapperHelper<Array<T> >; struct Wrap {}; Array(Wrap, const Data* data) : data_(data) {} const Data* data_; }; // UTF-8 encoded typedef Array<char> String; template <> class TypeConverter<String, std::string> { public: static String ConvertFrom(const std::string& input, Buffer* buf); static std::string ConvertTo(const String& input); }; template <size_t N> class TypeConverter<String, char[N]> { public: static String ConvertFrom(const char input[N], Buffer* buf) { String::Builder result(N - 1, buf); memcpy(&result[0], input, N - 1); return result.Finish(); } }; // Appease MSVC. template <size_t N> class TypeConverter<String, const char[N]> { public: static String ConvertFrom(const char input[N], Buffer* buf) { return TypeConverter<String, char[N]>::ConvertFrom(input, buf); } }; template <> class TypeConverter<String, const char*> { public: static String ConvertFrom(const char* input, Buffer* buf); // NOTE: |ConvertTo| explicitly not implemented since String is not null // terminated (and may have embedded null bytes). }; template <typename T, typename E> class TypeConverter<Array<T>, std::vector<E> > { public: static Array<T> ConvertFrom(const std::vector<E>& input, Buffer* buf) { typename Array<T>::Builder result(input.size(), buf); for (size_t i = 0; i < input.size(); ++i) result[i] = TypeConverter<T, E>::ConvertFrom(input[i], buf); return result.Finish(); } static std::vector<E> ConvertTo(const Array<T>& input) { std::vector<E> result; if (!input.is_null()) { result.resize(input.size()); for (size_t i = 0; i < input.size(); ++i) result[i] = TypeConverter<T, E>::ConvertTo(input[i]); } return result; } }; } // namespace mojo #endif // MOJO_PUBLIC_BINDINGS_LIB_ARRAY_H_