Skip to content

Commit f916683

Browse files
author
Arnaud Bouchez
committed
new TDocVariantData.AddObject method
1 parent 21d7230 commit f916683

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

src/core/mormot.core.variants.pas

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,10 @@ TDocVariantData = record
11611161
procedure InitCopy(const SourceDocVariant: variant;
11621162
aOptions: TDocVariantOptions);
11631163
/// 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
11641165
// - if you call Init*() methods in a row, ensure you call Clear in-between
11651166
procedure InitClone(const CloneFrom: TDocVariantData);
1167+
{$ifdef HASINLINE}inline;{$endif}
11661168
/// low-level copy a document-based variant with the very same options and count
11671169
// - if you call Init*() methods in a row, ensure you call Clear in-between
11681170
// - will copy Count and Names[] by reference, but Values[] only if CloneValues
@@ -1708,6 +1710,13 @@ TDocVariantData = record
17081710
/// add one or several values to this document, handled as array
17091711
// - if instance's Kind is dvObject, it will raise an EDocVariant exception
17101712
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 = '');
17111720
/// add one or several values from another document
17121721
// - supplied document should be of the same kind than the current one,
17131722
// otherwise nothing is added
@@ -3567,7 +3576,7 @@ procedure TSynInvokeableVariantType.Copy(var Dest: TVarData;
35673576
procedure TSynInvokeableVariantType.CopyByValue(
35683577
var Dest: TVarData; const Source: TVarData);
35693578
begin
3570-
Copy(Dest, Source, false);
3579+
Copy(Dest, Source, {Indirect=} false);
35713580
end;
35723581

35733582
function TSynInvokeableVariantType.TryJsonToVariant(var Json: PUtf8Char;
@@ -4752,7 +4761,8 @@ procedure TDocVariantData.SetOptions(const opt: TDocVariantOptions);
47524761

47534762
procedure TDocVariantData.InitClone(const CloneFrom: TDocVariantData);
47544763
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)));
47564766
pointer(VName) := nil; // to avoid GPF
47574767
pointer(VValue) := nil;
47584768
VCount := 0;
@@ -6064,6 +6074,28 @@ procedure TDocVariantData.AddItems(const aValue: array of const);
60646074
end;
60656075
end;
60666076

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+
60676099
function TDocVariantData.GetObjectProp(const aName: RawUtf8;
60686100
out aFound: PVariant): boolean;
60696101
var
@@ -6532,37 +6564,23 @@ procedure TDocVariantData.Reduce(const aPropNames: array of RawUtf8;
65326564
(high(aPropNames) < 0) then
65336565
exit;
65346566
if IsObject then
6535-
begin
6536-
if aCaseSensitive then
6567+
for j := 0 to high(aPropNames) do
65376568
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]);
65476575
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
65596576
else if IsArray then
65606577
for ndx := 0 to VCount - 1 do
65616578
begin
65626579
_Safe(VValue[ndx])^.Reduce(
65636580
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));
65666584
reduced.Clear;
65676585
end;
65686586
end;

src/mormot.commit.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
'2.0.3329'
1+
'2.0.3330'

0 commit comments

Comments
 (0)