Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | {2256} introducing HASCODEPAGE conditional to support FPC_HAS_CPSTRING feature available since FPC 2.7+ |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a4999ede0d8921a866a2bdd9aea354da |
User & Date: | ab 2016-01-13 18:14:11 |
2016-01-13
| ||
18:15 | {2257} updated documentation about how to use properly the ISQLDBRows interface check-in: e3848c4a9d user: ab tags: trunk | |
18:14 | {2256} introducing HASCODEPAGE conditional to support FPC_HAS_CPSTRING feature available since FPC 2.7+ check-in: a4999ede0d user: ab tags: trunk | |
15:10 | {2255} includes regression tests for latest commit feature check-in: f6da482791 user: ab tags: trunk | |
Changes to SQLite3/DDD/infra/dddInfraEmail.pas.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
result := fValidationServerRoot+fValidationMethodName+'/'+
GetWithSalt(aLogonName,aEmail,fValidationSalt)+
BinToBase64URI(pointer(result),length(result));
end;
procedure TDDDEmailValidationService.EmailValidate(
Ctxt: TSQLRestServerURIContext);
var code: RawByteString;
logon,email,signature: RawUTF8;
EmailValidation: TSQLRecordEmailValidation;
begin
signature := Copy(Ctxt.URIBlobFieldName,1,SHA256DIGESTSTRLEN);
if length(signature)<>SHA256DIGESTSTRLEN then
exit;
code := Copy(Ctxt.URIBlobFieldName,SHA256DIGESTSTRLEN+1,200);
|
| |
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
result := fValidationServerRoot+fValidationMethodName+'/'+
GetWithSalt(aLogonName,aEmail,fValidationSalt)+
BinToBase64URI(pointer(result),length(result));
end;
procedure TDDDEmailValidationService.EmailValidate(
Ctxt: TSQLRestServerURIContext);
var code: RawUTF8;
logon,email,signature: RawUTF8;
EmailValidation: TSQLRecordEmailValidation;
begin
signature := Copy(Ctxt.URIBlobFieldName,1,SHA256DIGESTSTRLEN);
if length(signature)<>SHA256DIGESTSTRLEN then
exit;
code := Copy(Ctxt.URIBlobFieldName,SHA256DIGESTSTRLEN+1,200);
|
Changes to SQLite3/DDD/infra/dddInfraSettings.pas.
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 |
begin if self=nil then exit; fOwner := aOwner; if fInitialJsonContent='' then exit; tmp := fInitialJsonContent; UniqueString(AnsiString(tmp)); RemoveCommentsFromJSON(pointer(tmp)); JSONToObject(fOwner,pointer(tmp),result); if not result then fInitialJsonContent := ''; end; procedure TDDDAppSettingsStorageAbstract.Store(const aJSON: RawUTF8); begin |
< | |
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
begin
if self=nil then
exit;
fOwner := aOwner;
if fInitialJsonContent='' then
exit;
tmp := fInitialJsonContent;
RemoveCommentsFromJSON(UniqueRawUTF8(tmp));
JSONToObject(fOwner,pointer(tmp),result);
if not result then
fInitialJsonContent := '';
end;
procedure TDDDAppSettingsStorageAbstract.Store(const aJSON: RawUTF8);
begin
|
Changes to SQLite3/mORMot.pas.
2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 .... 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 .... 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 .... 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 .... 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 .... 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 ..... 19248 19249 19250 19251 19252 19253 19254 19255 19256 19257 19258 19259 19260 19261 19262 ..... 20557 20558 20559 20560 20561 20562 20563 20564 20565 20566 20567 20568 20569 20570 20571 ..... 20670 20671 20672 20673 20674 20675 20676 20677 20678 20679 20680 20681 20682 20683 20684 ..... 25625 25626 25627 25628 25629 25630 25631 25632 25633 25634 25635 25636 25637 25638 25639 ..... 25832 25833 25834 25835 25836 25837 25838 25839 25840 25841 25842 25843 25844 25845 25846 25847 25848 ..... 25862 25863 25864 25865 25866 25867 25868 25869 25870 25871 25872 25873 25874 25875 25876 25877 25878 25879 ..... 25885 25886 25887 25888 25889 25890 25891 25892 25893 25894 25895 25896 25897 25898 25899 ..... 25916 25917 25918 25919 25920 25921 25922 25923 25924 25925 25926 25927 25928 25929 25930 ..... 25951 25952 25953 25954 25955 25956 25957 25958 25959 25960 25961 25962 25963 25964 25965 ..... 25997 25998 25999 26000 26001 26002 26003 26004 26005 26006 26007 26008 26009 26010 26011 26012 26013 26014 26015 26016 26017 26018 26019 26020 26021 26022 26023 26024 26025 26026 26027 26028 26029 26030 26031 26032 26033 26034 26035 26036 26037 26038 26039 26040 26041 26042 26043 26044 26045 ..... 26241 26242 26243 26244 26245 26246 26247 26248 26249 26250 26251 26252 26253 26254 26255 ..... 26452 26453 26454 26455 26456 26457 26458 26459 26460 26461 26462 26463 26464 26465 26466 26467 26468 26469 26470 26471 26472 26473 26474 26475 26476 ..... 26748 26749 26750 26751 26752 26753 26754 26755 26756 26757 26758 26759 26760 26761 26762 ..... 26797 26798 26799 26800 26801 26802 26803 26804 26805 26806 26807 26808 26809 26810 26811 ..... 27253 27254 27255 27256 27257 27258 27259 27260 27261 27262 27263 27264 27265 27266 27267 ..... 27331 27332 27333 27334 27335 27336 27337 27338 27339 27340 27341 27342 27343 27344 27345 ..... 42745 42746 42747 42748 42749 42750 42751 42752 42753 42754 42755 42756 42757 42758 42759 42760 42761 42762 42763 ..... 43597 43598 43599 43600 43601 43602 43603 43604 43605 43606 43607 43608 43609 43610 43611 ..... 43736 43737 43738 43739 43740 43741 43742 43743 43744 43745 43746 43747 43748 43749 43750 ..... 45625 45626 45627 45628 45629 45630 45631 45632 45633 45634 45635 45636 45637 45638 45639 ..... 45840 45841 45842 45843 45844 45845 45846 45847 45848 45849 45850 45851 45852 45853 45854 ..... 48379 48380 48381 48382 48383 48384 48385 48386 48387 48388 48389 48390 48391 48392 48393 48394 48395 48396 48397 |
{$ifdef UNICODE}, tkUString{$endif}); const // maps record or object types tkRecordTypes = [tkRecord]; {$endif} // maps long string types tkStringTypes = [tkLString,tkWString{$ifdef UNICODE},tkUString{$endif}{$ifdef FPC},tkAString{$endif}]; // maps 1, 8, 16, 32 and 64 bit ordinal types tkOrdinalTypes = [tkInteger, tkChar, tkWChar, tkEnumeration, tkSet, tkInt64 {$ifdef FPC},tkBool,tkQWord{$endif}]; type /// specify ordinal (tkInteger and tkEnumeration) storage size and sign ................................................................................ function DynArrayItemSize: integer; {$ifdef HASINLINE}inline;{$endif} /// recognize most used string types, returning their code page // - will recognize TSQLRawBlob as the fake CP_SQLRAWBLOB code page // - will return the exact code page since Delphi 2009, from RTTI // - for non Unicode versions of Delphi, will recognize WinAnsiString as // CODEPAGE_US, RawUnicode as CP_UTF16, RawByteString as CP_RAWBYTESTRING, // AnsiString as 0, and any other type as RawUTF8 function AnsiStringCodePage: integer; {$ifdef UNICODE}inline;{$endif} /// get the TGUID of a given interface type information // - returns nil if this type is not an interface function InterfaceGUID: PGUID; /// get the unit name of a given interface type information // - returns '' if this type is not an interface function InterfaceUnitName: PShortString; /// get the ancestor/parent of a given interface type information ................................................................................ {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure CopyLongStrProp(Source,Dest: TObject); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure GetWideStrProp(Instance: TObject; var Value: WideString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetWideStrProp(Instance: TObject; const Value: WideString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} {$ifdef UNICODE} function GetUnicodeStrProp(Instance: TObject): UnicodeString; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetUnicodeStrProp(Instance: TObject; const Value: UnicodeString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} {$endif} function GetCurrencyProp(Instance: TObject): currency; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetCurrencyProp(Instance: TObject; const Value: Currency); {$ifdef HASINLINE}inline;{$endif} function GetDoubleProp(Instance: TObject): double; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetDoubleProp(Instance: TObject; Value: Double); ................................................................................ procedure SetGenericStringValue(Instance: TObject; const Value: string); /// low-level getter of the long string property value of a given instance // - uses the generic string type: to be used within the VCL // - this method will check if the corresponding property is a Long String, // or an UnicodeString (for Delphi 2009+),and will return '' if it's // not the case function GetGenericStringValue(Instance: TObject): string; {$ifdef UNICODE} /// low-level setter of the Unicode string property value of a given instance // - this method will check if the corresponding property is a Unicode String procedure SetUnicodeStrValue(Instance: TObject; const Value: UnicodeString); /// low-level getter of the Unicode string property value of a given instance // - this method will check if the corresponding property is a Unicode String function GetUnicodeStrValue(Instance: TObject): UnicodeString; {$endif} /// low-level getter of a dynamic array wrapper // - this method will NOT check if the property is a dynamic array: caller // must have already checked that PropType^^.Kind=tkDynArray function GetDynArray(Instance: TObject): TDynArray; overload; {$ifdef HASINLINE}inline;{$endif} /// low-level getter of a dynamic array wrapper // - this method will NOT check if the property is a dynamic array: caller ................................................................................ procedure GetBinary(Instance: TObject; W: TFileBufferWriter); override; function SetBinary(Instance: TObject; P: PAnsiChar): PAnsiChar; override; procedure GetJSONValues(Instance: TObject; W: TJSONSerializer); override; function CompareValue(Item1,Item2: TObject; CaseInsensitive: boolean): PtrInt; override; function GetHash(Instance: TObject; CaseInsensitive: boolean): cardinal; override; end; {$ifdef UNICODE} /// information about a UnicodeString published property TSQLPropInfoRTTIUnicode = class(TSQLPropInfoRTTI) protected procedure CopySameClassProp(Source: TObject; DestInfo: TSQLPropInfo; Dest: TObject); override; public procedure SetValue(Instance: TObject; Value: PUTF8Char; wasString: boolean); override; procedure SetValueVar(Instance: TObject; const Value: RawUTF8; wasString: boolean); override; ................................................................................ procedure GetJSONValues(Instance: TObject; W: TJSONSerializer); override; procedure GetFieldSQLVar(Instance: TObject; var aValue: TSQLVar; var temp: RawByteString); override; function SetFieldSQLVar(Instance: TObject; const aValue: TSQLVar): boolean; override; function CompareValue(Item1,Item2: TObject; CaseInsensitive: boolean): PtrInt; override; function GetHash(Instance: TObject; CaseInsensitive: boolean): cardinal; override; end; {$endif} /// information about a dynamic array published property TSQLPropInfoRTTIDynArray = class(TSQLPropInfoRTTI) protected fObjArray: PClassInstance; function GetDynArray(Instance: TObject): TDynArray; overload; {$ifdef HASINLINE}inline;{$endif} ................................................................................ C := TSQLPropInfoRTTIDouble; tkLString {$ifdef FPC},tkAString{$endif}: case aType^.AnsiStringCodePage of // recognize optimized UTF-8/UTF-16 CP_UTF8: C := TSQLPropInfoRTTIRawUTF8; CP_UTF16: C := TSQLPropInfoRTTIRawUnicode; else C := TSQLPropInfoRTTIAnsi; // will use the right TSynAnsiConvert end; {$ifdef UNICODE} tkUString: C := TSQLPropInfoRTTIUnicode; {$endif} tkWString: C := TSQLPropInfoRTTIWide; end; end; ................................................................................ begin if Value<>nil then UTF8ToWideString(Value,StrLen(Value),Wide); fPropInfo.SetWideStrProp(Instance,Wide); end; {$ifdef UNICODE} { TSQLPropInfoRTTIUnicode } procedure TSQLPropInfoRTTIUnicode.CopySameClassProp(Source: TObject; DestInfo: TSQLPropInfo; Dest: TObject); begin TSQLPropInfoRTTIUnicode(DestInfo).fPropInfo.SetUnicodeStrProp(Dest, ................................................................................ var temp: RawByteString); begin temp := UnicodeStringToUtf8(fPropInfo.GetUnicodeStrProp(Instance)); aValue.VType := ftUTF8; aValue.VText := Pointer(temp); end; {$endif UNICODE} { TObjArraySerializer} type TObjArraySerializer = class(TPointerClassHashed) public ................................................................................ {$ifdef FPC}tkBool,{$endif} tkEnumeration, tkInteger, tkSet: begin V := P^.GetOrdProp(Value); if V<>P^.Default then Add('%%=%'#13,[SubCompName,P^.Name,V]); end; {$ifdef FPC}tkAString,{$endif} tkLString, tkWString {$ifdef UNICODE},tkUString{$endif}: begin P^.GetLongStrValue(Value,tmp); Add('%%=%'#13,[SubCompName,P^.Name,tmp]); end; tkFloat: begin VT[0] := AnsiChar(ExtendedToString(VT,P^.GetFloatProp(Value),DOUBLE_PRECISION)); Add('%%=%'#13,[SubCompName,P^.Name,VT]); end; ................................................................................ case cp of CP_UTF8: result := tmp; CP_SQLRAWBLOB: result := TSQLRawBlobToBlob(TSQLRawBlob(tmp)); else result := TSynAnsiConvert.Engine(cp).AnsiToUTF8(tmp); end; end; end; {$ifdef UNICODE} tkUString: StringToUTF8(GetUnicodeStrProp(Instance),result); {$endif} tkWString: begin GetWideStrProp(Instance,tmpWS); RawUnicodeToUtf8(pointer(tmpWS),length(tmpWS),result); end; else result := ''; end ................................................................................ var tmp: RawByteString; begin if cp=CP_SQLRAWBLOB then tmp := BlobToTSQLRawBlob(Value) else tmp := TSynAnsiConvert.Engine(cp).UTF8ToAnsi(Value); SetLongStrProp(Instance,tmp); end; {$ifdef UNICODE} procedure HandleUnicode(Instance: TObject; const Value: RawUTF8); begin SetUnicodeStrProp(Instance,UTF8ToString(Value)); end; {$endif} procedure HandleWideString(Instance: TObject; const Value: RawUTF8); begin SetWideStrProp(Instance,UTF8ToWideString(Value)); end; var cp: integer; ................................................................................ cp := PropType^.AnsiStringCodePage; if cp=CP_UTF8 then SetLongStrProp(Instance,Value) else HandleAnsiString(Instance,Value,cp); end else SetLongStrProp(Instance,''); end; {$ifdef UNICODE} tkUString: HandleUnicode(Instance,Value); {$endif} tkWString: HandleWideString(Instance,Value); end; end; ................................................................................ i := PropType^.EnumBaseType^.GetEnumNameValue(pointer(u),length(u)); if i>=0 then SetOrdProp(Instance,i) end; tkInt64{$ifdef FPC},tkQWord{$endif}: if VariantToInt64(Value,i64) then SetInt64Prop(Instance,i64); {$ifdef UNICODE}tkUString,{$endif}tkLString,tkWString{$ifdef FPC},tkAString{$endif}: if VariantToUTF8(Value,u) then SetLongStrValue(Instance,u); tkFloat: if VariantToDouble(Value,d) then SetFloatProp(Instance,d); tkVariant: SetVariantProp(Instance,Value); ................................................................................ case PropType^.Kind of tkInteger,tkEnumeration,tkSet,tkChar,tkWChar{$ifdef FPC},tkBool{$endif}: SetOrdProp(Instance,0); tkInt64{$ifdef FPC},tkQWord{$endif}: SetInt64Prop(Instance,0); tkLString{$ifdef FPC},tkAString{$endif}: SetLongStrProp(Instance,''); {$ifdef UNICODE} tkUString: SetUnicodeStrProp(Instance,''); {$endif} tkWString: SetWideStrProp(Instance,''); tkFloat: SetFloatProp(Instance,0); ................................................................................ if (Instance=nil) or (@self=nil) then result := '' else case PropType^.Kind of {$ifdef FPC}tkAString,{$endif} tkLString, tkWString: begin GetLongStrValue(Instance,tmp); result := UTF8ToString(tmp); end; {$ifdef UNICODE} tkUString: result := GetUnicodeStrProp(Instance); {$endif}else result := ''; end; end; procedure TPropInfo.SetGenericStringValue(Instance: TObject; const Value: string); begin if (Instance<>nil) and (@self<>nil) then case PropType^.Kind of {$ifdef FPC}tkAString,{$endif}tkLString, tkWString: SetLongStrValue(Instance,StringToUtf8(Value)); {$ifdef UNICODE} tkUString: SetUnicodeStrProp(Instance,Value); {$endif}end; end; {$ifdef UNICODE} function TPropInfo.GetUnicodeStrValue(Instance: TObject): UnicodeString; begin if (Instance<>nil) and (@self<>nil) and (PropType^^.Kind=tkUString) then result := GetUnicodeStrProp(Instance); end; procedure TPropInfo.SetUnicodeStrValue(Instance: TObject; const Value: UnicodeString); begin if (Instance<>nil) and (@self<>nil) and (PropType^^.Kind=tkUString) then SetUnicodeStrProp(Instance,Value); end; {$endif} procedure TPropInfo.SetOrdValue(Instance: TObject; Value: PtrInt); begin if (Instance<>nil) and (@self<>nil) and (PropType^.Kind in [ tkInteger,tkEnumeration,tkSet,{$ifdef FPC}tkBool,{$endif}tkClass]) then SetOrdProp(Instance,Value); ................................................................................ GetLongStrProp(Source,Value); DestInfo.SetLongStrProp(Dest,Value); end else str: if kD in tkStringTypes then begin GetLongStrValue(Source,RawUTF8(Value)); DestInfo.SetLongStrValue(Dest,RawUTF8(Value)); end; {$ifdef UNICODE} tkUString: if kD=tkUString then DestInfo.SetUnicodeStrProp(Dest,GetUnicodeStrProp(Source)) else goto str; {$endif} tkWString: if kD=tkWString then begin ................................................................................ end; procedure TPropInfo.SetWideStrProp(Instance: TObject; const Value: WideString); begin TypInfo.SetWideStrProp(Instance,@self,Value); end; {$ifdef UNICODE} function TPropInfo.GetUnicodeStrProp(Instance: TObject): UnicodeString; begin Value := TypInfo.GetUnicodeStrProp(Instance,@self); end; procedure TPropInfo.SetUnicodeStrProp(Instance: TObject; const Value: UnicodeString); begin TypInfo.SetUnicodeStrProp(Instance,@self,Value); end; {$endif} function TPropInfo.GetCurrencyProp(Instance: TObject): currency; begin if GetterIsField then result := PCurrency(GetterAddr(Instance))^ else result := TypInfo.GetFloatProp(Instance,@self); end; ................................................................................ M.Data := Instance; if Index=NO_INDEX then // no index TUStringSetProc(M)(Value) else TUStringIndexedSetProc(M)(Index, Value); end; end; {$ifdef UNICODE} function TPropInfo.GetUnicodeStrProp(Instance: TObject): UnicodeString; type TUStringGetProc = function: UnicodeString of object; TUStringIndexedGetProc = function(Index: Integer): UnicodeString of object; var M: TMethod; begin // caller must check that PropType^.Kind = tkUString if PropWrap(GetProc).Kind=$FF then ................................................................................ M.Code := Pointer(SetProc); M.Data := Instance; if Index=NO_INDEX then // no index TUStringSetProc(M)(Value) else TUStringIndexedSetProc(M)(Index, Value); end; end; {$endif} function TPropInfo.GetCurrencyProp(Instance: TObject): currency; type // function(Instance: TObject) trick does not work with CPU64 :( TGetProc = function: currency of object; TIndexedGetProc = function(Index: Integer): currency of object; var P: Pointer; Call: TMethod; ................................................................................ if @self=TypeInfo(WinAnsiString) then begin result := sftAnsiText; exit; end else begin result := sftUTF8Text; // CP_UTF8,CP_UTF16 and any other to UTF-8 text exit; end; {$ifdef UNICODE}tkUString,{$endif} tkChar, tkWChar, tkWString: begin result := sftUTF8Text; exit; end; tkDynArray: begin result := sftBlobDynArray; exit; end; ................................................................................ if @self=nil then result := 0 else DynArrayTypeInfoToRecordInfo(@self,@result); end; function TTypeInfo.AnsiStringCodePage: integer; begin {$ifdef UNICODE} if @self=TypeInfo(TSQLRawBlob) then result := CP_SQLRAWBLOB else if Kind in [{$ifdef FPC}tkAString,{$endif} tkLString] then result := PWord(AlignToPtr(@Name[ord(Name[0])+1]))^ else // from RTTI {$else} if @self=TypeInfo(RawUTF8) then result := CP_UTF8 else ................................................................................ Int64ToUtf8(P^.GetInt64Prop(Value))); {$ifdef FPC}tkBool,{$endif} tkEnumeration, tkSet, tkInteger: begin V := P^.GetOrdProp(Value); //if V<>P^.Default then NO DEFAULT: update INI -> must override previous UpdateIniEntry(IniContent,Section,SubCompName+ToUTF8(P^.Name), Int32ToUtf8(V)); end; {$ifdef UNICODE}tkUString,{$endif} {$ifdef FPC}tkAString,{$endif} tkLString, tkWString: begin P^.GetLongStrValue(Value,tmp); UpdateIniEntry(IniContent,Section,SubCompName+ToUTF8(P^.Name),tmp); end; tkClass: if Section='' then begin // recursive call works only as plain object Obj := P^.GetObjProp(Value); if (Obj<>nil) and Obj.InheritsFrom(TPersistent) then WriteObject(Value,IniContent,Section,SubCompName+ToUTF8(P^.Name)+'.'); end; // tkString (shortstring) and tkInterface are not handled ................................................................................ end; {$ifdef FPC}tkAString,{$endif} tkLString: if wasString or (j2oIgnoreStringType in Options) then begin SetString(U,PAnsiChar(PropValue),StrLen(PropValue)); P^.SetLongStrValue(Value,U); end else exit; {$ifdef UNICODE} tkUString: if wasString or (j2oIgnoreStringType in Options) then P^.SetUnicodeStrProp(Value, UTF8DecodeToUnicodeString(PropValue,StrLen(PropValue))) else exit; {$endif} tkWString: ................................................................................ if err=0 then P^.SetFloatProp(Value,E); end; {$ifdef FPC}tkAString,{$endif} tkLString: P^.SetLongStrValue(Value,U); tkWString: P^.SetWideStrProp(Value,UTF8ToWideString(U)); {$ifdef UNICODE} tkUString: P^.SetUnicodeStrProp(Value,UTF8ToString(U)); {$endif} tkDynArray: P^.GetDynArray(Value).LoadFrom(pointer(BlobToTSQLRawBlob(U))); {$ifdef PUBLISHRECORD} tkRecord{$ifdef FPC},tkObject{$endif}: ................................................................................ Table: TSQLTable absolute Value; aClassType: TClass; Kind: TTypeKind; UtfP: PPUtf8CharArray; IsObj: TJSONObject; IsObjCustomIndex: integer; WS: WideString; {$ifdef UNICODE} US: UnicodeString; {$endif} tmp: RawByteString; dyn: TDynArray; dynObjArray: PClassInstance; {$ifndef NOVARIANTS} VVariant: variant; ................................................................................ AddDateTime(P^.GetDoubleProp(Value)); if woDateTimeWithZSuffix in Options then Add('Z'); Add('"'); end else Add(P^.GetFloatProp(Value),DOUBLE_PRECISION); end; {$ifdef UNICODE} tkUString: begin // write converted to UTF-8 US := P^.GetUnicodeStrProp(Value); if (US<>'') or not (woDontStoreEmptyString in Options) then begin HR(P); Add('"'); AddJSONEscapeW(pointer(US)); Add('"'); ................................................................................ result := smvRawJSON else if P=TypeInfo(RawByteString) then result := smvRawByteString else {$ifndef UNICODE} if P=TypeInfo(AnsiString) then result := smvString else result := smvRawUTF8; // UTF-8 by default {$else UNICODE} result := smvRawUTF8; tkUString: result := smvString; {$endif} tkWString: result := smvWideString; tkClass: with P^.ClassType^ do if ClassHasPublishedFields(ClassType) or (JSONObject(ClassType,IsObjCustomIndex,[cpRead,cpWrite]) in [{$ifndef LVCL}oCollection,{$endif}oObjectList,oUtfs,oStrings, |
| | | | | | | | | | | | | | | | | > | | | | | | | | | > | < | | | | | | | | | | | | | | | | | > > > > | |
2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 .... 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 .... 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 .... 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 .... 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 .... 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 ..... 19248 19249 19250 19251 19252 19253 19254 19255 19256 19257 19258 19259 19260 19261 19262 ..... 20557 20558 20559 20560 20561 20562 20563 20564 20565 20566 20567 20568 20569 20570 20571 ..... 20670 20671 20672 20673 20674 20675 20676 20677 20678 20679 20680 20681 20682 20683 20684 ..... 25625 25626 25627 25628 25629 25630 25631 25632 25633 25634 25635 25636 25637 25638 25639 ..... 25832 25833 25834 25835 25836 25837 25838 25839 25840 25841 25842 25843 25844 25845 25846 25847 25848 ..... 25862 25863 25864 25865 25866 25867 25868 25869 25870 25871 25872 25873 25874 25875 25876 25877 25878 25879 ..... 25885 25886 25887 25888 25889 25890 25891 25892 25893 25894 25895 25896 25897 25898 25899 ..... 25916 25917 25918 25919 25920 25921 25922 25923 25924 25925 25926 25927 25928 25929 25930 25931 ..... 25952 25953 25954 25955 25956 25957 25958 25959 25960 25961 25962 25963 25964 25965 25966 ..... 25998 25999 26000 26001 26002 26003 26004 26005 26006 26007 26008 26009 26010 26011 26012 26013 26014 26015 26016 26017 26018 26019 26020 26021 26022 26023 26024 26025 26026 26027 26028 26029 26030 26031 26032 26033 26034 26035 26036 26037 26038 26039 26040 26041 26042 26043 26044 26045 26046 ..... 26242 26243 26244 26245 26246 26247 26248 26249 26250 26251 26252 26253 26254 26255 26256 ..... 26453 26454 26455 26456 26457 26458 26459 26460 26461 26462 26463 26464 26465 26466 26467 26468 26469 26470 26471 26472 26473 26474 26475 26476 26477 ..... 26749 26750 26751 26752 26753 26754 26755 26756 26757 26758 26759 26760 26761 26762 26763 ..... 26798 26799 26800 26801 26802 26803 26804 26805 26806 26807 26808 26809 26810 26811 26812 ..... 27254 27255 27256 27257 27258 27259 27260 27261 27262 27263 27264 27265 27266 27267 27268 ..... 27332 27333 27334 27335 27336 27337 27338 27339 27340 27341 27342 27343 27344 27345 27346 ..... 42746 42747 42748 42749 42750 42751 42752 42753 42754 42755 42756 42757 42758 42759 42760 42761 42762 42763 42764 ..... 43598 43599 43600 43601 43602 43603 43604 43605 43606 43607 43608 43609 43610 43611 43612 ..... 43737 43738 43739 43740 43741 43742 43743 43744 43745 43746 43747 43748 43749 43750 43751 ..... 45626 45627 45628 45629 45630 45631 45632 45633 45634 45635 45636 45637 45638 45639 45640 ..... 45841 45842 45843 45844 45845 45846 45847 45848 45849 45850 45851 45852 45853 45854 45855 ..... 48380 48381 48382 48383 48384 48385 48386 48387 48388 48389 48390 48391 48392 48393 48394 48395 48396 48397 48398 48399 48400 48401 48402 |
{$ifdef UNICODE}, tkUString{$endif}); const // maps record or object types tkRecordTypes = [tkRecord]; {$endif} // maps long string types tkStringTypes = [tkLString,tkWString{$ifdef HASVARUSTRING},tkUString{$endif}{$ifdef FPC},tkAString{$endif}]; // maps 1, 8, 16, 32 and 64 bit ordinal types tkOrdinalTypes = [tkInteger, tkChar, tkWChar, tkEnumeration, tkSet, tkInt64 {$ifdef FPC},tkBool,tkQWord{$endif}]; type /// specify ordinal (tkInteger and tkEnumeration) storage size and sign ................................................................................ function DynArrayItemSize: integer; {$ifdef HASINLINE}inline;{$endif} /// recognize most used string types, returning their code page // - will recognize TSQLRawBlob as the fake CP_SQLRAWBLOB code page // - will return the exact code page since Delphi 2009, from RTTI // - for non Unicode versions of Delphi, will recognize WinAnsiString as // CODEPAGE_US, RawUnicode as CP_UTF16, RawByteString as CP_RAWBYTESTRING, // AnsiString as 0, and any other type as RawUTF8 function AnsiStringCodePage: integer; {$ifdef HASCODEPAGE}inline;{$endif} /// get the TGUID of a given interface type information // - returns nil if this type is not an interface function InterfaceGUID: PGUID; /// get the unit name of a given interface type information // - returns '' if this type is not an interface function InterfaceUnitName: PShortString; /// get the ancestor/parent of a given interface type information ................................................................................ {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure CopyLongStrProp(Source,Dest: TObject); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure GetWideStrProp(Instance: TObject; var Value: WideString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetWideStrProp(Instance: TObject; const Value: WideString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} {$ifdef HASVARUSTRING} function GetUnicodeStrProp(Instance: TObject): UnicodeString; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetUnicodeStrProp(Instance: TObject; const Value: UnicodeString); {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} {$endif HASVARUSTRING} function GetCurrencyProp(Instance: TObject): currency; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetCurrencyProp(Instance: TObject; const Value: Currency); {$ifdef HASINLINE}inline;{$endif} function GetDoubleProp(Instance: TObject): double; {$ifdef USETYPEINFO}{$ifdef HASINLINE}inline;{$endif}{$endif} procedure SetDoubleProp(Instance: TObject; Value: Double); ................................................................................ procedure SetGenericStringValue(Instance: TObject; const Value: string); /// low-level getter of the long string property value of a given instance // - uses the generic string type: to be used within the VCL // - this method will check if the corresponding property is a Long String, // or an UnicodeString (for Delphi 2009+),and will return '' if it's // not the case function GetGenericStringValue(Instance: TObject): string; {$ifdef HASVARUSTRING} /// low-level setter of the Unicode string property value of a given instance // - this method will check if the corresponding property is a Unicode String procedure SetUnicodeStrValue(Instance: TObject; const Value: UnicodeString); /// low-level getter of the Unicode string property value of a given instance // - this method will check if the corresponding property is a Unicode String function GetUnicodeStrValue(Instance: TObject): UnicodeString; {$endif} /// low-level getter of a dynamic array wrapper // - this method will NOT check if the property is a dynamic array: caller // must have already checked that PropType^^.Kind=tkDynArray function GetDynArray(Instance: TObject): TDynArray; overload; {$ifdef HASINLINE}inline;{$endif} /// low-level getter of a dynamic array wrapper // - this method will NOT check if the property is a dynamic array: caller ................................................................................ procedure GetBinary(Instance: TObject; W: TFileBufferWriter); override; function SetBinary(Instance: TObject; P: PAnsiChar): PAnsiChar; override; procedure GetJSONValues(Instance: TObject; W: TJSONSerializer); override; function CompareValue(Item1,Item2: TObject; CaseInsensitive: boolean): PtrInt; override; function GetHash(Instance: TObject; CaseInsensitive: boolean): cardinal; override; end; {$ifdef HASVARUSTRING} /// information about a UnicodeString published property TSQLPropInfoRTTIUnicode = class(TSQLPropInfoRTTI) protected procedure CopySameClassProp(Source: TObject; DestInfo: TSQLPropInfo; Dest: TObject); override; public procedure SetValue(Instance: TObject; Value: PUTF8Char; wasString: boolean); override; procedure SetValueVar(Instance: TObject; const Value: RawUTF8; wasString: boolean); override; ................................................................................ procedure GetJSONValues(Instance: TObject; W: TJSONSerializer); override; procedure GetFieldSQLVar(Instance: TObject; var aValue: TSQLVar; var temp: RawByteString); override; function SetFieldSQLVar(Instance: TObject; const aValue: TSQLVar): boolean; override; function CompareValue(Item1,Item2: TObject; CaseInsensitive: boolean): PtrInt; override; function GetHash(Instance: TObject; CaseInsensitive: boolean): cardinal; override; end; {$endif HASVARUSTRING} /// information about a dynamic array published property TSQLPropInfoRTTIDynArray = class(TSQLPropInfoRTTI) protected fObjArray: PClassInstance; function GetDynArray(Instance: TObject): TDynArray; overload; {$ifdef HASINLINE}inline;{$endif} ................................................................................ C := TSQLPropInfoRTTIDouble; tkLString {$ifdef FPC},tkAString{$endif}: case aType^.AnsiStringCodePage of // recognize optimized UTF-8/UTF-16 CP_UTF8: C := TSQLPropInfoRTTIRawUTF8; CP_UTF16: C := TSQLPropInfoRTTIRawUnicode; else C := TSQLPropInfoRTTIAnsi; // will use the right TSynAnsiConvert end; {$ifdef HASVARUSTRING} tkUString: C := TSQLPropInfoRTTIUnicode; {$endif} tkWString: C := TSQLPropInfoRTTIWide; end; end; ................................................................................ begin if Value<>nil then UTF8ToWideString(Value,StrLen(Value),Wide); fPropInfo.SetWideStrProp(Instance,Wide); end; {$ifdef HASVARUSTRING} { TSQLPropInfoRTTIUnicode } procedure TSQLPropInfoRTTIUnicode.CopySameClassProp(Source: TObject; DestInfo: TSQLPropInfo; Dest: TObject); begin TSQLPropInfoRTTIUnicode(DestInfo).fPropInfo.SetUnicodeStrProp(Dest, ................................................................................ var temp: RawByteString); begin temp := UnicodeStringToUtf8(fPropInfo.GetUnicodeStrProp(Instance)); aValue.VType := ftUTF8; aValue.VText := Pointer(temp); end; {$endif HASVARUSTRING} { TObjArraySerializer} type TObjArraySerializer = class(TPointerClassHashed) public ................................................................................ {$ifdef FPC}tkBool,{$endif} tkEnumeration, tkInteger, tkSet: begin V := P^.GetOrdProp(Value); if V<>P^.Default then Add('%%=%'#13,[SubCompName,P^.Name,V]); end; {$ifdef FPC}tkAString,{$endif} tkLString, tkWString {$ifdef HASVARUSTRING},tkUString{$endif}: begin P^.GetLongStrValue(Value,tmp); Add('%%=%'#13,[SubCompName,P^.Name,tmp]); end; tkFloat: begin VT[0] := AnsiChar(ExtendedToString(VT,P^.GetFloatProp(Value),DOUBLE_PRECISION)); Add('%%=%'#13,[SubCompName,P^.Name,VT]); end; ................................................................................ case cp of CP_UTF8: result := tmp; CP_SQLRAWBLOB: result := TSQLRawBlobToBlob(TSQLRawBlob(tmp)); else result := TSynAnsiConvert.Engine(cp).AnsiToUTF8(tmp); end; end; end; {$ifdef HASVARUSTRING} tkUString: result := UnicodeStringToUTF8(GetUnicodeStrProp(Instance)); {$endif} tkWString: begin GetWideStrProp(Instance,tmpWS); RawUnicodeToUtf8(pointer(tmpWS),length(tmpWS),result); end; else result := ''; end ................................................................................ var tmp: RawByteString; begin if cp=CP_SQLRAWBLOB then tmp := BlobToTSQLRawBlob(Value) else tmp := TSynAnsiConvert.Engine(cp).UTF8ToAnsi(Value); SetLongStrProp(Instance,tmp); end; {$ifdef HASVARUSTRING} procedure HandleUnicode(Instance: TObject; const Value: RawUTF8); begin SetUnicodeStrProp(Instance,UTF8DecodeToUnicodeString(Value)); end; {$endif} procedure HandleWideString(Instance: TObject; const Value: RawUTF8); begin SetWideStrProp(Instance,UTF8ToWideString(Value)); end; var cp: integer; ................................................................................ cp := PropType^.AnsiStringCodePage; if cp=CP_UTF8 then SetLongStrProp(Instance,Value) else HandleAnsiString(Instance,Value,cp); end else SetLongStrProp(Instance,''); end; {$ifdef HASVARUSTRING} tkUString: HandleUnicode(Instance,Value); {$endif} tkWString: HandleWideString(Instance,Value); end; end; ................................................................................ i := PropType^.EnumBaseType^.GetEnumNameValue(pointer(u),length(u)); if i>=0 then SetOrdProp(Instance,i) end; tkInt64{$ifdef FPC},tkQWord{$endif}: if VariantToInt64(Value,i64) then SetInt64Prop(Instance,i64); {$ifdef HASVARUSTRING}tkUString,{$endif} tkLString, tkWString {$ifdef FPC},tkAString{$endif}: if VariantToUTF8(Value,u) then SetLongStrValue(Instance,u); tkFloat: if VariantToDouble(Value,d) then SetFloatProp(Instance,d); tkVariant: SetVariantProp(Instance,Value); ................................................................................ case PropType^.Kind of tkInteger,tkEnumeration,tkSet,tkChar,tkWChar{$ifdef FPC},tkBool{$endif}: SetOrdProp(Instance,0); tkInt64{$ifdef FPC},tkQWord{$endif}: SetInt64Prop(Instance,0); tkLString{$ifdef FPC},tkAString{$endif}: SetLongStrProp(Instance,''); {$ifdef HASVARUSTRING} tkUString: SetUnicodeStrProp(Instance,''); {$endif} tkWString: SetWideStrProp(Instance,''); tkFloat: SetFloatProp(Instance,0); ................................................................................ if (Instance=nil) or (@self=nil) then result := '' else case PropType^.Kind of {$ifdef FPC}tkAString,{$endif} tkLString, tkWString: begin GetLongStrValue(Instance,tmp); result := UTF8ToString(tmp); end; {$ifdef HASVARUSTRING} tkUString: result := string(GetUnicodeStrProp(Instance)); {$endif}else result := ''; end; end; procedure TPropInfo.SetGenericStringValue(Instance: TObject; const Value: string); begin if (Instance<>nil) and (@self<>nil) then case PropType^.Kind of {$ifdef FPC}tkAString,{$endif}tkLString, tkWString: SetLongStrValue(Instance,StringToUtf8(Value)); {$ifdef HASVARUSTRING} tkUString: SetUnicodeStrProp(Instance,UnicodeString(Value)); {$endif} end; end; {$ifdef HASVARUSTRING} function TPropInfo.GetUnicodeStrValue(Instance: TObject): UnicodeString; begin if (Instance<>nil) and (@self<>nil) and (PropType^.Kind=tkUString) then result := GetUnicodeStrProp(Instance); end; procedure TPropInfo.SetUnicodeStrValue(Instance: TObject; const Value: UnicodeString); begin if (Instance<>nil) and (@self<>nil) and (PropType^.Kind=tkUString) then SetUnicodeStrProp(Instance,Value); end; {$endif HASVARUSTRING} procedure TPropInfo.SetOrdValue(Instance: TObject; Value: PtrInt); begin if (Instance<>nil) and (@self<>nil) and (PropType^.Kind in [ tkInteger,tkEnumeration,tkSet,{$ifdef FPC}tkBool,{$endif}tkClass]) then SetOrdProp(Instance,Value); ................................................................................ GetLongStrProp(Source,Value); DestInfo.SetLongStrProp(Dest,Value); end else str: if kD in tkStringTypes then begin GetLongStrValue(Source,RawUTF8(Value)); DestInfo.SetLongStrValue(Dest,RawUTF8(Value)); end; {$ifdef HASVARUSTRING} tkUString: if kD=tkUString then DestInfo.SetUnicodeStrProp(Dest,GetUnicodeStrProp(Source)) else goto str; {$endif} tkWString: if kD=tkWString then begin ................................................................................ end; procedure TPropInfo.SetWideStrProp(Instance: TObject; const Value: WideString); begin TypInfo.SetWideStrProp(Instance,@self,Value); end; {$ifdef HASVARUSTRING} function TPropInfo.GetUnicodeStrProp(Instance: TObject): UnicodeString; begin result := TypInfo.GetUnicodeStrProp(Instance,@self); end; procedure TPropInfo.SetUnicodeStrProp(Instance: TObject; const Value: UnicodeString); begin TypInfo.SetUnicodeStrProp(Instance,@self,Value); end; {$endif HASVARUSTRING} function TPropInfo.GetCurrencyProp(Instance: TObject): currency; begin if GetterIsField then result := PCurrency(GetterAddr(Instance))^ else result := TypInfo.GetFloatProp(Instance,@self); end; ................................................................................ M.Data := Instance; if Index=NO_INDEX then // no index TUStringSetProc(M)(Value) else TUStringIndexedSetProc(M)(Index, Value); end; end; {$ifdef HASVARUSTRING} function TPropInfo.GetUnicodeStrProp(Instance: TObject): UnicodeString; type TUStringGetProc = function: UnicodeString of object; TUStringIndexedGetProc = function(Index: Integer): UnicodeString of object; var M: TMethod; begin // caller must check that PropType^.Kind = tkUString if PropWrap(GetProc).Kind=$FF then ................................................................................ M.Code := Pointer(SetProc); M.Data := Instance; if Index=NO_INDEX then // no index TUStringSetProc(M)(Value) else TUStringIndexedSetProc(M)(Index, Value); end; end; {$endif HASVARUSTRING} function TPropInfo.GetCurrencyProp(Instance: TObject): currency; type // function(Instance: TObject) trick does not work with CPU64 :( TGetProc = function: currency of object; TIndexedGetProc = function(Index: Integer): currency of object; var P: Pointer; Call: TMethod; ................................................................................ if @self=TypeInfo(WinAnsiString) then begin result := sftAnsiText; exit; end else begin result := sftUTF8Text; // CP_UTF8,CP_UTF16 and any other to UTF-8 text exit; end; {$ifdef HASVARUSTRING}tkUString,{$endif} tkChar, tkWChar, tkWString: begin result := sftUTF8Text; exit; end; tkDynArray: begin result := sftBlobDynArray; exit; end; ................................................................................ if @self=nil then result := 0 else DynArrayTypeInfoToRecordInfo(@self,@result); end; function TTypeInfo.AnsiStringCodePage: integer; begin {$ifdef HASCODEPAGE} if @self=TypeInfo(TSQLRawBlob) then result := CP_SQLRAWBLOB else if Kind in [{$ifdef FPC}tkAString,{$endif} tkLString] then result := PWord(AlignToPtr(@Name[ord(Name[0])+1]))^ else // from RTTI {$else} if @self=TypeInfo(RawUTF8) then result := CP_UTF8 else ................................................................................ Int64ToUtf8(P^.GetInt64Prop(Value))); {$ifdef FPC}tkBool,{$endif} tkEnumeration, tkSet, tkInteger: begin V := P^.GetOrdProp(Value); //if V<>P^.Default then NO DEFAULT: update INI -> must override previous UpdateIniEntry(IniContent,Section,SubCompName+ToUTF8(P^.Name), Int32ToUtf8(V)); end; {$ifdef HASVARUSTRING}tkUString,{$endif} {$ifdef FPC}tkAString,{$endif} tkLString, tkWString: begin P^.GetLongStrValue(Value,tmp); UpdateIniEntry(IniContent,Section,SubCompName+ToUTF8(P^.Name),tmp); end; tkClass: if Section='' then begin // recursive call works only as plain object Obj := P^.GetObjProp(Value); if (Obj<>nil) and Obj.InheritsFrom(TPersistent) then WriteObject(Value,IniContent,Section,SubCompName+ToUTF8(P^.Name)+'.'); end; // tkString (shortstring) and tkInterface are not handled ................................................................................ end; {$ifdef FPC}tkAString,{$endif} tkLString: if wasString or (j2oIgnoreStringType in Options) then begin SetString(U,PAnsiChar(PropValue),StrLen(PropValue)); P^.SetLongStrValue(Value,U); end else exit; {$ifdef HASVARUSTRING} tkUString: if wasString or (j2oIgnoreStringType in Options) then P^.SetUnicodeStrProp(Value, UTF8DecodeToUnicodeString(PropValue,StrLen(PropValue))) else exit; {$endif} tkWString: ................................................................................ if err=0 then P^.SetFloatProp(Value,E); end; {$ifdef FPC}tkAString,{$endif} tkLString: P^.SetLongStrValue(Value,U); tkWString: P^.SetWideStrProp(Value,UTF8ToWideString(U)); {$ifdef HASVARUSTRING} tkUString: P^.SetUnicodeStrProp(Value,UTF8ToString(U)); {$endif} tkDynArray: P^.GetDynArray(Value).LoadFrom(pointer(BlobToTSQLRawBlob(U))); {$ifdef PUBLISHRECORD} tkRecord{$ifdef FPC},tkObject{$endif}: ................................................................................ Table: TSQLTable absolute Value; aClassType: TClass; Kind: TTypeKind; UtfP: PPUtf8CharArray; IsObj: TJSONObject; IsObjCustomIndex: integer; WS: WideString; {$ifdef HASVARUSTRING} US: UnicodeString; {$endif} tmp: RawByteString; dyn: TDynArray; dynObjArray: PClassInstance; {$ifndef NOVARIANTS} VVariant: variant; ................................................................................ AddDateTime(P^.GetDoubleProp(Value)); if woDateTimeWithZSuffix in Options then Add('Z'); Add('"'); end else Add(P^.GetFloatProp(Value),DOUBLE_PRECISION); end; {$ifdef HASVARUSTRING} tkUString: begin // write converted to UTF-8 US := P^.GetUnicodeStrProp(Value); if (US<>'') or not (woDontStoreEmptyString in Options) then begin HR(P); Add('"'); AddJSONEscapeW(pointer(US)); Add('"'); ................................................................................ result := smvRawJSON else if P=TypeInfo(RawByteString) then result := smvRawByteString else {$ifndef UNICODE} if P=TypeInfo(AnsiString) then result := smvString else result := smvRawUTF8; // UTF-8 by default {$ifdef HASVARUSTRING} tkUString: result := smvRawUTF8; {$endif} {$else UNICODE} result := smvRawUTF8; tkUString: result := smvString; {$endif UNICODE} tkWString: result := smvWideString; tkClass: with P^.ClassType^ do if ClassHasPublishedFields(ClassType) or (JSONObject(ClassType,IsObjCustomIndex,[cpRead,cpWrite]) in [{$ifndef LVCL}oCollection,{$endif}oObjectList,oUtfs,oStrings, |
Changes to SQLite3/mORMotUIOptions.pas.
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
|
end; tkLString: begin CLE := TLabeledEdit.Create(Scroll); if P^.PropType^=TypeInfo(RawUTF8) then CLE.Text := U2S(P^.GetLongStrValue(Obj)) else CLE.Text := P^.GetGenericStringValue(Obj); end; {$ifdef UNICODE} tkUString: begin CLE := TLabeledEdit.Create(Scroll); CLE.Text := P^.GetUnicodeStrValue(Obj); end; {$endif} tkClass: begin O := pointer(P^.GetOrdValue(Obj)); ................................................................................ Application.ProcessMessages; CNE.SetFocus; // focus corresponding field ShowMessage(CNE.EditLabel.Caption+':'#13+E.Message,true); exit; end; end else if C.InheritsFrom(TLabeledEdit) then {$ifdef UNICODE} if P^.PropType^^.Kind=tkUString then P^.SetUnicodeStrValue(Obj,CLE.Text) else {$endif} if P^.PropType^=TypeInfo(RawUTF8) then P^.SetLongStrValue(Obj,S2U(CLE.Text)) else P^.SetGenericStringValue(Obj,CLE.Text) else if C.InheritsFrom(TCheckBox) then |
|
|
|
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
|
end; tkLString: begin CLE := TLabeledEdit.Create(Scroll); if P^.PropType^=TypeInfo(RawUTF8) then CLE.Text := U2S(P^.GetLongStrValue(Obj)) else CLE.Text := P^.GetGenericStringValue(Obj); end; {$ifdef HASVARUSTRING} tkUString: begin CLE := TLabeledEdit.Create(Scroll); CLE.Text := P^.GetUnicodeStrValue(Obj); end; {$endif} tkClass: begin O := pointer(P^.GetOrdValue(Obj)); ................................................................................ Application.ProcessMessages; CNE.SetFocus; // focus corresponding field ShowMessage(CNE.EditLabel.Caption+':'#13+E.Message,true); exit; end; end else if C.InheritsFrom(TLabeledEdit) then {$ifdef HASVARUSTRING} if P^.PropType^^.Kind=tkUString then P^.SetUnicodeStrValue(Obj,CLE.Text) else {$endif} if P^.PropType^=TypeInfo(RawUTF8) then P^.SetLongStrValue(Obj,S2U(CLE.Text)) else P^.SetGenericStringValue(Obj,CLE.Text) else if C.InheritsFrom(TCheckBox) then |
Changes to SynBidirSock.pas.
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 |
raise ESynBidirSocket.CreateUTF8('%.GetFrame: received %, expected %',
[self,OpcodeText(opcode)^,OpcodeText(Frame.opcode)^]);
GetData(data);
Frame.payload := Frame.payload+data;
end;
if (fProtocol<>nil) and (Frame.payload<>'') then
fProtocol.AfterGetFrame(Frame);
{$ifdef UNICODE}
if opcode=focText then
SetCodePage(Frame.payload,CP_UTF8,false); // identify text value as UTF-8
{$endif}
Log(frame,'GetFrame');
SetLastPingTicks;
result := true;
finally
|
| |
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 |
raise ESynBidirSocket.CreateUTF8('%.GetFrame: received %, expected %',
[self,OpcodeText(opcode)^,OpcodeText(Frame.opcode)^]);
GetData(data);
Frame.payload := Frame.payload+data;
end;
if (fProtocol<>nil) and (Frame.payload<>'') then
fProtocol.AfterGetFrame(Frame);
{$ifdef HASCODEPAGE}
if opcode=focText then
SetCodePage(Frame.payload,CP_UTF8,false); // identify text value as UTF-8
{$endif}
Log(frame,'GetFrame');
SetLastPingTicks;
result := true;
finally
|
Changes to SynCommons.pas.
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 .... 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 .... 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 .... 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 .... 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 .... 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 .... 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 .... 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 ..... 14860 14861 14862 14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873 14874 ..... 14903 14904 14905 14906 14907 14908 14909 14910 14911 14912 14913 14914 14915 14916 14917 ..... 14936 14937 14938 14939 14940 14941 14942 14943 14944 14945 14946 14947 14948 14949 ..... 15346 15347 15348 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 ..... 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 15490 15491 15492 15493 15494 15495 15496 15497 15498 ..... 16161 16162 16163 16164 16165 16166 16167 16168 16169 16170 16171 16172 16173 16174 16175 16176 16177 ..... 16185 16186 16187 16188 16189 16190 16191 16192 16193 16194 16195 16196 16197 16198 16199 ..... 16398 16399 16400 16401 16402 16403 16404 16405 16406 16407 16408 16409 16410 16411 16412 ..... 16497 16498 16499 16500 16501 16502 16503 16504 16505 16506 16507 16508 16509 16510 16511 16512 16513 ..... 17976 17977 17978 17979 17980 17981 17982 17983 17984 17985 17986 17987 17988 17989 17990 ..... 17999 18000 18001 18002 18003 18004 18005 18006 18007 18008 18009 18010 18011 18012 18013 ..... 18310 18311 18312 18313 18314 18315 18316 18317 18318 18319 18320 18321 18322 18323 18324 ..... 18407 18408 18409 18410 18411 18412 18413 18414 18415 18416 18417 18418 18419 18420 18421 ..... 19644 19645 19646 19647 19648 19649 19650 19651 19652 19653 19654 19655 19656 19657 19658 19659 19660 19661 19662 19663 19664 19665 19666 19667 19668 19669 19670 19671 19672 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 19687 19688 19689 19690 19691 19692 19693 19694 ..... 21795 21796 21797 21798 21799 21800 21801 21802 21803 21804 21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 21819 21820 21821 21822 21823 21824 21825 21826 21827 21828 21829 ..... 21837 21838 21839 21840 21841 21842 21843 21844 21845 21846 21847 21848 21849 21850 21851 ..... 21864 21865 21866 21867 21868 21869 21870 21871 21872 21873 21874 21875 21876 21877 21878 21879 21880 21881 21882 21883 21884 21885 21886 21887 21888 21889 21890 21891 21892 21893 21894 21895 21896 ..... 23415 23416 23417 23418 23419 23420 23421 23422 23423 23424 23425 23426 23427 23428 23429 ..... 29155 29156 29157 29158 29159 29160 29161 29162 29163 29164 29165 29166 29167 29168 29169 ..... 30183 30184 30185 30186 30187 30188 30189 30190 30191 30192 30193 30194 30195 30196 30197 ..... 30302 30303 30304 30305 30306 30307 30308 30309 30310 30311 30312 30313 30314 30315 30316 ..... 30384 30385 30386 30387 30388 30389 30390 30391 30392 30393 30394 30395 30396 30397 30398 ..... 30457 30458 30459 30460 30461 30462 30463 30464 30465 30466 30467 30468 30469 30470 30471 30472 30473 30474 30475 30476 ..... 30537 30538 30539 30540 30541 30542 30543 30544 30545 30546 30547 30548 30549 30550 30551 ..... 30558 30559 30560 30561 30562 30563 30564 30565 30566 30567 30568 30569 30570 30571 30572 30573 30574 30575 30576 30577 30578 30579 ..... 30664 30665 30666 30667 30668 30669 30670 30671 30672 30673 30674 30675 30676 30677 30678 30679 30680 30681 30682 30683 30684 30685 30686 30687 30688 30689 30690 30691 30692 30693 ..... 33609 33610 33611 33612 33613 33614 33615 33616 33617 33618 33619 33620 33621 33622 33623 33624 33625 33626 33627 ..... 33632 33633 33634 33635 33636 33637 33638 33639 33640 33641 33642 33643 33644 33645 33646 33647 33648 33649 33650 ..... 33970 33971 33972 33973 33974 33975 33976 33977 33978 33979 33980 33981 33982 33983 33984 ..... 37167 37168 37169 37170 37171 37172 37173 37174 37175 37176 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 ..... 37257 37258 37259 37260 37261 37262 37263 37264 37265 37266 37267 37268 37269 37270 37271 ..... 37920 37921 37922 37923 37924 37925 37926 37927 37928 37929 37930 37931 37932 37933 37934 37935 37936 37937 37938 37939 37940 37941 37942 37943 37944 37945 37946 37947 37948 37949 37950 ..... 38303 38304 38305 38306 38307 38308 38309 38310 38311 38312 38313 38314 38315 38316 38317 ..... 38359 38360 38361 38362 38363 38364 38365 38366 38367 38368 38369 38370 38371 38372 38373 ..... 38436 38437 38438 38439 38440 38441 38442 38443 38444 38445 38446 38447 38448 38449 38450 ..... 38765 38766 38767 38768 38769 38770 38771 38772 38773 38774 38775 38776 38777 38778 38779 ..... 38801 38802 38803 38804 38805 38806 38807 38808 38809 38810 38811 38812 38813 38814 38815 ..... 38850 38851 38852 38853 38854 38855 38856 38857 38858 38859 38860 38861 38862 38863 38864 38865 38866 38867 38868 38869 38870 38871 38872 38873 ..... 38880 38881 38882 38883 38884 38885 38886 38887 38888 38889 38890 38891 38892 38893 38894 ..... 38910 38911 38912 38913 38914 38915 38916 38917 38918 38919 38920 38921 38922 38923 38924 38925 38926 38927 38928 38929 38930 38931 38932 38933 38934 38935 38936 38937 38938 38939 38940 ..... 39217 39218 39219 39220 39221 39222 39223 39224 39225 39226 39227 39228 39229 39230 39231 39232 39233 ..... 39236 39237 39238 39239 39240 39241 39242 39243 39244 39245 39246 39247 39248 39249 39250 39251 39252 39253 39254 ..... 39255 39256 39257 39258 39259 39260 39261 39262 39263 39264 39265 39266 39267 39268 39269 39270 39271 39272 39273 39274 39275 39276 39277 39278 39279 39280 39281 39282 39283 39284 39285 39286 39287 39288 ..... 40906 40907 40908 40909 40910 40911 40912 40913 40914 40915 40916 40917 40918 40919 40920 ..... 40927 40928 40929 40930 40931 40932 40933 40934 40935 40936 40937 40938 40939 40940 40941 ..... 41839 41840 41841 41842 41843 41844 41845 41846 41847 41848 41849 41850 41851 41852 41853 ..... 42084 42085 42086 42087 42088 42089 42090 42091 42092 42093 42094 42095 42096 42097 42098 42099 42100 42101 42102 42103 42104 42105 42106 42107 ..... 42145 42146 42147 42148 42149 42150 42151 42152 42153 42154 42155 42156 42157 42158 42159 ..... 42549 42550 42551 42552 42553 42554 42555 42556 42557 42558 42559 42560 42561 42562 42563 42564 |
/// a pointer to a variant array PVariantArray = ^TVariantArray; /// a dynamic array of variant values TVariantDynArray = array of variant; {$endif} /// RawUnicode is an Unicode String stored in an AnsiString // - 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 {$ifdef UNICODE} RawUnicode = type AnsiString(CP_UTF16); // Codepage for an UnicodeString {$else} RawUnicode = type AnsiString; {$endif} /// RawUTF8 is an UTF-8 String stored in an AnsiString // - use this type instead of System.UTF8String, which behavior changed // between Delphi 2009 compiler and previous versions: our implementation // is consistent and compatible with all versions of Delphi compiler // - mimic Delphi 2009 UTF8String, without the charset conversion overhead // - all conversion to/from AnsiString or RawUnicode must be explicit {$ifdef UNICODE} RawUTF8 = type AnsiString(CP_UTF8); // Codepage for an UTF8 string {$else} RawUTF8 = type AnsiString; {$endif} /// 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 RawUTF8 or RawUnicode must be explicit {$ifdef UNICODE} WinAnsiString = type AnsiString(1252); // WinAnsi Codepage {$else} WinAnsiString = type AnsiString; {$endif} {$ifndef UNICODE} /// 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} /// RawJSON will indicate that this variable content would stay in raw JSON // - i.e. won't be serialized into values // - could be any JSON content: number, string, object or array // - e.g. interface-based service will use it for efficient and AJAX-ready // transmission of TSQLTableJSON result RawJSON = type RawUTF8; ................................................................................ function UTF8DecodeToUnicodeString(const S: RawUTF8): UnicodeString; overload; inline; /// convert our UTF-8 encoded buffer into a Delphi 2009+ Unicode string // - this function is the same as direct assignment, since RawUTF8=AnsiString(CP_UTF8), // but is faster, since use no Win32 API call procedure UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer; var result: UnicodeString); overload; {$endif HASVARUSTRING} {$ifdef UNICODE} /// convert a Delphi 2009+ Unicode string into a WinAnsi (code page 1252) string function UnicodeStringToWinAnsi(const S: string): WinAnsiString; inline; /// convert our UTF-8 encoded buffer into a Delphi 2009+ Unicode string // - this function is the same as direct assignment, since RawUTF8=AnsiString(CP_UTF8), // but is faster, since use no Win32 API call function UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer): UnicodeString; overload; inline; ................................................................................ // - this function is faster than default RTL, since use no Win32 API call function WinAnsiToUnicodeString(WinAnsi: PAnsiChar; WinAnsiLen: integer): UnicodeString; overload; /// convert a Win-Ansi string into a Delphi 2009+ Unicode string // - this function is faster than default RTL, since use no Win32 API call function WinAnsiToUnicodeString(const WinAnsi: WinAnsiString): UnicodeString; inline; overload; {$endif UNICODE} /// convert any generic VCL Text into an UTF-8 encoded String // - it's prefered to use TLanguageFile.StringToUTF8() method in mORMoti18n, // which will handle full i18n of your application // - it will work as is with Delphi 2009+ (direct unicode conversion) // - under older version of Delphi (no unicode), it will use the // current RTL codepage, as with WideString conversion (but without slow ................................................................................ {$ifdef UNICODE}inline;{$endif} /// convert any UTF-8 encoded buffer into a generic VCL Text procedure UTF8DecodeToString(P: PUTF8Char; L: integer; var result: string); overload; /// convert any UTF-8 encoded String into a generic WideString Text function UTF8ToWideString(const Text: RawUTF8): WideString; overload; {$ifdef UNICODE}inline;{$endif} /// convert any UTF-8 encoded String into a generic WideString Text procedure UTF8ToWideString(const Text: RawUTF8; var result: WideString); overload; {$ifdef UNICODE}inline;{$endif} /// convert any UTF-8 encoded String into a generic WideString Text procedure UTF8ToWideString(Text: PUTF8Char; Len: integer; var result: WideString); overload; /// convert any UTF-8 encoded String into a generic SynUnicode Text function UTF8ToSynUnicode(const Text: RawUTF8): SynUnicode; overload; ................................................................................ // - just a wrapper around PosEx(substr,str,1) function Pos(const substr, str: RawUTF8): Integer; overload; inline; {$endif UNICODE} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - only useful if our Enhanced Runtime (or LVCL) library is not installed function Int64ToUtf8(Value: Int64): RawByteString; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - only useful if our Enhanced Runtime (or LVCL) library is not installed function Int32ToUtf8(Value: integer): RawByteString; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - result as var parameter saves a local assignment and a try..finally procedure Int32ToUTF8(Value: integer; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} ................................................................................ /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - result as var parameter saves a local assignment and a try..finally procedure Int64ToUtf8(Value: Int64; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} /// use our fast RawUTF8 version of IntToStr() function ToUTF8(Value: PtrInt): RawByteString; overload; {$ifdef HASINLINE}inline;{$endif} {$ifndef CPU64} /// use our fast RawUTF8 version of IntToStr() function ToUTF8(Value: Int64): RawByteString; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} {$endif} /// optimized conversion of a cardinal into RawUTF8 function UInt32ToUtf8(Value: cardinal): RawByteString; overload; {$ifdef HASINLINE}inline;{$endif} /// optimized conversion of a cardinal into RawUTF8 procedure UInt32ToUtf8(Value: cardinal; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} /// faster version than default SysUtils.IntToStr implementation ................................................................................ // - warning: will encode generic string fields as AnsiString (one byte per char) // prior to Delphi 2009, and as UnicodeString (two bytes per char) since Delphi // 2009: if you want to use this function between UNICODE and NOT UNICODE // versions of Delphi, you should use some explicit types like RawUTF8, // WinAnsiString, SynUnicode or even RawUnicode/WideString function RecordSave(const Rec; Dest: PAnsiChar; TypeInfo: pointer): PAnsiChar; overload; /// save a record content into a Base-64 encoded RawByteString content // - will use RecordSave() format, with a left-sided binary CRC function RecordSaveBase64(const Rec; TypeInfo: pointer; UriCompatible: boolean=false): RawByteString; /// compute the number of bytes needed to save a record content // using the RecordSave() function // - will return 0 in case of an invalid (not handled) record type (e.g. if // it contains an unknown variant) function RecordSaveLength(const Rec; TypeInfo: pointer): integer; ................................................................................ function HexDisplayToBin(Hex: PAnsiChar; Bin: PByte; BinBytes: integer): boolean; /// fast conversion from hexa chars into a cardinal function HexDisplayToCardinal(Hex: PAnsiChar; out aValue: cardinal): boolean; {$ifndef FPC}{$ifdef HASINLINE}inline;{$endif}{$endif} // inline gives an error under release conditions with FPC /// fast conversion from binary data into Base64 encoded text function BinToBase64(const s: RawByteString): RawByteString; overload; /// fast conversion from binary data into Base64 encoded text function BinToBase64(Bin: PAnsiChar; BinBytes: integer): RawByteString; overload; /// fast conversion from binary data into Base64-like URI-compatible encoded text // - will trim any right-sided '=' unsignificant characters, and replace // '+' or '/' by '_' or '-' function BinToBase64URI(Bin: PAnsiChar; BinBytes: integer): RawByteString; /// conversion from any Base64 encoded value into URI-compatible encoded text // - will trim any right-sided '=' unsignificant characters, and replace // '+' or '/' by '_' or '-' procedure Base64ToURI(var base64: RawByteString); /// conversion from URI-compatible encoded text into its original Base64 value // - will add any right-sided '=' unsignificant characters, and replace back // '_' or '-' by '+' or '/' procedure Base64FromURI(var base64: RawByteString); /// fast conversion from binary data into Base64 encoded text // with JSON_BASE64_MAGIC prefix (UTF-8 encoded \uFFF0 special code) function BinToBase64WithMagic(const s: RawByteString): RawByteString; overload; /// fast conversion from binary data into Base64 encoded text // with JSON_BASE64_MAGIC prefix (UTF-8 encoded \uFFF0 special code) function BinToBase64WithMagic(Data: pointer; DataLen: integer): RawByteString; overload; /// fast conversion from Base64 encoded text into binary data function Base64ToBin(const s: RawByteString): RawByteString; overload; {$ifdef HASINLINE}inline;{$endif} /// fast conversion from Base64 encoded text into binary data function Base64ToBin(sp: PAnsiChar; len: PtrInt): RawByteString; overload; ................................................................................ result := '' else begin if SourceChars<SizeOf(tmpA)shr fAnsiCharShift then SetString(result,tmpA,Utf8BufferToAnsi(tmpA,Source,SourceChars)-tmpA) else begin Getmem(A,(SourceChars+1) shl fAnsiCharShift); SetString(result,A,Utf8BufferToAnsi(A,Source,SourceChars)-A); FreeMem(A); end; {$ifdef UNICODE} SetCodePage(result,fCodePage,false); {$endif} end; end; function TSynAnsiConvert.UTF8ToAnsi(const UTF8: RawUTF8): RawByteString; begin ................................................................................ result := '' else begin if SourceChars<SizeOf(tmpA)shr fAnsiCharShift then SetString(result,tmpA,UnicodeBufferToAnsi(tmpA,Source,SourceChars)-tmpA) else begin Getmem(A,(SourceChars+1) shl fAnsiCharShift); SetString(result,A,UnicodeBufferToAnsi(A,Source,SourceChars)-A); FreeMem(A); end; {$ifdef UNICODE} SetCodePage(result,fCodePage,false); {$endif} end; end; function TSynAnsiConvert.RawUnicodeToAnsi(const Source: RawUnicode): RawByteString; begin ................................................................................ if SourceChars<sizeof(tmpU) shr 1 then result := UnicodeBufferToAnsi(tmpU, (PtrUInt(From.AnsiBufferToUnicode(tmpU,Source,SourceChars))-PtrUInt(@tmpU))shr 1) else begin GetMem(U,SourceChars*2+2); result := UnicodeBufferToAnsi(U,From.AnsiBufferToUnicode(U,Source,SourceChars)-U); FreeMem(U); end; end; { TSynAnsiFixedWidth } function TSynAnsiFixedWidth.AnsiBufferToUnicode(Dest: PWideChar; Source: PAnsiChar; SourceChars: Cardinal): PWideChar; ................................................................................ begin SetString(Result,Source,SourceChars); end; function TSynAnsiUTF8.UTF8ToAnsi(const UTF8: RawUTF8): RawByteString; begin result := UTF8; end; function TSynAnsiUTF8.AnsiToUTF8(const AnsiText: RawByteString): RawUTF8; begin result := AnsiText; end; function TSynAnsiUTF8.AnsiBufferToRawUTF8(Source: PAnsiChar; SourceChars: Cardinal): RawUTF8; begin SetString(Result,Source,SourceChars); end; ................................................................................ Dest[j] := AnsiChar((ucs4 and $3f)+$80); ucs4 := ucs4 shr 6; end; Dest^ := AnsiChar(ToByte(ucs4) or UTF8_FIRSTBYTE[result]); end; procedure AnyAnsiToUTF8(const s: RawByteString; var result: RawUTF8); {$ifdef UNICODE}var CodePage: Cardinal;{$endif} begin if s='' then result := '' else begin {$ifdef UNICODE} CodePage := StringCodePage(s); if (CodePage=CP_UTF8) or (CodePage=CP_RAWBYTESTRING) then result := s else result := TSynAnsiConvert.Engine(CodePage). {$else} result := CurrentAnsiConvert. {$endif} ................................................................................ if L<sizeof(short)div 3 then SetString(result,short,UTF8ToWideChar(short,P,L) shr 1) else begin GetMem(U,L*3+2); // maximum posible unicode size (if all <#128) SetString(result,U,UTF8ToWideChar(U,P,L) shr 1); FreeMem(U); end; end; {$endif} {$ifdef UNICODE} function UnicodeStringToWinAnsi(const S: string): WinAnsiString; begin result := RawUnicodeToWinAnsi(pointer(S),length(S)); end; function UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer): UnicodeString; begin ................................................................................ end; function WinAnsiToUnicodeString(const WinAnsi: WinAnsiString): UnicodeString; begin result := WinAnsiToUnicodeString(pointer(WinAnsi),length(WinAnsi)); end; {$endif} {$ifdef UNICODE} function Ansi7ToString(const Text: RawByteString): string; var i: integer; begin SetString(result,nil,length(Text)); for i := 0 to length(Text)-1 do ................................................................................ end; vtAnsiString: begin // expect UTF-8 content Res.Text := pointer(V.VAnsiString); Res.Len := length(RawUTF8(V.VAnsiString)); result := Res.Len; exit; end; {$ifdef UNICODE} vtUnicodeString: RawUnicodeToUtf8(V.VPWideChar,length(UnicodeString(V.VUnicodeString)),tmpStr); {$endif} vtWideString: RawUnicodeToUtf8(V.VPWideChar,length(WideString(V.VWideString)),tmpStr); vtPChar: begin Res.Text := V.VPointer; ................................................................................ isString := not (V.VType in [vtBoolean,vtInteger,vtInt64,vtCurrency,vtExtended]); with V do case V.VType of vtString: SetRawUTF8(result,@VString^[1],ord(VString^[0])); vtAnsiString: result := RawUTF8(VAnsiString); // expect UTF-8 content {$ifdef UNICODE} vtUnicodeString: result := UnicodeStringToUtf8(string(VUnicodeString)); {$endif} vtWideString: RawUnicodeToUtf8(VWideString,length(WideString(VWideString)),result); vtPChar: SetRawUTF8(result,VPChar,StrLen(VPChar)); vtChar: SetRawUTF8(result,PAnsiChar(@VChar),1); ................................................................................ Curr64ToStr(VInt64,result); varDate: begin wasString := true; DateTimeToIso8601TextVar(VDate,'T',result); end; varString: begin wasString := true; {$ifdef UNICODE} AnyAnsiToUTF8(RawByteString(VString),result); {$else} result := RawUTF8(VString); {$endif} end; {$ifdef HASVARUSTRING} varUString: begin ................................................................................ else if SetVariantUnRefSimpleValue(V,tmp) then VariantToUTF8(Variant(tmp),result,wasString) else if VType=varVariant or varByRef then // complex varByRef VariantToUTF8(PVariant(VPointer)^,result,wasString) else if VType=varByRef or varString then begin wasString := true; {$ifdef UNICODE} AnyAnsiToUTF8(PRawByteString(VString)^,result); {$else} result := PRawUTF8(VString)^; {$endif} end else if VType=varByRef or varOleStr then begin wasString := true; ................................................................................ {$ifndef PUREPASCAL} { these functions are implemented in asm } {$ifndef LVCL} { don't define these functions twice } {$ifndef FPC} { these asm function use some low-level system.pas calls } {$define OWNI2S} function Int32ToUTF8(Value : integer): RawByteString; // 3x faster than SysUtils.IntToStr // from IntToStr32_JOH_IA32_6_a, adapted for Delphi 2009+ asm // eax=Value, edx=@result push ebx push edi push esi mov ebx,eax {Value} sar ebx,31 {0 for +ve Value or -1 for -ve Value} ................................................................................ mov [ecx],ax {Save Final 2 Digits} ret @@LastDigit: or al,'0' {Ascii Adjustment} mov [ecx],al {Save Final Digit} end; function Int64ToUTF8(Value: Int64): RawByteString; // from IntToStr64_JOH_IA32_6_b, adapted for Delphi 2009+ asm push ebx mov ecx, [ebp+8] {Low Integer of Value} mov edx, [ebp+12] {High Integer of Value} xor ebp, ebp {Clear Sign Flag (EBP Already Pushed)} mov ebx, ecx {Low Integer of Value} ................................................................................ SetLength(result,Gen-pointer(result)); inc(maxParam); end; {$ifndef OWNI2S} function Int32ToUTF8(Value : integer): RawByteString; // faster than SysUtils.IntToStr var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; function Int64ToUtf8(Value: Int64): RawByteString; // faster than SysUtils.IntToStr var tmp: array[0..23] of AnsiChar; P: PAnsiChar; begin P := StrInt64(@tmp[23],Value); SetString(result,P,@tmp[23]-P); end; {$endif} {$ifndef CPU64} // already implemented by ToUTF8(Value: PtrInt) below function ToUTF8(Value: Int64): RawByteString; var tmp: array[0..23] of AnsiChar; P: PAnsiChar; begin P := StrInt64(@tmp[23],Value); SetString(result,P,@tmp[23]-P); end; {$endif} function ToUTF8(Value: PtrInt): RawByteString; var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; function UInt32ToUTF8(Value: Cardinal): RawByteString; var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrUInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; ................................................................................ end; function BinToBase64Length(len: PtrUInt): PtrUInt; begin result := ((len+2)div 3)*4; end; function BinToBase64(const s: RawByteString): RawByteString; var len: integer; begin result := ''; len := length(s); if len=0 then exit; SetLength(result,BinToBase64Length(len)); Base64Encode(pointer(result),pointer(s),len); end; function BinToBase64(Bin: PAnsiChar; BinBytes: integer): RawByteString; begin result := ''; if BinBytes=0 then exit; SetLength(result,BinToBase64Length(BinBytes)); Base64Encode(pointer(result),Bin,BinBytes); end; procedure Base64ToURI(var base64: RawByteString); var P: PUTF8Char; begin {$ifdef FPC} UniqueString(base64); // @base64[1] won't call UniqueString() under FPC :( {$endif} P := @base64[1]; if P<>nil then ................................................................................ break; end; end; inc(P); until false; end; procedure Base64FromURI(var base64: RawByteString); var P: PUTF8Char; len,i,append: integer; begin len := length(base64); if len=0 then exit; {$ifdef FPC} ................................................................................ if append<>4 then begin // add unsignificant trailing '=' characters SetLength(base64,len+append); for i := len+1 to len+append do base64[i] := '='; end; end; function BinToBase64URI(Bin: PAnsiChar; BinBytes: integer): RawByteString; begin result := BinToBase64(Bin,BinBytes); Base64ToURI(result); end; function BinToBase64WithMagic(const s: RawByteString): RawByteString; var len: integer; begin result:=''; len := length(s); if len=0 then exit; SetLength(result,((len+2) div 3)*4+3); PInteger(pointer(result))^ := JSON_BASE64_MAGIC; Base64Encode(PAnsiChar(pointer(result))+3,pointer(s),len); end; function BinToBase64WithMagic(Data: pointer; DataLen: integer): RawByteString; overload; begin result:=''; if DataLen<=0 then exit; SetLength(result,((DataLen+2) div 3)*4+3); PInteger(pointer(result))^ := JSON_BASE64_MAGIC; Base64Encode(PAnsiChar(pointer(result))+3,Data,DataLen); ................................................................................ while S[L]<=' ' do dec(L); result := Copy(S,I,L-I+1); end; end; {$endif} {$IFDEF PUREPASCAL} {$IFDEF UNICODE} function Trim(const S: RawUTF8): RawUTF8; var I,L: Integer; begin L := Length(S); I := 1; while (I<=L) and (S[I]<=' ') do inc(I); if I>L then ................................................................................ j := PosEx(endboundary,Body,i); // try last boundary if j=0 then exit; end; part.Content := copy(Body,i,j-i-2); // -2 to ignore latest #13#10 if (part.ContentType='') or (PosEx('-8',part.ContentType)>0) then begin part.ContentType := TEXT_CONTENT_TYPE; {$ifdef UNICODE} SetCodePage(part.Content,CP_UTF8,false); // ensure raw field value is UTF-8 {$endif} end else if IdemPropNameU(part.Encoding,'base64') then part.Content := Base64ToBin(part.Content); // note: "quoted-printable" not yet handled here SetLength(MultiPart,length(MultiPart)+1); ................................................................................ procedure FromVarString(var Source: PByte; var Value: RawByteString; CodePage: integer); var Len: PtrUInt; begin Len := FromVarUInt32(Source); if Len=0 then exit; SetString(Value,PAnsiChar(Source),Len); {$ifdef UNICODE} SetCodePage(Value,CodePage,false); {$endif} inc(Source,Len); end; function FromVarBlob(Data: PByte): TValueResult; begin ................................................................................ if PAnsiString(A)^=PAnsiString(B)^ then Diff := sizeof(pointer) else exit; tkWString: if PWideString(A)^=PWideString(B)^ then Diff := sizeof(pointer) else exit; {$ifdef UNICODE} tkUString: if PUnicodeString(A)^=PUnicodeString(B)^ then Diff := sizeof(pointer) else exit; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: if RecordEquals(A^,B^,Field^.TypeInfo{$ifndef FPC}^{$endif}) then ................................................................................ inc(result,DynArray.SaveToLength-sizeof(PtrUInt)); end; tkLString,tkWString{$ifdef FPC},tkLStringOld{$endif}: // length stored within WideString is in bytes if P^=0 then dec(result,sizeof(PtrUInt)-1) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(P^-STRRECSIZE))^.length)-sizeof(PtrUInt)); {$ifdef UNICODE} tkUString: if P^=0 then dec(result,sizeof(PtrUInt)-1) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(P^-STRRECSIZE))^.length*2)-sizeof(PtrUInt)); {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: begin Len := RecordSaveLength(P^,Field.TypeInfo{$ifndef FPC}^{$endif}); ................................................................................ Kind := Field.TypeInfo^.Kind; case Kind of tkDynArray: begin DynArray.Init(Field.TypeInfo{$ifndef FPC}^{$endif},R^); Dest := DynArray.SaveTo(Dest); Diff := sizeof(PtrUInt); // size of tkDynArray in record end; tkLString, tkWString {$ifdef UNICODE}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin if PPtrUInt(R)^=0 then LenBytes := 0 else LenBytes := PStrRec(Pointer(PPtrUInt(R)^-STRRECSIZE))^.length; {$ifdef UNICODE} // WideString has length in bytes, UnicodeString in WideChars if Kind=tkUString then LenBytes := LenBytes*2; {$endif} Dest := pointer(ToVarUInt32(LenBytes,pointer(Dest))); if LenBytes>0 then begin MoveFast(pointer(PPtrUInt(R)^)^,Dest^,LenBytes); inc(Dest,LenBytes); ................................................................................ begin Len := RecordSaveLength(Rec,TypeInfo); SetString(result,nil,Len); if Len<>0 then RecordSave(Rec,pointer(result),TypeInfo); end; function RecordSaveBase64(const Rec; TypeInfo: pointer; UriCompatible: boolean): RawByteString; var len: integer; data: RawByteString; dat: PAnsiChar; begin result := ''; len := RecordSaveLength(Rec,TypeInfo); if len=0 then ................................................................................ if UriCompatible then Base64ToURI(result); end; function RecordLoadBase64(Source: PAnsiChar; Len: integer; var Rec; TypeInfo: pointer; UriCompatible: boolean): boolean; var data: RawByteString; begin result := false; if Len<=6 then exit; if UriCompatible then begin SetString(data,Source,Len); Base64FromURI(data); data := Base64ToBin(data); end else data := Base64ToBin(Source,Len); Len := length(data); if Len<=4 then exit; Source := PAnsiChar(pointer(data))+4; if crc32c(0,Source,Len-4)=PCardinal(data)^ then ................................................................................ Kind := Field.TypeInfo^.Kind; case Kind of tkDynArray: begin DynArray.Init(Field.TypeInfo{$ifndef FPC}^{$endif},R^); Source := DynArray.LoadFrom(Source); Diff := sizeof(PtrUInt); // size of tkDynArray in record end; tkLString, tkWString {$ifdef UNICODE}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin LenBytes := FromVarUInt32(PByte(Source)); case Kind of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(PRawByteString(R)^,Source,LenBytes); {$ifdef UNICODE} { Delphi 2009+: set Code page for this AnsiString } if LenBytes<>0 then SetCodePage(PRawByteString(R)^,PWord(PtrUInt(Field.TypeInfo^)+ Field.TypeInfo^^.NameLen+2)^,false); {$endif} end; tkWString: SetString(PWideString(R)^,PWideChar(Source),LenBytes shr 1); {$ifdef UNICODE} tkUString: SetString(PString(R)^,PWideChar(Source),LenBytes shr 1); {$endif} end; inc(Source,LenBytes); Diff := sizeof(PtrUInt); // size of tkLString+tkWString+tkUString in record end; ................................................................................ if VType and VTYPE_STATIC<>0 then VarClear(Value); VType := varString; VAny := nil; // avoid GPF below when assigning a string variable to VAny if Txt='' then exit; end; {$ifdef UNICODE} if (PByte(Txt)<>nil) and (PWord(PByte(Txt)-12)^=CP_RAWBYTESTRING) then PWord(PByte(Txt)-12)^ := CP_UTF8; // force explicit UTF-8 {$endif} RawByteString(VAny) := Txt; end; end; function RawUTF8ToVariant(const Txt: RawUTF8): variant; begin RawUTF8ToVariant(Txt,result); end; ................................................................................ if Value.VType and VTYPE_STATIC<>0 then VarClear(variant(Value)); Value.VType := ExpectedValueType; Value.VAny := nil; // avoid GPF below if Txt<>'' then case ExpectedValueType of varString: begin {$ifdef UNICODE} if PWord(PByte(Txt)-12)^=CP_RAWBYTESTRING then PWord(PByte(Txt)-12)^ := CP_UTF8; // force explicit UTF-8 {$endif} RawByteString(Value.VAny) := Txt; end; varOleStr: UTF8ToWideString(Txt,WideString(Value.VAny)); {$ifdef HASVARUSTRING} varUString: UTF8DecodeToUnicodeString(pointer(Txt),length(Txt),UnicodeString(Value.VAny)); {$endif} ................................................................................ vtVariant: result := V.VVariant^; vtAnsiString: begin VType := varString; VAny := nil; RawByteString(VAny) := RawByteString(V.VAnsiString); end; vtString, {$ifdef UNICODE}vtUnicodeString,{$endif} vtPChar, vtChar, vtWideChar, vtWideString, vtClass: begin VType := varString; VAny := nil; // avoid GPF on next line VarRecToUTF8(V,RawUTF8(VAny)); end; vtObject: // class instance will be serialized as a TDocVariant ObjectToVariant(V.VObject,result); ................................................................................ [PShortString(@PTypeInfo(ArrayType).NameLen)^]) else begin // binary types: store as once n := n*integer(ElemSize); MoveFast(P^,Dest^,n); inc(Dest,n); end else case PTypeKind(ElemType)^ of tkLString, tkWString {$ifdef UNICODE}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin for i := 1 to n do begin if PPtrUInt(P)^=0 then LenBytes := 0 else begin LenBytes := PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length; {$ifdef UNICODE} // WideString length in bytes, UnicodeString in WideChars if PTypeKind(ElemType)^=tkUString then LenBytes := LenBytes*2; {$endif} end; Dest := pointer(ToVarUInt32(LenBytes,pointer(Dest))); if LenBytes>0 then begin MoveFast(pointer(PPtrUInt(P)^)^,Dest^,LenBytes); ................................................................................ tkLString, tkWString{$ifdef FPC}, tkLStringOld{$endif}: for i := 1 to n do begin if PPtrUInt(P)^=0 then inc(result) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length)); inc(P,sizeof(PtrUInt)); end; {$ifdef UNICODE} tkUString: // WideString has length in bytes, UnicodeString in WideChars for i := 1 to n do begin if PPtrUInt(P)^=0 then inc(result) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length*2)); inc(P,sizeof(PtrUInt)); end; ................................................................................ [PShortString(@PTypeInfo(ArrayType).NameLen)^]) else begin // binary type was stored as once n := n*integer(ElemSize); MoveFast(Source^,P^,n); inc(Source,n); end else case PTypeKind(ElemType)^ of tkLString, tkWString {$ifdef UNICODE}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: for i := 1 to n do begin LenBytes := FromVarUInt32(PByte(Source)); case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(PRawByteString(P)^,Source,LenBytes); {$ifdef UNICODE} { Delphi 2009+: set Code page for this AnsiString } if LenBytes<>0 then SetCodePage(PRawByteString(P)^,PWord(PtrUInt(ElemType)+ PTypeInfo(ElemType)^.NameLen+2)^,false); {$endif} end; tkWString: SetString(PWideString(P)^,PWideChar(Source),LenBytes shr 1); {$ifdef UNICODE} tkUString: SetString(PString(P)^,PWideChar(Source),LenBytes shr 1); {$endif} end; inc(Source,LenBytes); inc(P,sizeof(PtrUInt)); end; ................................................................................ case PTypeKind(ElemType)^ of tkRecord{$ifdef FPC},tkObject{$endif}: result := RecordEquals(A,B,ElemType); tkLString{$ifdef FPC},tkLStringOld{$endif}: result := AnsiString(A)=AnsiString(B); tkWString: result := WideString(A)=WideString(B); {$ifdef UNICODE} tkUString: result := UnicodeString(A)=UnicodeString(B); {$endif} tkInterface: result := pointer(A)=pointer(B); {$ifndef NOVARIANTS} tkVariant: ................................................................................ for i := 0 to n-1 do if AnsiString(A1^[i])<>AnsiString(A2^[i]) then exit; tkWString: for i := 0 to n-1 do if WideString(A1^[i])<>WideString(A2^[i]) then exit; {$ifdef UNICODE} tkUString: for i := 0 to n-1 do if UnicodeString(A1^[i])<>UnicodeString(A2^[i]) then exit; {$endif} tkInterface: if not CompareMem(P1,P2,SizeOf(pointer)*cardinal(n)) then ................................................................................ case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: for result := 0 to max do if AnsiString(PPtrIntArray(P)^[result])=AnsiString(Elem) then exit; tkWString: for result := 0 to max do if WideString(PPtrIntArray(P)^[result])=WideString(Elem) then exit; {$ifdef UNICODE} tkUString: for result := 0 to max do if UnicodeString(PPtrIntArray(P)^[result])=UnicodeString(Elem) then exit; {$endif} {$ifndef NOVARIANTS} tkVariant: for result := 0 to max do ................................................................................ case PTypeKind(ElemType)^ of // release reference counted tkLString{$ifdef FPC},tkLStringOld{$endif}: RawByteString(Elem) := ''; tkWString: WideString(Elem) := ''; tkInterface: IUnknown(Elem) := nil; {$ifdef UNICODE} tkUString: UnicodeString(Elem) := ''; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: RecordClear(Elem,ElemType); tkDynArray: _DynArrayClear(pointer(Elem),ElemType); ................................................................................ WideString(B) := WideString(A); exit; end; tkInterface: begin IUnknown(B) := IUnknown(A); exit; end; {$ifdef UNICODE} tkUString: begin UnicodeString(B) := UnicodeString(A); exit; end; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: begin RecordCopy(B,A,ElemType); ................................................................................ if Source=nil then exit; // avoid GPF if ElemType=nil then MoveFast(Source^,Elem,ElemSize) else case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(RawByteString(Elem),Source+4,PInteger(Source)^); {$ifdef UNICODE} { Delphi 2009+: set Code page for this AnsiString } if PPtrUInt(@Elem)^<>0 then SetCodePage(RawByteString(Elem),PWord(PtrUInt(ElemType)+ PTypeInfo(ElemType)^.NameLen+2)^,false); {$endif} end; tkWString: // WideString internal length is in bytes SetString(WideString(Elem),PWideChar(Source+4),PInteger(Source)^ shr 1); {$ifdef UNICODE} tkUString: SetString(UnicodeString(Elem),PWideChar(Source+4),PInteger(Source)^); {$endif} {$ifndef NOVARIANTS} tkVariant: VariantLoad(variant(Elem),Source,@JSON_OPTIONS[true]); {$endif} ................................................................................ begin if (ElemType<>nil) and (length(ElemLoaded)=integer(ElemSize)) then case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: PRawByteString(pointer(ElemLoaded))^ := ''; tkWString: PWideString(pointer(ElemLoaded))^ := ''; {$ifdef UNICODE} tkUString: PUnicodeString(pointer(ElemLoaded))^ := ''; {$endif} {$ifndef NOVARIANTS} tkVariant: VarClear(PVariant(pointer(ElemLoaded))^); {$endif} ................................................................................ tkLString, tkWString, tkLStringOld: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else begin LenBytes := PStrRec(Pointer(PPtrInt(@Elem)^-STRRECSIZE))^.length; SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)),LenBytes+sizeof(integer)); PInteger(result)^ := LenBytes; end; {$ifdef UNICODE} tkUString: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else begin LenBytes := PStrRec(Pointer(PPtrInt(@Elem)^-STRRECSIZE))^.length; SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)),LenBytes*2+sizeof(integer)); PInteger(result)^ := LenBytes; end; end; {$endif} {$else FPC} tkLString, tkWString: // WideString internal length is in bytes if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)), PInteger(PPtrInt(@Elem)^-sizeof(integer))^+sizeof(integer)); {$ifdef UNICODE} tkUString: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)), PInteger(PPtrInt(@Elem)^-sizeof(integer))^*2+sizeof(integer)); {$endif} {$endif FPC} ................................................................................ {$ifdef UNICODE} function HashUnicodeString(const Elem; Hasher: THasher): cardinal; begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(PtrUInt(Elem)), {$ifdef FPC}PStrRec(Pointer(PtrUInt(Elem)-STRRECSIZE))^.length {$else}PInteger(PtrUInt(Elem)-sizeof(integer))^{$endif}*2); end; function HashUnicodeStringI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else ................................................................................ {$endif UNICODE} function HashSynUnicode(const Elem; Hasher: THasher): cardinal; begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(PtrUInt(Elem)), {$ifdef FPC}PStrRec(Pointer(PtrUInt(Elem)-STRRECSIZE))^.length {$else}PInteger(PtrUInt(Elem)-sizeof(integer))^{$endif} {$ifdef UNICODE}*sizeof(WideChar){$endif}); // WideString internal size is in bytes, UnicodeString is in WideChars end; function HashSynUnicodeI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else ................................................................................ result := Hasher(0,tmp,UpperCopy255W(tmp,SynUnicode(Elem))-tmp); end; function HashWideString(const Elem; Hasher: THasher): cardinal; begin // WideString internal size is in bytes, not WideChar if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(PtrUInt(Elem)), {$ifdef FPC}PStrRec(Pointer(PtrUInt(Elem)-STRRECSIZE))^.length {$else}PInteger(PtrUInt(Elem)-sizeof(integer))^{$endif}); end; function HashWideStringI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,tmp,UpperCopy255W(tmp,pointer(Elem),Length(WideString(Elem)))-tmp); end; function HashPtrUInt(const Elem; Hasher: THasher): cardinal; begin {$ifdef CPU64} result := Hasher(0,@Elem,sizeof(PtrUInt)); {$else} result := (PtrUInt(Elem) shr 4)+1; // naive but optimal for TDynArrayHashed {$endif} end; function HashPointer(const Elem; Hasher: THasher): cardinal; begin result := Hasher(0,@Elem,sizeof(pointer)); end; ................................................................................ varDate: AddDateTime(@VDate,'T','"'); varCurrency: AddCurr64(VInt64); varBoolean: Add(VBoolean); varVariant: AddVariant(PVariant(VPointer)^,Escape,ForcedSerializeAsNonExtendedJson); varString: begin if Escape=twJSONEscape then Add('"'); {$ifdef UNICODE} AddAnyAnsiString(RawByteString(VString),Escape); {$else} // VString is expected to be a RawUTF8 Add(VAny,length(RawUTF8(VAny)),Escape); {$endif} if Escape=twJSONEscape then Add('"'); end; ................................................................................ end; else if VType=varVariant or varByRef then AddVariant(PVariant(VPointer)^,Escape,ForcedSerializeAsNonExtendedJson) else if VType=varByRef or varString then begin if Escape=twJSONEscape then Add('"'); {$ifdef UNICODE} AddAnyAnsiString(PRawByteString(VAny)^,Escape); {$else} // VString is expected to be a RawUTF8 Add(PPointer(VAny)^,length(PRawUTF8(VAny)^),Escape); {$endif} if Escape=twJSONEscape then Add('"'); end else ................................................................................ if L=0 then exit; if PInteger(s)^ and $ffffff=JSON_BASE64_MAGIC then begin AddNoJSONEscape(pointer(s),L); // identified as a BLOB content exit; end; if CodePage<0 then {$ifdef UNICODE} CodePage := StringCodePage(s); {$else} CodePage := 0; // TSynAnsiConvert.Engine(0)=CurrentAnsiConvert {$endif} AddAnyAnsiBuffer(pointer(s),L,Escape,CodePage); end; ................................................................................ end; procedure TTextWriter.AddJSONEscape(const V: TVarRec); begin with V do case VType of vtPointer: AddShort('null'); vtString, vtAnsiString,{$ifdef UNICODE}vtUnicodeString,{$endif} vtPChar, vtChar, vtWideChar, vtWideString, vtClass: begin Add('"'); case VType of vtString: AddJSONEscape(@VString^[1],ord(VString^[0])); vtAnsiString: AddJSONEscape(pointer(RawUTF8(VAnsiString))); {$ifdef UNICODE} vtUnicodeString: AddJSONEscapeW( pointer(string(VUnicodeString)),length(string(VUnicodeString))); {$endif} vtPChar: AddJSONEscape(VPChar); vtChar: AddJSONEscape(@VChar,1); vtWideChar: AddJSONEscapeW(@VWideChar,1); vtWideString: AddJSONEscapeW(VWideString); vtClass: AddClassName(VClass); end; Add('"'); ................................................................................ AddW(VWideString,length(WideString(VWideString)),Escape); vtInt64: Add(VInt64^); {$ifndef NOVARIANTS} vtVariant: AddVariant(VVariant^,Escape); {$endif} {$ifdef UNICODE} vtUnicodeString: if VUnicodeString<>nil then // convert to UTF-8 AddW(VUnicodeString,length(UnicodeString(VUnicodeString)),Escape); {$endif} end; end; {$ifndef NOVARIANTS} ................................................................................ begin FlushFinal; Len := fTotalFileSize-fInitialStreamPosition; if Len=0 then result := '' else if fStream.InheritsFrom(TRawByteStringStream) then with TRawByteStringStream(fStream) do if fInitialStreamPosition=0 then result := DataString else SetRawUTF8(result,PAnsiChar(pointer(DataString))+fInitialStreamPosition,Len) else if fStream.InheritsFrom(TCustomMemoryStream) then with TCustomMemoryStream(fStream) do SetRawUTF8(result,PAnsiChar(Memory)+fInitialStreamPosition,Len) else begin FastNewRawUTF8(result,Len); fStream.Seek(fInitialStreamPosition,soBeginning); fStream.Read(pointer(result)^,Len); |
| | | | | | | | | > | | | | | > > > > > | < < < < | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > | | < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | < < | < < < < | < < | | | | | | | | | | | | > > > | > |
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 1001 1002 1003 1004 .... 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 .... 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 .... 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 .... 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 .... 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 .... 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 .... 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 ..... 14862 14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873 14874 14875 14876 ..... 14905 14906 14907 14908 14909 14910 14911 14912 14913 14914 14915 14916 14917 14918 14919 ..... 14938 14939 14940 14941 14942 14943 14944 14945 14946 14947 14948 14949 14950 14951 14952 14953 14954 ..... 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 ..... 15491 15492 15493 15494 15495 15496 15497 15498 15499 15500 15501 15502 15503 15504 15505 15506 15507 15508 15509 ..... 16172 16173 16174 16175 16176 16177 16178 16179 16180 16181 16182 16183 16184 16185 16186 ..... 16194 16195 16196 16197 16198 16199 16200 16201 16202 16203 16204 16205 16206 16207 16208 ..... 16407 16408 16409 16410 16411 16412 16413 16414 16415 16416 16417 16418 16419 16420 16421 ..... 16506 16507 16508 16509 16510 16511 16512 16513 16514 16515 16516 16517 16518 16519 16520 16521 16522 ..... 17985 17986 17987 17988 17989 17990 17991 17992 17993 17994 17995 17996 17997 17998 17999 ..... 18008 18009 18010 18011 18012 18013 18014 18015 18016 18017 18018 18019 18020 18021 18022 ..... 18319 18320 18321 18322 18323 18324 18325 18326 18327 18328 18329 18330 18331 18332 18333 ..... 18416 18417 18418 18419 18420 18421 18422 18423 18424 18425 18426 18427 18428 18429 18430 ..... 19653 19654 19655 19656 19657 19658 19659 19660 19661 19662 19663 19664 19665 19666 19667 19668 19669 19670 19671 19672 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 19687 19688 19689 19690 19691 19692 19693 19694 19695 19696 19697 19698 19699 19700 19701 19702 19703 ..... 21804 21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 21819 21820 21821 21822 21823 21824 21825 21826 21827 21828 21829 21830 21831 21832 21833 21834 21835 21836 21837 21838 ..... 21846 21847 21848 21849 21850 21851 21852 21853 21854 21855 21856 21857 21858 21859 21860 ..... 21873 21874 21875 21876 21877 21878 21879 21880 21881 21882 21883 21884 21885 21886 21887 21888 21889 21890 21891 21892 21893 21894 21895 21896 21897 21898 21899 21900 21901 21902 21903 21904 21905 ..... 23424 23425 23426 23427 23428 23429 23430 23431 23432 23433 23434 23435 23436 23437 23438 ..... 29164 29165 29166 29167 29168 29169 29170 29171 29172 29173 29174 29175 29176 29177 29178 ..... 30192 30193 30194 30195 30196 30197 30198 30199 30200 30201 30202 30203 30204 30205 30206 ..... 30311 30312 30313 30314 30315 30316 30317 30318 30319 30320 30321 30322 30323 30324 30325 ..... 30393 30394 30395 30396 30397 30398 30399 30400 30401 30402 30403 30404 30405 30406 30407 ..... 30466 30467 30468 30469 30470 30471 30472 30473 30474 30475 30476 30477 30478 30479 30480 30481 30482 30483 30484 30485 ..... 30546 30547 30548 30549 30550 30551 30552 30553 30554 30555 30556 30557 30558 30559 30560 ..... 30567 30568 30569 30570 30571 30572 30573 30574 30575 30576 30577 30578 30579 30580 30581 30582 30583 30584 30585 30586 30587 30588 30589 ..... 30674 30675 30676 30677 30678 30679 30680 30681 30682 30683 30684 30685 30686 30687 30688 30689 30690 30691 30692 30693 30694 30695 30696 30697 30698 30699 30700 30701 30702 30703 ..... 33619 33620 33621 33622 33623 33624 33625 33626 33627 33628 33629 33630 33631 33632 33633 33634 33635 33636 33637 ..... 33642 33643 33644 33645 33646 33647 33648 33649 33650 33651 33652 33653 33654 33655 33656 33657 33658 33659 33660 ..... 33980 33981 33982 33983 33984 33985 33986 33987 33988 33989 33990 33991 33992 33993 33994 ..... 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 ..... 37267 37268 37269 37270 37271 37272 37273 37274 37275 37276 37277 37278 37279 37280 37281 ..... 37930 37931 37932 37933 37934 37935 37936 37937 37938 37939 37940 37941 37942 37943 37944 37945 37946 37947 37948 37949 37950 37951 37952 37953 37954 37955 37956 37957 37958 37959 37960 ..... 38313 38314 38315 38316 38317 38318 38319 38320 38321 38322 38323 38324 38325 38326 38327 ..... 38369 38370 38371 38372 38373 38374 38375 38376 38377 38378 38379 38380 38381 38382 38383 ..... 38446 38447 38448 38449 38450 38451 38452 38453 38454 38455 38456 38457 38458 38459 38460 ..... 38775 38776 38777 38778 38779 38780 38781 38782 38783 38784 38785 38786 38787 38788 38789 ..... 38811 38812 38813 38814 38815 38816 38817 38818 38819 38820 38821 38822 38823 38824 38825 ..... 38860 38861 38862 38863 38864 38865 38866 38867 38868 38869 38870 38871 38872 38873 38874 38875 38876 38877 38878 38879 38880 38881 38882 38883 ..... 38890 38891 38892 38893 38894 38895 38896 38897 38898 38899 38900 38901 38902 38903 38904 ..... 38920 38921 38922 38923 38924 38925 38926 38927 38928 38929 38930 38931 38932 38933 38934 38935 38936 38937 38938 38939 38940 38941 38942 38943 38944 38945 38946 38947 38948 38949 ..... 39226 39227 39228 39229 39230 39231 39232 39233 39234 39235 39236 39237 39238 39239 39240 ..... 39243 39244 39245 39246 39247 39248 39249 39250 39251 39252 39253 39254 39255 39256 39257 ..... 39258 39259 39260 39261 39262 39263 39264 39265 39266 39267 39268 39269 39270 39271 39272 39273 39274 39275 39276 39277 39278 39279 39280 39281 39282 39283 39284 39285 39286 39287 39288 39289 ..... 40907 40908 40909 40910 40911 40912 40913 40914 40915 40916 40917 40918 40919 40920 40921 ..... 40928 40929 40930 40931 40932 40933 40934 40935 40936 40937 40938 40939 40940 40941 40942 ..... 41840 41841 41842 41843 41844 41845 41846 41847 41848 41849 41850 41851 41852 41853 41854 ..... 42085 42086 42087 42088 42089 42090 42091 42092 42093 42094 42095 42096 42097 42098 42099 42100 42101 42102 42103 42104 42105 42106 42107 42108 ..... 42146 42147 42148 42149 42150 42151 42152 42153 42154 42155 42156 42157 42158 42159 42160 ..... 42550 42551 42552 42553 42554 42555 42556 42557 42558 42559 42560 42561 42562 42563 42564 42565 42566 42567 42568 42569 |
/// a pointer to a variant array PVariantArray = ^TVariantArray; /// a dynamic array of variant values TVariantDynArray = array of variant; {$endif} /// RawUnicode is an Unicode String stored in an AnsiString // - 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 is not able to make valid implicit conversion on CP_UTF16 {$ifdef HASCODEPAGE} RawUnicode = type AnsiString(CP_UTF16); // Codepage for an UnicodeString {$else} RawUnicode = type AnsiString; {$endif} /// RawUTF8 is an UTF-8 String stored in an AnsiString // - use this type instead of System.UTF8String, which behavior changed // between Delphi 2009 compiler and previous versions: our implementation // is consistent and compatible with all versions of Delphi compiler // - mimic Delphi 2009 UTF8String, without the charset conversion overhead // - all conversion to/from AnsiString or RawUnicode must be explicit {$ifdef HASCODEPAGE} RawUTF8 = type AnsiString(CP_UTF8); // Codepage for an UTF8 string {$else} RawUTF8 = type AnsiString; {$endif} /// 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 RawUTF8 or RawUnicode must be explicit {$ifdef HASCODEPAGE} WinAnsiString = type AnsiString(CODEPAGE_US); // WinAnsi Codepage {$else} WinAnsiString = type AnsiString; {$endif} {$ifdef HASCODEPAGE} {$ifdef FPC} // missing declaration PRawByteString = ^RawByteString; {$endif} {$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} /// RawJSON will indicate that this variable content would stay in raw JSON // - i.e. won't be serialized into values // - could be any JSON content: number, string, object or array // - e.g. interface-based service will use it for efficient and AJAX-ready // transmission of TSQLTableJSON result RawJSON = type RawUTF8; ................................................................................ function UTF8DecodeToUnicodeString(const S: RawUTF8): UnicodeString; overload; inline; /// convert our UTF-8 encoded buffer into a Delphi 2009+ Unicode string // - this function is the same as direct assignment, since RawUTF8=AnsiString(CP_UTF8), // but is faster, since use no Win32 API call procedure UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer; var result: UnicodeString); overload; /// convert a Delphi 2009+ Unicode string into a WinAnsi (code page 1252) string function UnicodeStringToWinAnsi(const S: string): WinAnsiString; inline; /// convert our UTF-8 encoded buffer into a Delphi 2009+ Unicode string // - this function is the same as direct assignment, since RawUTF8=AnsiString(CP_UTF8), // but is faster, since use no Win32 API call function UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer): UnicodeString; overload; inline; ................................................................................ // - this function is faster than default RTL, since use no Win32 API call function WinAnsiToUnicodeString(WinAnsi: PAnsiChar; WinAnsiLen: integer): UnicodeString; overload; /// convert a Win-Ansi string into a Delphi 2009+ Unicode string // - this function is faster than default RTL, since use no Win32 API call function WinAnsiToUnicodeString(const WinAnsi: WinAnsiString): UnicodeString; inline; overload; {$endif HASVARUSTRING} /// convert any generic VCL Text into an UTF-8 encoded String // - it's prefered to use TLanguageFile.StringToUTF8() method in mORMoti18n, // which will handle full i18n of your application // - it will work as is with Delphi 2009+ (direct unicode conversion) // - under older version of Delphi (no unicode), it will use the // current RTL codepage, as with WideString conversion (but without slow ................................................................................ {$ifdef UNICODE}inline;{$endif} /// convert any UTF-8 encoded buffer into a generic VCL Text procedure UTF8DecodeToString(P: PUTF8Char; L: integer; var result: string); overload; /// convert any UTF-8 encoded String into a generic WideString Text function UTF8ToWideString(const Text: RawUTF8): WideString; overload; {$ifdef HASINLINE}inline;{$endif} /// convert any UTF-8 encoded String into a generic WideString Text procedure UTF8ToWideString(const Text: RawUTF8; var result: WideString); overload; {$ifdef HASINLINE}inline;{$endif} /// convert any UTF-8 encoded String into a generic WideString Text procedure UTF8ToWideString(Text: PUTF8Char; Len: integer; var result: WideString); overload; /// convert any UTF-8 encoded String into a generic SynUnicode Text function UTF8ToSynUnicode(const Text: RawUTF8): SynUnicode; overload; ................................................................................ // - just a wrapper around PosEx(substr,str,1) function Pos(const substr, str: RawUTF8): Integer; overload; inline; {$endif UNICODE} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - only useful if our Enhanced Runtime (or LVCL) library is not installed function Int64ToUtf8(Value: Int64): RawUTF8; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - only useful if our Enhanced Runtime (or LVCL) library is not installed function Int32ToUtf8(Value: integer): RawUTF8; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - result as var parameter saves a local assignment and a try..finally procedure Int32ToUTF8(Value: integer; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} ................................................................................ /// use our fast RawUTF8 version of IntToStr() // - without any slow UnicodeString=String->AnsiString conversion for Delphi 2009 // - result as var parameter saves a local assignment and a try..finally procedure Int64ToUtf8(Value: Int64; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} /// use our fast RawUTF8 version of IntToStr() function ToUTF8(Value: PtrInt): RawUTF8; overload; {$ifdef HASINLINE}inline;{$endif} {$ifndef CPU64} /// use our fast RawUTF8 version of IntToStr() function ToUTF8(Value: Int64): RawUTF8; overload; {$ifdef PUREPASCAL}{$ifdef HASINLINE}inline;{$endif}{$endif} {$endif} /// optimized conversion of a cardinal into RawUTF8 function UInt32ToUtf8(Value: cardinal): RawUTF8; overload; {$ifdef HASINLINE}inline;{$endif} /// optimized conversion of a cardinal into RawUTF8 procedure UInt32ToUtf8(Value: cardinal; var result: RawUTF8); overload; {$ifdef HASINLINE}inline;{$endif} /// faster version than default SysUtils.IntToStr implementation ................................................................................ // - warning: will encode generic string fields as AnsiString (one byte per char) // prior to Delphi 2009, and as UnicodeString (two bytes per char) since Delphi // 2009: if you want to use this function between UNICODE and NOT UNICODE // versions of Delphi, you should use some explicit types like RawUTF8, // WinAnsiString, SynUnicode or even RawUnicode/WideString function RecordSave(const Rec; Dest: PAnsiChar; TypeInfo: pointer): PAnsiChar; overload; /// save a record content into a Base-64 encoded UTF-8 text content // - will use RecordSave() format, with a left-sided binary CRC function RecordSaveBase64(const Rec; TypeInfo: pointer; UriCompatible: boolean=false): RawUTF8; /// compute the number of bytes needed to save a record content // using the RecordSave() function // - will return 0 in case of an invalid (not handled) record type (e.g. if // it contains an unknown variant) function RecordSaveLength(const Rec; TypeInfo: pointer): integer; ................................................................................ function HexDisplayToBin(Hex: PAnsiChar; Bin: PByte; BinBytes: integer): boolean; /// fast conversion from hexa chars into a cardinal function HexDisplayToCardinal(Hex: PAnsiChar; out aValue: cardinal): boolean; {$ifndef FPC}{$ifdef HASINLINE}inline;{$endif}{$endif} // inline gives an error under release conditions with FPC /// fast conversion from binary data into Base64 encoded UTF-8 text function BinToBase64(const s: RawByteString): RawUTF8; overload; /// fast conversion from binary data into Base64 encoded UTF-8 text function BinToBase64(Bin: PAnsiChar; BinBytes: integer): RawUTF8; overload; /// fast conversion from binary data into Base64-like URI-compatible encoded text // - will trim any right-sided '=' unsignificant characters, and replace // '+' or '/' by '_' or '-' function BinToBase64URI(Bin: PAnsiChar; BinBytes: integer): RawUTF8; /// conversion from any Base64 encoded value into URI-compatible encoded text // - will trim any right-sided '=' unsignificant characters, and replace // '+' or '/' by '_' or '-' procedure Base64ToURI(var base64: RawUTF8); /// conversion from URI-compatible encoded text into its original Base64 value // - will add any right-sided '=' unsignificant characters, and replace back // '_' or '-' by '+' or '/' procedure Base64FromURI(var base64: RawUTF8); /// fast conversion from binary data into Base64 encoded UTF-8 text // with JSON_BASE64_MAGIC prefix (UTF-8 encoded \uFFF0 special code) function BinToBase64WithMagic(const s: RawByteString): RawUTF8; overload; /// fast conversion from binary data into Base64 encoded UTF-8 text // with JSON_BASE64_MAGIC prefix (UTF-8 encoded \uFFF0 special code) function BinToBase64WithMagic(Data: pointer; DataLen: integer): RawUTF8; overload; /// fast conversion from Base64 encoded text into binary data function Base64ToBin(const s: RawByteString): RawByteString; overload; {$ifdef HASINLINE}inline;{$endif} /// fast conversion from Base64 encoded text into binary data function Base64ToBin(sp: PAnsiChar; len: PtrInt): RawByteString; overload; ................................................................................ result := '' else begin if SourceChars<SizeOf(tmpA)shr fAnsiCharShift then SetString(result,tmpA,Utf8BufferToAnsi(tmpA,Source,SourceChars)-tmpA) else begin Getmem(A,(SourceChars+1) shl fAnsiCharShift); SetString(result,A,Utf8BufferToAnsi(A,Source,SourceChars)-A); FreeMem(A); end; {$ifdef HASCODEPAGE} SetCodePage(result,fCodePage,false); {$endif} end; end; function TSynAnsiConvert.UTF8ToAnsi(const UTF8: RawUTF8): RawByteString; begin ................................................................................ result := '' else begin if SourceChars<SizeOf(tmpA)shr fAnsiCharShift then SetString(result,tmpA,UnicodeBufferToAnsi(tmpA,Source,SourceChars)-tmpA) else begin Getmem(A,(SourceChars+1) shl fAnsiCharShift); SetString(result,A,UnicodeBufferToAnsi(A,Source,SourceChars)-A); FreeMem(A); end; {$ifdef HASCODEPAGE} SetCodePage(result,fCodePage,false); {$endif} end; end; function TSynAnsiConvert.RawUnicodeToAnsi(const Source: RawUnicode): RawByteString; begin ................................................................................ if SourceChars<sizeof(tmpU) shr 1 then result := UnicodeBufferToAnsi(tmpU, (PtrUInt(From.AnsiBufferToUnicode(tmpU,Source,SourceChars))-PtrUInt(@tmpU))shr 1) else begin GetMem(U,SourceChars*2+2); result := UnicodeBufferToAnsi(U,From.AnsiBufferToUnicode(U,Source,SourceChars)-U); FreeMem(U); end; {$ifdef HASCODEPAGE} SetCodePage(result,fCodePage,false); {$endif} end; { TSynAnsiFixedWidth } function TSynAnsiFixedWidth.AnsiBufferToUnicode(Dest: PWideChar; Source: PAnsiChar; SourceChars: Cardinal): PWideChar; ................................................................................ begin SetString(Result,Source,SourceChars); end; function TSynAnsiUTF8.UTF8ToAnsi(const UTF8: RawUTF8): RawByteString; begin result := UTF8; {$ifdef HASCODEPAGE} SetCodePage(result,CP_UTF8,false); {$endif} end; function TSynAnsiUTF8.AnsiToUTF8(const AnsiText: RawByteString): RawUTF8; begin result := AnsiText; {$ifdef HASCODEPAGE} SetCodePage(RawByteString(result),CP_UTF8,false); {$endif} end; function TSynAnsiUTF8.AnsiBufferToRawUTF8(Source: PAnsiChar; SourceChars: Cardinal): RawUTF8; begin SetString(Result,Source,SourceChars); end; ................................................................................ Dest[j] := AnsiChar((ucs4 and $3f)+$80); ucs4 := ucs4 shr 6; end; Dest^ := AnsiChar(ToByte(ucs4) or UTF8_FIRSTBYTE[result]); end; procedure AnyAnsiToUTF8(const s: RawByteString; var result: RawUTF8); {$ifdef HASCODEPAGE}var CodePage: Cardinal;{$endif} begin if s='' then result := '' else begin {$ifdef HASCODEPAGE} CodePage := StringCodePage(s); if (CodePage=CP_UTF8) or (CodePage=CP_RAWBYTESTRING) then result := s else result := TSynAnsiConvert.Engine(CodePage). {$else} result := CurrentAnsiConvert. {$endif} ................................................................................ if L<sizeof(short)div 3 then SetString(result,short,UTF8ToWideChar(short,P,L) shr 1) else begin GetMem(U,L*3+2); // maximum posible unicode size (if all <#128) SetString(result,U,UTF8ToWideChar(U,P,L) shr 1); FreeMem(U); end; end; function UnicodeStringToWinAnsi(const S: string): WinAnsiString; begin result := RawUnicodeToWinAnsi(pointer(S),length(S)); end; function UTF8DecodeToUnicodeString(P: PUTF8Char; L: integer): UnicodeString; begin ................................................................................ end; function WinAnsiToUnicodeString(const WinAnsi: WinAnsiString): UnicodeString; begin result := WinAnsiToUnicodeString(pointer(WinAnsi),length(WinAnsi)); end; {$endif HASVARUSTRING} {$ifdef UNICODE} function Ansi7ToString(const Text: RawByteString): string; var i: integer; begin SetString(result,nil,length(Text)); for i := 0 to length(Text)-1 do ................................................................................ end; vtAnsiString: begin // expect UTF-8 content Res.Text := pointer(V.VAnsiString); Res.Len := length(RawUTF8(V.VAnsiString)); result := Res.Len; exit; end; {$ifdef HASVARUSTRING} vtUnicodeString: RawUnicodeToUtf8(V.VPWideChar,length(UnicodeString(V.VUnicodeString)),tmpStr); {$endif} vtWideString: RawUnicodeToUtf8(V.VPWideChar,length(WideString(V.VWideString)),tmpStr); vtPChar: begin Res.Text := V.VPointer; ................................................................................ isString := not (V.VType in [vtBoolean,vtInteger,vtInt64,vtCurrency,vtExtended]); with V do case V.VType of vtString: SetRawUTF8(result,@VString^[1],ord(VString^[0])); vtAnsiString: result := RawUTF8(VAnsiString); // expect UTF-8 content {$ifdef HASVARUSTRING} vtUnicodeString: result := UnicodeStringToUtf8(UnicodeString(VUnicodeString)); {$endif} vtWideString: RawUnicodeToUtf8(VWideString,length(WideString(VWideString)),result); vtPChar: SetRawUTF8(result,VPChar,StrLen(VPChar)); vtChar: SetRawUTF8(result,PAnsiChar(@VChar),1); ................................................................................ Curr64ToStr(VInt64,result); varDate: begin wasString := true; DateTimeToIso8601TextVar(VDate,'T',result); end; varString: begin wasString := true; {$ifdef HASCODEPAGE} AnyAnsiToUTF8(RawByteString(VString),result); {$else} result := RawUTF8(VString); {$endif} end; {$ifdef HASVARUSTRING} varUString: begin ................................................................................ else if SetVariantUnRefSimpleValue(V,tmp) then VariantToUTF8(Variant(tmp),result,wasString) else if VType=varVariant or varByRef then // complex varByRef VariantToUTF8(PVariant(VPointer)^,result,wasString) else if VType=varByRef or varString then begin wasString := true; {$ifdef HASCODEPAGE} AnyAnsiToUTF8(PRawByteString(VString)^,result); {$else} result := PRawUTF8(VString)^; {$endif} end else if VType=varByRef or varOleStr then begin wasString := true; ................................................................................ {$ifndef PUREPASCAL} { these functions are implemented in asm } {$ifndef LVCL} { don't define these functions twice } {$ifndef FPC} { these asm function use some low-level system.pas calls } {$define OWNI2S} function Int32ToUTF8(Value : integer): RawUtf8; // 3x faster than SysUtils.IntToStr // from IntToStr32_JOH_IA32_6_a, adapted for Delphi 2009+ asm // eax=Value, edx=@result push ebx push edi push esi mov ebx,eax {Value} sar ebx,31 {0 for +ve Value or -1 for -ve Value} ................................................................................ mov [ecx],ax {Save Final 2 Digits} ret @@LastDigit: or al,'0' {Ascii Adjustment} mov [ecx],al {Save Final Digit} end; function Int64ToUTF8(Value: Int64): RawUtf8; // from IntToStr64_JOH_IA32_6_b, adapted for Delphi 2009+ asm push ebx mov ecx, [ebp+8] {Low Integer of Value} mov edx, [ebp+12] {High Integer of Value} xor ebp, ebp {Clear Sign Flag (EBP Already Pushed)} mov ebx, ecx {Low Integer of Value} ................................................................................ SetLength(result,Gen-pointer(result)); inc(maxParam); end; {$ifndef OWNI2S} function Int32ToUTF8(Value : integer): RawUTF8; // faster than SysUtils.IntToStr var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; function Int64ToUtf8(Value: Int64): RawUTF8; // faster than SysUtils.IntToStr var tmp: array[0..23] of AnsiChar; P: PAnsiChar; begin P := StrInt64(@tmp[23],Value); SetString(result,P,@tmp[23]-P); end; {$endif} {$ifndef CPU64} // already implemented by ToUTF8(Value: PtrInt) below function ToUTF8(Value: Int64): RawUTF8; var tmp: array[0..23] of AnsiChar; P: PAnsiChar; begin P := StrInt64(@tmp[23],Value); SetString(result,P,@tmp[23]-P); end; {$endif} function ToUTF8(Value: PtrInt): RawUTF8; var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; function UInt32ToUTF8(Value: Cardinal): RawUTF8; var tmp: array[0..15] of AnsiChar; P: PAnsiChar; begin P := StrUInt32(@tmp[15],Value); SetString(result,P,@tmp[15]-P); end; ................................................................................ end; function BinToBase64Length(len: PtrUInt): PtrUInt; begin result := ((len+2)div 3)*4; end; function BinToBase64(const s: RawByteString): RawUTF8; var len: integer; begin result := ''; len := length(s); if len=0 then exit; SetLength(result,BinToBase64Length(len)); Base64Encode(pointer(result),pointer(s),len); end; function BinToBase64(Bin: PAnsiChar; BinBytes: integer): RawUTF8; begin result := ''; if BinBytes=0 then exit; SetLength(result,BinToBase64Length(BinBytes)); Base64Encode(pointer(result),Bin,BinBytes); end; procedure Base64ToURI(var base64: RawUTF8); var P: PUTF8Char; begin {$ifdef FPC} UniqueString(base64); // @base64[1] won't call UniqueString() under FPC :( {$endif} P := @base64[1]; if P<>nil then ................................................................................ break; end; end; inc(P); until false; end; procedure Base64FromURI(var base64: RawUTF8); var P: PUTF8Char; len,i,append: integer; begin len := length(base64); if len=0 then exit; {$ifdef FPC} ................................................................................ if append<>4 then begin // add unsignificant trailing '=' characters SetLength(base64,len+append); for i := len+1 to len+append do base64[i] := '='; end; end; function BinToBase64URI(Bin: PAnsiChar; BinBytes: integer): RawUTF8; begin result := BinToBase64(Bin,BinBytes); Base64ToURI(result); end; function BinToBase64WithMagic(const s: RawByteString): RawUTF8; var len: integer; begin result:=''; len := length(s); if len=0 then exit; SetLength(result,((len+2) div 3)*4+3); PInteger(pointer(result))^ := JSON_BASE64_MAGIC; Base64Encode(PAnsiChar(pointer(result))+3,pointer(s),len); end; function BinToBase64WithMagic(Data: pointer; DataLen: integer): RawUTF8; overload; begin result:=''; if DataLen<=0 then exit; SetLength(result,((DataLen+2) div 3)*4+3); PInteger(pointer(result))^ := JSON_BASE64_MAGIC; Base64Encode(PAnsiChar(pointer(result))+3,Data,DataLen); ................................................................................ while S[L]<=' ' do dec(L); result := Copy(S,I,L-I+1); end; end; {$endif} {$IFDEF PUREPASCAL} {$IFDEF HASCODEPAGE} function Trim(const S: RawUTF8): RawUTF8; var I,L: Integer; begin L := Length(S); I := 1; while (I<=L) and (S[I]<=' ') do inc(I); if I>L then ................................................................................ j := PosEx(endboundary,Body,i); // try last boundary if j=0 then exit; end; part.Content := copy(Body,i,j-i-2); // -2 to ignore latest #13#10 if (part.ContentType='') or (PosEx('-8',part.ContentType)>0) then begin part.ContentType := TEXT_CONTENT_TYPE; {$ifdef HASCODEPAGE} SetCodePage(part.Content,CP_UTF8,false); // ensure raw field value is UTF-8 {$endif} end else if IdemPropNameU(part.Encoding,'base64') then part.Content := Base64ToBin(part.Content); // note: "quoted-printable" not yet handled here SetLength(MultiPart,length(MultiPart)+1); ................................................................................ procedure FromVarString(var Source: PByte; var Value: RawByteString; CodePage: integer); var Len: PtrUInt; begin Len := FromVarUInt32(Source); if Len=0 then exit; SetString(Value,PAnsiChar(Source),Len); {$ifdef HASCODEPAGE} SetCodePage(Value,CodePage,false); {$endif} inc(Source,Len); end; function FromVarBlob(Data: PByte): TValueResult; begin ................................................................................ if PAnsiString(A)^=PAnsiString(B)^ then Diff := sizeof(pointer) else exit; tkWString: if PWideString(A)^=PWideString(B)^ then Diff := sizeof(pointer) else exit; {$ifdef HASVARUSTRING} tkUString: if PUnicodeString(A)^=PUnicodeString(B)^ then Diff := sizeof(pointer) else exit; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: if RecordEquals(A^,B^,Field^.TypeInfo{$ifndef FPC}^{$endif}) then ................................................................................ inc(result,DynArray.SaveToLength-sizeof(PtrUInt)); end; tkLString,tkWString{$ifdef FPC},tkLStringOld{$endif}: // length stored within WideString is in bytes if P^=0 then dec(result,sizeof(PtrUInt)-1) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(P^-STRRECSIZE))^.length)-sizeof(PtrUInt)); {$ifdef HASVARUSTRING} tkUString: if P^=0 then dec(result,sizeof(PtrUInt)-1) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(P^-STRRECSIZE))^.length*2)-sizeof(PtrUInt)); {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: begin Len := RecordSaveLength(P^,Field.TypeInfo{$ifndef FPC}^{$endif}); ................................................................................ Kind := Field.TypeInfo^.Kind; case Kind of tkDynArray: begin DynArray.Init(Field.TypeInfo{$ifndef FPC}^{$endif},R^); Dest := DynArray.SaveTo(Dest); Diff := sizeof(PtrUInt); // size of tkDynArray in record end; tkLString, tkWString {$ifdef HASVARUSTRING}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin if PPtrUInt(R)^=0 then LenBytes := 0 else LenBytes := PStrRec(Pointer(PPtrUInt(R)^-STRRECSIZE))^.length; {$ifdef HASVARUSTRING} // WideString has length in bytes, UnicodeString in WideChars if Kind=tkUString then LenBytes := LenBytes*2; {$endif} Dest := pointer(ToVarUInt32(LenBytes,pointer(Dest))); if LenBytes>0 then begin MoveFast(pointer(PPtrUInt(R)^)^,Dest^,LenBytes); inc(Dest,LenBytes); ................................................................................ begin Len := RecordSaveLength(Rec,TypeInfo); SetString(result,nil,Len); if Len<>0 then RecordSave(Rec,pointer(result),TypeInfo); end; function RecordSaveBase64(const Rec; TypeInfo: pointer; UriCompatible: boolean): RawUTF8; var len: integer; data: RawByteString; dat: PAnsiChar; begin result := ''; len := RecordSaveLength(Rec,TypeInfo); if len=0 then ................................................................................ if UriCompatible then Base64ToURI(result); end; function RecordLoadBase64(Source: PAnsiChar; Len: integer; var Rec; TypeInfo: pointer; UriCompatible: boolean): boolean; var data: RawByteString; uri: RawUTF8; begin result := false; if Len<=6 then exit; if UriCompatible then begin SetString(uri,Source,Len); Base64FromURI(uri); data := Base64ToBin(uri); end else data := Base64ToBin(Source,Len); Len := length(data); if Len<=4 then exit; Source := PAnsiChar(pointer(data))+4; if crc32c(0,Source,Len-4)=PCardinal(data)^ then ................................................................................ Kind := Field.TypeInfo^.Kind; case Kind of tkDynArray: begin DynArray.Init(Field.TypeInfo{$ifndef FPC}^{$endif},R^); Source := DynArray.LoadFrom(Source); Diff := sizeof(PtrUInt); // size of tkDynArray in record end; tkLString, tkWString {$ifdef HASVARUSTRING}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin LenBytes := FromVarUInt32(PByte(Source)); case Kind of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(PRawByteString(R)^,Source,LenBytes); {$ifdef HASCODEPAGE} { Delphi 2009+: set Code page for this AnsiString } if LenBytes<>0 then SetCodePage(PRawByteString(R)^,PWord(PtrUInt(Field.TypeInfo{$ifndef FPC}^{$endif})+ Field.TypeInfo{$ifndef FPC}^{$endif}^.NameLen+2)^,false); {$endif} end; tkWString: SetString(PWideString(R)^,PWideChar(Source),LenBytes shr 1); {$ifdef HASVARUSTRING} tkUString: SetString(PString(R)^,PWideChar(Source),LenBytes shr 1); {$endif} end; inc(Source,LenBytes); Diff := sizeof(PtrUInt); // size of tkLString+tkWString+tkUString in record end; ................................................................................ if VType and VTYPE_STATIC<>0 then VarClear(Value); VType := varString; VAny := nil; // avoid GPF below when assigning a string variable to VAny if Txt='' then exit; end; RawByteString(VAny) := Txt; {$ifdef HASCODEPAGE} if (Txt<>'') and (StringCodePage(Txt)=CP_RAWBYTESTRING) then SetCodePage(RawByteString(VAny),CP_UTF8,false); // force explicit UTF-8 {$endif} end; end; function RawUTF8ToVariant(const Txt: RawUTF8): variant; begin RawUTF8ToVariant(Txt,result); end; ................................................................................ if Value.VType and VTYPE_STATIC<>0 then VarClear(variant(Value)); Value.VType := ExpectedValueType; Value.VAny := nil; // avoid GPF below if Txt<>'' then case ExpectedValueType of varString: begin RawByteString(Value.VAny) := Txt; {$ifdef HASCODEPAGE} if (Txt<>'') and (StringCodePage(Txt)=CP_RAWBYTESTRING) then SetCodePage(RawByteString(Value.VAny),CP_UTF8,false); // force explicit UTF-8 {$endif} end; varOleStr: UTF8ToWideString(Txt,WideString(Value.VAny)); {$ifdef HASVARUSTRING} varUString: UTF8DecodeToUnicodeString(pointer(Txt),length(Txt),UnicodeString(Value.VAny)); {$endif} ................................................................................ vtVariant: result := V.VVariant^; vtAnsiString: begin VType := varString; VAny := nil; RawByteString(VAny) := RawByteString(V.VAnsiString); end; vtString, {$ifdef HASVARUSTRING}vtUnicodeString,{$endif} vtPChar, vtChar, vtWideChar, vtWideString, vtClass: begin VType := varString; VAny := nil; // avoid GPF on next line VarRecToUTF8(V,RawUTF8(VAny)); end; vtObject: // class instance will be serialized as a TDocVariant ObjectToVariant(V.VObject,result); ................................................................................ [PShortString(@PTypeInfo(ArrayType).NameLen)^]) else begin // binary types: store as once n := n*integer(ElemSize); MoveFast(P^,Dest^,n); inc(Dest,n); end else case PTypeKind(ElemType)^ of tkLString, tkWString {$ifdef HASVARUSTRING}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: begin for i := 1 to n do begin if PPtrUInt(P)^=0 then LenBytes := 0 else begin LenBytes := PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length; {$ifdef HASVARUSTRING} // WideString length in bytes, UnicodeString in WideChars if PTypeKind(ElemType)^=tkUString then LenBytes := LenBytes*2; {$endif} end; Dest := pointer(ToVarUInt32(LenBytes,pointer(Dest))); if LenBytes>0 then begin MoveFast(pointer(PPtrUInt(P)^)^,Dest^,LenBytes); ................................................................................ tkLString, tkWString{$ifdef FPC}, tkLStringOld{$endif}: for i := 1 to n do begin if PPtrUInt(P)^=0 then inc(result) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length)); inc(P,sizeof(PtrUInt)); end; {$ifdef HASVARUSTRING} tkUString: // WideString has length in bytes, UnicodeString in WideChars for i := 1 to n do begin if PPtrUInt(P)^=0 then inc(result) else inc(result,ToVarUInt32LengthWithData(PStrRec(Pointer(PPtrUInt(P)^-STRRECSIZE))^.length*2)); inc(P,sizeof(PtrUInt)); end; ................................................................................ [PShortString(@PTypeInfo(ArrayType).NameLen)^]) else begin // binary type was stored as once n := n*integer(ElemSize); MoveFast(Source^,P^,n); inc(Source,n); end else case PTypeKind(ElemType)^ of tkLString, tkWString {$ifdef HASVARUSTRING}, tkUString{$endif} {$ifdef FPC}, tkLStringOld{$endif}: for i := 1 to n do begin LenBytes := FromVarUInt32(PByte(Source)); case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(PRawByteString(P)^,Source,LenBytes); {$ifdef HASCODEPAGE} { Delphi 2009+: set Code page for this AnsiString } if LenBytes<>0 then SetCodePage(PRawByteString(P)^,PWord(PtrUInt(ElemType)+ PTypeInfo(ElemType)^.NameLen+2)^,false); {$endif} end; tkWString: SetString(PWideString(P)^,PWideChar(Source),LenBytes shr 1); {$ifdef HASVARUSTRING} tkUString: SetString(PString(P)^,PWideChar(Source),LenBytes shr 1); {$endif} end; inc(Source,LenBytes); inc(P,sizeof(PtrUInt)); end; ................................................................................ case PTypeKind(ElemType)^ of tkRecord{$ifdef FPC},tkObject{$endif}: result := RecordEquals(A,B,ElemType); tkLString{$ifdef FPC},tkLStringOld{$endif}: result := AnsiString(A)=AnsiString(B); tkWString: result := WideString(A)=WideString(B); {$ifdef HASVARUSTRING} tkUString: result := UnicodeString(A)=UnicodeString(B); {$endif} tkInterface: result := pointer(A)=pointer(B); {$ifndef NOVARIANTS} tkVariant: ................................................................................ for i := 0 to n-1 do if AnsiString(A1^[i])<>AnsiString(A2^[i]) then exit; tkWString: for i := 0 to n-1 do if WideString(A1^[i])<>WideString(A2^[i]) then exit; {$ifdef HASVARUSTRING} tkUString: for i := 0 to n-1 do if UnicodeString(A1^[i])<>UnicodeString(A2^[i]) then exit; {$endif} tkInterface: if not CompareMem(P1,P2,SizeOf(pointer)*cardinal(n)) then ................................................................................ case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: for result := 0 to max do if AnsiString(PPtrIntArray(P)^[result])=AnsiString(Elem) then exit; tkWString: for result := 0 to max do if WideString(PPtrIntArray(P)^[result])=WideString(Elem) then exit; {$ifdef HASVARUSTRING} tkUString: for result := 0 to max do if UnicodeString(PPtrIntArray(P)^[result])=UnicodeString(Elem) then exit; {$endif} {$ifndef NOVARIANTS} tkVariant: for result := 0 to max do ................................................................................ case PTypeKind(ElemType)^ of // release reference counted tkLString{$ifdef FPC},tkLStringOld{$endif}: RawByteString(Elem) := ''; tkWString: WideString(Elem) := ''; tkInterface: IUnknown(Elem) := nil; {$ifdef HASVARUSTRING} tkUString: UnicodeString(Elem) := ''; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: RecordClear(Elem,ElemType); tkDynArray: _DynArrayClear(pointer(Elem),ElemType); ................................................................................ WideString(B) := WideString(A); exit; end; tkInterface: begin IUnknown(B) := IUnknown(A); exit; end; {$ifdef HASVARUSTRING} tkUString: begin UnicodeString(B) := UnicodeString(A); exit; end; {$endif} tkRecord{$ifdef FPC},tkObject{$endif}: begin RecordCopy(B,A,ElemType); ................................................................................ if Source=nil then exit; // avoid GPF if ElemType=nil then MoveFast(Source^,Elem,ElemSize) else case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: begin SetString(RawByteString(Elem),Source+4,PInteger(Source)^); {$ifdef HASCODEPAGE} { Delphi 2009+: set Code page for this AnsiString } if PPtrUInt(@Elem)^<>0 then SetCodePage(RawByteString(Elem),PWord(PtrUInt(ElemType)+ PTypeInfo(ElemType)^.NameLen+2)^,false); {$endif} end; tkWString: // WideString internal length is in bytes SetString(WideString(Elem),PWideChar(Source+4),PInteger(Source)^ shr 1); {$ifdef HASVARUSTRING} tkUString: SetString(UnicodeString(Elem),PWideChar(Source+4),PInteger(Source)^); {$endif} {$ifndef NOVARIANTS} tkVariant: VariantLoad(variant(Elem),Source,@JSON_OPTIONS[true]); {$endif} ................................................................................ begin if (ElemType<>nil) and (length(ElemLoaded)=integer(ElemSize)) then case PTypeKind(ElemType)^ of tkLString{$ifdef FPC},tkLStringOld{$endif}: PRawByteString(pointer(ElemLoaded))^ := ''; tkWString: PWideString(pointer(ElemLoaded))^ := ''; {$ifdef HASVARUSTRING} tkUString: PUnicodeString(pointer(ElemLoaded))^ := ''; {$endif} {$ifndef NOVARIANTS} tkVariant: VarClear(PVariant(pointer(ElemLoaded))^); {$endif} ................................................................................ tkLString, tkWString, tkLStringOld: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else begin LenBytes := PStrRec(Pointer(PPtrInt(@Elem)^-STRRECSIZE))^.length; SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)),LenBytes+sizeof(integer)); PInteger(result)^ := LenBytes; end; {$ifdef HASVARUSTRING} tkUString: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else begin LenBytes := PStrRec(Pointer(PPtrInt(@Elem)^-STRRECSIZE))^.length; SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)),LenBytes*2+sizeof(integer)); PInteger(result)^ := LenBytes; end; {$endif} {$else FPC} tkLString, tkWString: // WideString internal length is in bytes if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)), PInteger(PPtrInt(@Elem)^-sizeof(integer))^+sizeof(integer)); {$ifdef HASVARUSTRING} tkUString: if PPtrInt(@Elem)^=0 then SetString(result,PAnsiChar(@Elem),4) else SetString(result,PAnsiChar(PPtrInt(@Elem)^-sizeof(integer)), PInteger(PPtrInt(@Elem)^-sizeof(integer))^*2+sizeof(integer)); {$endif} {$endif FPC} ................................................................................ {$ifdef UNICODE} function HashUnicodeString(const Elem; Hasher: THasher): cardinal; begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(Elem),length(UnicodeString(Elem))*2); end; function HashUnicodeStringI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else ................................................................................ {$endif UNICODE} function HashSynUnicode(const Elem; Hasher: THasher): cardinal; begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(Elem),length(SynUnicode(Elem))*2); end; function HashSynUnicodeI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else ................................................................................ result := Hasher(0,tmp,UpperCopy255W(tmp,SynUnicode(Elem))-tmp); end; function HashWideString(const Elem; Hasher: THasher): cardinal; begin // WideString internal size is in bytes, not WideChar if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,Pointer(Elem),Length(WideString(Elem))*2); end; function HashWideStringI(const Elem; Hasher: THasher): cardinal; var tmp: array[byte] of AnsiChar; // avoid slow heap allocation begin if PtrUInt(Elem)=0 then result := HASH_ONVOIDCOLISION else result := Hasher(0,tmp,UpperCopy255W(tmp,pointer(Elem),Length(WideString(Elem)))-tmp); end; function HashPtrUInt(const Elem; Hasher: THasher): cardinal; begin {$ifdef CPU64} result := Hasher(0,@Elem,sizeof(PtrUInt)); {$else} result := (PtrUInt(Elem) shr 4)+1; // naive but optimal for TDynArrayHashed {$endif} end; function HashPointer(const Elem; Hasher: THasher): cardinal; begin result := Hasher(0,@Elem,sizeof(pointer)); end; ................................................................................ varDate: AddDateTime(@VDate,'T','"'); varCurrency: AddCurr64(VInt64); varBoolean: Add(VBoolean); varVariant: AddVariant(PVariant(VPointer)^,Escape,ForcedSerializeAsNonExtendedJson); varString: begin if Escape=twJSONEscape then Add('"'); {$ifdef HASCODEPAGE} AddAnyAnsiString(RawByteString(VString),Escape); {$else} // VString is expected to be a RawUTF8 Add(VAny,length(RawUTF8(VAny)),Escape); {$endif} if Escape=twJSONEscape then Add('"'); end; ................................................................................ end; else if VType=varVariant or varByRef then AddVariant(PVariant(VPointer)^,Escape,ForcedSerializeAsNonExtendedJson) else if VType=varByRef or varString then begin if Escape=twJSONEscape then Add('"'); {$ifdef HASCODEPAGE} AddAnyAnsiString(PRawByteString(VAny)^,Escape); {$else} // VString is expected to be a RawUTF8 Add(PPointer(VAny)^,length(PRawUTF8(VAny)^),Escape); {$endif} if Escape=twJSONEscape then Add('"'); end else ................................................................................ if L=0 then exit; if PInteger(s)^ and $ffffff=JSON_BASE64_MAGIC then begin AddNoJSONEscape(pointer(s),L); // identified as a BLOB content exit; end; if CodePage<0 then {$ifdef HASCODEPAGE} CodePage := StringCodePage(s); {$else} CodePage := 0; // TSynAnsiConvert.Engine(0)=CurrentAnsiConvert {$endif} AddAnyAnsiBuffer(pointer(s),L,Escape,CodePage); end; ................................................................................ end; procedure TTextWriter.AddJSONEscape(const V: TVarRec); begin with V do case VType of vtPointer: AddShort('null'); vtString, vtAnsiString,{$ifdef HASVARUSTRING}vtUnicodeString,{$endif} vtPChar, vtChar, vtWideChar, vtWideString, vtClass: begin Add('"'); case VType of vtString: AddJSONEscape(@VString^[1],ord(VString^[0])); vtAnsiString: AddJSONEscape(pointer(RawUTF8(VAnsiString))); {$ifdef HASVARUSTRING} vtUnicodeString: AddJSONEscapeW( pointer(UnicodeString(VUnicodeString)),length(UnicodeString(VUnicodeString))); {$endif} vtPChar: AddJSONEscape(VPChar); vtChar: AddJSONEscape(@VChar,1); vtWideChar: AddJSONEscapeW(@VWideChar,1); vtWideString: AddJSONEscapeW(VWideString); vtClass: AddClassName(VClass); end; Add('"'); ................................................................................ AddW(VWideString,length(WideString(VWideString)),Escape); vtInt64: Add(VInt64^); {$ifndef NOVARIANTS} vtVariant: AddVariant(VVariant^,Escape); {$endif} {$ifdef HASVARUSTRING} vtUnicodeString: if VUnicodeString<>nil then // convert to UTF-8 AddW(VUnicodeString,length(UnicodeString(VUnicodeString)),Escape); {$endif} end; end; {$ifndef NOVARIANTS} ................................................................................ begin FlushFinal; Len := fTotalFileSize-fInitialStreamPosition; if Len=0 then result := '' else if fStream.InheritsFrom(TRawByteStringStream) then with TRawByteStringStream(fStream) do if fInitialStreamPosition=0 then begin {$ifdef HASCODEPAGE} // FPC expects this SetCodePage(fDataString,CP_UTF8,false); {$endif} result := fDataString; end else SetRawUTF8(result,PAnsiChar(pointer(DataString))+fInitialStreamPosition,Len) else if fStream.InheritsFrom(TCustomMemoryStream) then with TCustomMemoryStream(fStream) do SetRawUTF8(result,PAnsiChar(Memory)+fInitialStreamPosition,Len) else begin FastNewRawUTF8(result,Len); fStream.Seek(fInitialStreamPosition,soBeginning); fStream.Read(pointer(result)^,Len); |
Changes to SynCrtSock.pas.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 .... 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 .... 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 .... 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 .... 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 .... 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 .... 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 |
/// define the fastest Unicode string type of the compiler SynUnicode = UnicodeString; /// define a raw storage string type, used for data buffer management SockString = type RawByteString; {$else} /// define the fastest Unicode string type of the compiler SynUnicode = WideString; /// define a raw storage string type, used for data buffer management SockString = type AnsiString; {$endif} {$ifndef CONDITIONALEXPRESSIONS} // not defined in Delphi 5 or older PPointer = ^Pointer; TTextLineBreakStyle = (tlbsLF, tlbsCRLF); UTF8String = AnsiString; ................................................................................ result := nil; exit; end; Inc(result); end; end; {$ifdef UNICODE} // rewrite some functions to avoid unattempted ansi<->unicode conversion function Trim(const S: SockString): SockString; {$ifdef PUREPASCAL} var I, L: Integer; begin L := Length(S); I := 1; while (I<=L) and (S[i]<=' ') do Inc(I); if I>L then Result := '' else ................................................................................ function UpperCase(const S: SockString): SockString; procedure Upper(Source, Dest: PAnsiChar; L: cardinal); var Ch: AnsiChar; // this sub-call is shorter and faster than 1 plain proc begin repeat Ch := Source^; if (Ch >= 'a') and (Ch <= 'z') then dec(Ch, 32); Dest^ := Ch; dec(L); inc(Source); inc(Dest); until L=0; end; var L: cardinal; ................................................................................ L := Length(S); if L=0 then exit; SetLength(result, L); Upper(pointer(S),pointer(result),L); end; {$endif} function GetCardinal(P: PAnsiChar): cardinal; overload; var c: cardinal; begin if P=nil then begin result := 0; exit; ................................................................................ constructor TCrtSocket.Bind(const aPort: SockString; aLayer: TCrtSocketLayer=cslTCP); var s,p: SockString; i: integer; begin // on Linux, Accept() blocks even after Shutdown() -> use 0.5 second timeout Create({$ifdef LINUX}500{$else}5000{$endif}); i := pos({$ifdef UNICODE}SockString{$endif}(':'),aPort); if i=0 then begin s := '0.0.0.0'; p := aPort; end else begin s := Copy(aPort,1,i-1); p := Copy(aPort,i+1,10); end; ................................................................................ for i := 0 to high(Values) do with Values[i] do case VType of vtString: SockSend(@VString^[1],pByte(VString)^); vtAnsiString: SockSend(VAnsiString,length(SockString(VAnsiString))); {$ifdef UNICODE} vtUnicodeString: begin tmp := ShortString(UnicodeString(VUnicodeString)); // convert into ansi SockSend(@tmp[1],length(tmp)); end; {$endif} vtPChar: SockSend(VPChar,StrLen(VPChar)); vtChar: SockSend(@VChar,1); vtWideChar: SockSend(@VWideChar,1); // only ansi part of the character vtInteger: begin ................................................................................ end else Exec('HELO '+Server,'25'); writeln(TCP.SockOut^,'MAIL FROM:<',From,'>'); Expect('250'); ToList := 'To: '; repeat rec := trim(GetNextItem(P)); if rec='' then continue; if pos({$ifdef UNICODE}SockString{$endif}('<'),rec)=0 then rec := '<'+rec+'>'; Exec('RCPT TO:'+rec,'25'); ToList := ToList+rec+', '; until P=nil; Exec('DATA','354'); writeln(TCP.SockOut^,'Subject: ',Subject,#13#10, ToList,#13#10'Content-Type: text/plain; charset=',TextCharSet, |
> > > > | | | | | | | | | |
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 .... 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 .... 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 .... 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 .... 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 .... 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 .... 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 |
/// define the fastest Unicode string type of the compiler SynUnicode = UnicodeString; /// define a raw storage string type, used for data buffer management SockString = type RawByteString; {$else} /// define the fastest Unicode string type of the compiler SynUnicode = WideString; {$ifdef HASCODEPAGE} // FPC expects a CP, e.g. to compare to string constants SockString = type AnsiString(CP_UTF8); {$else} /// define a raw storage string type, used for data buffer management SockString = type AnsiString; {$endif} {$endif} {$ifndef CONDITIONALEXPRESSIONS} // not defined in Delphi 5 or older PPointer = ^Pointer; TTextLineBreakStyle = (tlbsLF, tlbsCRLF); UTF8String = AnsiString; ................................................................................ result := nil; exit; end; Inc(result); end; end; {$ifdef HASCODEPAGE} // rewrite some functions to avoid unattempted ansi<->unicode conversion function Trim(const S: SockString): SockString; {$ifdef FPC_OR_PUREPASCAL} var I, L: Integer; begin L := Length(S); I := 1; while (I<=L) and (S[i]<=' ') do Inc(I); if I>L then Result := '' else ................................................................................ function UpperCase(const S: SockString): SockString; procedure Upper(Source, Dest: PAnsiChar; L: cardinal); var Ch: AnsiChar; // this sub-call is shorter and faster than 1 plain proc begin repeat Ch := Source^; if (Ch>='a') and (Ch<='z') then dec(Ch,32); Dest^ := Ch; dec(L); inc(Source); inc(Dest); until L=0; end; var L: cardinal; ................................................................................ L := Length(S); if L=0 then exit; SetLength(result, L); Upper(pointer(S),pointer(result),L); end; {$endif HASCODEPAGE} function GetCardinal(P: PAnsiChar): cardinal; overload; var c: cardinal; begin if P=nil then begin result := 0; exit; ................................................................................ constructor TCrtSocket.Bind(const aPort: SockString; aLayer: TCrtSocketLayer=cslTCP); var s,p: SockString; i: integer; begin // on Linux, Accept() blocks even after Shutdown() -> use 0.5 second timeout Create({$ifdef LINUX}500{$else}5000{$endif}); i := pos({$ifdef HASCODEPAGE}SockString{$endif}(':'),aPort); if i=0 then begin s := '0.0.0.0'; p := aPort; end else begin s := Copy(aPort,1,i-1); p := Copy(aPort,i+1,10); end; ................................................................................ for i := 0 to high(Values) do with Values[i] do case VType of vtString: SockSend(@VString^[1],pByte(VString)^); vtAnsiString: SockSend(VAnsiString,length(SockString(VAnsiString))); {$ifdef HASVARUSTRING} vtUnicodeString: begin tmp := ShortString(UnicodeString(VUnicodeString)); // convert into ansi SockSend(@tmp[1],length(tmp)); end; {$endif} vtPChar: SockSend(VPChar,StrLen(VPChar)); vtChar: SockSend(@VChar,1); vtWideChar: SockSend(@VWideChar,1); // only ansi part of the character vtInteger: begin ................................................................................ end else Exec('HELO '+Server,'25'); writeln(TCP.SockOut^,'MAIL FROM:<',From,'>'); Expect('250'); ToList := 'To: '; repeat rec := trim(GetNextItem(P)); if rec='' then continue; if pos({$ifdef HASCODEPAGE}SockString{$endif}('<'),rec)=0 then rec := '<'+rec+'>'; Exec('RCPT TO:'+rec,'25'); ToList := ToList+rec+', '; until P=nil; Exec('DATA','354'); writeln(TCP.SockOut^,'Subject: ',Subject,#13#10, ToList,#13#10'Content-Type: text/plain; charset=',TextCharSet, |
Changes to SynDB.pas.
6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 .... 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 .... 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 |
BindTextU(i,'',IO) else begin c := PInteger(VAnsiString)^ and $00ffffff; if c=JSON_BASE64_MAGIC then BindBlob(i,Base64ToBin(PAnsiChar(VAnsiString)+3,length(RawUTF8(VAnsiString))-3)) else if c=JSON_SQLDATE_MAGIC then BindDateTime(i,Iso8601ToDateTimePUTF8Char(PUTF8Char(VAnsiString)+3,length(RawUTF8(VAnsiString))-3)) else // expect UTF-8 content only for AnsiString, i.e. RawUTF8 variables BindTextU(i,RawUTF8(VAnsiString),IO); end; vtPChar: BindTextP(i,PUTF8Char(VPChar),IO); vtChar: BindTextU(i,RawUTF8(VChar),IO); vtWideChar: BindTextU(i,RawUnicodeToUtf8(@VWideChar,1),IO); vtPWideChar: BindTextU(i,RawUnicodeToUtf8(VPWideChar,StrLenW(VPWideChar)),IO); vtWideString: BindTextW(i,WideString(VWideString),IO); {$ifdef UNICODE} vtUnicodeString: BindTextS(i,string(VUnicodeString),IO); {$endif} vtBoolean: Bind(i,integer(VBoolean),IO); vtInteger: Bind(i,VInteger,IO); vtInt64: Bind(i,VInt64^,IO); vtCurrency: BindCurrency(i,VCurrency^,IO); vtExtended: Bind(i,VExtended^,IO); vtPointer: if VPointer=nil then ................................................................................ if DataIsBlob then if (VAny<>nil) and (PInteger(VAny)^ and $00ffffff=JSON_BASE64_MAGIC) then // recognized as Base64 encoded text BindBlob(Param,Base64ToBin(PAnsiChar(VAny)+3,length(RawByteString(VAny))-3)) else // no conversion if was set via TQuery.AsBlob property e.g. BindBlob(Param,RawByteString(VAny),IO) else // direct bind of AnsiString as UTF-8 value {$ifdef UNICODE} BindTextU(Param,AnyAnsiToUTF8(RawByteString(VAny)),IO); {$else} // on older Delphi, we assume AnsiString = RawUTF8 BindTextU(Param,RawUTF8(VAny),IO); {$endif} else if VType=varByRef or varVariant then BindVariant(Param,PVariant(VPointer)^,DataIsBlob,IO) else ................................................................................ dec(L); // avoid return of invalid UTF-8 buffer if L=0 then L := MaxCharCount; SetString(result,PAnsiChar(VAny),L); end else result := RawUTF8(VAny); end; {$ifdef UNICODE} varUString: begin L := length(string(VAny)); if L>MaxCharCount then begin Truncated := true; L := MaxCharCount; end; RawUnicodeToUtf8(VAny,L,result); end; {$endif} |
> > > > > | > > | > | | | |
6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 .... 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 .... 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 |
BindTextU(i,'',IO) else begin c := PInteger(VAnsiString)^ and $00ffffff; if c=JSON_BASE64_MAGIC then BindBlob(i,Base64ToBin(PAnsiChar(VAnsiString)+3,length(RawUTF8(VAnsiString))-3)) else if c=JSON_SQLDATE_MAGIC then BindDateTime(i,Iso8601ToDateTimePUTF8Char(PUTF8Char(VAnsiString)+3,length(RawUTF8(VAnsiString))-3)) else // expect UTF-8 content only for AnsiString, i.e. RawUTF8 variables {$ifdef HASCODEPAGE} BindTextU(i,AnyAnsiToUTF8(RawByteString(VAnsiString)),IO); {$else} BindTextU(i,RawUTF8(VAnsiString),IO); {$endif} end; vtPChar: BindTextP(i,PUTF8Char(VPChar),IO); vtChar: BindTextU(i,RawUTF8(VChar),IO); vtWideChar: BindTextU(i,RawUnicodeToUtf8(@VWideChar,1),IO); vtPWideChar: BindTextU(i,RawUnicodeToUtf8(VPWideChar,StrLenW(VPWideChar)),IO); vtWideString: BindTextW(i,WideString(VWideString),IO); {$ifdef HASVARUSTRING} {$ifdef UNICODE} vtUnicodeString: BindTextS(i,string(VUnicodeString),IO); {$else} vtUnicodeString: BindTextU(i,UnicodeStringToUtf8(UnicodeString(VUnicodeString)),IO); {$endif} {$endif} vtBoolean: Bind(i,integer(VBoolean),IO); vtInteger: Bind(i,VInteger,IO); vtInt64: Bind(i,VInt64^,IO); vtCurrency: BindCurrency(i,VCurrency^,IO); vtExtended: Bind(i,VExtended^,IO); vtPointer: if VPointer=nil then ................................................................................ if DataIsBlob then if (VAny<>nil) and (PInteger(VAny)^ and $00ffffff=JSON_BASE64_MAGIC) then // recognized as Base64 encoded text BindBlob(Param,Base64ToBin(PAnsiChar(VAny)+3,length(RawByteString(VAny))-3)) else // no conversion if was set via TQuery.AsBlob property e.g. BindBlob(Param,RawByteString(VAny),IO) else // direct bind of AnsiString as UTF-8 value {$ifdef HASCODEPAGE} BindTextU(Param,AnyAnsiToUTF8(RawByteString(VAny)),IO); {$else} // on older Delphi, we assume AnsiString = RawUTF8 BindTextU(Param,RawUTF8(VAny),IO); {$endif} else if VType=varByRef or varVariant then BindVariant(Param,PVariant(VPointer)^,DataIsBlob,IO) else ................................................................................ dec(L); // avoid return of invalid UTF-8 buffer if L=0 then L := MaxCharCount; SetString(result,PAnsiChar(VAny),L); end else result := RawUTF8(VAny); end; {$ifdef HASVARUSTRING} varUString: begin L := length(UnicodeString(VAny)); if L>MaxCharCount then begin Truncated := true; L := MaxCharCount; end; RawUnicodeToUtf8(VAny,L,result); end; {$endif} |
Changes to SynDBZeos.pas.
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
|
end; end; inc(len,startlen+finlen);//add { and } SetLength(result,len); P := pointer(result); if startlen>0 then begin Move(pointer(start)^,P^,startlen); inc(P,startlen); end; i := 0; repeat L := length(Values[i]); if L>0 then begin ................................................................................ j := 0; while k+j<l do begin case Values[i][k+j] of '"': break; else inc(j); end; end; move(pointer(@Values[i][k])^,P^,j); inc(P,j); inc(k,j); case Values[i][k] of '"': begin move(pointer(dQuoteRepl)^,P^,dQuoteRepllen); inc(P,dQuoteRepllen); inc(k); end; end; end; P^ := '"'; inc(p); end else begin move(pointer(Values[i])^,P^,L); inc(P,L); end; end; if i=high(Values) then Break; if seplen>0 then begin Move(pointer(Sep)^,P^,seplen); inc(P,seplen); end; inc(i); until false; if finlen>0 then begin Move(pointer(fin)^,P^,finlen); inc(P,finlen); end; Assert(P-pointer(result)=len); end; procedure TSQLDBZEOSStatement.ExecutePrepared; var i,n: integer; |
|
|
|
|
|
|
|
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
|
end; end; inc(len,startlen+finlen);//add { and } SetLength(result,len); P := pointer(result); if startlen>0 then begin MoveFast(pointer(start)^,P^,startlen); inc(P,startlen); end; i := 0; repeat L := length(Values[i]); if L>0 then begin ................................................................................ j := 0; while k+j<l do begin case Values[i][k+j] of '"': break; else inc(j); end; end; MoveFast(pointer(@Values[i][k])^,P^,j); inc(P,j); inc(k,j); case Values[i][k] of '"': begin MoveFast(pointer(dQuoteRepl)^,P^,dQuoteRepllen); inc(P,dQuoteRepllen); inc(k); end; end; end; P^ := '"'; inc(p); end else begin MoveFast(pointer(Values[i])^,P^,L); inc(P,L); end; end; if i=high(Values) then Break; if seplen>0 then begin MoveFast(pointer(Sep)^,P^,seplen); inc(P,seplen); end; inc(i); until false; if finlen>0 then begin MoveFast(pointer(fin)^,P^,finlen); inc(P,finlen); end; Assert(P-pointer(result)=len); end; procedure TSQLDBZEOSStatement.ExecutePrepared; var i,n: integer; |
Changes to SynGdiPlus.pas.
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
....
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
|
/// helper to save a specified graphic into GIF/PNG/JPG/TIFF format // - CompressionQuality is only used for gptJPG format saving // and is expected to be from 0 to 100 // - if MaxPixelsForBiggestSide is set to something else than 0, the resulting // picture biggest side won't exceed this pixel number procedure SaveAsRawByteString(Graphic: TPersistent; out DataRawByteString; Format: TGDIPPictureType; CompressionQuality: integer=80; MaxPixelsForBiggestSide: cardinal=0; BitmapSetResolution: single=0); /// helper to load a specified graphic from GIF/PNG/JPG/TIFF format content function LoadFromRawByteString(const Picture: {$ifdef UNICODE}RawByteString{$else}AnsiString{$endif}): TBitmap; /// helper function to create a bitmap from any GIF/PNG/JPG/TIFF/EMF/WMF file // - if file extension if .EMF, the file is drawn with a special antialiased // GDI+ drawing method (if the global Gdip var is a TGDIPlusFull instance) function LoadFrom(const FileName: TFileName): TBitmap; overload; /// helper function to create a bitmap from any EMF content ................................................................................ SaveAs(Graphic,Stream,Format,CompressionQuality,MaxPixelsForBiggestSide, BitmapSetResolution); finally Stream.Free; end; end; {$ifndef UNICODE} type RawByteString = AnsiString; {$endif} procedure SaveAsRawByteString(Graphic: TPersistent; out DataRawByteString; Format: TGDIPPictureType; CompressionQuality: integer=80; MaxPixelsForBiggestSide: cardinal=0; BitmapSetResolution: single=0); overload; var Stream: TMemoryStream; begin Stream := TMemoryStream.Create; try SaveAs(Graphic,Stream,Format,CompressionQuality,MaxPixelsForBiggestSide, BitmapSetResolution); SetString(RawByteString(DataRawByteString),PAnsiChar(Stream.Memory),Stream.Seek(0,soFromCurrent)); finally Stream.Free; end; end; function LoadFromRawByteString(const Picture: {$ifdef UNICODE}RawByteString{$else}AnsiString{$endif}): TBitmap; var ST: TStringStream; begin Result := nil; if Picture='' then exit; ST := TStringStream.Create(Picture); try |
>
|
|
|
>
|
|
|
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
....
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
|
/// helper to save a specified graphic into GIF/PNG/JPG/TIFF format // - CompressionQuality is only used for gptJPG format saving // and is expected to be from 0 to 100 // - if MaxPixelsForBiggestSide is set to something else than 0, the resulting // picture biggest side won't exceed this pixel number procedure SaveAsRawByteString(Graphic: TPersistent; out DataRawByteString{$ifdef HASCODEPAGE}: RawByteString{$endif}; Format: TGDIPPictureType; CompressionQuality: integer=80; MaxPixelsForBiggestSide: cardinal=0; BitmapSetResolution: single=0); /// helper to load a specified graphic from GIF/PNG/JPG/TIFF format content function LoadFromRawByteString(const Picture: {$ifdef HASCODEPAGE}RawByteString{$else}AnsiString{$endif}): TBitmap; /// helper function to create a bitmap from any GIF/PNG/JPG/TIFF/EMF/WMF file // - if file extension if .EMF, the file is drawn with a special antialiased // GDI+ drawing method (if the global Gdip var is a TGDIPlusFull instance) function LoadFrom(const FileName: TFileName): TBitmap; overload; /// helper function to create a bitmap from any EMF content ................................................................................ SaveAs(Graphic,Stream,Format,CompressionQuality,MaxPixelsForBiggestSide, BitmapSetResolution); finally Stream.Free; end; end; {$ifndef HASCODEPAGE} type RawByteString = AnsiString; {$endif} procedure SaveAsRawByteString(Graphic: TPersistent; out DataRawByteString{$ifdef HASCODEPAGE}: RawByteString{$endif}; Format: TGDIPPictureType; CompressionQuality: integer=80; MaxPixelsForBiggestSide: cardinal=0; BitmapSetResolution: single=0); overload; var Stream: TMemoryStream; begin Stream := TMemoryStream.Create; try SaveAs(Graphic,Stream,Format,CompressionQuality,MaxPixelsForBiggestSide, BitmapSetResolution); SetString(RawByteString(DataRawByteString),PAnsiChar(Stream.Memory),Stream.Seek(0,soFromCurrent)); finally Stream.Free; end; end; function LoadFromRawByteString(const Picture: RawByteString): TBitmap; var ST: TStringStream; begin Result := nil; if Picture='' then exit; ST := TStringStream.Create(Picture); try |
Changes to SynMongoDB.pas.
3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 |
case value.VType of
vtBoolean: BSONWrite(name,value.VBoolean);
vtInteger: BSONWrite(name,value.VInteger);
vtInt64: BSONWrite(name,value.VInt64^);
vtCurrency: BSONWrite(name,value.VCurrency^);
vtExtended: BSONWrite(name,value.VExtended^);
vtVariant: BSONWriteVariant(name,value.VVariant^);
vtString, vtAnsiString, {$ifdef UNICODE}vtUnicodeString,{$endif}
vtPChar, vtChar, vtWideChar, vtWideString: begin
VarRecToUTF8(value,tmp);
BSONWrite(name,tmp);
end;
else raise EBSONException.CreateUtf8(
'%.BSONWrite(TVarRec.VType=%)',[self,value.VType]);
end;
|
| |
3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 |
case value.VType of
vtBoolean: BSONWrite(name,value.VBoolean);
vtInteger: BSONWrite(name,value.VInteger);
vtInt64: BSONWrite(name,value.VInt64^);
vtCurrency: BSONWrite(name,value.VCurrency^);
vtExtended: BSONWrite(name,value.VExtended^);
vtVariant: BSONWriteVariant(name,value.VVariant^);
vtString, vtAnsiString, {$ifdef HASVARUSTRING}vtUnicodeString,{$endif}
vtPChar, vtChar, vtWideChar, vtWideString: begin
VarRecToUTF8(value,tmp);
BSONWrite(name,tmp);
end;
else raise EBSONException.CreateUtf8(
'%.BSONWrite(TVarRec.VType=%)',[self,value.VType]);
end;
|
Changes to SynPdf.pas.
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 .... 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 .... 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 |
fCodePage: integer; fAddGlyphFont: (fNone, fMain, fFallBack); fDoc: TPdfDocument; Tmp: array[0..511] of AnsiChar; /// internal Ansi->Unicode conversion, using the CodePage used in Create() // - caller must release the returned memory via FreeMem() function ToWideChar(const Ansi: PDFString; out DLen: Integer): PWideChar; {$ifdef USE_UNISCRIBE} /// internal method using the Windows Uniscribe API // - return FALSE if PW was not appened to the PDF content, TRUE if OK function AddUnicodeHexTextUniScribe(PW: PWideChar; WinAnsiTTF: TPdfFontTrueType; NextLine: boolean; Canvas: TPdfCanvas): boolean; {$endif} /// internal method NOT using the Windows Uniscribe API procedure AddUnicodeHexTextNoUniScribe(PW: PWideChar; TTF: TPdfFontTrueType; NextLine: boolean; Canvas: TPdfCanvas); /// internal methods handling font fall-back procedure AddGlyphFromChar(Char: WideChar; Canvas: TPdfCanvas; TTF: TPdfFontTrueType; NextLine: PBoolean); procedure AddGlyphFlush(Canvas: TPdfCanvas; TTF: TPdfFontTrueType; NextLine: PBoolean); ................................................................................ // line by (tx ,ty) // - tx and ty are numbers expressed in unscaled text space units procedure MoveTextPoint(tx, ty: Single); {$ifdef HASINLINE}inline;{$endif} { Td } /// set the Text Matrix to a,b,c,d and the text line Matrix x,y procedure SetTextMatrix(a, b, c, d, x, y: Single); { Tm } /// Move to the start of the next line procedure MoveToNextLine; { T* } {$ifdef UNICODE} /// Show a text string // - text is expected to be Unicode encoded // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(const text: UnicodeString; NextLine: boolean=false); overload; inline; { Tj or ' } /// Show a text string // - text is expected to be Ansi-Encoded, in the current CharSet; if // some Unicode or MBCS conversion is necessary, it will be notified to the // corresponding // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(const text: PDFString; NextLine: boolean=false); overload; { Tj or ' } {$else} /// Show a text string // - text is expected to be Ansi-Encoded, in the current CharSet; if // some Unicode or MBCS conversion is necessary, it will be notified to the // corresponding // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(const text: PDFString; NextLine: boolean=false); overload; { Tj or ' } {$endif} /// Show an Unicode Text string // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(PW: PWideChar; NextLine: boolean=false); overload; {$ifdef HASINLINE}inline;{$endif} /// Show an Unicode Text string, encoded as Glyphs or the current font // - PW must follow the ETO_GLYPH_INDEX layout, i.e. refers to an array as ................................................................................ procedure TPdfCanvas.MoveToNextLine; begin if FContents<>nil then FContents.Writer.Add('T*'#10); end; {$ifdef UNICODE} procedure TPdfCanvas.ShowText(const text: UnicodeString; NextLine: boolean); begin // direct call of the unicode text drawing method below ShowText(pointer(text),NextLine); end; {$endif} |
| | | > < < < < < < < < < | |
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 .... 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 .... 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 |
fCodePage: integer; fAddGlyphFont: (fNone, fMain, fFallBack); fDoc: TPdfDocument; Tmp: array[0..511] of AnsiChar; /// internal Ansi->Unicode conversion, using the CodePage used in Create() // - caller must release the returned memory via FreeMem() function ToWideChar(const Ansi: PDFString; out DLen: Integer): PWideChar; {$ifdef USE_UNISCRIBE} /// internal method using the Windows Uniscribe API // - return FALSE if PW was not appened to the PDF content, TRUE if OK function AddUnicodeHexTextUniScribe(PW: PWideChar; WinAnsiTTF: TPdfFontTrueType; NextLine: boolean; Canvas: TPdfCanvas): boolean; {$endif} /// internal method NOT using the Windows Uniscribe API procedure AddUnicodeHexTextNoUniScribe(PW: PWideChar; TTF: TPdfFontTrueType; NextLine: boolean; Canvas: TPdfCanvas); /// internal methods handling font fall-back procedure AddGlyphFromChar(Char: WideChar; Canvas: TPdfCanvas; TTF: TPdfFontTrueType; NextLine: PBoolean); procedure AddGlyphFlush(Canvas: TPdfCanvas; TTF: TPdfFontTrueType; NextLine: PBoolean); ................................................................................ // line by (tx ,ty) // - tx and ty are numbers expressed in unscaled text space units procedure MoveTextPoint(tx, ty: Single); {$ifdef HASINLINE}inline;{$endif} { Td } /// set the Text Matrix to a,b,c,d and the text line Matrix x,y procedure SetTextMatrix(a, b, c, d, x, y: Single); { Tm } /// Move to the start of the next line procedure MoveToNextLine; { T* } {$ifdef HASVARUSTRING} /// Show a text string // - text is expected to be Unicode encoded // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(const text: UnicodeString; NextLine: boolean=false); overload; inline; { Tj or ' } {$endif} /// Show a text string // - text is expected to be Ansi-Encoded, in the current CharSet; if // some Unicode or MBCS conversion is necessary, it will be notified to the // corresponding // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(const text: PDFString; NextLine: boolean=false); overload; { Tj or ' } /// Show an Unicode Text string // - if NextLine is TRUE, moves to the next line and show a text string; // in this case, method as the same effect as MoveToNextLine; ShowText(s); procedure ShowText(PW: PWideChar; NextLine: boolean=false); overload; {$ifdef HASINLINE}inline;{$endif} /// Show an Unicode Text string, encoded as Glyphs or the current font // - PW must follow the ETO_GLYPH_INDEX layout, i.e. refers to an array as ................................................................................ procedure TPdfCanvas.MoveToNextLine; begin if FContents<>nil then FContents.Writer.Add('T*'#10); end; {$ifdef HASVARUSTRING} procedure TPdfCanvas.ShowText(const text: UnicodeString; NextLine: boolean); begin // direct call of the unicode text drawing method below ShowText(pointer(text),NextLine); end; {$endif} |
Changes to SynSM.pas.
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 |
FValue := DOUBLE_TO_JSVAL(V.VExtended^);
vtVariant:
SetVariant(cx,V.VVariant^);
vtWideString:
SetWideString(cx,WideString(V.VPointer));
vtAnsiString:
SetAnsiChar(cx,V.VPointer,length(RawByteString(V.VAnsiString)),
{$ifndef UNICODE} CP_UTF8);
{$else} StringCodePage(RawByteString(V.VAnsiString)));
vtUnicodeString:
SetSynUnicode(cx,UnicodeString(V.VPointer));
{$endif}
vtString:
SetAnsiChar(cx,PAnsiChar(@V.VString^[1]),ord(V.VString^[0]),0);
vtPChar:
|
| |
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 |
FValue := DOUBLE_TO_JSVAL(V.VExtended^);
vtVariant:
SetVariant(cx,V.VVariant^);
vtWideString:
SetWideString(cx,WideString(V.VPointer));
vtAnsiString:
SetAnsiChar(cx,V.VPointer,length(RawByteString(V.VAnsiString)),
{$ifndef HASCODEPAGE} CP_UTF8);
{$else} StringCodePage(RawByteString(V.VAnsiString)));
vtUnicodeString:
SetSynUnicode(cx,UnicodeString(V.VPointer));
{$endif}
vtString:
SetAnsiChar(cx,PAnsiChar(@V.VString^[1]),ord(V.VString^[0]),0);
vtPChar:
|
Changes to SynSelfTests.pas.
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 .... 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 .... 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 .... 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 .... 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 .... 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 .... 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 .... 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 .... 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 .... 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 |
procedure TTestLowLevelCommon._TDynArray; var AI, AI2: TIntegerDynArray; AU: TRawUTF8DynArray; AR: TRecs; AF: TFVs; AF2: TFV2s; i,j,k,Len, count,AIcount: integer; U: RawUTF8; P: PUTF8Char; PI: PIntegerArray; R: TRec; F, F1: TFV; F2: TFV2; City: TCity; Province: TProvince; ................................................................................ end; W.CancelAll; W.AddDynArrayJSON(ARP); U := W.Text; Check(Hash32(U)={$ifdef CPU64}$9F98936D{$else}$54659D65{$endif}); P := pointer(U); JSON_BASE64_MAGIC_UTF8 := RawUnicodeToUtf8(@MAGIC,2); Check(U='['+JSON_BASE64_MAGIC_UTF8+BinToBase64(ARP.SaveTo)+'"]'); ARP.Clear; Check(ARP.LoadFromJSON(pointer(U))<>nil); if not CheckFailed(ARP.Count=1001) then for i := 0 to 1000 do with AR[i] do begin Check(A=i); Check(B=byte(i+1)); ................................................................................ {Check(A.Dyn[0]=0) bug in original VCL?} Check(C.Dyn[0]=10); end; procedure TTestLowLevelCommon.UrlEncoding; var i: integer; s: RawByteString; name,value: RawUTF8; P: PUTF8Char; GUID2: TGUID; U: TURI; const GUID: TGUID = '{c9a646d3-9c61-4cb7-bfcd-ee2522c8f633}'; procedure Test(const decoded,encoded: RawUTF8); begin Check(UrlEncode(decoded)=encoded); ................................................................................ Check(P^=#0); Check(name='name,complex'); Check(value='value'); for i := 0 to 100 do begin s := RandomString(i*5); Check(UrlDecode(UrlEncode(s))=s,string(s)); end; s := BinToBase64URI(@GUID,sizeof(GUID)); Check(s='00amyWGct0y_ze4lIsj2Mw'); Base64FromURI(s); Check(Base64ToBinLength(pointer(s),length(s))=sizeof(GUID2)); fillchar(GUID2,sizeof(GUID2),0); SynCommons.Base64Decode(Pointer(s),@GUID2,SizeOf(GUID2)); Check(IsEqualGUID(GUID2,GUID)); Check(U.From('toto.com')); Check(U.URI='http://toto.com/'); Check(U.From('toto.com:123')); Check(U.URI='http://toto.com:123/'); Check(U.From('https://toto.com:123/tata/titi')); Check(U.URI='https://toto.com:123/tata/titi'); ................................................................................ end; end; procedure TTestLowLevelCommon._UTF8; procedure Test(CP: cardinal; const W: WinAnsiString); var C: TSynAnsiConvert; L: integer; tmpA: array[0..127] of AnsiChar; begin C := TSynAnsiConvert.Engine(CP); Check(C.UTF8ToAnsi(C.AnsiToUTF8(W))=W); Check(C.RawUnicodeToAnsi(C.AnsiToRawUnicode(W))=W); FillChar(tmpA,SizeOf(tmpA),1); if CP=CP_UTF16 then exit; L := C.Utf8ToAnsiBuffer(RawByteString(W),tmpA,sizeof(tmpA)); Check(L=StrLen(@tmpA)); if L<sizeof(tmpA)-1 then Check(L=Length(W)) else ................................................................................ var i, CP, L: integer; W: WinAnsiString; WS: WideString; SU: SynUnicode; U, res, Up,Up2: RawUTF8; arr: TRawUTF8DynArray; PB: PByte; {$ifndef DELPHI5OROLDER} q: RawUTF8; {$endif} Unic: RawUnicode; WA: Boolean; begin res := 'one,two,three'; Check(StrLen(nil)=0); for i := length(res)+1 downto 1 do Check(StrLen(Pointer(@res[i]))=length(res)-i+1); ................................................................................ Test(CP_UTF8,W); L := Length(W); if L and 1<>0 then SetLength(W,L-1); // force exact UTF-16 buffer length Test(CP_UTF16,W); W := WinAnsiString(RandomString(i*5)); U := WinAnsiToUtf8(W); Check(Utf8ToWinAnsi(U)=W); Check(WinAnsiConvert.UTF8ToAnsi(WinAnsiConvert.AnsiToUTF8(W))=W); Check(WinAnsiConvert.RawUnicodeToAnsi(WinAnsiConvert.AnsiToRawUnicode(W))=W); if CurrentAnsiConvert.InheritsFrom(TSynAnsiFixedWidth) then begin Check(CurrentAnsiConvert.UTF8ToAnsi(CurrentAnsiConvert.AnsiToUTF8(W))=W); Check(CurrentAnsiConvert.RawUnicodeToAnsi(CurrentAnsiConvert.AnsiToRawUnicode(W))=W); end; Unic := Utf8DecodeToRawUnicode(U); res := RawUnicodeToUtf8(Unic); Check(res=U); Check(RawUnicodeToWinAnsi(Unic)=W); WS := UTF8ToWideString(U); Check(length(WS)=length(Unic)shr 1); if WS<>'' then Check(CompareMem(pointer(WS),pointer(Unic),length(WS)*sizeof(WideChar))); Check(integer(Utf8ToUnicodeLength(Pointer(U)))=length(WS)); SU := UTF8ToSynUnicode(U); Check(length(SU)=length(Unic)shr 1); ................................................................................ Trans: TTestCustomJSON2; Disco: TTestCustomDiscogs; Cache: TSQLRestCacheEntryValue; {$ifndef DELPHI5OROLDER} peop: TSQLRecordPeople; K,U2: RawUTF8; Valid: boolean; {$ifndef LVCL} Instance: TClassInstance; Coll, C2: TCollTst; MyItem: TCollTest; Comp: TComplexNumber; DA: TDynArray; F: TFV; ................................................................................ Check(not IsString(V[2])); Check(not IsStringJSON(V[2])); Check(GetInteger(V[2])=a); Check(V[3]=nil); J := BinToBase64WithMagic(U); check(PInteger(J)^ and $00ffffff=JSON_BASE64_MAGIC); {$ifndef DELPHI5OROLDER} check(BlobToTSQLRawBlob(pointer(J))=U); Base64MagicToBlob(@J[4],K); check(BlobToTSQLRawBlob(pointer(K))=U); { J := TSQLRestServer.JSONEncodeResult([r]); Check(SameValue(GetExtended(pointer(JSONDecode(J)),err),r)); } {$ifndef NOVARIANTS} with TTextWriter.CreateOwnedStream do try AddVariant(a); Add(','); ................................................................................ procedure TTestCryptographicRoutines._Adler32; begin Check(Adler32SelfTest); end; procedure TTestCryptographicRoutines._Base64; const Value64: RawByteString = 'SGVsbG8gL2Mn6XRhaXQg5+Ar'; var tmp, b64: RawByteString; Value: WinAnsiString; i, L: Integer; begin Value := 'Hello /c''0tait 67+'; Value[10] := #$E9; Value[16] := #$E7; Value[17] := #$E0; |
| | > | | | | | | > > > | > > > > > > > > > > > > > > > > > > | | > > < > > | > > | > > | | > |
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 .... 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 .... 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 .... 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 .... 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 .... 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 .... 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 .... 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 .... 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 .... 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 |
procedure TTestLowLevelCommon._TDynArray; var AI, AI2: TIntegerDynArray; AU: TRawUTF8DynArray; AR: TRecs; AF: TFVs; AF2: TFV2s; i,j,k,Len, count,AIcount: integer; U,U2: RawUTF8; P: PUTF8Char; PI: PIntegerArray; R: TRec; F, F1: TFV; F2: TFV2; City: TCity; Province: TProvince; ................................................................................ end; W.CancelAll; W.AddDynArrayJSON(ARP); U := W.Text; Check(Hash32(U)={$ifdef CPU64}$9F98936D{$else}$54659D65{$endif}); P := pointer(U); JSON_BASE64_MAGIC_UTF8 := RawUnicodeToUtf8(@MAGIC,2); U2 := RawUTF8('[')+JSON_BASE64_MAGIC_UTF8+RawUTF8(BinToBase64(ARP.SaveTo))+RawUTF8('"]'); Check(U=U2); ARP.Clear; Check(ARP.LoadFromJSON(pointer(U))<>nil); if not CheckFailed(ARP.Count=1001) then for i := 0 to 1000 do with AR[i] do begin Check(A=i); Check(B=byte(i+1)); ................................................................................ {Check(A.Dyn[0]=0) bug in original VCL?} Check(C.Dyn[0]=10); end; procedure TTestLowLevelCommon.UrlEncoding; var i: integer; s: RawByteString; name,value,utf: RawUTF8; P: PUTF8Char; GUID2: TGUID; U: TURI; const GUID: TGUID = '{c9a646d3-9c61-4cb7-bfcd-ee2522c8f633}'; procedure Test(const decoded,encoded: RawUTF8); begin Check(UrlEncode(decoded)=encoded); ................................................................................ Check(P^=#0); Check(name='name,complex'); Check(value='value'); for i := 0 to 100 do begin s := RandomString(i*5); Check(UrlDecode(UrlEncode(s))=s,string(s)); end; utf := BinToBase64URI(@GUID,sizeof(GUID)); Check(utf='00amyWGct0y_ze4lIsj2Mw'); Base64FromURI(utf); Check(Base64ToBinLength(pointer(utf),length(utf))=sizeof(GUID2)); fillchar(GUID2,sizeof(GUID2),0); SynCommons.Base64Decode(Pointer(utf),@GUID2,SizeOf(GUID2)); Check(IsEqualGUID(GUID2,GUID)); Check(U.From('toto.com')); Check(U.URI='http://toto.com/'); Check(U.From('toto.com:123')); Check(U.URI='http://toto.com:123/'); Check(U.From('https://toto.com:123/tata/titi')); Check(U.URI='https://toto.com:123/tata/titi'); ................................................................................ end; end; procedure TTestLowLevelCommon._UTF8; procedure Test(CP: cardinal; const W: WinAnsiString); var C: TSynAnsiConvert; L: integer; A: RawByteString; U: RawUTF8; tmpA: array[0..127] of AnsiChar; begin C := TSynAnsiConvert.Engine(CP); Check(C.CodePage=CP); U := C.AnsiToUTF8(W); A := C.UTF8ToAnsi(U); Check(length(W)=length(A)); if W='' then exit; {$ifdef HASCODEPAGE} {$ifndef FPC} Check(StringCodePage(W)=1252); {$endif} CP := StringCodePage(A); Check(CP=C.CodePage); {$endif} {$ifdef FPC} if CP=CP_UTF16 then exit; Check(CompareMem(pointer(W),pointer(A),length(W))); {$else} Check(A=W); Check(C.RawUnicodeToAnsi(C.AnsiToRawUnicode(W))=W); {$endif} FillChar(tmpA,SizeOf(tmpA),1); if CP=CP_UTF16 then exit; L := C.Utf8ToAnsiBuffer(RawByteString(W),tmpA,sizeof(tmpA)); Check(L=StrLen(@tmpA)); if L<sizeof(tmpA)-1 then Check(L=Length(W)) else ................................................................................ var i, CP, L: integer; W: WinAnsiString; WS: WideString; SU: SynUnicode; U, res, Up,Up2: RawUTF8; arr: TRawUTF8DynArray; PB: PByte; {$ifndef DELPHI5OROLDER} q: RawUTF8; {$endif} Unic: RawUnicode; WA: Boolean; begin res := 'one,two,three'; Check(StrLen(nil)=0); for i := length(res)+1 downto 1 do Check(StrLen(Pointer(@res[i]))=length(res)-i+1); ................................................................................ Test(CP_UTF8,W); L := Length(W); if L and 1<>0 then SetLength(W,L-1); // force exact UTF-16 buffer length Test(CP_UTF16,W); W := WinAnsiString(RandomString(i*5)); U := WinAnsiToUtf8(W); Unic := Utf8DecodeToRawUnicode(U); {$ifndef FPC_HAS_CPSTRING} // buggy FPC Check(Utf8ToWinAnsi(U)=W); Check(WinAnsiConvert.UTF8ToAnsi(WinAnsiConvert.AnsiToUTF8(W))=W); Check(WinAnsiConvert.RawUnicodeToAnsi(WinAnsiConvert.AnsiToRawUnicode(W))=W); if CurrentAnsiConvert.InheritsFrom(TSynAnsiFixedWidth) then begin Check(CurrentAnsiConvert.UTF8ToAnsi(CurrentAnsiConvert.AnsiToUTF8(W))=W); Check(CurrentAnsiConvert.RawUnicodeToAnsi(CurrentAnsiConvert.AnsiToRawUnicode(W))=W); end; res := RawUnicodeToUtf8(Unic); Check(res=U); Check(RawUnicodeToWinAnsi(Unic)=W); {$endif FPC_HAS_CPSTRING} WS := UTF8ToWideString(U); Check(length(WS)=length(Unic)shr 1); if WS<>'' then Check(CompareMem(pointer(WS),pointer(Unic),length(WS)*sizeof(WideChar))); Check(integer(Utf8ToUnicodeLength(Pointer(U)))=length(WS)); SU := UTF8ToSynUnicode(U); Check(length(SU)=length(Unic)shr 1); ................................................................................ Trans: TTestCustomJSON2; Disco: TTestCustomDiscogs; Cache: TSQLRestCacheEntryValue; {$ifndef DELPHI5OROLDER} peop: TSQLRecordPeople; K,U2: RawUTF8; Valid: boolean; RB: TSQLRawBlob; {$ifndef LVCL} Instance: TClassInstance; Coll, C2: TCollTst; MyItem: TCollTest; Comp: TComplexNumber; DA: TDynArray; F: TFV; ................................................................................ Check(not IsString(V[2])); Check(not IsStringJSON(V[2])); Check(GetInteger(V[2])=a); Check(V[3]=nil); J := BinToBase64WithMagic(U); check(PInteger(J)^ and $00ffffff=JSON_BASE64_MAGIC); {$ifndef DELPHI5OROLDER} RB := BlobToTSQLRawBlob(pointer(J)); check(length(RB)=length(U)); // RB=U is buggy under FPC :( check(CompareMem(pointer(RB),pointer(U),length(U))); Base64MagicToBlob(@J[4],K); RB := BlobToTSQLRawBlob(pointer(K)); check(length(RB)=length(U)); // RB=U is buggy under FPC :( check(CompareMem(pointer(RB),pointer(U),length(U))); { J := TSQLRestServer.JSONEncodeResult([r]); Check(SameValue(GetExtended(pointer(JSONDecode(J)),err),r)); } {$ifndef NOVARIANTS} with TTextWriter.CreateOwnedStream do try AddVariant(a); Add(','); ................................................................................ procedure TTestCryptographicRoutines._Adler32; begin Check(Adler32SelfTest); end; procedure TTestCryptographicRoutines._Base64; const Value64: RawUTF8 = 'SGVsbG8gL2Mn6XRhaXQg5+Ar'; var tmp: RawByteString; b64: RawUTF8; Value: WinAnsiString; i, L: Integer; begin Value := 'Hello /c''0tait 67+'; Value[10] := #$E9; Value[16] := #$E7; Value[17] := #$E0; |
Changes to SynZip.pas.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
// - by default, will use the deflate/.zip header-less format, but you may set
// ZlibFormat=true to add an header, as expected by zlib (and pdf)
function UnCompressStream(src: pointer; srcLen: integer; aStream: TStream;
checkCRC: PCardinal; ZlibFormat: Boolean=false): cardinal;
type
{$ifdef UNICODE}
/// define a raw storage string type, used for data buffer management
ZipString = type RawByteString;
{$else}
/// define a raw storage string type, used for data buffer management
ZipString = type AnsiString;
/// as available in newer Delphi versions
NativeUInt = cardinal;
|
| |
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
// - by default, will use the deflate/.zip header-less format, but you may set
// ZlibFormat=true to add an header, as expected by zlib (and pdf)
function UnCompressStream(src: pointer; srcLen: integer; aStream: TStream;
checkCRC: PCardinal; ZlibFormat: Boolean=false): cardinal;
type
{$ifdef HASCODEPAGE}
/// define a raw storage string type, used for data buffer management
ZipString = type RawByteString;
{$else}
/// define a raw storage string type, used for data buffer management
ZipString = type AnsiString;
/// as available in newer Delphi versions
NativeUInt = cardinal;
|
Changes to Synopse.inc.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 ... 181 182 183 184 185 186 187 188 189 190 191 192 193 194 ... 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
// LVCL does not support variants {$define NOVARIANTS} {$endif} {$ifdef UNICODE} {$undef ENHANCEDRTL} // Delphi 2009 and up don't have our Enhanced Runtime library {$define HASVARUSTRING} { due to a bug in Delphi 2009+, we need to fake inheritance of record, since TDynArrayHashed = object(TDynArray) fails to initialize http://blog.synopse.info/post/2011/01/29/record-and-object-issue-in-Delphi-2010 } {$define UNDIRECTDYNARRAY} {$endif} ................................................................................ {$ifdef FPC} {$MODE DELPHI} // e.g. for asm syntax - disabled for FPC 2.6 compatibility {$INLINE ON} {$MINENUMSIZE 1} {$PACKSET 1} {$PACKENUM 1} {$undef ENHANCEDRTL} // there is no version of our Enhanced RTL for FPC {$undef DOPATCHTRTL} {$define USETYPEINFO} // will use SynFPCTypInfo.pas wrapper {$define HASINLINE} {$define NODELPHIASM} // ignore low-level System.@LStrFromPCharLen calls {$define HASAESNI} ................................................................................ {$endif} {$define FPC_OR_PUREPASCAL} {$define FPC_OR_KYLIX} // exceptions interception code in FPC differs from Delphi {$define NOEXCEPTIONINTERCEPT} {$ifdef VER2_7} {$define ISFPC27} {$endif} {$ifdef VER3_0} {$define ISFPC27} {$endif} {$ifdef VER3_1} {$define ISFPC27} {$endif} {$ifdef ISFPC27} {$define ISFPC271} {$define HASVARUSTRING} {$define HASVARUSTRARG} // defined if the http://mantis.freepascal.org/view.php?id=26773 bug is fixed // you should use 2.7.1/trunk branch in revision 28995 from 2014-11-05T22:17:54 // => this will change the TInvokeableVariantType.SetProperty() signature |
> > > > > > |
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 ... 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 ... 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 |
// LVCL does not support variants {$define NOVARIANTS} {$endif} {$ifdef UNICODE} {$undef ENHANCEDRTL} // Delphi 2009 and up don't have our Enhanced Runtime library {$define HASVARUSTRING} {$define HASCODEPAGE} { due to a bug in Delphi 2009+, we need to fake inheritance of record, since TDynArrayHashed = object(TDynArray) fails to initialize http://blog.synopse.info/post/2011/01/29/record-and-object-issue-in-Delphi-2010 } {$define UNDIRECTDYNARRAY} {$endif} ................................................................................ {$ifdef FPC} {$MODE DELPHI} // e.g. for asm syntax - disabled for FPC 2.6 compatibility {$INLINE ON} {$MINENUMSIZE 1} {$PACKSET 1} {$PACKENUM 1} {$CODEPAGE UTF8} // otherwise unexpected behavior occurs in most cases {$undef ENHANCEDRTL} // there is no version of our Enhanced RTL for FPC {$undef DOPATCHTRTL} {$define USETYPEINFO} // will use SynFPCTypInfo.pas wrapper {$define HASINLINE} {$define NODELPHIASM} // ignore low-level System.@LStrFromPCharLen calls {$define HASAESNI} ................................................................................ {$endif} {$define FPC_OR_PUREPASCAL} {$define FPC_OR_KYLIX} // exceptions interception code in FPC differs from Delphi {$define NOEXCEPTIONINTERCEPT} // {$if FPC_FULLVERSION>20700} does not compile under Delphi 6-7 :( {$ifdef VER2_7} {$define ISFPC27} {$endif} {$ifdef VER3_0} {$define ISFPC27} {$endif} {$ifdef VER3_1} {$define ISFPC27} {$endif} {$ifdef FPC_HAS_CPSTRING} {$define HASCODEPAGE} // UNICODE means {$mode delphiunicode} {$endif} {$ifdef ISFPC27} {$define ISFPC271} {$define HASVARUSTRING} {$define HASVARUSTRARG} // defined if the http://mantis.freepascal.org/view.php?id=26773 bug is fixed // you should use 2.7.1/trunk branch in revision 28995 from 2014-11-05T22:17:54 // => this will change the TInvokeableVariantType.SetProperty() signature |
Changes to SynopseCommit.inc.
1 |
'1.18.2255'
|
| |
1 |
'1.18.2256'
|