blob: 89d021155b7e0364f29fd945e0f9930af207a154 [file] [log] [blame]
Jens Geyerd5436f52014-10-03 19:50:38 +02001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20unit Thrift.Utils;
21
22interface
23
Jens Geyer9f7f11e2016-04-14 21:37:11 +020024{$I Thrift.Defines.inc}
Nick4f5229e2016-04-14 16:43:22 +030025
Jens Geyerd5436f52014-10-03 19:50:38 +020026uses
Jens Geyer9f7f11e2016-04-14 21:37:11 +020027 {$IFDEF OLD_UNIT_NAMES}
Jens Geyer71070432016-01-29 10:08:39 +010028 Classes, Windows, SysUtils, Character, SyncObjs;
Jens Geyer9f7f11e2016-04-14 21:37:11 +020029 {$ELSE}
Nick4f5229e2016-04-14 16:43:22 +030030 System.Classes, Winapi.Windows, System.SysUtils, System.Character, System.SyncObjs;
Jens Geyer9f7f11e2016-04-14 21:37:11 +020031 {$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +020032
33type
34 IOverlappedHelper = interface
35 ['{A1832EFA-2E02-4884-8F09-F0A0277157FA}']
36 function Overlapped : TOverlapped;
37 function OverlappedPtr : POverlapped;
38 function WaitHandle : THandle;
39 function WaitFor(dwTimeout: DWORD) : DWORD;
40 end;
41
42 TOverlappedHelperImpl = class( TInterfacedObject, IOverlappedHelper)
43 strict protected
44 FOverlapped : TOverlapped;
45 FEvent : TEvent;
46
47 // IOverlappedHelper
48 function Overlapped : TOverlapped;
49 function OverlappedPtr : POverlapped;
50 function WaitHandle : THandle;
51 function WaitFor(dwTimeout: DWORD) : DWORD;
52 public
53 constructor Create;
54 destructor Destroy; override;
55 end;
56
57
Jens Geyerd8bddbc2014-12-14 00:41:33 +010058 Base64Utils = class sealed
59 public
60 class function Encode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; static;
61 class function Decode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; static;
62 end;
63
64
Jens Geyer71070432016-01-29 10:08:39 +010065 CharUtils = class sealed
66 public
67 class function IsHighSurrogate( const c : Char) : Boolean; static; inline;
68 class function IsLowSurrogate( const c : Char) : Boolean; static; inline;
69 end;
70
71
Jens Geyerf7904452017-07-26 15:02:12 +020072{$IFDEF Win64}
73function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64;
74{$ENDIF}
Jens Geyer9f7f11e2016-04-14 21:37:11 +020075
Jens Geyer71070432016-01-29 10:08:39 +010076
Jens Geyerd5436f52014-10-03 19:50:38 +020077implementation
78
Jens Geyerd5436f52014-10-03 19:50:38 +020079{ TOverlappedHelperImpl }
80
81constructor TOverlappedHelperImpl.Create;
82begin
83 inherited Create;
84 FillChar( FOverlapped, SizeOf(FOverlapped), 0);
85 FEvent := TEvent.Create( nil, TRUE, FALSE, ''); // always ManualReset, see MSDN
86 FOverlapped.hEvent := FEvent.Handle;
87end;
88
89
90
91destructor TOverlappedHelperImpl.Destroy;
92begin
93 try
94 FOverlapped.hEvent := 0;
95 FreeAndNil( FEvent);
96
97 finally
98 inherited Destroy;
99 end;
100
101end;
102
103
104function TOverlappedHelperImpl.Overlapped : TOverlapped;
105begin
106 result := FOverlapped;
107end;
108
109
110function TOverlappedHelperImpl.OverlappedPtr : POverlapped;
111begin
112 result := @FOverlapped;
113end;
114
115
116function TOverlappedHelperImpl.WaitHandle : THandle;
117begin
118 result := FOverlapped.hEvent;
119end;
120
121
122function TOverlappedHelperImpl.WaitFor( dwTimeout : DWORD) : DWORD;
123begin
124 result := WaitForSingleObject( FOverlapped.hEvent, dwTimeout);
125end;
126
127
Jens Geyerd8bddbc2014-12-14 00:41:33 +0100128{ Base64Utils }
129
130class function Base64Utils.Encode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer;
131const ENCODE_TABLE : PAnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
132begin
133 ASSERT( len in [1..3]);
134 dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff] shr 2) and $3F]);
135 case len of
136 3 : begin
137 Inc(dstOff);
138 dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff] shl 4) and $30) or ((src[srcOff + 1] shr 4) and $0F)]);
139 Inc(dstOff);
140 dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff + 1] shl 2) and $3C) or ((src[srcOff + 2] shr 6) and $03)]);
141 Inc(dstOff);
142 dst[dstOff] := Byte( ENCODE_TABLE[ src[srcOff + 2] and $3F]);
143 result := 4;
144 end;
145
146 2 : begin
147 Inc(dstOff);
148 dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff] shl 4) and $30) or ((src[srcOff + 1] shr 4) and $0F)]);
149 Inc(dstOff);
150 dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff + 1] shl 2) and $3C]);
151 result := 3;
152 end;
153
154 1 : begin
155 Inc(dstOff);
156 dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff] shl 4) and $30]);
157 result := 2;
158 end;
159
160 else
161 ASSERT( FALSE);
Jens Geyer9f9535c2014-12-14 04:16:05 +0100162 result := 0; // because invalid call
Jens Geyerd8bddbc2014-12-14 00:41:33 +0100163 end;
164end;
165
166
167class function Base64Utils.Decode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer;
168const DECODE_TABLE : array[0..$FF] of Integer
169 = ( -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
170 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
171 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
172 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
173 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
174 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
175 -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
176 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
177 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
178 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
179 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
180 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
181 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
182 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
183 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
184 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 );
185begin
186 ASSERT( len in [1..4]);
187 result := 1;
188 dst[dstOff] := ((DECODE_TABLE[src[srcOff] and $0FF] shl 2)
189 or (DECODE_TABLE[src[srcOff + 1] and $0FF] shr 4));
190
191 if (len > 2) then begin
192 Inc( result);
193 Inc( dstOff);
194 dst[dstOff] := (((DECODE_TABLE[src[srcOff + 1] and $0FF] shl 4) and $F0)
195 or (DECODE_TABLE[src[srcOff + 2] and $0FF] shr 2));
196
197 if (len > 3) then begin
198 Inc( result);
199 Inc( dstOff);
200 dst[dstOff] := (((DECODE_TABLE[src[srcOff + 2] and $0FF] shl 6) and $C0)
201 or DECODE_TABLE[src[srcOff + 3] and $0FF]);
202 end;
203 end;
204end;
Jens Geyerd5436f52014-10-03 19:50:38 +0200205
206
Jens Geyer71070432016-01-29 10:08:39 +0100207class function CharUtils.IsHighSurrogate( const c : Char) : Boolean;
208begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200209 {$IF CompilerVersion < 23.0}
210 result := Character.IsHighSurrogate( c);
Jens Geyer71070432016-01-29 10:08:39 +0100211 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200212 result := c.IsHighSurrogate();
Jens Geyer71070432016-01-29 10:08:39 +0100213 {$IFEND}
214end;
215
216
217class function CharUtils.IsLowSurrogate( const c : Char) : Boolean;
218begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200219 {$IF CompilerVersion < 23.0}
220 result := Character.IsLowSurrogate( c);
Jens Geyer71070432016-01-29 10:08:39 +0100221 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200222 result := c.IsLowSurrogate;
Jens Geyer71070432016-01-29 10:08:39 +0100223 {$IFEND}
224end;
225
226
Jens Geyerf7904452017-07-26 15:02:12 +0200227{$IFDEF Win64}
228
229function InterlockedCompareExchange64( var Target : Int64; Exchange, Comparand : Int64) : Int64; inline;
230begin
231 {$IFDEF OLD_UNIT_NAMES}
232 result := Windows.InterlockedCompareExchange64( Target, Exchange, Comparand);
233 {$ELSE}
234 result := WinApi.Windows.InterlockedCompareExchange64( Target, Exchange, Comparand);
235 {$ENDIF}
236end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200237
238
Jens Geyerf7904452017-07-26 15:02:12 +0200239function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200240var old : Int64;
241begin
242 repeat
243 Old := Addend;
244 until (InterlockedCompareExchange64( Addend, Old + Value, Old) = Old);
245 result := Old;
246end;
247
Jens Geyerf7904452017-07-26 15:02:12 +0200248{$ENDIF}
Jens Geyer71070432016-01-29 10:08:39 +0100249
250
Jens Geyerd5436f52014-10-03 19:50:38 +0200251end.