]> git.stg.codes - stg.git/blob - libs/srvconf/parsers/get_container.h
Add instrumentation.
[stg.git] / libs / srvconf / parsers / get_container.h
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
19  */
20
21 #pragma once
22
23 #include "base.h"
24
25 #include <string>
26
27 #include <strings.h>
28
29 namespace STG
30 {
31 namespace GetContainer
32 {
33
34 template <typename ElementParser>
35 class Parser: public STG::Parser
36 {
37     public:
38         using Info = std::vector<typename ElementParser::Info>;
39         using Callback = void (*)(bool result, const std::string& reason, const Info& info, void* data);
40
41         Parser(const std::string& t, Callback f, void* d, const std::string& e)
42             : tag(t), callback(f), data(d), encoding(e),
43               elementParser(&Parser<ElementParser>::ElementCallback, this, e),
44               depth(0), parsingAnswer(false)
45         {}
46
47         int  ParseStart(const char* el, const char** attr) override
48         {
49             depth++;
50             if (depth == 1 && strcasecmp(el, tag.c_str()) == 0)
51                 parsingAnswer = true;
52
53             if (depth > 1 && parsingAnswer)
54                 elementParser.ParseStart(el, attr);
55
56             return 0;
57         }
58         void ParseEnd(const char* el) override
59         {
60             depth--;
61             if (depth > 0 && parsingAnswer)
62                 elementParser.ParseEnd(el);
63
64             if (depth == 0 && parsingAnswer)
65             {
66                 if (callback)
67                     callback(error.empty(), error, info, data);
68                 error.clear();
69                 info.clear();
70                 parsingAnswer = false;
71             }
72         }
73         void Failure(const std::string & reason) override { callback(false, reason, info, data); }
74
75     private:
76         std::string tag;
77         Callback callback;
78         void* data;
79         std::string encoding;
80         ElementParser elementParser;
81         Info info;
82         int depth;
83         bool parsingAnswer;
84         std::string error;
85
86         void AddElement(const typename ElementParser::Info& elementInfo)
87         {
88             info.push_back(elementInfo);
89         }
90         void SetError(const std::string& e) { error = e; }
91
92         static void ElementCallback(bool result, const std::string& reason, const typename ElementParser::Info& info, void* data)
93         {
94             auto parser = static_cast<Parser<ElementParser>*>(data);
95             if (!result)
96                 parser->SetError(reason);
97             else
98                 parser->AddElement(info);
99         }
100 };
101
102 } // namespace GET_CONTAINER
103 } // namespace STG