summaryrefslogtreecommitdiff
path: root/src/loader.h
blob: 93ec42bf2b356083dd214ab46bb2592092a5ee76 (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
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
/*
 * Copyright 2022 Frederico de Oliveira Linhares
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CANDY_GEAR_LOADER_STACK_H
#define CANDY_GEAR_LOADER_STACK_H 1

#include <SDL2/SDL.h>

#ifdef __cplusplus
extern "C" {
#endif

struct LoaderStack_s;

/**
 * Stores a reversible action.
 */
typedef struct
{
  SDL_bool (*load)(void *obj, struct LoaderStack_s *ls);
  void (*unload)(void *obj, struct LoaderStack_s *ls);
} Loader;

/**
 * Stores a sequence of functions that must be executed and rolled back in
 * order.
 *
 * For example, if the variable _loaders contain A→B→C→D→E, it will load A,
 * then B, then C, etc. If D fails, it unloads C, then B, then A.
 */
struct LoaderStack_s
{
  void *_obj;

  int32_t _last_loaded;

  uint32_t _loader_capacity;
  uint32_t _loader_size;
  Loader *_loaders;

  char* error_message;
};

typedef struct LoaderStack_s LoaderStack;

/// \memberof LoaderStack_s @{

/**
 * Must be called to initialize the variables.
 *
 * @param[self] a pointer to the LoaderStack_s to be initalized.
 * @param[obj] a pointer to an struct that will be send to every function
 *   inside the _loaders.
 */
void
LoaderStack_constructor(LoaderStack *self, void *obj);

/**
 * Must be called to finalize the variables and cleanup memory.
 *
 * @param[self] a pointer to the LoaderStack_s to be finalized.
 */
void
LoaderStack_destructor(LoaderStack *self);

/**
 * Adds a reversible action to the loader. The first action added is the first
 * to de executed the last rolled back, and so on. Those functions are stored
 * inside _loaders.
 *
 * @param[self] a pointer to the LoaderStack_s hat stores the action.
 * @param[load] the do action. The function pointed by this variable must
 *   return SDL_TRUE on success and SDL_FALSE on fail.
 * @param[unload] the undo/rollback action, if the action do not need a
 *   rollback, this pointer can be set to null.
 */
void
LoaderStack_add(
  LoaderStack *self,
  SDL_bool (*load)(void *obj, LoaderStack *ls),
  void (*unload)(void *obj, LoaderStack *ls));

/**
 * Can be used to set error before returning SDL_FALSE from a function used by
 * _loaders
 *
 * @param[self] a pointer to the LoaderStack_s where the error happened.
 * @param[base_error] the error message.
 * @param[additional_error] if you need to concatenate two error messages, use
 *   this variable to a second message. Otherwise set to NULL.
 */
void
LoaderStack_set_error(
  LoaderStack *self, const char* base_error, const char* additional_error);

/**
 * @return SDL_TRUE if you successfuly executed LoaderStack_load or
 *   LoaderStack_reload in the LoaderStack. SDL_FALSE after
 *   LoaderStack_constructor or LoaderStack_unload is executed.
 */
SDL_bool
LoaderStack_is_loaded(LoaderStack *self);

/**
 * Execute some of the load functions in the _loaders. If one of them fails,
 * roll back everything inside _loaders. The LoaderStack knows which functions
 * it already executed and will not rerun them unless they are rolled back
 * first.
 *
 * @param[step] the number of functions to be executed.
 * @return SDL_TRUE on success and SDL_FALSE on fail.
 */
SDL_bool
LoaderStack_partial_load(LoaderStack *self, int32_t step);

/**
 * Execute all of the load functions in the _loaders. If one of them fails,
 * roll back everything inside _loaders.
 * @return SDL_TRUE on success and SDL_FALSE on fail.
 */
SDL_bool
LoaderStack_load(LoaderStack *self);

/**
 * Roll back all loaded function inside loaders, if there are any. Then execute
 * all of the load functions in the _loaders. If one of them fails, roll back
 * everything inside _loaders.
 *
 * @return SDL_TRUE on success and SDL_FALSE on fail.
 */
SDL_bool
LoaderStack_reload(LoaderStack *self);

/**
 * Roll back all loaded function inside loaders, if there are any.
 */
void
LoaderStack_unload(LoaderStack *self);

/// @}

#ifdef __cplusplus
};
#endif

#endif /* CANDY_GEAR_LOADER_STACK_H */