@@ -1161,8 +1161,10 @@ TDocVariantData = record
1161
1161
procedure InitCopy (const SourceDocVariant: variant;
1162
1162
aOptions: TDocVariantOptions);
1163
1163
// / clone a document-based variant with the very same options but no data
1164
+ // - the same options will be used, without the dvArray/dvObject flags
1164
1165
// - if you call Init*() methods in a row, ensure you call Clear in-between
1165
1166
procedure InitClone (const CloneFrom: TDocVariantData);
1167
+ { $ifdef HASINLINE} inline;{ $endif}
1166
1168
// / low-level copy a document-based variant with the very same options and count
1167
1169
// - if you call Init*() methods in a row, ensure you call Clear in-between
1168
1170
// - will copy Count and Names[] by reference, but Values[] only if CloneValues
@@ -1708,6 +1710,13 @@ TDocVariantData = record
1708
1710
// / add one or several values to this document, handled as array
1709
1711
// - if instance's Kind is dvObject, it will raise an EDocVariant exception
1710
1712
procedure AddItems (const aValue: array of const );
1713
+ // / add one object document to this document
1714
+ // - if the document is an array, keep aName=''
1715
+ // - if the document is an object, set the new object property as aName
1716
+ // - new object will keep the same options as this document
1717
+ // - slightly faster than AddItem(_Obj(...)) or AddValue(aName, _Obj(...))
1718
+ procedure AddObject (const aNameValuePairs: array of const ;
1719
+ const aName: RawUtf8 = ' ' );
1711
1720
// / add one or several values from another document
1712
1721
// - supplied document should be of the same kind than the current one,
1713
1722
// otherwise nothing is added
@@ -3567,7 +3576,7 @@ procedure TSynInvokeableVariantType.Copy(var Dest: TVarData;
3567
3576
procedure TSynInvokeableVariantType.CopyByValue (
3568
3577
var Dest: TVarData; const Source: TVarData);
3569
3578
begin
3570
- Copy(Dest, Source, false);
3579
+ Copy(Dest, Source, { Indirect= } false);
3571
3580
end ;
3572
3581
3573
3582
function TSynInvokeableVariantType.TryJsonToVariant (var Json: PUtf8Char;
@@ -4752,7 +4761,8 @@ procedure TDocVariantData.SetOptions(const opt: TDocVariantOptions);
4752
4761
4753
4762
procedure TDocVariantData.InitClone (const CloneFrom: TDocVariantData);
4754
4763
begin
4755
- TRttiVarData(self).VType := TRttiVarData(CloneFrom).VType; // VType+VOptions
4764
+ TRttiVarData(self).VType := TRttiVarData(CloneFrom).VType // VType+VOptions
4765
+ and not ((1 shl (ord(dvoIsObject) + 16 )) + (1 shl (ord(dvoIsArray) + 16 )));
4756
4766
pointer(VName) := nil ; // to avoid GPF
4757
4767
pointer(VValue) := nil ;
4758
4768
VCount := 0 ;
@@ -6064,6 +6074,28 @@ procedure TDocVariantData.AddItems(const aValue: array of const);
6064
6074
end ;
6065
6075
end ;
6066
6076
6077
+ procedure TDocVariantData.AddObject (const aNameValuePairs: array of const ;
6078
+ const aName: RawUtf8);
6079
+ var
6080
+ added: PtrInt;
6081
+ o: PDocVariantData;
6082
+ begin
6083
+ if (aName <> ' ' ) and
6084
+ (dvoCheckForDuplicatedNames in VOptions) then
6085
+ if GetValueIndex(aName) >= 0 then
6086
+ raise EDocVariant.CreateUtf8(' AddObject: Duplicated [%] name' , [aName]);
6087
+ added := InternalAdd(aName);
6088
+ o := @VValue[added];
6089
+ if PInteger(o)^ = 0 then // most common case is adding a new value
6090
+ o^.InitClone(self) // same options than owner document
6091
+ else if (o^.VType <> VType) or
6092
+ not o^.IsObject then
6093
+ raise EDocVariant.CreateUtf8(' AddObject: wrong existing [%]' , [aName]);
6094
+ o^.AddNameValuesToObject(aNameValuePairs);
6095
+ if dvoInternValues in VOptions then
6096
+ InternalUniqueValue(added);
6097
+ end ;
6098
+
6067
6099
function TDocVariantData.GetObjectProp (const aName: RawUtf8;
6068
6100
out aFound: PVariant): boolean;
6069
6101
var
@@ -6532,37 +6564,23 @@ procedure TDocVariantData.Reduce(const aPropNames: array of RawUtf8;
6532
6564
(high(aPropNames) < 0 ) then
6533
6565
exit;
6534
6566
if IsObject then
6535
- begin
6536
- if aCaseSensitive then
6567
+ for j := 0 to high(aPropNames) do
6537
6568
begin
6538
- for j := 0 to high(aPropNames) do
6539
- for ndx := 0 to VCount - 1 do
6540
- if VName[ndx] = aPropNames[j] then
6541
- begin
6542
- if not aDoNotAddVoidProp or
6543
- not VarIsVoid(VValue[ndx]) then
6544
- result.AddValue(VName[ndx], VValue[ndx]);
6545
- break;
6546
- end ;
6569
+ ndx := DocVariantFind[aCaseSensitive](
6570
+ pointer(VName), pointer(aPropNames[j]), length(aPropNames[j]), VCount);
6571
+ if ndx >= 0 then
6572
+ if not aDoNotAddVoidProp or
6573
+ not VarIsVoid(VValue[ndx]) then
6574
+ result.AddValue(VName[ndx], VValue[ndx]);
6547
6575
end
6548
- else
6549
- for j := 0 to high(aPropNames) do
6550
- for ndx := 0 to VCount - 1 do
6551
- if IdemPropNameU(VName[ndx], aPropNames[j]) then
6552
- begin
6553
- if not aDoNotAddVoidProp or
6554
- not VarIsVoid(VValue[ndx]) then
6555
- result.AddValue(VName[ndx], VValue[ndx]);
6556
- break;
6557
- end ;
6558
- end
6559
6576
else if IsArray then
6560
6577
for ndx := 0 to VCount - 1 do
6561
6578
begin
6562
6579
_Safe(VValue[ndx])^.Reduce(
6563
6580
aPropNames, aCaseSensitive, reduced, aDoNotAddVoidProp);
6564
- if reduced.IsObject then
6565
- result.AddItem(variant(reduced));
6581
+ if not reduced.IsObject then
6582
+ continue;
6583
+ result.AddItem(variant(reduced));
6566
6584
reduced.Clear;
6567
6585
end ;
6568
6586
end ;
0 commit comments