lib/nbt: implement readString NBT helper function

BodgeMaster-unfinished
Milan Suman 2022-07-20 12:08:04 +05:30
parent 9562ae7be9
commit b5312aeb58
9 changed files with 87 additions and 14 deletions

View File

@ -72,7 +72,7 @@ echo "Building tools..."
mkdir -pv bin/tools
# add compile commands to this array
COMPILE_COMMANDS=(
"$CXX_WITH_FLAGS src/tools/dumpnbt.cpp -Lbin/lib -l:nbt.so -o bin/tools/dumpnbt"
"$CXX_WITH_FLAGS src/tools/dumpnbt.cpp -I dependencies/tiny-utf8-4.4.3/include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/tools/dumpnbt"
"$CXX_WITH_FLAGS src/tools/hexnet.cpp -Lbin/lib -l:cli.so -l:libsockpp.so -Idependencies/sockpp-0.7.1/include -o bin/tools/hexnet"
)
for command in ${!COMPILE_COMMANDS[@]}; do

View File

@ -37,7 +37,7 @@ echo "Building tests..."
# add compile commands to this array
COMPILE_COMMANDS=(
"$CXX_WITH_FLAGS src/test/nbt_helpers.cpp -Lbin/lib -l:nbt.so -o bin/test/nbt_helpers"
"$CXX_WITH_FLAGS src/test/nbt_helpers.cpp -Idependencies/tiny-utf8-4.4.3/include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_helpers"
"$CXX_WITH_FLAGS src/test/cli_argument_parser.cpp -Lbin/lib -l:cli.so -o bin/test/cli_argument_parser"
"$CXX_WITH_FLAGS src/test/javacompat.cpp -Idependencies/tiny-utf8-4.4.3/include -Lbin/lib -l:javacompat.so -o bin/test/javacompat"
)

View File

@ -81,4 +81,7 @@ namespace ErrorCodes {
const uint8_t UNIMPLEMENTED = 254;
const uint8_t UNKNOWN = 255;
//mismatched size in java strings
const uint8_t MISMATCHEDSIZE = 6;
}

View File

@ -32,9 +32,13 @@
namespace JavaCompat {
//FIXME: contrary to what I said, we need to explicitly pass the data
// size because files could have been tampered with or corrupted
tiny_utf8::string importJavaString(uint8_t data[]) {
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size) {
std::string stdString;
uint16_t size = static_cast<uint16_t>(data[0])<<8 | static_cast<uint16_t>(data[1]);
uint16_t encodedSize = static_cast<uint16_t>(data[0])<<8 | static_cast<uint16_t>(data[1]);
if(encodedSize != size){
return ErrorOr<tiny_utf8::string>(true, ErrorCodes::MISMATCHEDSIZE);
}
for(uint8_t i=2; i<size+2; i++){
if(i != 0){
@ -45,7 +49,7 @@ namespace JavaCompat {
}
stdString.push_back((char) data[i]);
}
return tiny_utf8::string(stdString);
return ErrorOr<tiny_utf8::string>(tiny_utf8::string(stdString));
}
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data) {
@ -54,6 +58,10 @@ namespace JavaCompat {
std::vector<uint8_t> output = std::vector<uint8_t>();
std::string stdString = data.cpp_str();
if(stdString.size() > 0xFFFF){
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::OVERRUN);
}
*size = (uint16_t) stdString.size();
//placeholder size bytes

View File

@ -18,8 +18,6 @@
#include <vector>
namespace JavaCompat {
//FIXME: contrary to what I said, we need to explicitly pass the data
// size because files could have been tampered with or corrupted
tiny_utf8::string importJavaString(uint8_t data[]);
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size);
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data);
}

View File

@ -16,9 +16,12 @@
#include <bit>
#include <cstdint>
#include <vector>
#include <tinyutf8/tinyutf8.h>
#include "nbt.h++"
#include "error.h++"
#include "javacompat.h++"
#include "../../.endianness"
#ifdef FOSSVG_ENDIAN_BIG_WORD
@ -148,10 +151,17 @@ namespace NBT {
// Maybe use a struct that holds decoded (de-Java-fied) string
// data, decoded size, and original size? Original size is needed
// so the parser knows where to continue.
//ErrorOr<> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
// return ErrorOr<>("");
//}
ErrorOr<tiny_utf8::string> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if(dataSize > 0xFFFF){
return ErrorOr<tiny_utf8::string>(true, ErrorCodes::OVERRUN);
}
ErrorOr<tiny_utf8::string> output = JavaCompat::importJavaString(data+currentPosition, (uint16_t) dataSize);
if(output.isError){
return ErrorOr<tiny_utf8::string>(true, output.errorCode);
}
return output;
}
ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
// get size prefix

View File

@ -38,6 +38,7 @@
#include <cstdint>
#include <vector>
#include "error.h++"
#include <tinyutf8/tinyutf8.h>
namespace NBT {
namespace helper {
@ -52,7 +53,7 @@ namespace NBT {
// floating point number
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
//ErrorOr<> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<tiny_utf8::string> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int64_t>> readInt64Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);

View File

@ -52,7 +52,7 @@ int main(){
return 2;
}
tiny_utf8::string importedString = JavaCompat::importJavaString(reinterpret_cast<uint8_t*>(javaStdString.data()));
tiny_utf8::string importedString = JavaCompat::importJavaString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0x75).value;
std::streampos normalSize;
std::string normalStdString;

View File

@ -16,11 +16,13 @@
#include <iostream>
#include <cstdint>
#include <vector>
#include <fstream>
#include "assert.h++"
#include "../lib/nbt.h++"
#include "../lib/error.h++"
#include "../lib/javacompat.h++"
int main(){
std::cout << "################################################################################" << std::endl;
@ -442,5 +444,56 @@ int main(){
std::cout << "Passed writeInt64 NBT helper test" << std::endl;
//readString test
char* nextChar = new char;
//reading data from the java modified utf8 file
std::streampos javaSize;
std::string javaStdString;
const char* javaFilePath = "./resources/unicode_data/java-style_unicode";
std::ifstream javaFile(javaFilePath, std::ios::in | std::ios::binary | std::ios::ate);
if(javaFile.is_open()){
javaSize = javaFile.tellg();
javaFile.seekg(0, std::ios::beg);
for (int i=0; i<javaSize; i++) {
javaFile.read(nextChar, 1);
javaStdString.push_back(*nextChar);
}
javaFile.close();
} else {
std::cerr << "Failed to open file: " << javaFilePath << std::endl;
return 2;
}
//reading data from the normal utf8 file
std::streampos normalSize;
std::string normalStdString;
const char* normalFilePath = "./resources/unicode_data/normal_utf-8";
std::ifstream normalFile(normalFilePath, std::ios::in | std::ios::binary | std::ios::ate);
if(normalFile.is_open()){
normalSize = normalFile.tellg();
normalFile.seekg(0, std::ios::beg);
for (int i=0; i<normalSize; i++) {
normalFile.read(nextChar, 1);
normalStdString.push_back(*nextChar);
}
normalFile.close();
} else {
std::cerr << "Failed to open file: " << normalFilePath << std::endl;
return 2;
}
tiny_utf8::string normalString = tiny_utf8::string(normalStdString);
ASSERT(normalString == NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0x75, 0).value)
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0xFFFFF, 0).errorCode == ErrorCodes::OVERRUN);
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0xF, 0).errorCode == ErrorCodes::MISMATCHEDSIZE);
std::cout << "Passed readString NBT helper test." << std::endl;
return 0;
}