blob: dd07740a9edd892e78975707d75412c30fa29893 [file] [log] [blame]
/*//////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014-2016 Jamboree
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//////////////////////////////////////////////////////////////////////////////*/
#ifndef BUSTACHE_FORMAT_HPP_INCLUDED
#define BUSTACHE_FORMAT_HPP_INCLUDED
#include <bustache/ast.hpp>
#include <stdexcept>
#include <memory>
namespace bustache
{
struct format;
using option_type = bool;
constexpr option_type normal = false;
constexpr option_type escape_html = true;
template<class T, class Context>
struct manipulator
{
format const& fmt;
T const& data;
Context const& context;
option_type const flag;
};
struct no_context
{
using value_type = std::pair<std::string const, format>;
using iterator = value_type const*;
constexpr iterator find(std::string const&) const
{
return nullptr;
}
constexpr iterator end() const
{
return nullptr;
}
static no_context const& dummy()
{
static no_context const _{};
return _;
}
};
enum error_type
{
error_set_delim,
error_baddelim,
error_delim,
error_section,
error_badkey
};
class format_error : public std::runtime_error
{
error_type _err;
public:
explicit format_error(error_type err);
error_type code() const
{
return _err;
}
};
struct format
{
format() = default;
format(char const* begin, char const* end)
{
init(begin, end);
}
template<class Source>
explicit format(Source const& source)
{
init(source.data(), source.data() + source.size());
}
template<class Source>
explicit format(Source const&& source)
{
init(source.data(), source.data() + source.size());
copy_text(text_size());
}
template<std::size_t N>
explicit format(char const (&source)[N])
{
init(source, source + (N - 1));
}
explicit format(ast::content_list contents, bool copytext = true)
: _contents(std::move(contents))
{
if (copytext)
copy_text(text_size());
}
format(format&& other) noexcept
: _contents(std::move(other._contents)), _text(std::move(other._text))
{}
format(format const& other) : _contents(other._contents)
{
if (other._text)
copy_text(text_size());
}
template<class T>
manipulator<T, no_context>
operator()(T const& data, option_type flag = normal) const
{
return {*this, data, no_context::dummy(), flag};
}
template<class T, class Context>
manipulator<T, Context>
operator()(T const& data, Context const& context, option_type flag = normal) const
{
return {*this, data, context, flag};
}
ast::content_list const& contents() const
{
return _contents;
}
private:
void init(char const* begin, char const* end);
std::size_t text_size() const;
void copy_text(std::size_t n);
ast::content_list _contents;
std::unique_ptr<char[]> _text;
};
inline namespace literals
{
inline format operator"" _fmt(char const* str, std::size_t n)
{
return format(str, str + n);
}
}
}
#endif