// Copyright 2014 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_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ #include #include "mojo/public/cpp/bindings/array.h" #include "mojo/public/cpp/bindings/lib/template_util.h" namespace mojo { namespace internal { template struct MapTraits {}; template struct MapTraits { // Map keys can't be move only types. static_assert(!internal::IsMoveOnlyType::value, "Map keys can not be move only types."); typedef Key KeyStorageType; typedef Key& KeyRefType; typedef const Key& KeyConstRefType; typedef KeyConstRefType KeyForwardType; typedef Value ValueStorageType; typedef Value& ValueRefType; typedef const Value& ValueConstRefType; typedef ValueConstRefType ValueForwardType; static inline void InitializeFrom( std::map* m, mojo::Array keys, mojo::Array values) { for (size_t i = 0; i < keys.size(); ++i) Insert(m, keys[i], values[i]); } static inline void Decompose(std::map* m, mojo::Array* keys, mojo::Array* values) { keys->resize(m->size()); values->resize(m->size()); int i = 0; for (typename std::map::iterator it = m->begin(); it != m->end(); ++it, ++i) { (*keys)[i] = it->first; (*values)[i] = it->second; } } static inline void Finalize(std::map* m) {} static inline ValueRefType at(std::map* m, KeyForwardType key) { // We don't have C++11 library support yet, so we have to emulate the crash // on a non-existent key. auto it = m->find(key); MOJO_CHECK(it != m->end()); return it->second; } static inline ValueConstRefType at( const std::map* m, KeyForwardType key) { // We don't have C++11 library support yet, so we have to emulate the crash // on a non-existent key. auto it = m->find(key); MOJO_CHECK(it != m->end()); return it->second; } static inline ValueRefType GetOrInsert( std::map* m, KeyForwardType key) { // This is the backing for the index operator (operator[]). return (*m)[key]; } static inline void Insert(std::map* m, KeyForwardType key, ValueForwardType value) { m->insert(std::make_pair(key, value)); } static inline KeyConstRefType GetKey( const typename std::map::const_iterator& it) { return it->first; } static inline ValueConstRefType GetValue( const typename std::map::const_iterator& it) { return it->second; } static inline ValueRefType GetValue( const typename std::map::iterator& it) { return it->second; } static inline void Clone( const std::map& src, std::map* dst) { dst->clear(); for (auto it = src.begin(); it != src.end(); ++it) dst->insert(*it); } }; template struct MapTraits { // Map keys can't be move only types. static_assert(!internal::IsMoveOnlyType::value, "Map keys can not be move only types."); typedef Key KeyStorageType; typedef Key& KeyRefType; typedef const Key& KeyConstRefType; typedef KeyConstRefType KeyForwardType; struct ValueStorageType { // Make 8-byte aligned. char buf[sizeof(Value) + (8 - (sizeof(Value) % 8)) % 8]; }; typedef Value& ValueRefType; typedef const Value& ValueConstRefType; typedef Value ValueForwardType; static inline void InitializeFrom( std::map* m, mojo::Array keys, mojo::Array values) { for (size_t i = 0; i < keys.size(); ++i) Insert(m, keys[i], values[i]); } static inline void Decompose(std::map* m, mojo::Array* keys, mojo::Array* values) { keys->resize(m->size()); values->resize(m->size()); int i = 0; for (typename std::map::iterator it = m->begin(); it != m->end(); ++it, ++i) { (*keys)[i] = it->first; (*values)[i] = GetValue(it).Pass(); } } static inline void Finalize(std::map* m) { for (auto& pair : *m) reinterpret_cast(pair.second.buf)->~Value(); } static inline ValueRefType at(std::map* m, KeyForwardType key) { // We don't have C++11 library support yet, so we have to emulate the crash // on a non-existent key. auto it = m->find(key); MOJO_CHECK(it != m->end()); return GetValue(it); } static inline ValueConstRefType at( const std::map* m, KeyForwardType key) { // We don't have C++11 library support yet, so we have to emulate the crash // on a non-existent key. auto it = m->find(key); MOJO_CHECK(it != m->end()); return GetValue(it); } static inline ValueRefType GetOrInsert( std::map* m, KeyForwardType key) { // This is the backing for the index operator (operator[]). auto it = m->find(key); if (it == m->end()) { it = m->insert(std::make_pair(key, ValueStorageType())).first; new (it->second.buf) Value(); } return GetValue(it); } static inline void Insert(std::map* m, KeyForwardType key, ValueRefType value) { // STL insert() doesn't insert |value| if |key| is already part of |m|. We // have to use operator[] to initialize into the storage buffer, but we // have to do a manual check so that we don't overwrite an existing object. auto it = m->find(key); if (it == m->end()) new ((*m)[key].buf) Value(value.Pass()); } static inline KeyConstRefType GetKey( const typename std::map::const_iterator& it) { return it->first; } static inline ValueConstRefType GetValue( const typename std::map::const_iterator& it) { return *reinterpret_cast(it->second.buf); } static inline ValueRefType GetValue( const typename std::map::iterator& it) { return *reinterpret_cast(it->second.buf); } static inline void Clone( const std::map& src, std::map* dst) { Finalize(dst); dst->clear(); for (auto it = src.begin(); it != src.end(); ++it) new ((*dst)[it->first].buf) Value(GetValue(it).Clone()); } }; } // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_