Added an error string set by check() macro.

This commit is contained in:
Aaron Helton
2017-04-16 01:09:15 -04:00
parent fe276fa7b3
commit 3dcb255e74
3 changed files with 44 additions and 31 deletions

View File

@@ -39,9 +39,8 @@ typedef struct NyTGA_Image {
char __padding[7];
} TGAImage; /* SIZEOF == 24 */
TGAError TGA_ERR;
TGAError tga_error(void); /* Returns the current error, if any. */
char *tga_error_str(void); /* Returns a string with error details. */
void tga_clear_error(void);
TGAImage *read_tga_image(FILE *file);
int write_tga_image(TGAImage *image, const char *filename);

View File

@@ -1,3 +1,6 @@
#ifndef _TGA_PRIVATE_H
#define _TGA_PRIVATE_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
@@ -9,38 +12,42 @@
#define TGA_HEADER_SIZE 18
#define TGA_FOOTER_SIZE 26
#define __TGA_SIG_SIZE 18
#define TGA_ERR_MAX 256
#define TRUEVISION_SIG "TRUEVISION-XFILE."
extern TGAError tga_err;
extern char tga_err_string[TGA_ERR_MAX];
/*
* The below macros are used the perform a check on a simple boolean condition.
* The below macros are used to perform a check on a simple boolean condition.
* If the condition is false, assume an error, set the specified error flag, log
* the error if debugging has been enabled, and goto the error section. I've
* done this because I believe it keeps the code easier to read/modify.
* the error if debugging has been enabled, set the error string, and goto the
* error section. I've done this because I believe it keeps the code easier to
* read/modify due to the numerous places where all the above would have to be
* repeated anyway without the macros.
*/
#define errno_str() (errno == 0 ? "NO ERRNO ERROR" : strerror(errno))
#define __ERR_TEXT "[ERROR] (%s:%d - errno: %s) "
#ifndef _TGA_DEBUG
#define check(A, _NY_ERR, ...) \
do { \
if(!(A)) { \
TGA_ERR = _NY_ERR; \
goto error; \
} \
} while(0)
#ifdef _TGA_DEBUG
#define do_print_err(...) \
fprintf(stderr, __ERR_TEXT, __FILE__, __LINE__, errno_str()); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n");
#else
#define check(A, _NY_ERR, ...) \
do { \
if(!(A)) { \
fprintf(stderr, __ERR_TEXT, __FILE__, __LINE__, errno_str()); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
TGA_ERR = _NY_ERR; \
goto error; \
} \
} while(0)
#define do_print_err(...)
#endif/*_TGA_DEBUG*/
#define check(A, _NY_ERR, ...) \
do { \
if(!(A)) { \
tga_err = _NY_ERR; \
do_print_err(__VA_ARGS__); \
snprintf(tga_err_string, TGA_ERR_MAX, __VA_ARGS__); \
goto error; \
} \
} while(0)
/* The below macro is for unimplemented functions, or 'impossible' branches. */
#define fail(_TGA_ERR, ...) check(false, _TGA_ERR, __VA_ARGS__)
@@ -69,3 +76,5 @@ static bool _tga_sanity(TGAImage* image)
{
return image && image->_meta;
}
#endif/*_TGA_PRIVATE_H*/

View File

@@ -4,15 +4,14 @@
#include <TGAImage.h>
#include "Private/TGAPrivate.h"
TGAError tga_err = TGA_NO_ERR;
char tga_err_string[TGA_ERR_MAX] = {0};
static int _allocate_tga_data(TGAImage *image, uint8_t depth,
uint16_t width, uint16_t height)
{
int bytes = (depth + 7)/8;
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGA Image.");
if(!_tga_sanity(image)) {
TGA_ERR = TGA_INV_IMAGE_PNT;
goto error;
}
image->data = malloc(bytes * sizeof(uint8_t) * width * height);
check(image->data, TGA_MEM_ERR, "Out of memory.");
return 1;
@@ -285,12 +284,18 @@ error:
return 0;
}
TGAError tga_error()
TGAError tga_error(void)
{
return TGA_ERR;
return tga_err;
}
void tga_clear_error()
char *tga_error_str(void)
{
TGA_ERR = TGA_NO_ERR;
return tga_err_string;
}
void tga_clear_error(void)
{
tga_err = TGA_NO_ERR;
memset(tga_err_string, 0, TGA_ERR_MAX);
}