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 <optional>
32#include <seastar/util/modules.hh>
33#include <seastar/core/future.hh>
34#endif
35
36namespace 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;
55public:
56 class guard;
57public:
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;
71public:
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
97SEASTAR_MODULE_EXPORT_BEGIN
98
99// CRTP
100template <typename ConcreteParser>
102protected:
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;
111protected:
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 }
129public:
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
144inline 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}
155SEASTAR_MODULE_EXPORT_END
156
157}
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
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
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
CharType * get_write() noexcept
Definition: temporary_buffer.hh:128
Seastar API namespace.
Definition: abort_on_ebadf.hh:26