Skip to content

Commit

Permalink
impl last error
Browse files Browse the repository at this point in the history
  • Loading branch information
nna774 committed Jul 28, 2021
1 parent 45ea715 commit 829bd94
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 15 deletions.
7 changes: 7 additions & 0 deletions _cgo/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdbool.h>

typedef struct exif_value {
char *name;
char *value;
Expand All @@ -30,3 +32,8 @@ typedef struct exif_value {
typedef struct exif_stack {
struct exif_value* head;
} exif_stack_t;

typedef struct logging_option {
bool show_debug_message;
bool detail_error;
} logging_option_t;
37 changes: 29 additions & 8 deletions exif.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ package exif
exif_value_t* pop_exif_value(exif_stack_t *);
void free_exif_value(exif_value_t* n);
exif_stack_t* exif_dump(ExifData *);
void set_exif_log(ExifLog *log);
void set_exif_log(ExifLog *log, logging_option_t* opt);
ExifLogCode last_exif_log_code();
*/
import "C"

Expand All @@ -48,13 +49,16 @@ import (
var (
ErrNoExifData = errors.New(`no EXIF data found`)
ErrFoundExifInData = errors.New(`found EXIF header. OK to call Parse`)
ErrNoMemory = errors.New(`not enough memory`)
ErrCorruptData = errors.New(`data provided does not follow the specification`)
)

// Data stores the EXIF tags of a file.
type Data struct {
exifLoader *C.ExifLoader
exifLog *C.ExifLog
loggingEnabled bool
option *LoggingOption
Tags map[string]string
}

Expand Down Expand Up @@ -116,9 +120,16 @@ func (d *Data) Write(p []byte) (n int, err error) {
runtime.SetFinalizer(d, (*Data).cleanup)
}
if d.loggingEnabled && d.exifLog == nil {
if d.option == nil {
d.option = &LoggingOption{}
}
d.exifLog = C.exif_log_new()
C.exif_loader_log(d.exifLoader, d.exifLog)
C.set_exif_log(d.exifLog)
opt := C.logging_option_t{
show_debug_message: (C.bool)(d.option.ShowDebugMessage),
detail_error: (C.bool)(d.option.DetailError),
}
C.set_exif_log(d.exifLog, (*C.logging_option_t)(unsafe.Pointer(&opt)))
C.exif_log_ref(d.exifLog)
// cleanup will be defered by above
}
Expand All @@ -128,7 +139,17 @@ func (d *Data) Write(p []byte) (n int, err error) {
if res == 1 {
return len(p), nil
}
return len(p), ErrFoundExifInData

// if logging not enabled, code is always EXIF_LOG_CODE_NONE. so return ErrFoundExifInData(successful value)
code := C.last_exif_log_code()
if code == C.EXIF_LOG_CODE_NO_MEMORY {
err = ErrNoMemory
} else if code == C.EXIF_LOG_CODE_CORRUPT_DATA {
err = ErrCorruptData
} else {
err = ErrFoundExifInData
}
return len(p), err
}

// Parse finalizes the data loader and sets the tags
Expand Down Expand Up @@ -158,12 +179,12 @@ func (d *Data) cleanup() {
}
}

type LoggingOption struct{}
type LoggingOption struct {
ShowDebugMessage bool
DetailError bool
}

func (d *Data) EnableLogging(opt *LoggingOption) {
d.loggingEnabled = true
}

func (d *Data) DisableLogging() {
d.loggingEnabled = false
d.option = opt
}
35 changes: 29 additions & 6 deletions exif_c.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,35 @@ exif_stack_t* exif_dump(ExifData* data) {
return user_data;
}

void show_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args, void* _) {
printf("domain %s: %s: %s\n ", domain, exif_log_code_get_title(code), exif_log_code_get_message (code));
vprintf(format, args);
puts("");
typedef struct {
logging_option_t* opt;
ExifLogCode* last_code;
} logfunc_data_t;

void show_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args, void* vdata) {
logfunc_data_t* data = vdata;
if (data->opt->show_debug_message) {
printf("domain %s: %s: %s\n ", domain, exif_log_code_get_title(code), exif_log_code_get_message (code));
vprintf(format, args);
puts("");
}
if (data->opt->detail_error && code != EXIF_LOG_CODE_NONE) {
*(data->last_code) = code;
}
}

logfunc_data_t* logfunc_data() { // hold logfunc_data_t like global val
static ExifLogCode code = EXIF_LOG_CODE_NONE;
static logfunc_data_t data = {NULL, &code};
return &data;
}

ExifLogCode last_exif_log_code() {
return *(logfunc_data()->last_code);
}

void set_exif_log(ExifLog *log) {
exif_log_set_func(log, show_log, NULL);
void set_exif_log(ExifLog *log, logging_option_t* opt) {
logfunc_data_t* d = logfunc_data();
d->opt = opt;
exif_log_set_func(log, show_log, d);
}
14 changes: 13 additions & 1 deletion exif_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package exif

import (
"fmt"
"github.com/stretchr/testify/assert"
"io"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestOpen(t *testing.T) {
Expand Down Expand Up @@ -76,3 +77,14 @@ func TestGetLatitude(t *testing.T) {

assert.Equal(t, "25, 21, 32.6101", latitude)
}

func TestBrokenExif(t *testing.T) {
exif := New()
exif.EnableLogging(&LoggingOption{ShowDebugMessage: true, DetailError: true})
file, err := os.Open("_examples/resources/broken_exif.jpg")
assert.NoError(t, err)
defer file.Close()
_, err = io.Copy(exif, file)
assert.Error(t, err)
assert.Equal(t, ErrCorruptData, err)
}

0 comments on commit 829bd94

Please sign in to comment.