2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
2024-09-27 20:19:11 +02:00
|
|
|
Copyright (C) 2024 the OpenMoHAA team
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2024-09-27 20:19:11 +02:00
|
|
|
#pragma once
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-04-29 21:56:38 +02:00
|
|
|
#include "g_local.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
#include "class.h"
|
|
|
|
#include "str.h"
|
2023-04-29 21:56:38 +02:00
|
|
|
#include "vector.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
#define ARCHIVE_NULL_POINTER (-654321)
|
|
|
|
#define ARCHIVE_POINTER_VALID (0)
|
|
|
|
#define ARCHIVE_POINTER_NULL (ARCHIVE_NULL_POINTER)
|
|
|
|
#define ARCHIVE_POINTER_SELF_REFERENTIAL (-123456)
|
2016-03-27 11:49:47 +02:00
|
|
|
#define ARCHIVE_USE_TYPES
|
|
|
|
|
2023-09-14 00:19:55 +02:00
|
|
|
typedef enum {
|
|
|
|
ARCHIVE_NONE,
|
|
|
|
ARCHIVE_WRITE,
|
|
|
|
ARCHIVE_READ
|
|
|
|
} archivemode_e;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
enum {
|
2023-09-14 00:19:55 +02:00
|
|
|
pointer_fixup_ptr,
|
2023-09-13 19:46:39 +02:00
|
|
|
pointer_fixup_normal,
|
|
|
|
pointer_fixup_safe
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
typedef struct {
|
|
|
|
void **ptr;
|
|
|
|
int index;
|
|
|
|
int type;
|
2016-03-27 11:49:47 +02:00
|
|
|
} pointer_fixup_t;
|
|
|
|
|
2023-01-30 16:26:38 +01:00
|
|
|
using fileSize_t = uint32_t;
|
|
|
|
|
2023-09-14 00:19:55 +02:00
|
|
|
class ArchiveFile
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
protected:
|
2023-09-13 19:46:39 +02:00
|
|
|
str filename;
|
|
|
|
size_t length;
|
|
|
|
byte *buffer;
|
|
|
|
byte *pos;
|
2023-09-14 00:19:55 +02:00
|
|
|
size_t bufferlength;
|
|
|
|
bool writing;
|
|
|
|
bool opened;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
public:
|
2023-09-14 00:19:55 +02:00
|
|
|
ArchiveFile();
|
|
|
|
~ArchiveFile();
|
|
|
|
void Close();
|
2023-09-13 19:46:39 +02:00
|
|
|
const char *Filename(void);
|
2023-09-14 00:19:55 +02:00
|
|
|
qboolean Compress();
|
2023-09-13 19:46:39 +02:00
|
|
|
size_t Length(void);
|
|
|
|
size_t Pos(void);
|
2023-09-14 00:19:55 +02:00
|
|
|
size_t Tell(void);
|
2023-09-13 19:46:39 +02:00
|
|
|
qboolean Seek(size_t newpos);
|
2023-09-14 00:19:55 +02:00
|
|
|
qboolean OpenRead(const char *name);
|
|
|
|
qboolean OpenWrite(const char *name);
|
2023-09-13 19:46:39 +02:00
|
|
|
qboolean Read(void *dest, size_t size);
|
2023-09-14 00:19:55 +02:00
|
|
|
qboolean Write(const void *source, size_t size);
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2023-09-14 00:19:55 +02:00
|
|
|
class Archiver
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
private:
|
2023-09-14 00:19:55 +02:00
|
|
|
Container<LightClass *> classpointerList;
|
2023-09-13 19:46:39 +02:00
|
|
|
Container<pointer_fixup_t *> fixupList;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
protected:
|
2023-09-14 00:19:55 +02:00
|
|
|
str filename;
|
|
|
|
qboolean fileerror;
|
|
|
|
ArchiveFile archivefile;
|
|
|
|
int archivemode;
|
|
|
|
int numclassespos;
|
|
|
|
qboolean harderror;
|
|
|
|
size_t m_iNumBytesIO;
|
|
|
|
qboolean silent;
|
2023-09-13 19:46:39 +02:00
|
|
|
|
|
|
|
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);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
public:
|
2023-09-13 19:46:39 +02:00
|
|
|
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);
|
2023-09-14 00:19:55 +02:00
|
|
|
void ArchiveObjectPointer(LightClass **ptr);
|
2023-09-13 19:46:39 +02:00
|
|
|
void ArchiveObjectPointer(Class **ptr);
|
2023-09-14 00:19:55 +02:00
|
|
|
void ArchiveObjectPosition(LightClass *obj);
|
2023-09-13 19:46:39 +02:00
|
|
|
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);
|
2024-03-04 23:34:31 +01:00
|
|
|
void ArchiveObject(SafePtrBase* obj); // Added in OPM
|
2023-09-13 19:46:39 +02:00
|
|
|
|
|
|
|
qboolean ObjectPositionExists(void *obj);
|
|
|
|
|
2023-09-14 00:19:55 +02:00
|
|
|
void Reset();
|
|
|
|
size_t Counter() const;
|
|
|
|
|
|
|
|
void ArchiveConfigString(int cs);
|
2023-09-13 19:46:39 +02:00
|
|
|
void SetSilent(bool bSilent);
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
template<class Type>
|
|
|
|
inline void Container<Type>::Archive(Archiver& arc, void (*ArchiveFunc)(Archiver& arc, Type *obj))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
int num;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (arc.Loading()) {
|
|
|
|
arc.ArchiveInteger(&num);
|
|
|
|
Resize(num);
|
|
|
|
} else {
|
|
|
|
num = numobjects;
|
|
|
|
arc.ArchiveInteger(&num);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 1; i <= num; i++) {
|
|
|
|
if (num > numobjects) {
|
|
|
|
numobjects = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArchiveFunc(arc, &objlist[i - 1]);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2023-09-13 19:46:39 +02:00
|
|
|
inline void Container<str>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
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));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2023-09-13 19:46:39 +02:00
|
|
|
inline void Container<Vector>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
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));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2023-09-13 19:46:39 +02:00
|
|
|
inline void Container<int>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
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));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2023-09-13 19:46:39 +02:00
|
|
|
inline void Container<float>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
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));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
template<typename c>
|
|
|
|
inline void ArchiveClass(Archiver& arc, c *obj)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
arc.ArchiveObject(obj);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 20:45:49 +02:00
|
|
|
template<typename Type>
|
|
|
|
void Container<Type>::Archive(Archiver& arc)
|
|
|
|
{
|
|
|
|
Archive(arc, ArchiveClass<Type>);
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
#ifndef NO_ARCHIVE
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
template<typename key, typename value>
|
|
|
|
void con_set<key, value>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-28 20:10:23 +01:00
|
|
|
Entry *e = NULL;
|
2023-09-13 19:46:39 +02:00
|
|
|
int hash;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
arc.ArchiveUnsigned(&tableLength);
|
|
|
|
arc.ArchiveUnsigned(&threshold);
|
|
|
|
arc.ArchiveUnsigned(&count);
|
|
|
|
arc.ArchiveUnsignedShort(&tableLengthIndex);
|
|
|
|
|
|
|
|
if (arc.Loading()) {
|
|
|
|
if (tableLength != 1) {
|
|
|
|
table = new Entry *[tableLength]();
|
|
|
|
memset(table, 0, tableLength * sizeof(Entry *));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
e = new Entry;
|
|
|
|
e->Archive(arc);
|
|
|
|
|
2023-11-28 19:28:19 +01:00
|
|
|
hash = HashCode<key>(e->GetKey()) % tableLength;
|
2023-09-13 19:46:39 +02:00
|
|
|
|
|
|
|
e->next = table[hash];
|
|
|
|
table[hash] = e;
|
|
|
|
}
|
2023-11-28 20:10:23 +01:00
|
|
|
|
|
|
|
defaultEntry = e;
|
2023-09-13 19:46:39 +02:00
|
|
|
} else {
|
2023-11-28 19:28:19 +01:00
|
|
|
#ifndef NDEBUG
|
|
|
|
int total;
|
|
|
|
|
2023-11-26 20:31:58 +01:00
|
|
|
total = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < tableLength; i++) {
|
2023-09-13 19:46:39 +02:00
|
|
|
for (e = table[i]; e != NULL; e = e->next) {
|
|
|
|
e->Archive(arc);
|
2023-11-26 20:31:58 +01:00
|
|
|
total++;
|
2023-09-13 19:46:39 +02:00
|
|
|
}
|
|
|
|
}
|
2023-11-28 19:28:19 +01:00
|
|
|
// it must match the number of elements
|
2023-11-26 20:31:58 +01:00
|
|
|
assert(total == count);
|
2023-11-28 19:28:19 +01:00
|
|
|
#else
|
|
|
|
for (i = 0; i < tableLength; i++) {
|
|
|
|
for (e = table[i]; e != NULL; e = e->next) {
|
|
|
|
e->Archive(arc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2023-09-13 19:46:39 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
template<typename key, typename value>
|
|
|
|
void con_map<key, value>::Archive(Archiver& arc)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-13 19:46:39 +02:00
|
|
|
m_con_set.Archive(arc);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2023-09-13 19:46:39 +02:00
|
|
|
#define ArchiveEnum(thing, type) \
|
|
|
|
{ \
|
|
|
|
int tempInt; \
|
|
|
|
\
|
|
|
|
tempInt = (int)(thing); \
|
|
|
|
arc.ArchiveInteger(&tempInt); \
|
|
|
|
(thing) = (type)tempInt; \
|
|
|
|
}
|