vars: added code to read AQH_VARS from GWEN_DB strings.
This commit is contained in:
@@ -68,6 +68,7 @@
|
||||
datafile_direct_p.h
|
||||
vars.h
|
||||
vars_p.h
|
||||
vars_dbread.h
|
||||
path.h
|
||||
</headers>
|
||||
|
||||
@@ -80,6 +81,7 @@
|
||||
storage_writexml.c
|
||||
datafile_direct.c
|
||||
vars.c
|
||||
vars_dbread.c
|
||||
path.c
|
||||
</sources>
|
||||
|
||||
@@ -89,6 +91,8 @@
|
||||
path-t.c
|
||||
vars-t.h
|
||||
vars-t.c
|
||||
vars_dbread-t.h
|
||||
vars_dbread-t.c
|
||||
</extradist>
|
||||
|
||||
|
||||
|
||||
@@ -128,6 +128,25 @@ void AQH_Vars_free(AQH_VARS *vt)
|
||||
|
||||
|
||||
|
||||
AQH_VARS_DATATYPE AQH_Vars_DataTypeFromString(const char *s)
|
||||
{
|
||||
if (s && *s) {
|
||||
if (strcasecmp(s, "group")==0)
|
||||
return AQH_Vars_DataType_Group;
|
||||
else if (strcasecmp(s, "variable")==0)
|
||||
return AQH_Vars_DataType_Variable;
|
||||
else if (strcasecmp(s, "char")==0)
|
||||
return AQH_Vars_DataType_ValueString;
|
||||
else if (strcasecmp(s, "int")==0)
|
||||
return AQH_Vars_DataType_ValueInt;
|
||||
else if (strcasecmp(s, "double")==0)
|
||||
return AQH_Vars_DataType_ValueDouble;
|
||||
}
|
||||
return AQH_Vars_DataType_Unknown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VARS *AQH_Vars_dup(const AQH_VARS *vt)
|
||||
{
|
||||
AQH_VARS *vtCopy;
|
||||
@@ -215,7 +234,14 @@ const char *AQH_Vars_GetStringData(const AQH_VARS *vt, const char *defValue)
|
||||
case AQH_Vars_DataType_Variable:
|
||||
case AQH_Vars_DataType_ValueString:
|
||||
return vt->data.dataString;
|
||||
case AQH_Vars_DataType_ValueInt:
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Unexpected type INT: %d", vt->data.dataInt);
|
||||
break;
|
||||
case AQH_Vars_DataType_ValueDouble:
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Unexpected type DOUBLE: %f", vt->data.dataDouble);
|
||||
break;
|
||||
default:
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Unexpected type %d", vt->dataType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -348,10 +374,8 @@ const char *AQH_Vars_GetCharValue(AQH_VARS *vt, const char *path, int idx, const
|
||||
AQH_VARS *vtValue;
|
||||
|
||||
vtChild=_getPath(vt, path, AQH_PATH_FLAGS_PATHMUSTEXIST | AQH_PATH_FLAGS_VARIABLE);
|
||||
if (vtChild==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Path for var \"%s\" not found", path);
|
||||
if (vtChild==NULL)
|
||||
return defaultValue;
|
||||
}
|
||||
vtValue=_getValueNodeByIdx(vtChild, idx);
|
||||
if (vtValue)
|
||||
return AQH_Vars_GetStringData(vtValue, defaultValue);
|
||||
@@ -388,10 +412,9 @@ int AQH_Vars_GetIntValue(AQH_VARS *vt, const char *path, int idx, int defaultVal
|
||||
AQH_VARS *vtValue;
|
||||
|
||||
vtChild=_getPath(vt, path, AQH_PATH_FLAGS_PATHMUSTEXIST | AQH_PATH_FLAGS_VARIABLE);
|
||||
if (vtChild==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Path for var \"%s\" not found", path);
|
||||
if (vtChild==NULL)
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
vtValue=_getValueNodeByIdx(vtChild, idx);
|
||||
if (vtValue)
|
||||
return AQH_Vars_GetIntData(vtValue, defaultValue);
|
||||
@@ -428,10 +451,8 @@ double AQH_Vars_GetDoubleValue(AQH_VARS *vt, const char *path, int idx, double d
|
||||
AQH_VARS *vtValue;
|
||||
|
||||
vtChild=_getPath(vt, path, AQH_PATH_FLAGS_PATHMUSTEXIST | AQH_PATH_FLAGS_VARIABLE);
|
||||
if (vtChild==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Path for var \"%s\" not found", path);
|
||||
if (vtChild==NULL)
|
||||
return defaultValue;
|
||||
}
|
||||
vtValue=_getValueNodeByIdx(vtChild, idx);
|
||||
if (vtValue)
|
||||
return AQH_Vars_GetDoubleData(vtValue, defaultValue);
|
||||
@@ -528,7 +549,7 @@ AQH_VARS *_getNodeByTypeAndName(const AQH_VARS *vt, AQH_VARS_DATATYPE dt, const
|
||||
/* look it up */
|
||||
vtChild=AQH_Vars_GetFirstChildByType(vt, dt);
|
||||
while(vtChild) {
|
||||
if (vtChild->data.dataString && strcasecmp(vtChild->data.dataString, name)!=-1) {
|
||||
if (vtChild->data.dataString && strcasecmp(vtChild->data.dataString, name)==0) {
|
||||
if (idx==0)
|
||||
break;
|
||||
else
|
||||
|
||||
@@ -34,6 +34,8 @@ typedef struct AQH_VARS AQH_VARS;
|
||||
GWEN_TREE2_FUNCTION_LIB_DEFS(AQH_VARS, AQH_Vars, AQHOME_API);
|
||||
|
||||
|
||||
AQHOME_API AQH_VARS_DATATYPE AQH_Vars_DataTypeFromString(const char *s);
|
||||
|
||||
AQHOME_API AQH_VARS *AQH_Vars_CreateGroup(const char *s);
|
||||
AQHOME_API AQH_VARS *AQH_Vars_CreateVariable(const char *s);
|
||||
AQHOME_API AQH_VARS *AQH_Vars_CreateStringValue(char *s);
|
||||
|
||||
207
aqhome/data/vars_dbread-t.c
Normal file
207
aqhome/data/vars_dbread-t.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project Gwenhywfar.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
/* This file is included by "vars_dbread.c" */
|
||||
|
||||
|
||||
#include <gwenhywfar/testframework.h>
|
||||
#include "vars_dbread-t.h"
|
||||
|
||||
|
||||
#ifdef AQHOME_ENABLE_TESTCODE
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int GWENHYWFAR_CB test1(GWEN_TEST_MODULE *mod);
|
||||
static int GWENHYWFAR_CB test2(GWEN_TEST_MODULE *mod);
|
||||
static int GWENHYWFAR_CB test3(GWEN_TEST_MODULE *mod);
|
||||
static int GWENHYWFAR_CB test4(GWEN_TEST_MODULE *mod);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Vars_DbRead_AddTests(GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
GWEN_TEST_MODULE *newMod;
|
||||
|
||||
newMod=GWEN_Test_Module_AddModule(mod, "AQH_Vars_DbRead", NULL);
|
||||
|
||||
GWEN_Test_Module_AddTest(newMod, "test 1: read group", test1, NULL);
|
||||
GWEN_Test_Module_AddTest(newMod, "test 2: read var", test2, NULL);
|
||||
GWEN_Test_Module_AddTest(newMod, "test 3: read group and var", test3, NULL);
|
||||
GWEN_Test_Module_AddTest(newMod, "test 4: read multi groups and vars", test4, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GWENHYWFAR_CB test1(GWEN_UNUSED GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
AQH_VARS *vtRoot;
|
||||
const char *testData="testGroup1 {\n}\n";
|
||||
|
||||
vtRoot=AQH_Vars_ReadDbFormat(testData);
|
||||
if (vtRoot==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading dbformat");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
if (NULL==AQH_Vars_GetGroup(vtRoot, "testGroup1", AQH_PATH_FLAGS_PATHMUSTEXIST)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read group \"testGroup1\" not found");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
AQH_Vars_free(vtRoot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GWENHYWFAR_CB test2(GWEN_UNUSED GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
AQH_VARS *vtRoot;
|
||||
const char *testData="char testVar1=\"value1\"\n";
|
||||
const char *s;
|
||||
|
||||
vtRoot=AQH_Vars_ReadDbFormat(testData);
|
||||
if (vtRoot==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading dbformat");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
s=AQH_Vars_GetCharValue(vtRoot, "testVar1", 0, NULL);
|
||||
if (!(s && strcasecmp(s, "value1")==0)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read var \"testVar1\" with bad value (%s)", s?s:"<empty>");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
AQH_Vars_free(vtRoot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GWENHYWFAR_CB test3(GWEN_UNUSED GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
AQH_VARS *vtRoot;
|
||||
const char *testData=
|
||||
"testGroup1 {\n"
|
||||
" char testVar1=\"value1\"\n"
|
||||
"}";
|
||||
const char *s;
|
||||
|
||||
vtRoot=AQH_Vars_ReadDbFormat(testData);
|
||||
if (vtRoot==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading dbformat");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
if (NULL==AQH_Vars_GetGroup(vtRoot, "testGroup1", AQH_PATH_FLAGS_PATHMUSTEXIST)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read group \"testGroup1\" not found");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
s=AQH_Vars_GetCharValue(vtRoot, "testGroup1/testVar1", 0, NULL);
|
||||
if (!(s && strcasecmp(s, "value1")==0)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read var \"testVar1\" with bad value (%s)", s?s:"<empty>");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
AQH_Vars_free(vtRoot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GWENHYWFAR_CB test4(GWEN_UNUSED GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
AQH_VARS *vtRoot;
|
||||
const char *testData=
|
||||
"testGroup1 {\n"
|
||||
" char testVar1=\"value1\"\n"
|
||||
" secondGroup { # here starts the 2nd group\n"
|
||||
"# this is the second comment\n"
|
||||
" int firstVarOfSecondGroup=\"1234\";\n"
|
||||
" secondVarOfSecondGroup=\"secondValue\"\n"
|
||||
" }\n"
|
||||
"}";
|
||||
const char *s;
|
||||
int i;
|
||||
|
||||
vtRoot=AQH_Vars_ReadDbFormat(testData);
|
||||
if (vtRoot==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading dbformat");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
if (NULL==AQH_Vars_GetGroup(vtRoot, "testGroup1", AQH_PATH_FLAGS_PATHMUSTEXIST)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read group \"testGroup1\" not found");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
s=AQH_Vars_GetCharValue(vtRoot, "testGroup1/testVar1", 0, NULL);
|
||||
if (!(s && strcasecmp(s, "value1")==0)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read var \"testVar1\" with bad value (%s)", s?s:"<empty>");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
i=AQH_Vars_GetIntValue(vtRoot, "testGroup1/secondGroup/firstVarOfSecondGroup", 0, -1);
|
||||
if (i!=1234) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read var \"testGroup1/secondGroup/firstVarOfSecondGroup\" with bad value (%i)", i);
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
s=AQH_Vars_GetCharValue(vtRoot, "testGroup1/secondGroup/secondVarOfSecondGroup", 0, NULL);
|
||||
if (!(s && strcasecmp(s, "secondValue")==0)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Freshly read var \"testGroup1/secondGroup/secondVarOfSecondGroup\" with bad value (%s)", s?s:"<empty>");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
AQH_Vars_free(vtRoot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
int AQH_Vars_DbRead_AddTests(GWEN_TEST_MODULE *mod)
|
||||
{
|
||||
DBG_ERROR(GWEN_LOGDOMAIN, "AqHome was compiled without test code enabled.");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
29
aqhome/data/vars_dbread-t.h
Normal file
29
aqhome/data/vars_dbread-t.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project Gwenhywfar.
|
||||
* Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_VARS_DBREAD_T_H
|
||||
#define AQH_VARS_DBREAD_T_H
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include <gwenhywfar/gwenhywfarapi.h>
|
||||
#include <gwenhywfar/testframework.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests for "Vars" reading GWEN_DB data.
|
||||
*/
|
||||
AQHOME_API int AQH_Vars_DbRead_AddTests(GWEN_TEST_MODULE *mod);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
319
aqhome/data/vars_dbread.c
Normal file
319
aqhome/data/vars_dbread.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project Gwenhywfar.
|
||||
* Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "./vars_p.h"
|
||||
#include "./vars_dbread.h"
|
||||
#include "aqhome/data/path.h"
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
|
||||
const uint32_t _textFlags=
|
||||
GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS |
|
||||
GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS |
|
||||
GWEN_TEXT_FLAGS_DEL_QUOTES;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static const char *_readLine(AQH_VARS **pVars, const char *src, GWEN_BUFFER *wbuf);
|
||||
static const char *_readGroupOrVar(AQH_VARS **pVars, const char *src, GWEN_BUFFER *wbuf);
|
||||
static const char *_contAsTypedVar(AQH_VARS **pVars, const char *src, const char *tname, GWEN_BUFFER *wbuf);
|
||||
static const char *_contAsVar(AQH_VARS **pVars, AQH_VARS_DATATYPE dataType, const char *src, const char *vname, GWEN_BUFFER *wbuf);
|
||||
static const char *_readValue(AQH_VARS *vtVar, AQH_VARS_DATATYPE dataType, const char *s, GWEN_BUFFER *wbuf);
|
||||
static AQH_VARS *_mkStringValue(const char *s);
|
||||
static AQH_VARS *_mkIntValue(const char *s);
|
||||
static AQH_VARS *_mkDoubleValue(const char *s);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
AQH_VARS *AQH_Vars_ReadDbFormat(const char *src)
|
||||
{
|
||||
AQH_VARS *vtRoot;
|
||||
AQH_VARS *vt;
|
||||
GWEN_BUFFER *wbuf;
|
||||
const char *s;
|
||||
|
||||
vtRoot=AQH_Vars_CreateGroup("root");
|
||||
vt=vtRoot;
|
||||
wbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
s=src;
|
||||
while(*s) {
|
||||
GWEN_Buffer_Reset(wbuf);
|
||||
s=_readLine(&vt, s, wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
GWEN_Buffer_free(wbuf);
|
||||
AQH_Vars_free(vtRoot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
GWEN_Buffer_free(wbuf);
|
||||
|
||||
if (vt!=vtRoot) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Incomplete groups read");
|
||||
AQH_Vars_free(vtRoot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vtRoot;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *_readLine(AQH_VARS **pVars, const char *src, GWEN_BUFFER *wbuf)
|
||||
{
|
||||
int rv;
|
||||
const char *s;
|
||||
|
||||
s=src;
|
||||
while(*s && isblank(*s))
|
||||
s++;
|
||||
|
||||
if (*s=='}') {
|
||||
AQH_VARS *vt;
|
||||
|
||||
/* current group ends */
|
||||
vt=AQH_Vars_Tree2_GetParent(*pVars);
|
||||
*pVars=vt;
|
||||
s++;
|
||||
}
|
||||
else if (*s=='#') {
|
||||
/* rest of line is a comment */
|
||||
s++;
|
||||
while(*s && !(*s==10 || *s==13))
|
||||
s++;
|
||||
}
|
||||
else if (*s==10 || *s==13) {
|
||||
/* end of line, so empty line */
|
||||
}
|
||||
else {
|
||||
s=_readGroupOrVar(pVars, s, wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle end of line */
|
||||
while(*s && isblank(*s))
|
||||
s++;
|
||||
while(*s==10 || *s==13)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *_readGroupOrVar(AQH_VARS **pVars, const char *src, GWEN_BUFFER *wbuf)
|
||||
{
|
||||
const char *s;
|
||||
int rv;
|
||||
|
||||
rv=GWEN_Text_GetWordToBuffer(src, " ={#\t\r\n", wbuf, _textFlags, &s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(*s && isblank(*s))
|
||||
s++;
|
||||
|
||||
if (*s=='{') {
|
||||
AQH_VARS *vt;
|
||||
|
||||
/* read group */
|
||||
vt=AQH_Vars_CreateGroup(GWEN_Buffer_GetStart(wbuf));
|
||||
AQH_Vars_Tree2_AddChild(*pVars, vt);
|
||||
*pVars=vt;
|
||||
s++;
|
||||
}
|
||||
else if (*s=='=') {
|
||||
/* read untyped var, assume string */
|
||||
s=_contAsVar(pVars, AQH_Vars_DataType_ValueString, s, GWEN_Buffer_GetStart(wbuf), wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (*s=='#' || *s=='\r' || *s=='\n') {
|
||||
/* line logically or physically ends after first word, syntax error */
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Unexpected end of line");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
s=_contAsTypedVar(pVars, s, GWEN_Buffer_GetStart(wbuf), wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *_contAsTypedVar(AQH_VARS **pVars, const char *src, const char *tname, GWEN_BUFFER *wbuf)
|
||||
{
|
||||
AQH_VARS_DATATYPE dataType;
|
||||
const char *s;
|
||||
int rv;
|
||||
|
||||
/* got type, convert to type */
|
||||
dataType=AQH_Vars_DataTypeFromString(tname);
|
||||
if (dataType<AQH_Vars_DataType_ValueString || dataType>AQH_Vars_DataType_ValueDouble) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid type \"%s\"", tname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read name */
|
||||
GWEN_Buffer_Reset(wbuf);
|
||||
rv=GWEN_Text_GetWordToBuffer(src, " \t={#\r\n", wbuf, _textFlags, &s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(*s && isblank(*s))
|
||||
s++;
|
||||
|
||||
s=_contAsVar(pVars, dataType, s, GWEN_Buffer_GetStart(wbuf), wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *_contAsVar(AQH_VARS **pVars, AQH_VARS_DATATYPE dataType, const char *src, const char *vname, GWEN_BUFFER *wbuf)
|
||||
{
|
||||
const char *s;
|
||||
AQH_VARS *vtVar;
|
||||
|
||||
s=src;
|
||||
if (*s!='=') {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Expected \"=\"");
|
||||
return NULL;
|
||||
}
|
||||
s++;
|
||||
|
||||
vtVar=AQH_Vars_CreateVariable(vname);
|
||||
AQH_Vars_Tree2_AddChild(*pVars, vtVar);
|
||||
|
||||
while(*s) {
|
||||
GWEN_Buffer_Reset(wbuf);
|
||||
s=_readValue(vtVar, dataType, s, wbuf);
|
||||
if (s==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(*s && isblank(*s))
|
||||
s++;
|
||||
if (*s==';') {
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
if (*s!=',')
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *_readValue(AQH_VARS *vtVar, AQH_VARS_DATATYPE dataType, const char *s, GWEN_BUFFER *wbuf)
|
||||
{
|
||||
int rv;
|
||||
AQH_VARS *vtValue;
|
||||
|
||||
rv=GWEN_Text_GetWordToBuffer(s, " \t,;#\r\n", wbuf, _textFlags, &s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return NULL;
|
||||
}
|
||||
switch(dataType) {
|
||||
case AQH_Vars_DataType_ValueString: vtValue=_mkStringValue(GWEN_Buffer_GetStart(wbuf)); break;
|
||||
case AQH_Vars_DataType_ValueInt: vtValue=_mkIntValue(GWEN_Buffer_GetStart(wbuf)); break;
|
||||
case AQH_Vars_DataType_ValueDouble: vtValue=_mkDoubleValue(GWEN_Buffer_GetStart(wbuf)); break;
|
||||
default: vtValue=NULL; break;
|
||||
}
|
||||
if (vtValue==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
AQH_Vars_Tree2_AddChild(vtVar, vtValue);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VARS *_mkStringValue(const char *s)
|
||||
{
|
||||
return AQH_Vars_CreateStringValue(strdup(s));
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VARS *_mkIntValue(const char *s)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (1!=sscanf(s, "%i", &v)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not an int value [%s]", s);
|
||||
return NULL;
|
||||
}
|
||||
return AQH_Vars_CreateIntValue(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VARS *_mkDoubleValue(const char *s)
|
||||
{
|
||||
int rv;
|
||||
double v;
|
||||
|
||||
rv=GWEN_Text_StringToDouble(s, &v);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a double value [%s] (%d)", s, rv);
|
||||
return NULL;
|
||||
}
|
||||
return AQH_Vars_CreateDoubleValue(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "./vars_dbread-t.c"
|
||||
|
||||
24
aqhome/data/vars_dbread.h
Normal file
24
aqhome/data/vars_dbread.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project Gwenhywfar.
|
||||
* Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_VARS_DBREAD_H
|
||||
#define AQH_VARS_DBREAD_H
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include <aqhome/data/vars.h>
|
||||
|
||||
|
||||
AQHOME_API AQH_VARS *AQH_Vars_ReadDbFormat(const char *src);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user