diff --git a/src/database.c b/src/database.c index 2ff2356..a874095 100644 --- a/src/database.c +++ b/src/database.c @@ -250,6 +250,36 @@ simdb_record_used(simdb_t *db, int num) { return ret; } +int +simdb_record_add(simdb_t *db, int num, const char *path, int flags) { + simdb_urec_t *rec = NULL; + + assert(db != NULL); + + if (num < 0 || path == NULL) + return SIMDB_ERR_USAGE; + + if (flags & SIMDB_ADD_NOEXTEND && num > db->records) + return 0; + + if (access(path, R_OK) < 0) + return SIMDB_ERR_SYSTEM; + + if (num > 0 && flags & SIMDB_ADD_NOREPLACE && simdb_record_used(db, num)) + return 0; + + if ((rec = simdb_record_create(path)) == NULL) + return SIMDB_ERR_SAMPLER; + + if (num == 0) + num = db->records + 1; + + num = simdb_write(db, num, 1, rec); + + FREE(rec); + return num; +} + int simdb_record_del(simdb_t *db, int num) { simdb_urec_t *rec; diff --git a/src/record.h b/src/record.h index f60803b..1a5b3b7 100644 --- a/src/record.h +++ b/src/record.h @@ -18,4 +18,11 @@ typedef struct __attribute__((__packed__)) { typedef char size_mismatch_for__simdb_urec_t[(sizeof(simdb_urec_t) == SIMDB_REC_LEN) * 2 - 1]; +/** + * @brief Creates metadata record from given image + * @param path Path to source image + * @returns Pointer to allocated record or NULL on error + */ +simdb_urec_t * simdb_record_create(const char * const path); + #endif /* RECORD_H */ diff --git a/src/samplers/dummy.c b/src/samplers/dummy.c index bfc8488..a2a701c 100644 --- a/src/samplers/dummy.c +++ b/src/samplers/dummy.c @@ -2,13 +2,11 @@ #include "../record.h" #include "../simdb.h" -bool -simdb_record_create(void *rec, const char * const source) { - assert(rec != NULL); - assert(source != NULL); +simdb_urec_t * +simdb_record_create(const char * const path) { + assert(path != NULL); - (void)(rec); - (void)(source); + (void)(path); - return false; + return NULL; } diff --git a/src/samplers/magick.c b/src/samplers/magick.c index 83c1c89..dd8c408 100644 --- a/src/samplers/magick.c +++ b/src/samplers/magick.c @@ -5,22 +5,21 @@ #include -bool -simdb_record_create(void * r, const char * const source) { +simdb_urec_t * +simdb_record_create(const char * const path) { MagickWand *wand = NULL; MagickPassFail status = MagickPass; uint16_t w = 0, h = 0; size_t buf_size = 64 * sizeof(char); unsigned char *buf = NULL; - simdb_urec_t *rec = r; + simdb_urec_t *rec = NULL; - assert(rec != NULL); - assert(source != NULL); + assert(path != NULL); InitializeMagick("/"); wand = NewMagickWand(); if (status == MagickPass) - status = MagickReadImage(wand, source); + status = MagickReadImage(wand, path); if (status == MagickPass) w = MagickGetImageWidth(wand); @@ -83,11 +82,12 @@ simdb_record_create(void * r, const char * const source) { if (status == MagickPass) { assert(buf_size == SIMDB_BITMAP_SIZE); - memset(rec, 0x0, sizeof(simdb_urec_t)); - rec->used = 0xFF; - rec->image_w = w; - rec->image_h = h; - memcpy(rec->bitmap, buf, SIMDB_BITMAP_SIZE); + if ((rec = calloc(1, sizeof(simdb_urec_t))) != NULL) { + rec->used = 0xFF; + rec->image_w = w; + rec->image_h = h; + memcpy(rec->bitmap, buf, SIMDB_BITMAP_SIZE); + } #ifdef DEBUG } else { ExceptionType severity = 0; @@ -99,5 +99,5 @@ simdb_record_create(void * r, const char * const source) { DestroyMagickWand(wand); DestroyMagick(); - return (status == MagickPass) ? true : false; + return rec; } diff --git a/src/simdb-write.c b/src/simdb-write.c index d0f5631..18c76d2 100644 --- a/src/simdb-write.c +++ b/src/simdb-write.c @@ -83,13 +83,11 @@ int main(int argc, char **argv) case add : if (num == 0 || sample == NULL) usage(EXIT_FAILURE); - if (!simdb_record_create(&rec, sample)) { - fprintf(stderr, "sampler failure\n"); - exit(EXIT_FAILURE); - } - if ((err = simdb_write(db, num, 1, (void *) &rec)) < 1) { + if ((err = simdb_record_add(db, num, sample, 0)) < 0) { fprintf(stderr, "%s\n", simdb_error(err)); exit(EXIT_FAILURE); + } else { + fprintf(stderr, "added as record #%d", err); } break; case del : diff --git a/src/simdb.h b/src/simdb.h index ae6126d..ee3f6ae 100644 --- a/src/simdb.h +++ b/src/simdb.h @@ -24,6 +24,13 @@ /* 3 used, 5 reserved */ /** @} */ +/** + * @defgroup SIMDBAddModifiers Flags for simdb_record_add() call + * @{ */ +#define SIMDB_ADD_NOREPLACE 1 << (0 + 0) /**< don't replace existing record */ +#define SIMDB_ADD_NOEXTEND 1 << (0 + 1) /**< don't extend database if @a num greater than existing records count */ +/** @} */ + /** * @defgroup SIMDBErrors Database error codes * @{ */ @@ -114,11 +121,18 @@ int simdb_search(simdb_t * const db, int num, bool simdb_record_used(simdb_t *db, int num); /** - * @brief Create record from image file + * @brief Create an record from image file + * @param db Database handle + * @param num Number of record to add / replace * @param path Path to source image - * @returns Pointer to newly created record or NULL on error + * @param flags Modifier flags. See @a SIMDBAddModifiers group for possible values. + * @retval <0 on error + * @retval 0 if @a num > 0, SIMDB_ADD_NOEXPAND flag set, but record not exists + * or if @a num > 0, SIMDB_ADD_NOREPLACE flag set, and record already used + * @retval >0 if record added successfully + * @note setting @a num to zero means "append to end" */ -bool simdb_record_create(void * rec, const char *path); +int simdb_record_add(simdb_t *db, int num, const char *path, int flags); /** * @brief Delete a record from database by num diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3aef81d..1e09785 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,5 +4,5 @@ add_test("test/bitmap" "test-bitmap") add_executable("test-record" "record.c") add_test("test/record" "test-record") -add_executable("test-io" "io.c" "../src/database.c" "../src/bitmap.c") +add_executable("test-io" "io.c" "../src/database.c" "../src/bitmap.c" "../src/samplers/dummy.c") add_test("test/io" "test-io")