Compare commits

..

No commits in common. "e6f4884b60a395cd8fddce9c829604875add9b5c" and "310011a6da8b27d6aa09749658a83c8461db686b" have entirely different histories.

8 changed files with 56 additions and 342 deletions

View File

@ -1,192 +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 "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;
}
}
}

View File

@ -1,89 +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
#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();
};
}

16
src/lib/error.cpp Normal file
View File

@ -0,0 +1,16 @@
// 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,21 +68,9 @@ 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 OUT_OF_RANGE = 1;
const uint8_t RANGE_ERROR = 1;
// when going out of bounds in a non-predetermined way
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;
const uint8_t OVERRUN_ERROR = 2;
}

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::OUT_OF_RANGE);
if (dataSize<currentPosition+1) return ErrorOr<int8_t>(true, ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
if (dataSize<currentPosition+2) return ErrorOr<int16_t>(true, ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
if (dataSize<currentPosition+4) return ErrorOr<int32_t>(true, ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
if (dataSize<currentPosition+8) return ErrorOr<int64_t>(true, ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
if (dataSize<currentPosition+4) return ErrorOr<float>(true, ErrorCodes::OVERRUN);
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+4) return ErrorOr<float>(true, ErrorCodes::OVERRUN_ERROR);
#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::OUT_OF_RANGE);
if (dataSize<currentPosition+8) return ErrorOr<double>(true, ErrorCodes::OVERRUN);
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::RANGE_ERROR);
if (dataSize<currentPosition+8) return ErrorOr<double>(true, ErrorCodes::OVERRUN_ERROR);
#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);
if (currentPosition+4+size.value > dataSize) return ErrorOr<std::vector<int8_t>>(true, ErrorCodes::OVERRUN_ERROR);
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);
if (currentPosition+4+(size.value*4) > dataSize) return ErrorOr<std::vector<int32_t>>(true, ErrorCodes::OVERRUN_ERROR);
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);
if (currentPosition+4+(size.value*8) > dataSize) return ErrorOr<std::vector<int64_t>>(true, ErrorCodes::OVERRUN_ERROR);
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

@ -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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// fully out of bounds
currentPosition = 10;
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
// 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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
// 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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
// 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::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
// read out of bounds
currentPosition = 200;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
// read out of bounds
currentPosition = 4;
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
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);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN_ERROR);
// read out of bounds
currentPosition = 8;
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::RANGE_ERROR);
std::cout << "Passed readFloat64 NBT helper test" << std::endl;

View File

@ -32,8 +32,7 @@ int main(int argc, char* argv[]){
bool ipv6 = true;
bool tcp = true;
bool udp = true;
bool listen = false;
std::string host = "";
bool server = false;
uint16_t port;
if (argc<2) {
usage;
@ -62,7 +61,7 @@ int main(int argc, char* argv[]){
continue;
}
if (argument=="-l") {
listen = true;
server = true;
continue;
}
if (argument=="-h") {
@ -73,15 +72,12 @@ int main(int argc, char* argv[]){
usage;
return EXIT_SUCCESS;
}
if (!listen && i==argc-2) {
host = argument;
continue;
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 (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())) {
@ -140,10 +136,5 @@ int main(int argc, char* argv[]){
}
// Argument parsing end ############################################
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;
}
//TODO: implement the actual tool
}