nginxconfig
C++libraryforparsingandprintingnginx.conf
|
00001 00011 #include <nginxconfig/ast.hpp> 00012 #include <nginxconfig/encode.hpp> 00013 00014 #include <cassert> 00015 #include <ostream> 00016 00017 namespace nginxconfig 00018 { 00019 00021 // encoder // 00023 00024 const encoder::context::path_type& encoder::context::path() const 00025 { 00026 return _path; 00027 } 00028 00029 encoder::context::size_type encoder::context::indent_level() const 00030 { 00031 return _path.empty() ? 0 : _path.size() - 1; 00032 } 00033 00034 encoder::~encoder() noexcept = default; 00035 00036 void encoder::encode(const ast_entry& ast) 00037 { 00038 context cxt; 00039 return encode_impl(cxt, ast); 00040 } 00041 00042 void encoder::encode_impl(encoder::context& cxt, const ast_entry& ast) 00043 { 00044 switch (ast.kind()) 00045 { 00046 case ast_entry_kind::comment: 00047 write_comment(cxt, ast); 00048 break; 00049 case ast_entry_kind::complex: 00050 case ast_entry_kind::document: 00051 if (ast.kind() == ast_entry_kind::complex) 00052 write_complex_begin(cxt, ast); 00053 else 00054 write_document_begin(cxt, ast); 00055 00056 cxt._path.push_back(&ast); 00057 for (const ast_entry& sub : ast.children()) 00058 { 00059 encode_impl(cxt, sub); 00060 } 00061 cxt._path.pop_back(); 00062 00063 if (ast.kind() == ast_entry_kind::complex) 00064 write_complex_end(cxt, ast); 00065 else 00066 write_document_end(cxt, ast); 00067 break; 00068 case ast_entry_kind::simple: 00069 write_simple(cxt, ast); 00070 break; 00071 default: 00072 assert(false && "Memory corruption?"); 00073 break; 00074 } 00075 } 00076 00077 void encoder::write_document_begin(const context&, const ast_entry&) 00078 { } 00079 00080 void encoder::write_document_end(const context&, const ast_entry&) 00081 { } 00082 00084 // ostream_encoder // 00086 00087 static const std::string default_indent = " "; 00088 00089 ostream_encoder::ostream_encoder(std::ostream& output, std::string indent) : 00090 _output(output), 00091 _indent(indent) 00092 { } 00093 00094 ostream_encoder::ostream_encoder(std::ostream& output) : 00095 ostream_encoder(output, default_indent) 00096 { } 00097 00098 ostream_encoder::~ostream_encoder() noexcept = default; 00099 00100 void ostream_encoder::write_attributes(const ast_entry& ast) 00101 { 00102 for (const auto& attr : ast.attributes()) 00103 _output << ' ' << attr; 00104 } 00105 00106 void ostream_encoder::write_comment(const context& cxt, const ast_entry& ast) 00107 { 00108 write_indent(cxt); 00109 if (!ast.comment().empty()) 00110 _output << '#' << ast.comment(); 00111 _output << std::endl; 00112 } 00113 00114 void ostream_encoder::write_complex_begin(const context& cxt, const ast_entry& ast) 00115 { 00116 write_indent(cxt); 00117 _output << ast.name(); 00118 write_attributes(ast); 00119 _output << " {"; 00120 if (!ast.comment().empty()) 00121 _output << '#' << ast.comment(); 00122 _output << std::endl; 00123 } 00124 00125 void ostream_encoder::write_complex_end(const context& cxt, const ast_entry&) 00126 { 00127 write_indent(cxt); 00128 _output << '}'; 00129 _output << std::endl; 00130 } 00131 00132 void ostream_encoder::write_indent(const context& cxt) 00133 { 00134 for (context::size_type x = 0; x < cxt.indent_level(); ++x) 00135 _output << _indent; 00136 } 00137 00138 void ostream_encoder::write_simple(const encoder::context& cxt, const ast_entry& ast) 00139 { 00140 write_indent(cxt); 00141 _output << ast.name(); 00142 write_attributes(ast); 00143 _output << " ;"; 00144 if (!ast.comment().empty()) 00145 _output << '#' << ast.comment(); 00146 _output << std::endl; 00147 } 00148 00150 // Free Functions // 00152 00153 void encode(const ast_entry& ast, std::ostream& output, std::string indent) 00154 { 00155 ostream_encoder encoder(output, std::move(indent)); 00156 encoder.encode(ast); 00157 } 00158 00159 void encode(const ast_entry& ast, std::ostream& output) 00160 { 00161 return encode(ast, output, default_indent); 00162 } 00163 00164 }