File: presets.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (242 lines) | stat: -rw-r--r-- 5,308 bytes parent folder | download | duplicates (2)
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#pragma once

#include "cfile/cfile.h"
#include "controlconfig/controlsconfig.h"
#include "globalincs/pstypes.h"
#include "globalincs/vmallocator.h"

#include <jansson.h>

/** API for saving and loading player custom bindings, known as Presets

 Init.  If the player/preset dir doesn't exist. Create it, and print a help.txt with all enums (as strings) to label
 the button names and action names.

 Example output:
 {
	"actions": {
		"TARGET_NEXT": {
			"first": {
				"cid": 0,
				"flags": 0,
				"btn": 0
			},
			"second": {
				"cid": 0,
				"flags": 0,
				"btn": 0
			}
		},
		"TARGET_PREV" : {
			"first": {
				"cid": 0,
				"flags": 0,
				"btn": 0
			},
			"second": {
				"cid": 0,
				"flags": 0,
				"btn": 0
			}
		},
	},
	"version": 0
 }


*/
namespace io {
namespace presets {

static const unsigned int PST_VERSION = 0;
static const unsigned int PST_FILE_ID = 0x5f545350;  // "PST_" in file

enum class Section {
	Invalid = -1,
	Unnamed = 0,
	
	// arrays
	Actions,

	// subsections
	Primary,
	Secondary
};

class PresetFileHandler {
public:
	PresetFileHandler(CFILE* cfp, bool reading);
	~PresetFileHandler();

	/**
	 * begins writing to a section using the presets::Section as its name
	 * @param[in] s     id of the section
	 */
	void beginSectionWrite(presets::Section s);

	/**
	 * begins reading a section, if it exists
	 * @param[in] s    id of the section
	 */
	bool beginSectionRead(presets::Section s);

	/**
	 * Begins writing to an array using the presets::Section as its name
	 *
	 * @param[in] s     id of the array
	 */
	void beginArrayWrite(presets::Section s);

	/**
	 * Begins reading from an array
	 * @param[int] s    id of the array
	 * @param[out] size the size of the array
	 */
	bool beginArrayRead(presets::Section s, size_t &size);

	/**
	 * ends writing to a section
	 */
	void endSectionWrite();

	/**
	 * ends reading a section
	 */
	void endSectionRead();

	/**
	 * ends writing to an array.
	 */
	void endArrayWrite();

	/**
	 * ends reading from an array
	 */
	void endArrayRead();

	/**
	 * Writes a string with the given key name
	 */
	void writeString(const char* key, SCP_string s);

	/**
	 * Reads a string with the given key name
	 */
	SCP_string readString(const char* key);

	/**
	 * Writes an int with the given key name
	 */
	void writeInt(const char* key, int val);

	/**
	 * Reads an int with the given key name
	 */
	int readInt(const char* key);

	/**
	 * For writing, Flushes the buffers and dumps to file
	 */
	void flush();

	/**
	 * Advances the array parser to the next element
	 */
	void nextArrayElement();

private:
	CFILE* _cfp = nullptr;

	json_t* _rootObj = nullptr;

	json_t* _currentEl = nullptr;

	/**
	 * BufferStack of all json elements being read/written
	 */
	SCP_vector<json_t*> _elementStack;

	/**
	 * Stack to keep track of the heirachy/nesting. Back is immediate parent, Front is root
	 */
	SCP_vector<void*> _parentStack;

	size_t _arrayIndex = INVALID_SIZE;

	//void* _sectionIterator = nullptr;	//!< Pointer to the current section/array we're in

private:
	/**
	 * Pushes an element onto the elementStack
	 */
	void pushElement(json_t* el);
	
	/**
	 * Pops an element off the elementStack
	 */
	json_t * popElement();

	/**
	 * Used for optionals, checks if an element exists with the given name
	 * @return True     if the element exists
	 * @return False    otherwise
	 */
	bool exists(const char* name);

	/**
	 * Throws an error if an element with the given name does not exist
	 */
	void ensureExists(const char* name);

	/**
	 * Throws an error if an element with the given name exists
	 */
	void ensureNotExists(const char* name);
};

} // namespace presets
} // namespace io

/**
 * @brief Saves the given preset to file.
 * @param[in] preset    The preset to save
 * @param[in] overwrite If true, overwrite existing preset file which have the same name as the given preset
 *
 * @returns True    if successful, or
 * @returns False   Preset does not have a name, or
 * @returns False   Preset file exists and overwrite == false, or
 * @returns False   Preset file .JSON could not be written
 */
bool save_preset_file(CC_preset preset, bool overwrite);

/**
 * @brief Deletes the given preset to file.
 * @param[in] preset    The preset to delete
 *
 * @returns True    if successful, or
 * @returns False   Preset is default, or
 * @returns False   Preset file is the currently selected preset
 */
bool delete_preset_file(CC_preset preset);

/**
 * @brief Loads in all preset .json files from 'players/presets'
 * @details If a preset file is unique, it is loaded into the game and available for use by the player.  However, if
 * a preset is a duplicate of another preset, it is ignored, and the player is warned of it
 * 
 * @param[in] clone Used to check if we just cloned a particular preset and allows just that clone in without warning
 */
void load_preset_files(SCP_string clone = "");

/**
 * @brief Checks if the given preset is a duplicate within Control_config_presets vector
 * @returns iterator to the duplicate if found, or
 * @returns iterator to Control_config_presets.end() otherwise
 */
SCP_vector<CC_preset>::iterator preset_find_duplicate(const CC_preset& new_preset);


/**
 * @brief Returns true if a preset file with the given name exists.
 */
bool preset_file_exists(SCP_string name);