8000 refactor: optimize the stream and result types by hexorer · Pull Request #68 · hexorer/parsi · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor: optimize the stream and result types #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions examples/json_validator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@

namespace {

constexpr static std::string_view strview(std::span<const char> buffer)
{
return std::string_view(buffer.data(), buffer.size());
}

constexpr static auto create_json_string_validator_parser()
{
constexpr auto oct_charset = parsi::Charset("01234567");
Expand Down Expand Up @@ -78,15 +73,18 @@ constexpr static auto create_joined_repeated_parser(JoinParserF&& join_parser, I
return parsi::Result{stream, true};
}

while ((res = join_parser(res.stream))) {
res = item_parser(res.stream);
stream = res.stream();
while ((res = join_parser(stream))) {
stream = res.stream();
res = item_parser(stream);
if (!res)
{
return parsi::Result{res.stream, false};
return parsi::Result{stream, false};
}
stream = res.stream();
}

return parsi::Result{res.stream, true};
return parsi::Result{stream, true};
};
}

Expand Down Expand Up @@ -196,7 +194,7 @@ int main(int argc, char** argv)
);

if (auto res = parser(std::string_view(file_content)); !res) {
std::cout << " [Syntax Error] Remaining buffer that couldn't be parsed: " << strview(res.stream.remaining_buffer()) << '\n';
std::cout << " [Syntax Error] Remaining buffer that couldn't be parsed: " << res.stream().as_string_view() << '\n';
return 1;
}

Expand Down
110 changes: 44 additions & 66 deletions include/parsi/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define PARSI_BASE_HPP

#include <concepts>
#include <cstdint>
#include <cstring>
#include <span>
#include <string_view>
Expand All @@ -14,27 +15,23 @@ namespace parsi {
*/
class Stream {
public:
using buffer_type = std::span<const char>;

private:
buffer_type _buffer{};
std::size_t _cursor = 0;
const char* _cursor = nullptr;
std::size_t _size = 0;

public:
constexpr Stream(const char* str) noexcept : Stream(str, std::strlen(str))
{
}

constexpr Stream(const char* str, const std::size_t size) noexcept
: _buffer(str, size), _cursor(0)
constexpr Stream(const char* str, const std::size_t size) noexcept : _cursor(str), _size(size)
{
}

constexpr Stream(std::string_view str) noexcept : _buffer(str.data(), str.size()), _cursor(0)
constexpr Stream(std::string_view str) noexcept : _cursor(str.data()), _size(str.size())
{
}

constexpr Stream(buffer_type buffer) noexcept : _buffer(buffer), _cursor(0)
constexpr Stream(std::span<const char> buffer) noexcept : _cursor(buffer.data()), _size(buffer.size())
{
}

Expand All @@ -43,104 +40,85 @@ class Stream {
*/
constexpr void advance(std::size_t count) noexcept
{
_cursor = _cursor + count;
_cursor += count;
_size -= count;
}

/**
* returns a copy of this stream that is advanced forward by `count` bytes.
*/
[[nodiscard]] constexpr auto advanced(std::size_t count) const noexcept -> Stream
{
auto ret = Stream(_buffer);
ret._cursor = _cursor + count;
return ret;
}

[[nodiscard]] constexpr auto starts_with(const char character) const noexcept -> bool
{
if (_cursor >= _buffer.size()) [[unlikely]] {
return false;
}

return character == _buffer[_cursor];
}

[[nodiscard]] constexpr auto starts_with(std::span<const char> span) const noexcept -> bool
{
if (size() < span.size()) {
return false;
}

for (std::size_t idx = 0; idx < span.size(); ++idx) {
if (_buffer[_cursor + idx] != span[idx]) [[unlikely]] {
return false;
}
}

return true;
return Stream(_cursor + count, _size - count);
}

/**
* size of the available buffer in stream.
*/
[[nodiscard]] constexpr auto size() const noexcept -> std::size_t
{
return _buffer.size() - _cursor;
return _size;
}

/**
* size of the underlying buffer.
* underlying buffer.
*/
[[nodiscard]] constexpr auto buffer_size() const noexcept -> std::size_t
[[nodiscard]] constexpr auto data() const noexcept -> const char*
{
return _buffer.size();
return _cursor;
}

/**
* an index to current position into the buffer.
*/
[[nodiscard]] constexpr auto cursor() const noexcept -> std::size_t
[[nodiscard]] constexpr auto as_string_view() const noexcept -> std::string_view
{
return _cursor;
return std::string_view(_cursor, _size);
}

/**
* underlying buffer.
* first byte in the remainder of buffer.
*/
[[nodiscard]] constexpr auto buffer() const noexcept -> buffer_type
[[nodiscard]] constexpr auto front() const noexcept -> char
{
return _buffer;
return _cursor[0];
}
};

/**
* returns the remaining buffer span.
*/
[[nodiscard]] constexpr auto remaining_buffer() const noexcept -> buffer_type
class Result {
static constexpr std::size_t valid_bit_offset = 63;
static constexpr std::size_t size_mask = 0xFFFFFFFF;

const char* _cursor = nullptr;
std::size_t _size_and_bits = 0;

public:
constexpr Result(Stream stream, bool is_valid) noexcept
: _cursor(stream.data())
, _size_and_bits(stream.size() | (static_cast<std::size_t>(is_valid) << valid_bit_offset))
{
return _buffer.subspan(cursor());
}

[[nodiscard]] constexpr auto at(const std::size_t index) const noexcept -> const char
[[nodiscard]] constexpr auto cursor() const noexcept -> const char*
{
return _buffer[_cursor + index];
return _cursor;
}

/**
* first byte in the remainder of buffer.
*/
[[nodiscard]] constexpr auto front() const noexcept -> const char
[[nodiscard]] constexpr auto size() const noexcept -> std::size_t
{
return _buffer[_cursor];
return _size_and_bits & size_mask;
}

[[nodiscard]] constexpr auto stream() const noexcept -> Stream
{
return Stream(_cursor, _size_and_bits & size_mask);
}
};

struct Result {
Stream stream;
bool valid = false;
[[nodiscard]] constexpr auto is_valid() const noexcept -> bool
{
return _size_and_bits & (1ull << valid_bit_offset);
}

[[nodiscard]] constexpr operator bool() const noexcept
{
return valid;
return is_valid();
}
};

Expand Down
26 changes: 17 additions & 9 deletions include/parsi/fn/expect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ namespace parsi {

namespace fn {

struct Negation {
bool negated = false;
};

/**
* A parser that expects the stream to start with the given character.
*/
template <Negation NegationV = Negation{.negated = false}>
struct ExpectChar {
char expected;
bool negate = false;

[[nodiscard]] constexpr auto operator()(Stream stream) const noexcept -> Result
{
if (stream.size() <= 0) [[unlikely]] {
return Result{stream, false};
}
const bool is_valid = negate ^ stream.starts_with(expected);
const bool is_valid = stream.as_string_view().starts_with(expected);
stream.advance(1);
return Result{stream, is_valid};
if constexpr (NegationV.negated) {
return Result{stream, !is_valid};
} else {
return Result{stream, is_valid};
}
}
};

Expand Down Expand Up @@ -80,7 +88,7 @@ struct ExpectFixedString {
[[nodiscard]] constexpr auto operator()(Stream stream) const noexcept -> Result
{
const auto expected_strview = expected.as_string_view();
const bool starts_with = stream.starts_with(expected_strview);
const bool starts_with = stream.as_string_view().starts_with(expected_strview);
return Result{stream.advanced(starts_with * expected_strview.size()), starts_with};
}
};
Expand All @@ -93,7 +101,7 @@ struct ExpectString {

[[nodiscard]] auto operator()(Stream stream) const noexcept -> Result
{
const bool starts_with = stream.starts_with(expected);
const bool starts_with = stream.as_string_view().starts_with(expected);
return Result{stream.advanced(starts_with * expected.size()), starts_with};
}
};
Expand Down Expand Up @@ -135,18 +143,18 @@ template <std::size_t SizeV, typename CharT = const char>
* Creates a parser that expects the stream to start with the given character.
*/
[[nodiscard]] constexpr auto expect(char expected) noexcept
-> fn::ExpectChar
-> fn::ExpectChar<>
{
return fn::ExpectChar{expected};
return fn::ExpectChar<>{expected};
}

/**
* Creates a parser that expects the stream to start with the given character.
*/
[[nodiscard]] constexpr auto expect_not(char expected) noexcept
-> fn::ExpectChar
-> fn::ExpectChar<fn::Negation{.negated = true}>
{
return fn::ExpectChar{ .expected = expected, .negate = true };
return fn::ExpectChar<fn::Negation{.negated = true}>{expected};
}

/**
Expand Down
10 changes: 4 additions & 6 deletions include/parsi/fn/extract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ struct Extract {
{
auto result = parser(stream);
if (result) {
auto buffer = stream.buffer();
auto start = stream.cursor();
auto end = result.stream.cursor();
const auto start = stream.data();
const auto end = result.stream().data();

auto subspan = buffer.subspan(start, end - start);
auto substr = std::string_view(subspan.data(), subspan.size());
const std::string_view substr = stream.as_string_view().substr(0, end - start);

if constexpr (requires { { visitor(substr) } -> std::same_as<bool>; }) {
if (!visitor(substr)) {
return Result{result.stream, false};
return Result{result.stream(), false};
}
}
else {
Expand Down
1 change: 0 additions & 1 deletion include/parsi/fn/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct Optional {
if (!result) [[likely]] {
return Result{stream, true};
}

return result;
}
};
Expand Down
4 changes: 2 additions & 2 deletions include/parsi/fn/repeated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct Repeated {
}
}

stream.advance(result.stream.cursor() - stream.cursor());
stream = result.stream();
}

if constexpr (Min != 0) {
Expand Down Expand Up @@ -92,7 +92,7 @@ struct RepeatedRanged {
break;
}

stream = result.stream;
stream = result.stream();
}

if (count < min || max < count) [[unlikely]] {
Expand Down
2 changes: 1 addition & 1 deletion include/parsi/fn/sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct Sequence {
if (!res) {
return res;
}
return parse_rec<I+1>(res.stream);
return parse_rec<I+1>(res.stream());
}
}
};
Expand Down
Loading
0