mirror of
https://github.com/michaeldv/pit.git
synced 2025-12-09 16:05:35 +00:00
Fixed table_delete(); implemented table_save() and table_load()
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "pit.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
static int usage() {
|
||||
printf("usage...\n");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "pit.h"
|
||||
#include "project.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
#include "project.h"
|
||||
|
||||
int pit_project(char *argv[]) {
|
||||
char **arg = &argv[1];
|
||||
|
||||
205
src/table.c
205
src/table.c
@@ -1,26 +1,16 @@
|
||||
#include "pit.h"
|
||||
#include "table.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#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");
|
||||
|
||||
BIN
src/table.c.out
Executable file
BIN
src/table.c.out
Executable file
Binary file not shown.
23
src/table.h
23
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
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "pit.h"
|
||||
#include "task.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
#include "task.h"
|
||||
|
||||
int pit_task(char *argv[]) {
|
||||
printf("pit_task\n");
|
||||
|
||||
Reference in New Issue
Block a user