nginxconfig
C++libraryforparsingandprintingnginx.conf
nginxconfig/ast.cpp
Go to the documentation of this file.
00001 
00011 #include <nginxconfig/ast.hpp>
00012 #include <nginxconfig/encode.hpp>
00013 
00014 #include <algorithm>
00015 #include <sstream>
00016 #include <tuple>
00017 
00018 namespace nginxconfig
00019 {
00020 
00022 // Helpers                                                                                                            //
00024 
00025 void check_kind(std::initializer_list<ast_entry_kind> expected, ast_entry_kind actual)
00026 {
00027     if (std::none_of(expected.begin(), expected.end(), [actual] (ast_entry_kind x) { return x == actual; }))
00028     {
00029         std::ostringstream stream;
00030         stream << "Unexpected kind: expected ";
00031         std::size_t num = 1;
00032         for (ast_entry_kind k : expected)
00033         {
00034             stream << k;
00035             if (num + 1 < expected.size())
00036                 stream << ", ";
00037             else if (num < expected.size())
00038                 stream << " or ";
00039             ++num;
00040         }
00041         throw kind_error(stream.str());
00042     }
00043 }
00044 
00046 // ast_entry_kind                                                                                                     //
00048 
00049 std::ostream& operator<<(std::ostream& os, const ast_entry_kind& kind)
00050 {
00051     switch (kind)
00052     {
00053     case ast_entry_kind::complex:  return os << "complex";
00054     case ast_entry_kind::comment:  return os << "comment";
00055     case ast_entry_kind::document: return os << "document";
00056     case ast_entry_kind::simple:   return os << "simple";
00057     default:                       return os << "???";
00058     }
00059 }
00060 
00062 // kind_error                                                                                                         //
00064 
00065 kind_error::kind_error(const std::string& description) :
00066         std::logic_error(description)
00067 { }
00068 
00069 kind_error::~kind_error() noexcept = default;
00070 
00072 // ast_entry                                                                                                          //
00074 
00075 ast_entry::ast_entry(ast_entry_kind kind_) :
00076         _kind(kind_)
00077 { }
00078 
00079 ast_entry::ast_entry(const ast_entry&) = default;
00080 ast_entry& ast_entry::operator=(const ast_entry&) = default;
00081 
00082 ast_entry::ast_entry(ast_entry&& src) noexcept :
00083         _kind(src._kind),
00084         _name(std::move(src._name)),
00085         _attributes(std::move(src._attributes)),
00086         _children(std::move(src._children)),
00087         _comment(std::move(src._comment))
00088 { }
00089 
00090 ast_entry& ast_entry::operator=(ast_entry&& src) noexcept
00091 {
00092     _kind = src._kind;
00093     _name = std::move(src._name);
00094     _attributes = std::move(src._attributes);
00095     _children = std::move(src._children);
00096     _comment = std::move(src._comment);
00097     return *this;
00098 }
00099 
00100 ast_entry::~ast_entry() noexcept = default;
00101 
00102 void swap(ast_entry& a, ast_entry& b) noexcept
00103 {
00104     using std::swap;
00105     swap(a._kind, b._kind);
00106     swap(a._name, b._name);
00107     swap(a._attributes, b._attributes);
00108     swap(a._children, b._children);
00109     swap(a._comment, b._comment);
00110 }
00111 
00112 ast_entry ast_entry::make_complex(std::string    name,
00113                                   attribute_list attributes,
00114                                   child_list     children
00115                                  )
00116 {
00117     ast_entry out(ast_entry_kind::complex);
00118     out.name()       = std::move(name);
00119     out.attributes() = std::move(attributes);
00120     out.children()   = std::move(children);
00121     return out;
00122 }
00123 
00124 ast_entry ast_entry::make_document(child_list children)
00125 {
00126     ast_entry out(ast_entry_kind::document);
00127     out.children()   = std::move(children);
00128     return out;
00129 }
00130 
00131 ast_entry ast_entry::make_simple(std::string    name,
00132                                  attribute_list attributes,
00133                                  std::string    comment_text
00134                                 )
00135 {
00136     ast_entry out(ast_entry_kind::simple);
00137     out.name()       = std::move(name);
00138     out.attributes() = std::move(attributes);
00139     out.comment()    = std::move(comment_text);
00140     return out;
00141 }
00142 
00143 ast_entry ast_entry::make_comment(std::string comment_text)
00144 {
00145     ast_entry out(ast_entry_kind::comment);
00146     out.comment() = std::move(comment_text);
00147     return out;
00148 }
00149 
00150 ast_entry_kind ast_entry::kind() const
00151 {
00152     return _kind;
00153 }
00154 
00155 const ast_entry::attribute_list& ast_entry::attributes() const
00156 {
00157     check_kind({ ast_entry_kind::complex, ast_entry_kind::simple }, kind());
00158     return _attributes;
00159 }
00160 
00161 ast_entry::attribute_list& ast_entry::attributes()
00162 {
00163     check_kind({ ast_entry_kind::complex, ast_entry_kind::simple }, kind());
00164     return _attributes;
00165 }
00166 
00167 const ast_entry::child_list& ast_entry::children() const
00168 {
00169     check_kind({ ast_entry_kind::complex, ast_entry_kind::document }, kind());
00170     return _children;
00171 }
00172 
00173 ast_entry::child_list& ast_entry::children()
00174 {
00175     check_kind({ ast_entry_kind::complex, ast_entry_kind::document }, kind());
00176     return _children;
00177 }
00178 
00179 const std::string& ast_entry::comment() const
00180 {
00181     check_kind({ ast_entry_kind::comment, ast_entry_kind::simple, ast_entry_kind::complex }, kind());
00182     return _comment;
00183 }
00184 
00185 std::string& ast_entry::comment()
00186 {
00187     check_kind({ ast_entry_kind::comment, ast_entry_kind::simple, ast_entry_kind::complex }, kind());
00188     return _comment;
00189 }
00190 
00191 const std::string& ast_entry::name() const
00192 {
00193     check_kind({ ast_entry_kind::complex, ast_entry_kind::simple }, kind());
00194     return _name;
00195 }
00196 
00197 std::string& ast_entry::name()
00198 {
00199     check_kind({ ast_entry_kind::complex, ast_entry_kind::simple }, kind());
00200     return _name;
00201 }
00202 
00203 #define NGINXCONFIG_AST_ENTRY_TIE_TUPLE(x)                                                                             \
00204     std::tie((x)._kind, (x)._name, (x)._attributes, (x)._children, (x)._comment)
00205 
00206 bool ast_entry::operator==(const ast_entry& other) const
00207 {
00208     return NGINXCONFIG_AST_ENTRY_TIE_TUPLE(*this) == NGINXCONFIG_AST_ENTRY_TIE_TUPLE(other);
00209 }
00210 
00211 bool ast_entry::operator!=(const ast_entry& other) const
00212 {
00213     return NGINXCONFIG_AST_ENTRY_TIE_TUPLE(*this) != NGINXCONFIG_AST_ENTRY_TIE_TUPLE(other);
00214 }
00215 
00216 std::ostream& operator<<(std::ostream& os, const ast_entry& ast)
00217 {
00218     encode(ast, os);
00219     return os;
00220 }
00221 
00222 }
 All Classes Files Functions Variables Friends Defines