Files
aqhomecontrol/aqhome/data/path.c
Martin Preuss bcc7629b1e aqhome: added PATH module, started VARS module.
those might later get incorporated into libgwenhywfar.
2024-05-07 23:57:07 +02:00

136 lines
2.8 KiB
C

/****************************************************************************
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./path.h"
#include <gwenhywfar/stringlist.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
static void *_handleElement(const char *element, void *data, uint32_t flags, AQH_PATHHANDLERFN fn);
void *AQH_Path_Handle(const char *path, void *data, uint32_t flags, AQH_PATHHANDLERFN fn)
{
if (path && *path) {
GWEN_STRINGLIST *elementList;
/* clear internal flags */
flags&=~(AQH_PATH_FLAGS_ROOT | AQH_PATH_FLAGS_LAST);
if (*path=='/') {
flags|=AQH_PATH_FLAGS_ROOT;
path++;
}
elementList=GWEN_StringList_fromString2(path, "/", 0, GWEN_TEXT_FLAGS_CHECK_BACKSLASH | GWEN_TEXT_FLAGS_DEL_QUOTES);
if (elementList) {
GWEN_STRINGLISTENTRY *se;
se=GWEN_StringList_FirstEntry(elementList);
while(se) {
const char *s;
GWEN_STRINGLISTENTRY *seNext;
seNext=GWEN_StringListEntry_Next(se);
if (seNext)
flags&=~AQH_PATH_FLAGS_LAST;
else
flags|=AQH_PATH_FLAGS_LAST;
s=GWEN_StringListEntry_Data(se);
if (s && *s) {
void *result;
result=_handleElement(s, data, flags, fn);
if (result==NULL) {
DBG_INFO(NULL, "Error handling element \"%s\" (%08x)", s, flags);
GWEN_StringList_free(elementList);
return NULL;
}
data=result;
}
flags&=~AQH_PATH_FLAGS_ROOT;
se=GWEN_StringListEntry_Next(se);
}
GWEN_StringList_free(elementList);
return data;
}
else {
DBG_INFO(NULL, "Error reading path \"%s\" into stringlist", path);
}
}
else {
DBG_ERROR(NULL, "Empty path given");
}
return NULL;
}
void *_handleElement(const char *element, void *data, uint32_t flags, AQH_PATHHANDLERFN fn)
{
if (flags & AQH_PATH_FLAGS_PARSEIDX) {
const char *ptrOpenBracket;
ptrOpenBracket=strchr(element, '[');
if (ptrOpenBracket) {
if (ptrOpenBracket!=element) {
const char *s;
int idx=0;
s=ptrOpenBracket+1;
while(*s && isdigit(*s)) {
idx*=10;
idx+=*s-'0';
s++;
}
if (*s!=']') {
DBG_ERROR(NULL, "Closed bracket expected (got \"%c\")", *s);
return NULL;
}
else {
char *rawElement;
void *result;
s++;
rawElement=GWEN_Text_strndup(element, ptrOpenBracket-element);
result=fn?fn(rawElement, data, idx, flags):data;
free(rawElement);
return result;
}
}
else {
DBG_ERROR(NULL, "Empty element with index");
return NULL;
}
}
}
return fn(element, data, 0, flags);
}
#include "./path-t.c"