NBT: implement readFloat helpers
parent
38b2a6f270
commit
4f9577eb36
|
@ -20,33 +20,16 @@
|
||||||
#include "nbt.h++"
|
#include "nbt.h++"
|
||||||
#include "error.h++"
|
#include "error.h++"
|
||||||
|
|
||||||
// This is just an example for how to find out if the system is big endian
|
#include "../../.endianness"
|
||||||
// or little endian.
|
#ifdef FOSSVG_ENDIAN_BIG_WORD
|
||||||
//int endianness_example() {
|
#error "Honeywell-316-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||||
// if constexpr (std::endian::native == std::endian::big)
|
#endif
|
||||||
// {
|
#ifdef FOSSVG_ENDIAN_LITTLE_WORD
|
||||||
// // Big-endian system
|
#error "PDP-11-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||||
// return 0;
|
#endif
|
||||||
// }
|
#ifdef FOSSVG_ENDIAN_UNKNOWN
|
||||||
// else if constexpr (std::endian::native == std::endian::little)
|
#error "The endianness of your system could not be determined. Please set it manually. FOSS-VG is currently implemented using some endian-specific functions."
|
||||||
// {
|
#endif
|
||||||
// // Little-endian system
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// // Something else
|
|
||||||
// return 2;
|
|
||||||
// // How did we even end up here?
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// There is supposedly also a function htobe64 and be64toh to deal with
|
|
||||||
// converting 64 bit integers between host order and big endian.
|
|
||||||
|
|
||||||
// Though converting between host order and BE may not be necessary if the
|
|
||||||
// raw NBT data is to be used as instructions for rebuilding the data in memory.
|
|
||||||
// Doing the opposite may just be very painful.
|
|
||||||
|
|
||||||
namespace NBT {
|
namespace NBT {
|
||||||
namespace helper {
|
namespace helper {
|
||||||
|
@ -85,21 +68,63 @@ namespace NBT {
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: we just assume that float is a single-precision IEEE754
|
//FIXME: we just assume that float is a single-precision IEEE754
|
||||||
// floating point number
|
// floating point number, also we are using endian-dependent
|
||||||
|
// implementations
|
||||||
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
||||||
//TODO: implement assuming standard single-precision IEEE754 float
|
float* value = new float;
|
||||||
// Alternatively, maybe calculate a floating point number by using
|
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
|
||||||
// the stored value as math instructions?
|
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::RANGE_ERROR);
|
||||||
return ErrorOr<float>(0.0f);
|
if (dataSize<currentPosition+4) return ErrorOr<float>(true, ErrorCodes::OVERRUN_ERROR);
|
||||||
|
#ifdef FOSSVG_BIG_ENDIAN
|
||||||
|
*valueAsBytes = data[currentPosition];
|
||||||
|
*(valueAsBytes+1) = data[currentPosition+1];
|
||||||
|
*(valueAsBytes+2) = data[currentPosition+2];
|
||||||
|
*(valueAsBytes+3) = data[currentPosition+3];
|
||||||
|
#else
|
||||||
|
#ifdef FOSSVG_LITTLE_ENDIAN
|
||||||
|
*valueAsBytes = data[currentPosition+3];
|
||||||
|
*(valueAsBytes+1) = data[currentPosition+2];
|
||||||
|
*(valueAsBytes+2) = data[currentPosition+1];
|
||||||
|
*(valueAsBytes+3) = data[currentPosition];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
float dereferencedValue = *value;
|
||||||
|
delete value;
|
||||||
|
return ErrorOr<float>(dereferencedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: we just assume that double is a double-precision IEEE754
|
//FIXME: we just assume that double is a double-precision IEEE754
|
||||||
// floating point number
|
// floating point number, also we are using endian-dependent
|
||||||
|
// implementations
|
||||||
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
||||||
//TODO: implement assuming standard double-precision IEEE754 float
|
double* value = new double;
|
||||||
// Alternatively, maybe calculate a floating point number by using
|
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
|
||||||
// the stored value as math instructions?
|
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::RANGE_ERROR);
|
||||||
return ErrorOr<double>(0.0);
|
if (dataSize<currentPosition+8) return ErrorOr<double>(true, ErrorCodes::OVERRUN_ERROR);
|
||||||
|
#ifdef FOSSVG_BIG_ENDIAN
|
||||||
|
*valueAsBytes = data[currentPosition];
|
||||||
|
*(valueAsBytes+1) = data[currentPosition+1];
|
||||||
|
*(valueAsBytes+2) = data[currentPosition+2];
|
||||||
|
*(valueAsBytes+3) = data[currentPosition+3];
|
||||||
|
*(valueAsBytes+4) = data[currentPosition+4];
|
||||||
|
*(valueAsBytes+5) = data[currentPosition+5];
|
||||||
|
*(valueAsBytes+6) = data[currentPosition+6];
|
||||||
|
*(valueAsBytes+7) = data[currentPosition+7];
|
||||||
|
#else
|
||||||
|
#ifdef FOSSVG_LITTLE_ENDIAN
|
||||||
|
*valueAsBytes = data[currentPosition+7];
|
||||||
|
*(valueAsBytes+1) = data[currentPosition+6];
|
||||||
|
*(valueAsBytes+2) = data[currentPosition+5];
|
||||||
|
*(valueAsBytes+3) = data[currentPosition+4];
|
||||||
|
*(valueAsBytes+4) = data[currentPosition+3];
|
||||||
|
*(valueAsBytes+5) = data[currentPosition+2];
|
||||||
|
*(valueAsBytes+6) = data[currentPosition+1];
|
||||||
|
*(valueAsBytes+7) = data[currentPosition];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
double dereferencedValue = *value;
|
||||||
|
delete value;
|
||||||
|
return ErrorOr<double>(dereferencedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
|
||||||
|
|
|
@ -208,5 +208,41 @@ int main(){
|
||||||
|
|
||||||
std::cout << "Passed int64[] NBT helper test" << std::endl;
|
std::cout << "Passed int64[] NBT helper test" << std::endl;
|
||||||
|
|
||||||
|
// float32 ["float" in the current implementation :( ] #############
|
||||||
|
uint8_t dataForFloat32Test[] = {0xC7, 0x77, 0x77, 0x77};
|
||||||
|
dataSize = 4;
|
||||||
|
currentPosition = 0;
|
||||||
|
// read successfully
|
||||||
|
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).value == -63351.46484375f);
|
||||||
|
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == false);
|
||||||
|
// read overrun
|
||||||
|
currentPosition = 1;
|
||||||
|
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
|
||||||
|
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::RANGE_ERROR);
|
||||||
|
|
||||||
|
std::cout << "Passed float32 NBT helper test" << std::endl;
|
||||||
|
|
||||||
|
// float64 ["double" in the current implementation :( ] ############
|
||||||
|
uint8_t dataForFloat64Test[] = {0xC0, 0x34, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00};
|
||||||
|
dataSize = 8;
|
||||||
|
currentPosition = 0;
|
||||||
|
// read successfully
|
||||||
|
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).value == -20.015625476837158203125);
|
||||||
|
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == false);
|
||||||
|
// read overrun
|
||||||
|
currentPosition = 1;
|
||||||
|
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
|
||||||
|
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::RANGE_ERROR);
|
||||||
|
|
||||||
|
std::cout << "Passed float64 NBT helper test" << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue