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");
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]);
| ---- | ---- | ---- | ---- |
| 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 | |
| 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 |
| ---- | ---- | ---- |
| 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` `<NUL>` `type` `name` `<NUL>` ... `type` `name` `<NUL>` `<NUL>` |
+
+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 |
.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)
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]; }
--- /dev/null
+/* $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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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;
+ }
+}
#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
* @~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
bool __dw_unlockfile(FILE* fp) {
off_t off = ftell(fp);
fseek(fp, 0, SEEK_SET);
+ fflush(fp);
#if defined(DOS)
#elif defined(__MINGW32__)