From 5f109813bb7c5fb09b3d155b693d929e4ecda1a9 Mon Sep 17 00:00:00 2001 From: nishi Date: Wed, 22 May 2024 03:24:38 +0000 Subject: [PATCH] can create table now git-svn-id: file:///raid/svn-main/nishi-dataworks/trunk@67 d4a5a174-5a4a-5b4b-b672-37683c10d7d5 --- Client/main.c | 4 +- FORMATv1.md | 21 ++++--- Library/Makefile | 2 +- Library/database.c | 47 +-------------- Library/database_table.c | 120 +++++++++++++++++++++++++++++++++++++++ Library/dw_database.h | 54 +++++++++++++++++- Library/util.c | 1 + 7 files changed, 189 insertions(+), 60 deletions(-) create mode 100644 Library/database_table.c diff --git a/Client/main.c b/Client/main.c index 3eeb4b7..062d108 100644 --- a/Client/main.c +++ b/Client/main.c @@ -123,7 +123,7 @@ int main(int argc, char** argv) { struct tm* tm = localtime(&mtime); char mtimestr[256]; strftime(mtimestr, 255, "%a %b %d %H:%M:%S %Z %Y", tm); - printf("Opened the database (Version %d, Modified at %s).\n", dataworks_database_get_version(db), mtimestr); + printf("Opened the database (Version %d, Modified at %s).\n", dataworks_database_get_version(db), mtimestr); printf("\n"); printf("Type a command (.help) for the help.\n"); printf("\n"); @@ -160,7 +160,7 @@ int main(int argc, char** argv) { int i; for(i = 0; list[i] != NULL; i++) ; - printf("%d tables found.\n", i); + printf("%d table(s) found.\n", i); for(i = 0; list[i] != NULL; i++) { printf(" %s\n", list[i]); free(list[i]); diff --git a/FORMATv1.md b/FORMATv1.md index b287f59..3da0874 100644 --- a/FORMATv1.md +++ b/FORMATv1.md @@ -18,7 +18,6 @@ Database entry (`dbentry`) MUST be in this format: | ---- | ---- | ---- | ---- | | length | 4 bytes | uint32\_t | Size of the entry | | size | 4 bytes | uint32\_t | | -| type | 1 byte | ASCII | | | flag | 1 byte | uint8\_t | | | field\_index | 1 byte | uint8\_t | | | db\_index | 1 byte | uint8\_t | | @@ -26,15 +25,6 @@ Database entry (`dbentry`) MUST be in this format: | fragnum | 8 bytes | uint64\_t | | | data | \[size\] bytes | ASCII | | -There are 5 types for `dbentry`: -| Type | Character | Type | Info | -| ---- | --------- | ---- | ---- | -| String | `S` | ASCII | | -| Integer | `I` | uint64\_t | | -| Double | `D` | double | | -| Logical | `L` | uint8\_t | 0 for false, other value for true | -| Help | `?` | ASCII | Should be just ignored | - and 2 flags for `dbentry`: | Type | Mask | Info | | ---- | ---- | ---- | @@ -48,7 +38,16 @@ Index entry (`indexentry`) MUST be in this format: | count | 8 bytes | uint64\_t | | | dbname\_len | 1 byte | uint8\_t | | | dbname | 256 bytes | ASCII | | -| fields | 4096 bytes | ASCII | Separate field names using NUL. Put NUL twice on the last field name. | +| fields | 4096 bytes | ASCII | Separate field names using NUL. Put NUL twice on the last field name. Like: `type` `name` `` `type` `name` `` ... `type` `name` `` `` | + +There are 5 types for `indexentry`: +| Type | Character | Type | Info | +| ---- | --------- | ---- | ---- | +| String | `S` | ASCII | | +| Integer | `I` | uint64\_t | | +| Double | `D` | double | | +| Logical | `L` | uint8\_t | 0 for false, other value for true | +| Help | `?` | ASCII | Should be just ignored | There is 1 flag for `indexentry`: | Type | Mask | Info | diff --git a/Library/Makefile b/Library/Makefile index c033494..e11800a 100644 --- a/Library/Makefile +++ b/Library/Makefile @@ -3,7 +3,7 @@ .PHONY: all clean .SUFFIXES: .c .o -OBJS = parser.o database.o util.o dataworks.o +OBJS = parser.o database.o util.o dataworks.o database_table.o all: $(LIB_PREFIX)dataworks$(LIB_SUFFIX) $(STATICLIB_PREFIX)dataworks$(STATICLIB_SUFFIX) diff --git a/Library/database.c b/Library/database.c index a550720..f0e07da 100644 --- a/Library/database.c +++ b/Library/database.c @@ -119,49 +119,6 @@ int dataworks_database_get_version(struct dataworks_db* db) { return db->version uint64_t dataworks_database_get_mtime(struct dataworks_db* db) { return db->mtime; } -#define buffer_to_db_v1_indexentry(buf, index) \ - memcpy(&index.flag, buf, 1); \ - uint64_t be_count; \ - memcpy(&be_count, buf + 1, 8); \ - __dw_native_endian(be_count, uint64_t, index.count = __converted); \ - memcpy(&index.dbname_len, buf + 1 + 8, 1); \ - memcpy(index.dbname, buf + 1 + 8 + 1, 256); \ - memcpy(index.fields, buf + 1 + 8 + 1 + 256, 4096); +const char* dw_errors[] = {"Success", "Used already"}; -char** dataworks_database_get_table_list(struct dataworks_db* db) { - if(db->version == 1) { - __dw_lockfile(db->fp); - fseek(db->fp, sizeof(sig) + 10, SEEK_SET); - int i; - struct dataworks_db_v1_indexentry index; - char* buf = malloc(1 + 8 + 1 + 256 + 4096); - int c = 0; - for(i = 0; i < 256; i++) { - fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); - buffer_to_db_v1_indexentry(buf, index); - if(index.flag & DATAWORKS_V1_INDEXENTRY_USED) { - c++; - } - } - char** list = malloc(sizeof(*list) * (c + 1)); - fseek(db->fp, sizeof(sig) + 10, SEEK_SET); - c = 0; - for(i = 0; i < 256; i++) { - fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); - buffer_to_db_v1_indexentry(buf, index); - if(index.flag & DATAWORKS_V1_INDEXENTRY_USED) { - list[c] = malloc(index.dbname_len + 1); - memcpy(list[c], index.dbname, index.dbname_len); - list[c][index.dbname_len] = 0; - c++; - } - } - list[c] = NULL; - free(buf); - __dw_unlockfile(db->fp); - return list; - } else { - /* Not implemented for the version */ - return NULL; - } -} +const char* dataworks_database_strerror(int n) { return dw_errors[n]; } diff --git a/Library/database_table.c b/Library/database_table.c new file mode 100644 index 0000000..bc2cd58 --- /dev/null +++ b/Library/database_table.c @@ -0,0 +1,120 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* -------------------------------------------------------------------------- */ +/* Copyright (c) 2024 Nishi. */ +/* Redistribution and use in source and binary forms, with or without modific */ +/* ation, are permitted provided that the following conditions are met: */ +/* 1. Redistributions of source code must retain the above copyright noti */ +/* ce, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright n */ +/* otice, this list of conditions and the following disclaimer in the documen */ +/* tation and/or other materials provided with the distribution. */ +/* 3. Neither the name of the copyright holder nor the names of its contr */ +/* ibutors may be used to endorse or promote products derived from this softw */ +/* are without specific prior written permission. */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS */ +/* " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, TH */ +/* E IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPO */ +/* SE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CON */ +/* SEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU */ +/* TE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPT */ +/* ION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, S */ +/* TRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AN */ +/* Y WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY */ +/* OF SUCH DAMAGE. */ +/* -------------------------------------------------------------------------- */ +/* --- END LICENSE --- */ + +#include "dw_database.h" + +#include "dw_util.h" + +#include +#include +#include + +int dataworks_database_create_table(struct dataworks_db* db, const char* name, char** fields, const char* fieldtypes) { + if(db->version == 1) { + __dw_lockfile(db->fp); + fseek(db->fp, 3 + 10, SEEK_SET); + int i; + struct dataworks_db_v1_indexentry index; + char* buf = malloc(1 + 8 + 1 + 256 + 4096); + for(i = 0; i < 256; i++) { + fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); + __dw_buffer_to_db_v1_indexentry(buf, index); + if(index.flag & DATAWORKS_V1_INDEXENTRY_USED) { + char* dbname = malloc(index.dbname_len + 1); + memcpy(dbname, index.dbname, index.dbname_len); + dbname[index.dbname_len] = 0; + if(strcmp(name, dbname) == 0) { + free(dbname); + free(buf); + __dw_unlockfile(db->fp); + return DW_ERR_USED; + } + } + } + fseek(db->fp, 3 + 10, SEEK_SET); + for(i = 0; i < 256; i++) { + fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); + __dw_buffer_to_db_v1_indexentry(buf, index); + if(!(index.flag & DATAWORKS_V1_INDEXENTRY_USED)) { + fseek(db->fp, -(1 + 8 + 1 + 256 + 4096), SEEK_CUR); + buf[0] |= DATAWORKS_V1_INDEXENTRY_USED; + buf[8 + 1] = strlen(name); + memcpy(buf + 1 + 8 + 1, name, strlen(name)); + fwrite(buf, 1, 1 + 8 + 1 + 256, db->fp); + int j; + for(j = 0; fieldtypes[j] != 0; j++) { + fwrite(fieldtypes + j, 1, 1, db->fp); + fwrite(fields[j], 1, strlen(fields[j]), db->fp); + fwrite("\0", 1, 1, db->fp); + } + fwrite("\0", 1, 1, db->fp); + break; + } + } + free(buf); + __dw_unlockfile(db->fp); + } +} + +char** dataworks_database_get_table_list(struct dataworks_db* db) { + if(db->version == 1) { + __dw_lockfile(db->fp); + fseek(db->fp, 3 + 10, SEEK_SET); + int i; + struct dataworks_db_v1_indexentry index; + char* buf = malloc(1 + 8 + 1 + 256 + 4096); + int c = 0; + for(i = 0; i < 256; i++) { + fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); + __dw_buffer_to_db_v1_indexentry(buf, index); + if(index.flag & DATAWORKS_V1_INDEXENTRY_USED) { + c++; + } + } + char** list = malloc(sizeof(*list) * (c + 1)); + fseek(db->fp, 3 + 10, SEEK_SET); + c = 0; + for(i = 0; i < 256; i++) { + fread(buf, 1, 1 + 8 + 1 + 256 + 4096, db->fp); + __dw_buffer_to_db_v1_indexentry(buf, index); + if(index.flag & DATAWORKS_V1_INDEXENTRY_USED) { + list[c] = malloc(index.dbname_len + 1); + memcpy(list[c], index.dbname, index.dbname_len); + list[c][index.dbname_len] = 0; + c++; + } + } + list[c] = NULL; + free(buf); + __dw_unlockfile(db->fp); + return list; + } else { + /* Not implemented for the version */ + return NULL; + } +} diff --git a/Library/dw_database.h b/Library/dw_database.h index 7777781..b8ee6a6 100644 --- a/Library/dw_database.h +++ b/Library/dw_database.h @@ -49,6 +49,35 @@ extern "C" { #define PACKED __attribute__((__packed__)) #endif +#define __dw_buffer_to_db_v1_indexentry(buf, index) \ + memcpy(&index.flag, buf, 1); \ + uint64_t be_count; \ + memcpy(&be_count, buf + 1, 8); \ + __dw_native_endian(be_count, uint64_t, index.count = __converted); \ + memcpy(&index.dbname_len, buf + 1 + 8, 1); \ + memcpy(index.dbname, buf + 1 + 8 + 1, 256); \ + memcpy(index.fields, buf + 1 + 8 + 1 + 256, 4096); + +/** + * @~english + * @brief Error enum + * + */ +enum DW_ERRORS { + /** + * @~english + * @brief Success + * + */ + DW_ERR_SUCCESS = 0, + /** + * @~english + * @brief Used already + * + */ + DW_ERR_USED +}; + /** * @~english * @brief Database struct @@ -155,11 +184,34 @@ uint64_t dataworks_database_get_mtime(struct dataworks_db* db); * @~english * @brief Get the table list of the database. * @param db Database - * @return Table list of the databas + * @return Table list of the database * */ char** dataworks_database_get_table_list(struct dataworks_db* db); +/** + * @~english + * @brief Creates a table. + * @param db Database + * @param name Table name + * @param fields Fields + * @param fieldtypes Types + * @return + * - `0` if success + * - `DW_ERR_USED` if the name is already used + * + */ +int dataworks_database_create_table(struct dataworks_db* db, const char* name, char** fields, const char* fieldtypes); + +/** + * @~english + * @brief Converts error number to a string. + * @param n Error number + * @return Error string + * + */ +const char* dataworks_database_strerror(int n); + #ifdef __cplusplus } #endif diff --git a/Library/util.c b/Library/util.c index 554ea12..b66e809 100644 --- a/Library/util.c +++ b/Library/util.c @@ -72,6 +72,7 @@ bool __dw_lockfile(FILE* fp) { bool __dw_unlockfile(FILE* fp) { off_t off = ftell(fp); fseek(fp, 0, SEEK_SET); + fflush(fp); #if defined(DOS) #elif defined(__MINGW32__) -- 2.43.0