From bd45c1c96370673c401cdc41c4340aa6c94c076d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 29 Feb 2020 17:34:21 -0500 Subject: [PATCH] Adds `append` and generally seeks to improve string accumulation. --- Machines/Utility/Typer.cpp | 76 +++++++++++++++++++++++++++----------- Machines/Utility/Typer.hpp | 10 ++++- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/Machines/Utility/Typer.cpp b/Machines/Utility/Typer.cpp index 18a847968..20d5a345e 100644 --- a/Machines/Utility/Typer.cpp +++ b/Machines/Utility/Typer.cpp @@ -8,8 +8,6 @@ #include "Typer.hpp" -#include - using namespace Utility; Typer::Typer(const std::string &string, HalfCycles delay, HalfCycles frequency, std::unique_ptr character_mapper, Delegate *delegate) : @@ -17,33 +15,69 @@ Typer::Typer(const std::string &string, HalfCycles delay, HalfCycles frequency, counter_(-delay), delegate_(delegate), character_mapper_(std::move(character_mapper)) { - std::ostringstream string_stream; - string_stream << Typer::BeginString << string << Typer::EndString; - string_ = string_stream.str(); + // Retain only those characters that actually map to something. + if(sequence_for_character(Typer::BeginString)) { + string_ += Typer::BeginString; + } + if(sequence_for_character(Typer::EndString)) { + string_ += Typer::EndString; + } + + append(string); } void Typer::run_for(const HalfCycles duration) { - if(string_pointer_ < string_.size()) { - if(counter_ < 0 && counter_ + duration >= 0) { - if(!type_next_character()) { - delegate_->typer_reset(this); - } - } + if(string_pointer_ >= string_.size()) { + return; + } - counter_ += duration; - while(string_pointer_ < string_.size() && counter_ > frequency_) { - counter_ -= frequency_; - if(!type_next_character()) { - delegate_->typer_reset(this); - } + if(counter_ < 0 && counter_ + duration >= 0) { + if(!type_next_character()) { + delegate_->typer_reset(this); + } + } + + counter_ += duration; + while(string_pointer_ < string_.size() && counter_ > frequency_) { + counter_ -= frequency_; + if(!type_next_character()) { + delegate_->typer_reset(this); } } } -bool Typer::try_type_next_character() { - uint16_t *sequence = character_mapper_->sequence_for_character(string_[string_pointer_]); +void Typer::append(const std::string &string) { + // Remove any characters that are already completely done; + // otherwise things may accumulate here indefinitely. + string_.erase(string_.begin(), string_.begin() + ssize_t(string_pointer_)); + string_pointer_ = 0; + // If the final character in the string is not Typer::EndString + // then this machine doesn't need Begin and End, so don't worry about it. + ssize_t insertion_position = ssize_t(string_.size()); + if(string_.back() == Typer::EndString) --insertion_position; + + string_.reserve(string_.size() + string.size()); + for(const char c : string) { + if(sequence_for_character(c)) { + string_.insert(string_.begin() + insertion_position, c); + ++insertion_position; + } + } +} + +const uint16_t *Typer::sequence_for_character(char c) const { + const uint16_t *const sequence = character_mapper_->sequence_for_character(c); if(!sequence || sequence[0] == KeyboardMachine::MappedMachine::KeyNotMapped) { + return nullptr; + } + return sequence; +} + +bool Typer::try_type_next_character() { + const uint16_t *const sequence = sequence_for_character(string_[string_pointer_]); + + if(!sequence) { return false; } @@ -61,10 +95,10 @@ bool Typer::type_next_character() { if(!try_type_next_character()) { phase_ = 0; - string_pointer_++; + ++string_pointer_; if(string_pointer_ == string_.size()) return false; } else { - phase_++; + ++phase_; } return true; diff --git a/Machines/Utility/Typer.hpp b/Machines/Utility/Typer.hpp index fbf11a6e8..90eb21d9b 100644 --- a/Machines/Utility/Typer.hpp +++ b/Machines/Utility/Typer.hpp @@ -51,14 +51,21 @@ class Typer { public: class Delegate: public KeyboardMachine::KeyActions { public: + /// Informs the delegate that this typer has reached the end of its content. virtual void typer_reset(Typer *typer) = 0; }; Typer(const std::string &string, HalfCycles delay, HalfCycles frequency, std::unique_ptr character_mapper, Delegate *delegate); + /// Advances for @c duration. void run_for(const HalfCycles duration); + + /// Types the next character now, if there is one. + /// @returns @c true if there was anything left to type; @c false otherwise. bool type_next_character(); - bool is_completed(); + + /// Adds the contents of @c str to the end of the current string. + void append(const std::string &str); const char BeginString = 0x02; // i.e. ASCII start of text const char EndString = 0x03; // i.e. ASCII end of text @@ -75,6 +82,7 @@ class Typer { std::unique_ptr character_mapper_; bool try_type_next_character(); + const uint16_t *sequence_for_character(char) const; }; /*!