alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalMetroDxe/UiLib/XmlParser.c

227 lines
4.1 KiB
C

/** @file
XML parser
;******************************************************************************
;* Copyright (c) 2012 - 2015, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "UiControls.h"
#define TAG 1
#define CONTENT 2
#define QUOTE 3
#define MAX_ATTRIBS 128
STATIC
BOOLEAN
IsSpace (
INT32 c
)
{
return ((c<=' ' && (c==' ' || (c<=13 && c>=9))));
}
STATIC
VOID
ParserContent (
CHAR16 *Str,
SAX_PARSER_CONTENT_CALLBACK ContentCb,
VOID *Data
)
{
while (*Str != '\0' && IsSpace (*Str)) {
Str++;
}
if (*Str == '\0') {
return ;
}
if (ContentCb != NULL) {
(*ContentCb)(Data, Str);
}
}
STATIC
VOID
ParseElement (
IN OUT CHAR16 *Str,
IN SAX_PARSER_START_CALLBACK StartCb,
IN SAX_PARSER_END_CALLBACK EndCb,
IN OUT VOID *Data
)
{
CHAR16 *AttrNames[MAX_ATTRIBS];
CHAR16 *AttrValues[MAX_ATTRIBS];
UINTN AttrNum;
CHAR16 *TagName;
BOOLEAN IsStart;
BOOLEAN IsEnd;
CHAR16 QuoteChar;
AttrNum = 0;
TagName = NULL;
IsStart = FALSE;
IsEnd = FALSE;
//
// trim white space after the '<'
//
while (*Str != '\0' && IsSpace (*Str)) {
Str++;
}
//
// start tag or end tag
//
if (*Str == L'/') {
Str++;
IsEnd = TRUE;
} else {
IsStart = TRUE;
}
//
// commonts or preprocessor
//
if (*Str == '\0' || *Str == L'?' || *Str == '!') {
return ;
}
TagName = Str;
while (*Str !='\0' && !IsSpace (*Str) && *Str != '/') {
Str++;
}
if (*Str != '\0') {
if (*Str == '/') {
IsEnd = TRUE;
}
*Str++ = L'\0';
}
while (!IsEnd && *Str != '\0' && AttrNum < (MAX_ATTRIBS - 1)) {
while (*Str != '\0' && IsSpace (*Str)) {
Str++;
}
if (*Str == '\0') {
break;
}
if (*Str == '/') {
IsEnd = TRUE;
break;
}
AttrNames[AttrNum] = Str++;
AttrValues[AttrNum] = NULL;
while (*Str !='\0' && !IsSpace (*Str) && *Str != '=') {
Str++;
}
if (*Str != '\0') {
*Str++ = '\0';
}
//
// beginning of the value
//
while (*Str != '\0' && *Str != '\"' && *Str != '\'') {
Str++;
}
if (*Str == '\0') {
break;
}
QuoteChar = *Str;
Str++;
AttrValues[AttrNum++] = Str;
while (*Str != '\0' && *Str != QuoteChar) {
if (*Str == '\\' && *(Str + 1) == QuoteChar) {
Str += 2;
continue;
}
Str++;
}
if (*Str != '\0') {
*Str++ = '\0';
}
}
AttrNames[AttrNum] = NULL;
AttrValues[AttrNum++] = NULL;
if (IsStart && StartCb) {
(*StartCb)(Data, TagName, AttrNames, AttrValues);
}
if (IsEnd && EndCb) {
(*EndCb)(Data, TagName);
}
}
BOOLEAN
EFIAPI
SaxParser (
CHAR16 *XMLBuffer,
SAX_PARSER_START_CALLBACK StartCb,
SAX_PARSER_CONTENT_CALLBACK ContentCb,
SAX_PARSER_END_CALLBACK EndCb,
VOID *Data
)
{
CHAR16 *Str;
CHAR16 *Mark;
UINTN State;
CHAR16 QuoteChar;
Str = XMLBuffer;
Mark = Str;
State = CONTENT;
QuoteChar = 0;
while (*Str != '\0') {
if (*Str == '<' && State == CONTENT) {
*Str++ = '\0';
ParserContent (Mark, ContentCb, Data);
Mark = Str;
State = TAG;
} else if (*Str == '\\' && State == QUOTE) {
if (*(Str + 1) == QuoteChar) {
Str += 2;
continue;
}
Str++;
} else if (*Str == '\"' || *Str == '\'') {
if (State == TAG) {
State = QUOTE;
QuoteChar = *Str;
} else if (State == QUOTE && *Str == QuoteChar) {
State = TAG;
}
Str++;
} else if (*Str == '>' && State == TAG) {
*Str++ = '\0';
ParseElement (Mark, StartCb, EndCb, Data);
Mark = Str;
State = CONTENT;
} else {
Str++;
}
}
return TRUE;
}