You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

200 lines
4.9 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define TRANS 1
#define NOTRANS 0
#ifndef DEBUG
#define DEBUG 0
#endif
#define ENCODE 0
#define DECODE 1
#ifndef MODE
#define MODE ENCODE
#endif
int print_buffer(char *buf, unsigned int bytes) {
//Takes in a buffer and prints specified number of bytes
for(int i = 0; i < bytes; i++) {
printf("%c", buf[i]);
}
return bytes;
}
int transpose_buffer(char *out, char *in, unsigned int dim) {
//Transpose buffer in into buffer out, with a block of size dim*dim
int j = 0;
int mod = dim*dim -1;
for(int i = 0; i < dim * dim; i++) {
if(j > mod) {
j -= mod;
}
out[i] = in[j];
j+=dim;
}
return 0;
}
int dump_buffer(char *buffer, unsigned int bufsize,
unsigned int bytes, char *output, FILE *OUTPUT) {
/* prints a buffer one character at a time to a file using %c
* takes in:
* buffer -- pointer to a buffer
* bufsize -- size of 'buffer'
* bytes -- number of bytes from buffer to print
* output -- path to the file to open and output to
*/
/* print 'bytes' bytes from buffer to output file one char at a time */
for(int q = 0; q < bytes; q++) {
fprintf(OUTPUT, "%c", buffer[q]);
}
return bytes;
}
int pad_buffer(char *buffer, unsigned int bufsize, unsigned int rbuf_index) {
/* pad_buffer pads the empty space in a buffer
* buffer -- pointer to buffer
* bufsize -- size of 'buffer'
* rbuf_index -- first "empty" spot in buffer, i.e.,
* put the 'X' at rbuf_index and fill the
* rest with 'Y' characters.
*/
int padded = 0;
buffer[rbuf_index] = 'X';
printf("%d : X\n", rbuf_index);
for(int g = rbuf_index+1; g < bufsize; g++) {
buffer[g] = 'Y';
printf("%d : Y\n", g);
padded++;
}
return padded;
}
int unpad_buffer(char *buffer, unsigned int bufsize) {
int end = bufsize;
for(end = end; end > 0; end--) {
if(buffer[end] == 'X' && buffer[end - 1] != 'Y') {
break;
}
}
return end;
}
int main(int argc, char *argv[]) {
printf("main\n");
if (argc < 4) {
printf("Missing arguments!\n\n");
printf("Usage: encoder dim infile outfile ['notrans']\n\n");
printf("Note: outfile will be overwritten.\n");
printf("Optional '1' as last parameter will disable transposition.\n");
return 1;
}
/* give input and output nicer names */
unsigned int dim = atoi(argv[1]); /* dimension of the box */
char *input = argv[2]; /* input file path */
char *output = argv[3]; /* output file path */
/* use 'transmode' to determine if we are just padding or also
* doing transposition. very helpful for debugging! */
unsigned int transmode = TRANS; /* default is TRANS */
if (argc > 4 && (atoi(argv[4]) == 1)) {
printf("Warning: Transposition disabled\n");
transmode = NOTRANS;
}
unsigned int rbuf_count = 0;
unsigned int bufsize = dim * dim;
char read_buf[bufsize]; /* buffer for reading and padding */
char write_buf[bufsize]; /* buffer for transposition */
/* open the input or quit on error. */
FILE *INPUT;
if ((INPUT = fopen(input, "r")) == NULL) {
printf("Problem opening input file '%s'; errno: %d\n", input, errno);
return 1;
}
/* get length of input file */
unsigned int filesize; /* length of file in bytes */
unsigned int bytesleft; /* counter we reduce on reading */
struct stat filestats; /* struct for file stats */
int err;
if ((err = stat(input, &filestats)) < 0) {
printf("error statting file! Error: %d\n", err);
}
filesize = filestats.st_size;
bytesleft = filesize;
if (DEBUG) printf("Size of 'input' is: %u bytes\n", filesize);
/* truncate output file if it exists */
FILE *OUTPUT;
if ((OUTPUT = fopen(output, "w+")) == NULL) {
printf("Problem truncating output file '%s'; errno: %d\n", output, errno);
return 1;
}
int blocks = filesize/dim/dim;
/* loop through the input file, reading into a buffer and
* processing the buffer when 1) the buffer is full or
* 2) the file has ended (or in the case of decoding, when
* the last block is being processed.
*/
int rbuf_index = 0; // index into the read buffer
int dataByte;
int f;
if(MODE == DECODE) {
blocks--;
}
for(int l = 0; l <= blocks; l++) {
for(f = 0; f < dim*dim; f++) {
dataByte = fgetc(INPUT);
if(dataByte != EOF) {
read_buf[f] = dataByte;
}
else break;
}
if(MODE != ENCODE) {
//Transpose block and output to file.
transpose_buffer(write_buf, read_buf, dim);
int dumpBytes = bufsize;
if(bytesleft == bufsize) {
dumpBytes = unpad_buffer(write_buf, bufsize);
}
bytesleft -= bufsize;
dump_buffer(write_buf, bufsize, dumpBytes, output, OUTPUT);
}
else {
//Decode block and output to file
if(f < dim*dim) {
pad_buffer(read_buf, bufsize, f);
}
if(transmode == TRANS) {
transpose_buffer(write_buf, read_buf, dim);
}
dump_buffer(write_buf, bufsize, bufsize, output, OUTPUT);
}
}
fclose(INPUT);
fclose(OUTPUT);
return 0;
}