5 #ifndef PACKIO_NL_JSON_RPC_INCREMENTAL_BUFFERS_H
6 #define PACKIO_NL_JSON_RPC_INCREMENTAL_BUFFERS_H
14 namespace nl_json_rpc {
16 class incremental_buffers {
18 std::size_t available_buffers()
const
20 return serialized_objects_.size();
23 std::optional<std::string> get_parsed_buffer()
25 if (serialized_objects_.empty()) {
29 auto buffer = std::move(serialized_objects_.front());
30 serialized_objects_.pop_front();
34 void feed(std::string_view data)
36 reserve_in_place_buffer(data.size());
37 std::copy(begin(data), end(data), in_place_buffer());
38 in_place_buffer_consumed(data.size());
41 char* in_place_buffer()
43 return raw_buffer_.data() + buffer_.size();
46 std::size_t in_place_buffer_capacity()
const
48 return raw_buffer_.size() - buffer_.size();
51 void in_place_buffer_consumed(std::size_t bytes)
56 incremental_parse(bytes);
59 void reserve_in_place_buffer(std::size_t bytes)
61 if (in_place_buffer_capacity() >= bytes) {
64 raw_buffer_.resize(buffer_.size() + bytes);
68 void incremental_parse(std::size_t bytes)
70 if (buffer_.empty()) {
71 std::string_view new_data{in_place_buffer(), bytes};
72 auto first_pos = new_data.find_first_of(
"{[");
73 if (first_pos == std::string::npos) {
77 initialize(new_data[first_pos]);
80 std::size_t token_pos = buffer_.size();
81 buffer_ = std::string_view{raw_buffer_.data(), buffer_.size() + bytes};
84 token_pos = buffer_.find_first_of(tokens_, token_pos + 1);
85 if (token_pos == std::string::npos) {
89 char token = buffer_[token_pos];
90 if (token ==
'"' && !is_escaped(token_pos)) {
91 in_string_ = !in_string_;
99 if (token == last_char_) {
102 std::size_t buffer_size = token_pos + 1;
103 std::string new_raw_buffer = raw_buffer_.substr(buffer_size);
104 raw_buffer_.resize(buffer_size);
105 serialized_objects_.push_back(std::move(raw_buffer_));
107 std::size_t bytes_left = buffer_.size() - buffer_size;
108 raw_buffer_ = std::move(new_raw_buffer);
109 buffer_ = std::string_view{raw_buffer_.data(), bytes_left};
110 token_pos -= buffer_size;
114 assert(token == first_char_);
120 bool is_escaped(std::size_t pos)
122 bool escaped =
false;
124 if (buffer_[pos] ==
'\\') {
134 void initialize(
char first_char)
136 first_char_ = first_char;
137 if (first_char_ ==
'{') {
142 assert(first_char_ ==
'[');
156 std::string_view buffer_;
157 std::string raw_buffer_;
159 std::deque<std::string> serialized_objects_;
165 #endif // PACKIO_NL_JSON_RPC_INCREMENTAL_BUFFERS_H