/** * Ashita SDK - Copyright (c) 2023 Ashita Development Team * Contact: https://www.ashitaxi.com/ * Contact: https://discord.gg/Ashita * * This file is part of Ashita. * * Ashita is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Ashita is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Ashita. If not, see . */ #ifndef ASHITA_SDK_COMMANDS_H_INCLUDED #define ASHITA_SDK_COMMANDS_H_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif #include #include #include /** * Helper Macros */ #define HANDLECOMMAND(...) \ if (args.size() > 0 && Ashita::Commands::CommandCheck(args[0], std::vector({__VA_ARGS__}))) namespace Ashita::Commands { /** * Checks if the command exists in the given list of command strings. * * @param {std::string&} cmd - The command to compare against. * @param {std::vector&} cmds - The list of commands available to try and compare against. * @return {bool} True if found, false otherwise. */ static __forceinline bool CommandCheck(const std::string& cmd, const std::vector& cmds) { if (cmd.size() == 0 || cmds.size() == 0) return false; return std::ranges::any_of(cmds, [&cmd](const std::string& s) -> bool { return _stricmp(cmd.c_str(), s.c_str()) == 0; }); } /** * Checks if the given character is considered a white-space character. * ' ', (escaped) t, n, v, f, r * * @param {char} c - The character to check. * @return {bool} True if whitespace, false otherwise. */ static __forceinline bool _isspace(const char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; } /** * Parses a command string for quoted sub-arguments. * * @param {const char*} command - The command to parse. * @param {std::vector*} args - The return container to hold the found arguments. * @return {uint32_t} The number of arguments parsed from the command. */ static uint32_t GetCommandArgs(const char* command, std::vector* args) { enum class cState { None, InWord, InString }; // Prepare the needed variables.. char curr[2048]{}; auto p = command; char* pStart = nullptr; auto state = cState::None; // Walk the command and parse for quoted arguments.. for (; *p != 0; ++p) { const auto c = (char)*p; // Handle the current state.. switch (state) { /** * No current state, look for quotes to start a string.. */ case cState::None: if (Ashita::Commands::_isspace(c)) continue; if (c == '"') { state = cState::InString; pStart = (char*)p + 1; continue; } state = cState::InWord; pStart = (char*)p; continue; /** * String state, look for ending quote to complete a string.. */ case cState::InString: if (c == '"') { strncpy_s(curr, pStart, p - pStart); args->push_back(std::string(curr)); state = cState::None; pStart = nullptr; } continue; /** * Word state, look for a space to end the word.. */ case cState::InWord: if (Ashita::Commands::_isspace(c)) { strncpy_s(curr, pStart, p - pStart); args->push_back(std::string(curr)); state = cState::None; pStart = nullptr; } continue; } } // Add any left-over words to the args container.. if (pStart != nullptr) { strncpy_s(curr, pStart, p - pStart); args->push_back(std::string(curr)); } // Return the amount of found arguments.. return args->size(); } } // namespace Ashita::Commands #endif // ASHITA_SDK_COMMANDS_H_INCLUDED