writer.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. #pragma once
  2. #include "byte_writer.h"
  3. #include "cescape.h"
  4. #include "percent_scalar.h"
  5. #include "stream_counter.h"
  6. #include "symbols.h"
  7. #include "varint.h"
  8. #include <library/cpp/yson_pull/consumer.h>
  9. #include <library/cpp/yson_pull/event.h>
  10. #include <library/cpp/yson_pull/output.h>
  11. #include <library/cpp/yson_pull/stream_type.h>
  12. #include <library/cpp/yson_pull/writer.h>
  13. #include <util/generic/vector.h>
  14. #include <util/system/yassert.h>
  15. #include <cmath>
  16. namespace NYsonPull {
  17. namespace NDetail {
  18. class writer: public IConsumer {
  19. enum class state {
  20. maybe_key,
  21. maybe_value,
  22. value,
  23. value_noattr,
  24. before_begin,
  25. before_end,
  26. after_end,
  27. };
  28. byte_writer<stream_counter<false>> stream_;
  29. TVector<EEventType> stack_;
  30. bool need_item_separator_ = false;
  31. EStreamType mode_ = EStreamType::ListFragment;
  32. state state_ = state::before_begin;
  33. public:
  34. void OnBeginStream() override {
  35. update_state(EEventType::BeginStream);
  36. }
  37. void OnEndStream() override {
  38. update_state(EEventType::EndStream);
  39. stream_.flush_buffer();
  40. }
  41. void OnBeginList() override {
  42. begin_node();
  43. write(NSymbol::begin_list);
  44. update_state(EEventType::BeginList);
  45. begin_collection(collection_type::list);
  46. }
  47. void OnEndList() override {
  48. update_state(EEventType::EndList);
  49. end_collection(collection_type::list);
  50. write(NSymbol::end_list);
  51. end_node();
  52. }
  53. void OnBeginMap() override {
  54. begin_node();
  55. write(NSymbol::begin_map);
  56. update_state(EEventType::BeginMap);
  57. begin_collection(collection_type::map);
  58. }
  59. void OnEndMap() override {
  60. update_state(EEventType::EndMap);
  61. end_collection(collection_type::map);
  62. write(NSymbol::end_map);
  63. end_node();
  64. }
  65. void OnBeginAttributes() override {
  66. begin_node();
  67. write(NSymbol::begin_attributes);
  68. update_state(EEventType::BeginAttributes);
  69. begin_collection(collection_type::attributes);
  70. }
  71. void OnEndAttributes() override {
  72. update_state(EEventType::EndAttributes);
  73. end_collection(collection_type::attributes);
  74. write(NSymbol::end_attributes);
  75. // no end_node
  76. }
  77. void OnEntity() override {
  78. begin_node();
  79. update_state(EEventType::Scalar);
  80. write(NSymbol::entity);
  81. end_node();
  82. }
  83. protected:
  84. enum class collection_type {
  85. list,
  86. map,
  87. attributes,
  88. };
  89. writer(NYsonPull::NOutput::IStream& stream, EStreamType mode)
  90. : stream_(stream)
  91. , mode_{mode} {
  92. }
  93. bool need_item_separator() const {
  94. return need_item_separator_;
  95. }
  96. void need_item_separator(bool value) {
  97. need_item_separator_ = value;
  98. }
  99. size_t depth() const {
  100. Y_ASSERT(!stack_.empty());
  101. if (mode_ == EStreamType::Node) {
  102. return stack_.size() - 1;
  103. } else {
  104. return stack_.size() - 2;
  105. }
  106. }
  107. EStreamType mode() const {
  108. return mode_;
  109. }
  110. void write(ui8 c) {
  111. stream_.write(c);
  112. }
  113. void write(TStringBuf value) {
  114. write_raw(value.data(), value.size());
  115. }
  116. void write_raw(const void* ptr, size_t len) {
  117. stream_.write(static_cast<const ui8*>(ptr), len);
  118. }
  119. template <typename T>
  120. void write_varint(T value) {
  121. NVarInt::write(stream_, value);
  122. }
  123. void write_escaped_string(TStringBuf value) {
  124. write(NSymbol::quote);
  125. NCEscape::encode(stream_, value);
  126. write(NSymbol::quote);
  127. }
  128. void push(EEventType type) {
  129. stack_.push_back(type);
  130. }
  131. void pop(EEventType type) {
  132. if (stack_.empty()) {
  133. fail("Unpaired events: empty event stack");
  134. }
  135. if (stack_.back() != type) {
  136. fail("Unpaired events: expected ", type, ", got ", stack_.back());
  137. }
  138. stack_.pop_back();
  139. }
  140. void update_state(EEventType event) {
  141. switch (state_) {
  142. case state::before_begin:
  143. if (event != EEventType::BeginStream) {
  144. fail("Expected begin_stream, got ", event);
  145. }
  146. begin_stream();
  147. return;
  148. case state::before_end:
  149. if (event != EEventType::EndStream) {
  150. fail("Expected end_stream, got ", event);
  151. }
  152. end_stream();
  153. return;
  154. case state::after_end:
  155. fail("Attempted write past stream end");
  156. case state::maybe_key:
  157. if (event == EEventType::Key) {
  158. state_ = state::value;
  159. return;
  160. }
  161. switch (event) {
  162. case EEventType::EndStream:
  163. end_stream();
  164. return;
  165. case EEventType::EndMap:
  166. pop(EEventType::BeginMap);
  167. next_state();
  168. return;
  169. case EEventType::EndAttributes:
  170. pop(EEventType::BeginAttributes);
  171. state_ = state::value_noattr;
  172. return;
  173. default:
  174. fail("Unexpected event ", event, " in maybe_key");
  175. }
  176. break;
  177. case state::maybe_value:
  178. switch (event) {
  179. case EEventType::EndList:
  180. pop(EEventType::BeginList);
  181. next_state();
  182. return;
  183. case EEventType::EndStream:
  184. end_stream();
  185. return;
  186. default:
  187. break;
  188. }
  189. [[fallthrough]];
  190. case state::value:
  191. if (event == EEventType::BeginAttributes) {
  192. push(EEventType::BeginAttributes);
  193. next_state();
  194. return;
  195. }
  196. [[fallthrough]];
  197. case state::value_noattr:
  198. switch (event) {
  199. case EEventType::Scalar:
  200. next_state();
  201. return;
  202. case EEventType::BeginList:
  203. push(EEventType::BeginList);
  204. next_state();
  205. return;
  206. case EEventType::BeginMap:
  207. push(EEventType::BeginMap);
  208. next_state();
  209. return;
  210. default:
  211. fail("Unexpected event ", event, " (in value_*)");
  212. }
  213. break;
  214. }
  215. }
  216. void next_state() {
  217. Y_ASSERT(!stack_.empty());
  218. switch (stack_.back()) {
  219. case EEventType::BeginMap:
  220. case EEventType::BeginAttributes:
  221. state_ = state::maybe_key;
  222. break;
  223. case EEventType::BeginList:
  224. state_ = state::maybe_value;
  225. break;
  226. case EEventType::BeginStream:
  227. state_ = state::before_end;
  228. break;
  229. default:
  230. Y_UNREACHABLE();
  231. }
  232. }
  233. void begin_stream() {
  234. push(EEventType::BeginStream);
  235. switch (mode_) {
  236. case EStreamType::ListFragment:
  237. push(EEventType::BeginList);
  238. state_ = state::maybe_value;
  239. break;
  240. case EStreamType::MapFragment:
  241. push(EEventType::BeginMap);
  242. state_ = state::maybe_key;
  243. break;
  244. case EStreamType::Node:
  245. state_ = state::value;
  246. break;
  247. }
  248. }
  249. void end_stream() {
  250. switch (mode_) {
  251. case EStreamType::ListFragment:
  252. pop(EEventType::BeginList);
  253. break;
  254. case EStreamType::MapFragment:
  255. pop(EEventType::BeginMap);
  256. break;
  257. case EStreamType::Node:
  258. break;
  259. }
  260. pop(EEventType::BeginStream);
  261. state_ = state::after_end;
  262. }
  263. virtual void begin_node() {
  264. if (need_item_separator_) {
  265. write(NSymbol::item_separator);
  266. }
  267. }
  268. virtual void end_node() {
  269. need_item_separator_ = true;
  270. }
  271. virtual void begin_key() {
  272. begin_node();
  273. }
  274. virtual void end_key() {
  275. need_item_separator_ = false;
  276. write(NSymbol::key_value_separator);
  277. }
  278. virtual void begin_collection(collection_type type) {
  279. Y_UNUSED(type);
  280. need_item_separator_ = false;
  281. }
  282. virtual void end_collection(collection_type type) {
  283. need_item_separator_ = (type != collection_type::attributes);
  284. }
  285. template <typename... Args>
  286. ATTRIBUTE(noinline, cold)
  287. void fail[[noreturn]](const char* msg, Args&&... args) {
  288. auto formatted_message = format_string(
  289. msg,
  290. std::forward<Args>(args)...);
  291. throw NException::TBadOutput(
  292. formatted_message,
  293. stream_.counter().info());
  294. }
  295. };
  296. class TBinaryWriterImpl final: public writer {
  297. public:
  298. TBinaryWriterImpl(NYsonPull::NOutput::IStream& stream, EStreamType mode)
  299. : writer(stream, mode)
  300. {
  301. }
  302. void OnScalarBoolean(bool value) override {
  303. update_state(EEventType::Scalar);
  304. begin_node();
  305. write(value ? NSymbol::true_marker : NSymbol::false_marker);
  306. end_node();
  307. }
  308. void OnScalarInt64(i64 value) override {
  309. update_state(EEventType::Scalar);
  310. begin_node();
  311. write(NSymbol::int64_marker);
  312. write_varint(value);
  313. end_node();
  314. }
  315. void OnScalarUInt64(ui64 value) override {
  316. update_state(EEventType::Scalar);
  317. begin_node();
  318. write(NSymbol::uint64_marker);
  319. write_varint(value);
  320. end_node();
  321. }
  322. void OnScalarFloat64(double value) override {
  323. update_state(EEventType::Scalar);
  324. begin_node();
  325. write(NSymbol::double_marker);
  326. write_raw(&value, sizeof value);
  327. end_node();
  328. }
  329. void OnScalarString(TStringBuf value) override {
  330. update_state(EEventType::Scalar);
  331. begin_node();
  332. write(NSymbol::string_marker);
  333. write_varint(static_cast<i32>(value.size()));
  334. write_raw(value.data(), value.size());
  335. end_node();
  336. }
  337. void OnKey(TStringBuf name) override {
  338. update_state(EEventType::Key);
  339. begin_key();
  340. write(NSymbol::string_marker);
  341. write_varint(static_cast<i32>(name.size()));
  342. write_raw(name.data(), name.size());
  343. end_key();
  344. }
  345. };
  346. class TTextWriterImpl: public writer {
  347. public:
  348. TTextWriterImpl(NYsonPull::NOutput::IStream& stream, EStreamType mode)
  349. : writer(stream, mode)
  350. {
  351. }
  352. void OnScalarBoolean(bool value) override {
  353. update_state(EEventType::Scalar);
  354. begin_node();
  355. write(value ? percent_scalar::true_literal : percent_scalar::false_literal);
  356. end_node();
  357. }
  358. void OnScalarInt64(i64 value) override {
  359. update_state(EEventType::Scalar);
  360. char buf[32];
  361. auto len = ::snprintf(buf, sizeof(buf), "%" PRIi64, value);
  362. begin_node();
  363. write_raw(buf, len);
  364. end_node();
  365. }
  366. void OnScalarUInt64(ui64 value) override {
  367. update_state(EEventType::Scalar);
  368. char buf[32];
  369. auto len = ::snprintf(buf, sizeof(buf), "%" PRIu64, value);
  370. begin_node();
  371. write_raw(buf, len);
  372. write('u');
  373. end_node();
  374. }
  375. void OnScalarFloat64(double value) override {
  376. update_state(EEventType::Scalar);
  377. begin_node();
  378. if (std::isfinite(value)) {
  379. char buf[32];
  380. auto len = ::snprintf(buf, sizeof(buf), "%#.17lg", value);
  381. write_raw(buf, len);
  382. } else if (std::isnan(value)) {
  383. write(percent_scalar::nan_literal);
  384. } else if (value > 0) {
  385. write(percent_scalar::positive_inf_literal);
  386. } else {
  387. write(percent_scalar::negative_inf_literal);
  388. }
  389. end_node();
  390. }
  391. void OnScalarString(TStringBuf value) override {
  392. update_state(EEventType::Scalar);
  393. begin_node();
  394. write_escaped_string(value);
  395. end_node();
  396. }
  397. void OnKey(TStringBuf name) override {
  398. update_state(EEventType::Key);
  399. begin_key();
  400. write_escaped_string(name);
  401. end_key();
  402. }
  403. protected:
  404. void begin_node() override {
  405. if (need_item_separator()) {
  406. write(NSymbol::item_separator);
  407. write(' ');
  408. }
  409. }
  410. void end_node() override {
  411. if (mode() != EStreamType::Node && depth() == 0) {
  412. write(NSymbol::item_separator);
  413. write('\n');
  414. need_item_separator(false);
  415. } else {
  416. writer::end_node();
  417. }
  418. }
  419. void end_key() override {
  420. write(' ');
  421. writer::end_key();
  422. write(' ');
  423. }
  424. };
  425. class TPrettyWriterImpl final: public TTextWriterImpl {
  426. size_t indent_size_;
  427. public:
  428. TPrettyWriterImpl(
  429. NYsonPull::NOutput::IStream& stream,
  430. EStreamType mode,
  431. size_t indent_size)
  432. : TTextWriterImpl(stream, mode)
  433. , indent_size_{indent_size} {
  434. }
  435. protected:
  436. void begin_node() override {
  437. if (need_item_separator()) {
  438. write(NSymbol::item_separator);
  439. newline();
  440. }
  441. }
  442. void begin_collection(collection_type type) override {
  443. TTextWriterImpl::begin_collection(type);
  444. newline();
  445. }
  446. void end_collection(collection_type type) override {
  447. TTextWriterImpl::end_collection(type);
  448. newline();
  449. }
  450. void newline() {
  451. write('\n');
  452. indent(depth());
  453. }
  454. void indent(size_t count) {
  455. for (size_t i = 0; i < count * indent_size_; ++i) {
  456. write(' ');
  457. }
  458. }
  459. };
  460. template <typename T, typename... Args>
  461. NYsonPull::TWriter make_writer(
  462. THolder<NYsonPull::NOutput::IStream> stream,
  463. Args&&... args) {
  464. auto impl = MakeHolder<T>(*stream, std::forward<Args>(args)...);
  465. return NYsonPull::TWriter(std::move(stream), std::move(impl));
  466. }
  467. }
  468. }