Program Listing for File Template.h¶
↰ Return to documentation for file (uri-template/Template.h
)
#pragma once
#include "Operator.h"
#include "Variable.h"
namespace URI {
namespace Template {
namespace detail { // NOLINT(readability-identifier-naming)
template <typename...>
struct typelist;
}
class Literal
{
public:
static const std::unordered_set<char> kNotAllowedChars;
Literal(std::string&& lit_string);
Literal(const Literal&) = default;
Literal& operator=(const Literal&) = default;
Literal(Literal&&) noexcept = default;
Literal& operator=(Literal&&) noexcept = default;
~Literal() = default;
std::size_t Size() const;
const std::string& String() const noexcept;
bool operator==(const Literal& rhs) const;
bool operator!=(const Literal& rhs) const;
private:
std::string lit_string_;
};
class Expression
{
public:
Expression(std::shared_ptr<Operator>&& oper, std::vector<Variable>&& variables);
Expression(const Expression&) = default;
Expression& operator=(const Expression&) = default;
Expression(Expression&&) noexcept = default;
Expression& operator=(Expression&&) noexcept = default;
~Expression() = default;
const Operator& Oper() const;
const std::vector<Variable>& Vars() const;
std::string String() const noexcept;
bool operator==(const Expression& rhs) const;
bool operator!=(const Expression& rhs) const;
private:
std::shared_ptr<Operator> oper_;
std::vector<Variable> var_list_;
};
enum class PartType
{
LITERAL,
EXPRESSION
};
class Part
{
public:
template <typename... Args, typename = std::enable_if_t<!std::is_same<
detail::typelist<Part>, detail::typelist<std::decay_t<Args>...>>::value>>
Part(Args&&... args)
: part_(std::forward<Args>(args)...)
{
if (std::holds_alternative<Literal>(part_)) {
type_ = PartType::LITERAL;
} else {
type_ = PartType::EXPRESSION;
}
}
Part(const Part&) = default;
Part& operator=(const Part&) = default;
Part(Part&&) noexcept = default;
Part& operator=(Part&&) noexcept = default;
~Part() = default;
template <class T>
T& Get()
{
return std::get<T>(part_);
}
template <class T>
const T& Get() const
{
return std::get<T>(part_);
}
inline PartType Type() const
{
return type_;
}
inline std::string String() const noexcept
{
if (std::holds_alternative<Literal>(part_)) {
return Get<Literal>().String();
}
return Get<Expression>().String();
}
inline bool operator==(const Part& rhs) const
{
return type_ == rhs.type_ && part_ == rhs.part_;
}
inline bool operator!=(const Part& rhs) const
{
return !(*this == rhs);
}
private:
PartType type_;
std::variant<Literal, Expression> part_;
};
class Template
{
public:
Template() = default;
Template(const Template&) = default;
Template& operator=(const Template&) = default;
Template(Template&&) noexcept = default;
Template& operator=(Template&&) noexcept = default;
~Template() = default;
template <class... Args>
Part& EmplaceBack(Args&&... args)
{
return parts_.emplace_back(std::forward<Args>(args)...);
}
bool IsTemplated() const;
std::size_t Size() const;
std::vector<Part>& Parts();
const std::vector<Part>& Parts() const;
Part& operator[](std::size_t pos);
const Part& operator[](std::size_t pos) const;
std::string String() const noexcept;
private:
std::vector<Part> parts_;
};
} // namespace Template
} // namespace URI