-
-
Notifications
You must be signed in to change notification settings - Fork 136
/
mormot.core.base.pas
12901 lines (11485 loc) · 402 KB
/
mormot.core.base.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/// Framework Core Shared Types and RTL-like Functions
// - this unit is a part of the Open Source Synopse mORMot framework 2,
// licensed under a MPL/GPL/LGPL three license - see LICENSE.md
unit mormot.core.base;
{
*****************************************************************************
Basic types and reusable stand-alone functions shared by all framework units
- Framework Version and Information
- Common Types Used for Compatibility Between Compilers and CPU
- Numbers (floats and integers) Low-level Definitions
- Integer Arrays Manipulation
- ObjArray PtrArray InterfaceArray Wrapper Functions
- Low-level Types Mapping Binary or Bits Structures
- Buffers (e.g. Hashing and SynLZ compression) Raw Functions
- Efficient Variant Values Conversion
- Sorting/Comparison Functions
- Some Convenient TStream descendants and File access functions
- Faster Alternative to RTL Standard Functions
- Raw Shared Constants / Types Definitions
Aim of those types and functions is to be cross-platform and cross-compiler,
without any dependency but the main FPC/Delphi RTL. It also detects the
kind of CPU it runs on, to adapt to the fastest asm version available.
It is the main unit where x86_64 or i386 asm stubs are included.
*****************************************************************************
}
interface
{$I ..\mormot.defines.inc}
uses
variants,
classes,
contnrs,
types,
sysutils;
{ ************ Framework Version and Information }
const
/// the full text of the Synopse mORMot framework
// - note: we don't supply full version number with build revision for
// HTTP servers, to reduce potential attack surface
SYNOPSE_FRAMEWORK_NAME = 'mORMot';
/// the corresponding version of the mORMot framework, as '2.#.#'
// - 2nd digit is minor version, increased at each framework release,
// when adding functionality in a stable enough manner
// - 3rd digit is a globally increasing git commit number (as generated by the
// commit.sh script) - so won't be reset when minor is up
// - specific branches may have prefixes, e.g. 'lts-2.3.#'
SYNOPSE_FRAMEWORK_VERSION = {$I ..\mormot.commit.inc};
/// a text including the version and the main active conditional options
// - usefull for low-level debugging purpose
SYNOPSE_FRAMEWORK_FULLVERSION = SYNOPSE_FRAMEWORK_VERSION
{$ifdef FPC}
{$ifdef FPC_X64MM} + ' x64MM'
{$ifdef FPCMM_BOOST} + 'b' {$endif}
{$ifdef FPCMM_SERVER} + 's' {$endif}
{$else}
{$ifdef FPC_LIBCMM} + ' CM' {$endif}
{$endif FPC_X64MM}
{$else}
{$ifdef FullDebugMode} + ' FDM' {$endif}
{$endif FPC};
{ ************ Common Types Used for Compatibility Between Compilers and CPU }
const
/// internal Code Page for UTF-8 Unicode encoding
// - as used by RawUtf8 and all our internal framework text process
CP_UTF8 = 65001;
/// internal Code Page for UTF-16 Unicode encoding
// - used e.g. for Delphi 2009+ UnicodeString=String type
CP_UTF16 = 1200;
/// internal Code Page for RawByteString undefined string
CP_RAWBYTESTRING = 65535;
/// fake code page used to recognize RawBlob
// - RawBlob internal code page will be CP_RAWBYTESTRING = 65535, but our ORM
// will identify the RawBlob type and unserialize it using CP_RAWBLOB instead
// - TJsonWriter.AddAnyAnsiBuffer will recognize it and use Base-64 encoding
CP_RAWBLOB = 65534;
/// US English Windows Code Page, i.e. WinAnsi standard character encoding
CP_WINANSI = 1252;
/// Latin-1 ISO/IEC 8859-1 Code Page
// - map low 8-bit Unicode CodePoints
CP_LATIN1 = 819;
/// internal Code Page for System AnsiString encoding
CP_ACP = 0;
/// internal Code Page for System Console encoding
CP_OEM = 1;
/// use rather CP_WINANSI with mORMot 2
CODEPAGE_US = CP_WINANSI;
/// use rather CP_LATIN1 with mORMot 2
CODEPAGE_LATIN1 = CP_LATIN1;
{$ifdef FPC} { make cross-compiler and cross-CPU types available to Delphi }
type
PBoolean = ^boolean;
{$else FPC}
type
{$ifdef CPU64} // Delphi XE2 seems stable about those types (not Delphi 2009)
PtrInt = NativeInt;
PtrUInt = NativeUInt;
{$else}
/// a CPU-dependent signed integer type cast of a pointer / register
// - used for 64-bit compatibility, native under Free Pascal Compiler
PtrInt = integer;
/// a CPU-dependent unsigned integer type cast of a pointer / register
// - used for 64-bit compatibility, native under Free Pascal Compiler
PtrUInt = cardinal;
{$endif CPU64}
/// a CPU-dependent unsigned integer type cast of a pointer of pointer
// - used for 64-bit compatibility, native under Free Pascal Compiler
PPtrUInt = ^PtrUInt;
/// a CPU-dependent signed integer type cast of a pointer of pointer
// - used for 64-bit compatibility, native under Free Pascal Compiler
PPtrInt = ^PtrInt;
/// unsigned Int64 doesn't exist under older Delphi, but is defined in FPC
// - and UInt64 is buggy as hell under Delphi 2007 when inlining functions:
// older compilers will fallback to signed Int64 values
// - anyway, consider using SortDynArrayQWord() to compare QWord values
// in a safe and efficient way, under a CPUX86
// - use UInt64 explicitly in your computation (like in mormot.crypt.ecc),
// if you are sure that Delphi 6-2007 compiler handles your code as expected,
// but mORMot code will expect to use QWord for its internal process
// (e.g. ORM/SOA serialization)
{$ifdef UNICODE}
QWord = UInt64;
{$else}
QWord = type Int64;
{$endif UNICODE}
/// points to an unsigned Int64
PQWord = ^QWord;
// redefined here to not use the unexpected PWord definition from Windows unit
PWord = System.PWord;
// redefined here to not use the unexpected PSingle definition from Windows unit
PSingle = System.PSingle;
// this pointer is not defined on older Delphi revisions
PMethod = ^TMethod;
{$ifndef ISDELPHIXE2}
/// used to store the handle of a system Thread
TThreadID = cardinal;
/// compatibility definition with FPC and newer Delphi
PUInt64 = ^UInt64;
{$endif ISDELPHIXE2}
{$endif FPC}
type
/// RawUtf8 is an UTF-8 String stored in an AnsiString, alias to System.UTF8String
// - all conversion to/from string or WinAnsiString must be explicit on
// Delphi 7/2007, and it will be faster anyway to use our optimized functions
// from mormot.core.unicode.pas unit like StringToUtf8/Utf8ToString
RawUtf8 = System.UTF8String; // CP_UTF8 Codepage
/// a RawUtf8 value which may contain Sensitive Personal Information
// (e.g. a bank card number or a plain password)
// - identified as a specific type e.g. to be hidden in the logs - when the
// woHideSensitivePersonalInformation TTextWriterWriteObjectOption is set
SpiUtf8 = type RawUtf8;
/// WinAnsiString is a WinAnsi-encoded AnsiString (code page 1252)
// - use this type instead of System.String, which behavior changed
// between Delphi 2009 compiler and previous versions: our implementation
// is consistent and compatible with all versions of Delphi compiler
// - all conversion to/from string or RawUtf8/UTF8String must be explicit on
// Delphi 7/2007, and it will be faster anyway to use our optimized functions
// from mormot.core.unicode.pas unit like StringToUtf8/Utf8ToString
{$ifdef HASCODEPAGE}
WinAnsiString = type AnsiString(CP_WINANSI); // WinAnsi 1252 Codepage
{$else}
WinAnsiString = type AnsiString;
{$endif HASCODEPAGE}
{$ifdef HASCODEPAGE}
{$ifdef FPC}
// missing declaration
PRawByteString = ^RawByteString;
{$endif FPC}
{$else}
/// define RawByteString, as it does exist in Delphi 2009+
// - to be used for byte storage into an AnsiString
// - use this type if you don't want the Delphi compiler not to do any
// code page conversions when you assign a typed AnsiString to a RawByteString,
// i.e. a RawUtf8 or a WinAnsiString
RawByteString = type AnsiString;
/// pointer to a RawByteString
PRawByteString = ^RawByteString;
{$endif HASCODEPAGE}
/// RawJson will indicate that this variable content would stay as raw JSON
// - i.e. won't be serialized into values
// - could be any JSON content: number, boolean, null, string, object or array
// - e.g. interface-based service will use it for efficient and AJAX-ready
// transmission of TOrmTableJson result
RawJson = type RawUtf8;
/// a RawByteString sub-type used to store the BLOB content in our ORM
// - equals RawByteString for byte storage
// - TRttiInfo.AnsiStringCodePage will identify this type, and return
// CP_RAWBLOB fake codepage for such a published property, even if it is
// just an alias to CP_RAWBYTESTRING
// - our ORM will therefore identify such properties as BLOB
// - by default, the BLOB fields are not retrieved or updated with raw
// TRest.Retrieve() method, that is "Lazy loading" is enabled by default
// for blobs, unless TRestClientUri.ForceBlobTransfert property is TRUE
// (for all tables), or ForceBlobTransfertTable[] (for a particular table);
// so use RetrieveBlob() methods for handling BLOB fields
// - could be defined as value in a TOrm property as such:
// ! property Blob: RawBlob read fBlob write fBlob;
// - is defined here for proper TRttiProp.WriteAsJson serialization
RawBlob = type RawByteString;
/// SynUnicode is the fastest available Unicode native string type, depending
// on the compiler used
// - this type is native to the compiler, so you can use Length() Copy() and
// such functions with it (this is not possible with RawUnicodeString type)
// - before Delphi 2009+, it uses slow OLE compatible WideString
// (with our Enhanced RTL, WideString allocation can be made faster by using
// an internal caching mechanism of allocation buffers - WideString allocation
// has been made much faster since Windows Vista/Seven)
// - starting with Delphi 2009, it uses the faster UnicodeString type, which
// allow Copy On Write, Reference Counting and fast heap memory allocation
// - on recent FPC, HASVARUSTRING is defined and native UnicodeString is set
{$ifdef HASVARUSTRING}
SynUnicode = UnicodeString;
{$else}
SynUnicode = WideString;
{$endif HASVARUSTRING}
{$ifndef PUREMORMOT2}
/// low-level RawUnicode as an Unicode String stored in an AnsiString
// - DEPRECATED TYPE, introduced in Delphi 7/2007 days: SynUnicode is to be used
// - faster than WideString, which are allocated in Global heap (for COM)
// - an AnsiChar(#0) is added at the end, for having a true WideChar(#0) at ending
// - length(RawUnicode) returns memory bytes count: use (length(RawUnicode) shr 1)
// for WideChar count (that's why the definition of this type since Delphi 2009
// is AnsiString(1200) and not UnicodeString)
// - pointer(RawUnicode) is compatible with Win32 'Wide' API call
// - mimic Delphi 2009 UnicodeString, without the WideString or Ansi conversion overhead
// - all conversion to/from AnsiString or RawUtf8 must be explicit: the
// compiler may not be able to perform implicit conversions on CP_UTF16
{$ifdef HASCODEPAGE}
RawUnicode = type AnsiString(CP_UTF16); // Codepage for an "Unicode" String
{$else}
RawUnicode = type AnsiString;
{$endif HASCODEPAGE}
PRawUnicode = ^RawUnicode;
{$endif PUREMORMOT2}
/// store one 32-bit UCS-4 CodePoint (with a better naming than UCS-4 "Char")
// - RTL's Ucs4Char is buggy, especially on oldest Delphi
Ucs4CodePoint = cardinal;
/// pointer to one 32-bit UCS-4 CodePoint
PUcs4CodePoint = ^Ucs4CodePoint;
/// low-level storage of UCS-4 CodePoints, stored as 32-bit integers
RawUcs4 = array of Ucs4CodePoint;
{$ifdef CPU64}
HalfInt = integer;
HalfUInt = cardinal;
{$else}
/// a CPU-dependent signed integer type cast of half a pointer
HalfInt = smallint;
/// a CPU-dependent unsigned integer type cast of half a pointer
HalfUInt = word;
{$endif CPU64}
/// a CPU-dependent signed integer type cast of a pointer to half a pointer
PHalfInt = ^HalfInt;
/// a CPU-dependent unsigned integer type cast of a pointer to half a pointer
PHalfUInt = ^HalfUInt;
PRawJson = ^RawJson;
PPRawJson = ^PRawJson;
PRawUtf8 = ^RawUtf8;
PPRawUtf8 = ^PRawUtf8;
PWinAnsiString = ^WinAnsiString;
PWinAnsiChar = type PAnsiChar;
PSynUnicode = ^SynUnicode;
PFileName = ^TFileName;
/// a simple wrapper to UTF-8 encoded zero-terminated PAnsiChar
// - PAnsiChar is used only for Win-Ansi encoded text
// - the Synopse mORMot framework uses mostly this PUtf8Char type,
// because all data is internally stored and expected to be UTF-8 encoded
PUtf8Char = type PAnsiChar;
PPUtf8Char = ^PUtf8Char;
PPPUtf8Char = ^PPUtf8Char;
/// a Row/Col array of PUtf8Char, for containing sqlite3_get_table() result
TPUtf8CharArray = array[ 0 .. MaxInt div SizeOf(PUtf8Char) - 1 ] of PUtf8Char;
PPUtf8CharArray = ^TPUtf8CharArray;
/// a dynamic array of PUtf8Char pointers
TPUtf8CharDynArray = array of PUtf8Char;
/// a dynamic array of UTF-8 encoded strings
TRawUtf8DynArray = array of RawUtf8;
PRawUtf8DynArray = ^TRawUtf8DynArray;
TRawUtf8DynArrayDynArray = array of TRawUtf8DynArray;
/// a dynamic array of TVarRec, i.e. could match an "array of const" parameter
TTVarRecDynArray = array of TVarRec;
/// a TVarData values array
// - is not called TVarDataArray to avoid confusion with the corresponding
// type already defined in RTL Variants.pas, and used for custom late-binding
TVarDataStaticArray = array[ 0 .. MaxInt div SizeOf(TVarData) - 1 ] of TVarData;
PVarDataStaticArray = ^TVarDataStaticArray;
TVariantArray = array[ 0 .. MaxInt div SizeOf(Variant) - 1 ] of Variant;
PVariantArray = ^TVariantArray;
TVariantDynArray = array of variant;
PPVariant = ^PVariant;
PPVarData = ^PVarData;
PIntegerDynArray = ^TIntegerDynArray;
TIntegerDynArray = array of integer;
TIntegerDynArrayDynArray = array of TIntegerDynArray;
PCardinalDynArray = ^TCardinalDynArray;
TCardinalDynArray = array of cardinal;
PSingleDynArray = ^TSingleDynArray;
TSingleDynArray = array of Single;
PInt64DynArray = ^TInt64DynArray;
TInt64DynArray = array of Int64;
PQwordDynArray = ^TQwordDynArray;
TQwordDynArray = array of Qword;
TPtrUIntDynArray = array of PtrUInt;
THalfUIntDynArray = array of HalfUInt;
PDoubleDynArray = ^TDoubleDynArray;
TDoubleDynArray = array of double;
PCurrencyDynArray = ^TCurrencyDynArray;
TCurrencyDynArray = array of currency;
PExtendedDynArray = ^TExtendedDynArray;
TExtendedDynArray = array of Extended;
TWordDynArray = array of word;
PWordDynArray = ^TWordDynArray;
TByteDynArray = array of byte;
PByteDynArray = ^TByteDynArray;
{$ifndef ISDELPHI2007ANDUP}
TBytes = array of byte;
{$endif ISDELPHI2007ANDUP}
TBytesDynArray = array of TBytes;
PBytesDynArray = ^TBytesDynArray;
TObjectDynArray = array of TObject;
PObjectDynArray = ^TObjectDynArray;
TPersistentDynArray = array of TPersistent;
PPersistentDynArray = ^TPersistentDynArray;
TPointerDynArray = array of pointer;
PPointerDynArray = ^TPointerDynArray;
TPointerDynArrayDynArray = array of TPointerDynArray;
TPPointerDynArray = array of PPointer;
PPPointerDynArray = ^TPPointerDynArray;
TMethodDynArray = array of TMethod;
PMethodDynArray = ^TMethodDynArray;
TObjectListDynArray = array of TObjectList;
PObjectListDynArray = ^TObjectListDynArray;
TFileNameDynArray = array of TFileName;
PFileNameDynArray = ^TFileNameDynArray;
TBooleanDynArray = array of boolean;
PBooleanDynArray = ^TBooleanDynArray;
TClassDynArray = array of TClass;
TWinAnsiDynArray = array of WinAnsiString;
PWinAnsiDynArray = ^TWinAnsiDynArray;
TStringDynArray = array of string;
PStringDynArray = ^TStringDynArray;
PShortStringDynArray = array of PShortString;
PPShortStringArray = ^PShortStringArray;
TShortStringDynArray = array of ShortString;
TDateTimeDynArray = array of TDateTime;
PDateTimeDynArray = ^TDateTimeDynArray;
{$ifndef FPC_OR_UNICODE}
TDate = type TDateTime;
TTime = type TDateTime;
{$endif FPC_OR_UNICODE}
TDateDynArray = array of TDate;
PDateDynArray = ^TDateDynArray;
TTimeDynArray = array of TTime;
PTimeDynArray = ^TTimeDynArray;
TWideStringDynArray = array of WideString;
PWideStringDynArray = ^TWideStringDynArray;
TSynUnicodeDynArray = array of SynUnicode;
PSynUnicodeDynArray = ^TSynUnicodeDynArray;
TRawByteStringDynArray = array of RawByteString;
PRawByteStringDynArray = ^TRawByteStringDynArray;
{$ifdef HASVARUSTRING}
TUnicodeStringDynArray = array of UnicodeString;
PUnicodeStringDynArray = ^TUnicodeStringDynArray;
{$endif HASVARUSTRING}
TRawJsonDynArray = array of RawJson;
PRawJsonDynArray = ^TRawJsonDynArray;
TGuidDynArray = array of TGuid;
PGuidDynArray = array of PGuid;
PObject = ^TObject;
PClass = ^TClass;
PList = ^TList;
PObjectList = ^TObjectList;
PCollection = ^TCollection;
PStrings = ^TStrings;
PPByte = ^PByte;
PPPByte = ^PPByte;
PPInteger = ^PInteger;
PPCardinal = ^PCardinal;
PPPointer = ^PPointer;
PByteArray = ^TByteArray;
TByteArray = array[ 0 .. MaxInt - 1 ] of byte; // redefine here with {$R-}
PBooleanArray = ^TBooleanArray;
TBooleanArray = array[ 0 .. MaxInt - 1 ] of boolean;
PPWord = ^PWord;
TWordArray = array[ 0 .. MaxInt div SizeOf(word) - 1 ] of word;
PWordArray = ^TWordArray;
TIntegerArray = array[ 0 .. MaxInt div SizeOf(integer) - 1 ] of integer;
PIntegerArray = ^TIntegerArray;
PIntegerArrayDynArray = array of PIntegerArray;
TPIntegerArray = array[ 0 .. MaxInt div SizeOf(PIntegerArray) - 1 ] of PInteger;
PPIntegerArray = ^TPIntegerArray;
TCardinalArray = array[ 0 .. MaxInt div SizeOf(cardinal) - 1 ] of cardinal;
PCardinalArray = ^TCardinalArray;
TInt64Array = array[ 0 .. MaxInt div SizeOf(Int64) - 1 ] of Int64;
PInt64Array = ^TInt64Array;
TQWordArray = array[ 0 .. MaxInt div SizeOf(QWord) - 1 ] of QWord;
PQWordArray = ^TQWordArray;
TGuidArray = array[ 0 .. MaxInt div SizeOf(TGuid) - 1 ] of TGuid;
PGuidArray = ^TGuidArray;
TPtrUIntArray = array[ 0 .. MaxInt div SizeOf(PtrUInt) - 1 ] of PtrUInt;
PPtrUIntArray = ^TPtrUIntArray;
THalfUIntArray = array[ 0 .. MaxInt div SizeOf(HalfUInt) - 1 ] of HalfUInt;
PHalfUIntArray = ^THalfUIntArray;
TSmallIntArray = array[ 0 .. MaxInt div SizeOf(SmallInt) - 1 ] of SmallInt;
PSmallIntArray = ^TSmallIntArray;
TSingleArray = array[ 0 .. MaxInt div SizeOf(Single) - 1 ] of Single;
PSingleArray = ^TSingleArray;
TDoubleArray = array[ 0 .. MaxInt div SizeOf(Double) - 1 ] of Double;
PDoubleArray = ^TDoubleArray;
TDateTimeArray = array[ 0 .. MaxInt div SizeOf(TDateTime) - 1 ] of TDateTime;
PDateTimeArray = ^TDateTimeArray;
TPAnsiCharArray = array[ 0 .. MaxInt div SizeOf(PAnsiChar) - 1 ] of PAnsiChar;
PPAnsiCharArray = ^TPAnsiCharArray;
TRawUtf8Array = array[ 0 .. MaxInt div SizeOf(RawUtf8) - 1 ] of RawUtf8;
PRawUtf8Array = ^TRawUtf8Array;
TRawByteStringArray = array[ 0 .. MaxInt div SizeOf(RawByteString) - 1 ] of RawByteString;
PRawByteStringArray = ^TRawByteStringArray;
PShortStringArray = array[ 0 .. MaxInt div SizeOf(pointer) - 1 ] of PShortString;
TPointerArray = array[ 0 .. MaxInt div SizeOf(pointer) - 1 ] of pointer;
PPointerArray = ^TPointerArray;
TClassArray = array[ 0 .. MaxInt div SizeOf(TClass) - 1 ] of TClass;
PClassArray = ^TClassArray;
TObjectArray = array[ 0 .. MaxInt div SizeOf(TObject) - 1 ] of TObject;
PObjectArray = ^TObjectArray;
TPtrIntArray = array[ 0 .. MaxInt div SizeOf(PtrInt) - 1 ] of PtrInt;
PPtrIntArray = ^TPtrIntArray;
PInt64Rec = ^Int64Rec;
PLongRec = ^LongRec;
PPShortString = ^PShortString;
PTextFile = ^TextFile;
PInterface = ^IInterface;
TInterfaceDynArray = array of IInterface;
PInterfaceDynArray = ^TInterfaceDynArray;
TListClass = class of TList;
TStreamClass = class of TStream;
TStringsClass = class of TStrings;
TObjectListClass = class of TObjectList;
TCollectionClass = class of TCollection;
TCollectionItemClass = class of TCollectionItem;
TInterfacedObjectClass = class of TInterfacedObject;
/// meta-class of all Exception class types
ExceptionClass = class of Exception;
{$M+}
/// a parent Exception class with RTTI generated for its published properties
// - not as good as ESynException, but could be used without mormot.core.text
ExceptionWithProps = class(Exception);
/// a parent TObject class with a virtual constructor and RTTI generated
// for its published properties
// - lighter than TPersistent, TObjectWithRttiMethods or TClonable if you just
// want to persist some published properties, e.g. into JSON
TSynPersistent = class(TObject)
public
/// virtual constructor called at instance creation
// - inherited classes would have a root constructor to override
// - is recognized by our RTTI initialization / JSON serialization process
constructor Create; overload; virtual;
end;
/// a parent TInterfacedObject class with a virtual constructor and RTTI
// generated for its published properties and its methods
// - so class instances published properties could be serialized as JSON,
// and its methods could match IInvokable RTTI
TInterfacedPersistent = class(TInterfacedObject)
public
/// virtual constructor called at instance creation
// - inherited classes would have a root constructor to override
// - is recognized by our RTTI initialization / JSON serialization process
constructor Create; overload; virtual;
end;
/// used to determine the exact class type of a TSynPersistent
// - allow to create instances using its virtual constructor
TSynPersistentClass = class of TSynPersistent;
/// used to determine the exact class type of a TInterfacedPersistent
// - allow to create instances using its virtual constructor
TInterfacedPersistentClass = class of TInterfacedPersistent;
{$M-}
type
/// used e.g. to serialize up to 256-bit as hexadecimal
TShort64 = string[64];
PShort64 = ^TShort64;
/// a shortstring which only takes 48 bytes of memory
TShort47 = string[47];
PShort47 = ^TShort47;
/// used e.g. for SetThreadName/GetCurrentThreadName
TShort31 = string[31];
PShort31 = ^TShort31;
/// used e.g. by Int64ToHttpEtag
TShort23 = string[23];
PShort23 = ^TShort23;
/// used e.g. by PointerToHexShort/CardinalToHexShort/Int64ToHexShort/FormatShort16
// - such result type would avoid a string allocation on heap, so are highly
// recommended e.g. when logging small pieces of information
TShort16 = string[16];
PShort16 = ^TShort16;
/// used e.g. by TSynSystemTime.ToTextDateShort
TShort15 = string[15];
PShort15 = ^TShort15;
/// used e.g. for TTextWriter.AddShorter small text constants
TShort8 = string[8];
PShort8 = ^TShort8;
/// stack-allocated ASCII string, used by GuidToShort() function
TGuidShortString = string[38];
/// cross-compiler type used for string length
// - FPC uses PtrInt/SizeInt, Delphi uses longint even on CPU64
TStrLen = {$ifdef FPC} SizeInt {$else} longint {$endif};
/// pointer to cross-compiler type used for string length
PStrLen = ^TStrLen;
/// cross-compiler type used for dynamic array length
// - both FPC and Delphi uses PtrInt/NativeInt for dynamic array high/length
TDALen = PtrInt;
/// pointer to cross-compiler type used for dynamic array length
PDALen = ^TDALen;
/// cross-compiler type used for string reference counter
// - FPC and Delphi don't always use the same type
TStrCnt = {$ifdef STRCNT32} integer {$else} SizeInt {$endif};
/// pointer to cross-compiler type used for string reference counter
PStrCnt = ^TStrCnt;
/// cross-compiler type used for dynarray reference counter
// - FPC uses PtrInt/SizeInt, Delphi uses longint even on CPU64
TDACnt = {$ifdef DACNT32} integer {$else} SizeInt {$endif};
/// pointer to cross-compiler type used for dynarray reference counter
PDACnt = ^TDACnt;
/// cross-compiler return type of IUnknown._AddRef/_Release methods
// - used to reduce the $ifdef when implementing interfaces in Delphi and FPC
TIntCnt = {$ifdef FPC} longint {$else} integer {$endif};
/// cross-compiler return type of IUnknown.QueryInterface method
// - used to reduce the $ifdef when implementing interfaces in Delphi and FPC
TIntQry = {$ifdef FPC} longint {$else} HRESULT {$endif};
{$ifdef FPC}
TStrRec = record // see TAnsiRec/TUnicodeRec in astrings/ustrings.inc
case integer of
0: (
{$ifdef HASCODEPAGE}
codePage: TSystemCodePage; // =Word
elemSize: Word;
{$ifndef STRCNT32}
{$ifdef CPU64}
_PaddingToQWord: DWord;
{$endif CPU64}
{$endif STRCNT32}
{$endif HASCODEPAGE}
refCnt: TStrCnt; // =SizeInt on older FPC, =longint since FPC 3.4
length: TStrLen;
);
{$ifdef HASCODEPAGE}
1: (
codePageElemSize: cardinal;
);
{$endif HASCODEPAGE}
end;
TDynArrayRec = record
refCnt: TDACnt; // =SizeInt
high: TDALen; // =SizeInt (differs from Delphi: equals length-1)
function GetLength: TDALen; inline;
procedure SetLength(len: TDALen); inline;
property length: TDALen // Delphi compatibility wrapper
read GetLength write SetLength;
end;
{$else not FPC}
/// map the Delphi/FPC string header (stored before each instance)
TStrRec = packed record
{$ifdef HASCODEPAGE}
{$ifdef CPU64}
/// padding bytes for 16 byte alignment of the header
_Padding: cardinal;
{$endif CPU64}
/// the string code page - e.g. CP_UTF8 for RawUtf8
codePage: Word;
/// 1 for AnsiString/RawByteString/RawUtf8, 2 for UnicodeString
elemSize: Word;
{$endif HASCODEPAGE}
/// string reference count (basic garbage memory mechanism)
refCnt: TStrCnt; // 32-bit longint with Delphi
/// equals length(s) - i.e. size in AnsiChar/WideChar, not bytes
length: TStrLen; // 32-bit longint with Delphi
end;
/// map the Delphi/FPC dynamic array header (stored before each instance)
TDynArrayRec = packed record
{$ifdef CPUX64}
/// padding bytes for 16 byte alignment of the header
_Padding: cardinal;
{$endif}
/// dynamic array reference count (basic garbage memory mechanism)
refCnt: TDACnt; // 32-bit longint with Delphi
/// length in element count
// - size in bytes = length*ElemSize
length: TDALen; // PtrInt/NativeInt
end;
{$endif FPC}
PStrRec = ^TStrRec;
PDynArrayRec = ^TDynArrayRec;
const
/// codePage offset = string header size
// - used to calc the beginning of memory allocation of a string
_STRRECSIZE = SizeOf(TStrRec);
/// cross-compiler negative offset to TStrRec.length field
// - to be used inlined e.g. as PStrLen(p - _STRLEN)^
_STRLEN = SizeOf(TStrLen);
/// cross-compiler negative offset to TStrRec.refCnt field
// - to be used inlined e.g. as PStrCnt(p - _STRCNT)^
_STRCNT = SizeOf(TStrCnt) + _STRLEN;
/// used to calc the beginning of memory allocation of a dynamic array
_DARECSIZE = SizeOf(TDynArrayRec);
/// cross-compiler negative offset to TDynArrayRec.high/length field
// - to be used inlined e.g. as
// ! PDALen(PAnsiChar(Values) - _DALEN)^ + _DAOFF
// - both FPC and Delphi uses PtrInt/NativeInt for dynamic array high/length
_DALEN = SizeOf(TDALen);
/// cross-compiler adjuster to get length from TDynArrayRec.high/length field
_DAOFF = {$ifdef FPC} 1 {$else} 0 {$endif};
/// cross-compiler negative offset to TDynArrayRec.refCnt field
// - to be used inlined e.g. as PDACnt(PAnsiChar(Values) - _DACNT)^
_DACNT = SizeOf(TDACnt) + _DALEN;
/// in-memory string process will allow up to 800 MB
// - used as high limit e.g. for TBufferWriter over a TRawByteStringStream
// - Delphi strings have a 32-bit length so you should change your algorithm
// - even if FPC on CPU64 can handle bigger strings, consider other patterns
_STRMAXSIZE = $5fffffff;
/// in-memory TBytes process will allow up to 800 MB
// - used as high limit e.g. for TBufferWriter.FlushToBytes
// - even if a dynamic array can handle PtrInt length, consider other patterns
_DAMAXSIZE = $5fffffff;
/// like SetLength() but without any memory resize - WARNING: len should be > 0
procedure DynArrayFakeLength(arr: pointer; len: TDALen);
{$ifdef HASINLINE} inline; {$endif}
/// low-level deletion of one dynamic array item
// - Last=high(Values) should be > 0 - caller should set Values := nil for Last<=0
// - caller should have made Finalize(Values[Index]) before calling
// - used e.g. by TSecurityDescriptor.Delete()
procedure DynArrayFakeDelete(var Values; Index, Last, ValueSize: PtrUInt);
{$ifndef CPUARM}
type
/// used as ToByte() to properly truncate any integer into 8-bit
// - is defined as an inlined "and 255" function under ARM to work as expected
ToByte = byte;
{$else}
function ToByte(value: cardinal): cardinal; inline;
{$endif CPUARM}
const
/// used to point and return a void ASCIIZ buffer or ShortString
NULCHAR: AnsiChar = #0;
/// a TGuid containing all zero bytes
GUID_NULL: TGuid = '{00000000-0000-0000-0000-000000000000}';
NULL_LOW = ord('n') + ord('u') shl 8 + ord('l') shl 16 + ord('l') shl 24;
FALSE_LOW = ord('f') + ord('a') shl 8 + ord('l') shl 16 + ord('s') shl 24;
FALSE_LOW2 = ord('a') + ord('l') shl 8 + ord('s') shl 16 + ord('e') shl 24;
TRUE_LOW = ord('t') + ord('r') shl 8 + ord('u') shl 16 + ord('e') shl 24;
/// fill a TGuid with 0
procedure FillZero(var result: TGuid); overload;
{$ifdef HASINLINE}inline;{$endif}
/// compare two TGuid values
// - this version is faster than the one supplied by SysUtils
function IsEqualGuid({$ifdef FPC_HAS_CONSTREF}constref{$else}const{$endif}
guid1, guid2: TGuid): boolean; overload;
{$ifdef HASINLINE}inline;{$endif}
/// compare two TGuid values
// - this version is faster than the one supplied by SysUtils
function IsEqualGuid(guid1, guid2: PGuid): boolean; overload;
{$ifdef HASINLINE}inline;{$endif}
/// returns the index of a matching TGuid in an array
// - returns -1 if no item matched
function IsEqualGuidArray(const guid: TGuid; const guids: array of TGuid): integer;
/// check if a TGuid value contains only zero bytes, i.e. GUID_NULL
// - this version is faster than the one supplied by SysUtils
function IsNullGuid({$ifdef FPC_HAS_CONSTREF}constref{$else}const{$endif} guid: TGuid): boolean;
{$ifdef HASINLINE}inline;{$endif}
/// append one TGuid item to a TGuid dynamic array
// - returning the newly inserted index in guids[], or an existing index in
// guids[] if NoDuplicates is TRUE and TGuid already exists
function AddGuid(var guids: TGuidDynArray; const guid: TGuid;
NoDuplicates: boolean = false): integer;
/// compute a random UUid value from the RandomBytes() generator and RFC 4122
procedure RandomGuid(out result: TGuid); overload;
/// compute a random UUid value from the RandomBytes() generator and RFC 4122
function RandomGuid: TGuid; overload;
{$ifdef HASINLINE}inline;{$endif}
/// fast O(log(n)) binary search of a binary (e.g. TGuid) value in a sorted array
function FastFindBinarySorted(P, Value: PByteArray; Size, R: PtrInt): PtrInt;
/// compute the new capacity when expanding an array of items
// - handle tiny, small, medium, large and huge sizes properly to reduce
// memory usage and maximize performance
// - initial steps are 4, 8, 12, 28, 40, 56, 72, 88, 104, 120, 136, 170, 212,
// 265, 331, 413, 516, 645, 806, 1007, 1258, 1572, ...
function NextGrow(capacity: integer): integer;
/// compute the next power-of-two of a 32-bit number
function NextPowerOfTwo(number: cardinal): cardinal;
/// equivalence to SetString(s,pansichar,len) function but from a raw pointer
// - so works with both PAnsiChar and PUtf8Char input buffer (or even PByteArray)
// - faster especially under FPC
procedure FastSetString(var s: RawUtf8; p: pointer; len: PtrInt); overload;
{$ifndef HASCODEPAGE} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// faster equivalence to SetString(s,nil,len) function
procedure FastSetString(var s: RawUtf8; len: PtrInt); overload;
{$ifndef HASCODEPAGE} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// equivalence to SetString(s,pansichar,len) function but from a raw pointer
// - so works with both PAnsiChar and PUtf8Char input buffer (or even PByteArray)
// - faster especially under FPC
procedure FastSetRawByteString(var s: RawByteString; p: pointer; len: PtrInt);
{$ifndef HASCODEPAGE} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// equivalence to SetString(s,pwidechar,len) function but from a raw pointer
procedure FastSynUnicode(var s: SynUnicode; p: pointer; len: PtrInt);
{$ifndef HASVARUSTRING} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// equivalence to SetString(s,nil,len) function to allocate a new RawByteString
// - faster especially under FPC
procedure FastNewRawByteString(var s: RawByteString; len: PtrInt);
{$ifndef HASCODEPAGE} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// equivalence to SetString(s,pansichar,len) function with a specific code page
// - faster especially under FPC
procedure FastSetStringCP(var s; p: pointer; len, codepage: PtrInt);
{$ifndef HASCODEPAGE} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// assign any constant or already ref-counted AnsiString/RawUtf8 (or UnicodeString)
// - by default, called with s = nil, is an equivalence to Finalize(d) or d := ''
// - is also called by FastSetString/FastSetStringCP to setup its allocated value
// - faster especially under FPC
procedure FastAssignNew(var d; s: pointer = nil);
{$ifndef FPC_CPUX64} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// internal function to assign any constant or ref-counted AnsiString/RawUtf8
// - caller should have tested that pointer(d) <> nil
procedure FastAssignNewNotVoid(var d; s: pointer); overload;
{$ifndef FPC_CPUX64} {$ifdef HASINLINE}inline;{$endif} {$endif}
/// internal function used by FastSetString/FastSetStringCP
function FastNewString(len, codepage: PtrInt): PAnsiChar;
{$ifdef HASINLINE}inline;{$endif}
/// ensure the supplied variable will have a CP_UTF8 code page
// - making it unique if needed
procedure EnsureRawUtf8(var s: RawByteString); overload;
{$ifdef HASINLINE}inline;{$endif}
/// ensure the supplied variable will have a CP_UTF8 code page
// - making it unique if needed
procedure EnsureRawUtf8(var s: RawUtf8); overload;
{$ifdef HASINLINE}inline;{$endif}
/// internal function which could be used instead of SetLength() if RefCnt = 1
procedure FakeLength(var s: RawUtf8; len: PtrInt); overload;
{$ifdef HASINLINE} inline; {$endif}
/// internal function which could be used instead of SetLength() if RefCnt = 1
procedure FakeLength(var s: RawUtf8; endChar: PUtf8Char); overload;
{$ifdef HASINLINE} inline; {$endif}
/// internal function which could be used instead of SetLength() if RefCnt = 1
procedure FakeLength(var s: RawByteString; len: PtrInt); overload;
{$ifdef HASINLINE} inline; {$endif}
/// internal function which could be used instead of SetLength() if RefCnt = 1
// - FakeLength() don't handle len = 0, whereas this function will
procedure FakeSetLength(var s: RawUtf8; len: PtrInt); overload;
/// internal function which could be used instead of SetLength() if RefCnt = 1
// - FakeLength() don't handle len = 0, whereas this function will
procedure FakeSetLength(var s: RawByteString; len: PtrInt); overload;
/// internal function which could be used instead of SetCodePage() if RefCnt = 1
// - do nothing if HASCODEPAGE is not defined, e.g. on Delphi 7-2007
// - warning: s should NOT be read-only (i.e. assigned from a constant), but
// a just-allocated string with RefCnt <> -1
procedure FakeCodePage(var s: RawByteString; cp: cardinal);
{$ifdef HASINLINE} inline; {$endif}
/// internal function which assign src to dest, force CP_UTF8 and set src to ''
// - warning: calls FakeCodePage(CP_UTF8) so requires src to have a RefCnt of 1
procedure FastAssignUtf8(var dest: RawUtf8; var src: RawByteString);
{$ifdef HASINLINE} inline; {$endif}
{$ifdef HASCODEPAGE}
/// retrieve the code page of a non void string
// - caller should have ensure that s <> ''
function GetCodePage(const s: RawByteString): cardinal; inline;
{$endif HASCODEPAGE}
/// retrieve the code page of a string
// - StringRefCount() is not available on oldest Delphi
function GetRefCount(const s: RawByteString): PtrInt;
{$ifdef HASINLINE} inline; {$endif}
/// initialize a RawByteString, ensuring returned "aligned" pointer
// is 16-bytes aligned
// - to be used e.g. for proper SIMD process
// - you can specify an alternate alignment, but it should be a power of two
procedure GetMemAligned(var holder: RawByteString; fillwith: pointer; len: PtrUInt;
out aligned: pointer; alignment: PtrUInt = 16);
/// equivalence to @u[1] expression to ensure a RawUtf8 variable is unique
// - will ensure that the string refcount is 1, and return a pointer to the text
// - under FPC, @u[1] does not call UniqueString() as it does with Delphi
// - if u is a constant (refcount=-1), will allocate a temporary copy in heap
function UniqueRawUtf8(var u: RawUtf8): pointer;
{$ifdef HASINLINE}inline;{$endif}
/// direct conversion of an ANSI-7 ShortString into an AnsiString
// - can be used e.g. for names retrieved from RTTI to convert them into RawUtf8
function ShortStringToAnsi7String(const source: ShortString): RawByteString; overload;
{$ifdef HASINLINE}inline;{$endif}
/// direct conversion of an ANSI-7 ShortString into an AnsiString
// - can be used e.g. for names retrieved from RTTI to convert them into RawUtf8
procedure ShortStringToAnsi7String(const source: ShortString; var result: RawUtf8); overload;
{$ifdef HASINLINE}inline;{$endif}
/// direct conversion of an ANSI-7 AnsiString into an ShortString
// - can be used e.g. for names retrieved from RTTI
procedure Ansi7StringToShortString(const source: RawUtf8; var result: ShortString);
{$ifdef FPC}inline;{$endif}
/// simple concatenation of a 32-bit unsigned integer as text into a shorstring
procedure AppendShortCardinal(value: cardinal; var dest: ShortString);
/// simple concatenation of a signed 64-bit integer as text into a shorstring
procedure AppendShortInt64(value: Int64; var dest: ShortString);
/// simple concatenation of an unsigned 64-bit integer as text into a shorstring
procedure AppendShortQWord(value: QWord; var dest: ShortString);
/// simple concatenation of a character into a @shorstring
// - dest is @shortstring and not shortstring to circumvent a Delphi inlining bug
procedure AppendShortChar(chr: AnsiChar; dest: PAnsiChar);
{$ifdef HASINLINE} inline; {$endif}
/// simple concatenation of two characters into a @shorstring
// - dest is @shortstring and not shortstring to circumvent a Delphi inlining bug
procedure AppendShortTwoChars(twochars, dest: PAnsiChar);
{$ifdef HASINLINE} inline; {$endif}
/// simple concatenation of a #0 ending text into a @shorstring
// - dest is @shortstring and not shortstring to circumvent a Delphi inlining bug
procedure AppendShortBuffer(buf: PAnsiChar; len: PtrInt; dest: PAnsiChar);
{$ifdef HASINLINE} inline; {$endif}
/// simple concatenation of hexadecimal binary buffer into a shorstring
procedure AppendShortHex(value: PByte; len: PtrUInt; var dest: ShortString);
/// simple concatenation of an integer as lowercase hexadecimal into a shorstring
procedure AppendShortIntHex(value: Int64; var dest: ShortString);
/// simple concatenation of a byte as uppercase hexadecimal into a shorstring
procedure AppendShortByteHex(value: byte; var dest: ShortString);
/// simple concatenation of a ShortString text into a shorstring
procedure AppendShort(const src: ShortString; var dest: ShortString);
/// simple concatenation of an ANSI-7 AnsiString into a shorstring
procedure AppendShortAnsi7String(const buf: RawByteString; var dest: ShortString);
/// simple concatenation of a text buffer into a RawUtf8
procedure AppendBufferToUtf8(src: PUtf8Char; srclen: PtrInt; var dest: RawUtf8);
/// simple concatenation of a ShortString text into a RawUtf8
procedure AppendShortToUtf8(const src: ShortString; var dest: RawUtf8);
{$ifdef HASINLINE}inline;{$endif}
/// just a wrapper around vmtClassName to avoid a string conversion
function ClassNameShort(C: TClass): PShortString; overload;
{$ifdef HASINLINE}inline;{$endif}
/// just a wrapper around vmtClassName to avoid a string conversion
function ClassNameShort(Instance: TObject): PShortString; overload;
{$ifdef HASINLINE}inline;{$endif}
/// just a wrapper around vmtClassName to avoid a string conversion
procedure ClassToText(C: TClass; var result: RawUtf8);
/// just a wrapper around ClassToText() to avoid a string conversion
function ToText(C: TClass): RawUtf8; overload;
{$ifdef HASSAFEINLINE}inline;{$endif}
var
/// retrieve the unit name where a given class is implemented
// - is implemented in mormot.core.rtti.pas; so may be nil otherwise
// - is needed since Delphi 7-2009 do not define TObject.UnitName (because
// there is no such information available in RTTI)
ClassUnit: function(C: TClass): PShortString;
/// just a wrapper around vmtParent to avoid a function call
// - slightly faster than TClass.ClassParent thanks to proper inlining
function GetClassParent(C: TClass): TClass;
{$ifdef HASINLINE}inline;{$endif}
/// case-insensitive comparison of two text buffers only containing ASCII 7-bit
// - this is the actual comparison function called by its overloads
// - use e.g. with RTTI property names values only including A..Z,0..9,_ chars
// - will make the "XOR AND $DF" trick to quickly test A-Z / a-z characters
// - behavior is undefined with UTF-8 encoding (some false positive may occur)
// - see IdemPropName/IdemPropNameU functions in mormot.core.unicode for similar
// comparison functions with other kind of input variables
function PropNameEquals(P1, P2: PAnsiChar; P1Len, P2Len: PtrInt): boolean; overload;
{$ifdef FPC}inline;{$endif} // Delphi has troubles inlining goto/label