249 lines
6.2 KiB
C
249 lines
6.2 KiB
C
/****************************************************************************
|
|
* This file is part of the project AqHome.
|
|
* 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.
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
|
|
|
|
#include "./vars_p.h"
|
|
#include "./vars_dbwrite.h"
|
|
#include "aqhome/data/path.h"
|
|
|
|
#include <gwenhywfar/misc.h>
|
|
#include <gwenhywfar/text.h>
|
|
#include <gwenhywfar/syncio.h>
|
|
#include <gwenhywfar/debug.h>
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* definitions
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
const char *_acceptableChars=",.:;-+/&";
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static int _groupToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent);
|
|
static int _groupChildrenToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent);
|
|
static int _varToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent);
|
|
static void _appendEscapedString(const char *s, GWEN_BUFFER *dbuf);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
|
|
int AQH_Vars_WriteDbFile(const AQH_VARS *vt, const char *filename)
|
|
{
|
|
int rv;
|
|
GWEN_BUFFER *fbuf;
|
|
GWEN_BUFFER *dbuf;
|
|
|
|
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
|
GWEN_Buffer_AppendString(fbuf, filename);
|
|
GWEN_Buffer_AppendString(fbuf, ".tmp");
|
|
|
|
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
|
rv=AQH_Vars_WriteDbFormat(vt, dbuf);
|
|
if (rv<0) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(dbuf);
|
|
GWEN_Buffer_free(fbuf);
|
|
return rv;
|
|
}
|
|
|
|
rv=GWEN_SyncIo_Helper_WriteFile(GWEN_Buffer_GetStart(fbuf),
|
|
(const uint8_t*) GWEN_Buffer_GetStart(dbuf),
|
|
GWEN_Buffer_GetUsedBytes(dbuf));
|
|
if (rv<0) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(dbuf);
|
|
GWEN_Buffer_free(fbuf);
|
|
return rv;
|
|
}
|
|
GWEN_Buffer_free(dbuf);
|
|
|
|
if (rename(GWEN_Buffer_GetStart(fbuf), filename)) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d: %s)", errno, strerror(errno));
|
|
GWEN_Buffer_free(fbuf);
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
GWEN_Buffer_free(fbuf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQH_Vars_WriteDbFormat(const AQH_VARS *vt, GWEN_BUFFER *dbuf)
|
|
{
|
|
if (vt && dbuf) {
|
|
int rv;
|
|
|
|
rv=_groupChildrenToBuffer(vt, dbuf, 0);
|
|
if (rv<0) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _groupToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent)
|
|
{
|
|
int rv;
|
|
|
|
if (indent)
|
|
GWEN_Buffer_FillWithBytes(dbuf, ' ', indent);
|
|
|
|
if (vt->data.dataString && *(vt->data.dataString)) {
|
|
_appendEscapedString(vt->data.dataString, dbuf);
|
|
GWEN_Buffer_AppendString(dbuf, " {\n");
|
|
}
|
|
else {
|
|
DBG_ERROR(AQH_LOGDOMAIN, "Group has no name");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
rv=_groupChildrenToBuffer(vt, dbuf, indent+2);
|
|
if (rv<0) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
if (indent)
|
|
GWEN_Buffer_FillWithBytes(dbuf, ' ', indent);
|
|
GWEN_Buffer_AppendString(dbuf, "}\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _groupChildrenToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent)
|
|
{
|
|
const AQH_VARS *vtChild;
|
|
|
|
vtChild=AQH_Vars_Tree2_GetFirstChild(vt);
|
|
while(vtChild) {
|
|
int rv;
|
|
|
|
switch(vtChild->dataType) {
|
|
case AQH_Vars_DataType_Group: rv=_groupToBuffer(vtChild, dbuf, indent+2); break;
|
|
case AQH_Vars_DataType_Variable: rv=_varToBuffer(vtChild, dbuf, indent+2); break;
|
|
default:
|
|
DBG_ERROR(AQH_LOGDOMAIN,
|
|
"Unexpected data type \"%d\" (%s)",
|
|
vtChild->dataType,
|
|
AQH_Vars_DataTypeToString(vtChild->dataType));
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
if (rv<0) {
|
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
vtChild=AQH_Vars_Tree2_GetNext(vtChild);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _varToBuffer(const AQH_VARS *vt, GWEN_BUFFER *dbuf, int indent)
|
|
{
|
|
const AQH_VARS *vtChild;
|
|
int isFirst=1;
|
|
|
|
vtChild=AQH_Vars_Tree2_GetFirstChild(vt);
|
|
if (vtChild) {
|
|
if (vt->data.dataString && *(vt->data.dataString)) {
|
|
if (indent)
|
|
GWEN_Buffer_FillWithBytes(dbuf, ' ', indent);
|
|
GWEN_Buffer_AppendArgs(dbuf, "%s ", AQH_Vars_DataTypeToString(vtChild->dataType));
|
|
_appendEscapedString(vt->data.dataString, dbuf);
|
|
GWEN_Buffer_AppendString(dbuf, "=");
|
|
}
|
|
else {
|
|
DBG_ERROR(AQH_LOGDOMAIN, "Variable has no name");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
while(vtChild) {
|
|
if (!isFirst) {
|
|
GWEN_Buffer_AppendString(dbuf, ", ");
|
|
isFirst=0;
|
|
}
|
|
|
|
switch(vtChild->dataType) {
|
|
case AQH_Vars_DataType_ValueString:
|
|
GWEN_Buffer_AppendByte(dbuf, '\"');
|
|
_appendEscapedString(vtChild->data.dataString, dbuf);
|
|
GWEN_Buffer_AppendByte(dbuf, '\"');
|
|
break;
|
|
case AQH_Vars_DataType_ValueInt:
|
|
GWEN_Buffer_AppendArgs(dbuf, "\"%d\"", vtChild->data.dataInt);
|
|
break;
|
|
case AQH_Vars_DataType_ValueDouble:
|
|
GWEN_Buffer_AppendArgs(dbuf, "\"%f\"", vtChild->data.dataDouble);
|
|
break;
|
|
default:
|
|
DBG_ERROR(AQH_LOGDOMAIN, "Unexpected data type \"%d\" (%s)", vtChild->dataType, AQH_Vars_DataTypeToString(vtChild->dataType));
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
vtChild=AQH_Vars_Tree2_GetNext(vtChild);
|
|
}
|
|
GWEN_Buffer_AppendString(dbuf, "\n");
|
|
} /* if vtChild */
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _appendEscapedString(const char *s, GWEN_BUFFER *dbuf)
|
|
{
|
|
while(*s) {
|
|
unsigned char x;
|
|
|
|
x=*s;
|
|
if ((x>='A' && x<='Z') || (x>='a' && x<='z') || (x>='0' && x<='9') || strchr(_acceptableChars, x))
|
|
GWEN_Buffer_AppendByte(dbuf, x);
|
|
else
|
|
GWEN_Buffer_AppendArgs(dbuf, "%%%02x", x);
|
|
|
|
s++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "./vars_dbwrite-t.c"
|
|
|