diff options
Diffstat (limited to 'tools/lz/util.c')
-rw-r--r-- | tools/lz/util.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/tools/lz/util.c b/tools/lz/util.c new file mode 100644 index 000000000..d77ac7bcc --- /dev/null +++ b/tools/lz/util.c @@ -0,0 +1,54 @@ +#include "proto.h" + +noreturn error_exit (int error_code, const char * error, ...) { + va_list ap; + va_start(ap, error); + fputs("error: ", stderr); + vfprintf(stderr, error, ap); + va_end(ap); + fputc('\n', stderr); + exit(error_code); +} + +unsigned char * read_file_into_buffer (const char * file, unsigned short * size) { + FILE * fp = file ? fopen(file, "rb") : stdin; + if (!fp) error_exit(1, "could not open file %s for reading", file); + unsigned char * buf = malloc(MAX_FILE_SIZE + 1); + int rv = fread(buf, 1, MAX_FILE_SIZE + 1, fp); + if (file) fclose(fp); + if (rv < 0) error_exit(1, "could not read from file %s", file); + if (rv > MAX_FILE_SIZE) error_exit(1, "file %s is too big", file ? file : "<standard input>"); + *size = rv; + return buf; +} + +struct command pick_best_command (unsigned count, struct command command, ...) { + struct command result = command; + va_list ap; + va_start(ap, command); + while (-- count) { + command = va_arg(ap, struct command); + if (is_better(command, result)) result = command; + } + va_end(ap); + return result; +} + +int is_better (struct command new, struct command old) { + if (new.command == 7) return 0; + if (old.command == 7) return 1; + short new_savings = new.count - command_size(new), old_savings = old.count - command_size(old); + return new_savings > old_savings; +} + +short command_size (struct command command) { + short header_size = 1 + (command.count > SHORT_COMMAND_COUNT); + if (command.command & 4) return header_size + 1 + (command.value >= 0); + return header_size + command.command[(short []) {command.count, 1, 2, 0}]; +} + +unsigned short compressed_length (const struct command * commands, unsigned short count) { + unsigned short current, total = 0; + for (current = 0; current < count; current ++) if (commands[current].command != 7) total += command_size(commands[current]); + return total; +} |