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

Reply via email to