Compare commits

...

6 Commits

Author SHA1 Message Date
BodgeMaster e6f4884b60 lib/error: finally removed that useless cpp file 2022-07-14 03:16:58 +02:00
BodgeMaster 91f3dfaa5e lib/cli: Add a library for command line arguments parsing
This has the parser itself already implemented, all other functionality is still
missing. So are tests.

Yes, I’m making my own getopt. Let me.
2022-07-14 03:13:48 +02:00
BodgeMaster 7e049fcfd1 lib/error: rename and add error constants 2022-07-13 22:01:18 +02:00
BodgeMaster c406555e4e tools/hexnet: argument parser fix 2022-07-13 20:35:33 +02:00
BodgeMaster 5cb1a52ec4 tools/hexnet: replace "server" with "listen" because that's what netcat calls it and the argument we use is -l like netcat's listen mode 2022-07-13 20:30:27 +02:00
BodgeMaster 9639ef065f tools/hexnet: Work on argument parser to finish suppurt for client mode 2022-07-13 20:27:58 +02:00
8 changed files with 342 additions and 56 deletions

192
src/lib/cli.cpp Normal file
View File

@ -0,0 +1,192 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include "cli.h++"
#include <string>
#include <vector>
#include <map>
#include "error.h++"
namespace CLI {
Flag::Flag() {
this->present = false;
}
Flag::Flag(char shortName, std::string longName, std::string description) {
this->shortName = shortName;
this->longName = longName;
this->description = description;
this->present = false;
}
UnpositionalArgument::UnpositionalArgument() {
this->present = false;
}
UnpositionalArgument::UnpositionalArgument(char shortName, std::string longName, std::string placeholder, std::string description) {
this->shortName = shortName;
this->longName = longName;
this->description = description;
this->placeholder = placeholder;
this->present = false;
}
PositionalArgument::PositionalArgument() {
this->present = false;
}
PositionalArgument::PositionalArgument(std::string description, std::string placeholder) {
this->description = description;
this->placeholder = placeholder;
this->present = false;
}
// using int here bc that's how main() is defined
ArgumentsParser::ArgumentsParser(int argc, char* argv[], std::vector<Flag> flags, std::vector<UnpositionalArgument> unpositionalArguments, std::vector<PositionalArgument> positionalArguments) {
this->wrongUsage = false;
this->wrongUsageMessages = std::vector<std::string>();
this->positionalArguments = positionalArguments;
// create lookup tables for all flags and unpositional arguments
// by their names
this->flagsByShortName = std::map<char, Flag*>();
this->flagsByLongName = std::map<std::string, Flag*>();
for (Flag flag: flags) {
Flag* flagPointer = new Flag();
*flagPointer = flag;
this->flagsByShortName[flag.shortName] = flagPointer;
this->flagsByLongName[flag.longName] = flagPointer;
}
this->argumentsByShortName = std::map<char, UnpositionalArgument*>();
this->argumentsByLongName = std::map<std::string, UnpositionalArgument*>();
for (UnpositionalArgument unpositionalArgument: unpositionalArguments) {
UnpositionalArgument* argumentPointer = new UnpositionalArgument();
*argumentPointer = unpositionalArgument;
this->argumentsByShortName[unpositionalArgument.shortName] = argumentPointer;
this->argumentsByLongName[unpositionalArgument.longName] = argumentPointer;
}
UnpositionalArgument* argumentWaitingForValue = nullptr;
std::vector<CLI::PositionalArgument>::size_type positionalArgumentCounter = 0;
for (int i=0; i<argc; i++) {
std::string argument(argv[i]);
if (argument[0]=='-') {
// do we have unfinished business?
if (argumentWaitingForValue!=nullptr) {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Argument expects value but has none: ")+argumentWaitingForValue->longName);
argumentWaitingForValue = nullptr;
}
// long name or short name?
if (argument[1]=='-') {
// long name
//FIXME: instead of auto, this should be what string
// length is defined as
// (std::__cxx11::basic_string<char>::size_type ?)
// argument with =value specified?
auto position = argument.find("=");
if (position==std::string::npos) {
// no =value
//is argument or flag?
std::string argumentName = argument.substr(2,argument.length());
if (flagsByLongName.contains(argumentName)) {
// flag
flagsByLongName[argumentName]->present = true;
} else if (argumentsByLongName.contains(argumentName)) {
// unpositional argument
argumentsByLongName[argumentName]->present = true;
argumentWaitingForValue = argumentsByLongName[argumentName];
} else {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Unknown argument or flag: ")+argument);
}
} else {
// has =value
std::string value = argument.substr(position, argument.length());
std::string argumentName = argument.substr(2, position);
if (argumentsByLongName.contains(argumentName)) {
argumentsByLongName[argumentName]->present = true;
argumentsByLongName[argumentName]->value = value;
} else {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Unknown argument (or it's a flag that doesn't take a value): ")+argument);
}
}
} else {
// short name
//FIXME: instead of int, this should use what string
// length is defined as
// (std::__cxx11::basic_string<char>::size_type ?)
// starting at 1 because 0 is '-'
for (int i=1; i<(int) argument.length(); i++) {
//is argument or flag?
if (flagsByShortName.contains(argument[i])) {
flagsByShortName[argument[i]]->present = true;
} else if (argumentsByShortName.contains(argument[i])) {
argumentsByShortName[argument[i]]->present = true;
//FIXME: see above
if (i+1==(int) argument.length()) {
argumentWaitingForValue = argumentsByShortName[argument[i]];
} else {
//assume the rest of the argv is a concatenated argument value
argumentsByShortName[argument[i]]->value = argument.substr(i+1, argument.length());
break;
}
} else {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Unknown argument or flag(s): ")+argument.substr(i, argument.length()));
// err on the side of caution to ensure that
// no unwanted options get activated on programs
// that deal gracefully with unrecognized command
// line parameters
break;
}
}
}
} else {
// positional argument or value for unpositional arg?
if (argumentWaitingForValue==nullptr) {
// positional argument
if (positionalArgumentCounter < this->positionalArguments.size()) {
this->positionalArguments.at(positionalArgumentCounter).present = true;
this->positionalArguments.at(positionalArgumentCounter).value = argument;
} else {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Too many positional arguments. Unexpected encounter of: ")+argument);
}
positionalArgumentCounter++;
} else {
// value for unpositional argument
argumentWaitingForValue->value = argument;
}
}
}
for (PositionalArgument const& positionalArgument: this->positionalArguments) {
if (!positionalArgument.present) {
this->wrongUsage = true;
this->wrongUsageMessages.push_back(std::string("Too few positional arguments! Missing: ")+positionalArgument.placeholder);
}
}
}
ArgumentsParser::~ArgumentsParser() {
//TODO: check that this actually runs
for (auto const& [shortName, flag]: this->flagsByShortName) {
delete flag;
}
for (auto const& [shortName, unpositionalArgument]: this->argumentsByShortName) {
delete unpositionalArgument;
}
}
}

89
src/lib/cli.h++ Normal file
View File

@ -0,0 +1,89 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#pragma once
#include <string>
#include <vector>
#include <map>
#include "error.h++"
namespace CLI {
struct Flag {
char shortName;
std::string longName;
// used for automatic usage generation
std::string description;
bool present;
Flag();
Flag(char shortName, std::string longName, std::string description);
};
struct UnpositionalArgument {
char shortName;
std::string longName;
// used for automatic usage generation
std::string description;
std::string placeholder; // the "COUNT" in "ping [-c <COUNT>] <HOST>"
bool present;
std::string value;
UnpositionalArgument();
UnpositionalArgument(char shortName, std::string longName, std::string placeholder, std::string description);
};
struct PositionalArgument {
// used for automatic usage generation
std::string description;
std::string placeholder; // the "HOST" in "ping [-c <COUNT>] <HOST>"
bool present;
std::string value;
PositionalArgument();
PositionalArgument(std::string description, std::string placeholder);
};
class ArgumentsParser {
bool wrongUsage;
std::vector<std::string> wrongUsageMessages;
std::string programName;
std::map<char, Flag*> flagsByShortName;
std::map<std::string, Flag*> flagsByLongName;
std::map<char, UnpositionalArgument*> argumentsByShortName;
std::map<std::string, UnpositionalArgument*> argumentsByLongName;
std::vector<PositionalArgument> positionalArguments;
// using int here bc that's how main() is defined
ArgumentsParser(int argc, char* argv[], std::vector<Flag> flags, std::vector<UnpositionalArgument> unpositionalArguments, std::vector<PositionalArgument> positionalArguments);
~ArgumentsParser();
ErrorOr<std::string> getProgramName();
ErrorOr<bool> getFlag(int argc, char* argv, char shortName);
ErrorOr<bool> getFlag(int argc, char* argv, std::string longName);
ErrorOr<std::string> getPositionalArgument(int argc, char* argv, int position);
ErrorOr<std::string> getUnpositionalArgument(int argc, char* argv, char shortName);
ErrorOr<std::string> getUnpositionalArgument(int argc, char* argv, std::string longName);
std::string getUsage();
};
}

View File

@ -1,16 +0,0 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include "error.h++"

View File

@ -68,9 +68,21 @@ namespace ErrorCodes {
// Using them is optional as ErrorOr<> accepts any uint8_t value as
// error code, but they are useful for readability.
// Ahh yes, very useful.
const uint8_t SUCCESS = 0;
// IndexOutOfRangeException equivalent
const uint8_t RANGE_ERROR = 1;
const uint8_t OUT_OF_RANGE = 1;
// when going out of bounds in a non-predetermined way
const uint8_t OVERRUN_ERROR = 2;
const uint8_t OVERRUN = 2;
// when checking for presence of something, for example CLI arguments
const uint8_t NOT_PRESENT = 3;
const uint8_t WRONG_USAGE = 4;
const uint8_t UNIMPLEMENTED = 254;
const uint8_t UNKNOWN = 255;
}

View File

@ -34,17 +34,17 @@
namespace NBT {
namespace helper {
ErrorOr<int8_t> readInt8(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+1) return ErrorOr<int8_t>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+1) return ErrorOr<int8_t>(true, ErrorCodes::OUT_OF_RANGE);
return ErrorOr<int8_t>((int8_t) data[currentPosition]);
}
ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+2) return ErrorOr<int16_t>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+2) return ErrorOr<int16_t>(true, ErrorCodes::OUT_OF_RANGE);
return ErrorOr<int16_t>((int16_t) ((static_cast<int16_t>(data[currentPosition]) << 8) | static_cast<int16_t>(data[currentPosition+1])));
}
ErrorOr<int32_t> readInt32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+4) return ErrorOr<int32_t>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+4) return ErrorOr<int32_t>(true, ErrorCodes::OUT_OF_RANGE);
return ErrorOr<int32_t>((int32_t) (
(static_cast<int32_t>(data[currentPosition ]) << 24) |
(static_cast<int32_t>(data[currentPosition+1]) << 16) |
@ -54,7 +54,7 @@ namespace NBT {
}
ErrorOr<int64_t> readInt64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+8) return ErrorOr<int64_t>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+8) return ErrorOr<int64_t>(true, ErrorCodes::OUT_OF_RANGE);
return ErrorOr<int64_t>((int64_t) (
(static_cast<int64_t>(data[currentPosition ]) << 56) |
(static_cast<int64_t>(data[currentPosition+1]) << 48) |
@ -73,8 +73,8 @@ namespace NBT {
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
float* value = new float;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+4) return ErrorOr<float>(true, ErrorCodes::OVERRUN_ERROR);
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::OUT_OF_RANGE);
if (dataSize<currentPosition+4) return ErrorOr<float>(true, ErrorCodes::OVERRUN);
#ifdef FOSSVG_BIG_ENDIAN
*valueAsBytes = data[currentPosition];
*(valueAsBytes+1) = data[currentPosition+1];
@ -101,8 +101,8 @@ namespace NBT {
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
double* value = new double;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+8) return ErrorOr<double>(true, ErrorCodes::OVERRUN_ERROR);
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::OUT_OF_RANGE);
if (dataSize<currentPosition+8) return ErrorOr<double>(true, ErrorCodes::OVERRUN);
#ifdef FOSSVG_BIG_ENDIAN
*valueAsBytes = data[currentPosition];
*(valueAsBytes+1) = data[currentPosition+1];
@ -137,7 +137,7 @@ namespace NBT {
if (size.isError) return ErrorOr<std::vector<int8_t>>(true, size.errorCode);
// get content
if (currentPosition+4+size.value > dataSize) return ErrorOr<std::vector<int8_t>>(true, ErrorCodes::OVERRUN_ERROR);
if (currentPosition+4+size.value > dataSize) return ErrorOr<std::vector<int8_t>>(true, ErrorCodes::OVERRUN);
std::vector<int8_t> result = std::vector<int8_t>();
for (int i=0; i<size.value; i++) {
result.push_back(data[currentPosition+4+i]);
@ -159,7 +159,7 @@ namespace NBT {
if (size.isError) return ErrorOr<std::vector<int32_t>>(true, size.errorCode);
// get content
if (currentPosition+4+(size.value*4) > dataSize) return ErrorOr<std::vector<int32_t>>(true, ErrorCodes::OVERRUN_ERROR);
if (currentPosition+4+(size.value*4) > dataSize) return ErrorOr<std::vector<int32_t>>(true, ErrorCodes::OVERRUN);
std::vector<int32_t> result = std::vector<int32_t>();
for (int i=0; i<size.value; i++) {
ErrorOr<int32_t> nextInt32 = readInt32(data, dataSize, currentPosition+4+(i*4));
@ -175,7 +175,7 @@ namespace NBT {
if (size.isError) return ErrorOr<std::vector<int64_t>>(true, size.errorCode);
// get content
if (currentPosition+4+(size.value*8) > dataSize) return ErrorOr<std::vector<int64_t>>(true, ErrorCodes::OVERRUN_ERROR);
if (currentPosition+4+(size.value*8) > dataSize) return ErrorOr<std::vector<int64_t>>(true, ErrorCodes::OVERRUN);
std::vector<int64_t> result = std::vector<int64_t>();
for (int i=0; i<size.value; i++) {
ErrorOr<int64_t> nextInt64 = readInt64(data, dataSize, currentPosition+4+(i*8));

View File

View File

@ -44,7 +44,7 @@ int main(){
// out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt8 NBT helper test" << std::endl;
@ -72,11 +72,11 @@ int main(){
// partially out of bounds
currentPosition = 9;
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt16 NBT helper test" << std::endl;
@ -104,11 +104,11 @@ int main(){
// partially out of bounds
currentPosition = 7;
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt32 NBT helper test" << std::endl;
@ -141,11 +141,11 @@ int main(){
// partially out of bounds
currentPosition = 3;
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt64 NBT helper test" << std::endl;
@ -194,15 +194,15 @@ int main(){
// read overrun
currentPosition = 20;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read with size partially out of bounds
currentPosition = 114;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt8Array NBT helper test" << std::endl;
@ -246,15 +246,15 @@ int main(){
// read overrun
currentPosition = 20;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read with size partially out of bounds
currentPosition = 114;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt32Array NBT helper test" << std::endl;
@ -307,15 +307,15 @@ int main(){
// read overrun
currentPosition = 20;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read with size partially out of bounds
currentPosition = 114;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readInt64Array NBT helper test" << std::endl;
@ -383,11 +383,11 @@ int main(){
// read overrun
currentPosition = 1;
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds
currentPosition = 4;
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readFloat32 NBT helper test" << std::endl;
@ -414,11 +414,11 @@ int main(){
// read overrun
currentPosition = 1;
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds
currentPosition = 8;
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readFloat64 NBT helper test" << std::endl;

View File

@ -32,7 +32,8 @@ int main(int argc, char* argv[]){
bool ipv6 = true;
bool tcp = true;
bool udp = true;
bool server = false;
bool listen = false;
std::string host = "";
uint16_t port;
if (argc<2) {
usage;
@ -61,7 +62,7 @@ int main(int argc, char* argv[]){
continue;
}
if (argument=="-l") {
server = true;
listen = true;
continue;
}
if (argument=="-h") {
@ -72,12 +73,15 @@ int main(int argc, char* argv[]){
usage;
return EXIT_SUCCESS;
}
if (!server && i==argc-2) {
//TODO: check if valid host
std::cerr << "Host argument parsing is not yet implemented." << std::endl;
return EXIT_UNIMPLEMENTED;
if (!listen && i==argc-2) {
host = argument;
continue;
}
if (i==argc-1) {
if (!listen && host=="") {
std::cerr << "Not running in listen mode and no host specified." << std::endl;
return EXIT_USAGE;
}
if (argument.substr(0, 2)=="0b" || argument.substr(0, 2)=="0B") {
// check for 16 bit binary number
for (char const &digit : argument.substr(2,argument.length())) {
@ -136,5 +140,10 @@ int main(int argc, char* argv[]){
}
// Argument parsing end ############################################
//TODO: implement the actual tool
if (!listen) {
//TODO: verify that host is possibly a valid host (or usage error)
//TODO: look up host if necessary, determine IPv4 or IPv6 mode if necessary
std::cerr << "Client mode not implemented" << std::endl;
return EXIT_UNIMPLEMENTED;
}
}