151 lines
3.4 KiB
C++
151 lines
3.4 KiB
C++
#pragma once
|
|
|
|
#ifndef DONT_INCLUDE_SLASH_PARSER_HPP
|
|
#include "slash-parser.hpp"
|
|
#endif
|
|
#include <charconv>
|
|
|
|
|
|
|
|
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_;
|
|
}
|