uri: remove parent-child component support

This commit is contained in:
Danny Robson 2022-02-22 16:38:01 +10:00
parent 2c18bc3488
commit f4bb73dbec
3 changed files with 72 additions and 85 deletions

124
uri.cpp
View File

@ -3,45 +3,14 @@
#include "./string.hpp"
#include "./debug/panic.hpp"
#include "./debug/assert.hpp"
#include "./debug/warn.hpp"
#include <ostream>
using cruft::uri;
///////////////////////////////////////////////////////////////////////////////
#include <cruft/util/debug/assert.hpp>
#include <cruft/util/debug/warn.hpp>
#include <cruft/util/iterator/zip.hpp>
#include <optional>
//-----------------------------------------------------------------------------
using uric = cruft::uri::component;
struct {
cruft::uri::component self;
// prev sibling
std::optional<cruft::uri::component> prev;
// parent
std::optional<cruft::uri::component> parent;
} COMPONENT_ORDER[cruft::uri::NUM_COMPONENTS] {
{ uric::SCHEME, { }, {} },
{ uric::HIERARCHICAL, {uric::SCHEME }, {} },
{ uric::QUERY, {uric::HIERARCHICAL}, {} },
{ uric::FRAGMENT, {uric::QUERY }, {} },
{ uric::AUTHORITY, { }, {uric::HIERARCHICAL} },
{ uric::PATH, {uric::AUTHORITY}, {uric::HIERARCHICAL} },
{ uric::USER, { }, {uric::AUTHORITY} },
{ uric::HOST, {uric::USER}, {uric::AUTHORITY} },
{ uric::PORT, {uric::HOST}, {uric::AUTHORITY} },
};
///////////////////////////////////////////////////////////////////////////////
cruft::uri::uri (std::string &&_value):
m_views {
@ -52,23 +21,18 @@ cruft::uri::uri (std::string &&_value):
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
},
m_value (std::move (_value))
{
parse ();
for (auto const &order: COMPONENT_ORDER) {
if (m_views[order.self].data ())
continue;
if (m_views[0].begin () == nullptr)
m_views[0] = { m_value.data (), 0 };
if (order.prev)
m_views[order.self] = { m_views[*order.prev].end (), 0 };
else if (order.parent)
m_views[order.self] = { m_views[*order.parent].begin (), 0 };
else
m_views[order.self] = { m_value.data (), 0 };
for (int i = 1; i < NUM_COMPONENTS; ++i) {
if (m_views[i].data () != nullptr)
continue;
m_views[i] = { m_views[i - 1].end (), 0 };
}
CHECK_SANITY (*this);
@ -112,6 +76,8 @@ uri& uri::operator= (uri &&rhs) noexcept
{
m_views = std::move (rhs.m_views);
m_value = std::move (rhs.m_value);
CHECK_SANITY (*this);
return *this;
}
@ -171,6 +137,28 @@ uri::uri (
{ ; }
///////////////////////////////////////////////////////////////////////////////
std::string_view
uri::heirarchical (void) const&
{
for (int i = USER; i <= PATH; ++i)
if (!m_views[i].empty ())
return { m_views[i].data (), std::size_t (m_views[PATH].end () - m_views[i].data ()) };
return { m_views[USER].data (), 0 };
}
//-----------------------------------------------------------------------------
std::string_view
uri::authority (void) const&
{
for (int i = USER; i <= PORT; ++i)
if (!m_views[i].empty ())
return { m_views[i].data (), std::size_t (m_views[PORT ].end () - m_views[i].data ()) };
return { m_views[USER].data (), 0 };
}
///////////////////////////////////////////////////////////////////////////////
std::string_view
uri::get (component c) const&
@ -184,14 +172,23 @@ uri::get (component c) const&
void
uri::set (component c, std::string_view val)
{
auto const diff = val.size () - m_views[c].size ();
std::ptrdiff_t const diff = val.size () - m_views[c].size ();
auto const base = m_value.data ();
m_value.replace (
m_views[c].data () - m_value.data (),
m_views[c].size (),
val
);
auto const offset = m_value.data () - base;
for (int i = 0; i <= c; ++i)
m_views[i] += offset;
m_views[c] = { m_views[c].begin (), m_views[c].end () + diff };
for (int i = c + 1; i != component::NUM_COMPONENTS; ++i)
m_views[i] += diff;
m_views[i] += offset + diff;
CHECK_SANITY (*this);
}
@ -205,9 +202,12 @@ void uri::clear_fragment ()
m_views[FRAGMENT].begin () - m_value.data (),
m_views[FRAGMENT].size ()
);
CHECK (m_value.back () == '#');
m_value.pop_back ();
// Don't set this to nullptr. Other code assumes these views aren't null
// (eg, for offsetting during copy construction).
m_views[FRAGMENT] = { m_views[FRAGMENT].begin (), 0 };
m_views[FRAGMENT] = { m_views[FRAGMENT - 1].end (), 0 };
}
@ -330,8 +330,6 @@ 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";
@ -495,25 +493,17 @@ cruft::debug::validator<cruft::uri>::is_valid (cruft::uri const &val) noexcept
RETURN_FALSE_UNLESS (i.end () <= value.data () + value.size ());
}
// Each component reference memory after the previous component.
// Empty components can be coincident with their siblings.
for (auto const [selfidx, previdx, parentidx]: COMPONENT_ORDER) {
auto const &self = components[selfidx];
for (int i = 1; i < uri::NUM_COMPONENTS; ++i) {
auto const &a = components[i - 1];
auto const &b = components[i ];
if (previdx) {
auto const &prev = components[*previdx];
RETURN_FALSE_UNLESS (prev.begin () <= self.begin ());
RETURN_FALSE_UNLESS (prev.end () <= self.end ());
RETURN_FALSE_UNLESS (prev.end () <= self.begin ());
}
if (parentidx) {
auto const &parent = components[*parentidx];
RETURN_FALSE_UNLESS (parent.begin () <= self.begin ());
RETURN_FALSE_UNLESS (parent.end () >= self.end ());
}
// All of our data needs to occur before the next component
//
// It may not be coincident with a sibling if there is padding between
// (as is the case directly after the scheme).
RETURN_FALSE_UNLESS (a.begin () <= b.begin ());
RETURN_FALSE_UNLESS (a.end () <= b.end ());
RETURN_FALSE_UNLESS (a.end () <= b.begin ());
}
return true;

View File

@ -31,8 +31,8 @@ using cruft::uri;
action scheme_begin { starts[SCHEME] = p; }
action scheme_end { CHECK (starts[SCHEME]); m_views[SCHEME] = { starts[SCHEME], p }; }
action hier_begin { starts[HIERARCHICAL] = p; }
action hier_end { CHECK (starts[HIERARCHICAL]); m_views[HIERARCHICAL] = { starts[HIERARCHICAL], p }; }
action hier_begin { ; }
action hier_end { ; }
action user_begin { starts[USER] = p; }
action user_end { CHECK (starts[USER]); m_views[USER] = { starts[USER], p }; }
@ -43,8 +43,8 @@ using cruft::uri;
action port_begin { starts[PORT] = p; }
action port_end { CHECK (starts[PORT]); m_views[PORT] = { starts[PORT], p }; }
action authority_begin { starts[AUTHORITY] = p; }
action authority_end { CHECK (starts[AUTHORITY]); m_views[AUTHORITY] = { starts[AUTHORITY], p }; }
action authority_begin { ; }
action authority_end { ; }
action path_begin { starts[PATH] = p; }
action path_end { CHECK (starts[PATH]); m_views[PATH] = { starts[PATH], p }; }
@ -83,8 +83,6 @@ cruft::uri::parse (void)
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
};
const char *p = m_value.data ();

23
uri.hpp
View File

@ -70,14 +70,12 @@ namespace cruft {
// FRAGMENT: 'fragment'
enum component {
/* 0 */ SCHEME,
/* 1 */ HIERARCHICAL,
/* 2 */ AUTHORITY,
/* 3 */ USER,
/* 4 */ HOST,
/* 5 */ PORT,
/* 6 */ PATH,
/* 7 */ QUERY,
/* 8 */ FRAGMENT,
/* 1 */ USER,
/* 2 */ HOST,
/* 3 */ PORT,
/* 4 */ PATH,
/* 5 */ QUERY,
/* 6 */ FRAGMENT,
NUM_COMPONENTS
};
@ -85,14 +83,10 @@ namespace cruft {
std::string_view
get (component c) const&;
void set (component c, std::string_view);
std::string_view all (void) const& { return m_value; }
std::string const& value (void) const& { return m_value; }
std::string_view scheme (void) const& { return get (SCHEME); }
std::string_view heirarchical (void) const& { return get (HIERARCHICAL); }
std::string_view authority (void) const& { return get (AUTHORITY); }
std::string_view user (void) const& { return get (USER); }
std::string_view host (void) const& { return get (HOST); }
std::string_view port (void) const& { return get (PORT); }
@ -100,6 +94,9 @@ namespace cruft {
std::string_view query (void) const& { return get (QUERY); }
std::string_view fragment (void) const& { return get (FRAGMENT); }
std::string_view heirarchical (void) const&; //{ return { user ().begin (), path ().end () }; }
std::string_view authority (void) const&; //{ return { user ().begin (), port ().end () }; }
std::string_view
pqf (void) const& {
return {
@ -113,6 +110,8 @@ namespace cruft {
};
}
void set (component c, std::string_view val);
// void clear (component);
void clear_fragment (void);