First pass idLib conversion from hex rays4.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
template<typename type>
|
||||
class idAutoPtr {
|
||||
public:
|
||||
explicit idAutoPtr(type* pointer = nullptr)
|
||||
: Pointee(pointer) {
|
||||
}
|
||||
|
||||
~idAutoPtr() {
|
||||
delete Pointee;
|
||||
}
|
||||
|
||||
idAutoPtr(idAutoPtr&& other) noexcept
|
||||
: Pointee(other.Release()) {
|
||||
}
|
||||
|
||||
idAutoPtr& operator=(idAutoPtr&& other) noexcept {
|
||||
if (this != &other) {
|
||||
Reset(other.Release());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
idAutoPtr(const idAutoPtr&) = delete;
|
||||
idAutoPtr& operator=(const idAutoPtr&) = delete;
|
||||
|
||||
type* Get() const { return Pointee; }
|
||||
type* operator->() const { return Pointee; }
|
||||
type& operator*() const { return *Pointee; }
|
||||
explicit operator bool() const { return Pointee != nullptr; }
|
||||
|
||||
type* Release() {
|
||||
type* const result = Pointee;
|
||||
Pointee = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Reset(type* pointer = nullptr) {
|
||||
if (Pointee != pointer) {
|
||||
delete Pointee;
|
||||
Pointee = pointer;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
type* Pointee;
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
class idAutoPtr_Array {
|
||||
public:
|
||||
explicit idAutoPtr_Array(type* pointer = nullptr)
|
||||
: Pointee(pointer) {
|
||||
}
|
||||
|
||||
virtual ~idAutoPtr_Array() {
|
||||
std::free(Pointee);
|
||||
}
|
||||
|
||||
idAutoPtr_Array(const idAutoPtr_Array&) = delete;
|
||||
idAutoPtr_Array& operator=(const idAutoPtr_Array&) = delete;
|
||||
|
||||
type* Get() const { return Pointee; }
|
||||
type& operator[](const int index) const { return Pointee[index]; }
|
||||
|
||||
type* Release() {
|
||||
type* const result = Pointee;
|
||||
Pointee = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
type* Pointee;
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idAutoPtr<int>) == 4, "Recovered idAutoPtr ABI changed");
|
||||
static_assert(sizeof(idAutoPtr_Array<int>) == 8,
|
||||
"Recovered idAutoPtr_Array ABI changed");
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "binaryheap.h"
|
||||
|
||||
// The recovered BinaryHeap.cpp contains only the testBinaryHeap console
|
||||
// command. The reusable implementation was inline in BinaryHeap.h; its PC
|
||||
// regression coverage lives in source/tests/idlib_containers_test.cpp.
|
||||
@@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
template<typename nodeType, typename priorityType, priorityType LOWEST_VALUE>
|
||||
class idBinaryHeap {
|
||||
public:
|
||||
struct idHeapNode {
|
||||
nodeType node;
|
||||
priorityType priority;
|
||||
};
|
||||
|
||||
explicit idBinaryHeap(const int initialSize_ = 16)
|
||||
: nodes(nullptr), curSize(0), initialSize(std::max(1, initialSize_)),
|
||||
numNodes(0), ordered(true), externalBuffer(false) {
|
||||
Allocate(initialSize);
|
||||
}
|
||||
|
||||
idBinaryHeap(idHeapNode* const buffer, const int bufferSize)
|
||||
: nodes(buffer), curSize(std::max(0, bufferSize - 1)),
|
||||
initialSize(std::max(0, bufferSize - 1)), numNodes(0),
|
||||
ordered(true), externalBuffer(true) {
|
||||
if (nodes != nullptr && bufferSize > 0) {
|
||||
nodes[0].priority = LOWEST_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
~idBinaryHeap() {
|
||||
if (!externalBuffer) {
|
||||
std::free(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
idBinaryHeap(const idBinaryHeap&) = delete;
|
||||
idBinaryHeap& operator=(const idBinaryHeap&) = delete;
|
||||
|
||||
bool Insert(const nodeType& node, const priorityType& priority) {
|
||||
if (!ordered) {
|
||||
return InsertUnsorted(node, priority);
|
||||
}
|
||||
if (!EnsureCapacity()) {
|
||||
return false;
|
||||
}
|
||||
int hole = ++numNodes;
|
||||
while (hole > 1 && priority < nodes[hole / 2].priority) {
|
||||
nodes[hole] = nodes[hole / 2];
|
||||
hole /= 2;
|
||||
}
|
||||
nodes[hole].node = node;
|
||||
nodes[hole].priority = priority;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InsertUnsorted(const nodeType& node, const priorityType& priority) {
|
||||
if (!EnsureCapacity()) {
|
||||
return false;
|
||||
}
|
||||
++numNodes;
|
||||
nodes[numNodes].node = node;
|
||||
nodes[numNodes].priority = priority;
|
||||
if (numNodes > 1 && priority < nodes[numNodes / 2].priority) {
|
||||
ordered = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nodeType GetMin() {
|
||||
SortHeap();
|
||||
return numNodes == 0 ? nodeType() : nodes[1].node;
|
||||
}
|
||||
|
||||
priorityType GetMinPriority() {
|
||||
SortHeap();
|
||||
return numNodes == 0 ? LOWEST_VALUE : nodes[1].priority;
|
||||
}
|
||||
|
||||
nodeType RemoveMin() {
|
||||
SortHeap();
|
||||
if (numNodes == 0) {
|
||||
return nodeType();
|
||||
}
|
||||
const nodeType result = nodes[1].node;
|
||||
nodes[1] = nodes[numNodes--];
|
||||
if (numNodes > 0) {
|
||||
PercolateDown(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SortHeap() {
|
||||
if (ordered || numNodes < 2) {
|
||||
ordered = true;
|
||||
return;
|
||||
}
|
||||
for (int index = numNodes / 2; index > 0; --index) {
|
||||
PercolateDown(index);
|
||||
}
|
||||
ordered = true;
|
||||
}
|
||||
|
||||
void MakeEmpty() {
|
||||
if (!externalBuffer && curSize != initialSize) {
|
||||
std::free(nodes);
|
||||
nodes = nullptr;
|
||||
curSize = 0;
|
||||
Allocate(initialSize);
|
||||
}
|
||||
numNodes = 0;
|
||||
ordered = true;
|
||||
if (nodes != nullptr) {
|
||||
nodes[0].priority = LOWEST_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
int Num() const { return numNodes; }
|
||||
bool IsEmpty() const { return numNodes == 0; }
|
||||
|
||||
private:
|
||||
idHeapNode* nodes;
|
||||
int curSize;
|
||||
int initialSize;
|
||||
int numNodes;
|
||||
bool ordered;
|
||||
bool externalBuffer;
|
||||
|
||||
bool Allocate(const int size) {
|
||||
idHeapNode* const storage = static_cast<idHeapNode*>(
|
||||
std::malloc(sizeof(idHeapNode) * static_cast<std::size_t>(size + 1))
|
||||
);
|
||||
if (storage == nullptr) {
|
||||
return false;
|
||||
}
|
||||
nodes = storage;
|
||||
curSize = size;
|
||||
nodes[0].priority = LOWEST_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resize(const int newSize) {
|
||||
if (externalBuffer || newSize <= curSize) {
|
||||
return false;
|
||||
}
|
||||
idHeapNode* const replacement = static_cast<idHeapNode*>(
|
||||
std::malloc(sizeof(idHeapNode) * static_cast<std::size_t>(newSize + 1))
|
||||
);
|
||||
if (replacement == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::memcpy(replacement, nodes,
|
||||
sizeof(idHeapNode) * static_cast<std::size_t>(numNodes + 1));
|
||||
std::free(nodes);
|
||||
nodes = replacement;
|
||||
curSize = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EnsureCapacity() {
|
||||
if (numNodes < curSize) {
|
||||
return true;
|
||||
}
|
||||
return Resize(std::max(1, curSize * 2));
|
||||
}
|
||||
|
||||
void PercolateDown(int hole) {
|
||||
const idHeapNode value = nodes[hole];
|
||||
while (hole * 2 <= numNodes) {
|
||||
int child = hole * 2;
|
||||
if (child != numNodes
|
||||
&& nodes[child + 1].priority < nodes[child].priority) {
|
||||
++child;
|
||||
}
|
||||
if (!(nodes[child].priority < value.priority)) {
|
||||
break;
|
||||
}
|
||||
nodes[hole] = nodes[child];
|
||||
hole = child;
|
||||
}
|
||||
nodes[hole] = value;
|
||||
}
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idBinaryHeap<int, int, (-2147483647 - 1)>) == 20,
|
||||
"Recovered idBinaryHeap ABI changed");
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
// Recovered from shared/idlib/containers/BitArray.h. The field order is
|
||||
// intentionally kept identical to the 32-bit tungsten type.
|
||||
class idBitArray {
|
||||
public:
|
||||
explicit idBitArray(const std::int16_t tag = 0)
|
||||
: buffer(nullptr), bits(0), memTag(tag), ownsBuffer(false) {
|
||||
}
|
||||
|
||||
idBitArray(unsigned char* storage, const unsigned int numBits,
|
||||
const std::int16_t tag = 0)
|
||||
: buffer(storage), bits(numBits), memTag(tag), ownsBuffer(false) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
~idBitArray() {
|
||||
Free();
|
||||
}
|
||||
|
||||
idBitArray(const idBitArray&) = delete;
|
||||
idBitArray& operator=(const idBitArray&) = delete;
|
||||
|
||||
bool Alloc(const unsigned int numBits) {
|
||||
Free();
|
||||
bits = numBits;
|
||||
ownsBuffer = true;
|
||||
const std::size_t bytes = ByteCount();
|
||||
if (bytes == 0) {
|
||||
return true;
|
||||
}
|
||||
buffer = static_cast<unsigned char*>(std::calloc(bytes, 1));
|
||||
if (buffer == nullptr) {
|
||||
bits = 0;
|
||||
ownsBuffer = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
if (buffer != nullptr) {
|
||||
std::memset(buffer, 0, ByteCount());
|
||||
}
|
||||
}
|
||||
|
||||
void Set(const unsigned int bitNum) {
|
||||
if (bitNum < bits && buffer != nullptr) {
|
||||
buffer[bitNum >> 3] |= static_cast<unsigned char>(1u << (bitNum & 7));
|
||||
}
|
||||
}
|
||||
|
||||
void Clear(const unsigned int bitNum) {
|
||||
if (bitNum < bits && buffer != nullptr) {
|
||||
buffer[bitNum >> 3] &= static_cast<unsigned char>(~(1u << (bitNum & 7)));
|
||||
}
|
||||
}
|
||||
|
||||
void Set(const unsigned int bitNum, const bool value) {
|
||||
if (value) {
|
||||
Set(bitNum);
|
||||
} else {
|
||||
Clear(bitNum);
|
||||
}
|
||||
}
|
||||
|
||||
bool Get(const unsigned int bitNum) const {
|
||||
return bitNum < bits && buffer != nullptr
|
||||
&& (buffer[bitNum >> 3] & (1u << (bitNum & 7))) != 0;
|
||||
}
|
||||
|
||||
unsigned int Num() const {
|
||||
return bits;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char* buffer;
|
||||
unsigned int bits;
|
||||
std::int16_t memTag;
|
||||
bool ownsBuffer;
|
||||
|
||||
std::size_t ByteCount() const {
|
||||
return static_cast<std::size_t>((bits + 7u) >> 3);
|
||||
}
|
||||
|
||||
void Free() {
|
||||
if (buffer != nullptr && ownsBuffer) {
|
||||
std::free(buffer);
|
||||
}
|
||||
buffer = nullptr;
|
||||
bits = 0;
|
||||
ownsBuffer = false;
|
||||
}
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idBitArray) == 12, "Recovered idBitArray ABI changed");
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
// Tungsten's containers/BTree.cpp contains only the testBinaryTree console
|
||||
// command. The reusable idBTree implementation is header-only and is supplied
|
||||
// by the compiled Doom 3 BFG idlib/containers/BTree.h baseline.
|
||||
@@ -0,0 +1,4 @@
|
||||
// Tungsten's containers/List.cpp contains diagnostic console commands for the
|
||||
// header-only idList and idArray implementations. The PC runtime templates are
|
||||
// supplied by the compiled Doom 3 BFG idlib/containers/List.h baseline; the
|
||||
// recovery suite exercises container behavior without registering engine CVars.
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
template<class T>
|
||||
class idRecoveredList {
|
||||
public:
|
||||
explicit idRecoveredList(const int initialGranularity = 16)
|
||||
: list(nullptr), num(0), size(0),
|
||||
granularity(static_cast<std::int16_t>(initialGranularity)),
|
||||
memTag(0), listStatic(0) {
|
||||
}
|
||||
|
||||
~idRecoveredList() {
|
||||
Clear(true);
|
||||
}
|
||||
|
||||
idRecoveredList(const idRecoveredList&) = delete;
|
||||
idRecoveredList& operator=(const idRecoveredList&) = delete;
|
||||
|
||||
bool Reserve(const int capacity) {
|
||||
if (capacity <= size) return true;
|
||||
const int step = granularity > 0 ? granularity : 16;
|
||||
const int newSize = ((capacity + step - 1) / step) * step;
|
||||
T* const replacement = static_cast<T*>(
|
||||
std::malloc(sizeof(T) * static_cast<std::size_t>(newSize)));
|
||||
if (replacement == nullptr) return false;
|
||||
if (list != nullptr && num > 0) {
|
||||
std::memcpy(replacement, list,
|
||||
sizeof(T) * static_cast<std::size_t>(num));
|
||||
}
|
||||
std::free(list);
|
||||
list = replacement;
|
||||
size = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
T* Alloc() {
|
||||
if (!Reserve(num + 1)) return nullptr;
|
||||
T* const result = list + num++;
|
||||
std::memset(result, 0, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Append(const T& value) {
|
||||
T* const destination = Alloc();
|
||||
if (destination == nullptr) return false;
|
||||
*destination = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Clear(const bool freeMemory = false) {
|
||||
num = 0;
|
||||
if (freeMemory) {
|
||||
std::free(list);
|
||||
list = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Num() const { return num; }
|
||||
int Capacity() const { return size; }
|
||||
T* Ptr() { return list; }
|
||||
const T* Ptr() const { return list; }
|
||||
T& operator[](const int index) { return list[index]; }
|
||||
const T& operator[](const int index) const { return list[index]; }
|
||||
|
||||
private:
|
||||
T* list;
|
||||
int num;
|
||||
int size;
|
||||
std::int16_t granularity;
|
||||
std::uint8_t memTag;
|
||||
std::uint8_t listStatic;
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idRecoveredList<int>) == 16,
|
||||
"Recovered list ABI changed");
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
template<typename type>
|
||||
class idSearch {
|
||||
public:
|
||||
virtual ~idSearch() = default;
|
||||
virtual int Search(const type* base, unsigned int num,
|
||||
const type& value) const = 0;
|
||||
virtual int Search_FirstGreater(const type* base, int num,
|
||||
const type& value) const = 0;
|
||||
virtual int Search_FirstGreaterEqual(const type* base, int num,
|
||||
const type& value) const = 0;
|
||||
virtual int Search_LastLess(const type* base, int num,
|
||||
const type& value) const = 0;
|
||||
virtual int Search_LastLessEqual(const type* base, int num,
|
||||
const type& value) const = 0;
|
||||
};
|
||||
|
||||
template<typename type, typename derived>
|
||||
class idSearch_Binary : public idSearch<type> {
|
||||
public:
|
||||
int Search(const type* base, const unsigned int num,
|
||||
const type& value) const override {
|
||||
if (base == nullptr || num == 0) {
|
||||
return -1;
|
||||
}
|
||||
const int index = Search_LastLessEqual(base, static_cast<int>(num), value);
|
||||
return Compare(base[index], value) == 0 ? index : -1;
|
||||
}
|
||||
|
||||
int Search_FirstGreater(const type* base, const int num,
|
||||
const type& value) const override {
|
||||
int first = 0;
|
||||
int count = num < 0 ? 0 : num;
|
||||
while (count > 0) {
|
||||
const int step = count / 2;
|
||||
const int middle = first + step;
|
||||
if (Compare(base[middle], value) <= 0) {
|
||||
first = middle + 1;
|
||||
count -= step + 1;
|
||||
} else {
|
||||
count = step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
int Search_FirstGreaterEqual(const type* base, const int num,
|
||||
const type& value) const override {
|
||||
int first = 0;
|
||||
int count = num < 0 ? 0 : num;
|
||||
while (count > 0) {
|
||||
const int step = count / 2;
|
||||
const int middle = first + step;
|
||||
if (Compare(base[middle], value) < 0) {
|
||||
first = middle + 1;
|
||||
count -= step + 1;
|
||||
} else {
|
||||
count = step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
int Search_LastLess(const type* base, const int num,
|
||||
const type& value) const override {
|
||||
const int result = Search_FirstGreaterEqual(base, num, value) - 1;
|
||||
return result < 0 ? 0 : result;
|
||||
}
|
||||
|
||||
int Search_LastLessEqual(const type* base, const int num,
|
||||
const type& value) const override {
|
||||
const int result = Search_FirstGreater(base, num, value) - 1;
|
||||
return result < 0 ? 0 : result;
|
||||
}
|
||||
|
||||
private:
|
||||
int Compare(const type& left, const type& right) const {
|
||||
return static_cast<const derived*>(this)->Compare(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
class idSearch_BinaryDefault
|
||||
: public idSearch_Binary<type, idSearch_BinaryDefault<type>> {
|
||||
public:
|
||||
int Compare(const type& left, const type& right) const {
|
||||
if (left < right) {
|
||||
return -1;
|
||||
}
|
||||
if (right < left) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
using idSearch_DefaultCompare = idSearch_BinaryDefault<type>;
|
||||
Reference in New Issue
Block a user