nginxconfig
C++libraryforparsingandprintingnginx.conf
|
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 }