diff --git a/src/pit.c b/src/pit.c index 5e016c6..eda905f 100644 --- a/src/pit.c +++ b/src/pit.c @@ -1,7 +1,7 @@ -#include "pit.h" #include #include #include +#include "pit.h" static int usage() { printf("usage...\n"); diff --git a/src/project.c b/src/project.c index c91e23b..dfd3d8b 100644 --- a/src/project.c +++ b/src/project.c @@ -1,8 +1,8 @@ -#include "pit.h" -#include "project.h" #include #include #include +#include "pit.h" +#include "project.h" int pit_project(char *argv[]) { char **arg = &argv[1]; diff --git a/src/table.c b/src/table.c index 80362e0..8da6be9 100755 --- a/src/table.c +++ b/src/table.c @@ -1,26 +1,16 @@ -#include "pit.h" -#include "table.h" #include #include #include #include +#include "pit.h" +#include "table.h" -#define TABLE_INCREMENT 50 +#define TABLE_INCREMENT 5 #define TABLE_HAS_ID 1 #define TABLE_HAS_CREATED_AT 2 #define TABLE_HAS_UPDATED_AT 4 #define TABLE_HAS_TIMESTAMPS (TABLE_HAS_CREATED_AT | TABLE_HAS_UPDATED_AT) -typedef struct { - ulong flags; /* Bit mask with table flags */ - ulong record_size; /* Record size in bytes; all records are of fixed size */ - ulong number_of_slots; /* Number of slots allocated, each slot is 'record_size' long */ - ulong number_of_records; /* Number of records currently stored in slots */ - ulong auto_increment; /* Current value of record id */ - uchar *slots; /* Memory chunk to store records; compacted when a record gets deleted (no holes) */ - uchar **index; /* Memory chunk to store pointers to individual records, holes for deleted record ids */ -} Table, *PTable; - /* ** Initialize the table by alloocating necessary memory chunks. */ @@ -42,14 +32,14 @@ PTable table_initialize(ulong record_size, ulong flags) { /* ** Return the address of next avaiable slot within pt->slots chunk. */ -uchar *table_available_slot(PTable pt) { +static uchar *table_available_slot(PTable pt) { return pt->slots + pt->number_of_records * pt->record_size; } /* ** Return the address of last stored record. */ -uchar *table_last_record(PTable pt) { +static uchar *table_last_record(PTable pt) { if (pt->number_of_records == 0) { return pt->slots; } else { @@ -60,14 +50,14 @@ uchar *table_last_record(PTable pt) { /* ** Return the address of next available pointer within pt->index chunk. */ -uchar **table_available_index(PTable pt) { +static uchar **table_available_index(PTable pt) { return pt->index + pt->auto_increment; } /* ** Return the address of last pointer within pt->index chunk. */ -uchar **table_last_index(PTable pt) { +static uchar **table_last_index(PTable pt) { if (pt->auto_increment == 0) { return pt->index; } else { @@ -81,28 +71,29 @@ uchar **table_last_index(PTable pt) { ** of empty indices to the the pt->index chunk. Finally, we adjust ** existing indices to make them point to reallocated record slots. */ -PTable table_extend(PTable pt) { +static PTable table_extend(PTable pt) { register ulong i; register uchar **pi; - puts("EXTENDING...\n"); pt->number_of_slots += TABLE_INCREMENT; - - /* Re-allocate the records and set newly added memory chunk to 0. */ + /* + ** Re-allocate the records and set newly added memory chunk to 0. + */ pt->slots = realloc(pt->slots, pt->number_of_slots * pt->record_size); memset(table_available_slot(pt), 0, TABLE_INCREMENT * pt->record_size); - - /* Re-allocate the index and set newly added memory chunk to 0. */ + /* + ** Re-allocate the index and set newly added memory chunk to 0. + */ pt->index = realloc(pt->index, pt->number_of_slots * sizeof(char *)); memset(table_available_index(pt), 0, TABLE_INCREMENT * sizeof(char *)); - - /* Reassign index entries to point to the re-allocatted records. */ + /* + ** Reassign index entries to point to the re-allocatted records. + */ for (i = 0, pi = pt->index; i < pt->auto_increment; i++, pi++) { if (*pi != NULL) { *pi = pt->slots + i * pt->record_size; } } - return pt; } @@ -118,7 +109,8 @@ uchar *table_find(PTable pt, ulong id) { } /* -** Delete a record y its id and return the address of next record. +** Delete a record by its ID. Return the address of next record or NULL +** if deleted last record. */ uchar *table_delete(PTable pt, ulong id) { register uchar *pr = (uchar *)table_find(pt, id); @@ -126,28 +118,31 @@ uchar *table_delete(PTable pt, ulong id) { if (pr) { register ulong i; register uchar **pi; + register uchar *last = table_last_record(pt); /* - ** Overwrite current record by shifting over remaining records. + ** Overwrite current record by shifting over remaining records */ - memmove(pr, pr + pt->record_size, (pt->number_of_records - id) * pt->record_size); - /* + if (pr != last) { + memmove(pr, pr + pt->record_size, last - pr); + } + /* ** Set the slot occupied by the last record to zero. */ - memset(table_last_record(pt), 0, pt->record_size); + memset(last, 0, pt->record_size); /* - ** Set current record pointer to NULL, then update the rest of the index to point - ** to the shifted records. + ** Set current record pointer to NULL, then update the rest of + ** the index to point to the shifted records. */ - pi = pt->index + id - 1; - *pi++ = NULL; + pi = pt->index + id - 1; + *pi++ = NULL; - printf("shift: %lu/%lu\n", id, pt->auto_increment); for (i = id; i < pt->auto_increment; i++) { - printf("Shift: %08lX - %08lX\n", (ulong)*pi, (ulong)(*pi - pt->record_size)); *pi++ -= pt->record_size; } pt->number_of_records--; + } + if (pr && pt->number_of_records > 0) { return pr; } else { return NULL; @@ -155,7 +150,8 @@ uchar *table_delete(PTable pt, ulong id) { } /* -** Insert a record and return its address. The table gets extended as necessary. +** Insert a record and return its address. The table gets extended +** as necessary. */ uchar *table_insert(PTable pt, uchar *record) { register uchar **pi; @@ -209,48 +205,123 @@ PTable table_free(PTable pt) { return NULL; } +/* +** Save the contents of the table to file. The file handle should be +** open with for writing. +*/ +int table_save(FILE *file, PTable pt) { + register int written = 0; + /* + ** Save table header data: flags, record_size, number_of_slots, + ** number_of_records, and auto_increment. + */ + written += fwrite(pt, sizeof(ulong), 5, file); + /* + ** Save the records. Note that we save the actual (not allocated) data. + */ + written += fwrite(pt->slots, pt->record_size, pt->number_of_records, file); + return written; +} +/* +** Load the contents of the table from file. The file handle should be +** open with for reading. +*/ +PTable table_load(FILE *file) { + PTable pt; + register int read = 0; + register ulong i; + uchar *pr, **pi; + + pt = calloc(1, sizeof(Table)); + /* + ** First read the header. + */ + read += fread(pt, sizeof(ulong), 5, file); + /* + ** Now allocate slots and index based n original number of slots. + */ + printf("Allocating %lu slots\n", pt->number_of_slots); + pt->slots = pr = calloc(pt->number_of_slots, pt->record_size); + pt->index = pi = calloc(pt->number_of_slots, sizeof(uchar *)); + /* + ** Now read the records into the slots and rebuild the index. + */ + read += fread(pt->slots, pt->record_size, pt->number_of_records, file); + for(i = 0; i < pt->number_of_records; i++, pi++) { + if ((ulong)*pr == i + 1) { + *pi = pr; + pr += pt->record_size; + } + } + return pt; +} + + +/* #define TEST */ #if defined(TEST) + +typedef struct { + ulong id; + ulong value; + char name[30]; + time_t created_at; + time_t updated_at; +} Record; + +void dump(Record *prec) { + if (prec) { + printf("(%08lX) id: %08lu, value: %lu, created_at: %lu, updated_at: %lu)\n", + (ulong)prec, prec->id, prec->value, prec->created_at, prec->updated_at); + } else { + printf("(NULL)\n"); + } +} + +void dump_all(PTable pt) { + int i; + Record *prec; + + for(i = 1; i <= pt->number_of_slots; i++) { + prec = (Record *)table_find(pt, i); + if (prec) { + dump(prec); + } else { + printf("%d not found\n", i); + } + } +} + int main() { PTable pt; - typedef struct { - ulong id; - ulong id2; - char name[30]; - time_t created_at; - time_t updated_at; - } Record; Record rec, *prec; - ulong i, total = 4; + ulong i, total = 30; pt = table_initialize(sizeof(Record), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); for(i = 0; i < total; i++) { rec.id = 0; - rec.id2 = 42; + rec.value = 0x11223344 + i + 1; + strcpy(rec.name, "test"); rec.created_at = rec.updated_at = (time_t)0; - prec = (Record *)table_insert(pt, (uchar *)&rec); - printf("%08lX, %08lX (id: %lu, id2: %lu, created_at: %lu, updated_at: %lu)\n", - (ulong)*table_last_record(pt), - (ulong)table_last_record(pt), - prec->id, prec->id2, - (ulong)prec->created_at, - (ulong)prec->updated_at); - } - prec = (Record *)table_delete(pt, 1); - prec = (Record *)table_delete(pt, 2); - printf("DEL/id: %08lX, id2: %lu, created_at: %lu, updated_at: %lu)\n", - prec->id, prec->id2, prec->created_at, prec->updated_at); - for(i = total; i > 0; i--) { - prec = (Record *)table_find(pt, i); - if (prec) { - printf("id: %08lX, id2: %lu, created_at: %lu, updated_at: %lu)\n", - prec->id, prec->id2, prec->created_at, prec->updated_at); - } else { - printf("%lu not found\n", i); - } + prec = (Record *)table_insert(pt, (uchar *)&rec); + dump(prec); } + for (i = 20; i < total; i++) { + printf("Deleting %lu\n", i + 1); + prec = (Record *)table_delete(pt, i + 1); + } + dump_all(pt); + + FILE *file = fopen("/tmp/.pit", "w"); + table_save(file, pt); + fclose(file); + + file = fopen("/tmp/.pit", "r"); + pt = table_load(file); + dump_all(pt); + fclose(file); table_free(pt); printf("OK\n"); diff --git a/src/table.c.out b/src/table.c.out new file mode 100755 index 0000000..f04aa2e Binary files /dev/null and b/src/table.c.out differ diff --git a/src/table.h b/src/table.h index 790919b..4e25d69 100644 --- a/src/table.h +++ b/src/table.h @@ -1,5 +1,28 @@ #if !defined(__TABLE_H__) #define __TABLE_H__ +typedef struct { + ulong flags; /* Bit mask with table flags */ + ulong record_size; /* Record size in bytes; all records are of fixed size */ + ulong number_of_slots; /* Number of slots allocated, each slot is 'record_size' long */ + ulong number_of_records; /* Number of records currently stored in slots */ + ulong auto_increment; /* Current value of record id */ + uchar *slots; /* Memory chunk to store records; compacted when a record gets deleted (no holes) */ + uchar **index; /* Memory chunk to store pointers to individual records, holes for deleted record ids */ +} Table, *PTable; + +PTable table_initialize(ulong record_size, ulong flags); +PTable table_free(PTable pt); +uchar *table_find(PTable pt, ulong id); +uchar *table_delete(PTable pt, ulong id); +uchar *table_insert(PTable pt, uchar *record); +int table_save(FILE *file, PTable pt); +PTable table_load(FILE *file); + +static uchar *table_available_slot(PTable pt); +static uchar *table_last_record(PTable pt); +static uchar **table_available_index(PTable pt); +static uchar **table_last_index(PTable pt); +static PTable table_extend(PTable pt); #endif \ No newline at end of file diff --git a/src/task.c b/src/task.c index 334052f..9a01529 100644 --- a/src/task.c +++ b/src/task.c @@ -1,8 +1,8 @@ -#include "pit.h" -#include "task.h" #include #include #include +#include "pit.h" +#include "task.h" int pit_task(char *argv[]) { printf("pit_task\n");