ChargeSocketsHelper: implement a Diff method between old and new OSM keys

Signed-off-by: Séverin Lemaignan <severin@guakamole.org>
This commit is contained in:
Séverin Lemaignan
2025-10-02 00:19:20 +02:00
committed by x7z4w
parent 340b5ae3f9
commit 509ff4de72
4 changed files with 104 additions and 0 deletions

View File

@@ -47,6 +47,8 @@ std::string DebugPrint(char32_t * t) = delete;
template <typename U, typename V> template <typename U, typename V>
inline std::string DebugPrint(std::pair<U, V> const & p); inline std::string DebugPrint(std::pair<U, V> const & p);
template <typename U, typename V, typename W>
inline std::string DebugPrint(std::tuple<U, V, W> const & p);
template <typename T> template <typename T>
inline std::string DebugPrint(std::list<T> const & v); inline std::string DebugPrint(std::list<T> const & v);
template <typename T> template <typename T>
@@ -136,6 +138,14 @@ std::string DebugPrint(std::pair<U, V> const & p)
return out.str(); return out.str();
} }
template <typename U, typename V, typename W>
std::string DebugPrint(std::tuple<U, V, W> const & p)
{
std::ostringstream out;
out << "(" << DebugPrint(get<0>(p)) << ", " << DebugPrint(get<1>(p)) << ", " << DebugPrint(get<2>(p)) << ")";
return out.str();
}
template <typename IterT> template <typename IterT>
std::string DebugPrintSequence(IterT beg, IterT end) std::string DebugPrintSequence(IterT beg, IterT end)
{ {

View File

@@ -395,6 +395,35 @@ OSMKeyValues ChargeSocketsHelper::GetOSMKeyValues()
return result; return result;
} }
KeyValueDiffSet ChargeSocketsHelper::Diff(ChargeSocketDescriptors const & oldSockets)
{
KeyValueDiffSet result;
auto oldKeys = ChargeSocketsHelper(oldSockets).GetOSMKeyValues();
auto newKeys = GetOSMKeyValues();
std::unordered_map<std::string, std::string> oldMap, newMap;
for (auto && [k, v] : oldKeys)
oldMap.emplace(k, v);
for (auto && [k, v] : newKeys)
newMap.emplace(k, v);
// Handle keys that exist in old
for (auto && [k, oldVal] : oldMap)
if (auto it = newMap.find(k); it == newMap.end())
result.insert({k, oldVal, ""}); // deleted
else if (it->second != oldVal)
result.insert({k, oldVal, it->second}); // updated
// Handle keys that are only new
for (auto && [k, newVal] : newMap)
if (!oldMap.contains(k))
result.insert({k, "", newVal}); // created
return result;
}
void ChargeSocketsHelper::Sort() void ChargeSocketsHelper::Sort()
{ {
size_t const unknownTypeOrder = SUPPORTED_TYPES.size(); size_t const unknownTypeOrder = SUPPORTED_TYPES.size();

View File

@@ -1,7 +1,9 @@
#pragma once #pragma once
#include <array> #include <array>
#include <set>
#include <string> #include <string>
#include <tuple>
#include <utility> // for std::pair #include <utility> // for std::pair
#include <vector> #include <vector>
@@ -19,11 +21,15 @@ typedef std::vector<ChargeSocketDescriptor> ChargeSocketDescriptors;
typedef std::vector<std::pair<std::string, std::string>> OSMKeyValues; typedef std::vector<std::pair<std::string, std::string>> OSMKeyValues;
typedef std::set<std::tuple<std::string, std::string, std::string>> KeyValueDiffSet;
class ChargeSocketsHelper class ChargeSocketsHelper
{ {
public: public:
ChargeSocketsHelper() : m_dirty(false) {} ChargeSocketsHelper() : m_dirty(false) {}
ChargeSocketsHelper(ChargeSocketDescriptors const & sockets) : m_chargeSockets(sockets), m_dirty(true) {}
/** Create a ChareSocketsHelper instance from an existing list of sockets /** Create a ChareSocketsHelper instance from an existing list of sockets
* stored as "<type>|<nb>|[<power>];..." * stored as "<type>|<nb>|[<power>];..."
* *
@@ -91,6 +97,19 @@ public:
"mcs", "type2_combo", "chademo", "nacs", "type1", "gb_dc", "mcs", "type2_combo", "chademo", "nacs", "type1", "gb_dc",
"chaoji", "type3c", "type2_cable", "type2", "gb_ac", "type3a"}; "chaoji", "type3c", "type2_cable", "type2", "gb_ac", "type3a"};
/** Return a list of OSM attributes that have changed between the current
* list of sockets and the provided old list.
*
* Returns a set of (key, old_value, new_value) tuples.
*
* If old_value="", the attribute is new (ie has been created)
* If new_value="", the attribute has been deleted
*
* Note that this method is not const as it may trigger a re-ordering of the
* internal list of sockets.
*/
KeyValueDiffSet Diff(ChargeSocketDescriptors const & oldSockets);
protected: protected:
ChargeSocketDescriptors m_chargeSockets; ChargeSocketDescriptors m_chargeSockets;

View File

@@ -203,6 +203,52 @@ UNIT_TEST(ChargeSockets_Processing)
TEST_EQUAL( TEST_EQUAL(
ChargeSocketsHelper("type2|3|43;type2|5|7.4;type2_combo|10|250;type2|2|50;type2_combo|2|100").GetOSMKeyValues(), ChargeSocketsHelper("type2|3|43;type2|5|7.4;type2_combo|10|250;type2|2|50;type2_combo|2|100").GetOSMKeyValues(),
kvs, ()); kvs, ());
///////////////////////////////////////////////////////////
// OSM attribute diff
OSMKeyValues kvs_old, kvs_new;
KeyValueDiffSet diff;
kvs_old = {{"socket:type2", "2"}};
kvs_new = {{"socket:type2", "2"}};
diff = {};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
kvs_old = {{"socket:type2", "3"}};
kvs_new = {{"socket:type2", "2"}};
diff = {{"socket:type2", "3", "2"}};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
kvs_old = {{"socket:type2", "2"}};
kvs_new = {{"socket:type2", "3"}};
diff = {{"socket:type2", "2", "3"}};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
kvs_old = {};
kvs_new = {{"socket:type2", "2"}};
diff = {{"socket:type2", "", "2"}};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
kvs_old = {{"socket:type2", "2"}};
kvs_new = {};
diff = {{"socket:type2", "2", ""}};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
kvs_old = {{"socket:type2_combo", "10;2"},
{"socket:type2_combo:output", "250;100"},
{"socket:type1", "5"},
{"socket:type2", "2;3;5"},
{"socket:type2:output", "50;43;7.4"}};
kvs_new = {{"socket:type2_combo", "10;2"},
{"socket:type2_combo:output", "250;100"},
{"socket:chademo", "2"},
{"socket:type2", "2;3"},
{"socket:type2:output", "50;43"}};
diff = {{"socket:type1", "5", ""},
{"socket:type2", "2;3;5", "2;3"},
{"socket:type2:output", "50;43;7.4", "50;43"},
{"socket:chademo", "", "2"}};
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
} }
} // namespace feature_charge_sockets_test } // namespace feature_charge_sockets_test