#pragma once #ifndef DONT_INCLUDE_SLASH_PARSER_HPP #include "slash-parser.hpp" #endif #include void SlashCommandParser::skip_white() { while ((cursor_ < linelen_) && (ascii_isspace(line_[cursor_]))) { cursor_++; } } std::string SlashCommandParser::read_word() { int start = cursor_; while ((cursor_ < linelen_) && (!ascii_isspace(line_[cursor_]))) { cursor_++; } std::string result = line_.substr(start, cursor_ - start); skip_white(); return result; } SlashCommandParser::SlashCommandParser(std::string_view Line) { line_ = Line; linelen_ = int(Line.size()); cursor_ = 0; command_ = read_word(); if ((command_.size() < 2) || (command_[0] != '/')) { error_ = "Not a slash-command"; return; } if (!ascii_isalpha(command_[1])) { error_ = "Slash command must start with ascii alpha"; return; } for (int i = 1; i < int(command_.size()); i++) { if (!ascii_isalnum(command_[i])) { error_ = "Slash-command must be alphanumeric"; return; } } } bool SlashCommandParser::Parse(std::string_view Command, std::string_view ArgTypes) { if (Command != std::string_view(command_)) return false; args_.clear(); for (int i = 0; i < int(ArgTypes.size()); i++) { switch(ArgTypes[i]) { case 's': { std::string word = read_word(); if (word.empty()) { error_ = "Expected string arg"; return false; } args_.emplace_back(word); break; } case 'i': { std::string word = read_word(); const char *p = word.c_str(); const char *last = p + word.size(); if ((p < last) && (*p == '+')) p++; int64_t result; auto r = std::from_chars(p, last, result, 10); if ((r.ec != std::errc()) || (r.ptr != last)) { error_ = "Expected int arg"; return false; } args_.emplace_back(result); break; } case 'd': { error_ = "Double args not implemented yet."; break; } default: { error_ = "Invalid argtypes "; error_ += ArgTypes; error_ += " parsing "; error_ += Command; return false; } } } if (cursor_ != linelen_) { error_ = "Too many arguments for command: "; error_ += Command; return false; } error_.clear(); return true; } std::string SlashCommandParser::Error() const { if (!error_.empty()) { return error_; } else { return std::string("Unrecognized command: ") + command_; } } std::string SlashCommandParser::StringArg(int n) const { if ((n < 0) || (n >= int(args_.size()))) return ""; return args_[n].s_; } int64_t SlashCommandParser::IntArg(int n) const { if ((n < 0) || (n >= int(args_.size()))) return 0; return args_[n].i_; } double SlashCommandParser::DoubleArg(int n) const { if ((n < 0) || (n >= int(args_.size()))) return 0.0; return args_[n].d_; }