/
redgpu
/
tech5
Обзор
Документация
Войти
/
redgpu
/
tech5
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
source/shared/idlib/varargs.h
276 строк
10 KB
Justin Marshall
First pass idLib conversion from hex rays4.
08 авг 2026, 23:54
08 авг 2026, 23:54
09a4cb9
Код
Авторство
О чём код?
#pragma once #include "idlib/math/vector.h" #include "idlib/text/str.h" #include <algorithm> #include <cstdint> #include <cstring> #include <limits> #include <malloc.h> enum argTypes_t { ARG_BOOL = 1, ARG_CHAR = 2, ARG_INTEGER = 3, ARG_FLOAT = 4, ARG_VECTOR = 5, ARG_QUAT = 6, ARG_ANGLES = 7, ARG_STRING = 8, ARG_DECL = 9, ARG_ENTITY = 10, ARG_CLASS = 11, ARG_VECTOR4 = 12, ARG_ANIMALIAS = 13, ARG_SPAWNID = 14, ARG_TYPES_MAX = 15 }; // Compact heterogeneous argument storage recovered from animation, voice and // FSM call sites. MAX_ARGS is part of the object ABI (2, 4 and 6 occur). template<int MAX_ARGS> class idVarArgs { public: idVarArgs() : numArgs(0), argSize(0), buffSize(0), args(nullptr) { std::memset(argOffsets, 0, sizeof(argOffsets)); std::memset(argTypes, 0, sizeof(argTypes)); std::memset(argExTypes, 0, sizeof(argExTypes)); } idVarArgs(const idVarArgs& other) : idVarArgs() { Copy(other); } idVarArgs(idVarArgs&& other) noexcept : numArgs(other.numArgs), argSize(other.argSize), buffSize(other.buffSize), args(other.args) { std::memcpy(argOffsets, other.argOffsets, sizeof(argOffsets)); std::memcpy(argTypes, other.argTypes, sizeof(argTypes)); std::memcpy(argExTypes, other.argExTypes, sizeof(argExTypes)); other.ResetWithoutFree(); } ~idVarArgs() { Free(); } idVarArgs& operator=(const idVarArgs& other) { Copy(other); return *this; } idVarArgs& operator=(idVarArgs&& other) noexcept { if (this != &other) { Free(); numArgs = other.numArgs; argSize = other.argSize; buffSize = other.buffSize; args = other.args; std::memcpy(argOffsets, other.argOffsets, sizeof(argOffsets)); std::memcpy(argTypes, other.argTypes, sizeof(argTypes)); std::memcpy(argExTypes, other.argExTypes, sizeof(argExTypes)); other.ResetWithoutFree(); } return *this; } void ClearArgs() { Free(); std::memset(argOffsets, 0, sizeof(argOffsets)); std::memset(argTypes, 0, sizeof(argTypes)); std::memset(argExTypes, 0, sizeof(argExTypes)); } int NumArgs() const { return numArgs; } int GetArgSize() const { return argSize; } int GetArgType(const int index) const { return IsValidIndex(index) ? argTypes[index] : 0; } int GetArgExType(const int index) const { return IsValidIndex(index) ? argExTypes[index] : 0; } void AddArg(const bool value, const std::uint8_t exType = 0) { const std::uint8_t stored = value ? 1 : 0; AddRaw(ARG_BOOL, exType, &stored, sizeof(stored)); } void AddArg(const char value, const std::uint8_t exType = 0) { AddRaw(ARG_CHAR, exType, &value, sizeof(value)); } void AddArg(const int value, const std::uint8_t exType = 0) { AddRaw(ARG_INTEGER, exType, &value, sizeof(value)); } void AddArg(const float value, const std::uint8_t exType = 0) { AddRaw(ARG_FLOAT, exType, &value, sizeof(value)); } void AddArg(const idVec3& value, const std::uint8_t exType = 0) { AddRaw(ARG_VECTOR, exType, &value, 12); } void AddArg(const idQuat& value, const std::uint8_t exType = 0) { AddRaw(ARG_QUAT, exType, &value, 16); } void AddArg(const idAngles& value, const std::uint8_t exType = 0) { AddRaw(ARG_ANGLES, exType, &value, 12); } void AddArg(const idVec4& value, const std::uint8_t exType = 0) { AddRaw(ARG_VECTOR4, exType, &value, 16); } void AddArg(const char* value, const std::uint8_t exType = 0) { const char* const text = value == nullptr ? "" : value; AddRaw(ARG_STRING, exType, text, static_cast<unsigned int>(std::strlen(text) + 1)); } void AddHandleArg(const int value, const std::uint8_t type, const std::uint8_t exType = 0) { AddRaw(type, exType, &value, sizeof(value)); } bool GetArg(const int index, bool& value) const { std::uint8_t stored = 0; if (!GetRaw(index, ARG_BOOL, &stored, sizeof(stored))) return false; value = stored != 0; return true; } bool GetArg(const int index, char& value) const { return GetRaw(index, ARG_CHAR, &value, sizeof(value)); } bool GetArg(const int index, int& value) const { return GetRaw(index, ARG_INTEGER, &value, sizeof(value)); } bool GetArg(const int index, float& value) const { return GetRaw(index, ARG_FLOAT, &value, sizeof(value)); } bool GetArg(const int index, idVec3& value) const { return GetRaw(index, ARG_VECTOR, &value, 12); } bool GetArg(const int index, idQuat& value) const { return GetRaw(index, ARG_QUAT, &value, 16); } bool GetArg(const int index, idAngles& value) const { return GetRaw(index, ARG_ANGLES, &value, 12); } bool GetArg(const int index, idVec4& value) const { return GetRaw(index, ARG_VECTOR4, &value, 16); } bool GetArg(const int index, idStr& value) const { const char* text = nullptr; if (!GetArg(index, text)) return false; value = text; return true; } bool GetArg(const int index, const char*& value) const { if (!IsValidIndex(index) || argTypes[index] != ARG_STRING) return false; value = reinterpret_cast<const char*>(args + argOffsets[index]); return true; } bool GetArg(const int index, void*& value) const { if (!IsValidIndex(index) || (argTypes[index] != ARG_DECL && argTypes[index] != ARG_ENTITY && argTypes[index] != ARG_CLASS)) { return false; } std::memcpy(&value, args + argOffsets[index], sizeof(value)); return true; } bool GetHandleArg(const int index, int& value, const std::uint8_t type) const { return GetRaw(index, type, &value, sizeof(value)); } bool Equal(const idVarArgs& other) const { return numArgs == other.numArgs && argSize == other.argSize && std::memcmp(argOffsets, other.argOffsets, sizeof(argOffsets)) == 0 && std::memcmp(argTypes, other.argTypes, sizeof(argTypes)) == 0 && std::memcmp(argExTypes, other.argExTypes, sizeof(argExTypes)) == 0 && (argSize == 0 || std::memcmp(args, other.args, argSize) == 0); } bool operator==(const idVarArgs& other) const { return Equal(other); } bool operator!=(const idVarArgs& other) const { return !Equal(other); } private: bool IsValidIndex(const int index) const { return index >= 0 && index < numArgs; } bool Grow(const unsigned int amount) { if (amount == 0) return true; const unsigned int needed = static_cast<unsigned int>(argSize) + amount; if (needed > std::numeric_limits<std::uint16_t>::max()) return false; if (needed <= buffSize) return true; unsigned int newSize = std::max(needed, static_cast<unsigned int>(buffSize) * 2u); unsigned char* const replacement = static_cast<unsigned char*>( _aligned_malloc(newSize, 16)); if (replacement == nullptr) return false; if (args != nullptr && argSize > 0) { std::memcpy(replacement, args, argSize); } _aligned_free(args); args = replacement; buffSize = static_cast<std::uint16_t>(newSize); return true; } bool AddRaw(const std::uint8_t type, const std::uint8_t exType, const void* source, const unsigned int bytes) { if (numArgs >= MAX_ARGS || source == nullptr || !Grow(bytes)) return false; argTypes[numArgs] = type; argExTypes[numArgs] = exType; argOffsets[numArgs] = argSize; std::memcpy(args + argSize, source, bytes); argSize = static_cast<std::uint16_t>(argSize + bytes); ++numArgs; return true; } bool GetRaw(const int index, const std::uint8_t type, void* destination, const unsigned int bytes) const { if (!IsValidIndex(index) || argTypes[index] != type || destination == nullptr || static_cast<unsigned int>(argOffsets[index]) + bytes > argSize) { return false; } std::memcpy(destination, args + argOffsets[index], bytes); return true; } void Copy(const idVarArgs& other) { if (this == &other) return; ClearArgs(); if (other.buffSize > 0 && !Grow(other.buffSize)) return; numArgs = other.numArgs; argSize = other.argSize; std::memcpy(argOffsets, other.argOffsets, sizeof(argOffsets)); std::memcpy(argTypes, other.argTypes, sizeof(argTypes)); std::memcpy(argExTypes, other.argExTypes, sizeof(argExTypes)); if (argSize > 0) std::memcpy(args, other.args, argSize); } void Free() { _aligned_free(args); ResetWithoutFree(); } void ResetWithoutFree() { numArgs = 0; argSize = 0; buffSize = 0; args = nullptr; } std::uint16_t numArgs; std::uint16_t argSize; std::uint16_t buffSize; std::uint16_t argOffsets[MAX_ARGS]; std::uint8_t argTypes[MAX_ARGS]; std::uint8_t argExTypes[MAX_ARGS]; unsigned char* args; }; #if INTPTR_MAX == INT32_MAX static_assert(sizeof(idVarArgs<2>) == 20, "Recovered idVarArgs<2> ABI changed"); static_assert(sizeof(idVarArgs<4>) == 28, "Recovered idVarArgs<4> ABI changed"); static_assert(sizeof(idVarArgs<6>) == 36, "Recovered idVarArgs<6> ABI changed"); #endif