2
2
3
3
jsonDoc.pas
4
4
5
- Copyright 2015-2022 Stijn Sanders
5
+ Copyright 2015-2023 Stijn Sanders
6
6
Made available under terms described in file "LICENSE"
7
7
https://github.com/stijnsanders/jsonDoc
8
8
9
- v1.2.2
9
+ v1.2.3
10
10
11
11
}
12
12
unit jsonDoc;
@@ -63,6 +63,8 @@ interface
63
63
: TGUID = ' {4A534F4E-0001-0006-C000-000000000006}' ;
64
64
IID_IJSONDocWithReUse
65
65
: TGUID = ' {4A534F4E-0001-0007-C000-000000000007}' ;
66
+ IID_IJSONEnumerableSorted
67
+ : TGUID = ' {4A534F4E-0001-0008-C000-000000000008}' ;
66
68
67
69
type
68
70
{
@@ -164,6 +166,17 @@ interface
164
166
function ReUse (const Key: WideString): Variant; stdcall;
165
167
end ;
166
168
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
+
167
180
{
168
181
JSON function: JSON document factory
169
182
call JSON without parameters do create a new blank document
@@ -195,6 +208,14 @@ function JSONEnum(const x: Variant): IJSONEnumerator; overload;
195
208
function JSON (const x: IJSONEnumerator): IJSONDocument; overload; // inline;
196
209
function JSONEnum (const x: IJSONEnumerator): IJSONEnumerator; overload; // inline;
197
210
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
+
198
219
{
199
220
ja function
200
221
create and populate a new IJSONArray instance
@@ -259,7 +280,7 @@ TJSONImplBaseObj = class(TObject, IInterface)
259
280
see also: JSON function
260
281
}
261
282
TJSONDocument = class (TJSONImplBaseObj, IJSONDocument, IJSONEnumerable,
262
- IJSONDocWithReUse)
283
+ IJSONDocWithReUse, IJSONEnumerableSorted )
263
284
private
264
285
FElementIndex,FElementSize:integer;
265
286
FElements:array of record
@@ -293,6 +314,8 @@ TJSONDocument = class(TJSONImplBaseObj, IJSONDocument, IJSONEnumerable,
293
314
read Get_Item write Set_Item; default;
294
315
property AsString: WideString read JSONToString write Parse;
295
316
property UseIJSONArray:boolean read FUseIJSONArray write FUseIJSONArray;
317
+ function NewEnumeratorSorted : IJSONEnumerator; stdcall;
318
+ function IJSONEnumerableSorted.NewEnumerator = NewEnumeratorSorted;
296
319
end ;
297
320
298
321
{
@@ -315,6 +338,27 @@ TJSONEnumerator = class(TJSONImplBaseObj, IJSONEnumerator)
315
338
function v0 : pointer; stdcall;
316
339
end ;
317
340
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
+
318
362
{
319
363
TJSONArray class
320
364
Default ILightArray implementation
@@ -2016,6 +2060,11 @@ function TJSONDocument.NewEnumerator: IJSONEnumerator;
2016
2060
Result:=TJSONEnumerator.Create(Self);
2017
2061
end ;
2018
2062
2063
+ function TJSONDocument.NewEnumeratorSorted : IJSONEnumerator;
2064
+ begin
2065
+ Result:=TJSONEnumeratorSorted.Create(Self);
2066
+ end ;
2067
+
2019
2068
{ TJSONEnumerator }
2020
2069
2021
2070
constructor TJSONEnumerator.Create(Data: TJSONDocument);
@@ -2122,6 +2171,112 @@ function TJSONEnumerator.v0: pointer;
2122
2171
Result:
[email protected] [FIndex].
Value ;
2123
2172
end ;
2124
2173
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
+
2125
2280
{ TVarArrayEnumerator }
2126
2281
2127
2282
constructor TVarArrayEnumerator.Create(const Data: PVariant);
@@ -2819,6 +2974,40 @@ function JSONEnum(const x: IJSONEnumerator): IJSONEnumerator;
2819
2974
Result:=(IUnknown(x.Value ) as IJSONEnumerable).NewEnumerator;
2820
2975
end ;
2821
2976
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
+
2822
3011
function ja (const Items:array of Variant): IJSONArray;
2823
3012
var
2824
3013
a:TJSONArray;
0 commit comments