view src/libmlk-core/core/vfs.c @ 339:979960e65f76

js: add font bindings While here, correct int to long in font_render.
author David Demelier <markand@malikania.fr>
date Sat, 16 Oct 2021 09:01:20 +0200
parents 68287c7bcdb5
children 0969931b98e4
line wrap: on
line source

/*
 * vfs.c -- virtual file system abstraction
 *
 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "error.h"
#include "vfs.h"
#include "vfs_p.h"

int
vfs_open(struct vfs *vfs, struct vfs_file *file, const char *entry, const char *mode)
{
	assert(vfs);
	assert(entry);

	memset(file, 0, sizeof (*file));

	return vfs->open(vfs, file, entry, mode);
}

int
vfs_ok(struct vfs *vfs)
{
	return vfs && vfs->open && vfs->finish;
}

void
vfs_finish(struct vfs *vfs)
{
	assert(vfs);

	vfs->finish(vfs);
	memset(vfs, 0, sizeof (*vfs));
}

int
vfs_file_ok(struct vfs_file *file)
{
	return file && file->read && file->write && file->flush && file->finish;
}

size_t
vfs_file_read(struct vfs_file *file, void *buf, size_t bufsz)
{
	assert(file);
	assert(buf);

	return file->read(file, buf, bufsz);
}

char *
vfs_file_aread(struct vfs_file *file, size_t *outlen)
{
	FILE *fp;
	char *out = NULL, buf[BUFSIZ];
	size_t len, nr;

	if (!(fp = open_memstream(&out, &len)))
		return errorf("%s", strerror(errno)), NULL;

	while ((nr = vfs_file_read(file, buf, sizeof (buf))) > 0) {
		if (fwrite(buf, 1, nr, fp) != nr) {
			errorf("%s", strerror(errno));
			fclose(fp);
			free(out);
			return NULL;
		}
	}

	fclose(fp);

	if (outlen)
		*outlen = len;

	return out;
}

size_t
vfs_file_write(struct vfs_file *file, void *buf, size_t bufsz)
{
	assert(file);
	assert(buf);

	return file->write(file, buf, bufsz);
}

int
vfs_file_flush(struct vfs_file *file)
{
	assert(file);

	return file->flush(file);
}

void
vfs_file_finish(struct vfs_file *file)
{
	assert(file);

	file->finish(file);
}

/* private */

static int
rw_vfs_file_close(SDL_RWops *context)
{
	free(context->hidden.mem.base);
	free(context);

	return 0;
}

SDL_RWops *
vfs_to_rw(struct vfs_file *file)
{
	SDL_RWops *ops;
	char *data;
	size_t datasz;

	if (!(data = vfs_file_aread(file, &datasz)))
		return NULL;
	if (!(ops = SDL_RWFromConstMem(data, datasz))) {
		free(data);
		return errorf("%s", SDL_GetError()), NULL;
	}

	ops->close = rw_vfs_file_close;

	return ops;
}