
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2802 8e941d3f-bd1b-0410-a28a-d453659cc2b4
184 lines
5.2 KiB
ObjectPascal
184 lines
5.2 KiB
ObjectPascal
unit cmdlinecfgjson;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, cmdlinecfg, fpjson, jsonparser;
|
|
|
|
function CmdLineCfgJSONReadFile(stream: TStream; cfg: TCmdLineCfg): Boolean; overload;
|
|
function CmdLineCfgJSONReadFile(const FileName: String; cfg: TCmdLineCfg): Boolean; overload;
|
|
procedure CmdLineCfgJSONLoadFilesFromDir(const Dir: String; list: TList; const Mask : string = '*.copt');
|
|
|
|
implementation
|
|
|
|
// ugh... no better way to do it anyway. ... see TValueIterator below
|
|
type
|
|
{ TCfgIterator }
|
|
TCfgIterator = class(TObject)
|
|
class procedure Iterate(Const AName : TJSONStringType; Item: TJSONData; Data: TObject; var DoContinue: Boolean);
|
|
class procedure IterateOption(Const AName : TJSONStringType; Item: TJSONData; Data: TObject; var DoContinue: Boolean);
|
|
class procedure IterateValue(const AName: TJSONStringType; Item: TJSONdata; Data: TObject; var DoContinue: Boolean);
|
|
end;
|
|
|
|
type
|
|
TIterateValue = class(TObject)
|
|
opt : TCmdLineCfgOption;
|
|
idx : Integer;
|
|
end;
|
|
|
|
class procedure TCfgIterator.IterateOption(Const AName : TJSONStringType; Item: TJSONData; Data: TObject; var DoContinue: Boolean);
|
|
var
|
|
opt : TCmdLineCfgOption;
|
|
nm : String;
|
|
ja : TJSONArray;
|
|
i : Integer;
|
|
iv : TIterateValue;
|
|
begin
|
|
opt:=TCmdLineCfgOption(Data);
|
|
nm:=lowerCase(AName);
|
|
if nm='section' then opt.Section:=Item.AsString
|
|
else if nm='subsection' then opt.SubSection:=Item.AsString
|
|
else if nm='type' then opt.OptType:=Item.AsString
|
|
else if nm='name' then opt.Name:=Item.AsString
|
|
else if nm='key' then opt.Key:=Item.AsString
|
|
else if nm='masterkey' then opt.MasterKey:=Item.AsString
|
|
else if nm='display' then opt.Display:=Item.AsString
|
|
else if (nm='condition') or (nm='cond') then opt.Condition:=Item.AsString
|
|
else if (nm='value') then opt.SetValue(Item.AsString)
|
|
else if (nm='alias') then opt.AliasToKey:=Item.AsString
|
|
else if (nm='multiple') then opt.isMultiple:=(Item.JSONType=jtBoolean) and (Item.AsBoolean)
|
|
else if (nm='options') then begin
|
|
ja:=TJSONArray(Item);
|
|
if ja.Count>0 then begin
|
|
iv:=TIterateValue.Create;
|
|
try
|
|
iv.opt:=opt;
|
|
for i:=0 to ja.Count-1 do begin
|
|
if ja.Items[i].JSONType = jtObject then begin
|
|
iv.idx:=opt.ValCount;
|
|
TJSONObject(ja.Items[i]).Iterate ( TCfgIterator.IterateValue, iv);
|
|
end;
|
|
end;
|
|
finally
|
|
iv.Free;
|
|
end;
|
|
end;
|
|
end
|
|
end;
|
|
|
|
class procedure TCfgIterator.IterateValue(const AName: TJSONStringType;
|
|
Item: TJSONdata; Data: TObject; var DoContinue: Boolean);
|
|
var
|
|
opt : TCmdLineCfgOption;
|
|
idx : Integer;
|
|
nm : String;
|
|
begin
|
|
idx:=TIterateValue(Data).idx;
|
|
opt:=TIterateValue(Data).opt;
|
|
nm:=lowerCase(AName);
|
|
if nm='display' then opt.SetValDisplay(Item.AsString, idx)
|
|
else if nm='value' then opt.SetValue(Item.AsString, idx)
|
|
else if nm='condition' then opt.SetCondition(Item.AsString, idx);
|
|
end;
|
|
|
|
class procedure TCfgIterator.Iterate(Const AName : TJSONStringType; Item: TJSONData; Data: TObject; var DoContinue: Boolean);
|
|
var
|
|
cfg : TCmdLineCfg;
|
|
nm : string;
|
|
ja : TJSONArray;
|
|
j : TJSONData;
|
|
i : Integer;
|
|
opt : TCmdLineCfgOption;
|
|
|
|
begin
|
|
cfg:=TCmdLineCfg(data);
|
|
nm:=lowerCase(AName);
|
|
if nm='options' then begin
|
|
if Item.JSONType<>jtArray then Exit; // options must be an array of options
|
|
ja:=TJSONArray(Item);
|
|
for i:=0 to ja.Count-1 do begin
|
|
j:=ja.Items[i];
|
|
if j.JSONType<>jtObject then Continue;
|
|
|
|
opt:=TCmdLineCfgOption.Create;
|
|
TJSONObject(j).Iterate(TCfgIterator.IterateOption, opt);
|
|
if (opt.Key='') then begin
|
|
opt.Free
|
|
end else begin
|
|
CmdLineOptionNormalize(opt);
|
|
cfg.Options.Add(opt);
|
|
end;
|
|
end;
|
|
|
|
end else begin
|
|
if Item.JSONType<>jtString then Exit;
|
|
if nm='executable' then cfg.Executable:=Item.AsString
|
|
else if nm='version' then cfg.Version:=Item.AsString
|
|
else if nm='fromversion' then cfg.FromVersion:=Item.AsString
|
|
else if nm='testvalue' then cfg.TestValue:=Item.AsString
|
|
else if nm='testkey' then cfg.TestKey:=Item.AsString
|
|
end;
|
|
|
|
end;
|
|
|
|
function CmdLineCfgJSONReadFile(stream: TStream; cfg: TCmdLineCfg): Boolean;
|
|
var
|
|
p : TJSONParser;
|
|
d : TJSONData;
|
|
core : TJSONObject;
|
|
begin
|
|
Result:=False;
|
|
d:=nil;
|
|
p:=TJSONParser.Create(stream);
|
|
try
|
|
d:=p.Parse;
|
|
if d.JSONType<>jtObject then Exit;
|
|
core:=TJSONObject(d);
|
|
core.Iterate(TCfgIterator.Iterate, cfg);
|
|
Result:=cfg.Executable<>'';
|
|
finally
|
|
d.Free;
|
|
p.Free;
|
|
end;
|
|
end;
|
|
|
|
function CmdLineCfgJSONReadFile(const FileName: String; cfg: TCmdLineCfg): Boolean;
|
|
var
|
|
fs : TFileStream;
|
|
begin
|
|
fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
|
|
try
|
|
Result:=CmdLineCfgJSONReadFile(fs, cfg);
|
|
finally
|
|
fs.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure CmdLineCfgJSONLoadFilesFromDir(const Dir: String; list: TList; const Mask: string);
|
|
var
|
|
rslt : TSearchRec;
|
|
res : Integer;
|
|
pth : string;
|
|
cfg : TCmdLineCfg;
|
|
begin
|
|
pth:=IncludeTrailingPathDelimiter(Dir);
|
|
res:=FindFirst( pth+Mask, faAnyFile, rslt);
|
|
try
|
|
while res = 0 do begin
|
|
if (rslt.Attr and faDirectory=0) and (rslt.Size>0) then begin
|
|
cfg := TCmdLineCfg.Create;
|
|
if not CmdLineCfgJSONReadFile(pth+rslt.Name, cfg) then cfg.Free
|
|
else list.Add(cfg);
|
|
end;
|
|
res:=FindNext(rslt);
|
|
end;
|
|
finally
|
|
FindClose(rslt);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|