/* * 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 #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 */