diff --git a/CrowLeer.sln b/CrowLeer.sln
index 630a5e4..910e145 100644
--- a/CrowLeer.sln
+++ b/CrowLeer.sln
@@ -1,26 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.15
+VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CrowLeer", "CrowLeer\CrowLeer.vcxproj", "{A886CD9F-F24D-41A1-9E82-870548A0B2B8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
Release|x64 = Release|x64
- Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Debug|x64.ActiveCfg = Debug|x64
{A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Debug|x64.Build.0 = Debug|x64
- {A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Debug|x86.ActiveCfg = Debug|Win32
- {A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Debug|x86.Build.0 = Debug|Win32
{A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Release|x64.ActiveCfg = Release|x64
{A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Release|x64.Build.0 = Release|x64
- {A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Release|x86.ActiveCfg = Release|Win32
- {A886CD9F-F24D-41A1-9E82-870548A0B2B8}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/CrowLeer/CrowLeer.vcxproj b/CrowLeer/CrowLeer.vcxproj
index 826614a..0a3fda6 100644
--- a/CrowLeer/CrowLeer.vcxproj
+++ b/CrowLeer/CrowLeer.vcxproj
@@ -72,28 +72,43 @@
- D:\git\CrowLeer\CrowLeer\curl;$(IncludePath)
- D:\git\CrowLeer\CrowLeer\curl;$(LibraryPath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib;D:\git\CrowLeer\CrowLeer\curl;$(IncludePath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib;D:\git\CrowLeer\CrowLeer\curl;$(LibraryPath)
- D:\git\CrowLeer\CrowLeer\curl;$(IncludePath)
- D:\git\CrowLeer\CrowLeer\curl;$(LibraryPath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib;D:\git\CrowLeer\CrowLeer\curl;$(IncludePath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib;D:\git\CrowLeer\CrowLeer\curl;$(LibraryPath)
+
+
+ D:\git\CrowLeer\CrowLeer\cpp-netlib86;D:\git\CrowLeer\CrowLeer\curl86;$(IncludePath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib86;D:\git\CrowLeer\CrowLeer\curl86;$(LibraryPath)
+
+
+ D:\git\CrowLeer\CrowLeer\cpp-netlib86;D:\git\CrowLeer\CrowLeer\curl86;$(IncludePath)
+ D:\git\CrowLeer\CrowLeer\cpp-netlib86;D:\git\CrowLeer\CrowLeer\curl86;$(LibraryPath)
Level3
Disabled
true
+ MultiThreadedDebug
+
+ libcurl_a_debug.lib;network-urid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
Level3
Disabled
true
- MultiThreadedDebugDLL
+ MultiThreadedDebug
_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+ libcurl_a_debug.lib;network-urid.lib;%(AdditionalDependencies)
+
@@ -102,10 +117,12 @@
true
true
true
+ MultiThreaded
true
true
+ libcurl_a_debug.lib;network-urid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
@@ -115,12 +132,13 @@
true
true
true
- MultiThreadedDLL
+ MultiThreaded
_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
true
+ libcurl_a.lib;network-uri.lib;%(AdditionalDependencies)
diff --git a/CrowLeer/CrowLeer.vcxproj.filters b/CrowLeer/CrowLeer.vcxproj.filters
index e3788eb..c07b341 100644
--- a/CrowLeer/CrowLeer.vcxproj.filters
+++ b/CrowLeer/CrowLeer.vcxproj.filters
@@ -21,20 +21,17 @@
Source Files
-
- Source Files
-
Source Files
Source Files
+
+ Source Files
+
-
- Header Files
-
Header Files
@@ -50,6 +47,9 @@
Header Files
+
+ Header Files
+
diff --git a/CrowLeer/cpp-netlib/LICENSE_1_0.txt b/CrowLeer/cpp-netlib/LICENSE_1_0.txt
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/CrowLeer/cpp-netlib/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/CrowLeer/cpp-netlib/network-uri.lib b/CrowLeer/cpp-netlib/network-uri.lib
new file mode 100644
index 0000000..ad5f546
Binary files /dev/null and b/CrowLeer/cpp-netlib/network-uri.lib differ
diff --git a/CrowLeer/cpp-netlib/network-urid.lib b/CrowLeer/cpp-netlib/network-urid.lib
new file mode 100644
index 0000000..6d6bd9b
Binary files /dev/null and b/CrowLeer/cpp-netlib/network-urid.lib differ
diff --git a/CrowLeer/cpp-netlib/network/optional.hpp b/CrowLeer/cpp-netlib/network/optional.hpp
new file mode 100644
index 0000000..43b1cf1
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/optional.hpp
@@ -0,0 +1,711 @@
+// Copyright 2016 Glyn Matthews.
+// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Contains an implementation of C++17 optional (n3793).
+ *
+ * \sa https://github.com/akrzemi1/Optional
+ * \sa http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html
+ */
+
+#ifndef NETWORK_OPTIONAL_INC
+#define NETWORK_OPTIONAL_INC
+
+#include
+#include
+#include
+#include
+#include
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#ifdef NDEBUG
+#define NETWORK_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+#define NETWORK_ASSERTED_EXPRESSION(CHECK, EXPR) \
+ ((CHECK) ? (EXPR) : (fail(#CHECK, __FILE__, __LINE__), (EXPR)))
+inline void fail(const char*, const char*, unsigned) {}
+#endif // NDEBUG
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+namespace network {
+/**
+ * \ingroup optional
+ * \class nullopt_t optional.hpp network/uri.hpp
+ * \brief Disengaged state indicator.
+ * \sa optional
+ */
+struct nullopt_t {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ struct init {};
+ constexpr nullopt_t(init) {}
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+};
+
+/**
+ * \ingroup optional
+ * \brief Used to indicate a *disengaged* state for optional objects.
+ */
+constexpr nullopt_t nullopt{nullopt_t::init{}};
+
+/**
+ * \ingroup optional
+ * \class bad_optional_access optional.hpp network/uri.hpp
+ * \brief Exception thrown when the value member function is called when the
+ * optional object is disengaged.
+ */
+class bad_optional_access : public std::logic_error {
+ public:
+
+ /**
+ * \brief Constructor.
+ * \param what_arg The error message.
+ */
+ explicit bad_optional_access(const std::string& what_arg)
+ : std::logic_error(what_arg) {}
+
+ /**
+ * \brief Constructor.
+ * \param what_arg The error message.
+ */
+ explicit bad_optional_access(const char* what_arg)
+ : std::logic_error(what_arg) {}
+};
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+namespace details {
+struct dummy_t {};
+
+template
+union trivially_destructible_optional_storage {
+ static_assert(std::is_trivially_destructible::value, "");
+
+ dummy_t dummy_;
+ T value_;
+
+ constexpr trivially_destructible_optional_storage() : dummy_{} {}
+
+ constexpr trivially_destructible_optional_storage(const T& v) : value_{v} {}
+
+ ~trivially_destructible_optional_storage() = default;
+};
+
+template
+union optional_storage {
+ dummy_t dummy_;
+ T value_;
+
+ constexpr optional_storage() : dummy_{} {}
+
+ constexpr optional_storage(const T& v) : value_{v} {}
+
+ ~optional_storage() {}
+};
+
+template
+class trivially_destructible_optional_base {
+public:
+ typedef T value_type;
+
+ constexpr trivially_destructible_optional_base() noexcept
+ : init_(false),
+ storage_{} {}
+
+ constexpr trivially_destructible_optional_base(const T& v)
+ : init_(true), storage_{v} {}
+
+ constexpr trivially_destructible_optional_base(T&& v)
+ : init_(true), storage_{std::move(v)} {}
+
+ ~trivially_destructible_optional_base() = default;
+
+protected:
+
+ bool init_;
+ optional_storage storage_;
+};
+
+template
+class optional_base {
+public:
+ typedef T value_type;
+
+ constexpr optional_base() noexcept
+ : init_(false),
+ storage_{} {}
+
+ constexpr optional_base(const T& v)
+ : init_(true), storage_{v} {}
+
+ constexpr optional_base(T&& v)
+ : init_(true), storage_{std::move(v)} {}
+
+ ~optional_base() {
+ if (init_) {
+ storage_.value_.T::~T();
+ }
+ }
+
+protected:
+
+ bool init_;
+ optional_storage storage_;
+};
+} // namespace details
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+/**
+ * \ingroup optional
+ * \class optional optional.hpp network/uri.hpp
+ * \brief An implementation of C++17 optional (n3793)
+ */
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+template
+using optional_base = typename std::conditional<
+ std::is_trivially_destructible::value,
+ details::trivially_destructible_optional_base,
+ details::optional_base>::type;
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+template
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+class optional : optional_base {
+#else
+class optional {
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ typedef optional_base base_type;
+
+ public:
+ /**
+ * \brief Optional value type.
+ */
+ typedef T value_type;
+
+ /**
+ * \brief Constructor.
+ * \post *disengaged*.
+ */
+ constexpr optional() : optional_base() {}
+
+ /**
+ * \brief Constructor.
+ * \post *disengaged*.
+ */
+ constexpr optional(nullopt_t) noexcept : optional_base() {}
+
+ /**
+ * \brief Copy constructor.
+ * \param other The other optional object.
+ */
+ optional(const optional& other) {
+ if (other) {
+ ::new(static_cast(ptr())) T(*other);
+ base_type::init_ = true;
+ }
+ }
+
+ /**
+ * \brief Move constructor.
+ * \param other The other optional object.
+ */
+ optional(optional&& other) noexcept {
+ if (other) {
+ ::new(static_cast(ptr())) T(std::move(other.storage_.value_));
+ base_type::init_ = true;
+ }
+ }
+
+ /**
+ * \brief Constructor.
+ * \param value The value with which to initialize the optional object.
+ * \post *engaged*
+ */
+ constexpr optional(const T& value) : optional_base(value) {}
+
+ /**
+ * \brief Constructor.
+ * \param value The value with which to initialize the optional object.
+ * \post *engaged*
+ */
+ constexpr optional(T&& value) : optional_base(std::move(value)) {}
+
+ /**
+ * \brief Assignment operator.
+ * \post *disengaged*.
+ * \returns \c *this.
+ */
+ optional& operator=(nullopt_t) noexcept {
+ if (base_type::init_) {
+ ptr()->T::~T();
+ }
+ base_type::init_ = false;
+ return *this;
+ }
+
+ /**
+ * \brief Copy assignment operator.
+ * \param other The other optional object.
+ * \returns \c *this.
+ */
+ optional& operator=(const optional& other) {
+ if (bool(*this) && !other) {
+ ptr()->T::~T();
+ base_type::init_ = false;
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast(ptr())) T(*other);
+ base_type::init_ = true;
+ }
+ else if (bool(*this) && bool(other)) {
+ base_type::storage_.value_ = *other;
+ }
+ return *this;
+ }
+
+ /**
+ * \brief Move assignment operator.
+ * \param other The other optional object.
+ * \returns \c *this.
+ */
+ optional& operator=(optional&& other) noexcept {
+ if (bool(*this) && !other) {
+ ptr()->T::~T();
+ base_type::init_ = false;
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast(ptr())) T(std::move(*other));
+ base_type::init_ = true;
+ }
+ else if (bool(*this) && bool(other)) {
+ base_type::storage_.value_ = std::move(*other);
+ }
+ return *this;
+ }
+
+ /**
+ * \brief Destructor.
+ */
+ ~optional() = default;
+
+ /**
+ * \brief Swap function.
+ * \param other The other optional object.
+ */
+ void swap(optional& other) noexcept {
+ if (bool(*this) && !other) {
+ ::new(static_cast(other.ptr())) T(std::move(**this));
+ ptr()->T::~T();
+ std::swap(base_type::init_, other.base_type::init_);
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast(ptr())) T(std::move(*other));
+ other.ptr()->T::~T();
+ std::swap(base_type::init_, other.init_);
+ }
+ else if (bool(*this) && bool(other)) {
+ std::swap(**this, *other);
+ }
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ constexpr T const* operator->() const {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), ptr());
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ T* operator->() {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), ptr());
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ constexpr T const& operator*() const {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), base_type::storage_.value_);
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ T& operator*() {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), base_type::storage_.value_);
+ }
+
+ /**
+ * \brief Operator bool overloads.
+ * \returns \c true if the optional is *engaged*, \c false if it is *disengaged*.
+ */
+ constexpr explicit operator bool() const noexcept { return base_type::init_; }
+
+ /**
+ * \returns The underlying optional value, if \c bool(*this).
+ * \throws A bad_optional_access if \c !*this.
+ */
+ constexpr T const& value() const {
+ return *this ? base_type::storage_.value_
+ : (throw bad_optional_access("Uninitialized optional value"),
+ base_type::storage_.value_);
+ }
+ /**
+ * \returns The underlying optional value, if \c bool(*this).
+ * \throws A bad_optional_access if \c !*this.
+ */
+ T& value() {
+ return *this ? base_type::storage_.value_
+ : (throw bad_optional_access("Uninitialized optional value"),
+ base_type::storage_.value_);
+ }
+
+ /**
+ * \returns bool(*this) ? **this : static_cast(std::forward(v)).
+ * \pre \c std::is_copy_constructible::value is \c true and std::is_convertible::value is \c true.
+ */
+ template
+ T value_or(U&& other) const & {
+ static_assert(std::is_copy_constructible::value, "Must be copy constructible.");
+ static_assert(std::is_convertible::value, "U must be convertible to T.");
+ return bool(*this) ? **this : static_cast(std::forward(other));
+ }
+
+ /**
+ * \returns bool(*this) ? std::move(**this) : static_cast(std::forward(v)).
+ * \pre std::is_move_constructible::value is \c true and std::is_convertible::value is \c true.
+ */
+ template
+ T value_or(U&& other) && {
+ static_assert(std::is_copy_constructible::value, "Must be copy constructible.");
+ static_assert(std::is_convertible::value, "U must be convertible to T.");
+ return bool(*this) ? std::move(**this) : static_cast(std::forward(other));
+ }
+
+ private:
+
+ T* ptr() {
+ return std::addressof(base_type::storage_.value_);
+ }
+
+};
+
+/**
+ * \brief Equality operator.
+ */
+template
+bool operator==(const optional& lhs, const optional& rhs) {
+ if (bool(lhs) != bool(rhs)) {
+ return false;
+ } else if (!bool(lhs)) {
+ return true;
+ } else {
+ return *lhs == *rhs;
+ }
+}
+
+/**
+ * \brief Inequality operator.
+ */
+template
+bool operator!=(const optional& lhs, const optional& rhs) {
+ return !(lhs == rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ */
+template
+bool operator<(const optional& lhs, const optional& rhs) {
+ if (!rhs) {
+ return false;
+ } else if (!lhs) {
+ return true;
+ } else {
+ return *lhs < *rhs;
+ }
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns rhs < lhs.
+ */
+template
+bool operator>(const optional& lhs, const optional& rhs) {
+ return rhs < lhs;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(rhs < lhs).
+ */
+template
+bool operator<=(const optional& lhs, const optional& rhs) {
+ return !(rhs < lhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(rhs > lhs).
+ */
+template
+bool operator>=(const optional& lhs, const optional& rhs) {
+ return !(lhs < rhs);
+}
+
+/**
+ * \brief Equality operator.
+ * \returns \c !x.
+ */
+template
+bool operator==(const optional& x, nullopt_t) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns \c !x.
+ */
+template
+bool operator==(nullopt_t, const optional& x) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns \c bool(x).
+ */
+template
+bool operator!=(const optional& x, nullopt_t) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns \c bool(x).
+ */
+template
+bool operator!=(nullopt_t, const optional& x) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c false.
+ */
+template
+bool operator<(const optional& x, nullopt_t) noexcept {
+ return false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c bool(x).
+ */
+template
+bool operator<(nullopt_t, const optional& x) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c !x.
+ */
+template
+bool operator<=(const optional& x, nullopt_t) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c true.
+ */
+template
+bool operator<=(nullopt_t, const optional& x) noexcept {
+ return true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c bool(x).
+ */
+template
+bool operator>(const optional& x, nullopt_t) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c false.
+ */
+template
+bool operator>(nullopt_t, const optional& x) noexcept {
+ return false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c true.
+ */
+template
+bool operator>=(const optional& x, nullopt_t) noexcept {
+ return true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c !x.
+ */
+template
+bool operator>=(nullopt_t, const optional& x) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns bool(x) ? *x == v : false.
+ */
+template
+bool operator==(const optional& x, const T& v) {
+ return bool(x) ? *x == v : false;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns bool(x) ? v == *x : false.
+ */
+template
+bool operator==(const T& v, const optional& x) {
+ return bool(x) ? v == *x : false;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns bool(x) ? !(*x == v) : true.
+ */
+template
+bool operator!=(const optional& x, const T& v) {
+ return bool(x) ? !(*x == v) : true;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns bool(x) ? !(v == *x) : true.
+ */
+template
+bool operator!=(const T& v, const optional& x) {
+ return bool(x) ? !(v == *x) : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns bool(x) ? *x < v : true.
+ */
+template
+bool operator<(const optional& x, const T& v) {
+ return bool(x) ? *x < v : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns bool(x) ? v < *x : false.
+ */
+template
+bool operator<(const T& v, const optional& x) {
+ return bool(x) ? v < *x : false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns bool(x) ? *x < v : true.
+ */
+template
+bool operator>(const optional& x, const T& v) {
+ return bool(x) ? *x < v : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns bool(x) ? v < *x : false.
+ */
+template
+bool operator>(const T& v, const optional& x) {
+ return bool(x) ? v < *x : false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(x < v).
+ */
+template
+bool operator>=(const optional& x, const T& v) {
+ return !(x < v);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(v < x).
+ */
+template
+bool operator>=(const T& v, const optional& x) {
+ return !(v < x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(x > v).
+ */
+template
+bool operator<=(const optional& x, const T& v) {
+ return !(x > v);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(v > x).
+ */
+template
+bool operator<=(const T& v, const optional& x) {
+ return !(v > x);
+}
+
+/**
+ * \ingroup optional
+ * \brief Swap function.
+ * \param lhs The first optional object.
+ * \param rhs The second optional object.
+ *
+ * Calls:
+ * \code{.cpp}
+ * lhs.swap(rhs);
+ * \endcode
+ */
+template
+inline void swap(optional& lhs,
+ optional& rhs) noexcept(noexcept(lhs.swap(rhs))) {
+ return lhs.swap(rhs);
+}
+
+/**
+ * \ingroup optional
+ * \brief A helper function to contruct an optional object.
+ * \returns optional::type>(std::forward(value)).
+ */
+template
+inline constexpr optional::type> make_optional(T&& value) {
+ return optional::type>(std::forward(value));
+}
+} // namespace network
+
+#endif // NETWORK_OPTIONAL_INC
diff --git a/CrowLeer/cpp-netlib/network/string_view.hpp b/CrowLeer/cpp-netlib/network/string_view.hpp
new file mode 100644
index 0000000..cce9029
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/string_view.hpp
@@ -0,0 +1,268 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_STRING_VIEW_INC
+#define NETWORK_STRING_VIEW_INC
+
+/**
+ * \file
+ * \brief Contains an implementation of C++17 string_view (n3921).
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+namespace network {
+/**
+ * \class basic_string_view string_view.hpp network/uri/string_view.hpp
+ * \brief An implementation of C++17 string_view (n3921)
+ */
+template >
+class basic_string_view {
+ public:
+ typedef traits traits_type;
+ typedef charT value_type;
+ typedef charT* pointer;
+ typedef const charT* const_pointer;
+ typedef charT& reference;
+ typedef const charT& const_reference;
+ typedef const charT* const_iterator;
+ typedef const_iterator iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+ typedef const_reverse_iterator reverse_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ static constexpr size_type npos = size_type(-1);
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
+
+ /**
+ * \brief Copy constructor.
+ */
+ constexpr basic_string_view(const basic_string_view&) noexcept = default;
+
+ /**
+ * \brief Assignment operator.
+ */
+ basic_string_view& operator=(const basic_string_view&) noexcept = default;
+
+ /**
+ * \brief Constructor.
+ */
+ template
+ basic_string_view(
+ const std::basic_string& str) noexcept
+ : data_(str.data()),
+ size_(str.size()) {}
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view(const charT* str)
+ : data_(str), size_(traits::length(str)) {}
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view(const charT* str, size_type len)
+ : data_(str), size_(len) {}
+
+ constexpr const_iterator begin() const noexcept { return data_; }
+
+ constexpr const_iterator end() const noexcept { return data_ + size_; }
+
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ const_reverse_iterator rbegin() const noexcept {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ constexpr size_type size() const noexcept { return size_; }
+
+ constexpr size_type length() const noexcept { return size_; }
+
+ constexpr size_type max_size() const noexcept { return size_; }
+
+ constexpr bool empty() const noexcept { return size_ == 0; }
+
+ constexpr const_reference operator[](size_type pos) const {
+ return data_[pos];
+ }
+
+ const_reference at(size_type pos) const {
+ if (pos >= size_) {
+ throw std::out_of_range("Index out of range.");
+ }
+ return data_[pos];
+ }
+
+ const_reference front() const { return *begin(); }
+
+ const_reference back() const {
+ auto last = (end()) - 1;
+ return *last;
+ }
+
+ constexpr const_pointer data() const noexcept { return data_; }
+
+ void clear() noexcept {
+ data_ = nullptr;
+ size_ = 0;
+ }
+
+ void remove_prefix(size_type n) {
+ data_ += n;
+ size_ -= n;
+ }
+
+ void remove_suffix(size_type n) { size_ -= n; }
+
+ void swap(basic_string_view& s) noexcept {
+ std::swap(data_, s.data_);
+ std::swap(size_, s.size_);
+ }
+
+ template
+ explicit operator std::basic_string() const {
+ return to_string();
+ }
+
+ template >
+ std::basic_string to_string(
+ const Allocator& a = Allocator()) const {
+ return std::basic_string(begin(), end(), a);
+ }
+
+ size_type copy(charT* s, size_type n, size_type pos = 0) const {
+ size_type rlen = std::min(n, size() - pos);
+ std::copy_n(begin() + pos, rlen, s);
+ return rlen;
+ }
+
+ constexpr basic_string_view substr(size_type pos = 0,
+ size_type n = npos) const {
+ return basic_string_view(data() + pos, std::min(n, size() - pos));
+ }
+
+ constexpr int compare(basic_string_view s) const noexcept {
+ return traits::compare(data(), s.data(), std::min(size(), s.size()));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1,
+ basic_string_view s) const {
+ return substr(pos1, n1).compare(s);
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, basic_string_view s,
+ size_type pos2, size_type n2) const {
+ return substr(pos1, n1).compare(s.substr(pos2, n2));
+ }
+
+ constexpr int compare(const charT* s) const {
+ return compare(basic_string_view(s));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, const charT* s) const {
+ return substr(pos1, n1).compare(basic_string_view(s));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, const charT* s,
+ size_type n2) const {
+ return substr(pos1, n1).compare(basic_string_view(s, n2));
+ }
+
+ private:
+ const_pointer data_;
+ size_type size_;
+};
+
+/**
+ * \brief Equality operator.
+ * \returns lhs.compare(rhs) == 0.
+ */
+template
+constexpr bool operator==(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return lhs.compare(rhs) == 0;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns !(lhs == rhs).
+ */
+template
+constexpr bool operator!=(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return !(lhs == rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns lhs.compare(rhs) < 0.
+ */
+template
+constexpr bool operator<(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return lhs.compare(rhs) < 0;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns rhs < lhs.
+ */
+template
+constexpr bool operator>(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return rhs < lhs;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(lhs > rhs).
+ */
+template
+constexpr bool operator<=(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return !(lhs > rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns !(lhs < rhs).
+ */
+template
+constexpr bool operator>=(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return !(lhs < rhs);
+}
+
+/**
+ * \brief Output stream operator.
+ */
+template
+std::basic_ostream& operator<<(
+ std::basic_ostream& os,
+ basic_string_view str) {
+ return os << str.to_string();
+}
+
+typedef basic_string_view string_view;
+} // namespace network
+
+#endif // NETWORK_STRING_VIEW_INC
diff --git a/CrowLeer/cpp-netlib/network/uri.hpp b/CrowLeer/cpp-netlib/network/uri.hpp
new file mode 100644
index 0000000..f3d86e0
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri.hpp
@@ -0,0 +1,38 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Copyright 2012 Dean Michael Berris
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_HPP
+#define NETWORK_URI_HPP
+
+/**
+ * \defgroup uri URI
+ *
+ * This module contains a class encapsulating a URI, a URI builder and
+ * percent encoding and decoding functions.
+ *
+ * \defgroup optional Optional
+ *
+ * This module contains a utility to represent optional values.
+ *
+ * \defgroup string String
+ *
+ * This module contains a class for a non-owning reference to a string.
+ *
+ * \namespace network
+ *
+ * The \c network namespace contains all the classes and functions for
+ * the URI in this library.
+ *
+ * \file
+ * \brief Contains the uri, uri_builder classes and functions
+ * for percent encoding and decoding.
+ */
+
+#include
+#include
+
+#endif // NETWORK_URI_HPP
diff --git a/CrowLeer/cpp-netlib/network/uri/config.hpp b/CrowLeer/cpp-netlib/network/uri/config.hpp
new file mode 100644
index 0000000..39c3b58
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/config.hpp
@@ -0,0 +1,20 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Copyright 2012 Dean Michael Berris
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Contains macros to configure compiler or platform-specific workarounds.
+ */
+
+#ifndef NETWORK_URI_CONFIG_INC
+#define NETWORK_URI_CONFIG_INC
+
+#ifdef _MSC_VER
+#define NETWORK_URI_MSVC _MSC_VER
+#endif // _MSC_VER
+
+#endif // NETWORK_URI_CONFIG_INC
diff --git a/CrowLeer/cpp-netlib/network/uri/detail/decode.hpp b/CrowLeer/cpp-netlib/network/uri/detail/decode.hpp
new file mode 100644
index 0000000..4e92bb7
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/detail/decode.hpp
@@ -0,0 +1,82 @@
+// Copyright (c) Glyn Matthews 2011-2016.
+// Copyright 2012 Dean Michael Berris
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_DECODE_INC
+#define NETWORK_URI_DECODE_INC
+
+#include
+#include
+#include
+
+namespace network {
+namespace detail {
+template
+CharT letter_to_hex(CharT in) {
+ if ((in >= '0') && (in <= '9')) {
+ return in - '0';
+ }
+
+ if ((in >= 'a') && (in <= 'f')) {
+ return in + 10 - 'a';
+ }
+
+ if ((in >= 'A') && (in <= 'F')) {
+ return in + 10 - 'A';
+ }
+
+ throw percent_decoding_error(uri_error::non_hex_input);
+}
+
+template
+InputIterator decode_char(InputIterator it, charT *out) {
+ assert(*it == '%');
+ ++it;
+ auto h0 = *it;
+ auto v0 = detail::letter_to_hex(h0);
+ ++it;
+ auto h1 = *it;
+ auto v1 = detail::letter_to_hex(h1);
+ if (h0 >= '8') {
+ // unable to decode characters outside the ASCII character set.
+ throw percent_decoding_error(uri_error::conversion_failed);
+ }
+ ++it;
+ *out = static_cast((0x10 * v0) + v1);
+ return it;
+}
+
+template
+OutputIterator decode(InputIterator in_begin, InputIterator in_end,
+ OutputIterator out_begin) {
+ auto it = in_begin;
+ auto out = out_begin;
+ while (it != in_end) {
+ if (*it == '%') {
+ if (std::distance(it, in_end) < 3) {
+ throw percent_decoding_error(uri_error::not_enough_input);
+ }
+ char c = '\0';
+ it = decode_char(it, &c);
+ out = c;
+ ++out;
+ } else {
+ *out++ = *it++;
+ }
+ }
+ return out;
+}
+
+template
+String decode(const String &source) {
+ String unencoded;
+ decode(std::begin(source), std::end(source), std::back_inserter(unencoded));
+ return unencoded;
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_DECODE_INC
diff --git a/CrowLeer/cpp-netlib/network/uri/detail/encode.hpp b/CrowLeer/cpp-netlib/network/uri/detail/encode.hpp
new file mode 100644
index 0000000..794f393
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/detail/encode.hpp
@@ -0,0 +1,166 @@
+// Copyright (c) Glyn Matthews 2011-2016.
+// Copyright 2012 Dean Michael Berris
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_ENCODE_INC
+#define NETWORK_URI_ENCODE_INC
+
+#include
+#include
+#include
+#include
+#include
+
+namespace network {
+namespace detail {
+template
+inline CharT hex_to_letter(CharT in) {
+ if ((in >= 0) && (in < 10)) {
+ return in + '0';
+ }
+
+ if ((in >= 10) && (in < 16)) {
+ return in - 10 + 'A';
+ }
+
+ return in;
+}
+
+template
+void encode_char(charT in, OutputIterator &out, const char *ignore = "") {
+ if (((in >= 'a') && (in <= 'z')) ||
+ ((in >= 'A') && (in <= 'Z')) ||
+ ((in >= '0') && (in <= '9')) ||
+ (in == '-') ||
+ (in == '.') ||
+ (in == '_') ||
+ (in == '~')) {
+ out++ = in;
+ } else {
+ auto first = ignore, last = ignore + std::strlen(ignore);
+ if (std::find(first, last, in) != last) {
+ out++ = in;
+ } else {
+ out++ = '%';
+ out++ = hex_to_letter((in >> 4) & 0x0f);
+ out++ = hex_to_letter(in & 0x0f);
+ }
+ }
+}
+
+template
+OutputIterator encode_user_info(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, ":");
+ ++it;
+ }
+ return out;
+}
+
+template
+OutputIterator encode_host(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "[:]");
+ ++it;
+ }
+ return out;
+}
+
+template
+OutputIterator encode_port(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out);
+ ++it;
+ }
+ return out;
+}
+
+template
+OutputIterator encode_path(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/.@%;=");
+ ++it;
+ }
+ return out;
+}
+
+template
+OutputIterator encode_query(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/.@&%;=");
+ ++it;
+ }
+ return out;
+}
+
+template
+OutputIterator encode_fragment(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/.@&l;=%");
+ ++it;
+ }
+ return out;
+}
+
+template
+String encode_user_info(const String &user_info) {
+ String encoded;
+ encode_user_info(std::begin(user_info), std::end(user_info),
+ std::back_inserter(encoded));
+ return encoded;
+}
+
+template
+String encode_host(const String &host) {
+ String encoded;
+ encode_host(std::begin(host), std::end(host), std::back_inserter(encoded));
+ return encoded;
+}
+
+template
+String encode_port(const String &port) {
+ String encoded;
+ encode_port(std::begin(port), std::end(port), std::back_inserter(encoded));
+ return encoded;
+}
+
+template
+String encode_path(const String &path) {
+ String encoded;
+ encode_path(std::begin(path), std::end(path), std::back_inserter(encoded));
+ return encoded;
+}
+
+template
+String encode_query(const String &query) {
+ String encoded;
+ encode_query(std::begin(query), std::end(query), std::back_inserter(encoded));
+ return encoded;
+}
+
+template
+String encode_fragment(const String &fragment) {
+ String encoded;
+ encode_fragment(std::begin(fragment), std::end(fragment),
+ std::back_inserter(encoded));
+ return encoded;
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_ENCODE_INC
diff --git a/CrowLeer/cpp-netlib/network/uri/detail/translate.hpp b/CrowLeer/cpp-netlib/network/uri/detail/translate.hpp
new file mode 100644
index 0000000..7566c25
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/detail/translate.hpp
@@ -0,0 +1,89 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_DETAIL_TRANSLATE_INC
+#define NETWORK_URI_DETAIL_TRANSLATE_INC
+
+#include
+
+namespace network {
+namespace detail {
+template
+struct translate_impl;
+
+template <>
+struct translate_impl {
+ std::string operator()(const std::string &source) const { return source; }
+};
+
+template
+struct translate_impl {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template
+struct translate_impl {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl {
+ std::string operator()(const std::wstring &source) const {
+ return std::string(std::begin(source), std::end(source));
+ }
+};
+
+template
+struct translate_impl {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl impl;
+ return impl(source);
+ }
+};
+
+template
+struct translate_impl {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl impl;
+ return impl(source);
+ }
+};
+
+template <>
+struct translate_impl {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl impl;
+ return impl(source);
+ }
+};
+
+template <>
+struct translate_impl {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl impl;
+ return impl(source);
+ }
+};
+
+template
+inline std::string translate(const Source &source) {
+ translate_impl impl;
+ return impl(source);
+}
+
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_DETAIL_TRANSLATE_INC
diff --git a/CrowLeer/cpp-netlib/network/uri/detail/uri_parts.hpp b/CrowLeer/cpp-netlib/network/uri/detail/uri_parts.hpp
new file mode 100644
index 0000000..731e30d
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/detail/uri_parts.hpp
@@ -0,0 +1,74 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_PARTS_INC
+#define NETWORK_DETAIL_URI_PARTS_INC
+
+#include
+#include
+#include
+#include
+#include
+
+namespace network {
+namespace detail {
+class uri_part {
+ public:
+ typedef string_view::value_type value_type;
+ typedef string_view::iterator iterator;
+ typedef string_view::const_iterator const_iterator;
+ typedef string_view::const_pointer const_pointer;
+ typedef string_view::size_type size_type;
+ typedef string_view::difference_type difference_type;
+
+ uri_part() noexcept = default;
+
+ uri_part(const_iterator first, const_iterator last) noexcept
+ : first(first), last(last) {}
+
+ const_iterator begin() const noexcept { return first; }
+
+ const_iterator end() const noexcept { return last; }
+
+ bool empty() const noexcept { return first == last; }
+
+ std::string to_string() const { return std::string(first, last); }
+
+ const_pointer ptr() const noexcept {
+ assert(first != last);
+ return first;
+ }
+
+ difference_type length() const noexcept {
+ return last - first;
+ }
+
+ string_view to_string_view() const noexcept { return string_view(ptr(), length()); }
+
+ private:
+ const_iterator first, last;
+};
+
+struct hierarchical_part {
+ hierarchical_part() = default;
+
+ optional user_info;
+ optional host;
+ optional port;
+ optional path;
+};
+
+struct uri_parts {
+ uri_parts() = default;
+
+ optional scheme;
+ hierarchical_part hier_part;
+ optional query;
+ optional fragment;
+};
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_PARTS_INC
diff --git a/CrowLeer/cpp-netlib/network/uri/uri.hpp b/CrowLeer/cpp-netlib/network/uri/uri.hpp
new file mode 100644
index 0000000..66fb752
--- /dev/null
+++ b/CrowLeer/cpp-netlib/network/uri/uri.hpp
@@ -0,0 +1,711 @@
+// Copyright 2009-2010 Jeroen Habraken.
+// Copyright 2009-2017 Dean Michael Berris, Glyn Matthews.
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_INC
+#define NETWORK_URI_INC
+
+/**
+ * \file
+ * \brief Contains the uri class.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4251 4231 4660)
+#endif
+
+namespace network {
+/**
+ * \enum uri_comparison_level
+ * \brief Defines the steps on the URI comparison ladder.
+ */
+enum class uri_comparison_level {
+ string_comparison,
+ syntax_based,
+ scheme_based,
+};
+
+/**
+ * \ingroup uri
+ * \class uri_builder network/uri/uri_builder.hpp network/uri.hpp
+ * \brief A class that allows complex uri objects to be constructed.
+ * \sa uri
+ */
+class uri_builder;
+
+/**
+ * \ingroup uri
+ * \class uri network/uri/uri.hpp network/uri.hpp
+ * \brief A class that parses a URI (Uniform Resource Identifier)
+ * into its component parts.
+ *
+ * This class conforms to a URI as defined by RFC 3986, RFC 3987 and
+ * RFC 2732, including scoped IDs. It provides member functions for
+ * normalizing, comparing and resolving URIs.
+ *
+ * A URI has the syntax:
+ *
+ * \code
+ * [scheme:][user_info@][host][:port][path][?query][#fragment]
+ * \endcode
+ *
+ * Example:
+ *
+ * \code
+ * network::uri instance("http://cpp-netlib.org/");
+ * assert(instance.is_absolute());
+ * assert(!instance.is_opaque());
+ * assert(instance.scheme());
+ * assert("http" == *instance.scheme());
+ * assert(instance.host());
+ * assert("cpp-netlib.org" == *instance.host());
+ * assert(instance.path());
+ * assert("/" == *instance.path());
+ * \endcode
+ */
+class uri {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ friend class uri_builder;
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ public:
+ /**
+ * \brief The URI string_type.
+ */
+ typedef std::string string_type;
+
+ /**
+ * \brief A reference to the underlying string_type parts.
+ */
+ typedef network::string_view string_view;
+
+ /**
+ * \brief The char traits.
+ */
+ typedef string_view::traits_type traits_type;
+
+ /**
+ * \brief The URI const_iterator type.
+ */
+ typedef string_view::const_iterator const_iterator;
+
+ /**
+ * \brief The URI iterator type.
+ */
+ typedef const_iterator iterator;
+
+ /**
+ * \brief The URI value_type.
+ */
+ typedef std::iterator_traits::value_type value_type;
+
+ /**
+ *
+ */
+ class query_iterator {
+ public:
+ using value_type = std::pair;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const value_type *;
+ using reference = const value_type &;
+ using iterator_category = std::forward_iterator_tag;
+
+ query_iterator();
+ explicit query_iterator(optional);
+ query_iterator(const query_iterator &);
+ query_iterator &operator=(const query_iterator &);
+ reference operator++() noexcept;
+ value_type operator++(int) noexcept;
+ reference operator*() const noexcept;
+ pointer operator->() const noexcept;
+ bool operator==(const query_iterator &) const noexcept;
+ inline bool operator!=(const query_iterator &other) const noexcept {
+ return !(*this == other);
+ }
+
+ private:
+ void swap(query_iterator &) noexcept;
+ void advance_to_next_kvp() noexcept;
+ void assign_kvp() noexcept;
+ void increment() noexcept;
+
+ optional query_;
+ value_type kvp_;
+ };
+
+ /**
+ * \brief Default constructor.
+ */
+ uri();
+
+ /**
+ * \brief Constructor.
+ * \param first The first element in a string sequence.
+ * \param last The end + 1th element in a string sequence.
+ * \throws uri_syntax_error if the sequence is not a valid URI.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ template
+ uri(InputIter first, InputIter last) {
+ if (!initialize(string_type(first, last))) {
+ throw uri_syntax_error();
+ }
+ }
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ template
+ explicit uri(InputIter first, InputIter last, std::error_code &ec) {
+ if (!initialize(string_type(first, last))) {
+ ec = make_error_code(uri_error::invalid_syntax);
+ }
+ }
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /**
+ * \brief Constructor.
+ * \param source A source string that is to be parsed as a URI.
+ * \throws uri_syntax_error if the source is not a valid URI.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ template
+ explicit uri(const Source &source) {
+ if (!initialize(detail::translate(source))) {
+ throw uri_syntax_error();
+ }
+ }
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ template
+ explicit uri(const Source &source, std::error_code &ec) {
+ if (!initialize(detail::translate(source))) {
+ ec = make_error_code(uri_error::invalid_syntax);
+ }
+ }
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ explicit uri(const uri_builder &builder);
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /**
+ * \brief Copy constructor.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ uri(const uri &other);
+
+ /**
+ * \brief Move constructor.
+ */
+ uri(uri &&other) noexcept;
+
+ /**
+ * \brief Destructor.
+ */
+ ~uri();
+
+ /**
+ * \brief Assignment operator.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ uri &operator=(uri other);
+
+ /**
+ * \brief Swaps one uri object with another.
+ * \param other The other uri object.
+ */
+ void swap(uri &other) noexcept;
+
+ /**
+ * \brief Returns an iterator at the first element in the
+ * underlying sequence.
+ * \return An iterator starting at the first element.
+ */
+ const_iterator begin() const noexcept;
+
+ /**
+ * \brief Returns an iterator at the end + 1th element in the
+ * underlying sequence.
+ * \return An iterator starting at the end + 1th element.
+ */
+ const_iterator end() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a scheme component.
+ * \return \c true if the URI has a scheme, \c false otherwise.
+ */
+ bool has_scheme() const noexcept;
+
+ /**
+ * \brief Returns the URI scheme.
+ * \return The scheme.
+ * \pre has_scheme()
+ */
+ string_view scheme() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a user info component.
+ * \return \c true if the URI has a user info, \c false otherwise.
+ */
+ bool has_user_info() const noexcept;
+
+ /**
+ * \brief Returns the URI user info.
+ * \return The user info.
+ * \pre has_user_info()
+ */
+ string_view user_info() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a host component.
+ * \return \c true if the URI has a host, \c false otherwise.
+ */
+ bool has_host() const noexcept;
+
+ /**
+ * \brief Returns the URI host.
+ * \return The host.
+ * \pre has_host()
+ */
+ string_view host() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a port component.
+ * \return \c true if the URI has a port, \c false otherwise.
+ */
+ bool has_port() const noexcept;
+
+ /**
+ * \brief Returns the URI port.
+ * \return The port.
+ * \pre has_port()
+ */
+ string_view port() const noexcept;
+
+ /**
+ * \brief Returns the URI port as an integer.
+ * \return The port number.
+ * \pre has_port()
+ */
+ template
+ intT port(typename std::is_integral::type * = 0) const {
+ assert(has_port());
+ auto p = port();
+ const char *port_first = std::addressof(*p.begin());
+ char *port_last = 0;
+ return static_cast(std::strtoul(port_first, &port_last, 10));
+ }
+
+ /**
+ * \brief Tests whether this URI has a path component.
+ * \return \c true if the URI has a path, \c false otherwise.
+ */
+ bool has_path() const noexcept;
+
+ /**
+ * \brief Returns the URI path.
+ * \return The path.
+ * \pre has_path()
+ */
+ string_view path() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a query component.
+ * \return \c true if the URI has a query, \c false otherwise.
+ */
+ bool has_query() const noexcept;
+
+ /**
+ * \brief Returns the URI query.
+ * \return The query.
+ * \pre has_query()
+ */
+ string_view query() const noexcept;
+
+ /**
+ * \brief Returns an iterator to the first key-value pair in the query
+ * component.
+ *
+ * \return query_iterator.
+ */
+ query_iterator query_begin() const noexcept;
+
+ /**
+ * \brief Returns an iterator to the last key-value pair in the query
+ * component.
+ *
+ * \return query_iterator.
+ */
+ query_iterator query_end() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a fragment component.
+ * \return \c true if the URI has a fragment, \c false otherwise.
+ */
+ bool has_fragment() const noexcept;
+
+ /**
+ * \brief Returns the URI fragment.
+ * \return The fragment.
+ * \pre has_fragment()
+ */
+ string_view fragment() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a valid authority.
+ * \return \c true if the URI has an authority, \c false otherwise.
+ */
+ bool has_authority() const noexcept;
+
+ /**
+ * \brief Returns the URI authority.
+ * \return The authority.
+ */
+ string_view authority() const noexcept;
+
+ /**
+ * \brief Returns the URI as a std::basic_string object.
+ * \return A URI string.
+ */
+ template ,
+ class Allocator = std::allocator >
+ std::basic_string to_string(
+ const Allocator &alloc = Allocator()) const {
+ return std::basic_string(begin(), end());
+ }
+
+ /**
+ * \brief Returns the URI as a std::string object.
+ * \returns A URI string.
+ */
+ std::string string() const;
+
+ /**
+ * \brief Returns the URI as a std::wstring object.
+ * \returns A URI string.
+ */
+ std::wstring wstring() const;
+
+ /**
+ * \brief Returns the URI as a std::u16string object.
+ * \returns A URI string.
+ */
+ std::u16string u16string() const;
+
+ /**
+ * \brief Returns the URI as a std::u32string object.
+ * \returns A URI string.
+ */
+ std::u32string u32string() const;
+
+ /**
+ * \brief Checks if the uri object is empty, i.e. it has no parts.
+ * \returns \c true if there are no parts, \c false otherwise.
+ */
+ bool empty() const noexcept;
+
+ /**
+ * \brief Checks if the uri is absolute, i.e. it has a scheme.
+ * \returns \c true if it is absolute, \c false if it is relative.
+ */
+ bool is_absolute() const noexcept;
+
+ /**
+ * \brief Checks if the uri is opaque, i.e. if it doesn't have an
+ * authority.
+ * \returns \c true if it is opaque, \c false if it is hierarchical.
+ */
+ bool is_opaque() const noexcept;
+
+ /**
+ * \brief Normalizes a uri object at a given level in the
+ * comparison ladder.
+ * \param level The comparison level.
+ * \returns A normalized uri.
+ * \post compare(normalize(uri, level), level) == 0
+ * \throws std::bad_alloc
+ */
+ uri normalize(uri_comparison_level level) const;
+
+ /**
+ * \brief Returns a relative reference against the base URI.
+ * \param base The base URI.
+ * \returns A relative reference of this URI against the base.
+ * \throws std::bad_alloc
+ */
+ uri make_relative(const uri &base) const;
+
+ /**
+ * \brief Resolves a relative reference against the given URI.
+ * \param base The base URI to resolve against.
+ * \returns An absolute URI.
+ * \throws std::bad_alloc
+ */
+ uri resolve(const uri &base) const;
+
+ /**
+ * \brief Compares this URI against another, corresponding to the
+ * level in the comparison ladder.
+ * \param other The other URI.
+ * \param level The level in the comparison ladder.
+ * \returns \c 0 if the URIs are considered equal, \c -1 if this is
+ * less than other and and 1 if this is greater than
+ * other.
+ */
+ int compare(const uri &other, uri_comparison_level level) const noexcept;
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * user info part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_user_info(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_user_info(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * host part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_host(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_host(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * port part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_port(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_port(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * path part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_path(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_path(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * query part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_query(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_query(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * fragment part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter encode_fragment(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_fragment(first, last, out);
+ }
+
+ /**
+ * \brief Decodes a sequence according to the percent decoding
+ * rules.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template
+ static OutputIter decode(InputIter first, InputIter last, OutputIter out) {
+ return detail::decode(first, last, out);
+ }
+
+ private:
+ bool initialize(const string_type &uri);
+
+ void initialize(optional