Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: |
|
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9014c28bd559c9c87287c625c7c7e653 |
User & Date: | abouchez 2014-01-20 08:11:44 |
2014-01-20
| ||
13:34 | added SQLITE_MEMORY_DATABASE_NAME constant as alias to ':memory:' check-in: 18be73251a user: abouchez tags: trunk | |
08:11 |
| |
2014-01-19
| ||
14:52 |
| |
Changes to SQLite3/Documentation/Synopse SQLite3 Framework.pro.
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 |
!end;
!
!destructor TSQLServer.Destroy;
!begin
! FHttpServer.Free;
! inherited;
!end;
You will need to specify also no the client side that those {\f1\fs20 TSQLValue1} and {\f1\fs20 TSQLValue2} tables are virtual.
You have several possibilities:
- Inherit each table not from {\f1\fs20 TSQLRecord}, but from {\f1\fs20 @**TSQLRecordVirtualTableAutoID@}, as was stated above as standard procedure for virtual tables - see @76@;
- If your tables are defined as {\f1\fs20 TSQLRecord}, ensure that the Client side set the table property of its own model to {\f1\fs20 rCustomAutoID};
- If your tables are defined as {\f1\fs20 TSQLRecord}, ensure that both Client and Server set the table property of its own model to {\f1\fs20 rCustomAutoID}.
First option could be done as such:
!type
!! TSQLValue1 = class(TSQLRecordVirtualTableAutoID)
|
| |
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 |
!end;
!
!destructor TSQLServer.Destroy;
!begin
! FHttpServer.Free;
! inherited;
!end;
You will need to specify also on the client side that those {\f1\fs20 TSQLValue1} and {\f1\fs20 TSQLValue2} tables are virtual.
You have several possibilities:
- Inherit each table not from {\f1\fs20 TSQLRecord}, but from {\f1\fs20 @**TSQLRecordVirtualTableAutoID@}, as was stated above as standard procedure for virtual tables - see @76@;
- If your tables are defined as {\f1\fs20 TSQLRecord}, ensure that the Client side set the table property of its own model to {\f1\fs20 rCustomAutoID};
- If your tables are defined as {\f1\fs20 TSQLRecord}, ensure that both Client and Server set the table property of its own model to {\f1\fs20 rCustomAutoID}.
First option could be done as such:
!type
!! TSQLValue1 = class(TSQLRecordVirtualTableAutoID)
|
Changes to SynCommons.pas.
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 ... 528 529 530 531 532 533 534 535 536 537 538 539 540 541 .... 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 .... 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 ..... 11789 11790 11791 11792 11793 11794 11795 11796 11797 11798 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 ..... 21964 21965 21966 21967 21968 21969 21970 21971 21972 21973 21974 21975 21976 21977 21978 21979 21980 ..... 22107 22108 22109 22110 22111 22112 22113 22114 22115 22116 22117 22118 22119 22120 22121 22122 22123 22124 22125 22126 22127 22128 22129 22130 22131 22132 ..... 23200 23201 23202 23203 23204 23205 23206 23207 23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 23221 23222 23223 23224 23225 23226 23227 23228 23229 23230 23231 23232 23233 23234 23235 ..... 23554 23555 23556 23557 23558 23559 23560 23561 23562 23563 23564 23565 23566 23567 23568 23569 23570 23571 23572 23573 ..... 23580 23581 23582 23583 23584 23585 23586 23587 23588 23589 23590 23591 23592 23593 23594 23595 23596 23597 23598 23599 23600 23601 23602 23603 23604 23605 23606 23607 23608 23609 23610 23611 23612 23613 23614 23615 23616 23617 23618 23619 23620 23621 23622 23623 23624 23625 23626 23627 ..... 23632 23633 23634 23635 23636 23637 23638 23639 23640 23641 23642 23643 23644 23645 23646 ..... 28387 28388 28389 28390 28391 28392 28393 28394 28395 28396 28397 28398 28399 28400 ..... 37171 37172 37173 37174 37175 37176 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 37198 37199 37200 37201 37202 37203 37204 37205 ..... 37250 37251 37252 37253 37254 37255 37256 37257 37258 37259 37260 37261 37262 |
- added Base64MagicDecode() and SQLToDateTime() functions - added IsEqual(const A,B: TSQLFieldBits): boolean function - enhanced FPC/Lazarus Win32/Win64 compilation - TDynArrayHashed is now a record with Delphi 2009+, due to a bug in latest version of Delphi compiler when using TDynArrayHashed = object(TDynArray) - fixed [7658da5529] unexpected hash collision in TDynArrayHashed - fixed unexpected GPF in TSynCache.Find() e.g. when cache is disabled - fixed function GetJSONField() to properly decode JSON number with exponent - handle variant serialization in/from JSON using new VariantLoadJSON(), VariantSaveJSON() functions and TTextWriter.AddVariantJSON() method - handle variant serialization in/from our binary custom format, using new VariantLoad(), VariantSaveLength() and VariantSave() functions - added VariantToUTF8() overloaded functions for fast conversion - added VariantToInteger()/VariantToIntegerDef() functions for direct process of numerical variants (e.g. array indexes) ................................................................................ - confusing-named RoundTo2Digits() function renamed into Trunc2ToDigit() - added simple, non banker rounding SimpleRoundTo2Digits() function - fixed potential comparison error in TSynTableFieldProperties.SortCompare() when sorting UTF8 Field with tfoCaseInsensitive in Options - speedup of QuotedStr() function and TDynArrayHashed hashing process - several speedup in GetJSONField() and JSON parsing: it will now expect true, false or null to be in lowercase only (as in json.org specifications) - function GotoNextJSONField() renamed GotoNextJSONItem(), and fixed to handle nested JSON array or objects in addition to string/numbers - added function JSONRetrieveIDField() for fast retrieval of a "ID":.. value - added function JSONRetrieveStringField() for retrieval of a string field name or value from JSON buffer - added TextColor() and TextBackground() functions - will initialize internal console process after any manual AllocConsole call ................................................................................ // - any integer value is left as its ascii representation // - wasString is set to true if the JSON value was a "string" // - 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): PUTF8Char; /// test if the supplied buffer is a "string" value or a numerical value // (floating point or integer), according to the characters within // - this version will recognize null/false/true as strings // - e.g. IsString('0')=false, IsString('abc')=true, IsString('null')=true function IsString(P: PUTF8Char): boolean; /// test if the supplied buffer is a "string" value or a numerical value ................................................................................ {/ delete the window resources used to receive GDI messages - must be called for each CreateInternalWindow() function - both parameter values are then reset to ''/0 } function ReleaseInternalWindow(var aWindowName: string; var aWindow: HWND): boolean; type TPatchCode = array[0..4] of byte; PPatchCode = ^TPatchCode; /// Self-modifying code - change some memory buffer in the code segment // - if Backup is not nil, it should point to a Size array of bytes, ready // to contain the overriden code buffer, for further hook disabling procedure PatchCode(Old,New: pointer; Size: integer; Backup: pointer=nil; LeaveUnprotected: boolean=false); /// Self-modifying code - change one PtrUInt in the code segment procedure PatchCodePtrUInt(Code: PPtrUInt; Value: PtrUInt; LeaveUnprotected: boolean=false); /// Self-modifying code - add an asm JUMP to a redirected function // - if Backup is not nil, it should point to a Size array of bytes, ready // to contain the overriden code buffer, for further hook disabling procedure RedirectCode(Func, RedirectFunc: Pointer; Backup: PPatchCode=nil); /// Self-modifying code - restore a code from its RedirectCode() backup procedure RedirectCodeRestore(Func: pointer; const Backup: TPatchCode); {$else} /// compatibility function, to be implemented according to the running OS // - expect more or less the same result as the homonymous Win32 API function function GetTickCount: Cardinal; ................................................................................ asm bswap eax end; {$endif} {$endif} {$ifndef FPC} procedure FillCharInvoke; asm call System.@FillChar end; procedure MoveInvoke; asm call System.Move end; {$ifdef CPU64} {$ifndef NOX64PATCHRTL} { Some notes about MOVNTI opcode use below: - Delphi inline assembler is not able to compile the instruction -> so we had to write some manual DB $... values instead :( ................................................................................ asm // same params than _CopyRecord{ dest, source, typeInfo: Pointer } {$ifdef CPUX64} .NOFRAME {$endif} jmp System.@CopyRecord end; {$else PUREPASCAL} procedure RecordCopyInvoke; asm call System.@CopyRecord end; procedure RecordCopy(var Dest; const Source; TypeInfo: pointer); asm // faster version of _CopyRecord{dest, source, typeInfo: Pointer} by AB { -> EAX pointer to dest } { EDX pointer to source } { ECX pointer to typeInfo } ................................................................................ end; {$endif PUREPASCAL} {$endif FPC} {$endif ENHANCEDRTL} {$endif DELPHI5OROLDER} {$endif USEPACKAGES} /// used internally to retrieve hidden System.pas function address from asm stub function GetAddressFromCall(AStub: Pointer): Pointer; begin if AStub=nil then result := AStub else if PBYTE(AStub)^ = $E8 then begin Inc(PtrInt(AStub)); Result := Pointer(PtrInt(AStub)+SizeOf(integer)+PInteger(AStub)^); end else Result := nil; end; { ************ Custom record / dynamic array JSON serialization } type /// information about one customized JSON serialization TJSONCustomParserRegistration = record RecordTypeName: RawUTF8; ................................................................................ exit; end; end; end; result := Source; end; function GetJSONFieldOrObjectOrArray(var P: PUTF8Char; wasString: PBoolean=nil; EndOfObject: PUTF8Char=nil; HandleValuesAsObjectOrArray: Boolean=false): PUTF8Char; var Value: PUTF8Char; begin result := nil; while ord(P^) in [1..32] do inc(P); if HandleValuesAsObjectOrArray and (P^ in ['{','[']) then begin Value := P; P := GotoNextJSONObjectOrArray(P); if P=nil then exit; // invalid content if wasString<>nil then wasString^ := false; // was object or array if EndOfObject<>nil then EndOfObject^ := P^; P^ := #0; // so Values[] will be a valid ASCIIZ string inc(P); result := Value; end else result := GetJSONField(P,P,wasString,EndOfObject); end; function VariantLoadJSON(var Value: variant; JSON: PUTF8Char; ForceStringAs: TReturnedStringType; EndOfObject: PUTF8Char; HandleObjectArray: PDocVariantOptions): PUTF8Char; var wasString: boolean; Val: PUTF8Char; begin result := JSON; ................................................................................ var LastDispInvokeType: TSynInvokeableVariantType; procedure SynVarDispProc(Result: PVarData; const Instance: TVarData; CallDesc: PCallDesc; Params: Pointer); cdecl; const DO_PROP = 1; GET_PROP = 2; SET_PROP = 4; var i: integer; Value: TVarData; Handler: TCustomVariantType; CacheDispInvokeType: TSynInvokeableVariantType; // to be thread-safe begin if Instance.VType=varByRef or varVariant then // handle By Ref variants SynVarDispProc(Result,PVarData(Instance.VPointer)^,CallDesc,Params) else begin if Result<>nil then VarClear(Variant(Result^)); case Instance.VType of varDispatch, varDispatch or varByRef, varUnknown, varUnknown or varByRef, varAny: // process Ole Automation variants ................................................................................ CacheDispInvokeType := LastDispInvokeType; if (CacheDispInvokeType<>nil) and (CacheDispInvokeType.VarType=TVarData(Instance).VType) and (CallDesc^.CallType in [GET_PROP, DO_PROP]) and (Result<>nil) and (CallDesc^.ArgCount=0) then begin CacheDispInvokeType.IntGet(Result^,Instance,@CallDesc^.ArgTypes[0]); exit; end else // handle our custom types for i := 0 to SynVariantTypes.Count-1 do with TSynInvokeableVariantType(SynVariantTypes.List[i]) do if VarType=TVarData(Instance).VType then case CallDesc^.CallType of GET_PROP, DO_PROP: if (Result<>nil) and (CallDesc^.ArgCount=0) then begin IntGet(Result^,Instance,@CallDesc^.ArgTypes[0]); LastDispInvokeType := SynVariantTypes.List[i]; // speed up in loop exit; end; SET_PROP: if (Result=nil) and (CallDesc^.ArgCount=1) then begin ParseParamPointer(@Params,CallDesc^.ArgTypes[0],Value); IntSet(Instance,Value,@CallDesc^.ArgTypes[1]); exit; end; end; end; // here we call the default code handling custom types if FindCustomVariantType(Instance.VType,Handler) then TSynInvokeableVariantType(Handler).DispInvoke( {$ifdef DELPHI6OROLDER}Result^{$else}Result{$endif}, Instance,CallDesc,@Params) else raise EInvalidOp.Create('Invalid variant invoke'); end; end; end; end; procedure VariantsDispInvoke; asm call Variants.@DispInvoke; end; {$endif FPC} {$endif ISDELPHIXE2} function SynRegisterCustomVariantType(aClass: TSynInvokeableVariantTypeClass): TSynInvokeableVariantType; {$ifdef DELPHI6OROLDER} ................................................................................ {$ifdef DELPHI6OROLDER} GetVariantManager(VarMgr); VarMgr.DispInvoke := @SynVarDispProc; SetVariantManager(VarMgr); {$else} {$ifndef FPC} {$ifndef ISDELPHIXE2} // Delphi XE2 just does not like our performance trick :( RedirectCode(GetAddressFromCall(@VariantsDispInvoke),@SynVarDispProc); {$endif} {$endif} {$endif} GarbageCollectorFreeAndNil(SynVariantTypes,TObjectList.Create); end; result := aClass.Create; // register variant type SynVariantTypes.Add(result); ................................................................................ if EndOfObject<>nil then EndOfObject^ := P^; P^ := #0; // make zero-terminated PDest := @P[1]; if P[1]=#0 then PDest := nil; end; function IsString(P: PUTF8Char): boolean; // test if P^ is a "string" value begin if P=nil then begin result := false; exit; end; ................................................................................ {$endif PUREPASCAL} {$else} begin {$endif DELPHI5OROLDER} {$ifndef FPC} {$ifdef CPU64} {$ifndef NOX64PATCHRTL} RedirectCode(GetAddressFromCall(@FillCharInvoke),@FillChar); RedirectCode(GetAddressFromCall(@MoveInvoke),@Move); {$endif NOX64PATCHRTL} {$endif CPU64} {$ifndef ENHANCEDRTL} {$ifndef PUREPASCAL} {$ifndef DELPHI5OROLDER} {$ifndef USEPACKAGES} {$ifdef DOPATCHTRTL} RedirectCode(GetAddressFromCall(@RecordCopyInvoke),@RecordCopy); {$endif DOPATCHTRTL} {$endif USEPACKAGES} {$endif DELPHI5OROLDER} {$ifndef LVCL} {$ifndef DELPHI5OROLDER} if not SupportsSSE2 then // back to default X87 code for older CPUs PatchCode(@FillChar,@FillCharX87,FILLCHAR_SIZE); {$endif DELPHI5OROLDER} {$ifndef ISDELPHI2007ANDUP} // use faster FillChar/Move for older Delphi RedirectCode(GetAddressFromCall(@FillCharInvoke),@FillChar); RedirectCode(GetAddressFromCall(@MoveInvoke),@Move); {$endif ISDELPHI2007ANDUP} {$endif LVCL} {$endif PUREPASCAL} {$endif ENHANCEDRTL} {$endif FPC} end; ................................................................................ {$ifndef NOVARIANTS} Assert(SizeOf(TSynTableData)=sizeof(TVarData)); {$endif NOVARIANTS} finalization GarbageCollectorFree; end. |
< > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | < < > > > | > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | > | < | | | | | < | < < | < > > | > | > > > | > > > > > > > > > > > > > > > > > > > > > > | | | | | < < < < < |
439 440 441 442 443 444 445 446 447 448 449 450 451 452 ... 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 .... 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 .... 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 ..... 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 11814 11815 11816 11817 11818 11819 11820 11821 11822 11823 11824 11825 11826 ..... 21978 21979 21980 21981 21982 21983 21984 21985 21986 21987 21988 21989 21990 21991 21992 21993 21994 21995 21996 21997 21998 21999 ..... 22126 22127 22128 22129 22130 22131 22132 22133 22134 22135 22136 22137 22138 22139 ..... 23207 23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 ..... 23539 23540 23541 23542 23543 23544 23545 23546 23547 23548 23549 23550 23551 23552 23553 23554 23555 23556 23557 ..... 23564 23565 23566 23567 23568 23569 23570 23571 23572 23573 23574 23575 23576 23577 23578 23579 23580 23581 23582 23583 23584 23585 23586 23587 23588 23589 23590 23591 23592 23593 23594 23595 23596 23597 23598 23599 23600 23601 23602 23603 23604 23605 23606 23607 23608 23609 23610 23611 23612 23613 ..... 23618 23619 23620 23621 23622 23623 23624 23625 23626 23627 23628 23629 23630 23631 23632 ..... 28373 28374 28375 28376 28377 28378 28379 28380 28381 28382 28383 28384 28385 28386 28387 28388 28389 28390 28391 28392 28393 28394 28395 28396 28397 28398 28399 28400 28401 28402 28403 28404 28405 28406 28407 28408 ..... 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 37198 37199 37200 37201 37202 37203 37204 37205 37206 37207 37208 37209 37210 37211 37212 37213 ..... 37258 37259 37260 37261 37262 37263 37264 37265 |
- added Base64MagicDecode() and SQLToDateTime() functions - added IsEqual(const A,B: TSQLFieldBits): boolean function - enhanced FPC/Lazarus Win32/Win64 compilation - TDynArrayHashed is now a record with Delphi 2009+, due to a bug in latest version of Delphi compiler when using TDynArrayHashed = object(TDynArray) - fixed [7658da5529] unexpected hash collision in TDynArrayHashed - fixed unexpected GPF in TSynCache.Find() e.g. when cache is disabled - handle variant serialization in/from JSON using new VariantLoadJSON(), VariantSaveJSON() functions and TTextWriter.AddVariantJSON() method - handle variant serialization in/from our binary custom format, using new VariantLoad(), VariantSaveLength() and VariantSave() functions - added VariantToUTF8() overloaded functions for fast conversion - added VariantToInteger()/VariantToIntegerDef() functions for direct process of numerical variants (e.g. array indexes) ................................................................................ - confusing-named RoundTo2Digits() function renamed into Trunc2ToDigit() - added simple, non banker rounding SimpleRoundTo2Digits() function - fixed potential comparison error in TSynTableFieldProperties.SortCompare() when sorting UTF8 Field with tfoCaseInsensitive in Options - speedup of QuotedStr() function and TDynArrayHashed hashing process - several speedup in GetJSONField() and JSON parsing: it will now expect true, false or null to be in lowercase only (as in json.org specifications) - fixed function GetJSONField() to properly decode JSON number with exponent - added function GetJSONFieldOrObjectOrArray() in unit's interface section - function GotoNextJSONField() renamed GotoNextJSONItem(), and fixed to handle nested JSON array or objects in addition to string/numbers - added function JSONRetrieveIDField() for fast retrieval of a "ID":.. value - added function JSONRetrieveStringField() for retrieval of a string field name or value from JSON buffer - added TextColor() and TextBackground() functions - will initialize internal console process after any manual AllocConsole call ................................................................................ // - any integer value is left as its ascii representation // - wasString is set to true if the JSON value was a "string" // - 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): PUTF8Char; /// decode a JSON content in an UTF-8 encoded buffer // - GetJSONField() will only handle JSON "strings" or numbers - if // HandleValuesAsObjectOrArray is TRUE, this function will process JSON { // objects } or [ arrays ] and add a #0 at the end of it // - this function decodes in the P^ buffer memory itself (no memory allocation // or copy), for faster process - so take care that it is an unique string // - PDest points to the next field to be decoded, or nil on any unexpected end // - wasString is set to true if the JSON value was a "string" // - EndOfObject (if not nil) is set to the JSON value char (',' ':' or '}' e.g.) function GetJSONFieldOrObjectOrArray(var P: PUTF8Char; wasString: PBoolean=nil; EndOfObject: PUTF8Char=nil; HandleValuesAsObjectOrArray: Boolean=false): PUTF8Char; /// test if the supplied buffer is a "string" value or a numerical value // (floating point or integer), according to the characters within // - this version will recognize null/false/true as strings // - e.g. IsString('0')=false, IsString('abc')=true, IsString('null')=true function IsString(P: PUTF8Char): boolean; /// test if the supplied buffer is a "string" value or a numerical value ................................................................................ {/ delete the window resources used to receive GDI messages - must be called for each CreateInternalWindow() function - both parameter values are then reset to ''/0 } function ReleaseInternalWindow(var aWindowName: string; var aWindow: HWND): boolean; type /// small memory buffer used to backup a RedirectCode() redirection hook TPatchCode = array[0..4] of byte; /// pointer to a small memory buffer used to backup a RedirectCode() hook PPatchCode = ^TPatchCode; /// self-modifying code - change some memory buffer in the code segment // - if Backup is not nil, it should point to a Size array of bytes, ready // to contain the overriden code buffer, for further hook disabling procedure PatchCode(Old,New: pointer; Size: integer; Backup: pointer=nil; LeaveUnprotected: boolean=false); /// self-modifying code - change one PtrUInt in the code segment procedure PatchCodePtrUInt(Code: PPtrUInt; Value: PtrUInt; LeaveUnprotected: boolean=false); /// self-modifying code - add an asm JUMP to a redirected function // - if Backup is not nil, it should point to a TPatchCode buffer, ready // to contain the overriden code buffer, for further hook disabling procedure RedirectCode(Func, RedirectFunc: Pointer; Backup: PPatchCode=nil); /// self-modifying code - restore a code from its RedirectCode() backup procedure RedirectCodeRestore(Func: pointer; const Backup: TPatchCode); {$else} /// compatibility function, to be implemented according to the running OS // - expect more or less the same result as the homonymous Win32 API function function GetTickCount: Cardinal; ................................................................................ asm bswap eax end; {$endif} {$endif} {$ifndef FPC} function SystemFillCharAddress: Pointer; asm {$ifdef CPU64} mov rax,offset System.@FillChar {$else} mov eax,offset System.@FillChar {$endif} end; {$ifdef CPU64} {$ifndef NOX64PATCHRTL} { Some notes about MOVNTI opcode use below: - Delphi inline assembler is not able to compile the instruction -> so we had to write some manual DB $... values instead :( ................................................................................ asm // same params than _CopyRecord{ dest, source, typeInfo: Pointer } {$ifdef CPUX64} .NOFRAME {$endif} jmp System.@CopyRecord end; {$else PUREPASCAL} function SystemRecordCopyAddress: Pointer; asm {$ifdef CPU64} mov rax,offset System.@CopyRecord {$else} mov eax,offset System.@CopyRecord {$endif} end; procedure RecordCopy(var Dest; const Source; TypeInfo: pointer); asm // faster version of _CopyRecord{dest, source, typeInfo: Pointer} by AB { -> EAX pointer to dest } { EDX pointer to source } { ECX pointer to typeInfo } ................................................................................ end; {$endif PUREPASCAL} {$endif FPC} {$endif ENHANCEDRTL} {$endif DELPHI5OROLDER} {$endif USEPACKAGES} { ************ Custom record / dynamic array JSON serialization } type /// information about one customized JSON serialization TJSONCustomParserRegistration = record RecordTypeName: RawUTF8; ................................................................................ exit; end; end; end; result := Source; end; function VariantLoadJSON(var Value: variant; JSON: PUTF8Char; ForceStringAs: TReturnedStringType; EndOfObject: PUTF8Char; HandleObjectArray: PDocVariantOptions): PUTF8Char; var wasString: boolean; Val: PUTF8Char; begin result := JSON; ................................................................................ var LastDispInvokeType: TSynInvokeableVariantType; procedure SynVarDispProc(Result: PVarData; const Instance: TVarData; CallDesc: PCallDesc; Params: Pointer); cdecl; const DO_PROP = 1; GET_PROP = 2; SET_PROP = 4; var Value: TVarData; Handler: TSynInvokeableVariantType; CacheDispInvokeType: TSynInvokeableVariantType; // to be thread-safe begin if Instance.VType=varByRef or varVariant then // handle By Ref variants SynVarDispProc(Result,PVarData(Instance.VPointer)^,CallDesc,Params) else begin if Result<>nil then VarClear(Variant(Result^)); case Instance.VType of varDispatch, varDispatch or varByRef, varUnknown, varUnknown or varByRef, varAny: // process Ole Automation variants ................................................................................ CacheDispInvokeType := LastDispInvokeType; if (CacheDispInvokeType<>nil) and (CacheDispInvokeType.VarType=TVarData(Instance).VType) and (CallDesc^.CallType in [GET_PROP, DO_PROP]) and (Result<>nil) and (CallDesc^.ArgCount=0) then begin CacheDispInvokeType.IntGet(Result^,Instance,@CallDesc^.ArgTypes[0]); exit; end; end; // handle any custom variant type if FindCustomVariantType(Instance.VType,TCustomVariantType(Handler)) then begin if Handler.InheritsFrom(TSynInvokeableVariantType) then case CallDesc^.CallType of GET_PROP, DO_PROP: // fast direct call of our IntGet() virtual method if (Result<>nil) and (CallDesc^.ArgCount=0) then begin Handler.IntGet(Result^,Instance,@CallDesc^.ArgTypes[0]); LastDispInvokeType := Handler; // speed up in loop exit; end; SET_PROP: // fast direct call of our IntSet() virtual method if (Result=nil) and (CallDesc^.ArgCount=1) then begin ParseParamPointer(@Params,CallDesc^.ArgTypes[0],Value); Handler.IntSet(Instance,Value,@CallDesc^.ArgTypes[1]); exit; end; end; // here we call the default code handling custom types Handler.DispInvoke({$ifdef DELPHI6OROLDER}Result^{$else}Result{$endif}, Instance,CallDesc,@Params) end else raise EInvalidOp.CreateFmt('Invalid variant type %d invoke',[Instance.VType]); end; end; end; end; function VariantsDispInvokeAddress: pointer; asm {$ifdef CPU64} mov rax,offset Variants.@DispInvoke {$else} mov eax,offset Variants.@DispInvoke {$endif} end; {$endif FPC} {$endif ISDELPHIXE2} function SynRegisterCustomVariantType(aClass: TSynInvokeableVariantTypeClass): TSynInvokeableVariantType; {$ifdef DELPHI6OROLDER} ................................................................................ {$ifdef DELPHI6OROLDER} GetVariantManager(VarMgr); VarMgr.DispInvoke := @SynVarDispProc; SetVariantManager(VarMgr); {$else} {$ifndef FPC} {$ifndef ISDELPHIXE2} // Delphi XE2 just does not like our performance trick :( RedirectCode(VariantsDispInvokeAddress,@SynVarDispProc); {$endif} {$endif} {$endif} GarbageCollectorFreeAndNil(SynVariantTypes,TObjectList.Create); end; result := aClass.Create; // register variant type SynVariantTypes.Add(result); ................................................................................ if EndOfObject<>nil then EndOfObject^ := P^; P^ := #0; // make zero-terminated PDest := @P[1]; if P[1]=#0 then PDest := nil; end; function GetJSONFieldOrObjectOrArray(var P: PUTF8Char; wasString: PBoolean=nil; EndOfObject: PUTF8Char=nil; HandleValuesAsObjectOrArray: Boolean=false): PUTF8Char; var Value: PUTF8Char; begin result := nil; while ord(P^) in [1..32] do inc(P); if HandleValuesAsObjectOrArray and (P^ in ['{','[']) then begin Value := P; P := GotoNextJSONObjectOrArray(P); if P=nil then exit; // invalid content if wasString<>nil then wasString^ := false; // was object or array if EndOfObject<>nil then EndOfObject^ := P^; P^ := #0; // so Values[] will be a valid ASCIIZ string inc(P); result := Value; end else result := GetJSONField(P,P,wasString,EndOfObject); end; function IsString(P: PUTF8Char): boolean; // test if P^ is a "string" value begin if P=nil then begin result := false; exit; end; ................................................................................ {$endif PUREPASCAL} {$else} begin {$endif DELPHI5OROLDER} {$ifndef FPC} {$ifdef CPU64} {$ifndef NOX64PATCHRTL} RedirectCode(SystemFillCharAddress,@FillChar); RedirectCode(@System.Move,@Move); {$endif NOX64PATCHRTL} {$endif CPU64} {$ifndef ENHANCEDRTL} {$ifndef PUREPASCAL} {$ifndef DELPHI5OROLDER} {$ifndef USEPACKAGES} {$ifdef DOPATCHTRTL} RedirectCode(SystemRecordCopyAddress,@RecordCopy); {$endif DOPATCHTRTL} {$endif USEPACKAGES} {$endif DELPHI5OROLDER} {$ifndef LVCL} {$ifndef DELPHI5OROLDER} if not SupportsSSE2 then // back to default X87 code for older CPUs PatchCode(@FillChar,@FillCharX87,FILLCHAR_SIZE); {$endif DELPHI5OROLDER} {$ifndef ISDELPHI2007ANDUP} // use faster FillChar/Move for older Delphi RedirectCode(SystemFillCharAddress,@FillChar); RedirectCode(@System.Move,@Move); {$endif ISDELPHI2007ANDUP} {$endif LVCL} {$endif PUREPASCAL} {$endif ENHANCEDRTL} {$endif FPC} end; ................................................................................ {$ifndef NOVARIANTS} Assert(SizeOf(TSynTableData)=sizeof(TVarData)); {$endif NOVARIANTS} finalization GarbageCollectorFree; end. |
Changes to SynMongoDB.pas.
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 |
end; { TBSONVariant } function TBSONVariant.TryJSONToVariant(var JSON: PUTF8Char; var Value: variant; EndOfObject: PUTF8Char): boolean; // warning: this code should NOT modify the JSON buffer in-place ! procedure Return(kind: TBSONElementType; P: PUTF8Char; GotoEndOfObject: AnsiChar='}'); begin if GotoEndOfObject<>#0 then while P^<>GotoEndOfObject do if P^=#0 then exit else inc(P); P := GotoNextNotSpace(P+1); if EndOfObject<>nil then EndOfObject^ := P^; |
| |
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 |
end;
{ TBSONVariant }
function TBSONVariant.TryJSONToVariant(var JSON: PUTF8Char;
var Value: variant; EndOfObject: PUTF8Char): boolean;
// warning: code should NOT modify JSON buffer in-place, unless it returns true
procedure Return(kind: TBSONElementType; P: PUTF8Char; GotoEndOfObject: AnsiChar='}');
begin
if GotoEndOfObject<>#0 then
while P^<>GotoEndOfObject do if P^=#0 then exit else inc(P);
P := GotoNextNotSpace(P+1);
if EndOfObject<>nil then
EndOfObject^ := P^;
|