/* * This file is part of the Flowee project * Copyright (C) 2016, 2019-2024 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FLOWEE_CONSTBUFFER_H #define FLOWEE_CONSTBUFFER_H #include #include #include "Logger.h" namespace Streaming { /** * Class for holding a reference to an slice of the buffer in buffer_base * Since it has a reference to the actual buffer with a shared_array * the underlying memory will not be deallocated until all references are removed */ class ConstBuffer { public: static ConstBuffer create(const char *start, size_t size); static ConstBuffer create(const std::vector &vector); /// creates an invalid buffer ConstBuffer(); bool isValid() const { return m_start != nullptr && m_stop != nullptr; } bool isEmpty() const { return m_start == m_stop; } /// Construct from already allocated storage. /// Keep in mind that a shared_ptr can have a custom dtor if we want to send something special explicit ConstBuffer(std::shared_ptr buffer, char const *start, char const *stop); char const* begin() const; inline char const* cbegin() const { return begin(); } char const* end() const; inline char const* cend() const { return end(); } /// standard indexing operator - assumes begin() + idx < end() char operator[](size_t idx) const; char const* constData() const; /// returns end - begin int size() const; /// return a std::string copy inline std::string toString() const { return std::string(begin(), size()); } /// return the buffer as hex string. std::string toHex() const { return toHex(Forward); } /// return the buffer as hex string, in reversed order. std::string toHex_reversed() const { return toHex(Reversed); } /// return the index in the buffer where byte \a k is found, starting at 'begin()' plus \a offset. /// returns -1 if not found before end() int indexOf(char k, int offset = 0) const; /// Implement ConvertibleToConstBuffer for asio operator boost::asio::const_buffer() const; /** * Return a section of this buffer. * Notice that due to the nature of ConstBuffer, this is a O1 operation * that does not copy any actual data. */ ConstBuffer mid(int offset, int length = -1) const; /** * Returns true if this buffer starts with the \a other bytes */ bool startsWith(const Streaming::ConstBuffer &other) const; bool startsWith(char byte) const; bool endsWith(const Streaming::ConstBuffer &other) const; bool endsWith(char byte) const; /** * Compares the two buffers on having the same contents (byte-series). */ bool operator==(const Streaming::ConstBuffer &other) const; /** * Compares the two buffers on having the same contents (byte-series). */ inline bool operator!=(const Streaming::ConstBuffer &other) const { return !operator==(other); } /** * Drop current data and make this an invalid and empty buffer. */ void clear(); /// \internal std::shared_ptr internal_buffer() const; private: enum Direction_ { Forward, Reversed }; std::string toHex(Direction_ dir) const; std::shared_ptr m_buffer; char const* m_start; char const* m_stop; }; } inline Log::Item operator<<(Log::Item item, const Streaming::ConstBuffer &buf) { if (item.isEnabled()) { const bool old = item.useSpace(); item.nospace() << '{'; const bool tooLong = buf.size() > 80; const uint8_t *end = reinterpret_cast(tooLong ? buf.begin() + 77 : buf.end()); for (const uint8_t *p = reinterpret_cast(buf.begin()); p < end; ++p) { char h = '0' + (*p >> 4); if (h > '9') h += 7; char l = '0' + (*p & 0xF); if (l > '9') l += 7; item << h << l; } if (tooLong) item << "..."; item << '}'; if (old) return item.space(); } return item; } inline Log::SilentItem operator<<(Log::SilentItem item, const Streaming::ConstBuffer&) { return item; } #endif