Start implementing trie

master
teknomunk 1 year ago
parent 41dd937d41
commit 3cacd9fa08

@ -2,6 +2,12 @@
#include <stdbool.h>
// TODO: change value to char*
bool hash_index_set( const char* index, const char* key, int value );
bool hash_index_get( const char* index, const char* key, int* value );
bool hash_index_remove( const char* index, const char* key );
bool ffdb_hash_set( const char* index, const char* key, const char* value );
char* ffdb_hash_get( const char* index, const char* key );
bool ffdb_hash_remove( const char* index, const char* key );

@ -0,0 +1,16 @@
#include "test.h"
#include "trie.h"
#include <sys/stat.h>
bool ffdb_test()
{
const char* d = "/tmp/ffdb-test";
mkdir( d, 0755 );
ffdb_trie_set( d, "https://example.com/actor", "T" );
//ffdb_trie_set( d, "https://apogee.polaris-1.work/owner/actor", "T" );
return false;
}

@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
bool ffdb_test();

207
trie.c

@ -0,0 +1,207 @@
#include "trie.h"
#include "json/json.h"
#include <stdlib.h>
#include <string.h>
struct edge {
char* label;
char* value;
int count;
};
/*
{
"k": "test",
"t": 2,
"z": 7
}
*/
struct trie_entry
{
struct edge* edges;
int count;
};
static bool load_entry( FILE* f, struct trie_entry* e )
{
struct json_pull_parser jpp = {
.f = f,
.curr_state = jpp_initial_state,
};
if( !jpp.f ) { return false; }
int save;
if( !json_pull_parser_begin_object(&jpp,&save) ) { goto failed; }
e->count = 0;
char* edge_label = NULL;
while( edge_label = json_pull_parser_read_object_key(&jpp) ) {
e->count += 1;
e->edges = realloc( e->edges, sizeof(struct edge) * e->count );
struct edge* ed = &e->edges[ e->count-1 ];
memset(ed,0,sizeof(*ed));
ed->label = edge_label;
ed->count = 1;
if( !json_pull_parser_read_int( &jpp, &ed->count ) ) {
char* value = json_pull_parser_read_string(&jpp);
if( !value ) { goto failed; }
ed->value = value;
}
}
if( !json_pull_parser_end_object(&jpp,&save) ) { goto failed; }
return true;
failed:
fclose(jpp.f);
return false;
}
static void save_entry( FILE* f, struct trie_entry* e )
{
fprintf( f, "{" );
for( int i = 0; i < e->count; ++i ) {
if( i != 0 ) {
fprintf( f, ",\n\t" );
} else {
fprintf( f, "\n\t" );
}
struct edge* ed = &e->edges[i];
json_write_string( f, ed->label );
fprintf( f, ": " );
if( ed->count > 1 ) {
fprintf( f, "%d", ed->count );
} else {
json_write_string( f, ed->value );
}
}
fprintf( f, "\n}\n" );
}
// Escape '/' as "%|" and '%' as "%%"
static char* escape( const char* str )
{
int size = 0;
for( const char* i = str; *i; ++i ) {
switch( *i ) {
case '/': size += 2; break;
case '%': size += 2; break;
default: size += 1; break;
}
}
char* result = malloc(size+1);
char* o = result;
for( const char* i = str; *i; ++i ) {
switch( *i ) {
case '/':
o[0] = '%';
o[1] = '|';
o += 2;
break;
case '%':
o[0] = '%';
o[1] = '%';
o += 2;
break;
default:
*o = *i;
++o;
}
}
*o = '\0';
return o;
}
static int prefix_match( const char* a, const char* b )
{
int res = 0;
while( *a && *b && *a == *b ) {
a += 1;
b += 1;
res += 1;
}
return res;
}
static bool trie_set( struct trie_entry* e, const char* key, const char* value )
{
for( int i = 0; i < e->count; ++i ) {
struct edge* ed = &e->edges[i];
int prefix_len = prefix_match( key, ed->label );
if( prefix_len == strlen( ed->label ) ) {
if( ed->count == 1 ) {
free(ed->value);
ed->value = strdup(value);
return true;
} else {
printf( "TODO: exact match, go down this node\n" );
}
return false;
} else if( prefix_len != 0 ) {
printf( "TODO: create new node" );
return false;
}
}
// No match in node, add
printf( "Adding edge %s\n", key );
e->count += 1;
e->edges = realloc( e->edges, sizeof(struct edge) * e->count );
struct edge* ed = &e->edges[e->count-1];
ed->label = strdup(key);
ed->value = strdup(value);
ed->count = 1;
return true;
}
bool ffdb_trie_set( const char* filename, const char* key, const char* value )
{
char* key_escaped = escape(key);
struct trie_entry root;
memset(&root,0,sizeof(root));
char buffer[512];
snprintf( buffer, sizeof(buffer), "%s/%ROOT", filename );
FILE* f = fopen( buffer, "r" );
if( f ) {
load_entry( f, &root );
}
if( !trie_set( &root, key, value ) ) {
printf( "Failed to set %s to %s\n", key, value );
return false;
}
f = fopen( buffer, "w" );
save_entry( f, &root );
fclose(f);
return true;
}
char* ffdb_trie_get( const char* filename, const char* key )
{
return NULL;
}
bool ffdb_trie_remove( const char* filename, const char* key )
{
return false;
}
int ffdb_trie_count( const char* filename )
{
return 0;
}
void ffdb_trie_clean( const char* filename )
{
}

@ -0,0 +1,10 @@
#pragma once
#include <stdbool.h>
bool ffdb_trie_set( const char* filename, const char* key, const char* value );
char* ffdb_trie_get( const char* filename, const char* key );
bool ffdb_trie_remove( const char* filename, const char* key );
int ffdb_trie_count( const char* filename );
void ffdb_trie_clean( const char* filename );
Loading…
Cancel
Save