Skip to content

Instantly share code, notes, and snippets.

@SirKane
Created February 9, 2020 15:27
Show Gist options
  • Save SirKane/84f4d8bf1392a0a4b720087e414b4143 to your computer and use it in GitHub Desktop.
Save SirKane/84f4d8bf1392a0a4b720087e414b4143 to your computer and use it in GitHub Desktop.
Generation 1 binary varmap
enum class eSerializedVariantType_G1 : uint8_t
{
Empty = 0,
VarMap,
BoolTrue,
BoolFalse,
Int32,
Int64,
Float,
Vec4f,
Vec4i,
Vec3f,
Vec3i,
Vec2f,
Vec2i,
String,
File,
Uid,
UidRef,
};
static bool LoadValue(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value);
static bool Load_Empty(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
value = CVariant();
return true;
}
static bool Load_VarMap(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
uint32_t i;
uint32_t intKeyedCount, variantKeyedCount;
CVarMapHandle hVarMap;
if (!reader.ReadVarU32_G1(intKeyedCount))
{
return false;
}
if (!reader.ReadVarU32_G1(variantKeyedCount))
{
return false;
}
if (intKeyedCount > 0x10000000 ||
variantKeyedCount > 0x10000000)
{
return false;
}
for (i = 0; i < intKeyedCount; i++)
{
CVariant value;
if (!LoadValue(reader, strings, value))
{
return false;
}
hVarMap.Insert((int32_t)i, value);
}
for (i = 0; i < variantKeyedCount; i++)
{
CVariant key, value;
if (!LoadValue(reader, strings, key))
{
return false;
}
if (!LoadValue(reader, strings, value))
{
return false;
}
hVarMap.Insert(key, value);
}
value = hVarMap;
return true;
}
static bool Load_Int32(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
int32_t readValue;
if (!reader.ReadVarS32_G1(readValue))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Int64(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
int64_t readValue;
if (!reader.ReadS64(readValue))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Float(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
float readValue;
if (!reader.ReadFloat(readValue))
{
return false;
}
value = readValue;
return true;
}
static bool Load_BoolTrue(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
value = true;
return true;
}
static bool Load_BoolFalse(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
value = false;
return true;
}
static bool Load_Vec4f(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec4f readValue;
if (!reader.ReadFloat(readValue.x))
{
return false;
}
if (!reader.ReadFloat(readValue.y))
{
return false;
}
if (!reader.ReadFloat(readValue.z))
{
return false;
}
if (!reader.ReadFloat(readValue.w))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Vec4i(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec4i readValue;
if (!reader.ReadVarS32_G1(readValue.x))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.y))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.z))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.w))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Vec3f(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec3f readValue;
if (!reader.ReadFloat(readValue.x))
{
return false;
}
if (!reader.ReadFloat(readValue.y))
{
return false;
}
if (!reader.ReadFloat(readValue.z))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Vec3i(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec3i readValue;
if (!reader.ReadVarS32_G1(readValue.x))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.y))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.z))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Vec2f(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec2f readValue;
if (!reader.ReadFloat(readValue.x))
{
return false;
}
if (!reader.ReadFloat(readValue.y))
{
return false;
}
value = readValue;
return true;
}
static bool Load_Vec2i(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CVec2i readValue;
if (!reader.ReadVarS32_G1(readValue.x))
{
return false;
}
if (!reader.ReadVarS32_G1(readValue.y))
{
return false;
}
value = readValue;
return true;
}
static bool Load_String(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
uint32_t stringIndex;
if (!reader.ReadVarU32_G1(stringIndex))
{
return false;
}
if (stringIndex >= strings.Size())
{
return false;
}
value = CVarString(strings[stringIndex]());
return true;
}
static bool Load_File(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
uint32_t stringIndex;
if (!reader.ReadVarU32_G1(stringIndex))
{
return false;
}
if (stringIndex >= strings.Size())
{
return false;
}
value = CVarFile(strings[stringIndex]());
return true;
}
static bool Load_UID(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CUid uid;
if (!reader.ReadU64(uid.Uid.LowValue))
{
return false;
}
if (!reader.ReadU64(uid.Uid.HighValue))
{
return false;
}
value = uid;
return true;
}
static bool Load_UIDRef(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
CUidRef uid;
if (!reader.ReadU64(uid.Uid.LowValue))
{
return false;
}
if (!reader.ReadU64(uid.Uid.HighValue))
{
return false;
}
value = uid;
return true;
}
static bool LoadValue(CBinaryVarMapReader &reader,
TDynArray<CStringA> &strings, CVariant &value)
{
uint8_t valueType;
if (!reader.ReadU8(valueType))
{
return false;
}
eSerializedVariantType_G1 type = (eSerializedVariantType_G1)valueType;
switch (type)
{
case eSerializedVariantType_G1::Empty:
{
return Load_Empty(reader, strings, value);
}
case eSerializedVariantType_G1::VarMap:
{
return Load_VarMap(reader, strings, value);
}
case eSerializedVariantType_G1::BoolTrue:
{
return Load_BoolTrue(reader, strings, value);
}
case eSerializedVariantType_G1::BoolFalse:
{
return Load_BoolFalse(reader, strings, value);
}
case eSerializedVariantType_G1::Int32:
{
return Load_Int32(reader, strings, value);
}
case eSerializedVariantType_G1::Int64:
{
return Load_Int64(reader, strings, value);
}
case eSerializedVariantType_G1::Float:
{
return Load_Float(reader, strings, value);
}
case eSerializedVariantType_G1::Vec4f:
{
return Load_Vec4f(reader, strings, value);
}
case eSerializedVariantType_G1::Vec4i:
{
return Load_Vec4i(reader, strings, value);
}
case eSerializedVariantType_G1::Vec3f:
{
return Load_Vec3f(reader, strings, value);
}
case eSerializedVariantType_G1::Vec3i:
{
return Load_Vec3i(reader, strings, value);
}
case eSerializedVariantType_G1::Vec2f:
{
return Load_Vec2f(reader, strings, value);
}
case eSerializedVariantType_G1::Vec2i:
{
return Load_Vec2i(reader, strings, value);
}
case eSerializedVariantType_G1::String:
{
return Load_String(reader, strings, value);
}
case eSerializedVariantType_G1::File:
{
return Load_File(reader, strings, value);
}
case eSerializedVariantType_G1::Uid:
{
return Load_UID(reader, strings, value);
}
case eSerializedVariantType_G1::UidRef:
{
return Load_UIDRef(reader, strings, value);
}
default:
{
return false;
}
}
}
static bool LoadValueFromReader(CBinaryVarMapReader &reader, CVariant &outValue)
{
uint32_t stringCount, i;
TDynArray<CStringA> strings;
const uint32_t expectedMagic =
((uint32_t)0xFF << 0) |
((uint32_t)'B' << 8) |
((uint32_t)'V' << 16) |
((uint32_t)'M' << 24);
uint32_t magic;
if (!reader.ReadU32(magic))
{
return false;
}
if (magic != expectedMagic)
{
return false;
}
if (!reader.ReadVarU32_G1(stringCount))
{
return false;
}
strings.Resize(stringCount);
for (i = 0; i < stringCount; i++)
{
uint32_t stringLength;
if (!reader.ReadVarU32_G1(stringLength))
{
return false;
}
CStringA &string = strings[i];
string.Resize(stringLength);
if (!reader.ReadRaw(string.GetBuffer(), stringLength))
{
return false;
}
}
outValue = CVariant();
return LoadValue(reader, strings, outValue);
}
bool LoadVariant_G1(const void* pData, size_t length, CVariant &outVariant)
{
if (pData == nullptr ||
length < 4)
{
return false;
}
CBinaryVarMapReader reader(pData, length);
return LoadValueFromReader(reader, outVariant);
}
bool CBinaryVarMapReader::ReadVarU32_G1(uint32_t &value)
{
byte_t length;
if (SizeLeft() < 1)
{
return false;
}
value = *(m_pCurrent++);
length = value & 0xC0;
if (length == 0xC0)
{
if (SizeLeft() < sizeof(uint32_t))
{
return false;
}
value =
(uint32_t(m_pCurrent[1])) |
(uint32_t(m_pCurrent[2]) << 8) |
(uint32_t(m_pCurrent[3]) << 16) |
(uint32_t(m_pCurrent[4]) << 24);
m_pCurrent += sizeof(uint32_t);
}
else
{
switch (length)
{
case 0x40:
length = 1;
break;
case 0x80:
length = 3;
break;
default:
length = 0;
}
value &= 0x3F;
if (SizeLeft() < length)
{
return false;
}
for (uint8_t shift = 6;
length != 0;
length--, shift += 8)
{
value |= *(m_pCurrent++) << shift;
}
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment