#include "TemplateSegmentRule.h" #include "BoostLog.h" #include #include #include #include #include #include boost::system::result 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; }