openmohaa/code/fgame/archive.h
smallmodel 2c72908f76
Some checks failed
CodeQL / Analyze (push) Waiting to run
Build branch / build-all (push) Failing after 17s
Use the correct allocator when archiving a con_set object
The default c++ allocator was be used to allocate an array of pointers, but then when destroying the array, Z_Free was called which would throw an error
2025-02-22 23:31:20 +01:00

350 lines
8.4 KiB
C++

/*
===========================================================================
Copyright (C) 2025 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// archive.h: OpenMoHAA Archiver
#pragma once
#include "g_local.h"
#include "class.h"
#include "str.h"
#include "vector.h"
#define ARCHIVE_NULL_POINTER (-654321)
#define ARCHIVE_POINTER_VALID (0)
#define ARCHIVE_POINTER_NULL (ARCHIVE_NULL_POINTER)
#define ARCHIVE_POINTER_SELF_REFERENTIAL (-123456)
#define ARCHIVE_USE_TYPES
typedef enum {
ARCHIVE_NONE,
ARCHIVE_WRITE,
ARCHIVE_READ
} archivemode_e;
enum {
pointer_fixup_ptr,
pointer_fixup_normal,
pointer_fixup_safe
};
typedef struct {
void **ptr;
int index;
int type;
} pointer_fixup_t;
using fileSize_t = uint32_t;
class ArchiveFile
{
protected:
str filename;
size_t length;
byte *buffer;
byte *pos;
size_t bufferlength;
bool writing;
bool opened;
public:
ArchiveFile();
~ArchiveFile();
void Close();
const char *Filename(void);
qboolean Compress();
size_t Length(void);
size_t Pos(void);
size_t Tell(void);
qboolean Seek(size_t newpos);
qboolean OpenRead(const char *name);
qboolean OpenWrite(const char *name);
qboolean Read(void *dest, size_t size);
qboolean Write(const void *source, size_t size);
};
class Archiver
{
private:
Container<LightClass *> classpointerList;
Container<pointer_fixup_t *> fixupList;
protected:
str filename;
qboolean fileerror;
ArchiveFile archivefile;
int archivemode;
int numclassespos;
qboolean harderror;
size_t m_iNumBytesIO;
qboolean silent;
void CheckRead(void);
void CheckType(int type);
int ReadType(void);
fileSize_t ReadSize(void);
void CheckSize(int type, fileSize_t size);
void ArchiveData(int type, void *data, size_t size);
void CheckWrite(void);
void WriteType(int type);
void WriteSize(fileSize_t size);
public:
Archiver();
~Archiver();
void FileError(const char *fmt, ...);
void Close(void);
qboolean Read(str& name, qboolean harderror = qtrue);
qboolean Read(const char *name, qboolean harderror = qtrue);
Class *ReadObject(void);
qboolean Create(str& name, qboolean harderror = qtrue);
qboolean Create(const char *name, qboolean harderror = qtrue);
qboolean Loading(void);
qboolean Saving(void);
qboolean NoErrors(void);
void ArchiveVector(Vector *vec);
void ArchiveQuat(Quat *quat);
void ArchiveInteger(int *num);
void ArchiveUnsigned(unsigned *unum);
void ArchiveSize(long *unum);
void ArchiveByte(byte *num);
void ArchiveChar(char *ch);
void ArchiveShort(short *num);
void ArchiveUnsignedShort(unsigned short *num);
void ArchiveFloat(float *num);
void ArchiveDouble(double *num);
void ArchiveBoolean(qboolean *boolean);
void ArchiveString(str *string);
void ArchiveObjectPointer(LightClass **ptr);
void ArchiveObjectPointer(Class **ptr);
void ArchiveObjectPosition(LightClass *obj);
void ArchiveSafePointer(SafePtrBase *ptr);
void ArchiveEventPointer(Event **ev);
void ArchiveBool(bool *boolean);
void ArchivePosition(int *pos);
void ArchiveSvsTime(int *time);
void ArchiveVec2(vec2_t vec);
void ArchiveVec3(vec3_t vec);
void ArchiveVec4(vec4_t vec);
void ArchiveRaw(void *data, size_t size);
void ArchiveObject(Class *obj);
void ArchiveObject(SafePtrBase *obj); // Added in OPM
qboolean ObjectPositionExists(void *obj);
void Reset();
size_t Counter() const;
void ArchiveConfigString(int cs);
void SetSilent(bool bSilent);
};
template<class Type>
inline void Container<Type>::Archive(Archiver& arc, void (*ArchiveFunc)(Archiver& arc, Type *obj))
{
Type *obj;
int num;
int i;
if (arc.Loading()) {
arc.ArchiveInteger(&num);
Resize(num);
if (num > numobjects) {
numobjects = num;
}
for (i = 0; i < num; i++) {
obj = new (objlist + i) Type();
ArchiveFunc(arc, obj);
}
} else {
num = numobjects;
arc.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
ArchiveFunc(arc, &objlist[i]);
}
}
}
template<>
inline void Container<str>::Archive(Archiver& arc)
{
int i, num;
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveString(AddressOfObjectAt(i));
}
}
template<>
inline void Container<Vector>::Archive(Archiver& arc)
{
int i, num;
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveVector(AddressOfObjectAt(i));
}
}
template<>
inline void Container<int>::Archive(Archiver& arc)
{
int i, num;
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveInteger(AddressOfObjectAt(i));
}
}
template<>
inline void Container<float>::Archive(Archiver& arc)
{
int i, num;
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveFloat(AddressOfObjectAt(i));
}
}
template<typename c>
inline void ArchiveClass(Archiver& arc, c *obj)
{
arc.ArchiveObject(obj);
}
template<typename Type>
void Container<Type>::Archive(Archiver& arc)
{
Archive(arc, ArchiveClass<Type>);
}
#ifndef NO_ARCHIVE
template<typename key, typename value>
void con_set<key, value>::Archive(Archiver& arc)
{
Entry *e = NULL;
int hash;
int i;
arc.ArchiveUnsigned(&tableLength);
arc.ArchiveUnsigned(&threshold);
arc.ArchiveUnsigned(&count);
arc.ArchiveUnsignedShort(&tableLengthIndex);
if (arc.Loading()) {
if (tableLength != 1) {
table = new (NewTable(tableLength)) Entry *[tableLength]();
memset(table, 0, tableLength * sizeof(Entry *));
}
for (i = 0; i < count; i++) {
e = new Entry;
e->Archive(arc);
hash = HashCode<key>(e->GetKey()) % tableLength;
e->next = table[hash];
table[hash] = e;
}
defaultEntry = e;
} else {
# ifndef NDEBUG
int total;
total = 0;
for (i = 0; i < tableLength; i++) {
for (e = table[i]; e != NULL; e = e->next) {
e->Archive(arc);
total++;
}
}
// it must match the number of elements
assert(total == count);
# else
for (i = 0; i < tableLength; i++) {
for (e = table[i]; e != NULL; e = e->next) {
e->Archive(arc);
}
}
# endif
}
}
template<typename key, typename value>
void con_map<key, value>::Archive(Archiver& arc)
{
m_con_set.Archive(arc);
}
#endif
#define ArchiveEnum(thing, type) \
{ \
int tempInt; \
\
tempInt = (int)(thing); \
arc.ArchiveInteger(&tempInt); \
(thing) = (type)tempInt; \
}