/* * Given a valid huffman mode, this function will generate the compression table that lists the codes for each * of the ascii characters that the compression scheme uses. That table is placed into the pOutTable passed * in by the caller. * * Table will have 256 entries and look like: * 01001 * 001 * 0111 * ... * 00001 */ eFileCode GenerateTableAndCompressOrDecompress(eMode huffmanMode, const char *fileName) { eFileCode fileCode; // And error code which tells if the operation was successful or not. FILE *pFile = fopen(fileName, "r"); // Open file for reading. fileCode = FILE_SUCCESS; // Check that file was successfully opened. If not, return an error code. if (pFile == NULL) { return FILE_MISSING; } switch(huffmanMode) { case DECOMPRESS_MODE: { // If the file is a compressed huffman file, then use the get table for huff function to open it. char huffmanEncodings[ENTRIES * ENTRY_LENGTH]; unsigned long long lengthOfFile = huffmanEncodingsFromFile(pFile, huffmanEncodings); huffResult resultArray[ENTRIES]; createHuffResultArrayFromFileEncodings(huffmanEncodings, resultArray); huffNode huffmanTree[ENTRIES + ENTRIES - 1]; createDecodeTreeFromResultArray(resultArray, huffmanTree); FILE *rle_file = xtmpfile(); writeCompressedFileToNonCompressedOutput(pFile, rle_file, lengthOfFile, &huffmanTree[0]); rewind(rle_file); int nameLength = strlen(fileName) - strlen(".hurl"); char newFileName[nameLength + 1]; strncpy(newFileName, fileName, nameLength); newFileName[nameLength] = 0; FILE *pNewFile = xfopen(newFileName, "w"); rle_decode(rle_file, pNewFile); fclose(rle_file); fclose(pNewFile); break; } case TABLE_MODE_HURL: { // If we want a table and the file is .hurl, it may or may not be the same .hurl we want it to be. // We'll try to treat it as a .hurl but if it's the wrong format, we will treat it like a generic // file. char huffmanEncodings[ENTRIES * ENTRY_LENGTH]; huffmanEncodingsFromFile(pFile, huffmanEncodings); if (huffmanEncodings[0] != 0) { huffResult resultArray[ENTRIES]; createHuffResultArrayFromFileEncodings(huffmanEncodings, resultArray); printHuffResultArray(resultArray); } else { // File was a .hurl, but internally format doesn't fit. Oh well, we can still generate a compression table. // Maybe someone else in the world created their own .hurl file format. We need to handle that format. fseek(pFile, 0, SEEK_SET); // The frequency of occurrence of each character in the uncompressed file. unsigned long long pFrequencies[ENTRIES]; memset(pFrequencies, 0, sizeof(pFrequencies)); if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS) { huffResult resultArray[ENTRIES]; fileCode = GetTableForGeneric(pFrequencies, resultArray); } else { fileCode = FILE_INVALID_FORMAT; } } break; } case TABLE_MODE_GENERIC: { // If the file is not a .hurl, then generate frequencies and then a table for the file. // The frequency of occurrence of each character in the uncompressed file. unsigned long long pFrequencies[ENTRIES]; memset(pFrequencies, 0, sizeof(pFrequencies)); if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS) { huffResult resultArray[ENTRIES]; fileCode = GetTableForGeneric(pFrequencies, resultArray); printHuffResultArray(resultArray); } else { fileCode = FILE_INVALID_FORMAT; } break; } case COMPRESS_MODE: { FILE *rle_file = xtmpfile(); rle_encode(pFile, rle_file); rewind(rle_file); unsigned long long pFrequencies[ENTRIES]; memset(pFrequencies, 0, sizeof(pFrequencies)); if (GenerateFrequenciesForGeneric(rle_file, pFrequencies) != FILE_SUCCESS) { fileCode = FILE_INVALID_FORMAT; break; } huffResult resultArray[ENTRIES]; fileCode = GetTableForGeneric(pFrequencies, resultArray); char newFileName[strlen(fileName) + 6]; strcpy(newFileName, fileName); FILE *pNewFile = fopen(strcat(newFileName, ".hurl"), "w+"); if (pNewFile == NULL) { fileCode = FILE_INVALID_FORMAT; break; } writeNonCompressedFileToCompressedOutput(rle_file, pNewFile, resultArray); fclose(rle_file); fclose(pNewFile); break; } default: { // File must not be valid for the specified commandline options if we get this far. fileCode = FILE_INVALID_FORMAT; break; } } fclose(pFile); return fileCode; }
/* * Given a valid huffman mode, this function will generate the compression table that lists the codes for each * of the ascii characters that the compression scheme uses. That table is placed into the pOutTable passed * in by the caller. * * Table will have 256 entries and look like: * 01001 * 001 * 0111 * ... * 00001 */ eFileCode GenerateTableAndCompressOrDecompress(eMode huffmanMode, char* fileName, huffResult* resultArray) { FILE* pFile; FILE* pNewFile; char* huffmanEncodings; huffNode* huffmanTreeRootNode; unsigned long long lengthOfFile = 0; unsigned pFrequencies[ENTRIES] = {0}; // The frequency of occurrence of each character in the uncompressed file. eFileCode fileCode; // And error code which tells if the operation was successful or not. pFile = fopen(fileName, "r"); // Open file for reading. fileCode = FILE_SUCCESS; // Check that file was successfully opened. If not, return an error code. if (pFile == NULL) { return FILE_MISSING; } switch(huffmanMode) { case DECOMPRESS_MODE: // If the file is a compressed huffman file, then use the get table for huff function to open it. huffmanEncodings = huffmanEncodingsFromFile(pFile, &lengthOfFile); if (huffmanEncodings != NULL) { int nameLength = strlen(fileName) - strlen(".huff\0"); assert(nameLength > 0); char* newFileName = calloc(nameLength + 1, sizeof(char)); strncpy(newFileName, fileName, nameLength); pNewFile = fopen(strcat(newFileName, ".debug"), "w+"); if (pNewFile == NULL) { fileCode = FILE_INVALID_FORMAT; } else { resultArray = createHuffResultArrayFromFileEncodings(huffmanEncodings); huffmanTreeRootNode = createDecodeTreeFromResultArray(resultArray); writeCompressedFileToNonCompressedOutput(pFile, pNewFile, lengthOfFile, huffmanTreeRootNode); fclose(pNewFile); } } else { fileCode = FILE_INVALID_FORMAT; } break; case TABLE_MODE_HUFF: // If we want a table and the file is .huff, it may or may not be the same .huff we want it to be. // We'll try to treat it as a .huff but if it's the wrong format, we will treat it like a generic // file. huffmanEncodings = huffmanEncodingsFromFile(pFile, &lengthOfFile); if (huffmanEncodings != NULL) { if (pNewFile == NULL) { fileCode = FILE_INVALID_FORMAT; } else { resultArray = createHuffResultArrayFromFileEncodings(huffmanEncodings); } } else { // File was a .huff, but internally format doesn't fit. Oh well, we can still generate a compression table. // Maybe someone else in the world created their own .huff file format. We need to handle that format. fseek(pFile, 0, SEEK_SET); if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS) { fileCode = GetTableForGeneric(pFrequencies, &resultArray); } else { fileCode = FILE_INVALID_FORMAT; } } break; case TABLE_MODE_GENERIC: // If the file is not a .huff, then generate frequencies and then a table for the file. if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS) { fileCode = GetTableForGeneric(pFrequencies, &resultArray); } else { fileCode = FILE_INVALID_FORMAT; } break; case COMPRESS_MODE: // If the file is not a .huff, then generate frequencies and then a table for the file. if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS) { fileCode = GetTableForGeneric(pFrequencies, &resultArray); pNewFile = fopen(strcat(fileName, ".huff"), "w+"); if (pNewFile == NULL) { fileCode = FILE_INVALID_FORMAT; } else { writeNonCompressedFileToCompressedOutput(pFile, pNewFile, resultArray); fclose(pNewFile); } } else { fileCode = FILE_INVALID_FORMAT; } break; default: // File must not be valid for the specified commandline options if we get this far. fileCode = FILE_INVALID_FORMAT; break; } fclose(pFile); return fileCode; }