Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define and expose user-defined error handler #156

Merged
merged 12 commits into from
Aug 17, 2022
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;


/**
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an empty line before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* 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:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let this empty line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


/**
* 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) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, see README.md

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