summaryrefslogtreecommitdiffstats
path: root/src/cc4group.h
blob: a63d9955de0b1e8e26567388a2d56bcb4b9a9f39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once

#ifdef __cplusplus
extern "C" {
#define this this_
#define new new_
#define delete delete_
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

typedef struct {
	const char* fileName;
	int32_t modified;
	const char* author;
	size_t size;
	size_t totalSize;
	bool executable;
	bool directory;
	bool official;
} CC4Group_EntryInfo;

typedef struct CC4Group_t CC4Group;

typedef void(*CC4Group_CleanupFunc)(void* data);
typedef struct {
	CC4Group_CleanupFunc func;
	void* data;
} CC4Group_CleanupJob;
typedef void* (*CC4Group_TmpMemoryStrategy)(CC4Group* const this, const size_t size, CC4Group_CleanupJob* cleanupJob);

// the callback has to store a pointer to the newly read data in data, as well as the amount of read data in size
// the callback must return true if the end of data is reached or any read error happens and false otherwise
// the pointer passed in will be handled as specified with the corresponding MemoryManagement
typedef bool (*CC4Group_ReadCallback)(const uint8_t** const data, size_t* const size, void* const arg);

typedef struct {
	CC4Group* (*new)(void);
	bool (*create)(CC4Group* const this);
	void (*delete)(CC4Group* const this);

	// opens a group on the filesystem; path may point to a directory inside a group
	// only open an existing group on a frehsly created group object
	bool (*openExisting)(CC4Group* const this, const char* const path);

	// opens a group that is stored entirely in memory
	// only open an in-memory group on a frehsly created group object
	// see the description of MemoryManagement to know if and when data has to be freed by the caller
	// if the lazy mode is not used, the data can be freed immediately after this function returns
	bool (*openMemory)(CC4Group* const this, const uint8_t* const groupData, size_t const size, int const memoryManagement);

	// opens a group through a file descriptor
	// the file descriptor must have been opened with read access
	bool (*openFd)(CC4Group* const this, int fd);

	// opens a group through a FILE*
	// the file must have been opened with read access
	bool (*openFilePointer)(CC4Group* const this, FILE* fd);

	// opens a group and calls the callback to get the group data
	bool (*openWithReadCallback)(CC4Group* const this, CC4Group_ReadCallback const callback, void* const callbackArg, int const memoryManagement);

	bool (*save)(CC4Group* const this, const char* const path);
	bool (*saveOverwrite)(CC4Group* const this, const char* const path);

	// extraction to disk
	bool (*extractAll)(CC4Group* const this, const char* const targetPath);
	bool (*extractSingle)(CC4Group* const this, const char* const entryPath, const char* const targetPath);

	// the group owns the data pointed to. the pointer is valid until the group destructor is called
	bool (*getEntryData)(CC4Group* const this, const char* const entryPath, const void** const data, size_t* const size);

	// the returned error message pointer is valid until the next call to getErrorMessage is issued or the group is destructed
	const char* (*getErrorMessage)(CC4Group* const this);

	int32_t (*getErrorCode)(const CC4Group* const this);

	const char* (*getErrorMethod)(const CC4Group* const this);
	const char* (*getErrorCauser)(const CC4Group* const this);

	struct {
		CC4Group_TmpMemoryStrategy Memory;
		CC4Group_TmpMemoryStrategy File;
		CC4Group_TmpMemoryStrategy Auto;
	} const TmpMemoryStrategies;

	struct {
		int Take; // cc4group will free the data when its not needed anymore; e.g. in the destructor or when setting the file's data again
		int Copy; // cc4group will copy the data to use it; the original data is untouched and needs to be freed by the caller whenever desired
		int Reference; // cc4group will use the data as is (i.e. store the pointer and use it); the caller must guarantee it's validity throughout the groups lifetime (or until the file's data is set to a new pointer) and needs to take care of freeing it afterwards
	} const MemoryManagement;

	void (*setTmpMemoryStrategy)(const CC4Group_TmpMemoryStrategy strategy);

	// group metadata handling
	bool (*setMaker)(CC4Group* const this, const char* const maker, const char* const path, bool const recursive);
	bool (*setCreation)(CC4Group* const this, int32_t const creation, const char* const path, bool const recursive);
	bool (*setOfficial)(CC4Group* const this, bool const official, const char* const path, bool const recursive);
	bool (*setExecutable)(CC4Group* const this, bool const executable, const char* const path);

	bool (*getEntryInfo)(CC4Group* const this, const char* const path, CC4Group_EntryInfo* const info);
	bool (*getEntryInfos)(CC4Group* const this, const char* const path, CC4Group_EntryInfo** const infos, size_t* const size);

	// modifying the group
	bool (*deleteEntry)(CC4Group* const this, const char* const path, bool const recursive);
	bool (*renameEntry)(CC4Group* const this, const char* const oldPath, const char* const newPath);
	bool (*createDirectory)(CC4Group* const this, const char* const path);

	bool (*createFile)(CC4Group* const this, const char* const path);

	// see the description of MemoryManagement to know if and when data has to be freed by the caller
	bool (*setEntryData)(CC4Group* const this, const char* const entryPath, const void* const data, size_t const size, int const memoryManagementMode);
} const CC4Group_API;

#ifndef CC4GROUP_DYNAMIC_LOAD
extern CC4Group_API cc4group;
#endif

#ifdef __cplusplus
}
#undef this
#undef new
#undef delete
#endif