/** @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;
|
}
|