* File name: m_map.h
* Author: Seree Rakwong
* Date: 15-AUG-2018
*
* NOTE:
* VMS - LINK proc,bos_lib:sqlite3.opt/opt
* UNIX - gcc proc.c -lsqlite3
*/
#ifndef __M_MAP_H__
#define __M_MAP_H__
#include "sqlite3.h"
#include "m_node.h"
#ifdef __cplusplus
extern "C" {
#endif
struct _MAP_STRUCT;
typedef struct _MAP_STRUCT map_t;
map_t* map_create();
void map_destroy(map_t*);
typedef long (*fn_map_populate_callback)(char*, node_t, const void*);
/* map object functions */
typedef int (*fn_map_free)(map_t*);
typedef int (*fn_map_init)(map_t*, char*);
typedef int (*fn_map_release)(map_t*, char*);
typedef int (*fn_map_insert)(map_t*, char*, char*, const void*, unsigned long);
typedef int (*fn_map_erase)(map_t*, char*, char*);
typedef int (*fn_map_clear)(map_t*, char*);
typedef node_t (*fn_map_find)(map_t*, char*, char*);
typedef long (*fn_map_count)(map_t*, char*);
typedef long (*fn_map_populate)(map_t*, char*, fn_map_populate_callback, const void*);
typedef long (*fn_map_reverse_populate)(map_t*, char*, fn_map_populate_callback, const void*);
/*
int map_free(map_t* map);
int map_init(map_t* map, char* name);
int map_release(map_t* map, char* name);
int map_insert(map_t* map, char* name, char* key, const void* vp, unsigned long size);
int map_erase(map_t* map, char* name, char* key);
int map_clear(map_t* map, char* name);
node_t map_find(map_t* map, char* name, char* key);
long map_count(map_t* map, char* name);
/////////////////////////////////////////////////////////////
// fn_map_populate_callback
// Return: 0 to continue to next pair, otherwise stop populating
//
long map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* multi_puposed_usage);
long map_reverse_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* multi_puposed_usage);
*/
#define SYS_MAP_NAME "S00" /* Application CANNOT use this name */
struct _MAP_STRUCT
{
sqlite3* memdb;
/* methods */
fn_map_free free; /* release all map tables */
fn_map_init init; /* init the new map table */
fn_map_release release; /* release the specific name */
fn_map_insert insert; /* insert the new pair */
fn_map_erase erase; /* delete the specified pair */
fn_map_clear clear; /* delete all pairs */
fn_map_find find; /* find the pair */
fn_map_count count; /* cound the pairs */
fn_map_populate populate; /* populate all pairs */
fn_map_reverse_populate rpopulate; /* reverse populate all pairs */
};
#ifdef __cplusplus
}
#endif
#endif /* __M_MAP_H__ */
/*
* File name: m_map.c
* Author: Seree Rakwong
* Date: 15-AUG-2018
*
* NOTE:
* VMS - LINK proc,bos_lib:sqlite3.opt/opt
* UNIX - gcc proc.c -lsqlite3
*/
#include "m_map.h"
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
long _map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp,
int reverse);
long _map_clear_callback(char* key, node_t, const void*);
/*---------------------------------------------------------------------------*/
int map_free(map_t* map);
int map_init(map_t* map, char* name);
int map_release(map_t* map, char* name);
int map_insert(map_t* map, char* name, char* key, const void* vp, unsigned long size);
int map_erase(map_t* map, char* name, char* key);
int map_clear(map_t* map, char* name);
node_t map_find(map_t* map, char* name, char* key);
long map_count(map_t* map, char* name);
long map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp);
long map_reverse_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp);
/*---------------------------------------------------------------------------*/
#define USING_MEMDB ":memory:"
#define SELECT_FROM_NAME_ORDER_MAPKEY_QS "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY %s;"
#define SELECT_FROM_NAME_ORDER_MAPKEY_DESC_Q "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY DESC;"
#define SELECT_FROM_NAME_ORDER_MAPKEY_ASC_Q "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY ASC;"
#define CREATE_TABLE_SYS_MAP_NAME_Q "CREATE TABLE %q("\
" MAPNAME VARCHAR(256) PRIMARY KEY NOT NULL"\
");"
#define CREATE_TABLE_NAME_Q "CREATE TABLE %q("\
" MAPKEY VARCHAR(256) PRIMARY KEY NOT NULL,"\
" MAPVAL INTEGER NOT NULL"\
");"
#define INSERT_INTO_SYS_MAP_NAME_Q "INSERT INTO %q VALUES('%q');"
#define SELECT_FROM_SYS_MAP_NAME_Q "SELECT MAPNAME FROM %q;"
#define INSERT_INTO_NAME_QQL "INSERT INTO %q VALUES('%q',%ld);"
#define DELETE_FROM_NAME_WHERE_QQ "DELETE FROM %q WHERE MAPKEY='%q';"
#define DELETE_FROM_NAME_Q "DELETE FROM %q WHERE 1=1;"
#define SELECT_FROM_NAME_WHERE_QQ "SELECT MAPVAL FROM %q WHERE MAPKEY='%q';"
#define SELECT_COUNT_FROM_NAME_Q "SELECT COUNT(*) CNT FROM %q;"
#define DROP_TABLE_NAME_Q "DROP TABLE %q;"
/*---------------------------------------------------------------------------*/
long _map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp,
int reverse)
{
int rc = SQLITE_OK;
node_t iter = 0;
const unsigned char* key;
char* zSQL;
sqlite3_stmt* stmt;
if (0 == callback)
{
return rc;
}
zSQL = sqlite3_mprintf(
(reverse != 0 ? SELECT_FROM_NAME_ORDER_MAPKEY_DESC_Q :
SELECT_FROM_NAME_ORDER_MAPKEY_ASC_Q),
name);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
while (SQLITE_ROW == rc)
{
iter = (node_t)(sqlite3_column_int(stmt, 0));
key = sqlite3_column_text(stmt, 1);
if (callback((char*)key, iter, vp) != 0)
{
break;
}
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
return rc;
}
long _map_clear_callback(char* key, node_t iter, const void* vp)
{
node_release(iter);
return 0;
}
/*---------------------------------------------------------------------------*/
map_t* map_create()
{
map_t* map = (map_t*)malloc(sizeof(map_t));
if (map != NULL)
{
char* zSQL;
int rc = sqlite3_open(USING_MEMDB, &map->memdb);
if (rc != SQLITE_OK)
{
free(map);
return 0;
}
zSQL = sqlite3_mprintf(
CREATE_TABLE_SYS_MAP_NAME_Q,
SYS_MAP_NAME);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
if (rc != SQLITE_OK)
{
sqlite3_close(map->memdb);
free(map);
return 0;
}
/* init methods */
map->free = map_free;
map->init = map_init;
map->release = map_release;
map->insert = map_insert;
map->erase = map_erase;
map->clear = map_clear;
map->find = map_find;
map->count = map_count;
map->populate = map_populate;
map->rpopulate = map_reverse_populate;
}
return map;
}
void map_destroy(map_t* map)
{
if (map != 0)
{
map->free(map);
free(map);
}
}
/* map methods */
int map_init(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL = sqlite3_mprintf(
CREATE_TABLE_NAME_Q,
name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
if (rc != SQLITE_OK)
{
return rc;
}
zSQL = sqlite3_mprintf(
INSERT_INTO_SYS_MAP_NAME_Q,
SYS_MAP_NAME, name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
return rc;
}
int map_release(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL;
rc = map->clear(map, name);
if (SQLITE_OK == rc)
{
zSQL = sqlite3_mprintf(
DROP_TABLE_NAME_Q,
name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
}
return rc;
}
int map_free(map_t* map)
{
int rc = SQLITE_OK;
sqlite3_stmt* stmt;
char* zSQL;
if (0 == map->memdb)
{
return rc;
}
zSQL = sqlite3_mprintf(
SELECT_FROM_SYS_MAP_NAME_Q,
SYS_MAP_NAME);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
while (SQLITE_ROW == rc)
{
const unsigned char* name = sqlite3_column_text(stmt, 0);
map->clear(map, (char*)name);
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
rc = sqlite3_close(map->memdb);
map->memdb = 0;
return rc;
}
int map_insert(map_t* map, char* name, char* key, const void* vp, unsigned long size)
{
int rc = SQLITE_OK;
char *zSQL;
node_t iter = node_init(vp, size);
if (0 == iter)
{
return SQLITE_NOMEM;
}
zSQL = sqlite3_mprintf(
INSERT_INTO_NAME_QQL,
name, key, (long)iter);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
return rc;
}
int map_erase(map_t* map, char* name, char* key)
{
int rc = SQLITE_OK;
node_t iter = 0;
/* find the key if it is existing */
iter = map->find(map, name, key);
/* if found */
if (iter != 0)
{
char* zSQL = sqlite3_mprintf(
DELETE_FROM_NAME_WHERE_QQ,
name, key);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
node_release(iter);
}
else
{
rc = SQLITE_NOTFOUND;
}
return rc;
}
int map_clear(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL = sqlite3_mprintf(
DELETE_FROM_NAME_Q,
name);
rc = map->populate(map, name, _map_clear_callback, 0);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
return rc;
}
node_t map_find(map_t* map, char* name, char* key)
{
int rc = SQLITE_OK;
node_t iter = 0;
sqlite3_stmt* stmt;
char* zSQL = sqlite3_mprintf(
SELECT_FROM_NAME_WHERE_QQ,
name, key);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
if (SQLITE_ROW == rc)
{
iter = (node_t)(sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
}
return iter;
}
long map_count(map_t* map, char* name)
{
int rc = SQLITE_OK;
long cnt = 0;
sqlite3_stmt* stmt;
char* zSQL = sqlite3_mprintf(
SELECT_COUNT_FROM_NAME_Q,
name);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
if (SQLITE_ROW == rc)
{
cnt = sqlite3_column_int(stmt, 0);
}
sqlite3_finalize(stmt);
}
else
{
/* something errors */
cnt = -1;
}
return cnt;
}
long map_populate(
map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp)
{
return _map_populate(map, name, callback, vp, 0); /* 0 = not reverse */
}
long map_reverse_populate(
map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp)
{
return _map_populate(map, name, callback, vp, 1); /* 1 = reverse */
}
#ifdef __cplusplus
}
#endif
* File name: m_map.c
* Author: Seree Rakwong
* Date: 15-AUG-2018
*
* NOTE:
* VMS - LINK proc,bos_lib:sqlite3.opt/opt
* UNIX - gcc proc.c -lsqlite3
*/
#include "m_map.h"
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
long _map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp,
int reverse);
long _map_clear_callback(char* key, node_t, const void*);
/*---------------------------------------------------------------------------*/
int map_free(map_t* map);
int map_init(map_t* map, char* name);
int map_release(map_t* map, char* name);
int map_insert(map_t* map, char* name, char* key, const void* vp, unsigned long size);
int map_erase(map_t* map, char* name, char* key);
int map_clear(map_t* map, char* name);
node_t map_find(map_t* map, char* name, char* key);
long map_count(map_t* map, char* name);
long map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp);
long map_reverse_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp);
/*---------------------------------------------------------------------------*/
#define USING_MEMDB ":memory:"
#define SELECT_FROM_NAME_ORDER_MAPKEY_QS "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY %s;"
#define SELECT_FROM_NAME_ORDER_MAPKEY_DESC_Q "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY DESC;"
#define SELECT_FROM_NAME_ORDER_MAPKEY_ASC_Q "SELECT MAPVAL, MAPKEY FROM %q ORDER BY MAPKEY ASC;"
#define CREATE_TABLE_SYS_MAP_NAME_Q "CREATE TABLE %q("\
" MAPNAME VARCHAR(256) PRIMARY KEY NOT NULL"\
");"
#define CREATE_TABLE_NAME_Q "CREATE TABLE %q("\
" MAPKEY VARCHAR(256) PRIMARY KEY NOT NULL,"\
" MAPVAL INTEGER NOT NULL"\
");"
#define INSERT_INTO_SYS_MAP_NAME_Q "INSERT INTO %q VALUES('%q');"
#define SELECT_FROM_SYS_MAP_NAME_Q "SELECT MAPNAME FROM %q;"
#define INSERT_INTO_NAME_QQL "INSERT INTO %q VALUES('%q',%ld);"
#define DELETE_FROM_NAME_WHERE_QQ "DELETE FROM %q WHERE MAPKEY='%q';"
#define DELETE_FROM_NAME_Q "DELETE FROM %q WHERE 1=1;"
#define SELECT_FROM_NAME_WHERE_QQ "SELECT MAPVAL FROM %q WHERE MAPKEY='%q';"
#define SELECT_COUNT_FROM_NAME_Q "SELECT COUNT(*) CNT FROM %q;"
#define DROP_TABLE_NAME_Q "DROP TABLE %q;"
/*---------------------------------------------------------------------------*/
long _map_populate( map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp,
int reverse)
{
int rc = SQLITE_OK;
node_t iter = 0;
const unsigned char* key;
char* zSQL;
sqlite3_stmt* stmt;
if (0 == callback)
{
return rc;
}
zSQL = sqlite3_mprintf(
(reverse != 0 ? SELECT_FROM_NAME_ORDER_MAPKEY_DESC_Q :
SELECT_FROM_NAME_ORDER_MAPKEY_ASC_Q),
name);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
while (SQLITE_ROW == rc)
{
iter = (node_t)(sqlite3_column_int(stmt, 0));
key = sqlite3_column_text(stmt, 1);
if (callback((char*)key, iter, vp) != 0)
{
break;
}
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
return rc;
}
long _map_clear_callback(char* key, node_t iter, const void* vp)
{
node_release(iter);
return 0;
}
/*---------------------------------------------------------------------------*/
map_t* map_create()
{
map_t* map = (map_t*)malloc(sizeof(map_t));
if (map != NULL)
{
char* zSQL;
int rc = sqlite3_open(USING_MEMDB, &map->memdb);
if (rc != SQLITE_OK)
{
free(map);
return 0;
}
zSQL = sqlite3_mprintf(
CREATE_TABLE_SYS_MAP_NAME_Q,
SYS_MAP_NAME);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
if (rc != SQLITE_OK)
{
sqlite3_close(map->memdb);
free(map);
return 0;
}
/* init methods */
map->free = map_free;
map->init = map_init;
map->release = map_release;
map->insert = map_insert;
map->erase = map_erase;
map->clear = map_clear;
map->find = map_find;
map->count = map_count;
map->populate = map_populate;
map->rpopulate = map_reverse_populate;
}
return map;
}
void map_destroy(map_t* map)
{
if (map != 0)
{
map->free(map);
free(map);
}
}
/* map methods */
int map_init(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL = sqlite3_mprintf(
CREATE_TABLE_NAME_Q,
name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
if (rc != SQLITE_OK)
{
return rc;
}
zSQL = sqlite3_mprintf(
INSERT_INTO_SYS_MAP_NAME_Q,
SYS_MAP_NAME, name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
return rc;
}
int map_release(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL;
rc = map->clear(map, name);
if (SQLITE_OK == rc)
{
zSQL = sqlite3_mprintf(
DROP_TABLE_NAME_Q,
name);
rc = sqlite3_exec(map->memdb,
zSQL,
0,
0,
0);
sqlite3_free(zSQL);
}
return rc;
}
int map_free(map_t* map)
{
int rc = SQLITE_OK;
sqlite3_stmt* stmt;
char* zSQL;
if (0 == map->memdb)
{
return rc;
}
zSQL = sqlite3_mprintf(
SELECT_FROM_SYS_MAP_NAME_Q,
SYS_MAP_NAME);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
while (SQLITE_ROW == rc)
{
const unsigned char* name = sqlite3_column_text(stmt, 0);
map->clear(map, (char*)name);
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
rc = sqlite3_close(map->memdb);
map->memdb = 0;
return rc;
}
int map_insert(map_t* map, char* name, char* key, const void* vp, unsigned long size)
{
int rc = SQLITE_OK;
char *zSQL;
node_t iter = node_init(vp, size);
if (0 == iter)
{
return SQLITE_NOMEM;
}
zSQL = sqlite3_mprintf(
INSERT_INTO_NAME_QQL,
name, key, (long)iter);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
return rc;
}
int map_erase(map_t* map, char* name, char* key)
{
int rc = SQLITE_OK;
node_t iter = 0;
/* find the key if it is existing */
iter = map->find(map, name, key);
/* if found */
if (iter != 0)
{
char* zSQL = sqlite3_mprintf(
DELETE_FROM_NAME_WHERE_QQ,
name, key);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
node_release(iter);
}
else
{
rc = SQLITE_NOTFOUND;
}
return rc;
}
int map_clear(map_t* map, char* name)
{
int rc = SQLITE_OK;
char* zSQL = sqlite3_mprintf(
DELETE_FROM_NAME_Q,
name);
rc = map->populate(map, name, _map_clear_callback, 0);
rc = sqlite3_exec(map->memdb, zSQL, 0, 0, 0);
sqlite3_free(zSQL);
return rc;
}
node_t map_find(map_t* map, char* name, char* key)
{
int rc = SQLITE_OK;
node_t iter = 0;
sqlite3_stmt* stmt;
char* zSQL = sqlite3_mprintf(
SELECT_FROM_NAME_WHERE_QQ,
name, key);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
if (SQLITE_ROW == rc)
{
iter = (node_t)(sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
}
return iter;
}
long map_count(map_t* map, char* name)
{
int rc = SQLITE_OK;
long cnt = 0;
sqlite3_stmt* stmt;
char* zSQL = sqlite3_mprintf(
SELECT_COUNT_FROM_NAME_Q,
name);
rc = sqlite3_prepare(map->memdb,
zSQL,
-1,
&stmt,
0);
sqlite3_free(zSQL);
if (SQLITE_OK == rc)
{
rc = sqlite3_step(stmt);
if (SQLITE_ROW == rc)
{
cnt = sqlite3_column_int(stmt, 0);
}
sqlite3_finalize(stmt);
}
else
{
/* something errors */
cnt = -1;
}
return cnt;
}
long map_populate(
map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp)
{
return _map_populate(map, name, callback, vp, 0); /* 0 = not reverse */
}
long map_reverse_populate(
map_t* map,
char* name,
fn_map_populate_callback callback,
const void* vp)
{
return _map_populate(map, name, callback, vp, 1); /* 1 = reverse */
}
#ifdef __cplusplus
}
#endif
No comments:
Post a Comment