/** @file
This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
by EDKII.
//----------------------------------------------------------------------------
// Copyright Notice:
// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
//----------------------------------------------------------------------------
Copyright (c) 2019, Intel Corporation. All rights reserved.
(C) Copyright 2021 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
static char *
getVersion (
const char *path,
char **end
);
static void
parseNode (
const char *path,
redPathNode *node,
redPathNode **end
);
static char *
getStringTill (
const char *string,
const char *terminator,
char **retEnd
);
redPathNode *
parseRedPath (
const char *path
)
{
redPathNode *node;
redPathNode *endNode;
char *curPath;
char *end;
if (!path || (strlen (path) == 0)) {
return NULL;
}
node = (redPathNode *)calloc (1, sizeof (redPathNode));
if (!node) {
return NULL;
}
if (path[0] == '/') {
node->isRoot = true;
if (path[1] == 'v') {
node->version = getVersion (path+1, &curPath);
if (curPath == NULL) {
return node;
}
if (curPath[0] == '/') {
curPath++;
}
node->next = parseRedPath (curPath);
} else {
node->next = parseRedPath (path+1);
}
return node;
}
node->isRoot = false;
curPath = getStringTill (path, "/", &end);
endNode = node;
parseNode (curPath, node, &endNode);
free (curPath);
if (end != NULL) {
endNode->next = parseRedPath (end+1);
}
return node;
}
void
cleanupRedPath (
redPathNode *node
)
{
if (!node) {
return;
}
cleanupRedPath (node->next);
node->next = NULL;
if (node->version) {
free (node->version);
}
if (node->nodeName) {
free (node->nodeName);
}
if (node->op) {
free (node->op);
}
if (node->propName) {
free (node->propName);
}
if (node->value) {
free (node->value);
}
free (node);
}
static char *
getVersion (
const char *path,
char **end
)
{
return getStringTill (path, "/", end);
}
static void
parseNode (
const char *path,
redPathNode *node,
redPathNode **end
)
{
char *indexStart;
char *index;
char *indexEnd;
char *nodeName = getStringTill (path, "[", &indexStart);
size_t tmpIndex;
char *opChars;
node->nodeName = nodeName;
if (indexStart == NULL) {
*end = node;
return;
}
node->next = (redPathNode *)calloc (1, sizeof (redPathNode));
if (!node->next) {
return;
}
// Skip past [
indexStart++;
*end = node->next;
index = getStringTill (indexStart, "]", NULL);
tmpIndex = (size_t)strtoull (index, &indexEnd, 0);
if (indexEnd != index) {
free (index);
node->next->index = tmpIndex;
node->next->isIndex = true;
return;
}
opChars = strpbrk (index, "<>=~");
if (opChars == NULL) {
// TODO handle last() and position()
node->next->op = strdup ("exists");
node->next->propName = index;
return;
}
node->next->propName = (char *)malloc ((opChars - index)+1);
memcpy (node->next->propName, index, (opChars - index));
node->next->propName[(opChars - index)] = 0;
tmpIndex = 1;
while (1) {
if ((opChars[tmpIndex] == '=') || (opChars[tmpIndex] == '<') || (opChars[tmpIndex] == '>') || (opChars[tmpIndex] == '~')) {
tmpIndex++;
continue;
}
break;
}
node->next->op = (char *)malloc (tmpIndex+1);
memcpy (node->next->op, opChars, tmpIndex);
node->next->op[tmpIndex] = 0;
node->next->value = strdup (opChars+tmpIndex);
free (index);
}
static char *
getStringTill (
const char *string,
const char *terminator,
char **retEnd
)
{
char *ret;
char *end;
end = strstr ((char *)string, terminator);
if (retEnd) {
*retEnd = end;
}
if (end == NULL) {
// No terminator
return strdup (string);
}
ret = (char *)malloc ((end-string)+1);
memcpy (ret, string, (end-string));
ret[(end-string)] = 0;
return ret;
}