#ifndef SASS_ORDERED_MAP_H #define SASS_ORDERED_MAP_H namespace Sass { // ########################################################################## // Very simple and limited container for insert ordered hash map. // Piggy-back implementation on std::unordered_map and sass::vector // ########################################################################## template< class Key, class T, class Hash = std::hash, class KeyEqual = std::equal_to, class Allocator = std::allocator> > class ordered_map { private: using map_type = typename std::unordered_map< Key, T, Hash, KeyEqual, Allocator>; using map_iterator = typename std::unordered_map< Key, T, Hash, KeyEqual, Allocator>::iterator; using map_const_iterator = typename std::unordered_map< Key, T, Hash, KeyEqual, Allocator>::const_iterator; // The main unordered map map_type _map; // Keep insertion order sass::vector _keys; sass::vector _values; const KeyEqual _keyEqual; public: ordered_map() : _keyEqual(KeyEqual()) { } ordered_map& operator= (const ordered_map& other) { _map = other._map; _keys = other._keys; _values = other._values; return *this; } std::pair front() { return std::make_pair( _keys.front(), _values.front() ); } bool empty() const { return _keys.empty(); } void insert(const Key& key, const T& val) { if (!hasKey(key)) { _values.push_back(val); _keys.push_back(key); } _map[key] = val; } bool hasKey(const Key& key) const { return _map.find(key) != _map.end(); } bool erase(const Key& key) { _map.erase(key); // find the position in the array for (size_t i = 0; i < _keys.size(); i += 1) { if (_keyEqual(key, _keys[i])) { _keys.erase(_keys.begin() + i); _values.erase(_values.begin() + i); return true; } } return false; } const sass::vector& keys() const { return _keys; } const sass::vector& values() const { return _values; } const T& get(const Key& key) { if (hasKey(key)) { return _map[key]; } throw std::runtime_error("Key does not exist"); } using iterator = typename sass::vector::iterator; using const_iterator = typename sass::vector::const_iterator; using reverse_iterator = typename sass::vector::reverse_iterator; using const_reverse_iterator = typename sass::vector::const_reverse_iterator; typename sass::vector::iterator end() { return _keys.end(); } typename sass::vector::iterator begin() { return _keys.begin(); } typename sass::vector::reverse_iterator rend() { return _keys.rend(); } typename sass::vector::reverse_iterator rbegin() { return _keys.rbegin(); } typename sass::vector::const_iterator end() const { return _keys.end(); } typename sass::vector::const_iterator begin() const { return _keys.begin(); } typename sass::vector::const_reverse_iterator rend() const { return _keys.rend(); } typename sass::vector::const_reverse_iterator rbegin() const { return _keys.rbegin(); } }; } #endif