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 void** 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 void* 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
|