beast_rj_utils.h
1 // Copyright 2019, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 #pragma once
5 
6 #include <boost/beast/core/multi_buffer.hpp>
7 
8 namespace util {
9 namespace http {
10 
11 // This stream can not be insitu because rapidjson assumes
12 // that PutBegin/PutEnd denote continous memory range and not just an abstract stream.
14  public:
15  using Ch = char;
16  using multi_buffer = ::boost::beast::multi_buffer;
17 
18  RjBufSequenceStream(multi_buffer::const_buffers_type mdata) : end_(mdata.end()) {
19  src_.it = mdata.begin();
20  src_.Setup(end_);
21  }
22 
23  // Read
24  Ch Peek() const { return *src_.current; }
25 
26  Ch Take() {
27  Ch res = *src_.current++;
28  if (src_.finish()) {
29  src_consumed_ += src_.Inc(end_);
30  }
31  return res;
32  }
33 
34  size_t Tell() const {
35  size_t res = src_consumed_;
36  if (!src_.end) {
37  res += src_.current - reinterpret_cast<const char*>((*src_.it).data());
38  }
39  return res;
40  }
41 
42  Ch* PutBegin() { assert(0); return nullptr; }
43  size_t PutEnd(Ch* begin) { assert(0); return 0; }
44  void Put(Ch c) { assert(0); }
45 
46  /*Ch* PutBegin() {
47  assert(*src_.current);
48  dst_ = src_;
49  dst_consumed_ = 0;
50  return dst_.current;
51  }
52 
53  size_t PutEnd(Ch* begin) {
54  if (dst_consumed_ == 0)
55  return dst_.current - begin;
56 
57  size_t res = dst_consumed_ + (dst_.current - reinterpret_cast<char*>((*dst_.it).data()));
58  assert(res < 2000);
59  return res;
60  }
61 
62  void Put(Ch c) {
63  *dst_.current++ = c;
64  if (dst_.finish()) {
65  dst_consumed_ += dst_.Inc(end_);
66  }
67  }*/
68 
69  private:
70  using const_iterator = multi_buffer::const_buffers_type::const_iterator;
71 
72  struct Item {
73  const_iterator it;
74  const char *current, *end;
75 
76  Item() : current(nullptr), end(nullptr) {}
77 
78  size_t Inc(const_iterator end_it) {
79  size_t res = (*it).size();
80  ++it;
81  Setup(end_it);
82  return res;
83  }
84 
85  void Setup(const_iterator end_it) {
86  if (it == end_it) {
87  end = nullptr; // fill with 0 bytes
88  current = reinterpret_cast<char*>(&end); // use end_ as placeholder for '\0'
89  return;
90  }
91  const auto& mb = *it;
92  current = reinterpret_cast<const char*>(mb.data());
93  end = current + mb.size();
94  }
95 
96  bool finish() const { return end == current; }
97  };
98 
99  const_iterator end_;
100  Item src_; //, dst_;
101  size_t src_consumed_ = 0; //, dst_consumed_ = 0;
102 };
103 
104 } // namespace http
105 } // namespace util
106 
107 namespace rapidjson {
108 template <typename Stream> struct StreamTraits;
109 
110 template <> struct StreamTraits<util::http::RjBufSequenceStream> {
111  enum { copyOptimization = 1 };
112 };
113 
114 } // namespace rapidjson