mORMot and Open Source friends
Check-in [7200dbe52a]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:{4177} fixed TDocVariantData.InitJSONInPlace when dvoJSONObjectParseWithinString option is defined - also fixed GetJSONField() incorrect documentation
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7200dbe52a555b12b1fb27962223642cce24d875
User & Date: ab 2018-01-27 16:15:43
Context
2018-01-28
10:01
fix THttpServer.OnNginxAllowSend accodnt to changes about NginxSendFileFrom is a array of TFileName check-in: f3080e88a5 user: mpv tags: trunk
2018-01-27
16:15
{4177} fixed TDocVariantData.InitJSONInPlace when dvoJSONObjectParseWithinString option is defined - also fixed GetJSONField() incorrect documentation check-in: 7200dbe52a user: ab tags: trunk
14:56
{4176} added THttpServer.ThreadPoolContentionCount property - and fixed ThreadPoolContentionAbortCount as reported by ssoftpro - thanks! check-in: b94adf736c user: ab tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SynCommons.pas.

10942
10943
10944
10945
10946
10947
10948
10949

10950
10951
10952
10953
10954


10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
.....
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845
22846
22847
22848
.....
22856
22857
22858
22859
22860
22861
22862



22863
22864
22865
22866
22867
22868
22869
.....
41287
41288
41289
41290
41291
41292
41293
41294
41295
41296
41297
41298
41299
41300
41301
.....
41477
41478
41479
41480
41481
41482
41483
41484
41485
41486
41487
41488
41489
41490
41491
41492
41493
41494
.....
43130
43131
43132
43133
43134
43135
43136
43137
43138
43139
43140
43141
43142
43143
43144
.....
44260
44261
44262
44263
44264
44265
44266


44267
44268
44269
44270
44271
44272
44273
44274
.....
44294
44295
44296
44297
44298
44299
44300


44301
44302
44303
44304
44305
44306
44307
44308
function JSONRetrieveStringField(P: PUTF8Char; out Field: PUTF8Char;
  out FieldLen: integer; ExpectNameField: boolean): PUTF8Char;
  {$ifdef HASINLINE}inline;{$endif}

/// decode a JSON field in an UTF-8 encoded buffer (used in TSQLTableJSON.Create)
// - this function decodes in the P^ buffer memory itself (no memory allocation
// or copy), for faster process - so take care that P^ is not shared
// - PDest points to the next field to be decoded, or nil on any unexpected end

// - optional wasString is set to true if the JSON value was a JSON "string"
// - null is decoded as nil, with wasString=false
// - true/false boolean values are returned as 'true'/'false', with wasString=false
// - '"strings"' are decoded as 'strings', with wasString=true, properly JSON
// unescaped (e.g. any \u0123 pattern would be converted into UTF-8 content)


// - any integer value is left as its ascii representation, with wasString=true
// - works for both field names or values (e.g. '"FieldName":' or 'Value,')
// - EndOfObject (if not nil) is set to the JSON value char (',' ':' or '}' e.g.)
function GetJSONField(P: PUTF8Char; out PDest: PUTF8Char;
  wasString: PBoolean=nil; EndOfObject: PUTF8Char=nil; Len: PInteger=nil): PUTF8Char;

/// decode a JSON field name in an UTF-8 encoded buffer
// - this function decodes in the P^ buffer memory itself (no memory allocation
// or copy), for faster process - so take care that P^ is not shared
// - it will return the property name (with an ending #0) or nil on error
................................................................................
begin
  result := 0;
  if (P<>nil) and GetSetInfo(aTypeInfo,MaxValue,names) then begin
    P := GotoNextNotSpace(P);
    if P^='[' then begin
      P := GotoNextNotSpace(P+1);
      if P^=']' then 
        inc(P) else
        repeat
          Text := GetJSONField(P,P,@wasString,@EndOfObject,@TextLen);
          if (Text=nil) or not wasString then begin
            P := nil; // invalid input (expects a JSON array of strings)
            exit;
          end;
          if Text^='*' then begin
................................................................................
            i := -1;
          if i<0 then
            i := FindShortStringListTrimLowerCase(names,MaxValue,Text,TextLen);
          if i>=0 then
            SetBit(result,i);
          // unknown enum names (i=-1) would just be ignored
        until EndOfObject=']';



      while not (P^ in EndOfJSONField) do begin // mimics GetJSONField()
        if P^=#0 then begin
          P := nil;
          exit; // unexpected end
        end;
        inc(P);
      end;
................................................................................
      if FirstChar='"' then // special case e.g. for TGUID string
        EndOfObj := FirstChar else begin
        EndOfObj := JSON^;
        inc(JSON);
      end else
      EndOfObj := #0;
  end;
  if JSON=nil then
    result := @NULCHAR else
    result := JSON;
  if EndOfObject<>nil then
    EndOfObject^ := EndOfObj;
end;

function RecordLoadJSON(var Rec; const JSON: RawUTF8; TypeInfo: pointer): boolean;
................................................................................
    raise ESynException.CreateUTF8('%.CustomReader("%"): unsupported',
        [self,fCustomTypeName]);
  ktSet: begin
    i32 := GetSetNameValue(fCustomTypeInfo,P,EndOfObject);
    MoveFast(i32,aValue,fDataSize);
    result := P;
  end;
  else begin // encoded as JSON strings
    PropValue := GetJSONField(P,P,@wasString,@EndOfObject,@PropValueLen);
    if PropValue=nil then
      exit;
    if P=nil then // result=nil=error + caller may dec(P); P^:=EndOfObject; 
      P := PropValue+PropValueLen;
    case fKnownType of
    ktGUID:
      if wasString and (TextToGUID(PropValue,@aValue)<>nil) then
        result := P;
    ktEnumeration: begin
................................................................................
    end else
      GetJSONToAnyVariant(Value,result,EndOfObject,TryCustomVariants,AllowDouble);
  end else begin
    Val := GetJSONField(result,result,@wasString,EndOfObject);
    GetVariantFromJSON(Val,wasString,Value,nil,AllowDouble);
  end;
  if result=nil then
    result := @NULCHAR;
end;

procedure VariantLoadJSON(var Value: Variant; const JSON: RawUTF8;
  TryCustomVariants: PDocVariantOptions; AllowDouble: boolean);
var tmp: TSynTempBuffer;
begin
  tmp.Init(JSON);
................................................................................
    if n>0 then begin
      SetLength(VValue,n);
      repeat
        if VCount>=n then
          exit; // unexpected array size means invalid JSON
        GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
        if JSON=nil then


          exit;
        if intvalues<>nil then
          intvalues.UniqueVariant(VValue[VCount]);
        inc(VCount);
      until EndOfObject=']';
    end else
      if JSON^=']' then // n=0
        repeat inc(JSON) until not(JSON^ in [#1..' ']) else
................................................................................
        if Name=nil then
          exit;
        SetString(VName[VCount],PAnsiChar(Name),NameLen);
        if intnames<>nil then
          intnames.UniqueText(VName[VCount]);
        GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
        if JSON=nil then


          exit;
        if intvalues<>nil then
          intvalues.UniqueVariant(VValue[VCount]);
        inc(VCount);
      until EndOfObject='}';
    end else
      if JSON^='}' then // n=0
        repeat inc(JSON) until not(JSON^ in [#1..' ']) else






|
>

<
<


>
>
|

<







 







|







 







>
>
>







 







|







 







|


|







 







|







 







>
>
|







 







>
>
|







10942
10943
10944
10945
10946
10947
10948
10949
10950
10951


10952
10953
10954
10955
10956
10957

10958
10959
10960
10961
10962
10963
10964
.....
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845
22846
22847
22848
.....
22856
22857
22858
22859
22860
22861
22862
22863
22864
22865
22866
22867
22868
22869
22870
22871
22872
.....
41290
41291
41292
41293
41294
41295
41296
41297
41298
41299
41300
41301
41302
41303
41304
.....
41480
41481
41482
41483
41484
41485
41486
41487
41488
41489
41490
41491
41492
41493
41494
41495
41496
41497
.....
43133
43134
43135
43136
43137
43138
43139
43140
43141
43142
43143
43144
43145
43146
43147
.....
44263
44264
44265
44266
44267
44268
44269
44270
44271
44272
44273
44274
44275
44276
44277
44278
44279
.....
44299
44300
44301
44302
44303
44304
44305
44306
44307
44308
44309
44310
44311
44312
44313
44314
44315
function JSONRetrieveStringField(P: PUTF8Char; out Field: PUTF8Char;
  out FieldLen: integer; ExpectNameField: boolean): PUTF8Char;
  {$ifdef HASINLINE}inline;{$endif}

/// decode a JSON field in an UTF-8 encoded buffer (used in TSQLTableJSON.Create)
// - this function decodes in the P^ buffer memory itself (no memory allocation
// or copy), for faster process - so take care that P^ is not shared
// - PDest points to the next field to be decoded, or nil when end is reached
// - EndOfObject (if not nil) is set to the JSON value char (',' ':' or '}' e.g.)
// - optional wasString is set to true if the JSON value was a JSON "string"


// - '"strings"' are decoded as 'strings', with wasString=true, properly JSON
// unescaped (e.g. any \u0123 pattern would be converted into UTF-8 content)
// - null is decoded as nil, with wasString=false
// - true/false boolean values are returned as 'true'/'false', with wasString=false
// - any number value is returned as its ascii representation, with wasString=false
// - works for both field names or values (e.g. '"FieldName":' or 'Value,')

function GetJSONField(P: PUTF8Char; out PDest: PUTF8Char;
  wasString: PBoolean=nil; EndOfObject: PUTF8Char=nil; Len: PInteger=nil): PUTF8Char;

/// decode a JSON field name in an UTF-8 encoded buffer
// - this function decodes in the P^ buffer memory itself (no memory allocation
// or copy), for faster process - so take care that P^ is not shared
// - it will return the property name (with an ending #0) or nil on error
................................................................................
begin
  result := 0;
  if (P<>nil) and GetSetInfo(aTypeInfo,MaxValue,names) then begin
    P := GotoNextNotSpace(P);
    if P^='[' then begin
      P := GotoNextNotSpace(P+1);
      if P^=']' then 
        inc(P) else begin
        repeat
          Text := GetJSONField(P,P,@wasString,@EndOfObject,@TextLen);
          if (Text=nil) or not wasString then begin
            P := nil; // invalid input (expects a JSON array of strings)
            exit;
          end;
          if Text^='*' then begin
................................................................................
            i := -1;
          if i<0 then
            i := FindShortStringListTrimLowerCase(names,MaxValue,Text,TextLen);
          if i>=0 then
            SetBit(result,i);
          // unknown enum names (i=-1) would just be ignored
        until EndOfObject=']';
        if P=nil then
          exit; // avoid GPF below if already reached the input end
      end;
      while not (P^ in EndOfJSONField) do begin // mimics GetJSONField()
        if P^=#0 then begin
          P := nil;
          exit; // unexpected end
        end;
        inc(P);
      end;
................................................................................
      if FirstChar='"' then // special case e.g. for TGUID string
        EndOfObj := FirstChar else begin
        EndOfObj := JSON^;
        inc(JSON);
      end else
      EndOfObj := #0;
  end;
  if JSON=nil then // end reached, but valid content decoded
    result := @NULCHAR else
    result := JSON;
  if EndOfObject<>nil then
    EndOfObject^ := EndOfObj;
end;

function RecordLoadJSON(var Rec; const JSON: RawUTF8; TypeInfo: pointer): boolean;
................................................................................
    raise ESynException.CreateUTF8('%.CustomReader("%"): unsupported',
        [self,fCustomTypeName]);
  ktSet: begin
    i32 := GetSetNameValue(fCustomTypeInfo,P,EndOfObject);
    MoveFast(i32,aValue,fDataSize);
    result := P;
  end;
  else begin // encoded as JSON strings or number
    PropValue := GetJSONField(P,P,@wasString,@EndOfObject,@PropValueLen);
    if PropValue=nil then
      exit; // not a JSON string or number
    if P=nil then // result=nil=error + caller may dec(P); P^:=EndOfObject; 
      P := PropValue+PropValueLen;
    case fKnownType of
    ktGUID:
      if wasString and (TextToGUID(PropValue,@aValue)<>nil) then
        result := P;
    ktEnumeration: begin
................................................................................
    end else
      GetJSONToAnyVariant(Value,result,EndOfObject,TryCustomVariants,AllowDouble);
  end else begin
    Val := GetJSONField(result,result,@wasString,EndOfObject);
    GetVariantFromJSON(Val,wasString,Value,nil,AllowDouble);
  end;
  if result=nil then
    result := @NULCHAR; // reached end, but not invalid input
end;

procedure VariantLoadJSON(var Value: Variant; const JSON: RawUTF8;
  TryCustomVariants: PDocVariantOptions; AllowDouble: boolean);
var tmp: TSynTempBuffer;
begin
  tmp.Init(JSON);
................................................................................
    if n>0 then begin
      SetLength(VValue,n);
      repeat
        if VCount>=n then
          exit; // unexpected array size means invalid JSON
        GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
        if JSON=nil then
          if EndOfObject=']' then // valid end input
            JSON := @NULCHAR else
            exit; // invalid input
        if intvalues<>nil then
          intvalues.UniqueVariant(VValue[VCount]);
        inc(VCount);
      until EndOfObject=']';
    end else
      if JSON^=']' then // n=0
        repeat inc(JSON) until not(JSON^ in [#1..' ']) else
................................................................................
        if Name=nil then
          exit;
        SetString(VName[VCount],PAnsiChar(Name),NameLen);
        if intnames<>nil then
          intnames.UniqueText(VName[VCount]);
        GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
        if JSON=nil then
          if EndOfObject=']' then // valid end input
            JSON := @NULCHAR else
            exit; // invalid input
        if intvalues<>nil then
          intvalues.UniqueVariant(VValue[VCount]);
        inc(VCount);
      until EndOfObject='}';
    end else
      if JSON^='}' then // n=0
        repeat inc(JSON) until not(JSON^ in [#1..' ']) else

Changes to SynopseCommit.inc.

1
'1.18.4176'
|
1
'1.18.4177'