#include "ansi_parser.h" using std::string; using std::vector; ANSIParser::ANSIParser() : state(STATE_PLAIN), current_parameter(-1) {} ANSIParser::~ANSIParser() {} void ANSIParser::Parse(const std::string& data) { size_t len = data.length(); size_t i = 0; size_t left = (this->state == STATE_PLAIN) ? i : len; size_t right = len; while (i < len) { char ch = data.at(i); switch (this->state) { case STATE_PLAIN: { size_t nextESC = data.find_first_of('\x1B', i); if (nextESC == std::string::npos) { i = len; } else { right = i = nextESC; this->state = STATE_BEGIN; } } break; case STATE_BEGIN: if (ch == '[') { current_parameter = 0; this->state = STATE_PARAMETERS; } else { this->state = STATE_PLAIN; } break; case STATE_PARAMETERS: if ('0' <= ch && ch <= '9') { current_parameter = (current_parameter * 10) + (ch - '0'); } else { this->parameters.push_back(current_parameter); current_parameter = -1; this->state = STATE_PARAMETER_END; continue; // skip the i += 1 } break; case STATE_PARAMETER_END: if (ch == ';') { current_parameter = 0; this->state = STATE_PARAMETERS; } else { this->state = STATE_INTERMEDIATE; continue; // skip the i += 1 } break; case STATE_INTERMEDIATE: if (' ' <= ch && ch <= '/') { this->intermediate.append(1, ch); } else { this->state = STATE_END; continue; // skip the i += 1 } break; case STATE_END: if ('@' <= ch && ch <= '~') { if (left < right) { this->OnText(data.substr(left, right-left)); } this->OnCommand(ch, this->parameters, this->intermediate); left = i + 1; } this->state = STATE_PLAIN; this->Reset(); right = len; break; } i += 1; } if (left < right) { this->OnText(data.substr(left, right-left)); } } void ANSIParser::Reset() { this->current_parameter = -1; this->parameters.clear(); this->intermediate.clear(); }