int main(int argc, char* argv[]) { struct bitio *bd; uint64_t d, r; int i; //TEST 1: writes 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF23456789ABCDEF if ((bd = bitio_open("bitio_test.dat", 'w')) == NULL) { perror("bopen(w)"); exit(EXIT_FAILURE); } d = 0x0123456789ABCDEF; bitio_write(bd, d, 64); bitio_write(bd, d, 56); d = 0x23456789ABCDEF01; bitio_write(bd, d, 64); bitio_write(bd, d, 64); bitio_close(bd); if ((bd = bitio_open("bitio_test.dat", 'r')) == NULL) { perror("bopen(r)"); exit(EXIT_FAILURE); } for (i = 1; i <= 3; i++) { bitio_read(bd, &r, 64); if (r != 0x0123456789ABCDEF) exit(EXIT_FAILURE); } bitio_read(bd, &r, 56); if (r != 0x23456789ABCDEF) exit(EXIT_FAILURE); bitio_close(bd); //delete file unlink("bitio_test.dat"); //TEST 2: stdin and stdout while(bitio_read(bstdin, &r, 1) > 0) { bitio_write(bstdout, r, 1); } bitio_flush(bstdout); exit(EXIT_SUCCESS); }
int main() { struct bitio* b=bit_open("prova.txt", "w"); uint64_t a; bitio_write(b, 'a', 64); bitio_write(b, 'b', 64); bitio_write(b, 'c', 32); bitio_write(b, 'd', 8); bitio_write(b, 'd', 8); bitio_write(b, 'd', 8); bitio_write(b, 0x08, 6); bitio_write(b, 0xefafbfcf, 32); bitio_write(b, 'a', 64); bitio_write(b, 'b', 64); bitio_write(b, 'a', 64); bitio_close(b); b=bit_open("prova.txt", "r"); return 0; }
int main(int argc, char **argv) { bitio *b = NULL; uint64_t data = UINT64_MAX; int ret; if (!(b = bitio_open("test2", O_RDONLY))) { perror("bitio_open"); exit(-1); } for(int i = 0; i<1; i++ ) { ret = bitio_read(b, &data, 32); ret = bitio_read(b, &data, 64); if (ret) { printf("ret %d\n", ret); break; } fprintf(stderr,"%016llX -> %" PRIu64 "\n", (long long unsigned int)data, data); ret = bitio_read(b, &data, 32); /*ret = bitio_read(b, &data, 64); if (ret) { printf("ret %d\n", ret); break; } fprintf(stderr,"%016llX -> %" PRIu64 "\n", (long long unsigned int)data, data);*/ } bitio_close(b); return 0; }
int64_t decompress(const char* in_filename, const char* out_filename, uint8_t flags) { struct bitio *bd = bstdin; struct dictionary *d = NULL; struct utimbuf *t = NULL; FILE* fout = stdout; char *out_file = NULL; uint8_t bits, initial_bits, meta_type, meta_size; uint16_t c; uint32_t bitMask, cur, first_record, len, next_record, dict_size = 0, written = 0, write_count = 0; uint64_t filesize = 0; char *word; int first = 1, md5c_size = 0, md5d_size = 0; void *meta_data, *md5c = NULL, *md5d = NULL; EVP_MD_CTX *md_ctx = NULL; if (in_filename != NULL) { bd = bitio_open(in_filename, 'r'); if (bd == NULL) goto error; } //read metadata while ((meta_data = meta_read(bd, &meta_type, &meta_size)) != META_END) { LOG("META_TYPE: %d", meta_type); switch (meta_type) { case META_DICT_SIZE: dict_size = *(uint32_t*)meta_data; PRINT(1, "Dictionary Size:\t%d\n", dict_size); break; case META_NAME: PRINT(1, "Original file name:\t%s\n", (char*)meta_data); if (flags & DEC_ORIG_FILENAME) { out_file = malloc(meta_size); if (out_file == NULL) goto error; memcpy((void*)out_file, meta_data, meta_size); out_filename = out_file; } break; case META_MD5: md5c = malloc(meta_size); memcpy(md5c, meta_data, meta_size); md5c_size = meta_size; word = sprinth(md5c, md5c_size); PRINT(1, "Original md5sum:\t%s\n", word); free(word); // initialize md context OpenSSL_add_all_digests(); md_ctx = malloc(sizeof(EVP_MD_CTX)); EVP_MD_CTX_init(md_ctx); EVP_DigestInit(md_ctx, EVP_get_digestbyname("md5")); md5d_size = EVP_MD_CTX_size(md_ctx); md5d = malloc(md5d_size); break; case META_TIMESTAMP: t = malloc(sizeof(*t)); t->actime = *((time_t*)meta_data); // access time t->modtime = *((time_t*)meta_data); // modification time break; default: // META_ERROR LOG("Unknown metadata"); errno = EINVAL; goto error; } free(meta_data); } if ((flags & DEC_ORIG_FILENAME) && out_file == NULL) // if i have DEC_ORIG_FILENAME setted but no info in metadata i use stdin as outfile out_filename = "stdin"; if (out_filename != NULL) { fout = fopen(out_filename, "w"); if (fout == NULL) goto error; } if (out_filename != NULL && in_filename != NULL && strcmp(in_filename, out_filename) == 0) { errno = EINVAL; goto error; } if (dict_size == 0) goto error; d = dict_new(dict_size, 0, dict_size, NUM_SYMBOLS); if (d == NULL) goto error; first_record = dict_init(d); next_record = first_record; initial_bits = 0; bitMask = 1; while (bitMask < next_record) { bitMask <<= 1; initial_bits++; } bits = initial_bits; for (;;) { // put in cur the index of the fetched word in the dictionary cur = fetch(bd, bits); if (cur == ROOT_NODE) goto error; if (cur == EOF_SYMBOL) break; c = dict_first_symbol(d, cur); if (c == EOF_SYMBOL) goto error; if (!first) { // complete previous record with index of new record // ROOT_NODE as current node value means 'don't change it'. dict_fill(d, next_record, ROOT_NODE, (uint8_t) c, 0); next_record++; if ((next_record+1) & bitMask) { bitMask <<= 1; bits++; } } else first = 0; // get the word in the dictionary at index cur. word = dict_word(d, cur, &len); if (word == NULL) goto error; written = fwrite(word, 1, len, fout); if (written < len) goto error; else { // md5 computation and visual feedback if (md5c != NULL) // compute md5 of decompressed EVP_DigestUpdate(md_ctx, word, len); write_count += written; if (write_count >= COUNT_THRESHOLD) { filesize += write_count; write_count = 0; PRINT(1, "."); } } if (next_record + 1 == dict_size) { next_record = first_record; bits = initial_bits; bitMask = 1 << bits; first = 1; // set first iteration to be the next } // add a new record dict_fill(d, next_record, cur, 0, 0); // symbol will be filled at the beginning of next iteration } filesize += write_count; if (md5c != NULL) { EVP_DigestFinal_ex(md_ctx, md5d, (unsigned int*)&md5d_size); if (md5c_size == md5d_size && memcmp(md5c, md5d, md5c_size) == 0) PRINT(1, "\nmd5sum Check:\t\tOK"); else { PRINT(1, "\nmd5sum Check:\t\tFailed"); goto error; } } PRINT(1, "\nDecompression Finished\n\n"); fclose(fout); if (out_file != NULL && t != NULL) if (utime(out_filename, t) < 0) { // set modification time PRINT(1, "Error while changing last modification time"); } free(out_file); free(t); dict_delete(d); bitio_flush(bd); if (bd != bstdin) bitio_close(bd); return filesize; error: PRINT(1, "\n"); if (out_filename != NULL) unlink(out_filename); free(out_file); free(t); dict_delete(d); bitio_flush(bd); if (bd != bstdin) bitio_close(bd); if (fout != NULL) fclose(fout); return -1; }
/* compressor algorithm for lz78: * from is the path of the file to compress, size is the size of the dictionary * to is the compressed file name, it can be chose by the user, * otherwise a standard name is put in its place*/ void compress(char* from, char* to, int size){ //fprintf(stderr, "compressor\n"); //int, i, flen; //length of filename //int i; unsigned int tmp=0; //temporary variable in which we put the byte read unsigned int itmp=0, size_tmp=0; //itmp is the index to write; int position=0, father=0; //postion in the dictionary //int fd=open(filename, 'r'); //file descriptor dictionary* dict=malloc(sizeof(dictionary)); //dictionary int blen=1; //bit lenght of my dictionary's indexes size_tmp=size; struct bitio* bit; header hdr; //header of the file int result=0; int longest_match=1, tmp_longest_match=0; FILE* file_read, *file_write; //compute how many bit to write in the compressed file while(size_tmp>>=1) blen++; fprintf(stderr, "blen: %i\n", blen); //initialize the dictionary dict_init(dict, size, 256); father=0; //initialize the bitio structure to write bits instead of bytes bit=bit_open(to, "w"); if(bit==NULL) fprintf(stderr, "null bitio\n"); //creation of the header of the file hdr.dictionary_size=size; hdr.longest_match=0; //prepare the space for the overwriting //write the header in the top of the file //flen=strlen(hdr.extension); bitio_write(bit, (uint64_t)hdr.dictionary_size, sizeof(int)*8); bitio_write(bit, (uint64_t)hdr.longest_match, sizeof(int)*8); //for(i=0; i<6; i++) //bitio_write(bit, (uint64_t)hdr.extension[i], sizeof(char)*8); //read a byte from the file //fprintf(stderr, "%i\n", fd); if(from==NULL) file_read=stdin; else file_read=fopen(from, "r"); //fprintf(stderr, "%c\n", (char)tmp); //first read result=fread(&tmp, 1, 1, file_read); father=tmp; //read the file until reach the EOF or an error occurs do { //read one byte from the file result=fread(&tmp, 1, 1, file_read); //fprintf(stderr, "%i ",tmp ); itmp=father; tmp_longest_match++; //search if we already have the actual string in the dictionary position=dict_search(&father, tmp, dict); //fprintf(stderr, "new_father: %i %i\n", father, position); if(position!=0) { if(longest_match < tmp_longest_match) longest_match = tmp_longest_match; tmp_longest_match=0; //add the string in the dictionary dict_add_word(position, father, tmp, dict); //fprintf(stderr, "%i: %i %i\n", position, father, tmp); bitio_write(bit, (uint64_t)itmp, blen); //fprintf(stderr, "\n"); father=tmp; } } while(result!=0 || !feof(file_read)); //write the last position reached bitio_write(bit, father, blen); //close all the structures writing EOFC on the compressed file bitio_write(bit, EOFC, blen); bitio_close(bit); //fprintf(stderr, "%i\n", longest_match); //write the longest match in the file file_write=fopen(to, "r+b"); fseek(file_write, sizeof(int), SEEK_SET); hdr.longest_match=longest_match; fwrite(&hdr.longest_match, sizeof(int), 1, file_write); fclose(file_write); //free all other structures suppress_dictionary(dict); free(dict); fclose(file_read); fprintf(stderr, "compression executed\n"); }
int64_t compress(const char* in_filename, const char* out_filename, uint32_t dict_size, uint32_t ht_size, uint8_t flags) { struct bitio *bd = bstdout; struct dictionary *d = NULL; struct stat file_stat; time_t t; FILE *fin = stdin; char *md5_str; int c, read_count = 0; uint8_t bits, initial_bits; uint32_t bitMask, cur, next_record, y; uint64_t filesize = 0; unsigned char *md5; if (out_filename != NULL && in_filename != NULL && strcmp(in_filename, out_filename) == 0) { errno = EINVAL; goto error; } if (in_filename != NULL) { fin = fopen(in_filename, "r"); if (fin == NULL) goto error; } if (out_filename != NULL) { bd = bitio_open(out_filename, 'w'); if (bd == NULL) goto error; } //write metadata if (flags & META_DICT_SIZE) if (meta_write(bd, META_DICT_SIZE, &dict_size, sizeof(dict_size)) < 0) goto error; if (flags & META_MD5) { if (fin != stdin) { int md5_size; md5 = compute_digest(fin, "md5", &md5_size); if (meta_write(bd, META_MD5, md5, md5_size) < 0) goto error; md5_str = sprinth(md5, md5_size); PRINT(1, "md5sum:\t\t\t%s\n", md5_str); free(md5); free(md5_str); } else PRINT(1, "md5sum:\t\t\tNot availabe when reading from stdin\n"); } if ((flags & META_NAME) && in_filename != NULL) { //don't put META_NAME if input = stdin c = path_len(in_filename); if (meta_write(bd, META_NAME, (void*)&in_filename[c], strlen(in_filename) - c + 1) < 0) goto error; } if ((flags & META_TIMESTAMP) && in_filename != NULL) { //don't put META_TIMESTAMP if input = stdin fstat(fileno(fin), &file_stat); t = file_stat.st_mtime; if (meta_write(bd, META_TIMESTAMP, &t, sizeof(t)) < 0) goto error; } if (meta_finalize(bd) < 0) goto error; d = dict_new(dict_size, 1, ht_size, NUM_SYMBOLS); if (d == NULL) goto error; next_record = dict_init(d); initial_bits = 0; bitMask = 1; while (bitMask < next_record) { bitMask <<= 1; initial_bits++; } bits = initial_bits; bitMask = 1 << bits; cur = ROOT_NODE; for(;;) { c = fgetc(fin); if (c == EOF) { //emit last word if (emit(bd, cur, bits) < 0) goto error; //emit EOF dict_lookup(d, ROOT_NODE, EOF_SYMBOL, &y); if (emit(bd, y, bits) < 0) goto error; break; } filesize++; if (VERBOSE_LEVEL > 0 && ++read_count >= COUNT_THRESHOLD) { read_count = 0; PRINT(1, "."); } if (!dict_lookup(d, cur, (uint16_t) c, &y)) { //node not found if (emit(bd, cur, bits) < 0) goto error; dict_fill(d, y, cur, (uint16_t) c, next_record++); if (next_record & bitMask) { bitMask <<= 1; bits++; } if (next_record == dict_size) { next_record = dict_reinit(d); bits = initial_bits; bitMask = 1 << bits; } // search again starting from last unmatched symbol dict_lookup(d, ROOT_NODE, (uint16_t) c, &y); } cur = dict_next(d, y); } PRINT(1, "\nCompression Finished\n\n"); dict_delete(d); bitio_flush(bd); if (bd != bstdout) bitio_close(bd); if (fin != NULL) fclose(fin); return filesize; error: PRINT(1, "\n"); dict_delete(d); bitio_flush(bd); if (bd != bstdout) bitio_close(bd); if (fin != NULL) fclose(fin); return -1; }