nginxconfig
C++libraryforparsingandprintingnginx.conf
nginxconfig/encode.cpp
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Friends Defines