0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-16 06:51:08 +01:00

ircd::spirit: Fix signedness and displacements in generator state; add assertions.

This commit is contained in:
Jason Volk 2020-05-29 14:13:12 -07:00
parent bf91bf9bcd
commit 6eb54341ef

View file

@ -250,16 +250,16 @@ struct ircd::spirit::generator_state
mutable_buffer &out; mutable_buffer &out;
/// Current consumption count of the destination buffer. /// Current consumption count of the destination buffer.
size_t consumed {0}; ssize_t consumed {0};
/// The number of attemtped generated characters to the destination. This /// The number of attemtped generated characters to the destination. This
/// can be larger than the consumed counter to indicate the destination /// can be larger than the consumed counter to indicate the destination
/// buffer is insufficient. Note that characters are otherwise quietly /// buffer is insufficient. Note that characters are otherwise quietly
/// discarded when the destination (out) is full. /// discarded when the destination (out) is full.
size_t generated {0}; ssize_t generated {0};
/// Internal state for buffer_sink::copy() /// Internal state for buffer_sink::copy()
size_t last_generated {0}, last_width {0}; ssize_t last_generated {0}, last_width {0};
}; };
template<class gen, template<class gen,
@ -298,7 +298,7 @@ ircd::generate(mutable_buffer &out,
karma::generate(sink, std::forward<gen>(g), std::forward<attr>(a)...) karma::generate(sink, std::forward<gen>(g), std::forward<attr>(a)...)
}; };
if(unlikely(state.generated > max)) if(unlikely(size_t(state.generated) > max))
{ {
char pbuf[2][48]; char pbuf[2][48];
throw spirit::buffer_overrun throw spirit::buffer_overrun
@ -416,31 +416,38 @@ const
*ircd::spirit::generator_state *ircd::spirit::generator_state
}; };
assert(state.last_generated >= 0);
assert(state.generated >= state.last_generated);
const auto &width_diff const auto &width_diff
{ {
this->width - state.last_width state.last_generated == state.generated?
ssize_t(this->width) - state.last_width:
ssize_t(this->width)
}; };
state.consumed += assert(width_diff >= -state.consumed);
state.last_generated == state.generated? assert(state.generated >= state.consumed);
width_diff: state.consumed += width_diff;
this->width;
assert(state.consumed >= 0);
const auto &rewind_count const auto &rewind_count
{ {
std::min(state.generated - state.consumed, state.consumed) state.generated - state.consumed
}; };
const auto &rewind const auto &rewind
{ {
state.generated > state.consumed? rewind_count >= 0L?
rewind_count: std::min(rewind_count, state.generated):
0L 0L
}; };
assert(rewind >= 0L);
assert(rewind <= state.generated);
std::get<0>(state.out) -= rewind; std::get<0>(state.out) -= rewind;
state.generated -= rewind; state.generated -= rewind;
assert(state.generated >= 0);
state.last_generated = state.generated; state.last_generated = state.generated;
state.last_width = this->width; state.last_width = this->width;
return true; //sink.good(); return true; //sink.good();