From d247b77a1ead9f55df938d6abaecdaff2c68c9c8 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Mon, 31 Jan 2022 12:22:00 +0000 Subject: Move stdalgo::map::difference to its own utility header. --- include/utility/map.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 include/utility/map.h (limited to 'include/utility') diff --git a/include/utility/map.h b/include/utility/map.h new file mode 100644 index 000000000..efbca18b8 --- /dev/null +++ b/include/utility/map.h @@ -0,0 +1,84 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2021 Sadie Powell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#pragma once + + +namespace insp::map +{ + /** Compares two maps and returns a list of the differences. + * @param first The first map to compare. + * @param second The second map to compare. + * @param out The map to store the differences in. + */ + template typename Map> + void difference(const Map& first, const Map& second, + Map, std::optional>, Compare>& out) + { + auto fiter = first.cbegin(); + auto siter = second.cbegin(); + + while (fiter != first.end()) + { + if (siter == second.end()) + { + // Store the remaining from the first. + while (fiter != first.end()) + { + out[fiter->first] = { fiter->second, std::nullopt }; + fiter++; + } + return; + } + + if (fiter->first < siter->first) + { + // The key in first is not in second. + out[fiter->first] = { fiter->second, std::nullopt }; + fiter++; + } + else if (siter->first < fiter->first) + { + // The key in second is not in first. + out[siter->first] = { std::nullopt, siter->second }; + siter++; + } + else if (fiter->second != siter->second) + { + // The key exists in both but the value differs. + out[fiter->first] = { fiter->second, siter->second }; + fiter++; + siter++; + } + else + { + // The key/value is identical in both. + fiter++; + siter++; + } + } + + // Store the remaining from the second. + while (siter != second.end()) + { + out[siter->first] = { std::nullopt, siter->second }; + siter++; + } + } +} -- cgit v1.3.1-10-gc9f91