summaryrefslogtreecommitdiff
path: root/sax/src/buffer.hh
blob: d9fb9fc4959d1934d64bd9bbbdea5332b77d87a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#ifndef BUFFER_HH
#define BUFFER_HH

#include "macros.hh"

#include <memory>
#include <span>

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<uint8_t> 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<uint8_t const> 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<uint8_t> 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<uint8_t const> 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<uint8_t const> data);

  // Read as much as possible from buffer to data.
  // Returns bytes read (may be zero).
  std::size_t read(std::span<uint8_t> data);

  // Either fill data with data from buffer or return false.
  bool read_all(std::span<uint8_t> 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<Buffer> 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<Buffer> 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<ReadViewBuffer> HIDDEN make_read_view_buffer(
    std::unique_ptr<Buffer> buffer);

}  // namespace sax
}  // namespace modxml

#endif  // BUFFER_HH