-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
150 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
// Copyright (c) 2023 Team Dissolve and contributors | ||
|
||
#pragma once | ||
|
||
#include <algorithm> | ||
#include <map> | ||
#include <vector> | ||
|
||
namespace dissolve | ||
{ | ||
|
||
// This class is similar to std::map, but the values are returned in | ||
// order of insertion, rather than in alphabetical order (like | ||
// std::map) or random order (like std:unordered_map) | ||
// | ||
// Access is still O(1) and insertion is O(log(N)). Erasure hasn't | ||
// been implemented yet and will likely be O(N), unlike the O(log(N)) | ||
// of std::map. However, seeing as removal hasn't even been required | ||
// at this point, it seems unlikely that it will ever serve as a true | ||
// bottleneck. | ||
template <typename Key, typename Value> class OrderedMap | ||
{ | ||
|
||
private: | ||
// A mapping between keys and indices | ||
std::map<Key, int> index_; | ||
// An association array of the keys and values | ||
std::vector<std::pair<Key, Value>> values_; | ||
// If a key does not exist, add it to the array | ||
std::pair<Key, Value> &insistKey(const Key &key) | ||
{ | ||
if (index_.find(key) == index_.end()) | ||
{ | ||
index_[key] = values_.size(); | ||
return values_.emplace_back(key, Value{}); | ||
} | ||
else | ||
return values_[index_[key]]; | ||
} | ||
|
||
public: | ||
// Constructors | ||
OrderedMap(){}; | ||
// Constructor from an iterator off a std::map or std::unorderedmap | ||
template <typename Iter> OrderedMap(Iter begin, Iter end) | ||
{ | ||
for (auto i = begin; i != end; i++) | ||
(*this)[i->first] = i->second; | ||
}; | ||
|
||
// Iterator access | ||
typename std::vector<std::pair<Key, Value>>::iterator begin() { return values_.begin(); } | ||
typename std::vector<std::pair<Key, Value>>::iterator end() { return values_.end(); } | ||
typename std::vector<std::pair<Key, Value>>::const_iterator begin() const { return values_.begin(); } | ||
typename std::vector<std::pair<Key, Value>>::const_iterator end() const { return values_.end(); } | ||
|
||
// Required std::map interface functions | ||
const Value &at(const Key &key) const { return values_[index_.at(key)].second; } | ||
Value &at(const Key &key) { return values_[index_.at(key)].second; } | ||
// The number of times a key is used. This can only be zero or one. | ||
auto count(const Key &key) const { return index_.count(key); } | ||
|
||
// Operator overloads from std::map | ||
bool operator==(const OrderedMap<Key, Value> other) const | ||
{ | ||
if (values_.size() != other.values_.size()) | ||
return false; | ||
for (int i = 0; i < values_.size(); i++) | ||
if (values_[i] != other.values_[i]) | ||
return false; | ||
for (auto [k, v] : index_) | ||
if (other.index_.at(k) != v) | ||
return false; | ||
return true; | ||
} | ||
Value &operator[](const Key &key) { return insistKey(key).second; } | ||
Value &operator[](Key &&key) { return insistKey(key).second; } | ||
}; | ||
|
||
} // namespace dissolve |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
// Copyright (c) 2023 Team Dissolve and contributors | ||
|
||
#include "templates/orderedMap.h" | ||
#include <gtest/gtest.h> | ||
#include <toml11/toml.hpp> | ||
|
||
namespace UnitTest | ||
{ | ||
|
||
using SerialisedValue = toml::basic_value<toml::discard_comments, dissolve::OrderedMap, std::vector>; | ||
TEST(OrderedMapTest, BasicOrderedMap) | ||
{ | ||
SerialisedValue example; | ||
std::vector<std::string> keys = {"foo", "bar", "quux", "xyzzy"}; | ||
std::vector<int> values = {2, 7, 5, 3}; | ||
for (auto i = 0; i < keys.size(); i++) | ||
example[keys[i]] = values[i]; | ||
|
||
auto index = 0; | ||
for (auto [k, v] : example.as_table()) | ||
{ | ||
EXPECT_EQ(keys[index], k); | ||
EXPECT_EQ(values[index], v.as_integer()); | ||
index++; | ||
} | ||
EXPECT_EQ(index, keys.size()); | ||
} | ||
|
||
} // namespace UnitTest |