markup.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "markup.h"
  2. #include <util/stream/output.h>
  3. #include <util/stream/mem.h>
  4. #include <util/string/strip.h>
  5. #include <util/string/cast.h>
  6. using namespace NConfig;
  7. #define DBG(x)
  8. namespace {
  9. #define MACHINE_DATA
  10. #include "markupfsm.h"
  11. #undef MACHINE_DATA
  12. class IXmlCB {
  13. public:
  14. inline void DoTagOpen(const TStringBuf& key) {
  15. DBG(Cerr << "topen" << key << Endl);
  16. S_.push_back(key);
  17. OnTagOpen(key);
  18. }
  19. inline void DoTagClose(const TStringBuf& key) {
  20. DBG(Cerr << "tclose" << key << Endl);
  21. if (S_.empty()) {
  22. ythrow yexception() << "unbalanced tag";
  23. }
  24. if (S_.back() != key) {
  25. ythrow yexception() << "unbalanced tag";
  26. }
  27. S_.pop_back();
  28. OnTagClose();
  29. }
  30. inline void DoText(const TStringBuf& text) {
  31. DBG(Cerr << "ttext" << text << Endl);
  32. if (!!text) {
  33. OnText(text);
  34. }
  35. }
  36. inline void DoAttrKey(const TStringBuf& key) {
  37. DBG(Cerr << "tattrkey" << key << Endl);
  38. A_ = key;
  39. }
  40. inline void DoAttrValue(const TStringBuf& key) {
  41. DBG(Cerr << "tattrvalue" << key << Endl);
  42. if (!A_) {
  43. ythrow yexception() << "dangling attribute";
  44. }
  45. OnAttr(A_, key);
  46. A_ = TStringBuf();
  47. }
  48. virtual void OnTagOpen(const TStringBuf& key) = 0;
  49. virtual void OnTagClose() = 0;
  50. virtual void OnText(const TStringBuf& text) = 0;
  51. virtual void OnAttr(const TStringBuf& key, const TStringBuf& value) = 0;
  52. virtual ~IXmlCB() = default;
  53. private:
  54. TVector<TStringBuf> S_;
  55. TStringBuf A_;
  56. };
  57. inline void Parse(TStringBuf s, IXmlCB* cb) {
  58. const char* p = s.data();
  59. const char* pe = s.end();
  60. const char* eof = pe;
  61. const char* l = p;
  62. int cs;
  63. TString cur;
  64. #define MACHINE_INIT
  65. #include "markupfsm.h"
  66. #undef MACHINE_INIT
  67. #define MACHINE_EXEC
  68. #include "markupfsm.h"
  69. #undef MACHINE_EXEC
  70. if (cs < ParseXml_first_final) {
  71. ythrow TConfigParseError() << "can not parse markup data at offset " << (p - s.data());
  72. }
  73. }
  74. inline IValue* SmartValue(const TStringBuf& v) {
  75. try {
  76. return ConstructValue(FromString<ui64>(v));
  77. } catch (...) {
  78. }
  79. try {
  80. return ConstructValue(FromString<i64>(v));
  81. } catch (...) {
  82. }
  83. try {
  84. return ConstructValue(FromString<double>(v));
  85. } catch (...) {
  86. }
  87. try {
  88. return ConstructValue(FromString<bool>(v));
  89. } catch (...) {
  90. }
  91. return ConstructValue(ToString(v));
  92. }
  93. inline TConfig Parse(TStringBuf s0) {
  94. struct TXmlParser: public IXmlCB {
  95. inline TXmlParser()
  96. : Root(ConstructValue(TDict()))
  97. {
  98. S.push_back(&Root);
  99. }
  100. void OnTagOpen(const TStringBuf& key) override {
  101. *Push(key) = ConstructValue(TDict());
  102. }
  103. void OnTagClose() override {
  104. S.pop_back();
  105. }
  106. static inline bool IsWS(char ch) {
  107. switch (ch) {
  108. case ' ':
  109. case '\t':
  110. case '\r':
  111. case '\n':
  112. case ':':
  113. return true;
  114. }
  115. return false;
  116. }
  117. void OnText(const TStringBuf& text) override {
  118. TMemoryInput mi(text.data(), text.size());
  119. TString line;
  120. while (mi.ReadLine(line)) {
  121. DBG(Cerr << line << Endl);
  122. TStringBuf s = StripString(TStringBuf(line));
  123. DBG(Cerr << s << Endl);
  124. if (!s) {
  125. continue;
  126. }
  127. const char* b = s.data();
  128. const char* c = b;
  129. const char* e = s.end();
  130. while (c < e && !IsWS(*c)) {
  131. ++c;
  132. }
  133. const TStringBuf key(b, c);
  134. while (c < e && IsWS(*c)) {
  135. ++c;
  136. }
  137. const TStringBuf value(c, e);
  138. if (!key) {
  139. continue;
  140. }
  141. DBG(Cerr << key << " " << value << Endl);
  142. SetAttr(key, value);
  143. }
  144. }
  145. void OnAttr(const TStringBuf& key, const TStringBuf& value) override {
  146. SetAttr(key, value);
  147. }
  148. inline void SetAttr(const TStringBuf& key, const TStringBuf& value) {
  149. Dict()[ToString(key)] = SmartValue(value);
  150. }
  151. inline TConfig* Top() {
  152. return S.back();
  153. }
  154. inline TConfig* Push(const TStringBuf& key) {
  155. TDict& d = Dict();
  156. const TString k = ToString(key);
  157. if (d.find(k) == d.end()) {
  158. S.push_back(&d[k]);
  159. } else {
  160. TConfig tmp = d[k];
  161. if (tmp.IsA<TArray>()) {
  162. TArray& arr = d[k].GetNonConstant<TArray>();
  163. arr.push_back(TConfig());
  164. S.push_back(&arr.back());
  165. } else {
  166. d[k] = ConstructValue(TArray());
  167. TArray& arr = d[k].GetNonConstant<TArray>();
  168. arr.push_back(tmp);
  169. arr.push_back(TConfig());
  170. S.push_back(&arr.back());
  171. }
  172. }
  173. return Top();
  174. }
  175. inline TDict& Dict() {
  176. try {
  177. return Top()->GetNonConstant<TDict>();
  178. } catch (...) {
  179. }
  180. return Top()->Get<TArray>().back().GetNonConstant<TDict>();
  181. }
  182. TConfig Root;
  183. TVector<TConfig*> S;
  184. };
  185. TXmlParser cb;
  186. Parse(s0, &cb);
  187. return cb.Root;
  188. }
  189. }
  190. TConfig NConfig::ParseRawMarkup(IInputStream& in) {
  191. return Parse(in.ReadAll());
  192. }