From a6c39e68f93c080d32741b68d60db953902eda2d Mon Sep 17 00:00:00 2001 From: Meutel Date: Sun, 1 Jan 2017 15:44:51 +0100 Subject: [PATCH] Book data (file) --- db.c | 118 ++++++++++++++++++++++++++++++++++++++++++------------- extern.h | 31 +++++++++------ main.c | 20 ++++++++-- 3 files changed, 128 insertions(+), 41 deletions(-) diff --git a/db.c b/db.c index 863c833..15fee04 100644 --- a/db.c +++ b/db.c @@ -31,6 +31,7 @@ enum stmt { STMT_BOOK, STMT_BOOK_AUTHORS, + STMT_BOOK_DATA, STMT_BOOKS, STMT_BOOKS_COUNT, STMT_BOOKS_AUTHORS, @@ -41,7 +42,7 @@ static const char *const stmts[STMT__MAX] = { /* STMT_BOOK */ "SELECT books.id AS id,title, series_index, series.name AS series_name, series.id AS series_id, \ strftime('%s', timestamp), strftime('%Y', pubdate), isbn,lccn,path,uuid,has_cover, \ - languages.lang_code,format,uncompressed_size,data.name AS data_name, publishers.name AS pubname FROM books \ + languages.lang_code, publishers.name AS pubname FROM books \ LEFT OUTER JOIN books_languages_link ON books_languages_link.book = books.id \ LEFT OUTER JOIN languages ON languages.id = books_languages_link.lang_code \ LEFT OUTER JOIN data ON data.book = books.id \ @@ -54,6 +55,9 @@ static const char *const stmts[STMT__MAX] = { "SELECT authors.id, authors.name, books_authors_link.book as book \ FROM authors, books_authors_link WHERE books_authors_link.author = authors.id \ AND books_authors_link.book = ?", + /* STMT_BOOK_DATA */ + "SELECT data.name, data.format, data.uncompressed_size \ + FROM data WHERE data.book = ?", /* STMT_BOOKS */ "SELECT books.id AS id,title,series_index,name as series_name,series.id AS series_id \ FROM books LEFT OUTER JOIN books_series_link ON books.id = books_series_link.book \ @@ -75,6 +79,15 @@ struct bookauth { struct bookauth *p; }; +/* + * Linked list book data. + */ +struct bookdata { + BookData *d; + BookFull *b; + struct bookdata *p; +}; + static char * strornull(struct ksqlstmt *stmt, int col) { @@ -114,6 +127,14 @@ db_author_unfill(Author *p) { free(p->name); } +static void +db_book_data_unfill(BookData *p) { + if (NULL == p) + return; + free(p->name); + free(p->format); +} + void db_book_free(Book *p) { @@ -138,13 +159,14 @@ db_book_full_unfill(BookFull *p) { if (NULL == p) return; + for (size_t i = 0; i < p->dsize; i++) { + db_book_data_unfill(p->data[i]); + } free(p->isbn); free(p->lccn); free(p->path); free(p->uuid); free(p->lang); - free(p->format); - free(p->dataname); free(p->publisher); } @@ -269,12 +291,73 @@ db_books_load(struct kreq *r, BookAdv **books, int limit, int offset) return count; } +static void +db_book_full_authors(BookAdv *b, struct kreq *r, int64_t id) { + struct ksqlstmt *stmt; + struct bookauth *p = NULL; + struct bookauth *item = NULL; + + ksql_stmt_alloc(r->arg, &stmt, + stmts[STMT_BOOK_AUTHORS], + STMT_BOOK_AUTHORS); + ksql_bind_int(stmt, 0, id); + while (KSQL_ROW == ksql_stmt_step(stmt)) { + item = kcalloc(1, sizeof(struct bookauth)); + item->a = kcalloc(1, sizeof(Author)); + item->a->id = ksql_stmt_int(stmt, 0); + item->a->name = kstrdup(ksql_stmt_str(stmt, 1)); + item->b = b; + item->b->asize++; + item->p = p; + p = item; + } + // assign authors to book + db_assign_book_authors(p); + + ksql_stmt_free(stmt); +} + +static void +db_book_full_data(BookFull *b, struct kreq *r, int64_t id) { + struct ksqlstmt *stmt; + struct bookdata *p = NULL; + struct bookdata *item = NULL; + + ksql_stmt_alloc(r->arg, &stmt, + stmts[STMT_BOOK_DATA], + STMT_BOOK_DATA); + ksql_bind_int(stmt, 0, id); + while (KSQL_ROW == ksql_stmt_step(stmt)) { + item = kcalloc(1, sizeof(struct bookdata)); + item->d = kcalloc(1, sizeof(BookData)); + item->d->name = kstrdup(ksql_stmt_str(stmt, 0)); + item->d->format = kstrdup(ksql_stmt_str(stmt, 1)); + item->d->size = ksql_stmt_int(stmt, 2); + item->b = b; + item->b->dsize++; + item->p = p; + p = item; + } + + ksql_stmt_free(stmt); + + while (NULL != p) { + if (NULL != p->b && NULL == p->b->data && p->b->dsize > 0) { + p->b->data = kcalloc(p->b->dsize, sizeof(BookData)); + p->b->dsize = 0; // use as counter for insert + } + p->b->data[p->b->dsize] = p->d; + p->b->dsize++; + item = p; + p = p->p; + free(item); + } +} + BookFull * db_book_load(struct kreq *r, int64_t id) { struct ksqlstmt *stmt; - struct bookauth *p = NULL; - struct bookauth *item = NULL; BookFull *book; ksql_stmt_alloc(r->arg, &stmt, @@ -296,31 +379,12 @@ db_book_load(struct kreq *r, int64_t id) book->uuid = strornull(stmt, 10); book->has_cover = ksql_stmt_int(stmt, 11); book->lang = strornull(stmt, 12); - book->format = strornull(stmt, 13); - book->unz_size = ksql_stmt_int(stmt, 14); - book->dataname = strornull(stmt, 15); - book->publisher = strornull(stmt, 16); + book->publisher = strornull(stmt, 13); ksql_stmt_free(stmt); - ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_BOOK_AUTHORS], - STMT_BOOK_AUTHORS); - ksql_bind_int(stmt, 0, id); - while (KSQL_ROW == ksql_stmt_step(stmt)) { - item = kcalloc(1, sizeof(struct bookauth)); - item->a = kcalloc(1, sizeof(Author)); - item->a->id = ksql_stmt_int(stmt, 0); - item->a->name = kstrdup(ksql_stmt_str(stmt, 1)); - item->b = &book->ba; - item->b->asize++; - item->p = p; - p = item; - } - // assign authors to book - db_assign_book_authors(p); - - ksql_stmt_free(stmt); + db_book_full_authors(&book->ba, r, id); + db_book_full_data(book, r, id); return book; } diff --git a/extern.h b/extern.h index 60f344a..742cd5b 100644 --- a/extern.h +++ b/extern.h @@ -46,6 +46,16 @@ typedef struct char *name; } Author; +/* + * Downloadable book data. + */ +typedef struct +{ + int64_t size; + char *format; + char *name; +} BookData; + /* * A book. Advanced data: authors, tags. */ @@ -60,6 +70,8 @@ typedef struct typedef struct { BookAdv ba; + BookData **data; + size_t dsize; int64_t timestamp; int64_t pubdate; char *isbn; @@ -68,27 +80,24 @@ typedef struct char *uuid; int64_t has_cover; char *lang; - char *format; - char *dataname; - int64_t unz_size; char *publisher; } BookFull; __BEGIN_DECLS BookFull *db_book_load(struct kreq *r, int64_t id); -int db_books_load(struct kreq *r, BookAdv **books, int limit, int offset); -int db_books_count(struct kreq *r); -void db_book_free(Book *p); -void db_book_adv_free(BookAdv *p); -void db_book_full_free(BookFull *p); +int db_books_load(struct kreq *r, BookAdv **books, int limit, int offset); +int db_books_count(struct kreq *r); +void db_book_free(Book *p); +void db_book_adv_free(BookAdv *p); +void db_book_full_free(BookFull *p); -void db_series_free(Series *p); +void db_series_free(Series *p); -void db_close(struct kreq *); +void db_close(struct kreq *); int db_open(struct kreq *, const char *); -void json_emptydoc(struct kreq *); +void json_emptydoc(struct kreq *); __END_DECLS diff --git a/main.c b/main.c index 90a2233..71464a3 100644 --- a/main.c +++ b/main.c @@ -127,6 +127,22 @@ putbook(struct kjsonreq *req, Book *b) } } +static void +putbookdata(struct kjsonreq *req, BookFull *b) +{ + if (b->dsize > 0) { + kjson_arrayp_open(req, "data"); + for (size_t i=0;idsize;i++) { + kjson_obj_open(req); + kjson_putstringp(req, "name", b->data[i]->name); + kjson_putstringp(req, "format", b->data[i]->format); + kjson_putintp(req, "size", b->data[i]->size); + kjson_obj_close(req); + } + kjson_array_close(req); + } +} + static void putauthors(struct kjsonreq *req, BookAdv *b) { @@ -155,9 +171,6 @@ putbookfull(struct kjsonreq *req, BookFull *b) kjson_putstringp(req, "uuid", b->uuid); kjson_putboolp(req, "has_cover", b->has_cover); kjson_putstringp(req, "lang", b->lang); - kjson_putstringp(req, "format", b->format); - kjson_putstringp(req, "data", b->dataname); - kjson_putintp(req, "uncompressed_size", b->unz_size); if (NULL != b->publisher) kjson_putstringp(req, "publisher", b->publisher); } @@ -189,6 +202,7 @@ sendbooks(struct kreq *r) } else if (NULL != b) { putbookfull(&req, b); putauthors(&req, &b->ba); + putbookdata(&req, b); kjson_obj_close(&req); db_book_full_free(b); } else {