Seastar
High performance C++ framework for concurrent servers
ragel.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright (C) 2014 Cloudius Systems, Ltd.
20  */
21 
22 #pragma once
23 
24 #ifndef SEASTAR_MODULE
25 #include <seastar/core/sstring.hh>
26 #include <seastar/core/temporary_buffer.hh>
27 #include <seastar/util/eclipse.hh>
28 #include <algorithm>
29 #include <memory>
30 #include <cassert>
31 #include <seastar/util/std-compat.hh>
32 #include <seastar/util/modules.hh>
33 #include <seastar/core/future.hh>
34 #endif
35 
36 namespace seastar {
37 
38 // Support classes for Ragel parsers
39 
40 // Builds an sstring that can be scattered across multiple packets.
41 //
42 // Use a sstring_build::guard variable to designate each scattered
43 // char array, and call mark_start() and mark_end() at the start
44 // and end points, respectively. sstring_builder will collect data
45 // from intervening segments, if needed.
46 //
47 // After mark_end() has been called, use the get() method to obtain
48 // the built string.
49 //
50 // FIXME: switch to string_view.
51 //
53  sstring _value;
54  const char* _start = nullptr;
55 public:
56  class guard;
57 public:
58  sstring get() && {
59  return std::move(_value);
60  }
61  void reset() {
62  _value = {};
63  _start = nullptr;
64  }
65  friend class guard;
66 };
67 
69  sstring_builder& _builder;
70  const char* _block_end;
71 public:
72  guard(sstring_builder& builder, const char* block_start, const char* block_end)
73  : _builder(builder), _block_end(block_end) {
74  if (!_builder._value.empty()) {
75  mark_start(block_start);
76  }
77  }
78  ~guard() {
79  if (_builder._start) {
80  mark_end(_block_end);
81  }
82  }
83  void mark_start(const char* p) {
84  _builder._start = p;
85  }
86  void mark_end(const char* p) {
87  if (_builder._value.empty()) {
88  // avoid an allocation in the common case
89  _builder._value = sstring(_builder._start, p);
90  } else {
91  _builder._value += sstring(_builder._start, p);
92  }
93  _builder._start = nullptr;
94  }
95 };
96 
97 SEASTAR_MODULE_EXPORT_BEGIN
98 
99 // CRTP
100 template <typename ConcreteParser>
102 protected:
103  int _fsm_cs;
104  std::unique_ptr<int[]> _fsm_stack = nullptr;
105  int _fsm_stack_size = 0;
106  int _fsm_top;
107  int _fsm_act;
108  char* _fsm_ts;
109  char* _fsm_te;
110  sstring_builder _builder;
111 protected:
112  void init_base() {
113  _builder.reset();
114  }
115  void prepush() {
116  if (_fsm_top == _fsm_stack_size) {
117  auto old = _fsm_stack_size;
118  _fsm_stack_size = std::max(_fsm_stack_size * 2, 16);
119  assert(_fsm_stack_size > old);
120  std::unique_ptr<int[]> new_stack{new int[_fsm_stack_size]};
121  std::copy(_fsm_stack.get(), _fsm_stack.get() + _fsm_top, new_stack.get());
122  std::swap(_fsm_stack, new_stack);
123  }
124  }
125  void postpop() {}
126  sstring get_str() {
127  return std::move(_builder).get();
128  }
129 public:
130  using unconsumed_remainder = std::optional<temporary_buffer<char>>;
132  char* p = buf.get_write();
133  char* pe = p + buf.size();
134  char* eof = buf.empty() ? pe : nullptr;
135  char* parsed = static_cast<ConcreteParser*>(this)->parse(p, pe, eof);
136  if (parsed) {
137  buf.trim_front(parsed - p);
138  return make_ready_future<unconsumed_remainder>(std::move(buf));
139  }
140  return make_ready_future<unconsumed_remainder>();
141  }
142 };
143 
144 inline void trim_trailing_spaces_and_tabs(sstring& str) {
145  auto data = str.data();
146  size_t i;
147  for (i = str.size(); i > 0; --i) {
148  auto c = data[i-1];
149  if (!(c == ' ' || c == '\t')) {
150  break;
151  }
152  }
153  str.resize(i);
154 }
155 SEASTAR_MODULE_EXPORT_END
156 
157 }
A representation of a possibly not-yet-computed value.
Definition: future.hh:1238
Definition: ragel.hh:101
Definition: ragel.hh:68
Definition: ragel.hh:52
bool empty() const noexcept
Checks whether the buffer is empty.
Definition: temporary_buffer.hh:152
CharType * get_write() noexcept
Definition: temporary_buffer.hh:128
void trim_front(size_t pos) noexcept
Definition: temporary_buffer.hh:186
size_t size() const noexcept
Gets the buffer size.
Definition: temporary_buffer.hh:130
Seastar API namespace.
Definition: abort_on_ebadf.hh:26