/** @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.<BR> | |
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <redpath.h> | |
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; | |
} |