blob: 7ea6419cb88345418fc57ca6318ec34d1c224f27 [file] [log] [blame]
peter klauslerdd9923b2018-02-16 19:42:171#ifndef FORTRAN_PARSER_CHAR_BUFFER_H_
2#define FORTRAN_PARSER_CHAR_BUFFER_H_
peter klausler15fdae62018-01-30 19:47:173
4// Defines a simple expandable buffer suitable for efficiently accumulating
5// a stream of bytes.
6
7#include <forward_list>
8#include <string>
9#include <utility>
10#include <vector>
11
12namespace Fortran {
peter klausler0ba1a142018-02-07 20:04:4213namespace parser {
peter klausler15fdae62018-01-30 19:47:1714
15class CharBuffer {
peter klauslerbdea10d2018-02-05 20:54:3616public:
peter klausler15fdae62018-01-30 19:47:1717 CharBuffer() {}
18 CharBuffer(CharBuffer &&that)
peter klausler16c6f532018-02-05 22:29:2619 : blocks_(std::move(that.blocks_)), last_{that.last_}, bytes_{that.bytes_},
20 lastBlockEmpty_{that.lastBlockEmpty_} {
peter klausler15fdae62018-01-30 19:47:1721 that.clear();
22 }
23 CharBuffer &operator=(CharBuffer &&that) {
24 blocks_ = std::move(that.blocks_);
25 last_ = that.last_;
26 bytes_ = that.bytes_;
27 lastBlockEmpty_ = that.lastBlockEmpty_;
28 that.clear();
29 return *this;
30 }
31
peter klausler09865ff2018-02-09 22:04:1132 size_t size() const { return bytes_; }
peter klausler15fdae62018-01-30 19:47:1733
34 void clear() {
35 blocks_.clear();
36 last_ = blocks_.end();
37 bytes_ = 0;
38 lastBlockEmpty_ = false;
39 }
40
41 char *FreeSpace(size_t *);
42 void Claim(size_t);
43 void Put(const char *data, size_t n);
44 void Put(const std::string &);
peter klausler15fdae62018-01-30 19:47:1745 void Put(char x) { Put(&x, 1); }
peter klausler15fdae62018-01-30 19:47:1746
peter klauslerbdea10d2018-02-05 20:54:3647private:
peter klausler15fdae62018-01-30 19:47:1748 struct Block {
49 static constexpr size_t capacity{1 << 20};
50 char data[capacity];
51 };
52
peter klauslerbdea10d2018-02-05 20:54:3653public:
peter klausler15fdae62018-01-30 19:47:1754 class iterator {
peter klauslerbdea10d2018-02-05 20:54:3655 public:
peter klausler15fdae62018-01-30 19:47:1756 iterator() {}
57 iterator(std::forward_list<Block>::const_iterator block, int offset)
58 : block_{block}, offset_{offset} {}
59 iterator(const iterator &that)
60 : block_{that.block_}, offset_{that.offset_} {}
61 iterator &operator=(const iterator &that) {
62 block_ = that.block_;
63 offset_ = that.offset_;
64 return *this;
65 }
66 const char &operator*() const { return block_->data[offset_]; }
67 iterator &operator++() {
68 if (++offset_ == Block::capacity) {
69 ++block_;
70 offset_ = 0;
71 }
72 return *this;
73 }
74 iterator operator++(int) {
75 iterator result{*this};
76 ++*this;
77 return result;
78 }
79 iterator &operator+=(size_t n) {
80 while (n >= Block::capacity - offset_) {
81 n -= Block::capacity - offset_;
82 offset_ = 0;
83 ++block_;
84 }
85 offset_ += n;
86 return *this;
87 }
88 bool operator==(const iterator &that) const {
89 return block_ == that.block_ && offset_ == that.offset_;
90 }
91 bool operator!=(const iterator &that) const {
92 return block_ != that.block_ || offset_ != that.offset_;
93 }
peter klausler16c6f532018-02-05 22:29:2694
peter klauslerbdea10d2018-02-05 20:54:3695 private:
peter klausler15fdae62018-01-30 19:47:1796 std::forward_list<Block>::const_iterator block_;
97 int offset_;
98 };
99
100 iterator begin() const { return iterator(blocks_.begin(), 0); }
101 iterator end() const {
102 int offset = LastBlockOffset();
103 if (offset != 0 || lastBlockEmpty_) {
104 return iterator(last_, offset);
105 }
106 return iterator(blocks_.end(), 0);
107 }
108
peter klauslerbdea10d2018-02-05 20:54:36109private:
peter klausler15fdae62018-01-30 19:47:17110 int LastBlockOffset() const { return bytes_ % Block::capacity; }
111 std::forward_list<Block> blocks_;
112 std::forward_list<Block>::iterator last_{blocks_.end()};
113 size_t bytes_{0};
114 bool lastBlockEmpty_{false};
115};
peter klausler0ba1a142018-02-07 20:04:42116} // namespace parser
peter klausler15fdae62018-01-30 19:47:17117} // namespace Fortran
peter klauslerdd9923b2018-02-16 19:42:17118#endif // FORTRAN_PARSER_CHAR_BUFFER_H_