Initial import of WIP records abstraction lib i began to make rtl_power mysql/sqlite/... compliant
This commit is contained in:
179
src/mysql_backend.c
Normal file
179
src/mysql_backend.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright (c) 2020 Gérald Colangelo <gcolangelo@ospow.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "smart_records_internals.h"
|
||||
//#include <mysql.h>
|
||||
|
||||
#define URI_SCHEME "mysql://user[:password]@host[:port]/db_name.table"
|
||||
|
||||
typedef struct mysql_uri {
|
||||
char *host;
|
||||
char *user;
|
||||
char *passwd;
|
||||
char *db;
|
||||
char *table;
|
||||
unsigned int port;
|
||||
} mysql_uri_t;
|
||||
|
||||
void mysql_free_uri(mysql_uri_t * uri)
|
||||
{
|
||||
if (!uri)
|
||||
return;
|
||||
if (uri->host)
|
||||
free(uri->host);
|
||||
if (uri->user)
|
||||
free(uri->user);
|
||||
if (uri->passwd)
|
||||
free(uri->passwd);
|
||||
if (uri->db)
|
||||
free(uri->db);
|
||||
if (uri->table)
|
||||
free(uri->table);
|
||||
free(uri);
|
||||
}
|
||||
|
||||
|
||||
|
||||
mysql_uri_t *mysql_parse_uri( /* MYSQL *mysql, */ const char *uri, char **error)
|
||||
{
|
||||
int conv;
|
||||
mysql_uri_t *r=NULL;
|
||||
char *p1=NULL, *p2=NULL, *p3=NULL, *tmp=NULL;
|
||||
|
||||
if(!uri) {
|
||||
set_error_and_fails("URI can't be null");
|
||||
}
|
||||
|
||||
r = malloc(sizeof(mysql_uri_t));
|
||||
memset(r,0,sizeof(mysql_uri_t));
|
||||
|
||||
/* Split the URI in 3 group: identifier, host identifier, db identifier */
|
||||
conv = sscanf(uri, "mysql://%m[^@]@%m[^/]/%ms", &p1, &p2, &p3);
|
||||
if (conv != 3) {
|
||||
set_error_and_fails("URI doesn't respect the scheme");
|
||||
}
|
||||
|
||||
/* Parse identifier */
|
||||
/* We consider that 'login:' stands for empty password */
|
||||
/* XXX: there's a leak here when : is present. Must fix !*/
|
||||
conv = sscanf(p1, "%m[^:]%m[:]%ms", &r->user, &tmp, &r->passwd);
|
||||
if (!conv) {
|
||||
set_error_and_fails("Bad URI: no identifier provided");
|
||||
}
|
||||
else if (conv == 1) {
|
||||
#ifdef _WITH_INTERACTIVE_TERMINAL // XXX: is there a way to detect this at runtime ?
|
||||
char *tmp = malloc(128);
|
||||
size_t n = 128, read;
|
||||
fprintf(stdout, "Please, enter password for connection to %s\n", uri);
|
||||
|
||||
read = getline(&tmp, &n, stdin);
|
||||
if (read >= 1)
|
||||
/* Remove trailing \n */
|
||||
r->passwd = strndup(tmp, strlen(tmp) - 1);
|
||||
free(tmp);
|
||||
#else
|
||||
set_error_and_fails("No password provided and built without support of INTERACTIVE_TERMINAL");
|
||||
#endif
|
||||
}
|
||||
free(p1);
|
||||
p1 = NULL;
|
||||
|
||||
/* Parse host identifier */
|
||||
conv = sscanf(p2, "%m[^:]:%d", &r->host, &r->port);
|
||||
if (!conv) {
|
||||
set_error_and_fails("Bad URI: need a port number after host:");
|
||||
}
|
||||
else if (conv == 1) {
|
||||
r->port = 3306;
|
||||
}
|
||||
free(p2);
|
||||
p2 = NULL;
|
||||
|
||||
/* Par db identifier */
|
||||
conv = sscanf(p3, "%m[^.].%ms", &r->db, &r->table);
|
||||
if (conv != 2) {
|
||||
set_error_and_fails("Bad URI: need a database.table syntax");
|
||||
}
|
||||
free(p3);
|
||||
p3 = NULL;
|
||||
|
||||
return r;
|
||||
failed:
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
if (r)
|
||||
mysql_free_uri(r);
|
||||
if (p1)
|
||||
free(p1);
|
||||
if (p2)
|
||||
free(p2);
|
||||
if (p3)
|
||||
free(p3);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _TEST
|
||||
char *tests[7][2] = {
|
||||
{ "Every info provided",
|
||||
"mysql://leon:bruxelles@lafrite:1024/STOCK_PATATE.avril" },
|
||||
/*
|
||||
{ "Every info provided except password",
|
||||
"mysql://leon@lafrite:1024/STOCK_PATATE.avril" },
|
||||
*/
|
||||
{ "Every info provided but empty password",
|
||||
"mysql://leon:@lafrite:1024/STOCK_PATATE.avril" },
|
||||
{ "Every info provided except port number",
|
||||
"mysql://leon:coin@lafrite/STOCK_PATATE.avril" },
|
||||
/*
|
||||
{ "Bad URI #1", "mysql://lafrite/PATATE.avril" },
|
||||
{ "Bad URI #1", "mysql://lafrite/" },
|
||||
*/
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
mysql_uri_t *r;
|
||||
char *error = NULL;
|
||||
|
||||
int i = 0;
|
||||
while (tests[i][0]) {
|
||||
printf("## %s ##\nURI: %s\nResult:\n", tests[i][0], tests[i][1]);
|
||||
r = mysql_parse_uri(tests[i][1], &error);
|
||||
if (r) {
|
||||
printf("\tr->host=%s\n\tr->port=%d\n\tr->user=%s\n\tr->password=%s\n\tr->db=%s\n\tr->table=%s\n",
|
||||
r->host, r->port, r->user, r->passwd, r->db, r->table);
|
||||
mysql_free_uri(r);
|
||||
} else {
|
||||
if(error) {
|
||||
printf("mysql_parse_uri : got error %s !\n", error);
|
||||
free(error);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
18
src/mysql_backend.h
Normal file
18
src/mysql_backend.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _SMART_RECORDS_MYSQL_BACKEND_H
|
||||
#define _SMART_RECORDS_MYSQL_BACKEND_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "smart_records_internals.h"
|
||||
//#include <mysql.h>
|
||||
|
||||
typedef struct mysql_backend_ctx_t {
|
||||
//MYSQL *mysql;
|
||||
char *format;
|
||||
} mysql_backend_ctx_t;
|
||||
|
||||
int mysql_backend_write_record(smart_records_ctx_t *ctx, char **error, va_list ap);
|
||||
int mysql_backend_set_format(smart_records_ctx_t *ctx, char **error, char *format);
|
||||
int mysql_backend_close_records_base(smart_records_ctx_t *ctx);
|
||||
void *mysql_backend_init(smart_records_ctx_t *ctx, char **error);
|
||||
|
||||
#endif
|
||||
108
src/smart_records.c
Normal file
108
src/smart_records.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "smart_records.h"
|
||||
#include "smart_records_internals.h"
|
||||
|
||||
#ifdef _HAS_MYSQL
|
||||
#include "mysql_backend.h"
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_SQLITE
|
||||
#include "sqlite_backend.h"
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_UDP
|
||||
#include "udp_backend.h"
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_CSV
|
||||
#include "csv_backend.h"
|
||||
#endif
|
||||
|
||||
|
||||
// nothing but give a context for the moment
|
||||
smart_records_ctx_t *smart_records_init(){
|
||||
return malloc(sizeof(smart_records_ctx_t));
|
||||
}
|
||||
|
||||
int smart_records_open_base(smart_records_ctx_t *ctx, char *uri, char **error)
|
||||
{
|
||||
int len_uri;
|
||||
|
||||
if(!uri) {
|
||||
set_error_and_fails("URI is null");
|
||||
}
|
||||
|
||||
len_uri = strlen(uri);
|
||||
if(!strncmp("mysql://", uri, len_uri < 8 ? len_uri : 8)) {
|
||||
#ifdef _HAS_MYSQL
|
||||
ctx->CTX = malloc(sizeof(mysql_backend_ctx_t));
|
||||
ctx->write_record = mysql_backend_write_record;
|
||||
ctx->set_format = mysql_backend_set_format;
|
||||
ctx->close_records_base = mysql_backend_close_records_base;
|
||||
if ( mysql_backend_init(ctx->CTX, error) < 0)
|
||||
goto failed;
|
||||
#else
|
||||
set_error_and_fails("built without support for mysql:// URIs");
|
||||
goto failed;
|
||||
#endif
|
||||
}
|
||||
|
||||
else if(!strncmp("sqlite://", uri, len_uri < 9 ? len_uri : 9)) {
|
||||
#ifdef _HAS_SQLITE
|
||||
ctx->CTX = malloc(sizeof(sqlite_backend_ctx_t));
|
||||
ctx->write_record = sqlite_backend_write_record(char *uri);
|
||||
ctx->close_records_base = sqlite_backend_close_records_base(char *uri);
|
||||
if ( sqlite_backend_init(ctx->CTX, error) < 0)
|
||||
goto failed;
|
||||
#else
|
||||
if(error) *error = strdup("built without support for sqlite:// URIs");
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
else if(!strncmp("udp://", uri, len_uri < 8 ? len_uri : 8)) {
|
||||
#ifdef _HAS_UDP
|
||||
ctx->CTX = malloc(sizeof(udp_backend_ctx_t));
|
||||
ctx->write_record = udp_backend_write_record(char *uri);
|
||||
ctx->close_records_base = udp_backend_close_records_base(char *uri);
|
||||
if ( udp_backend_init(ctx->CTX, error) < 0)
|
||||
goto failed;
|
||||
#else
|
||||
if(error) *error = strdup("built without support for udp:// URIs");
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
else if(!strncmp("csv://", uri, len_uri < 8 ? len_uri : 8)) {
|
||||
#ifdef _HAS_CSV
|
||||
ctx->CTX = malloc(sizeof(csv_backend_ctx_t));
|
||||
ctx->write_record = csv_backend_write_record(char *uri);
|
||||
ctx->close_records_base = csv_backend_close_records_base(char *uri);
|
||||
if ( csv_backend_init(ctx->CTX, error) < 0)
|
||||
goto failed;
|
||||
#else
|
||||
if(error) *error = strdup("built without suppor fort csv:// URIs");
|
||||
goto failed;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if(error) *error = strdup("Unknown scheme or bad URI.");
|
||||
goto failed;
|
||||
}
|
||||
return 0;
|
||||
failed:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int smart_records_close_base(smart_records_ctx_t *ctx)
|
||||
{
|
||||
return ctx->close_records_base(ctx);
|
||||
}
|
||||
|
||||
int smart_records_write(smart_records_ctx_t *ctx, char **error, va_list ap)
|
||||
{
|
||||
return ctx->write_record(ctx, error, ap);
|
||||
}
|
||||
12
src/smart_records.h
Normal file
12
src/smart_records.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _SMART_RECORDS_H
|
||||
#define _SMART_RECORDS_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "smart_records_internals.h"
|
||||
|
||||
smart_records_ctx_t *smart_records_init();
|
||||
int smart_records_open_base(smart_records_ctx_t *ctx, char *uri, char **error);
|
||||
int smart_records_set_format(smart_records_ctx_t *ctx, char *fmt, char **error);
|
||||
int smart_records_write(smart_records_ctx_t *ctx, char **error, va_list ap);
|
||||
int smart_records_close_base(smart_records_ctx_t *ctx);
|
||||
#endif
|
||||
Reference in New Issue
Block a user