diff --git a/CommandLine/CMakeLists.txt b/CommandLine/CMakeLists.txt index 7e8c179..33cea0b 100644 --- a/CommandLine/CMakeLists.txt +++ b/CommandLine/CMakeLists.txt @@ -10,7 +10,7 @@ file(GLOB SOURCES "./private/*.cpp") file(GLOB HEADERS "./public/*.hpp") add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) target_include_directories(${PROJECT_NAME} PUBLIC ./public/) -target_link_libraries(${PROJECT_NAME} PUBLIC Tokenizer) +target_link_libraries(${PROJECT_NAME} PUBLIC Tokenizer Storage) ### -------------------------- Tests -------------------------- ### enable_testing() diff --git a/CommandLine/private/CmdLineInterpreter.cpp b/CommandLine/private/CmdLineInterpreter.cpp new file mode 100644 index 0000000..d3b0e40 --- /dev/null +++ b/CommandLine/private/CmdLineInterpreter.cpp @@ -0,0 +1,120 @@ +#include "CmdLineInterpreter.hpp" + +#define MAX_LINE_LENGTH 1024 + +#include +#include + +using namespace tp; + +static bool helpFunction(CmdLineInterpreter* self, const CommandLine& args) { + self->help(args); + return true; +} + +void CmdLineInterpreter::help(const CommandLine& args) const { + auto commandName = args.getString("CommandName"); + auto allCommands = commandName == "_none_"; + + if (allCommands) { + printf("Commands:\n"); + for (auto command : mCommands) { + printf(" %s\n", command->key.read()); + } + return; + } + + auto idx = mCommands.presents(commandName); + if (!idx) { + printf("Command '%s' not found\n", commandName.read()); + return; + } + + printf("Command '%s'\n", commandName.read()); + auto command = &mCommands.getSlotVal(idx); + command->args->help(); +} + +CmdLineInterpreter::CmdLineInterpreter() { + auto helpArgs = new CommandLine{ + { "CommandName", "_none_" } + }; + + addCommand("help", helpArgs, (CommandFunction) helpFunction, this); +} + + +void CmdLineInterpreter::addCommand(const String& id, CommandLine* args, CommandFunction function, void* customData) { + ASSERT(!mCommands.presents(id)) + mCommands.put(id, { args, function, customData }); +} + +void CmdLineInterpreter::run() { + char buffer[MAX_LINE_LENGTH]; + printf("Command Line Interpreter (or type 'exit' to quit):\n"); + + while (true) { + printf("%s >> ", mName.read()); + + // Read input from the user + if (fgets(buffer, MAX_LINE_LENGTH, stdin) == nullptr) { + printf("Error reading input.\n"); + return; + } + + // Remove the trailing newline character if it exists + auto length = strlen(buffer); + if (length > 0 && buffer[length - 1] == '\n') { + buffer[length - 1] = '\0'; + } + + // Check if the user wants to exit + if (strcmp(buffer, "exit") == 0) { + return; + } + + // Process the input here + processCommand(buffer); + } +} + +bool CmdLineInterpreter::processCommand(int1* commandString) { + ualni commandLen = 0; + for (auto i = commandString; *i != 0; i++) { + if (*i == ' ') break; + commandLen++; + } + + commandString[commandLen] = 0; + auto args = commandString + commandLen + 1; + + auto idx = mCommands.presents(commandString); + if (!idx) { + printf("ERROR: Command '%s' is not found\n", commandString); + printf("Please execute 'help' for more information\n\n"); + return true; + } + + auto command = &mCommands.getSlotVal(idx); + + command->args->parse(args); + + if (command->args->mError) { + printf("ERROR: Command call '%s' has invalid arguments\n", commandString); + command->args->resetError(); + return true; + } + + if (!command->function(command->customData, *command->args)) { + printf("ERROR: Command call '%s' failed\n", commandString); + return true; + } + + return true; +} + +CmdLineInterpreter::~CmdLineInterpreter() { + for (auto cmd : mCommands) { + delete cmd->val.args; + } +} \ No newline at end of file diff --git a/CommandLine/private/CommandLine.cpp b/CommandLine/private/CommandLine.cpp index 39cea49..77bfa2e 100644 --- a/CommandLine/private/CommandLine.cpp +++ b/CommandLine/private/CommandLine.cpp @@ -3,6 +3,9 @@ using namespace tp; +static ModuleManifest* sModuleDependencies[] = { &gModuleTokenizer, &gModuleStorage, nullptr }; +ModuleManifest tp::gModuleStorage = ModuleManifest("CommandLine", nullptr, nullptr, sModuleDependencies); + const char* regexSpace = "\n|\t| |\r"; const char* regexFalse = "N|n|(False)|(false)"; const char* regexTrue = "Y|y|(True)|(true)"; @@ -13,11 +16,13 @@ const char* regexString = "'{'-'}*'"; CommandLine::Arg::Arg(const Arg& arg) { mId = arg.mId; switch (arg.mType) { - case CommandLine::Arg::INT: mType = INT; mInt = arg.mInt; break; - case CommandLine::Arg::FLOAT: mType = FLOAT; mFloat = arg.mFloat; break; - case CommandLine::Arg::BOOL: mType = BOOL; mBool = arg.mBool; break; - case CommandLine::Arg::STR: mType = STR; new (&mStr) StringArg(); mStr = arg.mStr; break; - case CommandLine::Arg::FILE_IN: mType = FILE_IN; new (&mFile) FileInputArg(); mFile = arg.mFile; break; + case CommandLine::Arg::INT: mType = INT; mInt = arg.mInt; break; + case CommandLine::Arg::FLOAT: mType = FLOAT; mFloat = arg.mFloat; break; + case CommandLine::Arg::BOOL: mType = BOOL; mBool = arg.mBool; break; + case CommandLine::Arg::STR: mType = STR; new (&mStr) StringArg(); mStr = arg.mStr; break; + case CommandLine::Arg::FILE_IN: mType = FILE_IN; new (&mFile) FileInputArg(); mFile = arg.mFile; break; + default: + ASSERT(false) } mOptional = arg.mOptional; } @@ -30,6 +35,7 @@ CommandLine::Arg::Arg(const String& id, Type type) { case CommandLine::Arg::BOOL: mType = BOOL; new (&mBool) BoolArg(); break; case CommandLine::Arg::STR: mType = STR; new (&mStr) StringArg(); break; case CommandLine::Arg::FILE_IN: mType = FILE_IN; new (&mFile) FileInputArg(); break; + default: ASSERT(false) } mOptional = false; } @@ -119,6 +125,13 @@ CommandLine::CommandLine(const init_list& args) { }); ASSERT(mTokenizer.isBuild() && "Internal Error") + + mArgumentTokenizer.build({ + { regexSpace, ArgTokType::SPACE }, + { "{ - }*", ArgTokType::ARG } + }); + + ASSERT(mTokenizer.isBuild() && "Internal Error") } CommandLine::~CommandLine() { @@ -153,17 +166,60 @@ bool CommandLine::parse(char argc, const char* argv[], bool logError, ualni skip } idx++; } - return true; - - //set_working_dir(); } -alni CommandLine::getInt(const String& id) { auto& arg = getArg(id, Arg::INT); return arg.mInt.mVal; } -alnf CommandLine::getFloat(const String& id) { auto& arg = getArg(id, Arg::FLOAT); return arg.mFloat.mVal; } -bool CommandLine::getBool(const String& id) { auto& arg = getArg(id, Arg::BOOL); return arg.mBool.mFlag; } -const String& CommandLine::getString(const String& id) { auto& arg = getArg(id, Arg::STR); return arg.mStr.mStr; } -File& CommandLine::getFile(const String& id) { auto& arg = getArg(id, Arg::FILE_IN); return arg.mFile.mFile; } +bool CommandLine::parse(const char* args, bool logError) { + mArgumentTokenizer.bindSource(args); + mArgumentTokenizer.reset(); + + ualni argc = 0; + auto tok = mArgumentTokenizer.readTok(); + auto argument = mArgsOrder.first(); + + while (tok != ArgTokType::FAILURE && tok != ArgTokType::END) { + if (tok != ArgTokType::ARG) { + tok = mArgumentTokenizer.readTok(); + continue; + } + + if (!argument) { + ErrInvalidArgCount(); + if (logError) ErrLog(); + return false; + } + + parseArg(*argument->data, mArgumentTokenizer.extractVal().read()); + + if (mError && logError) { + ErrLog(); + return false; + } + + argc++; + argument = argument->next; + tok = mArgumentTokenizer.readTok(); + } + + ualni idx = 0; + for (auto arg : mArgsOrder) { + if (idx >= argc) { + initDefault(*arg.data()); + } + if (mError) { + if (logError) ErrLog(); + return false; + } + idx++; + } + return true; +} + +alni CommandLine::getInt(const String& id) const { auto& arg = getArg(id, Arg::INT); return arg.mInt.mVal; } +alnf CommandLine::getFloat(const String& id) const { auto& arg = getArg(id, Arg::FLOAT); return arg.mFloat.mVal; } +bool CommandLine::getBool(const String& id) const { auto& arg = getArg(id, Arg::BOOL); return arg.mBool.mFlag; } +const String& CommandLine::getString(const String& id) const { auto& arg = getArg(id, Arg::STR); return arg.mStr.mStr; } +const FileLocation& CommandLine::getFile(const String& id) const { auto& arg = getArg(id, Arg::FILE_IN); return arg.mFile.mFileLocation; } CommandLine::Arg& CommandLine::getArg(const String& id, Arg::Type type) { @@ -174,6 +230,14 @@ CommandLine::Arg& CommandLine::getArg(const String& id, Arg::Type type) { return *arg; } +const CommandLine::Arg& CommandLine::getArg(const String& id, Arg::Type type) const { + auto idx = mArgs.presents(id); + ASSERT(idx && "Invalid Id") + auto& arg = mArgs.getSlotVal(idx); + ASSERT(arg->mType == type && "Invalid Type Requested") + return *arg; +} + void CommandLine::ErrInvalidArgCount() { mError = { "Invalid Number Of Arguments Passed", nullptr }; } void CommandLine::ErrInvalidArgSyntax(Arg* arg) { mError = { "Invalid Syntax Of Argument", arg }; } void CommandLine::ErrInvalidArgType(Arg* arg) { mError = { "Invalid Type Of Argument", arg }; } @@ -192,7 +256,7 @@ void CommandLine::ErrLog() { } printf("\nArgument: %lli\n", idx); - ArgLog(*mError.mArg); + logArg(*mError.mArg); } printf("Error Description: %s. \n", mError.mDescr); @@ -201,7 +265,7 @@ void CommandLine::ErrLog() { ualni idx = 0; for (auto arg : mArgsOrder) { printf(" -- %lli -- \n", idx); - ArgLog(*arg.data()); + logArg(*arg.data()); idx++; } @@ -214,42 +278,43 @@ void CommandLine::ErrLog() { printf(" File - else\n"); } -void CommandLine::ArgLog(Arg& arg) { +void CommandLine::logArg(const Arg& arg) { switch (arg.mType) { - case Arg::INT: { - printf("Type : Int\n"); - printf("Range : %lli - %lli\n", arg.mInt.mAcceptingRange.mBegin, arg.mInt.mAcceptingRange.mEnd); - if (arg.mOptional) { - printf("Default : %lli\n", arg.mInt.mDefault); - } - printf("Given : %lli\n", arg.mInt.mVal); - } break; - case Arg::FLOAT: { - printf("Type : Float\n"); - printf("Range : %f - %f\n", (halnf) arg.mFloat.mAcceptingRange.mBegin, (halnf) arg.mFloat.mAcceptingRange.mEnd); - if (arg.mOptional) { - printf("Default : %f\n", arg.mFloat.mDefault); - } - printf("Given : %f\n", arg.mFloat.mVal); - } break; - case Arg::BOOL: { - printf("Type : Bool\n"); - if (arg.mOptional) { - printf("Default : %s\n", arg.mBool.mDefault ? "True" : "False"); - } - printf("Given : %s\n", arg.mBool.mFlag ? "True" : "False"); - } break; - case Arg::STR: { - printf("Type : String\n"); - if (arg.mOptional) { - printf("Default : %s\n", arg.mStr.mDefault.read()); - } - printf("Given : %s\n", arg.mStr.mStr.read()); - } break; - case Arg::FILE_IN: { - printf("Type : File Input\n"); - printf("Given Path : %s\n", arg.mFile.mFilepath.read()); - } break; + case Arg::INT: { + printf("Type : Int\n"); + printf("Range : %lli - %lli\n", arg.mInt.mAcceptingRange.mBegin, arg.mInt.mAcceptingRange.mEnd); + if (arg.mOptional) { + printf("Default : %lli\n", arg.mInt.mDefault); + } + printf("Value : %lli\n", arg.mInt.mVal); + } break; + case Arg::FLOAT: { + printf("Type : Float\n"); + printf("Range : %f - %f\n", (halnf) arg.mFloat.mAcceptingRange.mBegin, (halnf) arg.mFloat.mAcceptingRange.mEnd); + if (arg.mOptional) { + printf("Default : %f\n", arg.mFloat.mDefault); + } + printf("Value : %f\n", arg.mFloat.mVal); + } break; + case Arg::BOOL: { + printf("Type : Bool\n"); + if (arg.mOptional) { + printf("Default : %s\n", arg.mBool.mDefault ? "True" : "False"); + } + printf("Value : %s\n", arg.mBool.mFlag ? "True" : "False"); + } break; + case Arg::STR: { + printf("Type : String\n"); + if (arg.mOptional) { + printf("Default : %s\n", arg.mStr.mDefault.read()); + } + printf("Value : %s\n", arg.mStr.mStr.read()); + } break; + case Arg::FILE_IN: { + printf("Type : File Input\n"); + printf("Value Path : %s\n", arg.mFile.mFileLocation.getLocation().read()); + } break; + default: ASSERT(false) } } @@ -305,7 +370,8 @@ void CommandLine::parseArg(Arg& arg, const char* src) { ErrInvalidArgType(&arg); return; } - arg.mStr.mStr = val; + arg.mStr.mStr.resize(val.size() - 2); + memCopy(arg.mStr.mStr.write(), val.read() + 1, val.size() - 2); } break; case Arg::BOOL: { @@ -313,7 +379,7 @@ void CommandLine::parseArg(Arg& arg, const char* src) { ErrInvalidArgType(&arg); return; } - arg.mBool.mFlag = bool(val); + arg.mBool.mFlag = tok == TokType::BOOL_TRUE; } break; case Arg::FILE_IN: { @@ -322,24 +388,23 @@ void CommandLine::parseArg(Arg& arg, const char* src) { return; } - arg.mFile.mFilepath = val; + arg.mFile.mFileLocation.setLocation(val); - /* - // TODO : replace - if (!File::exists(arg.mFile.mFilepath.cstr())) { + if (!arg.mFile.mFileLocation.exists()) { ErrFileNotExists(&arg); return; } - arg.mFile.mFile.open(arg.mFile.mFilepath.cstr(), osfile_openflags::LOAD); - if (!arg.mFile.mFile.opened) { - ErrFileCouldNotOpen(&arg); - return; - } - */ - } break; + default: ASSERT(false) } arg.mIsPassed = true; } + +void CommandLine::help() const { + printf("Arguments:\n"); + for (auto arg : mArgsOrder) { + logArg(*arg.data()); + } +} \ No newline at end of file diff --git a/CommandLine/public/CmdLineInterpreter.hpp b/CommandLine/public/CmdLineInterpreter.hpp new file mode 100644 index 0000000..5839544 --- /dev/null +++ b/CommandLine/public/CmdLineInterpreter.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "CommandLine.hpp" +#include "Map.hpp" + +namespace tp { + + class CmdLineInterpreter { + public: + + typedef bool (*CommandFunction)(void* customData, const CommandLine& args); + + private: + + struct Command { + CommandLine* args; + CommandFunction function; + void* customData = nullptr; + }; + + Map mCommands; + String mName = "InterpName"; + + public: + CmdLineInterpreter(); + ~CmdLineInterpreter(); + + void setName(const String& name) { mName = name; } + [[nodiscard]] const String& getName() const { return mName; } + + void help(const CommandLine& args) const; + void addCommand(const String& id, CommandLine* args, CommandFunction function, void* customData = nullptr); + void run(); + bool processCommand(int1* command); + }; +} \ No newline at end of file diff --git a/CommandLine/public/CommandLine.hpp b/CommandLine/public/CommandLine.hpp index 9e406e1..51c98b6 100644 --- a/CommandLine/public/CommandLine.hpp +++ b/CommandLine/public/CommandLine.hpp @@ -2,13 +2,11 @@ #include "Tokenizer.hpp" #include "Map.hpp" +#include "LocalStorage.hpp" namespace tp { - // TODO : replace - class File { - - }; + extern ModuleManifest gModuleCommandLine; struct CommandLine { @@ -35,13 +33,12 @@ namespace tp { }; struct FileInputArg { - String mFilepath; - File mFile; + FileLocation mFileLocation; }; struct Arg { String mId; - enum Type { INT, FLOAT, BOOL, STR, FILE_IN } mType; + enum Type { INT, FLOAT, BOOL, STR, FILE_IN, NONE } mType = NONE; union { IntArg mInt; FloatArg mFloat; @@ -73,16 +70,23 @@ namespace tp { CommandLine(const init_list& args); ~CommandLine(); - bool parse(char argc, const char* argv[], bool logError = true, ualni skipArgs = 1); + void resetError() { mError.mDescr = nullptr; } - alni getInt(const String& id); - alnf getFloat(const String& id); - bool getBool(const String& id); - const String& getString(const String& id); - File& getFile(const String& id); + bool parse(char argc, const char* argv[], bool logError = true, ualni skipArgs = 1); + bool parse(const char* args, bool logError = true); + + void help() const; + + [[nodiscard]] alni getInt(const String& id) const; + [[nodiscard]] alnf getFloat(const String& id) const; + [[nodiscard]] bool getBool(const String& id) const; + [[nodiscard]] const String& getString(const String& id) const; + [[nodiscard]] const FileLocation& getFile(const String& id) const; + + const CommandLine& operator=(const CommandLine&) = delete; private: - enum class TokType { SPACE, INT, FLOAT, BOOL_FALSE, BOOL_TRUE, STR, NONE, FAILURE, END, } mType; + enum class TokType { SPACE, INT, FLOAT, BOOL_FALSE, BOOL_TRUE, STR, NONE, FAILURE, END, }; typedef SimpleTokenizer Tokenizer; Tokenizer mTokenizer; @@ -90,7 +94,12 @@ namespace tp { List mArgsOrder; ualni mOptionals = 0; + enum class ArgTokType { SPACE, ARG, NONE, FAILURE, END, }; + SimpleTokenizer mArgumentTokenizer; + Arg& getArg(const String& id, Arg::Type type); + [[nodiscard]] const Arg& getArg(const String& id, Arg::Type type) const; + void ErrInvalidArgCount(); void ErrInvalidArgSyntax(Arg* arg); void ErrInvalidArgType(Arg* arg); @@ -98,8 +107,8 @@ namespace tp { void ErrFileCouldNotOpen(Arg* arg); void ErrValNotinRange(Arg* arg); void ErrLog(); - static void ArgLog(Arg& arg); + static void logArg(const Arg& arg); static void initDefault(Arg& arg); void parseArg(Arg& arg, const char* src); }; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/CommandLine/tests/TestInterpreter.cpp b/CommandLine/tests/TestInterpreter.cpp new file mode 100644 index 0000000..eb00474 --- /dev/null +++ b/CommandLine/tests/TestInterpreter.cpp @@ -0,0 +1,34 @@ +#include "Tests.hpp" +#include "CmdLineInterpreter.hpp" + +using namespace tp; + +TEST_DEF_STATIC(Simple) { + + struct TestStruct { + int val = 0; + + static bool print(TestStruct* self, const CommandLine& args) { + printf("Test Val - %i\n", (int) args.getBool("bool")); + return false; + } + + }; + + TestStruct self; + + CmdLineInterpreter interp; + + interp.addCommand("test", new CommandLine{ { "bool", CommandLine::Arg::BOOL } }, (CmdLineInterpreter::CommandFunction) TestStruct::print); + + printf("test false\n", stdin); + printf("help\n", stdin); + printf("help test\n", stdin); + printf("exit\n", stdin); + + interp.run(); +} + +TEST_DEF(Interpreter) { + //testSimple(); +} diff --git a/CommandLine/tests/Tests.cpp b/CommandLine/tests/Tests.cpp index c1d284f..89e1d0f 100644 --- a/CommandLine/tests/Tests.cpp +++ b/CommandLine/tests/Tests.cpp @@ -12,7 +12,8 @@ int main() { return 1; } - testCommandLine(); + // testCommandLine(); + testInterpreter(); testModule.deinitialize(); } diff --git a/CommandLine/tests/Tests.hpp b/CommandLine/tests/Tests.hpp index 13f4290..eaac059 100644 --- a/CommandLine/tests/Tests.hpp +++ b/CommandLine/tests/Tests.hpp @@ -5,3 +5,4 @@ #include "CommandLine.hpp" void testCommandLine(); +void testInterpreter(); diff --git a/Storage/CMakeLists.txt b/Storage/CMakeLists.txt index d18d496..33f269a 100644 --- a/Storage/CMakeLists.txt +++ b/Storage/CMakeLists.txt @@ -12,6 +12,10 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) target_include_directories(${PROJECT_NAME} PUBLIC ./public/) target_link_libraries(${PROJECT_NAME} PUBLIC Strings) + +### -------------------------- Applications -------------------------- ### +add_subdirectory(applications) + ### -------------------------- Tests -------------------------- ### enable_testing() file(GLOB TEST_SOURCES "./tests/*.cpp") @@ -19,8 +23,4 @@ add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils) add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) -install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib) - - -# todo :remove -add_subdirectory(applications) \ No newline at end of file +install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib) \ No newline at end of file diff --git a/Storage/applications/CMakeLists.txt b/Storage/applications/CMakeLists.txt index 8e1e2df..b8f171f 100644 --- a/Storage/applications/CMakeLists.txt +++ b/Storage/applications/CMakeLists.txt @@ -3,9 +3,15 @@ cmake_minimum_required(VERSION 3.2) project(Applications) -### ---------------------- Applications --------------------- ### -add_executable(Server ./Server.cpp) -add_executable(Client ./Client.cpp) +file(GLOB SOURCES_CLIENT ./Client.cpp) +file(GLOB SOURCES_SERVER ./Server.cpp) -include_directories(Client ./../../Externals/asio/asio/include) -include_directories(Server ./../../Externals/asio/asio/include) \ No newline at end of file +set(ASIO_INCLUDE ./../../Externals/asio/asio/include) + +add_executable(Client ${SOURCES_CLIENT}) +include_directories(Client ${ASIO_INCLUDE}) +#link_libraries(Client Storage CommandLine) + +add_executable(Server ${SOURCES_SERVER}) +include_directories(Server ${ASIO_INCLUDE}) +#link_libraries(Server Storage CommandLine) diff --git a/Storage/private/LocalStorage.cpp b/Storage/private/LocalStorage.cpp index fccaad7..3410854 100644 --- a/Storage/private/LocalStorage.cpp +++ b/Storage/private/LocalStorage.cpp @@ -2,8 +2,21 @@ #include "SystemHandle.hpp" +#include + using namespace tp; + +bool FileLocation::exists() const { + FILE* file = fopen(mLocation.read(), "r"); + if (file) { + // File exists, close it and return 1 + fclose(file); + return true; + } + return false; +} + bool File::connect(const FileLocation& location, const FileConnectionType& connectionInfo) { DEBUG_ASSERT(!mStatus.isOpened()); if (mStatus.isOpened()) return false; diff --git a/Storage/public/LocalStorage.hpp b/Storage/public/LocalStorage.hpp index 33e2f36..f1cf805 100644 --- a/Storage/public/LocalStorage.hpp +++ b/Storage/public/LocalStorage.hpp @@ -13,6 +13,7 @@ namespace tp { explicit FileLocation(const String& location) : mLocation(location) {} void setLocation(const String& location) { mLocation = location; } [[nodiscard]] const String& getLocation() const { return mLocation; } + [[nodiscard]] bool exists() const; }; class FileConnectionType { diff --git a/Strings/public/Strings.hpp b/Strings/public/Strings.hpp index c3b6472..b146d41 100644 --- a/Strings/public/Strings.hpp +++ b/Strings/public/Strings.hpp @@ -188,17 +188,20 @@ namespace tp { explicit operator alni() { alni out; - return Logic::convertStringToValue(read(), out); + Logic::convertStringToValue(read(), out); + return out; } explicit operator alnf() { alnf out; - return Logic::convertStringToValue(read(), out); + Logic::convertStringToValue(read(), out); + return out; } explicit operator bool() { bool out; - return Logic::convertStringToValue(read(), out); + Logic::convertStringToValue(read(), out); + return out; } Index size() const { diff --git a/Tokenizer/public/Tokenizer.hpp b/Tokenizer/public/Tokenizer.hpp index c48552a..3a041c5 100644 --- a/Tokenizer/public/Tokenizer.hpp +++ b/Tokenizer/public/Tokenizer.hpp @@ -168,7 +168,7 @@ namespace tp { String extractVal() { auto crs = getCursorPrev(); String out; - out.resize(mLastTokLen + 1); + out.resize(mLastTokLen); memCopy(out.write(), crs.str(), mLastTokLen); return out; }