/*++ DsCreateFromFile Creates a dynamic string from the contents of a file. Arguments: path - Pointer to a null-terminated string specifying the path of a file. pool - Pointer to a memory pool. Return Values: If the function succeeds, the return value is a pointer to a DYNAMIC_STRING structure. If the function fails, the return value is null. --*/ DYNAMIC_STRING * DsCreateFromFile( const char *path, apr_pool_t *pool ) { apr_byte_t *buffer; apr_size_t length; apr_status_t status; ASSERT(path != NULL); ASSERT(pool != NULL); status = BufferFile(path, &buffer, &length, pool); if (status != APR_SUCCESS) { return NULL; } // TODO: // - check for a BOM or for UTF8 chars // - convert buffer to UTF8, if necessary return NULL; }
// An old map may be passed in to avoid reloading the images for the tilesets. struct Map *loadMap(const char *path, SDL_Renderer *renderer, struct Map *reuse_images){ // Load the int size; struct Turbo_Value mapValue; struct Map *map = NULL; char *const data = BufferFile(path, &size); if(!data){ fprintf(stderr, "Could not open map file %s\n", path); return NULL; } assert(path); Turbo_Parse(&mapValue, data, data + size); if(mapValue.type == TJ_Error){ Turbo_WriteError(&mapValue, stderr, 0); goto ending; } if(mapValue.type != TJ_Object){ fprintf(stderr, "Invalid map object\n"); goto ending; } // Load the tilesets first. { unsigned i; const struct Turbo_Value *const tilesetArray = jsonFindObjectValue(&mapValue, "tilesets"); if(!tilesetArray){ fprintf(stderr, "Invalid map object: no tilesets\n"); goto ending; } else if(tilesetArray->type == TJ_Error){ Turbo_WriteError(&mapValue, stderr, 0); goto ending; } else if(tilesetArray->type != TJ_Array){ fprintf(stderr, "Invalid tileset array\n"); goto ending; } map = malloc(sizeof(struct Map)); map->numTilesets = tilesetArray->length; map->tilesets = calloc(map->numTilesets, sizeof(struct Tileset)); // Load all tilesets. for(i = 0; i < map->numTilesets; i++){ if(!loadTileset(map->tilesets + i, renderer, tilesetArray->value.array + i, reuse_images)){ // Free what we've loaded so far. unsigned e; for(e = 0; e != i; e++){ unsigned j; // If we reused an existing image, don't touch it. for(j = 0; j < reuse_images->numTilesets; j++){ if(reuse_images->tilesets[j].image == map->tilesets[e].image){ map->tilesets[e].image = NULL; map->tilesets[e].imagePath[0] = '\0'; break; } } destroyTileset(map->tilesets + e); } fprintf(stderr, "Error loading tileset %i\n", i); goto error_free_tilesets_only; } } // Change all reused surfaces to avoid any double-frees or use-after-frees. if(reuse_images){ for(i = 0; i < map->numTilesets; i++){ unsigned e; for(e = 0; e < reuse_images->numTilesets; e++){ if(reuse_images->tilesets[e].image == map->tilesets[i].image){ reuse_images->tilesets[e].image = NULL; reuse_images->tilesets[e].imagePath[0] = '\0'; } } } } } // Load layers { const struct Turbo_Value *const layers = jsonFindObjectValue(&mapValue, "layers"); if(!layers || layers->type != TJ_Array){ // Huh. This is at least a warning. fprintf(stderr, "Warning: No layers in map."); map->numLayers = 0; map->layers = NULL; } else{ unsigned i; map->numLayers = layers->length; map->layers = calloc(layers->length, sizeof(struct Layer)); for(i = 0; i < map->numLayers; i++){ if(!loadLayer(map->layers + i, layers->value.array + i)){ unsigned e; for(e = 0; e < i; e++){ destroyLayer(map->layers + e); } free(map->layers); goto error_free_tilesets; } } } } // All OK! goto ending; error_free_tilesets: { unsigned i; for(i = 0; i < map->numTilesets; i++) destroyTileset(map->tilesets + i); } error_free_tilesets_only: free(map->tilesets); error_free_map: free(map); map = NULL; ending: Turbo_FreeParse(&mapValue); FreeBufferFile(data, size); return map; }