More work on AnimQueueDecoder

This commit is contained in:
2023-09-08 05:38:09 -04:00
parent d845eab6f5
commit dcaa916347
4 changed files with 202 additions and 15 deletions

View File

@@ -0,0 +1,54 @@
#include "AnimQueue.h"
FAnimStep FAnimQueueDecoder::ReadStep() {
FAnimStep result;
result.Hash = Decoder.read_uint64();
result.Body = Decoder.read_string_view();
return result;
}
FAnimField FAnimStepDecoder::ReadField() {
FAnimField result;
result.Name = Decoder.read_string_view();
result.Persistent = Decoder.read_bool();
result.Type = (EAnimValueType)Decoder.read_uint8();
switch (result.Type) {
case T_STRING: {
result.S = Decoder.read_string_view();
break;
}
case T_NUMBER: {
result.X = Decoder.read_double();
break;
}
case T_BOOLEAN: {
result.X = Decoder.read_bool() ? 1.0 : 0.0;
break;
}
case T_XYZ: {
result.X = Decoder.read_double();
result.Y = Decoder.read_double();
result.Z = Decoder.read_double();
break;
}
default: {
Decoder.set_at_eof();
result.Type = T_BOOLEAN;
result.X = 0;
break;
}
}
return result;
}
FString FAnimQueueDecoder::DebugString(std::string_view queue) {
// IMPLEMENT ME
return FString();
}
FString FAnimStepDecoder::DebugString(const FAnimStep& step) {
// IMPLEMENT ME
return FString();
}

View File

@@ -0,0 +1,121 @@
#pragma once
#include "CoreMinimal.h"
#include "StringDecoder.h"
////////////////////////////////////////////////
//
// This is copied over from Luprex source. Not ideal.
//
////////////////////////////////////////////////
enum EAnimValueType {
T_STRING,
T_NUMBER,
T_BOOLEAN,
T_XYZ,
T_UNINITIALIZED
};
////////////////////////////////////////////////
//
// An single animation step.
//
// The body consists of a sequence of FAnimField
// records. The body is encoded, to read the
// FAnimField records you need an FAnimStepDecoder.
//
////////////////////////////////////////////////
struct FAnimStep {
uint32 Hash;
std::string_view Body;
};
////////////////////////////////////////////////
//
// A single animation field.
//
// A field consists of a variable name,
// a persistent flag, a type, and some fields
// to hold the values.
//
// If the value is boolean, it is stored in
// X, as either 1 or 0. If the value is double,
// it is stored in X.
//
////////////////////////////////////////////////
struct FAnimField {
std::string_view Name;
bool Persistent;
EAnimValueType Type;
double X, Y, Z;
std::string_view S;
};
////////////////////////////////////////////////
//
// An Animation Queue Decoder.
//
// This acts a lot like a stream reader,
// it reads one AnimEntry at a time from
// the animation queue until you reach
// 'end-of-file'.
//
////////////////////////////////////////////////
class FAnimQueueDecoder {
private:
FStringDecoder Decoder;
public:
// Initialize the FAnimQueueDecoder with the encoded animation queue.
//
FAnimQueueDecoder(std::string_view s) : Decoder(s) {}
// Return true if the parser has reached the end of the string.
//
bool AtEOF() { return Decoder.at_eof(); }
// Read one animation step.
//
FAnimStep ReadStep();
// Convert an AnimQueue to an FString.
//
static FString DebugString(std::string_view s);
};
////////////////////////////////////////////////
//
// An Animation Step Decoder.
//
// This acts a lot like a stream reader,
// it reads one FAnimField at a time from
// the animation queue until you reach
// 'end-of-file'.
//
////////////////////////////////////////////////
class FAnimStepDecoder {
private:
FStringDecoder Decoder;
public:
// Initialize the FAnimStepDecoder from the FAnimStep.
//
FAnimStepDecoder(const FAnimStep &step) : Decoder(step.Body) {}
// Return true if the parser has reached the end of the string.
//
bool AtEOF() { return Decoder.at_eof(); }
// Read one field.
//
FAnimField ReadField();
// Convert an AnimStep to an FString.
//
static FString DebugString(const FAnimStep &step);
};

View File

@@ -1,6 +1,13 @@
#include "StringDecoder.h" #include "StringDecoder.h"
std::string_view StringDecoder::read_string_view() { FStringDecoder::FStringDecoder(std::string_view s) {
Text = s.data();
Size = s.size();
ErrBeyondEOF = false;
ErrStringTooLong = false;
}
std::string_view FStringDecoder::read_string_view() {
size_t length = read_length(); size_t length = read_length();
if (length > Size) { if (length > Size) {
ErrBeyondEOF = true; ErrBeyondEOF = true;
@@ -11,3 +18,9 @@ std::string_view StringDecoder::read_string_view() {
Size -= length; Size -= length;
return result; return result;
} }
void FStringDecoder::set_at_eof() {
Text += Size;
Size = 0;
}

View File

@@ -1,17 +1,18 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "lpx-basewriter.hpp" #include "lpx-basewriter.hpp"
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// //
// StringDecoder // FStringDecoder
// //
// This class is used to decipher 8-bit strings that // This class is used to decipher 8-bit strings that
// contain packed ints, strings, and other data. // contain packed ints, strings, and other data.
// The typical example of usage is to decipher the // The typical example of usage is to decipher the
// serialized animation queues fed to us by Luprex. // serialized animation queues fed to us by Luprex.
// //
// The StringDecoder doesn't make a copy of the string // The FStringDecoder doesn't make a copy of the string
// you pass in, instead, it stores a pointer to it. // you pass in, instead, it stores a pointer to it.
// So be sure not to free the string until you're // So be sure not to free the string until you're
// done analyzing it. // done analyzing it.
@@ -25,7 +26,7 @@
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
class StringDecoder : public BaseReader<StringDecoder> { class FStringDecoder : public BaseReader<FStringDecoder> {
private: private:
const char* Text; const char* Text;
size_t Size; size_t Size;
@@ -42,10 +43,9 @@ public:
// //
void read_bytes_into(char* buffer, size_t size) { void read_bytes_into(char* buffer, size_t size) {
if (size > Size) { if (size > Size) {
ErrBeyondEOF = true;
memset(buffer, 0, size); memset(buffer, 0, size);
Text += Size; ErrBeyondEOF = true;
Size = 0; set_at_eof();
} }
else { else {
memcpy(buffer, Text, size); memcpy(buffer, Text, size);
@@ -68,20 +68,19 @@ public:
// Initialize the string decoder with a text to analyze. // Initialize the string decoder with a text to analyze.
// //
StringDecoder(const char* text, int size) { FStringDecoder(std::string_view s);
Text = text;
Size = size;
ErrBeyondEOF = false;
ErrStringTooLong = false;
}
// Get the size of the remaining text. // Get the size of the remaining text.
// //
size_t GetSize() { return Size; } size_t get_size() { return Size; }
// Return true if the remaining text is empty. // Return true if the remaining text is empty.
// //
bool AtEOF() { return Size == 0; } bool at_eof() { return Size == 0; }
// Move the cursor to EOF.
//
void set_at_eof();
// Read a string as a string_view // Read a string as a string_view
// //