2019-09-03 11:58:42 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
|
|
*
|
|
|
|
* The contents of this file constitute Original Code as defined in and
|
|
|
|
* are subject to the Apple Public Source License Version 1.1 (the
|
|
|
|
* "License"). You may not use this file except in compliance with the
|
|
|
|
* License. Please obtain a copy of the License at
|
|
|
|
* http://www.apple.com/publicsource and read it before using this file.
|
|
|
|
*
|
|
|
|
* This Original Code and all software distributed under the License are
|
|
|
|
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
|
|
|
|
* License for the specific language governing rights and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* plist.c - plist parsing functions
|
|
|
|
*
|
|
|
|
* Copyright (c) 2000-2005 Apple Computer, Inc.
|
|
|
|
*
|
|
|
|
* DRI: Josh de Cesare
|
|
|
|
* code split out from drivers.c by Soren Spies, 2005
|
|
|
|
*/
|
|
|
|
//Slice - rewrite for UEFI with more functions like Copyright (c) 2003 Apple Computer
|
2020-08-17 21:40:52 +02:00
|
|
|
#include <Platform.h> // Only use angled for Platform, else, xcode project won't compile
|
2020-04-16 09:15:26 +02:00
|
|
|
#include "b64cdecode.h"
|
2020-04-22 19:52:21 +02:00
|
|
|
#include "plist.h"
|
|
|
|
#include "../libeg/FloatLib.h"
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
#ifndef DEBUG_ALL
|
|
|
|
#define DEBUG_PLIST 0
|
|
|
|
#else
|
|
|
|
#define DEBUG_PLIST DEBUG_ALL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG_PLIST == 0
|
|
|
|
#define DBG(...)
|
|
|
|
#else
|
|
|
|
#define DBG(...) DebugLog(DEBUG_PLIST, __VA_ARGS__)
|
|
|
|
#endif
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
XObjArray<TagStruct> gTagsFree;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TagStruct::FreeTag()
|
|
|
|
{
|
|
|
|
// Clear and free the tag.
|
|
|
|
type = kTagTypeNone;
|
|
|
|
|
|
|
|
_string.setEmpty();
|
|
|
|
_intValue = 0;
|
|
|
|
_floatValue = 0;
|
|
|
|
|
|
|
|
if ( _data ) {
|
|
|
|
FreePool(_data);
|
|
|
|
_data = NULL;
|
|
|
|
}
|
|
|
|
_dataLen = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if ( _tag ) {
|
|
|
|
_tag->FreeTag();
|
|
|
|
_tag = NULL;
|
|
|
|
}
|
|
|
|
if ( _nextTag ) {
|
|
|
|
_nextTag->FreeTag();
|
|
|
|
_nextTag = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gTagsFree.AddReference(this, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-09-03 11:58:42 +02:00
|
|
|
|
2020-04-16 11:09:22 +02:00
|
|
|
|
2019-09-03 11:58:42 +02:00
|
|
|
CHAR8* buffer_start = NULL;
|
|
|
|
|
|
|
|
// Forward declarations
|
2020-08-18 18:45:44 +02:00
|
|
|
EFI_STATUS ParseTagDict( CHAR8* buffer, TagPtr * tag, UINT32 empty, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagArray( CHAR8* buffer, TagPtr * tag, UINT32 empty, UINT32* lenPtr);
|
2020-04-22 19:52:21 +02:00
|
|
|
EFI_STATUS ParseTagKey( char * buffer, TagPtr * tag, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagString(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagInteger(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagFloat(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagData(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr);
|
|
|
|
EFI_STATUS ParseTagDate(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr);
|
2020-08-18 18:45:44 +02:00
|
|
|
EFI_STATUS ParseTagBoolean(CHAR8* buffer, TagPtr * tag, bool value, UINT32* lenPtr);
|
2019-09-03 11:58:42 +02:00
|
|
|
//defined in Platform.h
|
|
|
|
//EFI_STATUS GetElement( TagPtr dict, INTN id, TagPtr *dict1);
|
|
|
|
//INTN GetTagCount( TagPtr dict );
|
|
|
|
|
|
|
|
TagPtr NewTag( void );
|
2020-02-17 21:41:09 +01:00
|
|
|
EFI_STATUS FixDataMatchingTag( CHAR8* buffer, CONST CHAR8* tag,UINT32* lenPtr);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
/* Function for basic XML character entities parsing */
|
|
|
|
typedef struct XMLEntity {
|
|
|
|
const CHAR8* name;
|
|
|
|
UINTN nameLen;
|
|
|
|
CHAR8 value;
|
|
|
|
} XMLEntity;
|
|
|
|
|
|
|
|
/* This is ugly, but better than specifying the lengths by hand */
|
|
|
|
#define _e(str,c) {str,sizeof(str)-1,c}
|
|
|
|
CONST XMLEntity ents[] = {
|
|
|
|
_e("quot;",'"'), _e("apos;",'\''),
|
|
|
|
_e("lt;", '<'), _e("gt;", '>'),
|
|
|
|
_e("amp;", '&')
|
|
|
|
};
|
|
|
|
|
2020-08-15 15:47:56 +02:00
|
|
|
/* Replace XML entities by their value */
|
2019-09-03 11:58:42 +02:00
|
|
|
CHAR8*
|
|
|
|
XMLDecode(CHAR8* src)
|
|
|
|
{
|
|
|
|
UINTN len;
|
|
|
|
CONST CHAR8 *s;
|
|
|
|
CHAR8 *out, *o;
|
|
|
|
|
|
|
|
if (!src) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = AsciiStrLen(src);
|
|
|
|
|
|
|
|
#if 0
|
2020-08-15 15:47:56 +02:00
|
|
|
out = (__typeof__(out))AllocateZeroPool(len+1);
|
2019-09-03 11:58:42 +02:00
|
|
|
if (!out)
|
|
|
|
return 0;
|
|
|
|
#else // unsafe
|
|
|
|
// out is always <= src, let's overwrite src
|
|
|
|
out = src;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
o = out;
|
|
|
|
s = src;
|
|
|
|
while (s <= src+len) /* Make sure the terminator is also copied */
|
|
|
|
{
|
2020-04-22 19:52:21 +02:00
|
|
|
if ( *s == '&' ) {
|
2019-09-03 11:58:42 +02:00
|
|
|
BOOLEAN entFound = FALSE;
|
|
|
|
UINTN i;
|
|
|
|
s++;
|
2020-04-22 19:52:21 +02:00
|
|
|
for (i = 0; i < sizeof(ents)/sizeof(ents[0]); i++) {
|
2020-05-16 21:30:29 +02:00
|
|
|
if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) {
|
2019-09-03 11:58:42 +02:00
|
|
|
entFound = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-04-22 19:52:21 +02:00
|
|
|
if ( entFound ) {
|
2019-09-03 11:58:42 +02:00
|
|
|
*o++ = ents[i].value;
|
|
|
|
s += ents[i].nameLen;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*o++ = *s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTN GetTagCount( TagPtr dict )
|
|
|
|
{
|
|
|
|
INTN count = 0;
|
|
|
|
TagPtr tagList, tag;
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if ( !dict || (!dict->isDict() && !dict->isArray()) ) {
|
2019-09-03 11:58:42 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
tag = 0;
|
2020-08-18 18:45:44 +02:00
|
|
|
tagList = dict->dictOrArrayTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
while (tagList)
|
|
|
|
{
|
|
|
|
tag = tagList;
|
2020-08-18 18:45:44 +02:00
|
|
|
tagList = tag->nextTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if ( (dict->isDict() && tag->isKey()) ||
|
|
|
|
dict->isArray() // If we are an array, any element is valid
|
2019-09-03 11:58:42 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->stringValue());
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS GetElement( TagPtr dict, INTN id, TagPtr * dict1)
|
|
|
|
{
|
|
|
|
INTN element = 0;
|
|
|
|
TagPtr child;
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if( !dict || (!dict->isArray() && !dict->isDict()) ) {
|
2019-09-03 11:58:42 +02:00
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
child = dict->dictOrArrayTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
while (child != NULL)
|
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
if ( (dict->isDict() && child->isKey()) || //in Dict count Keys
|
|
|
|
dict->isArray() // If we are an array, any element is valid
|
2019-09-03 11:58:42 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if (element++ >= id) break;
|
|
|
|
}
|
2020-08-18 18:45:44 +02:00
|
|
|
child = child->nextTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
*dict1 = child;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expects to see one dictionary in the XML file, the final pos will be returned
|
|
|
|
// If the pos is not equal to the strlen, then there are multiple dicts
|
|
|
|
// Puts the first dictionary it finds in the
|
|
|
|
// tag pointer and returns the end of the dic, or returns -1 if not found.
|
|
|
|
//
|
|
|
|
|
|
|
|
EFI_STATUS ParseXML(const CHAR8* buffer, TagPtr * dict, UINT32 bufSize)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
UINT32 pos = 0;
|
|
|
|
TagPtr tag = NULL;
|
|
|
|
CHAR8* configBuffer = NULL;
|
|
|
|
UINT32 bufferSize = 0;
|
|
|
|
UINTN i;
|
|
|
|
|
|
|
|
if (bufSize) {
|
|
|
|
bufferSize = bufSize;
|
|
|
|
} else {
|
|
|
|
bufferSize = (UINT32)AsciiStrLen(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(dict == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2020-08-15 15:47:56 +02:00
|
|
|
configBuffer = (__typeof__(configBuffer))AllocateZeroPool(bufferSize+1);
|
2019-09-03 11:58:42 +02:00
|
|
|
if(configBuffer == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem(configBuffer, buffer, bufferSize);
|
|
|
|
for (i=0; i<bufferSize; i++) {
|
|
|
|
if (configBuffer[i] == 0) {
|
|
|
|
configBuffer[i] = 0x20; //replace random zero bytes to spaces
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer_start = configBuffer;
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
Status = XMLParseNextTag(configBuffer + pos, &tag, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
DBG("error parsing next tag\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += length;
|
|
|
|
|
|
|
|
if (tag == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-08-18 18:45:44 +02:00
|
|
|
if (tag->isDict()) {
|
2019-09-03 11:58:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeTag(tag); tag = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FreePool(configBuffer);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
*dict = tag;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// xml
|
|
|
|
//
|
|
|
|
|
|
|
|
#define DOFREE 1
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// GetProperty
|
|
|
|
|
|
|
|
TagPtr GetProperty( TagPtr dict, const CHAR8* key )
|
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
if ( !dict->isDict() ) return NULL;
|
|
|
|
|
|
|
|
TagPtr tag = NULL;
|
|
|
|
TagPtr tagList = dict->dictOrArrayTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
while (tagList)
|
|
|
|
{
|
|
|
|
tag = tagList;
|
2020-08-18 18:45:44 +02:00
|
|
|
tagList = tag->nextTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if ( tag->isKey() && tag->keyValue().equalIC(key) ) return tag->keyTagValue();
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
//TagPtr GetNextProperty(TagPtr dict)
|
|
|
|
//{
|
|
|
|
// TagPtr tagList, tag;
|
|
|
|
//
|
|
|
|
// if (dict->isDict()) {
|
|
|
|
// return NULL;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// tag = NULL;
|
|
|
|
// tagList = dict->tag;
|
|
|
|
// while (tagList)
|
|
|
|
// {
|
|
|
|
// tag = tagList;
|
|
|
|
// tagList = tag->tagNext;
|
|
|
|
//
|
|
|
|
// if ( !tag->isKey() || tag->keyValue().isEmpty() ) {
|
|
|
|
// continue;
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
// return tag->tag;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// return NULL;
|
|
|
|
//}
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseNextTag
|
|
|
|
|
|
|
|
EFI_STATUS XMLParseNextTag(CHAR8* buffer, TagPtr* tag, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
UINT32 pos = 0;
|
|
|
|
CHAR8* tagName = NULL;
|
|
|
|
|
|
|
|
*lenPtr=0;
|
|
|
|
|
|
|
|
Status = GetNextTag((UINT8*)buffer, &tagName, 0, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
2020-03-25 19:32:44 +01:00
|
|
|
DBG("NextTag error %s\n", strerror(Status));
|
2019-09-03 11:58:42 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = length;
|
2020-05-16 21:30:29 +02:00
|
|
|
if (!strncmp(tagName, kXMLTagPList, 6)) {
|
2019-09-03 11:58:42 +02:00
|
|
|
length=0;
|
|
|
|
Status=EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
/***** dict ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagDict))
|
|
|
|
{
|
|
|
|
DBG("begin dict len=%d\n", length);
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagDict(buffer + pos, tag, 0, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagDict "/"))
|
|
|
|
{
|
|
|
|
DBG("end dict len=%d\n", length);
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagDict(buffer + pos, tag, 1, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagDict " ", 5))
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
DBG("space dict len=%d\n", length);
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagDict(buffer + pos, tag, 0, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
/***** key ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagKey))
|
|
|
|
{
|
|
|
|
DBG("parse key\n");
|
|
|
|
Status = ParseTagKey(buffer + pos, tag, &length);
|
|
|
|
}
|
|
|
|
/***** string ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagString))
|
|
|
|
{
|
|
|
|
DBG("parse String\n");
|
|
|
|
Status = ParseTagString(buffer + pos, tag, &length);
|
|
|
|
}
|
|
|
|
/***** string ****/
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagString " ", 7))
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
DBG("parse String len=%d\n", length);
|
|
|
|
Status = ParseTagString(buffer + pos, tag, &length);
|
|
|
|
}
|
|
|
|
/***** integer ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagInteger))
|
|
|
|
{
|
|
|
|
Status = ParseTagInteger(buffer + pos, tag, &length);
|
|
|
|
}
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagInteger " ", 8))
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
Status = ParseTagInteger(buffer + pos, tag, &length);
|
|
|
|
}
|
2020-04-22 19:52:21 +02:00
|
|
|
/***** float ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagFloat))
|
|
|
|
{
|
|
|
|
Status = ParseTagFloat(buffer + pos, tag, &length);
|
|
|
|
}
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagFloat " ", 8))
|
2020-04-22 19:52:21 +02:00
|
|
|
{
|
|
|
|
Status = ParseTagFloat(buffer + pos, tag, &length);
|
|
|
|
}
|
2019-09-03 11:58:42 +02:00
|
|
|
/***** data ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagData))
|
|
|
|
{
|
|
|
|
Status = ParseTagData(buffer + pos, tag, &length);
|
|
|
|
}
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagData " ", 5))
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
Status = ParseTagData(buffer + pos, tag, &length);
|
|
|
|
}
|
|
|
|
/***** date ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagDate))
|
|
|
|
{
|
|
|
|
Status = ParseTagDate(buffer + pos, tag, &length);
|
|
|
|
}
|
|
|
|
/***** FALSE ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagFalse))
|
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagBoolean(buffer + pos, tag, false, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
/***** TRUE ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagTrue))
|
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagBoolean(buffer + pos, tag, true, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
/***** array ****/
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagArray))
|
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagArray(buffer + pos, tag, 0, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
2020-05-16 21:30:29 +02:00
|
|
|
else if (!strncmp(tagName, kXMLTagArray " ", 6))
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
DBG("begin array len=%d\n", length);
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagArray(buffer + pos, tag, 0, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
else if (!AsciiStrCmp(tagName, kXMLTagArray "/"))
|
|
|
|
{
|
|
|
|
DBG("end array len=%d\n", length);
|
2020-08-18 18:45:44 +02:00
|
|
|
Status = ParseTagArray(buffer + pos, tag, 1, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
/***** unknown ****/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tag = NULL;
|
|
|
|
length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-02-17 21:41:09 +01:00
|
|
|
// TODO jief : seems to me that length cannot be -1. Added the cast anyway to avoid regression. If confirmed, the next 3 lines must be removed.
|
|
|
|
if (length == (UINT32)-1) {
|
2019-09-03 11:58:42 +02:00
|
|
|
DBG("(length == -1)\n");
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
*lenPtr = pos + length;
|
|
|
|
DBG(" len after success parse next tag %d\n", *lenPtr);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseTagList
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
EFI_STATUS __ParseTagList(bool isArray, CHAR8* buffer, TagPtr* tag, UINT32 empty, UINT32* lenPtr)
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
|
|
UINT32 pos;
|
|
|
|
TagPtr tagList;
|
|
|
|
TagPtr tagTail;
|
|
|
|
TagPtr tmpTag = NULL;
|
|
|
|
UINT32 length = 0;
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if (isArray) {
|
2019-09-03 11:58:42 +02:00
|
|
|
DBG("parsing array len=%d\n", *lenPtr);
|
2020-08-18 18:45:44 +02:00
|
|
|
} else {
|
2019-09-03 11:58:42 +02:00
|
|
|
DBG("parsing dict len=%d\n", *lenPtr);
|
|
|
|
}
|
|
|
|
tagList = NULL;
|
|
|
|
tagTail = NULL;
|
|
|
|
pos = 0;
|
|
|
|
|
|
|
|
if (!empty) {
|
|
|
|
while (TRUE) {
|
|
|
|
Status = XMLParseNextTag(buffer + pos, &tmpTag, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
2020-03-25 19:32:44 +01:00
|
|
|
DBG("error XMLParseNextTag in array: %s\n", strerror(Status));
|
2019-09-03 11:58:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += length;
|
|
|
|
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tagTail) {
|
2020-08-18 18:45:44 +02:00
|
|
|
tagTail->setNextTagValue(tmpTag);
|
2019-09-03 11:58:42 +02:00
|
|
|
} else {
|
|
|
|
tagList = tmpTag;
|
|
|
|
}
|
|
|
|
tagTail = tmpTag;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
if (tagList) {
|
|
|
|
FreeTag(tagList);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
if (tagList) {
|
|
|
|
FreeTag(tagList);
|
|
|
|
}
|
|
|
|
DBG("next tag is NULL\n");
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if (isArray) {
|
|
|
|
tmpTag->setArrayTagValue(tagList);
|
|
|
|
} else {
|
|
|
|
tmpTag->setDictTagValue(tagList);
|
|
|
|
}
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr=pos;
|
|
|
|
DBG(" return from ParseTagList with len=%d\n", *lenPtr);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
EFI_STATUS ParseTagDict( CHAR8* buffer, TagPtr* tag, UINT32 empty, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
return __ParseTagList(false, buffer, tag, empty, lenPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagArray( CHAR8* buffer, TagPtr* tag, UINT32 empty, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
return __ParseTagList(true, buffer, tag, empty, lenPtr);
|
|
|
|
}
|
|
|
|
|
2019-09-03 11:58:42 +02:00
|
|
|
//==========================================================================
|
|
|
|
// ParseTagKey
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagKey( char * buffer, TagPtr* tag, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
UINT32 length2 = 0;
|
|
|
|
TagPtr tmpTag;
|
|
|
|
TagPtr subTag = NULL;
|
|
|
|
|
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagKey, &length);
|
2020-03-25 19:32:44 +01:00
|
|
|
DBG("fixing key len=%d status=%s\n", length, strerror(Status));
|
2019-09-03 11:58:42 +02:00
|
|
|
if (EFI_ERROR(Status)){
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = XMLParseNextTag(buffer + length, &subTag, &length2);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
tmpTag = NewTag();
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setKeyValue(LString8(buffer), subTag);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length + length2;
|
2020-03-25 19:32:44 +01:00
|
|
|
DBG("parse key '%s' success len=%d\n", tmpString, *lenPtr);
|
2019-09-03 11:58:42 +02:00
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseTagString
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagString(CHAR8* buffer, TagPtr * tag,UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
TagPtr tmpTag;
|
|
|
|
|
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagString, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setStringValue(LString8(XMLDecode(buffer)));
|
2019-09-03 11:58:42 +02:00
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length;
|
2020-03-25 19:32:44 +01:00
|
|
|
DBG(" parse string %s\n", tmpString);
|
2019-09-03 11:58:42 +02:00
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseTagInteger
|
|
|
|
|
2020-04-22 19:52:21 +02:00
|
|
|
EFI_STATUS ParseTagInteger(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr)
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
INTN integer;
|
|
|
|
UINT32 size;
|
|
|
|
BOOLEAN negative = FALSE;
|
|
|
|
CHAR8* val = buffer;
|
|
|
|
TagPtr tmpTag;
|
|
|
|
|
2020-04-22 19:52:21 +02:00
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagInteger, &length);
|
2019-09-03 11:58:42 +02:00
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setIntValue(0);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
2020-08-17 21:40:52 +02:00
|
|
|
size = length;
|
2019-09-03 11:58:42 +02:00
|
|
|
integer = 0;
|
2020-08-17 21:40:52 +02:00
|
|
|
|
|
|
|
if(buffer[0] == '<')
|
|
|
|
{
|
2019-09-03 11:58:42 +02:00
|
|
|
*tag = tmpTag;
|
|
|
|
length = 0;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
if(size > 1 && (val[1] == 'x' || val[1] == 'X')) { // Hex value
|
|
|
|
val += 2;
|
|
|
|
while(*val) {
|
|
|
|
if ((*val >= '0' && *val <= '9')) { // 0 - 9
|
|
|
|
integer = (integer * 16) + (*val++ - '0');
|
|
|
|
}
|
|
|
|
else if ((*val >= 'a' && *val <= 'f')) { // a - f
|
|
|
|
integer = (integer * 16) + (*val++ - 'a' + 10);
|
|
|
|
}
|
|
|
|
else if ((*val >= 'A' && *val <= 'F')) { // A - F
|
|
|
|
integer = (integer * 16) + (*val++ - 'a' + 10);
|
|
|
|
}
|
|
|
|
else {
|
2020-04-17 15:14:24 +02:00
|
|
|
MsgLog("ParseTagInteger hex error (0x%hhX) in buffer %s\n", *val, buffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
// getchar();
|
|
|
|
FreeTag(tmpTag);
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( size ) { // Decimal value
|
|
|
|
if (*val == '-') {
|
|
|
|
negative = TRUE;
|
|
|
|
val++;
|
|
|
|
size--;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (integer = 0; size > 0; size--) {
|
|
|
|
if(*val) { // UGLY HACK, fix me.
|
|
|
|
if (*val < '0' || *val > '9') {
|
2020-04-17 15:14:24 +02:00
|
|
|
MsgLog("ParseTagInteger decimal error (0x%hhX) in buffer %s\n", *val, buffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
// getchar();
|
|
|
|
FreeTag(tmpTag);
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
integer = (integer * 10) + (*val++ - '0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (negative) {
|
|
|
|
integer = -integer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setIntValue(integer);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:52:21 +02:00
|
|
|
//==========================================================================
|
|
|
|
// ParseTagFloat
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagFloat(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
2020-08-18 18:45:44 +02:00
|
|
|
UINT32 length;
|
2020-04-22 19:52:21 +02:00
|
|
|
TagPtr tmpTag;
|
|
|
|
|
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagFloat, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
//----
|
2020-08-18 18:45:44 +02:00
|
|
|
float f;
|
|
|
|
AsciiStrToFloat(buffer, NULL, &f);
|
2020-04-22 19:52:21 +02:00
|
|
|
//----
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setFloatValue(f);
|
2020-04-22 19:52:21 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-09-03 11:58:42 +02:00
|
|
|
//==========================================================================
|
|
|
|
// ParseTagData
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagData(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
TagPtr tmpTag;
|
|
|
|
|
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagData,&length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
//Slice - correction as Apple 2003
|
2020-08-18 18:45:44 +02:00
|
|
|
// tmpTag->setStringValue(LString8(buffer));
|
2019-09-03 11:58:42 +02:00
|
|
|
// dmazar: base64 decode data
|
2020-08-18 18:45:44 +02:00
|
|
|
UINTN len = 0;
|
|
|
|
UINT8* data = (UINT8 *)Base64DecodeClover(buffer, &len);
|
|
|
|
tmpTag->setDataValue(data, len);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseTagDate
|
|
|
|
|
|
|
|
EFI_STATUS ParseTagDate(CHAR8* buffer, TagPtr * tag,UINT32* lenPtr)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length = 0;
|
|
|
|
TagPtr tmpTag;
|
|
|
|
|
|
|
|
Status = FixDataMatchingTag(buffer, kXMLTagDate,&length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setDateValue(LString8(buffer));
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = length;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// ParseTagBoolean
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
EFI_STATUS ParseTagBoolean(CHAR8* buffer, TagPtr * tag, bool value, UINT32* lenPtr)
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
TagPtr tmpTag;
|
|
|
|
|
|
|
|
tmpTag = NewTag();
|
|
|
|
if (tmpTag == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
tmpTag->setBoolValue(value);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
*tag = tmpTag;
|
|
|
|
*lenPtr = 0;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// GetNextTag
|
|
|
|
|
|
|
|
EFI_STATUS GetNextTag( UINT8* buffer, CHAR8** tag, UINT32* start, UINT32* length)
|
|
|
|
{
|
|
|
|
UINT32 cnt, cnt2;
|
|
|
|
|
|
|
|
if (tag == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the start of the tag.
|
|
|
|
cnt = 0;
|
|
|
|
while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) {
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer[cnt] == '\0') {
|
|
|
|
DBG("empty buffer at cnt=%d\n", cnt);
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the end of the tag.
|
|
|
|
cnt2 = cnt + 1;
|
|
|
|
while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) {
|
|
|
|
cnt2++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer[cnt2] == '\0') {
|
|
|
|
DBG("empty buffer at cnt2=%d\n", cnt2);
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix the tag data.
|
|
|
|
*tag = (CHAR8*)(buffer + cnt + 1);
|
|
|
|
buffer[cnt2] = '\0';
|
|
|
|
if (start) {
|
|
|
|
*start = cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
*length = cnt2 + 1; //unreal to be -1. This is UINT32
|
|
|
|
|
2020-02-17 21:41:09 +01:00
|
|
|
if (*length == (UINT32)-1) {
|
2019-09-03 11:58:42 +02:00
|
|
|
DBG("GetNextTag with *length == -1\n");
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// FixDataMatchingTag
|
|
|
|
// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
|
|
|
|
// Returns the length of the data found, counting the end tag,
|
|
|
|
// or -1 if the end tag was not found.
|
|
|
|
|
2020-02-17 21:41:09 +01:00
|
|
|
EFI_STATUS FixDataMatchingTag( CHAR8* buffer, CONST CHAR8* tag, UINT32* lenPtr)
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 length;
|
|
|
|
UINT32 start;
|
|
|
|
UINT32 stop;
|
|
|
|
CHAR8* endTag;
|
|
|
|
|
|
|
|
start = 0;
|
|
|
|
while (1) {
|
|
|
|
Status = GetNextTag(((UINT8 *)buffer) + start, &endTag, &stop, &length);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*endTag == '/') && !AsciiStrCmp(endTag + 1, tag)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
start += length;
|
|
|
|
}
|
|
|
|
DBG("fix buffer at pos=%d\n", start + stop);
|
|
|
|
buffer[start + stop] = '\0';
|
|
|
|
*lenPtr = start + length;
|
|
|
|
|
2020-03-11 16:44:11 +01:00
|
|
|
if (*lenPtr == (__typeof_am__(*lenPtr))-1) { // Why is this test. -1 is UINTN_MAX.
|
2019-09-03 11:58:42 +02:00
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// NewTag
|
|
|
|
|
|
|
|
TagPtr NewTag( void )
|
|
|
|
{
|
|
|
|
TagPtr tag;
|
|
|
|
|
2020-08-17 21:40:52 +02:00
|
|
|
if ( gTagsFree.size() > 0 ) {
|
|
|
|
tag = &gTagsFree[0];
|
|
|
|
gTagsFree.RemoveWithoutFreeingAtIndex(0);
|
|
|
|
return tag;
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
2020-08-17 21:40:52 +02:00
|
|
|
tag = new TagStruct();
|
2019-09-03 11:58:42 +02:00
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// XMLFreeTag
|
|
|
|
|
|
|
|
void FreeTag( TagPtr tag )
|
|
|
|
{
|
|
|
|
if (tag == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2020-08-18 18:45:44 +02:00
|
|
|
tag->FreeTag();
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-16 09:15:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
return TRUE if the property present && value = TRUE
|
|
|
|
else return FALSE
|
|
|
|
*/
|
|
|
|
BOOLEAN
|
2020-08-18 18:45:44 +02:00
|
|
|
IsPropertyTrue(TagPtr Prop)
|
2020-04-16 09:15:26 +02:00
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
return Prop != NULL && Prop->isTrueOrYy();
|
2020-04-16 09:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
return TRUE if the property present && value = FALSE
|
|
|
|
else return FALSE
|
|
|
|
*/
|
|
|
|
BOOLEAN
|
2020-08-18 18:45:44 +02:00
|
|
|
IsPropertyFalse(TagPtr Prop)
|
2020-04-16 09:15:26 +02:00
|
|
|
{
|
2020-08-18 18:45:44 +02:00
|
|
|
return Prop != NULL && Prop->isFalseOrNn();
|
2020-04-16 09:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Possible values
|
|
|
|
<integer>1234</integer>
|
|
|
|
<integer>+1234</integer>
|
|
|
|
<integer>-1234</integer>
|
|
|
|
<string>0x12abd</string>
|
|
|
|
*/
|
|
|
|
INTN
|
2020-04-23 11:08:10 +02:00
|
|
|
GetPropertyInteger(
|
2020-04-16 09:15:26 +02:00
|
|
|
TagPtr Prop,
|
|
|
|
INTN Default
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (Prop == NULL) {
|
|
|
|
return Default;
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if (Prop->isInt()) {
|
|
|
|
return Prop->intValue();
|
|
|
|
} else if ((Prop->isString()) && Prop->stringValue().notEmpty()) {
|
|
|
|
if ( Prop->stringValue().length() > 1 && (Prop->stringValue()[1] == 'x' || Prop->stringValue()[1] == 'X') ) {
|
|
|
|
return (INTN)AsciiStrHexToUintn(Prop->stringValue());
|
2020-04-16 09:15:26 +02:00
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
if (Prop->stringValue()[0] == '-') {
|
|
|
|
return -(INTN)AsciiStrDecimalToUintn (Prop->stringValue().c_str() + 1);
|
2020-04-16 09:15:26 +02:00
|
|
|
}
|
|
|
|
|
2020-08-18 18:45:44 +02:00
|
|
|
// return (INTN)AsciiStrDecimalToUintn (Prop->stringValue());
|
|
|
|
return (INTN)AsciiStrDecimalToUintn((Prop->stringValue()[0] == '+') ? (Prop->stringValue().c_str() + 1) : Prop->stringValue().c_str());
|
2020-04-16 09:15:26 +02:00
|
|
|
}
|
|
|
|
return Default;
|
|
|
|
}
|
2020-04-22 19:52:21 +02:00
|
|
|
|
|
|
|
float GetPropertyFloat (TagPtr Prop, float Default)
|
|
|
|
{
|
|
|
|
if (Prop == NULL) {
|
|
|
|
return Default;
|
|
|
|
}
|
2020-08-18 18:45:44 +02:00
|
|
|
if (Prop->isFloat()) {
|
|
|
|
return Prop->floatValue(); //this is union char* or float
|
|
|
|
} else if ((Prop->isString()) && Prop->stringValue().notEmpty()) {
|
2020-04-22 19:52:21 +02:00
|
|
|
float fVar = 0.f;
|
2020-08-18 18:45:44 +02:00
|
|
|
if(!AsciiStrToFloat(Prop->stringValue().c_str(), NULL, &fVar)) //if success then return 0
|
2020-04-22 19:52:21 +02:00
|
|
|
return fVar;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Default;
|
|
|
|
}
|