216 lines
5.1 KiB
C
216 lines
5.1 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 "./path.h"
|
|
|
|
#include <gwenhywfar/stringlist.h>
|
|
#include <gwenhywfar/text.h>
|
|
#include <gwenhywfar/debug.h>
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void *_handleElement(const char *element, void *data, uint32_t flags, AQH_PATH_HANDLERFN fn);
|
|
static void _getPathBetween(const char *path1, const char *path2, GWEN_BUFFER *diffBuf);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
void *AQH_Path_Handle(const char *path, void *data, uint32_t flags, const char *delimiters, AQH_PATH_HANDLERFN fn)
|
|
{
|
|
if (path && *path) {
|
|
GWEN_STRINGLIST *elementList;
|
|
|
|
/* clear internal flags */
|
|
flags&=~AQH_PATH_FLAGS_LAST;
|
|
|
|
elementList=GWEN_StringList_fromString2(path, delimiters, 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;
|
|
}
|
|
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_PATH_HANDLERFN 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);
|
|
}
|
|
|
|
|
|
|
|
int AQH_Path_GetPathBetween(const char *path1, const char *path2, GWEN_BUFFER *diffBuf)
|
|
{
|
|
if (!(path1 && *path1)) {
|
|
if (path2 && *path2) {
|
|
GWEN_Buffer_AppendString(diffBuf, path2);
|
|
return 0;
|
|
}
|
|
else {
|
|
DBG_INFO(AQH_LOGDOMAIN, "Both paths are NULL.");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!(path2 && *path2)) {
|
|
GWEN_STRINGLIST *sl1;
|
|
|
|
sl1=GWEN_StringList_fromString2(path1, "/", 0, GWEN_TEXT_FLAGS_DEL_QUOTES | GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
|
|
if (sl1) {
|
|
int cnt;
|
|
int i;
|
|
|
|
cnt=GWEN_StringList_Count(sl1);
|
|
for (i=0; i<cnt; i++) {
|
|
if (i>0)
|
|
GWEN_Buffer_AppendString(diffBuf, "/");
|
|
GWEN_Buffer_AppendString(diffBuf, "..");
|
|
}
|
|
GWEN_StringList_free(sl1);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
_getPathBetween(path1, path2, diffBuf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _getPathBetween(const char *path1, const char *path2, GWEN_BUFFER *diffBuf)
|
|
{
|
|
GWEN_STRINGLIST *sl1;
|
|
GWEN_STRINGLIST *sl2;
|
|
GWEN_STRINGLISTENTRY *se;
|
|
int count;
|
|
int i;
|
|
|
|
sl2=GWEN_StringList_fromString2(path2, "/", 0, GWEN_TEXT_FLAGS_DEL_QUOTES | GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
|
|
sl1=GWEN_StringList_fromString2(path1, "/", 0, GWEN_TEXT_FLAGS_DEL_QUOTES | GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
|
|
|
|
GWEN_StringList_RemoveCommonFirstEntries(sl1, sl2);
|
|
|
|
count=GWEN_StringList_Count(sl1);
|
|
for (i=0; i<count; i++) {
|
|
if (GWEN_Buffer_GetUsedBytes(diffBuf))
|
|
GWEN_Buffer_AppendString(diffBuf, "/");
|
|
GWEN_Buffer_AppendString(diffBuf, "..");
|
|
}
|
|
GWEN_StringList_free(sl1);
|
|
|
|
se=GWEN_StringList_FirstEntry(sl2);
|
|
while(se) {
|
|
const char *s;
|
|
|
|
s=GWEN_StringListEntry_Data(se);
|
|
if (s && *s) {
|
|
if (GWEN_Buffer_GetUsedBytes(diffBuf))
|
|
GWEN_Buffer_AppendString(diffBuf, "/");
|
|
GWEN_Buffer_AppendString(diffBuf, s);
|
|
}
|
|
|
|
se=GWEN_StringListEntry_Next(se);
|
|
}
|
|
GWEN_StringList_free(sl2);
|
|
}
|
|
|
|
|
|
|
|
#include "./path-t.c"
|
|
|
|
|
|
|
|
|