Esempio n. 1
0
/*
 * 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;
}
Esempio n. 2
0
/*
 * 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;
}