NBT: implement readFloat helpers
parent
38b2a6f270
commit
4f9577eb36
|
@ -20,33 +20,16 @@
|
|||
#include "nbt.h++"
|
||||
#include "error.h++"
|
||||
|
||||
// This is just an example for how to find out if the system is big endian
|
||||
// or little endian.
|
||||
//int endianness_example() {
|
||||
// if constexpr (std::endian::native == std::endian::big)
|
||||
// {
|
||||
// // Big-endian system
|
||||
// return 0;
|
||||
// }
|
||||
// else if constexpr (std::endian::native == std::endian::little)
|
||||
// {
|
||||
// // 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.
|
||||
#include "../../.endianness"
|
||||
#ifdef FOSSVG_ENDIAN_BIG_WORD
|
||||
#error "Honeywell-316-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_LITTLE_WORD
|
||||
#error "PDP-11-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_UNKNOWN
|
||||
#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
|
||||
|
||||
namespace NBT {
|
||||
namespace helper {
|
||||
|
@ -85,21 +68,63 @@ namespace NBT {
|
|||
}
|
||||
|
||||
//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) {
|
||||
//TODO: implement assuming standard single-precision IEEE754 float
|
||||
// Alternatively, maybe calculate a floating point number by using
|
||||
// the stored value as math instructions?
|
||||
return ErrorOr<float>(0.0f);
|
||||
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);
|
||||
#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
|
||||
// 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) {
|
||||
//TODO: implement assuming standard double-precision IEEE754 float
|
||||
// Alternatively, maybe calculate a floating point number by using
|
||||
// the stored value as math instructions?
|
||||
return ErrorOr<double>(0.0);
|
||||
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);
|
||||
#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) {
|
||||
|
|
|
@ -208,5 +208,41 @@ int main(){
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue