-
Notifications
You must be signed in to change notification settings - Fork 1
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
7 changed files
with
266 additions
and
9 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/** | ||
* @file Deserializer.hpp | ||
* @brief Implementation of a minimal map-like container which preserves insertion order. | ||
* | ||
* Copyright (c) 2023 fktn | ||
* Distributed under the MIT License (https://opensource.org/licenses/MIT) | ||
*/ | ||
|
||
#ifndef FK_YAML_ORDERED_MAP_HPP_ | ||
#define FK_YAML_ORDERED_MAP_HPP_ | ||
|
||
#include <functional> | ||
#include <initializer_list> | ||
#include <memory> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "fkYAML/VersioningMacros.hpp" | ||
#include "fkYAML/Exception.hpp" | ||
|
||
/** | ||
* @namespace fkyaml | ||
* @brief namespace for fkYAML library. | ||
*/ | ||
FK_YAML_NAMESPACE_BEGIN | ||
|
||
/** | ||
* @brief A minimal map-like container which preserves insertion order. | ||
* | ||
* @tparam Key | ||
* @tparam Value | ||
* @tparam IgnoredCompare | ||
* @tparam Allocator | ||
*/ | ||
template < | ||
typename Key, typename Value, typename IgnoredCompare = std::less<Key>, | ||
typename Allocator = std::allocator<std::pair<const Key, Value>>> | ||
class OrderedMap : public std::vector<std::pair<const Key, Value>, Allocator> | ||
{ | ||
public: | ||
using key_type = Key; | ||
using mapped_type = Value; | ||
using Container = std::vector<std::pair<const Key, Value>, Allocator>; | ||
using value_type = typename Container::value_type; | ||
using iterator = typename Container::iterator; | ||
using const_iterator = typename Container::const_iterator; | ||
using size_type = typename Container::size_type; | ||
using key_compare = std::equal_to<Key>; | ||
|
||
public: | ||
/** | ||
* @brief Construct a new OrderedMap object. | ||
*/ | ||
OrderedMap() noexcept(noexcept(Container())) | ||
: Container(), | ||
m_compare() | ||
{ | ||
} | ||
|
||
/** | ||
* @brief Construct a new OrderedMap object with an initializer list. | ||
* | ||
* @param init An initializer list to construct the inner container object. | ||
*/ | ||
OrderedMap(std::initializer_list<value_type> init) | ||
: Container {init}, | ||
m_compare() | ||
{ | ||
} | ||
|
||
public: | ||
mapped_type& operator[](const key_type& key) noexcept | ||
{ | ||
return emplace(key, mapped_type()).first->second; | ||
} | ||
|
||
public: | ||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
std::pair<iterator, bool> emplace(const key_type& key, const mapped_type& value) noexcept | ||
{ | ||
for (auto itr = this->begin(); itr != this->end(); ++itr) | ||
{ | ||
if (m_compare(itr->first, key)) | ||
{ | ||
return {itr, false}; | ||
} | ||
} | ||
this->emplace_back(key, value); | ||
return {std::prev(this->end()), true}; | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
mapped_type& at(const key_type& key) | ||
{ | ||
for (auto itr = this->begin(); itr != this->end(); ++itr) | ||
{ | ||
if (m_compare(itr->first, key)) | ||
{ | ||
return itr->second; | ||
} | ||
} | ||
throw Exception("key not found."); | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
const mapped_type& at(const key_type& key) const | ||
{ | ||
for (auto itr = this->begin(); itr != this->end(); ++itr) | ||
{ | ||
if (m_compare(itr->first, key)) | ||
{ | ||
return itr->second; | ||
} | ||
} | ||
throw Exception("key not found."); | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
iterator find(const key_type& key) noexcept | ||
{ | ||
for (auto itr = this->begin(); itr != this->end(); ++itr) | ||
{ | ||
if (m_compare(itr->first, key)) | ||
{ | ||
return itr; | ||
} | ||
} | ||
return this->end(); | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
const_iterator find(const key_type& key) const noexcept | ||
{ | ||
for (auto itr = this->begin(); itr != this->end(); ++itr) | ||
{ | ||
if (m_compare(itr->first, key)) | ||
{ | ||
return itr; | ||
} | ||
} | ||
return this->end(); | ||
} | ||
|
||
private: | ||
key_compare m_compare; | ||
}; | ||
|
||
FK_YAML_NAMESPACE_END | ||
|
||
#endif /* FK_YAML_ORDERED_MAP_HPP_ */ |
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,102 @@ | ||
/** | ||
* OrderedMapClassTest.cpp - implementation of test functions for the OrderedMap class | ||
* | ||
* Copyright (c) 2023 fktn | ||
* Distributed under the MIT License (https://opensource.org/licenses/MIT) | ||
*/ | ||
|
||
#include "catch2/catch.hpp" | ||
|
||
#include <string> | ||
|
||
#include "fkYAML/OrderedMap.hpp" | ||
|
||
TEST_CASE("OrderedMapClassTest_DefaultCtorTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE(map.empty()); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_InitListCtorTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map {{"foo", true}, {"bar", false}}; | ||
REQUIRE_FALSE(map.empty()); | ||
REQUIRE(map.size() == 2); | ||
REQUIRE(map["foo"] == true); | ||
REQUIRE(map["bar"] == false); | ||
REQUIRE_NOTHROW(map.at("foo")); | ||
REQUIRE_NOTHROW(map.at("bar")); | ||
REQUIRE_THROWS_AS(map.at("buz"), fkyaml::Exception); | ||
auto itr = map.begin(); | ||
REQUIRE(itr->first == "foo"); | ||
REQUIRE(itr->second == true); | ||
++itr; | ||
REQUIRE(itr->first == "bar"); | ||
REQUIRE(itr->second == false); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_SubscriptOperatorTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map {{"foo", true}, {"buz", false}}; | ||
REQUIRE(map["foo"] == true); | ||
REQUIRE(map["bar"] == false); | ||
REQUIRE(map["buz"] == false); | ||
map["buz"] = true; | ||
REQUIRE(map["buz"] == true); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_EmplaceTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE(map.emplace("foo", true).second == true); | ||
REQUIRE(map.emplace("foo", false).second == false); | ||
REQUIRE(map["foo"] == true); | ||
REQUIRE(map.emplace("bar", false).second == true); | ||
REQUIRE(map["bar"] == false); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_NonConstAtTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE_THROWS_AS(map.at("foo"), fkyaml::Exception); | ||
map.emplace("foo", true); | ||
REQUIRE_NOTHROW(map.at("foo")); | ||
REQUIRE(map.at("foo") == true); | ||
REQUIRE_THROWS_AS(map.at("bar"), fkyaml::Exception); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_ConstAtTest", "[OrderedMapClassTest]") | ||
{ | ||
const fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE_THROWS_AS(map.at("foo"), fkyaml::Exception); | ||
fkyaml::OrderedMap<std::string, bool> map_ = map; | ||
map_.emplace("foo", true); | ||
const fkyaml::OrderedMap<std::string, bool> map__ = map_; | ||
REQUIRE_NOTHROW(map__.at("foo")); | ||
REQUIRE(map__.at("foo") == true); | ||
REQUIRE_THROWS_AS(map.at("bar"), fkyaml::Exception); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_NonConstFindTest", "[OrderedMapClassTest]") | ||
{ | ||
fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE(map.find("foo") == map.end()); | ||
map.emplace("foo", true); | ||
REQUIRE(map.find("foo") != map.end()); | ||
REQUIRE(map.find("foo")->first == "foo"); | ||
REQUIRE(map.find("foo")->second == true); | ||
REQUIRE(map.find("bar") == map.end()); | ||
} | ||
|
||
TEST_CASE("OrderedMapClassTest_ConstFindTest", "[OrderedMapClassTest]") | ||
{ | ||
const fkyaml::OrderedMap<std::string, bool> map; | ||
REQUIRE(map.find("foo") == map.end()); | ||
fkyaml::OrderedMap<std::string, bool> map_ = map; | ||
map_.emplace("foo", true); | ||
const fkyaml::OrderedMap<std::string, bool> map__ = map_; | ||
REQUIRE(map__.find("foo") != map__.end()); | ||
REQUIRE(map__.find("foo")->first == "foo"); | ||
REQUIRE(map__.find("foo")->second == true); | ||
REQUIRE(map__.find("bar") == map__.end()); | ||
} |
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