-
Notifications
You must be signed in to change notification settings - Fork 0
/
variable_example.c
92 lines (75 loc) · 2.99 KB
/
variable_example.c
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
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stdint.h"
/*
* This Example demonstrates IO with fields of variable size.
* Options are:
* - to write the size of arrays into the file elsewhere
* - or in case of strings to use an in-file terminator. Although this option is somewhat slower.
*/
#define FFORMAT_IMPL
#include "fformat.h"
typedef struct{
char *name; // NULL terminated
char *desc; // NULL terminated
uint32_t width;
uint32_t height;
int32_t *data;
}map_t;
bool map_io(char *path, FF_MODE mode, map_t *map){
FILE *file = ff_open(path, mode);
if (!file) return false;
// variable to store the strlen in front of the string
size_t name_len = mode == FF_MODE_SAVE ? strlen(map->name) : 0;
// it's important to keep the success && .. chain going, to ensure an abort on first error.
bool success = true
&& ff_lit_string(file, mode, "Map v1.3\n") // version (this could be an entry point to handle different format version)
&& ff_lit_string(file, mode, "Name (prefix len): ")
&& ff_var_bytes(file, mode, &name_len, sizeof(name_len))
&& ff_var_string_alloc(file, mode, &map->name, name_len)
&& ff_lit_string(file, mode, "\nDescription (LF terminated): ")
&& ff_var_string_until_alloc(file, mode, &map->desc, '\n')
&& ff_lit_string(file, mode, "Width: ")
&& ff_var_bytes(file, mode, &map->width, sizeof(map->width))
&& ff_lit_string(file, mode, "\nHeight: ")
&& ff_var_bytes(file, mode, &map->height, sizeof(map->height))
&& ff_lit_string(file, mode, "\nData:\n")
&& ff_var_bytes_alloc(file, mode, (void**)&map->data, map->height * map->width * sizeof(*map->data)) // sizeof does not evaluate the expression
&& ff_lit_string(file, mode, "\n")
;
// TODO support formatting and parsing? scanf is unsafe? maybe own scanf + parsing?
// TODO support quoted string?
fclose(file);
return success;
}
int main(){
map_t map = {
.name = "nice map",
.desc = "it's a nice map of wonky proportions!",
.width = 23, .height = 7,
};
map.data = malloc(sizeof(map.data) * map.width * map.height);
for (size_t i = 0; i < map.width * map.height; i++){
map.data[i] = i*((i % 3) - 1);
}
// save
assert(map_io("beautiful.map", FF_MODE_SAVE, &map));
// load
map_t loaded_map = {0};
assert(map_io("beautiful.map", FF_MODE_LOAD, &loaded_map));
// check equality
assert(strcmp(map.name, loaded_map.name) == 0);
assert(strcmp(map.desc, loaded_map.desc) == 0);
assert(map.width == loaded_map.width);
assert(map.height == loaded_map.height);
assert(memcmp(map.data, loaded_map.data, map.width * map.height * sizeof(*map.data)) == 0);
// if you did not define FF_MALLOC, you may assume that the stdlib.h malloc/free are (and can be) used
FF_FREE(loaded_map.name);
FF_FREE(loaded_map.desc);
FF_FREE(loaded_map.data);
FF_FREE(map.data);
// no assertions failed
printf("success\n");
}