Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:08:24

0001 /* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
0002  *
0003  * Distributed under the Boost Software License, Version 1.0. (See
0004  * accompanying file LICENSE.txt)
0005  */
0006 
0007 #ifndef BOOST_REDIS_RESP3_PARSER_HPP
0008 #define BOOST_REDIS_RESP3_PARSER_HPP
0009 
0010 #include <boost/redis/resp3/node.hpp>
0011 #include <boost/system/error_code.hpp>
0012 #include <array>
0013 #include <string_view>
0014 #include <cstdint>
0015 #include <optional>
0016 
0017 namespace boost::redis::resp3 {
0018 
0019 class parser {
0020 public:
0021    using node_type = basic_node<std::string_view>;
0022    using result = std::optional<node_type>;
0023 
0024    static constexpr std::size_t max_embedded_depth = 5;
0025    static constexpr std::string_view sep = "\r\n";
0026 
0027 private:
0028    // The current depth. Simple data types will have depth 0, whereas
0029    // the elements of aggregates will have depth 1. Embedded types
0030    // will have increasing depth.
0031    std::size_t depth_;
0032 
0033    // The parser supports up to 5 levels of nested structures. The
0034    // first element in the sizes stack is a sentinel and must be
0035    // different from 1.
0036    std::array<std::size_t, max_embedded_depth + 1> sizes_;
0037 
0038    // Contains the length expected in the next bulk read.
0039    std::size_t bulk_length_;
0040 
0041    // The type of the next bulk. Contains type::invalid if no bulk is
0042    // expected.
0043    type bulk_;
0044 
0045    // The number of bytes consumed from the buffer.
0046    std::size_t consumed_;
0047 
0048    // Returns the number of bytes that have been consumed.
0049    auto consume_impl(type t, std::string_view elem, system::error_code& ec) -> node_type;
0050 
0051    void commit_elem() noexcept;
0052 
0053    // The bulk type expected in the next read. If none is expected
0054    // returns type::invalid.
0055    [[nodiscard]]
0056    auto bulk_expected() const noexcept -> bool
0057       { return bulk_ != type::invalid; }
0058 
0059 public:
0060    parser();
0061 
0062    // Returns true when the parser is done with the current message.
0063    [[nodiscard]]
0064    auto done() const noexcept -> bool;
0065 
0066    auto get_suggested_buffer_growth(std::size_t hint) const noexcept -> std::size_t;
0067 
0068    auto get_consumed() const noexcept -> std::size_t;
0069 
0070    auto consume(std::string_view view, system::error_code& ec) noexcept -> result;
0071 
0072    void reset();
0073 };
0074 
0075 // Returns false if more data is needed. If true is returned the
0076 // parser is either done or an error occured, that can be checked on
0077 // ec.
0078 template <class Adapter>
0079 bool
0080 parse(
0081    resp3::parser& p,
0082    std::string_view const& msg,
0083    Adapter& adapter,
0084    system::error_code& ec)
0085 {
0086    while (!p.done()) {
0087       auto const res = p.consume(msg, ec);
0088       if (ec)
0089          return true;
0090 
0091       if (!res)
0092          return false;
0093 
0094       adapter(res.value(), ec);
0095       if (ec)
0096          return true;
0097    }
0098 
0099    return true;
0100 }
0101 
0102 } // boost::redis::resp3
0103 
0104 #endif // BOOST_REDIS_RESP3_PARSER_HPP