type
TJSONSetHelper<TSet> =
record
strict private
class procedure GetEnumBounds(
var MinValue, MaxValue: Integer);
static;
inline;
public
class function ReadValue(JSON: PJSONVariantData;
const Name:
String;
const ElementStrings:
array of String): TSet;
static;
class procedure WriteValue(JSON: PJSONVariantData;
const Name:
String;
const ElementStrings:
array of String; Value: TSet);
static;
end;
class procedure TJSONSetHelper<TSet>.GetEnumBounds(
var MinValue, MaxValue: Integer);
var
TypInfo: PTypeInfo;
TypData: PTypeData;
begin
TypInfo := TypeInfo(TSet);
{$IFDEF DEBUG}
if (TypInfo^.Kind <> tkSet)
then
begin
raise Exception.Create('
Invalid generic type.');
end;
{$ENDIF}
TypData := GetTypeData(GetTypeData(TypInfo)^.CompType^);
{$IFDEF DEBUG}
if (TypData^.MinValue <> 0)
then
begin
raise Exception.Create('
The enum-type needs to be zero-based.');
end;
if (TypData^.MaxValue > 255)
then
begin
raise Exception.Create('
The enum-type''
s maximum value needs the be lower than 256.');
end;
{$ENDIF}
MinValue := TypData^.MinValue;
MaxValue := TypData^.MaxValue;
end;
class function TJSONSetHelper<TSet>.ReadValue(JSON: PJSONVariantData;
const Name:
String;
const ElementStrings:
array of String): TSet;
type
TSetType =
set of 0..255;
var
A: PJSONVariantData;
MinValue,
MaxValue: Integer;
I, J: Integer;
begin
GetEnumBounds(MinValue, MaxValue);
{$IFDEF DEBUG}
if (MaxValue <> High(ElementStrings))
then
begin
raise Exception.Create('
The size of the string-array does not match the size of the enum-type');
end;
{$ENDIF}
FillChar(Pointer(@Result)^, SizeOf(TSet), #0);
A := JSON^.Data(
Name);
if (Assigned(A))
then
begin
if (A^.Kind <> jvArray)
then
begin
raise Exception.CreateFmt('
The "%s" field is not a valid JSON array.', [
Name]);
end;
for I := 0
to A^.Count - 1
do
begin
for J := MinValue
to MaxValue
do
begin
if (LowerCase(A^.Item[I]) = ElementStrings[J])
then
begin
Include(TSetType(Pointer(@Result)^), J);
Break;
end;
end;
end;
end;
end;
class procedure TJSONSetHelper<TSet>.WriteValue(JSON: PJSONVariantData;
const Name:
String;
const ElementStrings:
array of String; Value: TSet);
type
TSetType =
set of 0..255;
var
A: TJSONVariantData;
MinValue,
MaxValue: Integer;
I: Integer;
begin
GetEnumBounds(MinValue, MaxValue);
{$IFDEF DEBUG}
if (MaxValue <> High(ElementStrings))
then
begin
raise Exception.Create('
The size of the string-array does not match the size of the enum-type');
end;
{$ENDIF}
A.Init;
for I := MinValue
to MaxValue
do
begin
if (I
in TSetType(Pointer(@Value)^))
then
begin
A.AddValue(ElementStrings[I]);
end;
end;
if (A.Count > 0)
then
begin
JSON^.AddNameValue(
Name, Variant(A));
end;
end;