fcl-css: resolver: parse value without registry

This commit is contained in:
mattias 2024-10-01 10:59:14 +02:00
parent 3a98dfde1b
commit 3dc3d83757

View File

@ -300,6 +300,9 @@ const
type
{ TCSSRegistryNamedItem }
TCSSRegistryNamedItem = class
public
Name: TCSSString; // case sensitive
@ -539,6 +542,7 @@ type
CurValue: TCSSString;
CurComp: TCSSResCompValue;
function InitParseAttr(Desc: TCSSAttributeDesc; AttrData: TCSSAttributeKeyData; const Value: TCSSString): boolean; virtual; // true if parsing can start
procedure InitParseAttr(const Value: TCSSString); virtual;
// check whole attribute, skipping invalid values, emit warnings:
function CheckAttribute_Keyword(const AllowedKeywordIDs: TCSSNumericalIDArray): boolean; virtual;
function CheckAttribute_CommaList_Keyword(const AllowedKeywordIDs: TCSSNumericalIDArray): boolean; virtual;
@ -559,11 +563,13 @@ type
function GetCompString(const aValue: string; const ResValue: TCSSResCompValue): TCSSString; overload;
// low level functions to parse attribute components
function ReadComp(var aComp: TCSSResCompValue): boolean; // true if parsing attribute can continue
function ReadNumber(var aComp: TCSSResCompValue): boolean;
function ReadIdentifier(var aComp: TCSSResCompValue): boolean;
procedure SkipToEndOfAttribute(var p: PCSSChar);
function SkipString(var p: PCSSChar): boolean;
function SkipBrackets(var p: PCSSChar; Lvl: integer = 1): boolean;
procedure ReadWordID(var aComp: TCSSResCompValue);
class function ReadValue(var aComp: TCSSResCompValue): boolean; // true if parsing attribute can continue, not using CSSRegistry
class function ReadNumber(var aComp: TCSSResCompValue): boolean;
class function ReadIdentifier(var aComp: TCSSResCompValue): boolean;
class procedure SkipToEndOfAttribute(var p: PCSSChar);
class function SkipString(var p: PCSSChar): boolean;
class function SkipBrackets(var p: PCSSChar; Lvl: integer = 1): boolean;
// registry
function GetAttributeID(const aName: TCSSString; AutoCreate: boolean = false): TCSSNumericalID; virtual;
function GetAttributeDesc(AttrID: TCSSNumericalID): TCSSAttributeDesc; virtual;
@ -1485,6 +1491,14 @@ begin
Result:=true;
end;
procedure TCSSBaseResolver.InitParseAttr(const Value: TCSSString);
begin
CurValue:=Value;
CurComp:=Default(TCSSResCompValue);
CurComp.EndP:=PCSSChar(CurValue);
ReadNext;
end;
function TCSSBaseResolver.CheckAttribute_Keyword(const AllowedKeywordIDs: TCSSNumericalIDArray
): boolean;
begin
@ -1618,6 +1632,34 @@ begin
end;
function TCSSBaseResolver.ReadComp(var aComp: TCSSResCompValue): boolean;
begin
Result:=ReadValue(aComp);
ReadWordID(aComp);
end;
procedure TCSSBaseResolver.ReadWordID(var aComp: TCSSResCompValue);
var
Identifier: TCSSString;
begin
case aComp.Kind of
rvkFunctionUnknown:
begin
SetString(Identifier,aComp.StartP,aComp.EndP-aComp.StartP);
aComp.FunctionID:=CSSRegistry.IndexOfAttrFunction(Identifier);
if aComp.FunctionID>CSSIDNone then
aComp.Kind:=rvkFunction;
end;
rvkKeywordUnknown:
begin
SetString(Identifier,aComp.StartP,aComp.EndP-aComp.StartP);
aComp.KeywordID:=CSSRegistry.IndexOfKeyword(Identifier);
if aComp.KeywordID>CSSIDNone then
aComp.Kind:=rvkKeyword;
end;
end;
end;
class function TCSSBaseResolver.ReadValue(var aComp: TCSSResCompValue): boolean;
var
c: TCSSChar;
p: PCSSChar;
@ -1743,7 +1785,7 @@ begin
aComp.EndP:=p;
end;
function TCSSBaseResolver.ReadNumber(var aComp: TCSSResCompValue): boolean;
class function TCSSBaseResolver.ReadNumber(var aComp: TCSSResCompValue): boolean;
var
Negative, HasNumber: Boolean;
Divisor: double;
@ -1859,9 +1901,8 @@ begin
//writeln('TCSSBaseResolver.ReadNumber "',p,'" Value=',FloatToCSSStr(aComp.Float),' U=',U,' Kind=',aComp.Kind,' Result=',Result);
end;
function TCSSBaseResolver.ReadIdentifier(var aComp: TCSSResCompValue): boolean;
class function TCSSBaseResolver.ReadIdentifier(var aComp: TCSSResCompValue): boolean;
var
Identifier: TCSSString;
IsFunc: Boolean;
p: PCSSChar;
begin
@ -1872,34 +1913,21 @@ begin
repeat
inc(p);
until not (p^ in AlNumIden);
SetString(Identifier,aComp.StartP,p-aComp.StartP);
IsFunc:=p^='(';
if IsFunc then
begin
// function call
aComp.Kind:=rvkFunctionUnknown;
aComp.BracketOpen:=p;
if not SkipBrackets(p) then
begin
aComp.EndP:=p;
exit;
end;
end;
end else
aComp.Kind:=rvkKeywordUnknown;
aComp.EndP:=p;
if IsFunc then
begin
aComp.FunctionID:=CSSRegistry.IndexOfAttrFunction(Identifier);
if aComp.FunctionID>CSSIDNone then
aComp.Kind:=rvkFunction
else
aComp.Kind:=rvkFunctionUnknown;
end else begin
aComp.KeywordID:=CSSRegistry.IndexOfKeyword(Identifier);
if aComp.KeywordID>CSSIDNone then
aComp.Kind:=rvkKeyword
else
aComp.Kind:=rvkKeywordUnknown;
end;
Result:=true;
end;
@ -1995,7 +2023,7 @@ begin
SetString(Result,Start,ResValue.EndP-Start);
end;
procedure TCSSBaseResolver.SkipToEndOfAttribute(var p: PCSSChar);
class procedure TCSSBaseResolver.SkipToEndOfAttribute(var p: PCSSChar);
begin
repeat
case p^ of
@ -2006,7 +2034,7 @@ begin
until false;
end;
function TCSSBaseResolver.SkipString(var p: PCSSChar): boolean;
class function TCSSBaseResolver.SkipString(var p: PCSSChar): boolean;
var
Delim, c: TCSSChar;
begin
@ -2026,7 +2054,7 @@ begin
until false;
end;
function TCSSBaseResolver.SkipBrackets(var p: PCSSChar; Lvl: integer): boolean;
class function TCSSBaseResolver.SkipBrackets(var p: PCSSChar; Lvl: integer): boolean;
const
CSSMaxBracketLvl = 10;
var