5 #include "../counter.h"
8 // cursors can only move forward, or reset completely
10 struct read_record_cursor {
12 typedef typename T::value value_type;
13 typedef typename T::value_descriptor value_descriptor_type;
15 // [px, px+nbytes) is assumed to be valid memory
16 read_record_cursor(const uint8_t *px, size_t nbytes)
17 : px_begin(px), nbytes(nbytes), px_cur(px), n(0) {}
19 // returns true on success, false on fail
24 INVARIANT(i < value_descriptor_type::nfields());
26 const size_t sz = value_descriptor_type::failsafe_skip_fn(n++)(px_cur, nbytes, nullptr);
38 INVARIANT(px_cur >= px_begin);
39 nbytes += (px_cur - px_begin);
50 // returns 0 on failure
52 read_current_and_advance(value_type *v)
54 INVARIANT(n < value_descriptor_type::nfields());
55 uint8_t * const buf = reinterpret_cast<uint8_t *>(v) +
56 value_descriptor_type::cstruct_offsetof(n);
57 const uint8_t * const px_skip =
58 value_descriptor_type::failsafe_read_fn(n++)(px_cur, nbytes, buf);
59 if (unlikely(!px_skip))
61 const size_t rawsz = px_skip - px_cur;
62 INVARIANT(rawsz <= value_descriptor_type::max_nbytes(n - 1));
68 // returns 0 on failure
70 read_current_raw_size_and_advance()
72 INVARIANT(n < value_descriptor_type::nfields());
74 value_descriptor_type::failsafe_skip_fn(n++)(px_cur, nbytes, nullptr);
75 if (unlikely(!nbytes))
77 INVARIANT(rawsz <= value_descriptor_type::max_nbytes(n - 1));
84 const uint8_t *px_begin;
86 // the 3 fields below are kept in sync:
87 // [px_cur, px_cur+nbytes) is valid memory
88 // px_cur points to the start of the n-th field
90 const uint8_t *px_cur;
91 size_t n; // current field position in cursor
96 struct write_record_cursor {
98 typedef typename T::value value_type;
99 typedef typename T::value_descriptor value_descriptor_type;
101 write_record_cursor(uint8_t *px)
102 : px_begin(px), px_cur(px), px_end(nullptr), n(0)
111 INVARIANT(i < value_descriptor_type::nfields());
113 px_cur += value_descriptor_type::skip_fn(n++)(px_cur, nullptr);
130 write_current_and_advance(const value_type *v, uint8_t *old_v = nullptr)
132 static event_counter evt_write_memmove(
133 util::cxx_typename<T>::value() + std::string("_write_memmove"));
134 const uint8_t * const buf = reinterpret_cast<const uint8_t *>(v) +
135 value_descriptor_type::cstruct_offsetof(n);
136 const size_t newsz = value_descriptor_type::nbytes_fn(n)(buf);
137 INVARIANT(newsz <= value_descriptor_type::max_nbytes(n));
138 uint8_t stack_buf[value_descriptor_type::max_nbytes(n)];
139 uint8_t * const old_buf = old_v ? old_v : &stack_buf[0];
140 const size_t oldsz = value_descriptor_type::skip_fn(n)(px_cur, old_buf);
141 INVARIANT(oldsz <= value_descriptor_type::max_nbytes(n));
142 if (unlikely(oldsz != newsz)) {
145 memmove(px_cur + newsz, px_cur + oldsz, px_end - px_cur - oldsz);
148 px_end -= (oldsz - newsz);
151 px_end += (newsz - oldsz);
153 px_cur = value_descriptor_type::write_fn(n++)(px_cur, buf);
163 uint8_t *px = px_cur;
165 while (i < value_descriptor_type::nfields())
166 px += value_descriptor_type::skip_fn(i++)(px, nullptr);
173 size_t n; // current field position in cursor