97 lines
3.6 KiB
C++
97 lines
3.6 KiB
C++
#include "TemplateSegmentRule.h"
|
|
#include "BoostLog.h"
|
|
#include <boost/url/decode_view.hpp>
|
|
#include <boost/url/detail/replacement_field_rule.hpp>
|
|
#include <boost/url/error.hpp>
|
|
#include <boost/url/grammar.hpp>
|
|
#include <boost/url/rfc/detail/path_rules.hpp>
|
|
#include <string_view>
|
|
|
|
boost::urls::result<TemplateSegmentRule::value_type> TemplateSegmentRule::parse(const char *&iterator,
|
|
const char *end) const noexcept {
|
|
TemplateSegmentRule::value_type ret;
|
|
bool isTemplate = false;
|
|
if (iterator != end && *iterator == '{') {
|
|
auto it0 = iterator;
|
|
++iterator;
|
|
auto rightBraces = boost::urls::grammar::find_if(iterator, end, boost::urls::grammar::lut_chars('}'));
|
|
if (rightBraces != end) {
|
|
boost::core::string_view segment(iterator, rightBraces);
|
|
static constexpr auto modifiers_cs = boost::urls::grammar::lut_chars("?*+");
|
|
static constexpr auto id_rule = boost::urls::grammar::tuple_rule(
|
|
boost::urls::grammar::optional_rule(boost::urls::detail::arg_id_rule),
|
|
boost::urls::grammar::optional_rule(boost::urls::grammar::delim_rule(modifiers_cs)));
|
|
if (segment.empty() || boost::urls::grammar::parse(segment, id_rule)) {
|
|
isTemplate = true;
|
|
iterator = rightBraces + 1;
|
|
ret.m_string = boost::core::string_view(it0, rightBraces + 1);
|
|
ret.m_isLiteral = false;
|
|
if (segment.ends_with('?'))
|
|
ret.modifier = TemplateSegment::Modifier::Optional;
|
|
else if (segment.ends_with('*'))
|
|
ret.modifier = TemplateSegment::Modifier::Star;
|
|
else if (segment.ends_with('+'))
|
|
ret.modifier = TemplateSegment::Modifier::Plus;
|
|
}
|
|
}
|
|
if (!isTemplate) iterator = it0;
|
|
}
|
|
if (!isTemplate) {
|
|
auto rv = boost::urls::grammar::parse(iterator, end, boost::urls::detail::segment_rule);
|
|
BOOST_ASSERT(rv);
|
|
rv->decode({}, boost::urls::string_token::assign_to(ret.m_string));
|
|
ret.m_isLiteral = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool TemplateSegment::isLiteral() const {
|
|
return m_isLiteral;
|
|
}
|
|
|
|
bool TemplateSegment::isStar() const {
|
|
return modifier == Modifier::Star;
|
|
}
|
|
|
|
bool TemplateSegment::isPlus() const {
|
|
return modifier == Modifier::Plus;
|
|
}
|
|
|
|
bool TemplateSegment::isOptional() const {
|
|
return modifier == Modifier::Optional;
|
|
}
|
|
|
|
bool TemplateSegment::hasModifier() const {
|
|
return !m_isLiteral && modifier != Modifier::None;
|
|
}
|
|
|
|
boost::core::string_view TemplateSegment::id() const {
|
|
BOOST_ASSERT(!isLiteral());
|
|
boost::core::string_view r = {m_string};
|
|
r.remove_prefix(1);
|
|
r.remove_suffix(1);
|
|
if (r.ends_with('?') || r.ends_with('+') || r.ends_with('*')) r.remove_suffix(1);
|
|
return r;
|
|
}
|
|
|
|
boost::core::string_view TemplateSegment::string() const {
|
|
return m_string;
|
|
}
|
|
|
|
bool TemplateSegment::match(boost::urls::pct_string_view segement) const {
|
|
if (m_isLiteral) return *segement == m_string;
|
|
return true; // other nodes match any string
|
|
}
|
|
|
|
bool TemplateSegment::operator==(const TemplateSegment &other) const {
|
|
if (m_isLiteral != other.m_isLiteral) return false;
|
|
if (m_isLiteral) return m_string == other.m_string;
|
|
return modifier == other.modifier;
|
|
}
|
|
|
|
bool TemplateSegment::operator<(const TemplateSegment &other) const {
|
|
if (other.m_isLiteral) return false;
|
|
if (m_isLiteral) return !other.m_isLiteral;
|
|
return modifier < other.modifier;
|
|
}
|