shithub: femtolisp

ref: 0d5459f1f08ef367cd8849fc733b64bbdd9fd552
dir: /compress.c/

View raw version
#include "flisp.h"
#include "compress.h"
#include "cvalues.h"
#include "types.h"
#include "brieflz.h"

BUILTIN("lz-pack", lz_pack)
{
	if(nargs < 1)
		argcount(nargs, 1);
	if(nargs > 2)
		argcount(nargs, 2);

	if(!isarray(args[0]))
		type_error("array", args[0]);
	uint8_t *in;
	size_t insz;
	to_sized_ptr(args[0], &in, &insz);
	int level = nargs > 1 ? tofixnum(args[1]) : 0;
	if(level < 0)
		level = 0;
	else if(level > 10)
		level = 10;

	value_t v = cvalue(cv_class(ptr(args[0])), blz_max_packed_size(insz));
	uint8_t *out = cvalue_data(v);

	size_t worksz = level > 0
		? blz_workmem_size_level(insz, level)
		: blz_workmem_size(insz);
	uint8_t *work = MEM_ALLOC(worksz);
	unsigned long n = level > 0
		? blz_pack_level(in, out, insz, work, level)
		: blz_pack(in, out, insz, work);
	MEM_FREE(work);
	if(n == BLZ_ERROR)
		lerrorf(FL(ArgError), "blz error");
	cvalue_len(v) = n;
	return v;
}

BUILTIN("lz-unpack", lz_unpack)
{
	argcount(nargs, 3);

	uint8_t *in;
	size_t insz;
	to_sized_ptr(args[0], &in, &insz);
	if(!isarray(args[0]))
		type_error("array", args[0]);
	size_t outsz;
	uint8_t *out;
	value_t v;
	if(args[1] == FL(sizesym)){
		outsz = tosize(args[2]);
		v = cvalue(cv_class(ptr(args[0])), outsz);
		out = cvalue_data(v);
	}else if(args[1] == FL(tosym)){
		v = args[2];
		to_sized_ptr(v, &out, &outsz);
	}else{
		lerrorf(FL(ArgError), "either :size or :to must be specified");
	}
	unsigned long n = blz_depack_safe(in, insz, out, outsz);
	if(n == BLZ_ERROR)
		lerrorf(FL(ArgError), "blz error");
	cvalue_len(v) = n;
	return v;
}

void
compress_init(void)
{
	FL(sizesym) = symbol(":size", false);
	FL(tosym) = symbol(":to", false);
}