Skip to content

Commit bdd8675

Browse files
committed
JSONEnumSorted: IJSONEnumerableSorted
1 parent 8a9936e commit bdd8675

File tree

3 files changed

+197
-5
lines changed

3 files changed

+197
-5
lines changed

CHANGELOG.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
v1.2.3
2+
- JSONEnumSorted: IJSONEnumerableSorted using internal keys sort order
3+
14
v1.2.2
25
- jsonV: detect file change on app activate
36
- jsonV: Ctrl+R to alpha-sort children

jsonDoc.pas

Lines changed: 192 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
33
jsonDoc.pas
44
5-
Copyright 2015-2022 Stijn Sanders
5+
Copyright 2015-2023 Stijn Sanders
66
Made available under terms described in file "LICENSE"
77
https://github.com/stijnsanders/jsonDoc
88
9-
v1.2.2
9+
v1.2.3
1010
1111
}
1212
unit jsonDoc;
@@ -63,6 +63,8 @@ interface
6363
: TGUID = '{4A534F4E-0001-0006-C000-000000000006}';
6464
IID_IJSONDocWithReUse
6565
: TGUID = '{4A534F4E-0001-0007-C000-000000000007}';
66+
IID_IJSONEnumerableSorted
67+
: TGUID = '{4A534F4E-0001-0008-C000-000000000008}';
6668

6769
type
6870
{
@@ -164,6 +166,17 @@ interface
164166
function ReUse(const Key: WideString): Variant; stdcall;
165167
end;
166168

169+
{
170+
IJSONEnumerableSorted interface
171+
used to get a IJSONEnumerable instance for a document, that uses the
172+
document's internal keys sort order
173+
see also: JSONEnum function
174+
}
175+
IJSONEnumerableSorted = interface(IUnknown)
176+
['{4A534F4E-0001-0008-C000-000000000008}']
177+
function NewEnumerator: IJSONEnumerator; stdcall;
178+
end;
179+
167180
{
168181
JSON function: JSON document factory
169182
call JSON without parameters do create a new blank document
@@ -195,6 +208,14 @@ function JSONEnum(const x: Variant): IJSONEnumerator; overload;
195208
function JSON(const x: IJSONEnumerator): IJSONDocument; overload; //inline;
196209
function JSONEnum(const x: IJSONEnumerator): IJSONEnumerator; overload; //inline;
197210

211+
{
212+
JSONEnumSorted function
213+
get a new enumerator to enumeratare the key-value pairs in the document,
214+
using the document's internal keys sort order
215+
}
216+
function JSONEnumSorted(const x: IJSONDocument): IJSONEnumerator; overload; //inline;
217+
function JSONEnumSorted(const x: Variant): IJSONEnumerator; overload;
218+
198219
{
199220
ja function
200221
create and populate a new IJSONArray instance
@@ -259,7 +280,7 @@ TJSONImplBaseObj = class(TObject, IInterface)
259280
see also: JSON function
260281
}
261282
TJSONDocument = class(TJSONImplBaseObj, IJSONDocument, IJSONEnumerable,
262-
IJSONDocWithReUse)
283+
IJSONDocWithReUse, IJSONEnumerableSorted)
263284
private
264285
FElementIndex,FElementSize:integer;
265286
FElements:array of record
@@ -293,6 +314,8 @@ TJSONDocument = class(TJSONImplBaseObj, IJSONDocument, IJSONEnumerable,
293314
read Get_Item write Set_Item; default;
294315
property AsString: WideString read JSONToString write Parse;
295316
property UseIJSONArray:boolean read FUseIJSONArray write FUseIJSONArray;
317+
function NewEnumeratorSorted: IJSONEnumerator; stdcall;
318+
function IJSONEnumerableSorted.NewEnumerator = NewEnumeratorSorted;
296319
end;
297320

298321
{
@@ -315,6 +338,27 @@ TJSONEnumerator = class(TJSONImplBaseObj, IJSONEnumerator)
315338
function v0: pointer; stdcall;
316339
end;
317340

341+
{
342+
TJSONEnumeratorSorted class
343+
a IJSONEnumerator implementation that uses the IJSONDocument's internal
344+
keys sort order
345+
see also: JSONEnumSorted function
346+
}
347+
TJSONEnumeratorSorted = class(TJSONImplBaseObj, IJSONEnumerator)
348+
private
349+
FData:TJSONDocument;
350+
FIndex: integer;
351+
public
352+
constructor Create(Data: TJSONDocument);
353+
destructor Destroy; override;
354+
function EOF: boolean; stdcall;
355+
function Next: boolean; stdcall;
356+
function Get_Key: WideString; stdcall;
357+
function Get_Value: Variant; stdcall;
358+
procedure Set_Value(const Value: Variant); stdcall;
359+
function v0: pointer; stdcall;
360+
end;
361+
318362
{
319363
TJSONArray class
320364
Default ILightArray implementation
@@ -2016,6 +2060,11 @@ function TJSONDocument.NewEnumerator: IJSONEnumerator;
20162060
Result:=TJSONEnumerator.Create(Self);
20172061
end;
20182062

2063+
function TJSONDocument.NewEnumeratorSorted: IJSONEnumerator;
2064+
begin
2065+
Result:=TJSONEnumeratorSorted.Create(Self);
2066+
end;
2067+
20192068
{ TJSONEnumerator }
20202069

20212070
constructor TJSONEnumerator.Create(Data: TJSONDocument);
@@ -2122,6 +2171,112 @@ function TJSONEnumerator.v0: pointer;
21222171
Result:[email protected][FIndex].Value;
21232172
end;
21242173

2174+
{ TJSONEnumeratorSorted }
2175+
2176+
constructor TJSONEnumeratorSorted.Create(Data: TJSONDocument);
2177+
begin
2178+
inherited Create;
2179+
FData:=Data;
2180+
FIndex:=-1;
2181+
//TODO: hook into TJSONDocument destructor?
2182+
end;
2183+
2184+
destructor TJSONEnumeratorSorted.Destroy;
2185+
begin
2186+
FData:=nil;
2187+
inherited;
2188+
end;
2189+
2190+
function TJSONEnumeratorSorted.EOF: boolean;
2191+
var
2192+
i:integer;
2193+
begin
2194+
if FData=nil then
2195+
Result:=true
2196+
else
2197+
begin
2198+
{$IFDEF JSONDOC_THREADSAFE}
2199+
EnterCriticalSection(FData.FLock);
2200+
try
2201+
{$ENDIF}
2202+
i:=FIndex;
2203+
if i=-1 then i:=0;
2204+
while (i<FData.FElementIndex) and
2205+
(FData.FElements[FData.FElements[i].SortIndex].LoadIndex<>FData.FLoadIndex) do
2206+
inc(i);
2207+
Result:=i>=FData.FElementIndex;
2208+
{$IFDEF JSONDOC_THREADSAFE}
2209+
finally
2210+
LeaveCriticalSection(FData.FLock);
2211+
end;
2212+
{$ENDIF}
2213+
end;
2214+
end;
2215+
2216+
function TJSONEnumeratorSorted.Next: boolean;
2217+
begin
2218+
if FData=nil then
2219+
Result:=false
2220+
else
2221+
begin
2222+
{$IFDEF JSONDOC_THREADSAFE}
2223+
EnterCriticalSection(FData.FLock);
2224+
try
2225+
{$ENDIF}
2226+
inc(FIndex);
2227+
while (FIndex<FData.FElementIndex) and
2228+
(FData.FElements[FData.FElements[FIndex].SortIndex].LoadIndex<>FData.FLoadIndex) do
2229+
inc(FIndex);
2230+
Result:=FIndex<FData.FElementIndex;
2231+
{$IFDEF JSONDOC_THREADSAFE}
2232+
finally
2233+
LeaveCriticalSection(FData.FLock);
2234+
end;
2235+
{$ENDIF}
2236+
end;
2237+
end;
2238+
2239+
function TJSONEnumeratorSorted.Get_Key: WideString;
2240+
begin
2241+
if (FIndex<0) or (FData=nil) or (FIndex>=FData.FElementIndex) then
2242+
raise ERangeError.Create('Out of range')
2243+
else
2244+
Result:=FData.FElements[FData.FElements[FIndex].SortIndex].Key;
2245+
end;
2246+
2247+
function TJSONEnumeratorSorted.Get_Value: Variant;
2248+
begin
2249+
if (FIndex<0) or (FData=nil) or (FIndex>=FData.FElementIndex) then
2250+
raise ERangeError.Create('Out of range')
2251+
else
2252+
Result:=FData.FElements[FData.FElements[FIndex].SortIndex].Value;
2253+
end;
2254+
2255+
procedure TJSONEnumeratorSorted.Set_Value(const Value: Variant);
2256+
begin
2257+
{$IFDEF JSONDOC_THREADSAFE}
2258+
EnterCriticalSection(FData.FLock);
2259+
try
2260+
{$ENDIF}
2261+
if (FIndex<0) or (FData=nil) or (FIndex>=FData.FElementIndex) then
2262+
raise ERangeError.Create('Out of range')
2263+
else
2264+
FData.FElements[FData.FElements[FIndex].SortIndex].Value:=Value;
2265+
{$IFDEF JSONDOC_THREADSAFE}
2266+
finally
2267+
LeaveCriticalSection(FData.FLock);
2268+
end;
2269+
{$ENDIF}
2270+
end;
2271+
2272+
function TJSONEnumeratorSorted.v0: pointer;
2273+
begin
2274+
if (FIndex<0) or (FData=nil) or (FIndex>=FData.FElementIndex) then
2275+
raise ERangeError.Create('Out of range')
2276+
else
2277+
Result:[email protected][FData.FElements[FIndex].SortIndex].Value;
2278+
end;
2279+
21252280
{ TVarArrayEnumerator }
21262281

21272282
constructor TVarArrayEnumerator.Create(const Data: PVariant);
@@ -2819,6 +2974,40 @@ function JSONEnum(const x: IJSONEnumerator): IJSONEnumerator;
28192974
Result:=(IUnknown(x.Value) as IJSONEnumerable).NewEnumerator;
28202975
end;
28212976

2977+
function JSONEnumSorted(const x: IJSONDocument): IJSONEnumerator;
2978+
var
2979+
je:IJSONEnumerableSorted;
2980+
begin
2981+
if x=nil then
2982+
Result:=TJSONEnumerator.Create(nil)
2983+
else
2984+
//Result:=(x as IJSONEnumerable).NewEnumerator;
2985+
if x.QueryInterface(IID_IJSONEnumerableSorted,je)=S_OK then
2986+
Result:=je.NewEnumerator
2987+
else
2988+
raise EJSONException.Create('IJSONDocument instance doesn''t implement IJSONEnumerableSorted');
2989+
end;
2990+
2991+
function JSONEnumSorted(const x: Variant): IJSONEnumerator;
2992+
var
2993+
vt:TVarType;
2994+
e:IJSONEnumerableSorted;
2995+
begin
2996+
vt:=TVarData(x).VType;
2997+
case vt of
2998+
varNull,varEmpty:
2999+
Result:=TJSONEnumerator.Create(nil);//has .EOF=true
3000+
varUnknown:
3001+
if (TVarData(x).VUnknown<>nil) and
3002+
(IUnknown(x).QueryInterface(IID_IJSONEnumerableSorted,e)=S_OK) then
3003+
Result:=e.NewEnumerator
3004+
else
3005+
raise EJSONException.Create('No supported interface found on object');
3006+
else
3007+
raise EJSONException.Create('Unsupported variant type '+IntToHex(vt,4));
3008+
end;
3009+
end;
3010+
28223011
function ja(const Items:array of Variant): IJSONArray;
28233012
var
28243013
a:TJSONArray;

jsonV1.pas

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ interface
44

55
uses
66
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7-
Dialogs, ComCtrls, ActnList, jsonDoc, StdActns, StdCtrls, ExtCtrls;
7+
Dialogs, ComCtrls, ActnList, jsonDoc, StdActns, StdCtrls, ExtCtrls, Menus;
88

99
type
1010
TfrmJsonViewer = class(TForm)
@@ -213,7 +213,7 @@ function TfrmJsonViewer.LoadJSON(const FilePath:string;
213213
m.Write(i,1);
214214
w:=UTF8Decode(PAnsiChar(@PAnsiChar(m.Memory)[3]));
215215
end
216-
//ANSI
216+
//UTF-8 without BOM, or ANSI
217217
else
218218
begin
219219
m.Position:=l;

0 commit comments

Comments
 (0)