diff --git a/Source/Integration/StringDecoder.cpp b/Source/Integration/StringDecoder.cpp new file mode 100644 index 00000000..4fb36ea5 --- /dev/null +++ b/Source/Integration/StringDecoder.cpp @@ -0,0 +1,13 @@ +#include "StringDecoder.h" + +std::string_view StringDecoder::read_string_view() { + size_t length = read_length(); + if (length > Size) { + ErrBeyondEOF = true; + return std::string_view(); + } + std::string_view result(Text, length); + Text += length; + Size -= length; + return result; +} diff --git a/Source/Integration/StringDecoder.h b/Source/Integration/StringDecoder.h new file mode 100644 index 00000000..a08008cc --- /dev/null +++ b/Source/Integration/StringDecoder.h @@ -0,0 +1,117 @@ +#pragma once +#include "CoreMinimal.h" +#include "lpx-basewriter.hpp" + +///////////////////////////////////////////////////// +// +// StringDecoder +// +// This class is used to decipher 8-bit strings that +// contain packed ints, strings, and other data. +// The typical example of usage is to decipher the +// serialized animation queues fed to us by Luprex. +// +// The StringDecoder doesn't make a copy of the string +// you pass in, instead, it stores a pointer to it. +// So be sure not to free the string until you're +// done analyzing it. +// +// You'll note that some of the function names are +// lowercase, with underscores. That's because they're +// inherited from Luprex classes, and luprex classes +// use that naming convention. There's not any easy +// workaround for that. +// +///////////////////////////////////////////////////// + + +class StringDecoder : public BaseReader { +private: + const char* Text; + size_t Size; + +public: + // You can check and clear these error flags at will. + // + bool ErrBeyondEOF; + bool ErrStringTooLong; + +public: + // This function is required by BaseReader. + // It's not meant for end users. + // + void read_bytes_into(char* buffer, size_t size) { + if (size > Size) { + ErrBeyondEOF = true; + memset(buffer, 0, size); + Text += Size; + Size = 0; + } + else { + memcpy(buffer, Text, size); + Text += size; + Size -= size; + } + } + + // This function is required by BaseReader. + // It's not meant for end users. + // + void raise_string_too_long() { + ErrStringTooLong = true; + } + +public: + // The type returned by read_string. + // + using read_string_type = std::string; + + // Initialize the string decoder with a text to analyze. + // + StringDecoder(const char* text, int size) { + Text = text; + Size = size; + ErrBeyondEOF = false; + ErrStringTooLong = false; + } + + // Get the size of the remaining text. + // + size_t GetSize() { return Size; } + + // Return true if the remaining text is empty. + // + bool AtEOF() { return Size == 0; } + + // Read a string as a string_view + // + // This reads a string from the source, returning + // it as a string_view that points into the buffer. + // Naturally, if you release the buffer, the + // string_view is invalidated. + // + // This is considerably faster than read_string. + // + std::string_view read_string_view(); + + // Inherited Methods: + // + // The following methods are inherited from BaseReader: + // + // uint8_t read_uint8(); + // uint16_t read_uint16(); + // uint32_t read_uint32(); + // uint64_t read_uint64(); + // int8_t read_int8(); + // int16_t read_int16(); + // int32_t read_int32(); + // int64_t read_int64(); + // bool read_bool(); + // char read_char(); + // float read_float(); + // double read_double(); + // size_t read_length(); + // std::string read_string_limit(uint64_t size); + // std::string read_string(); + // +};