123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- #include "markup.h"
- #include <util/stream/output.h>
- #include <util/stream/mem.h>
- #include <util/string/strip.h>
- #include <util/string/cast.h>
- using namespace NConfig;
- #define DBG(x)
- namespace {
- #define MACHINE_DATA
- #include "markupfsm.h"
- #undef MACHINE_DATA
- class IXmlCB {
- public:
- inline void DoTagOpen(const TStringBuf& key) {
- DBG(Cerr << "topen" << key << Endl);
- S_.push_back(key);
- OnTagOpen(key);
- }
- inline void DoTagClose(const TStringBuf& key) {
- DBG(Cerr << "tclose" << key << Endl);
- if (S_.empty()) {
- ythrow yexception() << "unbalanced tag";
- }
- if (S_.back() != key) {
- ythrow yexception() << "unbalanced tag";
- }
- S_.pop_back();
- OnTagClose();
- }
- inline void DoText(const TStringBuf& text) {
- DBG(Cerr << "ttext" << text << Endl);
- if (!!text) {
- OnText(text);
- }
- }
- inline void DoAttrKey(const TStringBuf& key) {
- DBG(Cerr << "tattrkey" << key << Endl);
- A_ = key;
- }
- inline void DoAttrValue(const TStringBuf& key) {
- DBG(Cerr << "tattrvalue" << key << Endl);
- if (!A_) {
- ythrow yexception() << "dangling attribute";
- }
- OnAttr(A_, key);
- A_ = TStringBuf();
- }
- virtual void OnTagOpen(const TStringBuf& key) = 0;
- virtual void OnTagClose() = 0;
- virtual void OnText(const TStringBuf& text) = 0;
- virtual void OnAttr(const TStringBuf& key, const TStringBuf& value) = 0;
- virtual ~IXmlCB() = default;
- private:
- TVector<TStringBuf> S_;
- TStringBuf A_;
- };
- inline void Parse(TStringBuf s, IXmlCB* cb) {
- const char* p = s.data();
- const char* pe = s.end();
- const char* eof = pe;
- const char* l = p;
- int cs;
- TString cur;
- #define MACHINE_INIT
- #include "markupfsm.h"
- #undef MACHINE_INIT
- #define MACHINE_EXEC
- #include "markupfsm.h"
- #undef MACHINE_EXEC
- if (cs < ParseXml_first_final) {
- ythrow TConfigParseError() << "can not parse markup data at offset " << (p - s.data());
- }
- }
- inline IValue* SmartValue(const TStringBuf& v) {
- try {
- return ConstructValue(FromString<ui64>(v));
- } catch (...) {
- }
- try {
- return ConstructValue(FromString<i64>(v));
- } catch (...) {
- }
- try {
- return ConstructValue(FromString<double>(v));
- } catch (...) {
- }
- try {
- return ConstructValue(FromString<bool>(v));
- } catch (...) {
- }
- return ConstructValue(ToString(v));
- }
- inline TConfig Parse(TStringBuf s0) {
- struct TXmlParser: public IXmlCB {
- inline TXmlParser()
- : Root(ConstructValue(TDict()))
- {
- S.push_back(&Root);
- }
- void OnTagOpen(const TStringBuf& key) override {
- *Push(key) = ConstructValue(TDict());
- }
- void OnTagClose() override {
- S.pop_back();
- }
- static inline bool IsWS(char ch) {
- switch (ch) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case ':':
- return true;
- }
- return false;
- }
- void OnText(const TStringBuf& text) override {
- TMemoryInput mi(text.data(), text.size());
- TString line;
- while (mi.ReadLine(line)) {
- DBG(Cerr << line << Endl);
- TStringBuf s = StripString(TStringBuf(line));
- DBG(Cerr << s << Endl);
- if (!s) {
- continue;
- }
- const char* b = s.data();
- const char* c = b;
- const char* e = s.end();
- while (c < e && !IsWS(*c)) {
- ++c;
- }
- const TStringBuf key(b, c);
- while (c < e && IsWS(*c)) {
- ++c;
- }
- const TStringBuf value(c, e);
- if (!key) {
- continue;
- }
- DBG(Cerr << key << " " << value << Endl);
- SetAttr(key, value);
- }
- }
- void OnAttr(const TStringBuf& key, const TStringBuf& value) override {
- SetAttr(key, value);
- }
- inline void SetAttr(const TStringBuf& key, const TStringBuf& value) {
- Dict()[ToString(key)] = SmartValue(value);
- }
- inline TConfig* Top() {
- return S.back();
- }
- inline TConfig* Push(const TStringBuf& key) {
- TDict& d = Dict();
- const TString k = ToString(key);
- if (d.find(k) == d.end()) {
- S.push_back(&d[k]);
- } else {
- TConfig tmp = d[k];
- if (tmp.IsA<TArray>()) {
- TArray& arr = d[k].GetNonConstant<TArray>();
- arr.push_back(TConfig());
- S.push_back(&arr.back());
- } else {
- d[k] = ConstructValue(TArray());
- TArray& arr = d[k].GetNonConstant<TArray>();
- arr.push_back(tmp);
- arr.push_back(TConfig());
- S.push_back(&arr.back());
- }
- }
- return Top();
- }
- inline TDict& Dict() {
- try {
- return Top()->GetNonConstant<TDict>();
- } catch (...) {
- }
- return Top()->Get<TArray>().back().GetNonConstant<TDict>();
- }
- TConfig Root;
- TVector<TConfig*> S;
- };
- TXmlParser cb;
- Parse(s0, &cb);
- return cb.Root;
- }
- }
- TConfig NConfig::ParseRawMarkup(IInputStream& in) {
- return Parse(in.ReadAll());
- }
|