libcruft-util/uri.hpp
Danny Robson fdaa5e1392 assert: split CHECK_LIMIT into INCLUSIVE and INDEX
LIMIT hid an off-by-one bug when tests used end iterators. We rename the
assertion to uncover all uses of the flawed implementation, and split it
into an identical assertion, and one intended to protect against
iterator ends.
2020-09-24 08:03:41 +10:00

102 lines
3.3 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2015, 2017 Danny Robson <danny@nerdcruft.net>
*/
#ifndef CRUFT_UTIL_URI_HPP
#define CRUFT_UTIL_URI_HPP
#include "debug/assert.hpp"
#include "view.hpp"
#include <array>
#include <string>
#include <stdexcept>
namespace cruft {
// parsing of rfc3986 uniform resource identifiers
//
// does not currently perform normalisation (scheme or protocol),
// comparison, or other associated operations. though these should be
// added in the future.
//
// note that the parsed results may not always conform to expectations
// for some protocols. eg, mailto identifiers are complex to parse
// reliably and would require a specialised parser to be reliable.
//
// not all fields will be present for all protocols (or all instances of
// any given protocol). eg, the "tel" is unlikely to have port numbers.
class uri {
public:
uri (std::string &&);
uri (const std::string&);
uri (const char *);
uri (view<const char *>);
class parse_error : public std::runtime_error
{ using runtime_error::runtime_error; };
// URI: 'https://user:password@example.com:80/path/to?foo=bar#fragment'
//
// SCHEME: 'https'
// HIERARCHICAL: 'user:password@example.com:80/path/to'
// AUTHORITY: 'user:password@example.com:80'
// USER: 'user:password'
// HOST: 'example.com'
// PORT: '80'
// PATH: '/path/to'
// QUERY: 'foo=bar'
// FRAGMENT: 'fragment'
enum component {
SCHEME,
HIERARCHICAL,
AUTHORITY,
USER,
HOST,
PORT,
PATH,
QUERY,
FRAGMENT,
NUM_COMPONENTS
};
view<const char*>
get (component c) const&
{
CHECK_INDEX (c, NUM_COMPONENTS);
return m_views[c];
}
cruft::view<const char*> all (void) const& { return cruft::make_view (m_value); }
cruft::view<const char*> scheme (void) const& { return get (SCHEME); }
cruft::view<const char*> heirarchical (void) const& { return get (HIERARCHICAL); }
cruft::view<const char*> authority (void) const& { return get (AUTHORITY); }
cruft::view<const char*> user (void) const& { return get (USER); }
cruft::view<const char*> host (void) const& { return get (HOST); }
cruft::view<const char*> port (void) const& { return get (PORT); }
cruft::view<const char*> path (void) const& { return get (PATH); }
cruft::view<const char*> query (void) const& { return get (QUERY); }
cruft::view<const char*> fragment (void) const& { return get (FRAGMENT); }
auto components (void) const& noexcept { return m_views; }
static std::string percent_decode (view<const char*>);
private:
std::array<view<const char*>, NUM_COMPONENTS> m_views;
std::string m_value;
};
std::ostream& operator<< (std::ostream&, uri::component);
}
#endif