Skip to content

Instantly share code, notes, and snippets.

@tsutsui
Created August 27, 2017 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsutsui/57efd752c1ece35a2eea1bbbd0881118 to your computer and use it in GitHub Desktop.
Save tsutsui/57efd752c1ece35a2eea1bbbd0881118 to your computer and use it in GitHub Desktop.
/*-
* Copyright (c) 2012, 2016 Izumi Tsutsui. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* dumb run-length compression
*/
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define DS_SIZE 8192
#define MAGIC 0x9c
static void
usage(void)
{
const char *prog;
prog = getprogname();
fprintf(stderr, "usage: %s binfile outfile\n", prog);
exit(EXIT_FAILURE);
}
int
main(int argc, char **argv)
{
struct stat sb;
int fd, ofd;
const char *binfile, *outfile;
uint8_t *buf, *outbuf;
int count, size, i, outi;
uint8_t data;
if (argc != 3)
usage();
binfile = argv[1];
outfile = argv[2];
/*
* open and check input files
*/
if ((fd = open(binfile, O_RDONLY, 0600)) == -1)
err(EXIT_FAILURE, "can't open input file `%s'", binfile);
if (fstat(fd, &sb) != 0)
err(EXIT_FAILURE, "can't stat %s", binfile);
size = sb.st_size;
if (size == 0 || size > DS_SIZE)
err(EXIT_FAILURE, "invalid size of %s (%d)",
binfile, (int)sb.st_size);
/* open output file */
if ((ofd = open(outfile, O_WRONLY|O_CREAT, 0644)) == -1)
err(EXIT_FAILURE, "can't open output file `%s'", binfile);
/* allocate buffer for input file */
buf = malloc(DS_SIZE);
if (buf == NULL)
err(1, "malloc input buffer");
memset(buf, 0, DS_SIZE);
count = read(fd, buf, size);
if (count != size)
err(EXIT_FAILURE, "failed to read input file");
close(fd);
/* allocate buffer for input file */
outbuf = malloc(size);
if (outbuf == NULL)
err(1, "malloc output buffer");
memset(outbuf, 0, size);
outi = 0;
data = buf[0];
count = 1;
for (i = 1; i < size; i++) {
if (data == buf[i] && count < 0xff && i != size - 1) {
count++;
} else {
if (count <= 2) {
if (data == MAGIC) {
outbuf[outi++] = MAGIC;
outbuf[outi++] = count;
outbuf[outi++] = data;
} else {
int j;
for (j = 0; j < count; j++) {
outbuf[outi++] = data;
}
}
} else {
outbuf[outi++] = MAGIC;
outbuf[outi++] = count;
outbuf[outi++] = data;
}
data = buf[i];
count = 1;
}
}
outbuf[outi++] = data;
count = write(ofd, outbuf, outi);
if (count != outi)
err(EXIT_FAILURE, "failed to write output file");
free(outbuf);
close(ofd);
free(buf);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment