source: branches/virtcpu varint/UVarInt.pas

Last change on this file was 197, checked in by chronos, 5 years ago
  • Modified: All parts of virtual machine have own form in Forms subdirectory.
  • Modified: Main form moved to Forms subdirectory.
  • Modified: TCpu class moved to UCpu unit.
  • Added: Assembler and dissasembler forms.
File size: 13.9 KB
Line 
1unit UVarInt;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, Math;
9
10const
11 BitAlignment = 8;
12
13type
14 { TVarInt }
15
16 TVarInt = record
17 private
18 public
19 Value: Int64;
20 class operator Implicit(A: TVarInt): Int64;
21 class operator Implicit(A: TVarInt): QWord;
22 class operator Implicit(A: TVarInt): Integer;
23 class operator Implicit(A: TVarInt): Byte;
24 class operator Implicit(A: TVarInt): Char;
25 class operator Implicit(A: Byte): TVarInt;
26 class operator Implicit(A: Integer): TVarInt;
27 class operator Implicit(A: Int64): TVarInt;
28 class operator Implicit(A: QWord): TVarInt;
29 class operator Explicit(A: Byte): TVarInt;
30 class operator Explicit(A: Integer): TVarInt;
31 class operator Explicit(A: Int64): TVarInt;
32 class operator Explicit(A: TVarInt): Int64;
33 class operator Inc(A: TVarInt): TVarInt;
34 class operator Inc(A: TVarInt; B: TVarInt): TVarInt;
35 class operator Dec(A: TVarInt): TVarInt;
36 class operator Dec(A: TVarInt; B: TVarInt): TVarInt;
37 class operator Negative(A: TVarInt): TVarInt;
38 class operator Add(A: TVarInt; B: TVarInt): TVarInt;
39 class operator Multiply(A: TVarInt; B: TVarInt): TVarInt;
40 class operator IntDivide(A: TVarInt; B: TVarInt): TVarInt;
41 class operator Modulus(A: TVarInt; B: TVarInt): TVarInt;
42 class operator Subtract(A: TVarInt; B: TVarInt): TVarInt;
43 class operator Equal(A: TVarInt; B: TVarInt): Boolean;
44 class operator NotEqual(A: TVarInt; B: TVarInt): Boolean;
45 class operator GreaterThan(A: TVarInt; B: TVarInt): Boolean;
46 class operator GreaterThanOrEqual(A: TVarInt; B: TVarInt): Boolean;
47 class operator LessThan(A: TVarInt; B: TVarInt): Boolean;
48 class operator LessThanOrEqual(A: TVarInt; B: TVarInt): Boolean;
49 class operator LeftShift(A: TVarInt; B: TVarInt): TVarInt;
50 class operator RightShift(A: TVarInt; B: TVarInt): TVarInt;
51 class operator BitwiseAnd(A: TVarInt; B: TVarInt): TVarInt;
52 class operator BitwiseOr(A: TVarInt; B: TVarInt): TVarInt;
53 class operator BitwiseXor(A: TVarInt; B: TVarInt): TVarInt;
54 function GetByteSize: Integer;
55 function WriteToAddr(Ptr: Pointer): Integer;
56 function ReadFromAddr(Ptr: Pointer): Integer;
57 end;
58
59 { TVarUInt }
60
61 TVarUInt = record
62 private
63 public
64 Value: QWord;
65 class operator Implicit(A: TVarUInt): Int64;
66 class operator Implicit(A: TVarUInt): QWord;
67 class operator Implicit(A: TVarUInt): Integer;
68 class operator Implicit(A: TVarUInt): Byte;
69 class operator Implicit(A: TVarUInt): Char;
70 class operator Implicit(A: TVarUInt): TVarInt;
71 class operator Implicit(A: Byte): TVarUInt;
72 class operator Implicit(A: Integer): TVarUInt;
73 class operator Implicit(A: Int64): TVarUInt;
74 class operator Implicit(A: QWord): TVarUInt;
75 class operator Implicit(A: TVarInt): TVarUInt;
76 class operator Explicit(A: Byte): TVarUInt;
77 class operator Explicit(A: Integer): TVarUInt;
78 class operator Explicit(A: Int64): TVarUInt;
79 class operator Explicit(A: TVarUInt): Int64;
80 class operator Inc(A: TVarUInt): TVarUInt;
81 class operator Inc(A: TVarUInt; B: TVarInt): TVarUInt;
82 class operator Dec(A: TVarUInt): TVarUInt;
83 class operator Dec(A: TVarUInt; B: TVarUInt): TVarUInt;
84 class operator Negative(A: TVarUInt): TVarUInt;
85 class operator Add(A: TVarUInt; B: TVarUInt): TVarUInt;
86 class operator Multiply(A: TVarUInt; B: TVarUInt): TVarUInt;
87 class operator IntDivide(A: TVarUInt; B: TVarUInt): TVarUInt;
88 class operator Modulus(A: TVarUInt; B: TVarUInt): TVarUInt;
89 class operator Subtract(A: TVarUInt; B: TVarUInt): TVarUInt;
90 class operator Equal(A: TVarUInt; B: TVarUInt): Boolean;
91 class operator NotEqual(A: TVarUInt; B: TVarUInt): Boolean;
92 class operator GreaterThan(A: TVarUInt; B: TVarUInt): Boolean;
93 class operator GreaterThanOrEqual(A: TVarUInt; B: TVarUInt): Boolean;
94 class operator LessThan(A: TVarUInt; B: TVarUInt): Boolean;
95 class operator LessThanOrEqual(A: TVarUInt; B: TVarUInt): Boolean;
96 class operator LeftShift(A: TVarUInt; B: TVarUInt): TVarUInt;
97 class operator RightShift(A: TVarUInt; B: TVarUInt): TVarUInt;
98 class operator BitwiseAnd(A: TVarUInt; B: TVarUInt): TVarUInt;
99 class operator BitwiseOr(A: TVarUInt; B: TVarUInt): TVarUInt;
100 class operator BitwiseXor(A: TVarUInt; B: TVarUInt): TVarUInt;
101 function GetByteSize: Integer;
102 function WriteToAddr(Ptr: Pointer): Integer;
103 function ReadFromAddr(Ptr: Pointer): Integer;
104 end;
105
106function DecodeUnaryLength(Data: Byte): Integer;
107function GetUnaryLengthMask(Length: Integer): Byte;
108
109resourcestring
110 SVarIntOverflow = 'VarInt read overflow.';
111
112
113implementation
114
115function GetUnaryLengthMask(Length: Integer): Byte;
116begin
117 Result := ((1 shl (BitAlignment - Length)) - 1) xor $ff;
118end;
119
120function DecodeUnaryLength(Data: Byte): Integer;
121begin
122 Result := 1;
123 while (((Data shr (BitAlignment - Result)) and 1) = 1) and
124 (Result <= BitAlignment) do Inc(Result);
125end;
126
127{ TVarUInt }
128
129class operator TVarUInt.Implicit(A: TVarUInt): Int64;
130begin
131 Result := A.Value;
132end;
133
134class operator TVarUInt.Implicit(A: TVarUInt): QWord;
135begin
136 Result := A.Value;
137end;
138
139class operator TVarUInt.Implicit(A: TVarUInt): Integer;
140begin
141 Result := A.Value;
142end;
143
144class operator TVarUInt.Implicit(A: TVarUInt): Byte;
145begin
146 Result := A.Value;
147end;
148
149class operator TVarUInt.Implicit(A: TVarUInt): Char;
150begin
151 Result := Chr(A.Value);
152end;
153
154class operator TVarUInt.Implicit(A: TVarUInt): TVarInt;
155begin
156 Result.Value := A.Value;
157end;
158
159class operator TVarUInt.Implicit(A: Byte): TVarUInt;
160begin
161 Result.Value := A;
162end;
163
164class operator TVarUInt.Implicit(A: Integer): TVarUInt;
165begin
166 Result.Value := A;
167end;
168
169class operator TVarUInt.Implicit(A: Int64): TVarUInt;
170begin
171 Result.Value := A;
172end;
173
174class operator TVarUInt.Implicit(A: QWord): TVarUInt;
175begin
176 Result.Value := A;
177end;
178
179class operator TVarUInt.Implicit(A: TVarInt): TVarUInt;
180begin
181 Result.Value := A.Value;
182end;
183
184class operator TVarUInt.Explicit(A: Byte): TVarUInt;
185begin
186 Result.Value := A;
187end;
188
189class operator TVarUInt.Explicit(A: Integer): TVarUInt;
190begin
191 Result.Value := A;
192end;
193
194class operator TVarUInt.Explicit(A: Int64): TVarUInt;
195begin
196 Result.Value := A;
197end;
198
199class operator TVarUInt.Explicit(A: TVarUInt): Int64;
200begin
201 Result := A.Value;
202end;
203
204class operator TVarUInt.Inc(A: TVarUInt): TVarUInt;
205begin
206 Result.Value := A.Value + 1;
207end;
208
209class operator TVarUInt.Inc(A: TVarUInt; B: TVarInt): TVarUInt;
210begin
211 Result.Value := A.Value + B.Value;
212end;
213
214class operator TVarUInt.Dec(A: TVarUInt): TVarUInt;
215begin
216 Result.Value := A.Value - 1;
217end;
218
219class operator TVarUInt.Dec(A: TVarUInt; B: TVarUInt): TVarUInt;
220begin
221 Result.Value := A.Value - B.Value;
222end;
223
224class operator TVarUInt.Negative(A: TVarUInt): TVarUInt;
225begin
226 Result.Value := -A.Value;
227end;
228
229class operator TVarUInt.Add(A: TVarUInt; B: TVarUInt): TVarUInt;
230begin
231 Result.Value := A.Value + B.Value;
232end;
233
234class operator TVarUInt.Multiply(A: TVarUInt; B: TVarUInt): TVarUInt;
235begin
236 Result.Value := A.Value * B.Value;
237end;
238
239class operator TVarUInt.IntDivide(A: TVarUInt; B: TVarUInt): TVarUInt;
240begin
241 Result.Value := A.Value div B.Value;
242end;
243
244class operator TVarUInt.Modulus(A: TVarUInt; B: TVarUInt): TVarUInt;
245begin
246 Result.Value := A.Value mod B.Value;
247end;
248
249class operator TVarUInt.Subtract(A: TVarUInt; B: TVarUInt): TVarUInt;
250begin
251 Result.Value := A.Value - B.Value;
252end;
253
254class operator TVarUInt.Equal(A: TVarUInt; B: TVarUInt): Boolean;
255begin
256 Result := A.Value = B.Value;
257end;
258
259class operator TVarUInt.NotEqual(A: TVarUInt; B: TVarUInt): Boolean;
260begin
261 Result := A.Value <> B.Value;
262end;
263
264class operator TVarUInt.GreaterThan(A: TVarUInt; B: TVarUInt): Boolean;
265begin
266 Result := A.Value > B.Value;
267end;
268
269class operator TVarUInt.GreaterThanOrEqual(A: TVarUInt; B: TVarUInt): Boolean;
270begin
271 Result := A.Value >= B.Value;
272end;
273
274class operator TVarUInt.LessThan(A: TVarUInt; B: TVarUInt): Boolean;
275begin
276 Result := A.Value < B.Value;
277end;
278
279class operator TVarUInt.LessThanOrEqual(A: TVarUInt; B: TVarUInt): Boolean;
280begin
281 Result := A.Value <= B.Value;
282end;
283
284class operator TVarUInt.LeftShift(A: TVarUInt; B: TVarUInt): TVarUInt;
285begin
286 Result.Value := A.Value shl B.Value;
287end;
288
289class operator TVarUInt.RightShift(A: TVarUInt; B: TVarUInt): TVarUInt;
290begin
291 Result.Value := A.Value shr B.Value;
292end;
293
294class operator TVarUInt.BitwiseAnd(A: TVarUInt; B: TVarUInt): TVarUInt;
295begin
296 Result.Value := A.Value and B.Value;
297end;
298
299class operator TVarUInt.BitwiseOr(A: TVarUInt; B: TVarUInt): TVarUInt;
300begin
301 Result.Value := A.Value or B.Value;
302end;
303
304class operator TVarUInt.BitwiseXor(A: TVarUInt; B: TVarUInt): TVarUInt;
305begin
306 Result.Value := A.Value xor B.Value;
307end;
308
309function TVarUInt.GetByteSize: Integer;
310var
311 Length: Integer;
312begin
313 // Get bit length
314 Length := SizeOf(Value) * BitAlignment - 1;
315 while (((Value shr Length) and 1) = 0) and (Length > 0) do
316 Dec(Length);
317 Inc(Length);
318 Result := Ceil(Length / (BitAlignment - 1));
319end;
320
321function TVarUInt.WriteToAddr(Ptr: Pointer): Integer;
322var
323 Length: Byte;
324 Data: Byte;
325 I: Integer;
326 LengthMask: Byte;
327begin
328 Result := 0;
329
330 Length := GetByteSize;
331 LengthMask := GetUnaryLengthMask(Length);
332
333 // Copy data
334 for I := Length downto 1 do begin
335 Data := (Value shr (BitAlignment * (I - 1))) and $ff;
336 if I = Length then Data := (Data and
337 (LengthMask xor $ff)) or ((LengthMask shl 1) and $ff);
338 PByte(Ptr)^ := Data;
339 Inc(Ptr);
340 Inc(Result);
341 end;
342end;
343
344function TVarUInt.ReadFromAddr(Ptr: Pointer): Integer;
345var
346 Data: Byte;
347 Length: Integer;
348 I: Integer;
349 LengthMask: Byte;
350begin
351 Value := 0;
352 Result := 0;
353 Length := 1;
354 I := 0;
355 while I < Length do begin
356 Data := PByte(Ptr)^;
357 if I = 0 then begin
358 if Data = $ff then begin
359 Length := PByte(Ptr)^;
360 Inc(Ptr);
361 if Length > BitAlignment then
362 raise Exception.Create(SVarIntOverflow);
363 if Length > 0 then begin
364 Data := PByte(Ptr)^;
365 Inc(Ptr);
366 end else Data := 0;
367 end else begin
368 Length := DecodeUnaryLength(Data);
369 LengthMask := GetUnaryLengthMask(Length);
370 Data := Data and (LengthMask xor $ff);
371 end;
372 end;
373 Value := Value or (QWord(Data) shl ((Length - I - 1) * BitAlignment));
374 Inc(I);
375 Inc(Ptr);
376 end;
377 Result := Length;
378end;
379
380{ TVarInt }
381
382class operator TVarInt.Implicit(A: TVarInt): Int64;
383begin
384 Result := A.Value;
385end;
386
387class operator TVarInt.Implicit(A: TVarInt): QWord;
388begin
389 Result := A.Value;
390end;
391
392class operator TVarInt.Implicit(A: TVarInt): Integer;
393begin
394 Result := A.Value;
395end;
396
397class operator TVarInt.Implicit(A: TVarInt): Byte;
398begin
399 Result := A.Value;
400end;
401
402class operator TVarInt.Implicit(A: TVarInt): Char;
403begin
404 Result := Char(A.Value);
405end;
406
407class operator TVarInt.Implicit(A: Byte): TVarInt;
408begin
409 Result.Value := A;
410end;
411
412class operator TVarInt.Implicit(A: Integer): TVarInt;
413begin
414 Result.Value := A;
415end;
416
417class operator TVarInt.Implicit(A: Int64): TVarInt;
418begin
419 Result.Value := A;
420end;
421
422class operator TVarInt.Implicit(A: QWord): TVarInt;
423begin
424 Result.Value := A;
425end;
426
427class operator TVarInt.Explicit(A: Byte): TVarInt;
428begin
429 Result.Value := A;
430end;
431
432class operator TVarInt.Explicit(A: Integer): TVarInt;
433begin
434 Result.Value := A;
435end;
436
437class operator TVarInt.Explicit(A: Int64): TVarInt;
438begin
439 Result.Value := A;
440end;
441
442class operator TVarInt.Explicit(A: TVarInt): Int64;
443begin
444 Result := A.Value;
445end;
446
447class operator TVarInt.Inc(A: TVarInt): TVarInt;
448begin
449 Result.Value := A.Value + 1;
450end;
451
452class operator TVarInt.Inc(A: TVarInt; B: TVarInt): TVarInt;
453begin
454 Result := A.Value + B.Value;
455end;
456
457class operator TVarInt.Dec(A: TVarInt): TVarInt;
458begin
459 Result.Value := A.Value - 1;
460end;
461
462class operator TVarInt.Dec(A: TVarInt; B: TVarInt): TVarInt;
463begin
464 Result.Value := A.Value - B.Value;
465end;
466
467class operator TVarInt.Negative(A: TVarInt): TVarInt;
468begin
469 Result.Value := -A.Value;
470end;
471
472class operator TVarInt.Add(A: TVarInt; B: TVarInt): TVarInt;
473begin
474 Result.Value := A.Value + B.Value;
475end;
476
477class operator TVarInt.Multiply(A: TVarInt; B: TVarInt): TVarInt;
478begin
479 Result.Value := A.Value * B.Value;
480end;
481
482class operator TVarInt.IntDivide(A: TVarInt; B: TVarInt): TVarInt;
483begin
484 Result.Value := A.Value div B.Value;
485end;
486
487class operator TVarInt.Modulus(A: TVarInt; B: TVarInt): TVarInt;
488begin
489 Result.Value := A.Value mod B.Value;
490end;
491
492class operator TVarInt.Subtract(A: TVarInt; B: TVarInt): TVarInt;
493begin
494 Result.Value := A.Value - B.Value;
495end;
496
497class operator TVarInt.Equal(A: TVarInt; B: TVarInt): Boolean;
498begin
499 Result := A.Value = B.Value;
500end;
501
502class operator TVarInt.NotEqual(A: TVarInt; B: TVarInt): Boolean;
503begin
504 Result := A.Value <> B.Value;
505end;
506
507class operator TVarInt.GreaterThan(A: TVarInt; B: TVarInt): Boolean;
508begin
509 Result := A.Value > B.Value;
510end;
511
512class operator TVarInt.GreaterThanOrEqual(A: TVarInt; B: TVarInt): Boolean;
513begin
514 Result := A.Value >= B.Value;
515end;
516
517class operator TVarInt.LessThan(A: TVarInt; B: TVarInt): Boolean;
518begin
519 Result := A.Value < B.Value;
520end;
521
522class operator TVarInt.LessThanOrEqual(A: TVarInt; B: TVarInt): Boolean;
523begin
524 Result := A.Value <= B.Value;
525end;
526
527class operator TVarInt.LeftShift(A: TVarInt; B: TVarInt): TVarInt;
528begin
529 Result.Value := A.Value shl B.Value;
530end;
531
532class operator TVarInt.RightShift(A: TVarInt; B: TVarInt): TVarInt;
533begin
534 Result.Value := A.Value shr B.Value;
535end;
536
537class operator TVarInt.BitwiseAnd(A: TVarInt; B: TVarInt): TVarInt;
538begin
539 Result.Value := A.Value and B.Value;
540end;
541
542class operator TVarInt.BitwiseOr(A: TVarInt; B: TVarInt): TVarInt;
543begin
544 Result.Value := A.Value or B.Value;
545end;
546
547class operator TVarInt.BitwiseXor(A: TVarInt; B: TVarInt): TVarInt;
548begin
549 Result.Value := A.Value xor B.Value;
550end;
551
552function TVarInt.GetByteSize: Integer;
553var
554 UInt: TVarUInt;
555begin
556 UInt := Value;
557 Result := UInt.GetByteSize;
558end;
559
560function TVarInt.WriteToAddr(Ptr: Pointer): Integer;
561var
562 UInt: TVarUInt;
563begin
564 UInt := Value;
565 Result := UInt.WriteToAddr(Ptr);
566end;
567
568function TVarInt.ReadFromAddr(Ptr: Pointer): Integer;
569var
570 UInt: TVarUInt;
571begin
572 Result := UInt.ReadFromAddr(Ptr);
573 Value := UInt;
574end;
575
576
577end.
578
Note: See TracBrowser for help on using the repository browser.