diff --git a/CMakeLists.txt b/CMakeLists.txt index f3bdf050..673f001e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ endif() ############################################################################### -RAGEL_TARGET(uri uri.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/uri.cpp COMPILE_FLAGS -G2) +RAGEL_TARGET(uri uri.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/uri.rl.cpp COMPILE_FLAGS -G2) RAGEL_TARGET(version version.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/version.cpp) RAGEL_TARGET(parse8601 time/parse8601.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/time/parse8601.cpp) @@ -584,6 +584,7 @@ list ( types/tagged.hpp types/traits.hpp uri.cpp + uri.rl.cpp uri.hpp utf8.cpp utf8.hpp diff --git a/uri.cpp b/uri.cpp new file mode 100644 index 00000000..b1e7d845 --- /dev/null +++ b/uri.cpp @@ -0,0 +1,116 @@ +#include "./uri.hpp" + +#include "./debug/panic.hpp" + +using cruft::uri; + + +/////////////////////////////////////////////////////////////////////////////// +cruft::uri::uri (const char *str): + uri (std::string (str)) +{ ; } + + +//----------------------------------------------------------------------------- +uri::uri (cruft::view _value): + uri (std::string (_value.begin (), _value.end ())) +{ ; } + + +//----------------------------------------------------------------------------- +uri::uri (const std::string &_value): + uri (std::string (_value)) +{ ; } + + +/////////////////////////////////////////////////////////////////////////////// +static uint8_t +hex_to_uint (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + unreachable (); +} + + +//----------------------------------------------------------------------------- +std::string +cruft::uri::percent_decode (view s) +{ + if (s.size () == 0) + return std::string (); + + // Early check for late percent-encoding so we can simplify the decode loop + { + auto tail = std::find (s.size () < 3 ? s.begin () + : s.end () - 2, + s.end (), + '%'); + if (tail != s.end ()) + throw parse_error ("triple overlaps end"); + } + + // Allocate and size a potentially overlong output string. This allows us + // to copy directly into its buffer. We'll shorten it at the end. + std::string out; + out.resize (s.size ()); + + // Find the percent, copy until that, decode, advance, repeat. + auto out_cursor = out.begin (); + + for (auto i = s.begin (); i < s.end (); ++i) { + auto cursor = std::find (i, s.end (), '%'); + + if (cursor == s.end ()) { + out_cursor = std::copy (i, s.end (), out_cursor); + break; + } + + out_cursor = std::copy (i, cursor, out_cursor); + *out_cursor = hex_to_uint (cursor[1]) << 4 | hex_to_uint(cursor[2]); + + i += 3; + } + + out.resize (out.end () - out_cursor); + return out; +} + + + +//----------------------------------------------------------------------------- +std::ostream& +cruft::operator<< (std::ostream &os, cruft::uri::component c) +{ + switch (c) { + case cruft::uri::SCHEME: return os << "SCHEME"; + case cruft::uri::HIERARCHICAL: return os << "HIERARCHICAL"; + case cruft::uri::AUTHORITY: return os << "AUTHORITY"; + case cruft::uri::USER: return os << "USER"; + case cruft::uri::HOST: return os << "HOST"; + case cruft::uri::PORT: return os << "PORT"; + case cruft::uri::PATH: return os << "PATH"; + case cruft::uri::QUERY: return os << "QUERY"; + case cruft::uri::FRAGMENT: return os << "FRAGMENT"; + + case cruft::uri::NUM_COMPONENTS: + unreachable (); + } + + unreachable (); +} + + +//----------------------------------------------------------------------------- +std::ostream& +cruft::operator<< (std::ostream &os, cruft::uri const &val) +{ + return os << val.value (); +} diff --git a/uri.cpp.rl b/uri.cpp.rl index af8ef6f1..8509a179 100644 --- a/uri.cpp.rl +++ b/uri.cpp.rl @@ -8,8 +8,6 @@ #include "uri.hpp" -#include "debug/panic.hpp" - #include #include @@ -70,41 +68,17 @@ using cruft::uri; /////////////////////////////////////////////////////////////////////////////// -// URI - -cruft::uri::uri (const char *str): - uri (std::string (str)) -{ ; } - - -//----------------------------------------------------------------------------- -uri::uri (cruft::view _value): - uri (std::string (_value.begin (), _value.end ())) -{ ; } - - -//----------------------------------------------------------------------------- -uri::uri (const std::string &_value): - uri (std::string (_value)) -{ ; } - - -//----------------------------------------------------------------------------- -static const cruft::view NULL_VIEW { nullptr, nullptr }; - - -//----------------------------------------------------------------------------- cruft::uri::uri (std::string &&_value): m_views { - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW, - NULL_VIEW + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr }, m_value (std::move (_value)) { @@ -121,97 +95,4 @@ cruft::uri::uri (std::string &&_value): if (!__success) throw parse_error ("invalid uri"); -} - - -//----------------------------------------------------------------------------- -static uint8_t -hex_to_uint (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - - unreachable (); -} - - -//----------------------------------------------------------------------------- -std::string -cruft::uri::percent_decode (view s) -{ - if (s.size () == 0) - return std::string (); - - // Early check for late percent-encoding so we can simplify the decode loop - { - auto tail = std::find (s.size () < 3 ? s.begin () - : s.end () - 2, - s.end (), - '%'); - if (tail != s.end ()) - throw parse_error ("triple overlaps end"); - } - - // Allocate and size a potentially overlong output string. This allows us - // to copy directly into its buffer. We'll shorten it at the end. - std::string out; - out.resize (s.size ()); - - // Find the percent, copy until that, decode, advance, repeat. - auto out_cursor = out.begin (); - - for (auto i = s.begin (); i < s.end (); ++i) { - auto cursor = std::find (i, s.end (), '%'); - - if (cursor == s.end ()) { - out_cursor = std::copy (i, s.end (), out_cursor); - break; - } - - out_cursor = std::copy (i, cursor, out_cursor); - *out_cursor = hex_to_uint (cursor[1]) << 4 | hex_to_uint(cursor[2]); - - i += 3; - } - - out.resize (out.end () - out_cursor); - return out; -} - - - -//----------------------------------------------------------------------------- -std::ostream& -cruft::operator<< (std::ostream &os, cruft::uri::component c) -{ - switch (c) { - case cruft::uri::SCHEME: return os << "SCHEME"; - case cruft::uri::HIERARCHICAL: return os << "HIERARCHICAL"; - case cruft::uri::AUTHORITY: return os << "AUTHORITY"; - case cruft::uri::USER: return os << "USER"; - case cruft::uri::HOST: return os << "HOST"; - case cruft::uri::PORT: return os << "PORT"; - case cruft::uri::PATH: return os << "PATH"; - case cruft::uri::QUERY: return os << "QUERY"; - case cruft::uri::FRAGMENT: return os << "FRAGMENT"; - - case cruft::uri::NUM_COMPONENTS: - unreachable (); - } - - unreachable (); -} - - -//----------------------------------------------------------------------------- -std::ostream& -cruft::operator<< (std::ostream &os, cruft::uri const &val) -{ - return os << val.value (); } \ No newline at end of file