/* * 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. */ #include #include "loader.h" void LoaderStack_constructor(LoaderStack *self, void *obj) { self->_last_loaded = 0; self->_loader_capacity = 10; // Totally arbitrary value. self->_loader_size = 0; self->_obj = obj; self->error_message = NULL; self->_loaders = malloc(sizeof(Loader) * self->_loader_capacity); } void LoaderStack_destructor(LoaderStack *self) { if(self->error_message != NULL) free(self->error_message); if(LoaderStack_is_loaded(self)) LoaderStack_unload(self); free(self->_loaders); } static void LoaderStack_partial_unload(LoaderStack *self, int32_t step) { // Already unloaded, nothing to do. if(self->_last_loaded <= step) return; for(; self->_last_loaded >= step; self->_last_loaded--) if(self->_loaders[self->_last_loaded].unload != NULL) self->_loaders[self->_last_loaded].unload(self->_obj, self); // This number will be one before the last loaded after the unloading loop // is over. self->_last_loaded++; } SDL_bool LoaderStack_partial_load(LoaderStack *self, int32_t step) { SDL_bool error = SDL_FALSE; // Already loaded, nothing to do. if(self->_last_loaded >= step) return SDL_TRUE; for(;self->_last_loaded < step; self->_last_loaded++) { error = !self->_loaders[self->_last_loaded].load(self->_obj, self); if(error) break; } // Self number will be one after the last loeaded after the loading loop is // over. self->_last_loaded--; if(error) LoaderStack_partial_unload(self, 0); return !error; } SDL_bool LoaderStack_is_loaded(LoaderStack *self) { return self->_last_loaded > 0; } void LoaderStack_add( LoaderStack *self, SDL_bool (*load)(void *obj, LoaderStack *ls), void (*unload)(void *obj, LoaderStack *ls)) { Loader *l; uint32_t next_loader = self->_loader_size; // Expand if is full. if(self->_loader_size == self->_loader_capacity) { self->_loader_capacity += 5; // Totally arbitrary value. self->_loaders = realloc(self->_loaders, sizeof(Loader) * self->_loader_capacity); } l = &(self->_loaders[next_loader]); l->load = load; l->unload = unload; self->_loader_size++; } void LoaderStack_set_error( LoaderStack *self, const char* base_error, const char* additional_error) { if(self->error_message != NULL) free(self->error_message); if(additional_error != NULL) { self->error_message = malloc(strlen(base_error) + strlen(additional_error) + 1); strcpy(self->error_message, base_error); strcat(self->error_message, additional_error); } else { self->error_message = malloc(strlen(base_error)); strcpy(self->error_message, base_error); } } SDL_bool LoaderStack_load(LoaderStack *self) { if(LoaderStack_is_loaded(self)) return SDL_TRUE; if(LoaderStack_partial_load(self, self->_loader_size)) return SDL_TRUE; else return SDL_FALSE; } SDL_bool LoaderStack_reload(LoaderStack *self) { if(!LoaderStack_is_loaded(self)) return SDL_FALSE; LoaderStack_partial_unload(self, self->_loader_size); return LoaderStack_partial_load(self, self->_loader_size); } void LoaderStack_unload(LoaderStack *self) { if(!LoaderStack_is_loaded(self)) return; LoaderStack_partial_unload(self, 0); }