Petr Onderka has submitted this change and it was merged. Change subject: Handle IPv6 addresses that use :: ......................................................................
Handle IPv6 addresses that use :: Change-Id: Ie070eff3783e7ad1f2db9824f2194c5667accde8 --- M CollectionHelpers.h M Objects/IpV6User.cpp M Objects/IpV6User.h M Objects/User.cpp M Objects/User.h M StringHelpers.cpp M StringHelpers.h 7 files changed, 81 insertions(+), 42 deletions(-) Approvals: Petr Onderka: Verified; Looks good to me, approved diff --git a/CollectionHelpers.h b/CollectionHelpers.h index b9abde6..55b443b 100644 --- a/CollectionHelpers.h +++ b/CollectionHelpers.h @@ -50,6 +50,12 @@ return result; } +template <typename TContainer, typename TValue> +auto find(const TContainer& container, const TValue& value) -> decltype(container.begin()) +{ + return std::find(container.begin(), container.end(), value); +} + void set(std::vector<bool> &vector, std::size_t index); void unset(std::vector<bool> &vector, std::size_t index); diff --git a/Objects/IpV6User.cpp b/Objects/IpV6User.cpp index cc3c0b7..4cc32b8 100644 --- a/Objects/IpV6User.cpp +++ b/Objects/IpV6User.cpp @@ -1,37 +1,68 @@ #include "IpV6User.h" #include <sstream> #include "../StringHelpers.h" +#include "../CollectionHelpers.h" #include "../DumpException.h" #include "Revision.h" -using std::stoi; -using std::ostringstream; - -std::array<uint16_t, 8> IpV6User::TryParseAddress(string address, bool &success) +bool expandEmptyGroup(std::vector<std::string>& groups) { - success = false; + if (groups.size() < 3) + return false; - std::vector<std::string> stringParts = split(address, ':'); - if (stringParts.size() != 8) - return std::array<uint16_t, 8>(); + if (groups.at(0).empty()) + { + if (groups.at(1).empty()) + groups.erase(groups.begin()); + else + return false; + } - std::array<uint16_t, 8> result; + if (groups.rbegin()->empty()) + { + if ((groups.rbegin() + 1)->empty()) + groups.pop_back(); + else + return false; + } + + auto emptyGroupIter = find(groups, std::string()); + + if (emptyGroupIter != groups.end()) + { + auto insertIter = groups.erase(emptyGroupIter); + + groups.insert(insertIter, 8 - groups.size(), "0"); + } + + return true; +} + +std::array<std::uint16_t, 8> IpV6User::TryParseAddress(const std::string& address, bool &success) +{ + std::vector<std::string> groups = split(address, ':'); + + success = expandEmptyGroup(groups); + if (!success || groups.size() != 8) + return std::array<std::uint16_t, 8>(); + + std::array<std::uint16_t, 8> result; for (int i = 0; i < 8; i++) { bool success; - long intPart = tryParseLong(stringParts.at(i), success, 16); - if (!success || intPart > 0xFFFF || intPart < 0) - return std::array<uint16_t, 8>(); + long intGroup = tryParseLong(groups.at(i), success, 16); + if (!success || intGroup > 0xFFFF || intGroup < 0) + return std::array<std::uint16_t, 8>(); - result.at(i) = intPart; + result.at(i) = intGroup; } success = true; return result; } -std::array<uint16_t, 8> IpV6User::ParseAddress(string address) +std::array<std::uint16_t, 8> IpV6User::ParseAddress(const std::string& address) { bool success; auto result = TryParseAddress(address, success); @@ -42,9 +73,9 @@ return result; } -string IpV6User::AddressToString(std::array<uint16_t, 8> address) +std::string IpV6User::AddressToString(std::array<std::uint16_t, 8> address) { - ostringstream s; + std::ostringstream s; s << std::hex << std::uppercase; @@ -59,12 +90,12 @@ return s.str(); } -IpV6User::IpV6User(string stringAddress) +IpV6User::IpV6User(const std::string& stringAddress) : User(0, stringAddress), Address(ParseAddress(stringAddress)) { } -IpV6User::IpV6User(string stringAddress, std::array<uint16_t, 8> parsedAddress) +IpV6User::IpV6User(const std::string& stringAddress, std::array<uint16_t, 8> parsedAddress) : User(0, stringAddress), Address(parsedAddress) {} diff --git a/Objects/IpV6User.h b/Objects/IpV6User.h index bee5128..1e5090a 100644 --- a/Objects/IpV6User.h +++ b/Objects/IpV6User.h @@ -7,15 +7,15 @@ class IpV6User : public User { public: - static std::array<uint16_t, 8> TryParseAddress(string address, bool &success); - static std::array<uint16_t, 8> ParseAddress(string address); - static string AddressToString(std::array<uint16_t, 8> address); + static std::array<std::uint16_t, 8> TryParseAddress(const std::string& address, bool &success); + static std::array<std::uint16_t, 8> ParseAddress(const std::string& address); + static std::string AddressToString(std::array<std::uint16_t, 8> address); - IpV6User(string stringAddress); - IpV6User(string stringAddress, std::array<uint16_t, 8> parsedAddress); - IpV6User(std::array<uint16_t, 8> parsedAddress); + IpV6User(const std::string& stringAddress); + IpV6User(const std::string& stringAddress, std::array<std::uint16_t, 8> parsedAddress); + IpV6User(std::array<std::uint16_t, 8> parsedAddress); - std::array<uint16_t, 8> Address; + std::array<std::uint16_t, 8> Address; virtual bool Equals(const User &second) const OVERRIDE; diff --git a/Objects/User.cpp b/Objects/User.cpp index 3ae80ed..36e7dd8 100644 --- a/Objects/User.cpp +++ b/Objects/User.cpp @@ -4,21 +4,21 @@ #include "NamedUser.h" #include "../DumpException.h" -unique_ptr<User> TryCreateFromIp(string ipAddress, bool &success) +std::unique_ptr<User> TryCreateFromIp(const std::string& ipAddress, bool &success) { - uint32_t ipV4 = IpV4User::TryParseAddress(ipAddress, success); + std::uint32_t ipV4 = IpV4User::TryParseAddress(ipAddress, success); if (success) - return unique_ptr<User>(new IpV4User(ipAddress, ipV4)); + return std::unique_ptr<User>(new IpV4User(ipAddress, ipV4)); auto ipV6 = IpV6User::TryParseAddress(ipAddress, success); if (success) - return unique_ptr<User>(new IpV6User(ipAddress, ipV6)); + return std::unique_ptr<User>(new IpV6User(ipAddress, ipV6)); success = false; return nullptr; } -unique_ptr<User> User::Create(uint32_t userId, string userName) +std::unique_ptr<User> User::Create(std::uint32_t userId, const std::string& userName) { if (userId == 0) { @@ -30,10 +30,10 @@ return ipUser; } - return unique_ptr<User>(new NamedUser(userId, userName)); + return std::unique_ptr<User>(new NamedUser(userId, userName)); } -unique_ptr<User> User::CreateFromIp(string ipAddress) +std::unique_ptr<User> User::CreateFromIp(const std::string& ipAddress) { bool success; @@ -45,7 +45,7 @@ return ipUser; } -User::User(uint32_t userId, string userName) +User::User(std::uint32_t userId, const std::string& userName) : UserId(userId), UserName(userName) {} diff --git a/Objects/User.h b/Objects/User.h index 9cc5115..b5007ec 100644 --- a/Objects/User.h +++ b/Objects/User.h @@ -4,8 +4,6 @@ #include <memory> #include <string> -using std::uint32_t; -using std::unique_ptr; using std::string; enum class RevisionFlags : uint8_t; @@ -13,14 +11,14 @@ class User { protected: - User(uint32_t userId, string userName); + User(std::uint32_t userId, const std::string& userName); public: - static unique_ptr<User> Create(uint32_t userId, string userName); + static std::unique_ptr<User> Create(std::uint32_t userId, const std::string& userName); // creates IPv4 or IPv6 anonymous users - static unique_ptr<User> CreateFromIp(string ipAddress); + static std::unique_ptr<User> CreateFromIp(const std::string& ipAddress); - uint32_t UserId; - string UserName; + std::uint32_t UserId; + std::string UserName; virtual bool Equals(const User &second) const = 0; diff --git a/StringHelpers.cpp b/StringHelpers.cpp index d960735..3995c38 100644 --- a/StringHelpers.cpp +++ b/StringHelpers.cpp @@ -2,8 +2,12 @@ #include <sstream> // http://stackoverflow.com/a/236803/41071 -std::vector<std::string> split(const std::string &s, char delim) +std::vector<std::string> split(std::string s, char delim) { + // getline() treats delim as terminator, not separator, this fixes that + if (s.back() == delim) + s.push_back(delim); + std::vector<std::string> elems; std::stringstream ss(s); std::string item; diff --git a/StringHelpers.h b/StringHelpers.h index 83b7bb5..877b58c 100644 --- a/StringHelpers.h +++ b/StringHelpers.h @@ -3,7 +3,7 @@ #include <string> #include <vector> -std::vector<std::string> split(const std::string &s, char delim); +std::vector<std::string> split(std::string s, char delim); // makes sure the whole string is converted to an int long tryParseLong(const std::string &s, bool &success, int radix = 10); \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/84530 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ie070eff3783e7ad1f2db9824f2194c5667accde8 Gerrit-PatchSet: 2 Gerrit-Project: operations/dumps/incremental Gerrit-Branch: gsoc Gerrit-Owner: Petr Onderka <gsv...@gmail.com> Gerrit-Reviewer: Petr Onderka <gsv...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits