Skip to content

Commit

Permalink
Merge pull request #156 from flomnes/feature/user-defined-error-handler
Browse files Browse the repository at this point in the history
Define and expose user-defined error handler
  • Loading branch information
ctabin authored Aug 17, 2022
2 parents c05c7fe + dde5462 commit e66c448
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 21 deletions.
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,31 @@ int main(int argc, char** argv) {

### Error handling

Actually the error handling is pretty basic and the errors details are dumped to `stderr`.
It is possible to override the macro `LIBZIPPP_ERROR_DEBUG` in order to handle the errors in
some custom way.
By default, the error handling is pretty basic and the errors details are dumped to `stderr`. However, it is possible to provide a callback method to override this behavior. If some context is required, you may use `std::bind` or lambda-functions.

```C++
#define LIBZIPPP_ERROR_DEBUG(str, errormsg) fprintf(stderr, str "\n", errormsg);
#include "libzippp.h"
using namespace libzippp;

int main(int argc, char** argv) {
ZipArchive zf("archive.zip");
zf.setErrorHandlerCallback([](const std::string& message,
int zip_error_code,
int system_error_code)
{
// Handle error here
});

zf.open(ZipArchive::Write);
zf.addEntry("folder/subdir/");

const char* textData = "Hello,World!";
zf.addData("helloworld.txt", textData, 12);

zf.close();

return 0;
}
```
## Known issues
Expand Down
48 changes: 36 additions & 12 deletions src/libzippp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ using namespace std;

#define NEW_CHAR_ARRAY(nb) new (std::nothrow) char[(nb)];

namespace Helper {
static void callErrorHandlingCallback(zip* zipHandle, const std::string& msg, const ErrorHandlerCallback& callback) {
int error_code_zip, error_code_system;
zip_error_get(zipHandle, &error_code_zip, &error_code_system);
callback(msg, error_code_zip, error_code_system);
}

static void callErrorHandlingCallback(zip_error_t* error, const std::string& msg, const ErrorHandlerCallback& callback) {
int error_code_zip, error_code_system;
error_code_zip = zip_error_code_zip(error);
error_code_system = zip_error_code_system(error);
callback(msg, error_code_zip, error_code_system);
}
}

static void defaultErrorHandler(const std::string& message,
int zip_error_code,
int system_error_code)
{
zip_error_t error;
zip_error_init(&error);
zip_error_set(&error, zip_error_code, system_error_code);
fprintf(stderr, message.c_str(), zip_error_strerror(&error));
zip_error_fini(&error);
}

ZipEntry::ZipEntry(void) : zipFile(nullptr), index(0), time(0), compressionMethod(ZIP_CM_DEFAULT), encryptionMethod(ZIP_EM_NONE), size(0), sizeComp(0), crc(0) {
}

Expand Down Expand Up @@ -84,7 +110,7 @@ int ZipEntry::readContent(std::ostream& ofOutput, ZipArchive::State state, libzi
return zipFile->readEntry(*this, ofOutput, state, chunksize);
}

ZipArchive::ZipArchive(const string& zipPath, const string& password, Encryption encryptionMethod) : path(zipPath), zipHandle(nullptr), zipSource(nullptr), mode(NotOpen), password(password), progressPrecision(LIBZIPPP_DEFAULT_PROGRESSION_PRECISION), bufferData(nullptr), bufferLength(0) {
ZipArchive::ZipArchive(const string& zipPath, const string& password, Encryption encryptionMethod) : path(zipPath), zipHandle(nullptr), zipSource(nullptr), mode(NotOpen), password(password), progressPrecision(LIBZIPPP_DEFAULT_PROGRESSION_PRECISION), bufferData(nullptr), bufferLength(0), errorHandlingCallback(defaultErrorHandler) {
switch(encryptionMethod) {
#ifdef LIBZIPPP_WITH_ENCRYPTION
case Encryption::Aes128:
Expand Down Expand Up @@ -159,7 +185,7 @@ bool ZipArchive::openBuffer(void** data, libzippp_uint32 size, OpenMode om, bool
/* create source from buffer */
zip_source* localZipSource = zip_source_buffer_create(*data, size, 0, &error);
if (localZipSource == nullptr) {
LIBZIPPP_ERROR_DEBUG("can't create zip source: %s\n", zip_error_strerror(&error));
Helper::callErrorHandlingCallback(&error, "can't create zip source: %s\n", errorHandlingCallback);
zip_error_fini(&error);
return false;
}
Expand Down Expand Up @@ -196,7 +222,7 @@ bool ZipArchive::openSource(zip_source* source, OpenMode om, bool checkConsisten
/* open zip archive from source */
zipHandle = zip_open_from_source(source, zipFlag, &error);
if (zipHandle == nullptr) {
LIBZIPPP_ERROR_DEBUG("can't open zip from source: %s", zip_error_strerror(&error))
Helper::callErrorHandlingCallback(&error, "can't open zip from source: %s",errorHandlingCallback);
zip_error_fini(&error);
return false;
}
Expand Down Expand Up @@ -236,14 +262,12 @@ bool ZipArchive::open(OpenMode om, bool checkConsistency) {

//error during opening of the file
if (errorFlag!=ZIP_ER_OK) {
zip_error_t error;
zip_error_init_with_code(&error, errorFlag);
Helper::callErrorHandlingCallback(&error, "unable to open archive: %s", errorHandlingCallback);
zip_error_fini(&error);

zipHandle = nullptr;

{
zip_error_t error;
zip_error_init_with_code(&error, errorFlag);
LIBZIPPP_ERROR_DEBUG("Unable to open archive: %s", zip_error_strerror(&error));
zip_error_fini(&error);
}
return false;
}

Expand Down Expand Up @@ -309,7 +333,7 @@ int ZipArchive::close(void) {
zip_int64_t newLength = bufferLength + increment;
sourceBuffer = realloc(sourceBuffer, newLength * sizeof(char));
if(sourceBuffer==nullptr) {
LIBZIPPP_ERROR_DEBUG("can't read back from source: %s", "unable to extend buffer")
Helper::callErrorHandlingCallback(zipHandle, "can't read back from source: unable to extend buffer", errorHandlingCallback);
return LIBZIPPP_ERROR_MEMORY_ALLOCATION;
}

Expand All @@ -327,7 +351,7 @@ int ZipArchive::close(void) {
*bufferData = sourceBuffer;
bufferLength = totalRead;
} else {
LIBZIPPP_ERROR_DEBUG("can't read back from source: %s", "changes were not pushed in the buffer")
Helper::callErrorHandlingCallback(zipHandle, "can't read back from source: changes were not pushed in the buffer", errorHandlingCallback);
return srcOpen;
}

Expand Down
22 changes: 17 additions & 5 deletions src/libzippp.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ struct zip_source;
#define LIBZIPPP_DEFAULT_CHUNK_SIZE 524288
#define LIBZIPPP_DEFAULT_PROGRESSION_PRECISION 0.5

// allow custom debug handling when errors occurs in libzippp
#define LIBZIPPP_ERROR_DEBUG(str, errormsg) fprintf(stderr, (str"\n"), (errormsg));

//libzip documentation
//- http://www.nih.at/libzip/libzip.html
//- http://slash.developpez.com/tutoriels/c/utilisation-libzip/
Expand Down Expand Up @@ -99,14 +96,22 @@ struct zip_source;
namespace libzippp {
class ZipEntry;
class ZipProgressListener;


/**
* User-defined error-handler.
* See https://libzip.org/documentation/zip_error_system_type.html
*/
using ErrorHandlerCallback = std::function<void(const std::string& message,
int zip_error_code,
int system_error_code)>;

/**
* Represents a ZIP archive. This class provides useful methods to handle an archive
* content. It is simply a wrapper around libzip.
*/
class LIBZIPPP_API ZipArchive {
public:

/**
* Defines how the zip file must be open.
* NotOpen is a special mode where the file is not open.
Expand Down Expand Up @@ -526,6 +531,10 @@ namespace libzippp {
inline double getProgressPrecision(void) const { return progressPrecision; }
void setProgressPrecision(double p) { progressPrecision = p; }

void setErrorHandlerCallback(const ErrorHandlerCallback& callback) {
errorHandlingCallback = callback;
}

private:
std::string path;
zip* zipHandle;
Expand All @@ -538,6 +547,9 @@ namespace libzippp {

void** bufferData;
libzippp_uint64 bufferLength;

// User-defined error handler
ErrorHandlerCallback errorHandlingCallback;

//open from in-memory data
bool openBuffer(void** buffer, libzippp_uint32 sz, OpenMode mode=ReadOnly, bool checkConsistency=false);
Expand Down

0 comments on commit e66c448

Please sign in to comment.