mirror of
https://github.com/fish-shell/fish-shell
synced 2025-02-13 04:33:33 +00:00
Add RAII-based event_queue_peeker_t
helper
This is a stack-allocating utility class to peek up to N characters/events out of an `event_queue_t` object. The need for a hard-coded maximum peek length N at each call site is to avoid any heap allocation, as this would be called in a hot path on every input event.
This commit is contained in:
parent
c203c88c66
commit
cc392b3774
2 changed files with 55 additions and 0 deletions
|
@ -467,6 +467,48 @@ maybe_t<input_mapping_t> inputter_t::find_mapping() {
|
|||
return generic ? maybe_t<input_mapping_t>(*generic) : none();
|
||||
}
|
||||
|
||||
template <size_t N = 16>
|
||||
class event_queue_peeker_t {
|
||||
private:
|
||||
input_event_queue_t &event_queue_;
|
||||
std::array<char_event_t, N> peeked_;
|
||||
size_t count = 0;
|
||||
bool consumed_ = false;
|
||||
|
||||
public:
|
||||
event_queue_peeker_t(input_event_queue_t &event_queue)
|
||||
: event_queue_(event_queue) {
|
||||
}
|
||||
|
||||
char_event_t next(bool timed = false) {
|
||||
assert(count < N && "Insufficient backing array size!");
|
||||
auto event = timed ? event_queue_.readch_timed() : event_queue_.readch();
|
||||
peeked_[count++] = event;
|
||||
return event;
|
||||
}
|
||||
|
||||
size_t len() {
|
||||
return count;
|
||||
}
|
||||
|
||||
void consume() {
|
||||
consumed_ = true;
|
||||
}
|
||||
|
||||
void restart() {
|
||||
if (count > 0) {
|
||||
event_queue_.insert_front(peeked_.cbegin(), peeked_.cbegin() + count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~event_queue_peeker_t() {
|
||||
if (!consumed_) {
|
||||
restart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void inputter_t::mapping_execute_matching_or_generic(const command_handler_t &command_handler) {
|
||||
if (auto mapping = find_mapping()) {
|
||||
mapping_execute(*mapping, command_handler);
|
||||
|
|
|
@ -107,6 +107,9 @@ enum class char_event_type_t : uint8_t {
|
|||
/// An event was handled internally, or an interrupt was received. Check to see if the reader
|
||||
/// loop should exit.
|
||||
check_exit,
|
||||
|
||||
/// There is no event. This should never happen, or is an assertion failure.
|
||||
none,
|
||||
};
|
||||
|
||||
/// Hackish: the input style, which describes how char events (only) are applied to the command
|
||||
|
@ -154,11 +157,21 @@ class char_event_t {
|
|||
return v_.c;
|
||||
}
|
||||
|
||||
maybe_t<wchar_t> maybe_char() const {
|
||||
if (type == char_event_type_t::charc) {
|
||||
return v_.c;
|
||||
} else {
|
||||
return none();
|
||||
}
|
||||
}
|
||||
|
||||
readline_cmd_t get_readline() const {
|
||||
assert(type == char_event_type_t::readline && "Not a readline type");
|
||||
return v_.rl;
|
||||
}
|
||||
|
||||
explicit char_event_t() : type(char_event_type_t::none) { }
|
||||
|
||||
/* implicit */ char_event_t(wchar_t c) : type(char_event_type_t::charc) { v_.c = c; }
|
||||
|
||||
/* implicit */ char_event_t(readline_cmd_t rl, wcstring seq = {})
|
||||
|
|
Loading…
Reference in a new issue