From 37f9390ef8a21ffb6adcbbc9a5be2358e47d270a Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 21 Sep 2015 15:36:05 +1000 Subject: [PATCH] view: template on arbirtrary iterator types --- test/uri.cpp | 36 +++++++++++++------------- uri.cpp.rl | 9 +++++-- uri.hpp | 6 ++--- view.cpp | 72 ++++++++++++++++++++-------------------------------- view.hpp | 29 +++++++++++---------- 5 files changed, 71 insertions(+), 81 deletions(-) diff --git a/test/uri.cpp b/test/uri.cpp index 05f457aa..0f6e2367 100644 --- a/test/uri.cpp +++ b/test/uri.cpp @@ -6,6 +6,8 @@ int main (void) { + util::TAP::logger tap; + static const struct { const char *src; const char *scheme; @@ -14,26 +16,26 @@ main (void) const char *query; const char *fragment; } GOOD[] = { - { "ftp://ftp.is.co.za/rfc/rfc1808.txt", "ftp", "ftp.is.co.za", "/rfc/rfc1808.txt", "", "" }, - { "http://www.ietf.org/rfc/rfc2396.txt", "http", "www.ietf.org", "/rfc/rfc2396.txt", "", "" }, - { "ldap://[2001:db8::7]/c=GB?objectClass?one", "ldap", "[2001:db8::7]", "/c=GB", "objectClass?one", "" }, - { "mailto:John.Doe@example.com", "mailto", "", "John.Doe@example.com", "", "" }, - { "news:comp.infosystems.www.servers.unix", "news", "", "comp.infosystems.www.servers.unix", "", "" }, - { "tel:+1-816-555-1212", "tel", "", "+1-816-555-1212", "", "" }, - { "telnet://192.0.2.16:80/", "telnet", "192.0.2.16:80", "/", "", "" }, - { "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", "urn", "", "oasis:names:specification:docbook:dtd:xml:4.1.2", "", "" }, + { "ftp://ftp.is.co.za/rfc/rfc1808.txt", "ftp", "ftp.is.co.za", "/rfc/rfc1808.txt", "", "" }, + { "http://www.ietf.org/rfc/rfc2396.txt", "http", "www.ietf.org", "/rfc/rfc2396.txt", "", "" }, + { "ldap://[2001:db8::7]/c=GB?objectClass?one", "ldap", "[2001:db8::7]", "/c=GB", "objectClass?one", "" }, + { "mailto:John.Doe@example.com", "mailto", "", "John.Doe@example.com", "", "" }, + { "news:comp.infosystems.www.servers.unix", "news", "", "comp.infosystems.www.servers.unix", "", "" }, + { "tel:+1-816-555-1212", "tel", "", "+1-816-555-1212", "", "" }, + { "telnet://192.0.2.16:80/", "telnet", "192.0.2.16:80", "/", "", "" }, + { "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", "urn", "", "oasis:names:specification:docbook:dtd:xml:4.1.2", "", "" }, }; for (auto i: GOOD) { - CHECK_NOTHROW (util::uri foo (i.src)); + tap.expect_nothrow ([i] (void) { util::uri foo (i.src); }, "nothrow parsing '%s'", i.src); util::uri u (i.src); - CHECK_EQ (i.scheme, u.get (util::uri::SCHEME)); - CHECK_EQ (i.authority, u.get (util::uri::AUTHORITY)); - CHECK_EQ (i.path, u.get (util::uri::PATH)); - CHECK_EQ (i.query, u.get (util::uri::QUERY)); - CHECK_EQ (i.fragment, u.get (util::uri::FRAGMENT)); + tap.expect (std::equal (u.get (util::uri::SCHEME).begin (), u.get (util::uri::SCHEME).end (), i.scheme), "extracting scheme for '%s'", i.src); + tap.expect (std::equal (u.get (util::uri::AUTHORITY).begin (), u.get (util::uri::AUTHORITY).end (), i.authority), "extracting authority '%s'", i.src); + tap.expect (std::equal (u.get (util::uri::PATH).begin (), u.get (util::uri::PATH).end (), i.path), "extracting path '%s'", i.src); + tap.expect (std::equal (u.get (util::uri::QUERY).begin (), u.get (util::uri::QUERY).end (), i.query), "extracting query '%s'", i.src); + tap.expect (std::equal (u.get (util::uri::FRAGMENT).begin (), u.get (util::uri::FRAGMENT).end (), i.fragment), "extracting fragment '%s'", i.src); } static const char* BAD[] = { @@ -41,8 +43,8 @@ main (void) }; for (auto i: BAD) - CHECK_THROWS (util::uri::parse_error, util::uri foo (i)); + tap.expect_throw ([i] (void) { util::uri foo (i); }, "throw parsing '%s'", i); - util::TAP::logger tap; - tap.skip ("convert to TAP"); + + return tap.status (); } diff --git a/uri.cpp.rl b/uri.cpp.rl index a02b7176..555cbb36 100644 --- a/uri.cpp.rl +++ b/uri.cpp.rl @@ -169,8 +169,13 @@ util::uri::uri (const char *first, const char *last): { ; } +/////////////////////////////////////////////////////////////////////////////// +static const util::view NULL_VIEW { nullptr, nullptr }; + + //----------------------------------------------------------------------------- util::uri::uri (std::string &&_value): + m_views {NULL_VIEW, NULL_VIEW, NULL_VIEW, NULL_VIEW, NULL_VIEW}, m_value (std::move (_value)) { const char *p = m_value.data (); @@ -190,7 +195,7 @@ util::uri::uri (std::string &&_value): //----------------------------------------------------------------------------- -util::view +util::view util::uri::get (util::uri::component c) { CHECK_NEQ (c, NUM_COMPONENTS); @@ -217,7 +222,7 @@ hex_to_uint (char c) //----------------------------------------------------------------------------- std::string -util::uri::percent_decode (view s) +util::uri::percent_decode (view s) { if (s.size () == 0) return std::string (); diff --git a/uri.hpp b/uri.hpp index 2f772c2f..82464f9f 100644 --- a/uri.hpp +++ b/uri.hpp @@ -44,12 +44,12 @@ namespace util { NUM_COMPONENTS }; - view get (component); + view get (component); - static std::string percent_decode (view); + static std::string percent_decode (view); private: - view m_views[NUM_COMPONENTS]; + view m_views[NUM_COMPONENTS]; std::string m_value; }; diff --git a/view.cpp b/view.cpp index 7cb08afb..d9becbcf 100644 --- a/view.cpp +++ b/view.cpp @@ -22,65 +22,57 @@ #include #include -//----------------------------------------------------------------------------- -util::view::view (): - m_begin (nullptr), - m_end (nullptr) -{ ; } +using util::view; //----------------------------------------------------------------------------- -util::view::view (const char *str): - m_begin (str), - m_end (str + strlen (str)) -{ ; } - - -//----------------------------------------------------------------------------- -util::view::view (const char *_begin, - const char *_end): +template +view::view (T _begin, T _end): m_begin (_begin), m_end (_end) { ; } //----------------------------------------------------------------------------- -const char* -util::view::begin (void) const +template +T +view::begin (void) { return m_begin; } //----------------------------------------------------------------------------- -const char* -util::view::end (void) const +template +T +view::end (void) { return m_end; } //----------------------------------------------------------------------------- +template bool -util::view::view::empty (void) const +view::empty (void) const { - return m_begin == nullptr || - m_end == nullptr || - m_begin == m_end; + return m_begin == m_end; } //----------------------------------------------------------------------------- +template size_t -util::view::size (void) const +view::size (void) const { - return m_end - m_begin; + return std::distance (m_begin, m_end); } //----------------------------------------------------------------------------- -const char& -util::view::operator[] (size_t idx) const +template +const typename view::value_type& +view::operator[] (size_t idx) const { CHECK_LT (m_begin + idx, m_end); return m_begin[idx]; @@ -88,34 +80,24 @@ util::view::operator[] (size_t idx) const //----------------------------------------------------------------------------- +template bool -util::view::operator== (const char *restrict rhs) const +view::operator== (const view rhs) const { - return strlen (rhs) == size () && - 0 == strncmp (rhs, m_begin, size ()); -} - - -//----------------------------------------------------------------------------- -bool -util::view::operator== (view v) const -{ - return std::equal (m_begin, m_end, v.begin ()); + return rhs.m_begin == m_begin && + rhs.m_end == m_end; } //----------------------------------------------------------------------------- +template std::ostream& -util::operator<< (std::ostream &os, util::view s) +util::operator<< (std::ostream &os, util::view v) { - std::copy (s.begin (), s.end (), std::ostream_iterator (os)); + std::copy (v.begin (), v.end (), std::ostream_iterator (os)); return os; } -//----------------------------------------------------------------------------- -bool -util::operator== (const char *str, view v) -{ - return v == str; -} +/////////////////////////////////////////////////////////////////////////////// +template struct util::view; diff --git a/view.hpp b/view.hpp index 86e33be9..da7f94e2 100644 --- a/view.hpp +++ b/view.hpp @@ -22,29 +22,30 @@ #include namespace util { - class view { + template + struct view { public: - view (); - explicit view (const char *str); - view (const char *first, const char *last); + using value_type = typename std::iterator_traits::value_type; - const char *begin (void) const; - const char *end (void) const; + view (T first, T last); - bool empty () const; + T begin (void); + T end (void); + + bool empty (void) const; size_t size (void) const; - const char& operator[] (size_t) const; - bool operator== (const char *restrict str) const; + value_type& operator[] (size_t); + const value_type& operator[] (size_t) const; + bool operator== (view) const; private: - const char *m_begin; - const char *m_end; + T m_begin; + T m_end; }; - - std::ostream& operator<< (std::ostream&, view); - bool operator== (const char*, view); + template + std::ostream& operator<< (std::ostream&, view); } #endif