#ifndef BUFFER_HH #define BUFFER_HH #include "macros.hh" #include #include namespace modxml { namespace sax { class HIDDEN Buffer { public: virtual ~Buffer() = default; Buffer(Buffer const&) = delete; Buffer& operator=(Buffer const&) = delete; // Returns a writable span, either at least need large or in case // the buffer is full, an empty span. // Returned span is valid until any other method is called on the buffer. virtual std::span wspan(std::size_t need = 1) = 0; // Commit size data from the last returned wspan. size must be <= span.size. // Remember that the span is now invalid and you need to call wspan again // to write more. virtual void commit(std::size_t size) = 0; // Returns a readable span of all readily available data in buffer. // If there is enought data in the buffer to satisfy want, the returned // span is at least as large. // Returned span is valid until any other method is called on the buffer. virtual std::span rspan(std::size_t want = 1) = 0; // Consume size data from buffer. size must be <= span.size. // Remember that the span is now invalid and you need to call rspan again // to read more. virtual void consume(std::size_t size) = 0; // Returns the same span as rspan but this is writable, you can modify // the content. You cannot change the size of the span. // If you wish to append data, use wspan() + commit(). // If you wish to remove data, use uncommit(). // If you wish to insert you have to be clever. // Returned span is valid until any other method is called on the buffer. virtual std::span mspan(std::size_t want = 1) = 0; // Uncommit the last size bytes in the buffer. Returns the bytes // removed. If you used wspan() + commit() to add ten (10) bytes say and then // call uncommit() with a size of seven (7) the first three (3) bytes written // will the left in the buffer. virtual std::size_t uncommit(std::size_t size) = 0; // Returns true if buffer is empty. virtual bool empty() const = 0; // Returns true if buffer is full. This means filled to max_size. virtual bool full() const = 0; // Clear buffer, reset back to initial state. virtual void reset() = 0; // Write as much as possible of data to buffer. // Returns bytes written (may be zero). std::size_t write(std::span data); // Either write all of the data to buffer or none. Returns true if data was // written or data was empty. bool write_all(std::span data); // Read as much as possible from buffer to data. // Returns bytes read (may be zero). std::size_t read(std::span data); // Either fill data with data from buffer or return false. bool read_all(std::span data); protected: Buffer() = default; }; // Create a buffer. default_size is used as an hint but generally that // will be the initial size of the buffer. max_size is an hard limit. // max_size == 0 is valid but will return an always full and empty buffer. std::unique_ptr HIDDEN make_buffer(std::size_t default_size, std::size_t max_size); class ReadViewBuffer : public Buffer { public: // Returns bytes consumed in this buffer. virtual std::size_t consumed() const = 0; // Take ownership back of the wrapped buffer from the read view. // The read view is now unusable. virtual std::unique_ptr release() = 0; protected: ReadViewBuffer() = default; }; // Create a read view buffer. Writing will go to wrapped buffer. Reading // is done on the read view buffer without moving the wrapped buffers read // pointer. These views are lightweight. std::unique_ptr HIDDEN make_read_view_buffer( std::unique_ptr buffer); } // namespace sax } // namespace modxml #endif // BUFFER_HH