diff --git a/src/lib/error.hpp b/src/lib/error.hpp index 207b0ee..697c9b4 100644 --- a/src/lib/error.hpp +++ b/src/lib/error.hpp @@ -17,6 +17,11 @@ #include + +//TODO: needed macros: +// TRY: takes a variable, a function call, and the ErrorOr return type of the calling function - intended to automatically unwrap the ErrorOr data type or propagate the error upwards +// RAISE: takes an error code and optionally a message to produce something like `return ErrorOr(true, errorCode, file, lineNumber, message)` + template struct ErrorOr { bool isError; @@ -100,6 +105,9 @@ namespace ErrorCodes { // when too much data is available const uint8_t OVERFLOW = 13; + const uint8_t COMPRESSION = 14; + const uint8_t DECOMPRESSION = 15; + const uint8_t UNIMPLEMENTED = 254; const uint8_t UNKNOWN = 255; diff --git a/src/lib/zlibutil.cpp b/src/lib/zlibutil.cpp index d9f1a85..e872cad 100644 --- a/src/lib/zlibutil.cpp +++ b/src/lib/zlibutil.cpp @@ -16,92 +16,101 @@ // version 3 along with this program. // If not, see https://www.gnu.org/licenses/agpl-3.0.en.html -#include "../lib/zlibutil.hpp" +// includes vector and error.hpp +#include "zlibutil.hpp" -#include -#include -#include -#include -#include #include #include -#include "../lib/cli.hpp" -#include "../lib/file.hpp" - #define EXIT_SUCCESS 0 #define EXIT_RUNTIME 1 #define EXIT_USAGE 2 -#include -#include -#include -#include - #define CHUNK_SIZE 16384 // Chunk size +namespace zlib { -std::vector compressData(const char* data, int size) { - z_stream zs; - memset(&zs, 0, sizeof(zs)); + ErrorOr> compressData(std::vector data) { + // I, too, love the fact that raw bytes are signed and therefore can have negative values. -_- + std::vector signedData = std::vector(data.begin(), data.end()); - if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) - throw(std::runtime_error("deflateInit failed while compressing.")); + z_stream zs; + memset(&zs, 0, sizeof(zs)); - zs.next_in = reinterpret_cast(const_cast(data)); - zs.avail_in = size; + if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) { + return ErrorOr>(true, ErrorCodes::COMPRESSION); + //TODO: include error message once implemented + //throw(std::runtime_error("deflateInit failed while compressing.")); + } - int ret; - char outbuffer[CHUNK_SIZE]; - std::vector compressedData; + zs.next_in = reinterpret_cast(reinterpret_cast(signedData.data())); + zs.avail_in = signedData.size(); - do { - zs.next_out = reinterpret_cast(outbuffer); - zs.avail_out = CHUNK_SIZE; + int ret; + char outbuffer[CHUNK_SIZE]; + std::vector compressedData; - ret = deflate(&zs, Z_FINISH); + do { + zs.next_out = reinterpret_cast(outbuffer); + zs.avail_out = CHUNK_SIZE; - if (compressedData.size() < zs.total_out) - compressedData.insert(compressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out); - } while (ret == Z_OK); + ret = deflate(&zs, Z_FINISH); - deflateEnd(&zs); + if (compressedData.size() < zs.total_out) + compressedData.insert(compressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out); + } while (ret == Z_OK); - if (ret != Z_STREAM_END) - throw(std::runtime_error("Error while compressing: " + std::to_string(ret))); + deflateEnd(&zs); + + if (ret != Z_STREAM_END) { + return ErrorOr>(true, ErrorCodes::COMPRESSION); + //TODO: include error message once implemented + //throw(std::runtime_error("Error while compressing: " + std::to_string(ret))); + } + + return ErrorOr>(std::vector(compressedData.begin(), compressedData.end())); + } + + + ErrorOr> decompressData(std::vector data) { + // I, too, love the fact that raw bytes are signed and therefore can have negative values. -_- + std::vector signedData = std::vector(data.begin(), data.end()); + + z_stream zs; + memset(&zs, 0, sizeof(zs)); + + if (inflateInit(&zs) != Z_OK) { + return ErrorOr>(true, ErrorCodes::DECOMPRESSION); + //TODO: include error message once implemented + //throw(std::runtime_error("inflateInit failed while decompressing.")); + } + + zs.next_in = reinterpret_cast(reinterpret_cast(signedData.data())); + zs.avail_in = signedData.size(); + + int ret; + char outbuffer[CHUNK_SIZE]; + std::vector decompressedData; + + do { + zs.next_out = reinterpret_cast(outbuffer); + zs.avail_out = CHUNK_SIZE; + + ret = inflate(&zs, 0); + + if (decompressedData.size() < zs.total_out) + decompressedData.insert(decompressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out); + } while (ret == Z_OK); + + inflateEnd(&zs); + + if (ret != Z_STREAM_END) { + return ErrorOr>(true, ErrorCodes::DECOMPRESSION); + //TODO: include error message once implemented + //throw(std::runtime_error("Error while decompressing: " + std::to_string(ret))); + } + + return ErrorOr>(std::vector(decompressedData.begin(), decompressedData.end())); + } - return compressedData; -} - - -std::vector decompressData(const char* data, int size) { - z_stream zs; - memset(&zs, 0, sizeof(zs)); - - if (inflateInit(&zs) != Z_OK) - throw(std::runtime_error("inflateInit failed while decompressing.")); - - zs.next_in = reinterpret_cast(const_cast(data)); - zs.avail_in = size; - - int ret; - char outbuffer[CHUNK_SIZE]; - std::vector decompressedData; - - do { - zs.next_out = reinterpret_cast(outbuffer); - zs.avail_out = CHUNK_SIZE; - - ret = inflate(&zs, 0); - - if (decompressedData.size() < zs.total_out) - decompressedData.insert(decompressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out); - } while (ret == Z_OK); - - inflateEnd(&zs); - - if (ret != Z_STREAM_END) - throw(std::runtime_error("Error while decompressing: " + std::to_string(ret))); - - return decompressedData; } diff --git a/src/lib/zlibutil.hpp b/src/lib/zlibutil.hpp index 3be3de2..861aeb8 100644 --- a/src/lib/zlibutil.hpp +++ b/src/lib/zlibutil.hpp @@ -16,12 +16,12 @@ // version 3 along with this program. // If not, see https://www.gnu.org/licenses/agpl-3.0.en.html +#pragma once + #include +#include "error.hpp" -#ifndef ZLIBUTIL_H -#define ZLIBUTIL_H - -std::vector compressData(const char* data, int size); -std::vector decompressData(const char* data, int size); - -#endif // ZLIBUTIL_H +namespace zlib { + ErrorOr> compressData(std::vector data); + ErrorOr> decompressData(std::vector data); +}