mirror of
https://github.com/michaeldv/pit.git
synced 2025-12-10 08:25:34 +00:00
Cleaned up pointer arithmetic by using **index
This commit is contained in:
120
src/table.c
120
src/table.c
@@ -2,23 +2,29 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
|
||||||
#define TABLE_INCREMENT 5
|
#define TABLE_INCREMENT 5
|
||||||
#define TABLE_HAS_ID 1
|
#define TABLE_HAS_ID 1
|
||||||
#define TABLE_HAS_CREATED_AT 2
|
#define TABLE_HAS_CREATED_AT 2
|
||||||
#define TABLE_HAS_UPDATED_AT 4
|
#define TABLE_HAS_UPDATED_AT 4
|
||||||
|
#define TABLE_HAS_TIMESTAMPS (TABLE_HAS_CREATED_AT | TABLE_HAS_UPDATED_AT)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long flags;
|
ulong flags; /* Bit mask with table flags */
|
||||||
unsigned long record_size;
|
ulong record_size; /* Record size in bytes; all records are of fixed size */
|
||||||
unsigned long number_of_slots;
|
ulong number_of_slots; /* Number of slots allocated, each slot is 'record_size' long */
|
||||||
unsigned long number_of_records;
|
ulong number_of_records; /* Number of records currently stored in slots */
|
||||||
unsigned long autoincrement;
|
ulong auto_increment; /* Current value of record id */
|
||||||
unsigned char *records;
|
uchar *slots; /* Memory chunk to store records; compacted when a record gets deleted (no holes) */
|
||||||
unsigned char *index;
|
uchar **index; /* Memory chunk to store pointers to individual records, holes for deleted record ids */
|
||||||
} Table, *PTable;
|
} Table, *PTable;
|
||||||
|
|
||||||
|
/*
|
||||||
PTable table_initialize(unsigned long record_size, unsigned long flags) {
|
** Initialize the table by alloocating necessary memory chunks.
|
||||||
|
*/
|
||||||
|
PTable table_initialize(ulong record_size, ulong flags) {
|
||||||
PTable pt;
|
PTable pt;
|
||||||
|
|
||||||
pt = calloc(1, sizeof(Table));
|
pt = calloc(1, sizeof(Table));
|
||||||
@@ -26,84 +32,103 @@ PTable table_initialize(unsigned long record_size, unsigned long flags) {
|
|||||||
pt->record_size = record_size;
|
pt->record_size = record_size;
|
||||||
pt->number_of_slots = TABLE_INCREMENT;
|
pt->number_of_slots = TABLE_INCREMENT;
|
||||||
pt->number_of_records = 0;
|
pt->number_of_records = 0;
|
||||||
pt->autoincrement = 0;
|
pt->auto_increment = 0;
|
||||||
pt->records = calloc(TABLE_INCREMENT, pt->record_size);
|
pt->slots = calloc(TABLE_INCREMENT, pt->record_size);
|
||||||
pt->index = calloc(TABLE_INCREMENT, sizeof(unsigned long *));
|
pt->index = calloc(TABLE_INCREMENT, sizeof(uchar *));
|
||||||
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *table_next_record(PTable pt) {
|
/*
|
||||||
return pt->records + pt->number_of_records * pt->record_size;
|
** Return the address of next avaiable slot within pt->slots chunk.
|
||||||
|
*/
|
||||||
|
uchar *table_available_slot(PTable pt) {
|
||||||
|
return pt->slots + pt->number_of_records * pt->record_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *table_last_record(PTable pt) {
|
/*
|
||||||
|
** Return the address of last stored record.
|
||||||
|
*/
|
||||||
|
uchar *table_last_record(PTable pt) {
|
||||||
if (pt->number_of_records == 0) {
|
if (pt->number_of_records == 0) {
|
||||||
return pt->records;
|
return pt->slots;
|
||||||
} else {
|
} else {
|
||||||
return table_next_record(pt) - pt->record_size;
|
return table_available_slot(pt) - pt->record_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *table_next_index(PTable pt) {
|
/*
|
||||||
return pt->index + pt->autoincrement * sizeof(unsigned long *);
|
** Return the address of next available pointer within pt->index chunk.
|
||||||
|
*/
|
||||||
|
uchar **table_available_index(PTable pt) {
|
||||||
|
return pt->index + pt->auto_increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *table_last_index(PTable pt) {
|
/*
|
||||||
if (pt->autoincrement == 0) {
|
** Return the address of last pointer within pt->index chunk.
|
||||||
|
*/
|
||||||
|
uchar **table_last_index(PTable pt) {
|
||||||
|
if (pt->auto_increment == 0) {
|
||||||
return pt->index;
|
return pt->index;
|
||||||
} else {
|
} else {
|
||||||
return table_last_index(pt) - sizeof(unsigned long *);
|
return table_last_index(pt) - sizeof(char *);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Extend the table involves three steps. First, we reallocate pt->slots
|
||||||
|
** chunk adding TABLE_INCREMENT empty slots. Then we add the same number
|
||||||
|
** 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) {
|
PTable table_extend(PTable pt) {
|
||||||
register long i;
|
register long i;
|
||||||
unsigned long *pi;
|
register uchar **pi;
|
||||||
|
|
||||||
|
puts("EXTENDING...\n");
|
||||||
pt->number_of_slots += TABLE_INCREMENT;
|
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->records = realloc(pt->records, pt->number_of_slots * pt->record_size);
|
pt->slots = realloc(pt->slots, pt->number_of_slots * pt->record_size);
|
||||||
memset(table_next_record(pt), 0, TABLE_INCREMENT * 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(unsigned long *));
|
pt->index = realloc(pt->index, pt->number_of_slots * sizeof(char *));
|
||||||
memset(table_next_index(pt), 0, TABLE_INCREMENT * sizeof(unsigned long *));
|
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 = (unsigned long *)pt->index; i < pt->autoincrement; i++, pi++) {
|
for (i = 0, pi = pt->index; i < pt->auto_increment; i++, pi++) {
|
||||||
*pi = (unsigned long)(pt->records + pt->record_size * i);
|
if (*pi != NULL) {
|
||||||
|
*pi = pt->slots + i * pt->record_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long *table_find(PTable pt, unsigned long id) {
|
uchar *table_find(PTable pt, ulong id) {
|
||||||
if (pt->number_of_records == 0 || id < 0 || id > pt->autoincrement) {
|
if (pt->number_of_records == 0 || id < 0 || id > pt->auto_increment) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
return (unsigned long *) *((unsigned long *)pt->index + id);
|
return *(pt->index + id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PTable table_insert(PTable pt, unsigned long *record) {
|
uchar *table_insert(PTable pt, uchar *record) {
|
||||||
unsigned long **pi;
|
uchar **pi;
|
||||||
|
|
||||||
if (pt->number_of_records >= pt->number_of_slots) {
|
if (pt->number_of_records >= pt->number_of_slots) {
|
||||||
pt = table_extend(pt);
|
pt = table_extend(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(table_next_record(pt), record, pt->record_size);
|
pi = table_available_index(pt);
|
||||||
// printf("rec: %lu, %08lX, mov: %08lX, next: %08lX\n", (unsigned long)*record, (unsigned long)*record, (unsigned long)*table_next_record(pt), (unsigned long)table_next_record(pt));
|
*pi = table_available_slot(pt);
|
||||||
pi = (unsigned long **)table_next_index(pt);
|
memmove(table_available_slot(pt), record, pt->record_size);
|
||||||
|
|
||||||
*pi = (unsigned long *)table_next_record(pt);
|
|
||||||
pt->number_of_records++;
|
pt->number_of_records++;
|
||||||
pt->autoincrement++;
|
pt->auto_increment++;
|
||||||
|
|
||||||
return pt;
|
return *pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -113,8 +138,8 @@ PTable table_free(PTable pt) {
|
|||||||
if (pt->index) {
|
if (pt->index) {
|
||||||
free(pt->index);
|
free(pt->index);
|
||||||
}
|
}
|
||||||
if (pt->records) {
|
if (pt->slots) {
|
||||||
free(pt->records);
|
free(pt->slots);
|
||||||
}
|
}
|
||||||
free(pt);
|
free(pt);
|
||||||
}
|
}
|
||||||
@@ -126,7 +151,7 @@ PTable table_free(PTable pt) {
|
|||||||
int main() {
|
int main() {
|
||||||
PTable pt;
|
PTable pt;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long id;
|
ulong id;
|
||||||
char name[30];
|
char name[30];
|
||||||
} Record;
|
} Record;
|
||||||
|
|
||||||
@@ -136,15 +161,16 @@ int main() {
|
|||||||
pt = table_initialize(sizeof(Record), 0);
|
pt = table_initialize(sizeof(Record), 0);
|
||||||
for(i = 0; i <= 100; i++) {
|
for(i = 0; i <= 100; i++) {
|
||||||
rec.id = i;
|
rec.id = i;
|
||||||
pt = table_insert(pt, (unsigned long *)&rec);
|
prec = (Record *)table_insert(pt, (uchar *)&rec);
|
||||||
printf("%08lX, %08lX\n", (unsigned long)*table_last_record(pt), (unsigned long)table_last_record(pt));
|
printf("%08lX, %08lX (id: %lu)\n", (ulong)*table_last_record(pt), (ulong)table_last_record(pt), prec->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 100; i >= 0; i--) {
|
for(i = 100; i >= 0; i--) {
|
||||||
prec = (Record *)table_find(pt, i);
|
prec = (Record *)table_find(pt, i);
|
||||||
printf("%lu\n", prec->id);
|
printf("id: %lu\n", prec->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
table_free(pt);
|
table_free(pt);
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user