/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StBase.pas
ViewVC logotype

Contents of /dao/DelphiScanner/Components/tpsystools_4.04/source/StBase.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 40195 byte(s)
Added tpsystools component
1 // Upgraded to Delphi 2009: Sebastian Zierer
2
3 (* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is TurboPower SysTools
17 *
18 * The Initial Developer of the Original Code is
19 * TurboPower Software
20 *
21 * Portions created by the Initial Developer are Copyright (C) 1996-2002
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * ***** END LICENSE BLOCK ***** *)
27
28 {*********************************************************}
29 {* SysTools: StBase.pas 4.04 *}
30 {*********************************************************}
31 {* SysTools: Base unit for SysTools *}
32 {*********************************************************}
33
34 {$I StDefine.inc}
35
36 unit StBase;
37
38 interface
39
40 uses
41 Windows,
42 Classes, SysUtils, Messages, StdCtrls,
43
44 StConst;
45
46 const
47 {.Z+}
48 StMaxBlockSize = MaxLongInt;
49 {.Z-}
50
51 type
52 {!!.01 - moved from StBase.pas }
53 TStLineTerminator = ( {possible line terminators...}
54 ltNone, {..no terminator, ie fixed length lines}
55 ltCR, {..carriage return (#13)}
56 ltLF, {..line feed (#10)}
57 ltCRLF, {..carriage return/line feed (#13/#10)}
58 ltOther); {..another character}
59 {!!.01 - end moved }
60
61 type
62 {$IFDEF CBuilder}
63 TStHwnd = Integer;
64 {$ELSE}
65 TStHwnd = HWND;
66 {$ENDIF}
67
68 {-SysTools exception class tree}
69 type
70 EStException = class(Exception) {ancestor to all SysTools exceptions}
71 protected {private}
72 FErrorCode : Longint;
73
74 public
75 constructor CreateResTP(Ident : LongInt; Dummy : Word);
76 constructor CreateResFmtTP(Ident : Longint; const Args : array of const;
77 Dummy : Word);
78 property ErrorCode : LongInt
79 read FErrorCode
80 write FErrorCode;
81 end;
82 EStExceptionClass = class of EStException;
83
84 EStContainerError = class(EStException); {container exceptions}
85 EStSortError = class(EStException); {sorting exceptions}
86 EStRegIniError = class(EStException); {registry/INI file exceptions}
87 EStBCDError = class(EStException); {Bcd exceptions}
88 EStStringError = class(EStException); {String class exceptions}
89 EStVersionInfoError = class(EStException); {Version info exception}
90 EStNetException = class(EStException); {Network exception}
91 EStBarCodeError = class(EStException); {BarCode exception}
92 EStPNBarCodeError = class(EStException); {PostNet BarCode exception}
93 EStStatError = class(EStException); {statistics exceptions}
94 EStFinError = class(EStException); {Financial exceptions}
95 EStMimeError = class(EStException); {Mime exceptions}
96 EStToHTMLError = class(EStException); {ToHTML exceptions}
97 EStSpawnError = class(EStException); {SpawnApplication errors}
98 EStMMFileError = class(EStException); {MemoryMappedFile errors}
99 EStBufStreamError =class(EStException); {Buffered stream errors}
100 EStRegExError = class(EStException); {RegEx errors}
101 EStDecMathError = class(EStException); {Decimal math errors}
102 EStPRNGError = class(EStException); {Random number errors}
103
104 EStExprError = class(EStException) {expression evaluator exceptions}
105 protected {private}
106 FErrorCol : Integer;
107 public
108 constructor CreateResTPCol(Ident : Longint; Column : Integer; Dummy : Integer);
109 property ErrorColumn : Integer
110 {-Returns the string position at the start of the token where
111 the error was detected}
112 read FErrorCol;
113 end;
114
115
116 const
117 {.Z+}
118 StMaxFileLen = 260;
119
120 StRLEMaxCount = 127; { Used by RLE }
121 StRLERunMode = $80; { Used by RLE }
122 {.Z-}
123
124 const
125 {.Z+}
126 {used by CompareLetterSets for estimating word similarity}
127 StLetterValues : array['A'..'Z'] of Byte = (
128 3 {A} , 6 {B} , 5 {C} , 4 {D} , 3 {E} , 5 {F} , 5 {G} , 4 {H} , 3 {I} ,
129 8 {J} , 7 {K} , 4 {L} , 5 {M} , 3 {N} , 3 {O} , 5 {P} , 7 {Q} , 4 {R} ,
130 3 {S} , 3 {T} , 4 {U} , 6 {V} , 5 {W} , 8 {X} , 8 {Y} , 9 {Z} );
131
132 StHexDigits : array[0..$F] of AnsiChar = '0123456789ABCDEF';
133 DosDelimSet : set of AnsiChar = ['\', ':', #0];
134 {$IFDEF VERSION4} { Delphi/Builder 3 doesn't like widestring typed constants }
135 StHexDigitsW : WideString = '0123456789ABCDEF';
136 DosDelimSetW : WideString = '\:';
137 {$ENDIF}
138
139 {.Z-}
140
141 type
142 {.Z+}
143 TSmallArrayA = array[0..StMaxFileLen-1] of AnsiChar;
144 TSmallArray = array[0..StMaxFileLen-1] of Char;
145 BTable = array[0..255] of Byte; {Table used by Boyer-Moore search routines}
146 {$IFDEF UNICODE}
147 BTableU = array[0..$FFFF] of Byte;
148 {$ENDIF}
149 {.Z-}
150
151 type
152 {.Z+}
153 PDouble = ^Double;
154 TDoubleArray = array[0..(stMaxBlockSize div SizeOf(Double))-1] of Double;
155 PDoubleArray = ^TDoubleArray;
156 TIntArray = array[0..(StMaxBlockSize div SizeOf(Integer))-1] of Integer;
157 PIntArray = ^TIntArray;
158 {.Z-}
159
160 type
161 {the SysTools floating point type}
162 {$IFOPT N+}
163 TStFloat = Extended;
164 {$ELSE}
165 TStFloat = Real;
166 {$ENDIF}
167
168 const
169 WMCOPYID : DWORD = $AFAF;
170
171 type
172 TStNode = class(TPersistent)
173 {.Z+}
174 protected {private}
175 FData : Pointer;
176 {.Z-}
177 public
178 constructor Create(AData : Pointer);
179 virtual;
180 property Data : Pointer
181 read FData
182 write FData;
183 end;
184
185 {.Z+}
186 TStNodeClass = class of TStNode;
187 {.Z-}
188
189 TStContainer = class;
190
191 TCompareFunc =
192 function(Data1, Data2 : Pointer) : Integer;
193 TStCompareEvent =
194 procedure(Sender : TObject; Data1, Data2 : Pointer; var Compare : Integer)
195 of object;
196
197 TDisposeDataProc =
198 procedure(Data : Pointer);
199 TStDisposeDataEvent =
200 procedure(Sender : TObject; Data : Pointer)
201 of object;
202
203 TLoadDataFunc =
204 function(Reader : TReader) : Pointer;
205 TStLoadDataEvent =
206 procedure(Sender : TObject; Reader : TReader; var Data : Pointer)
207 of object;
208
209 TStoreDataProc =
210 procedure(Writer : TWriter; Data : Pointer);
211 TStStoreDataEvent =
212 procedure(Sender : TObject; Writer : TWriter; Data : Pointer)
213 of object;
214
215 TStringCompareFunc =
216 function(const String1, String2 : string) : Integer;
217 TStStringCompareEvent =
218 procedure(Sender : TObject; const String1, String2 : string; var Compare : Integer)
219 of object;
220
221 TUntypedCompareFunc =
222 function(const El1, El2) : Integer;
223 TStUntypedCompareEvent =
224 procedure(Sender : TObject; const El1, El2; var Compare : Integer)
225 of object;
226
227 TIterateFunc =
228 function(Container : TStContainer; Node : TStNode; OtherData : Pointer) : Boolean;
229 TIteratePointerFunc =
230 function(Container : TStContainer; Data, OtherData : Pointer) : Boolean;
231 TIterateUntypedFunc =
232 function(Container : TStContainer; var Data; OtherData : Pointer) : Boolean;
233
234 TStContainer = class(TPersistent)
235 {.Z+}
236 protected {private}
237 {property instance variables}
238 FCompare : TCompareFunc;
239 FDisposeData : TDisposeDataProc;
240 FLoadData : TLoadDataFunc;
241 FStoreData : TStoreDataProc;
242
243 {event variables}
244 FOnCompare : TStCompareEvent;
245 FOnDisposeData : TStDisposeDataEvent;
246 FOnLoadData : TStLoadDataEvent;
247 FOnStoreData : TStStoreDataEvent;
248
249 {private instance variables}
250 {$IFDEF ThreadSafe}
251 conThreadSafe : TRTLCriticalSection;
252 {$ENDIF}
253
254 procedure SetCompare(C : TCompareFunc);
255 procedure SetDisposeData(D : TDisposeDataProc);
256 procedure SetLoadData(L : TLoadDataFunc);
257 procedure SetStoreData(S : TStoreDataProc);
258
259 protected
260 conNodeClass : TStNodeClass;
261 conNodeProt : Integer;
262 FCount : Longint;
263
264 {protected undocumented methods}
265 function AssignPointers(Source : TPersistent; AssignData : TIteratePointerFunc) : boolean;
266 function AssignUntypedVars(Source : TPersistent; AssignData : TIterateUntypedFunc) : boolean;
267 procedure ForEachPointer(Action : TIteratePointerFunc; OtherData : Pointer);
268 virtual;
269 procedure ForEachUntypedVar(Action : TIterateUntypedFunc; OtherData : pointer);
270 virtual;
271 procedure GetArraySizes(var RowCount, ColCount, ElSize : Cardinal);
272 virtual;
273 procedure SetArraySizes(RowCount, ColCount, ElSize : Cardinal);
274 virtual;
275 function StoresPointers : boolean;
276 virtual;
277 function StoresUntypedVars : boolean;
278 virtual;
279
280 {protected documented}
281 procedure IncNodeProtection;
282 {-Prevent container Destroy from destroying its nodes}
283 procedure DecNodeProtection;
284 {-Allow container Destroy to destroy its nodes}
285 procedure EnterCS;
286 {-Enter critical section for this instance}
287 procedure LeaveCS;
288 {-Leave critical section for this instance}
289 {.Z-}
290 public
291 constructor CreateContainer(NodeClass : TStNodeClass; Dummy : Integer);
292 {-Create an abstract container (called by descendants)}
293 destructor Destroy;
294 override;
295 {-Destroy a collection, and perhaps its nodes}
296 procedure Clear;
297 virtual; abstract;
298 {-Remove all elements from collection}
299 procedure DisposeNodeData(P : TStNode);
300 {-Destroy the data associated with a node}
301
302 {wrapper methods for using events or proc/func pointers}
303 function DoCompare(Data1, Data2 : Pointer) : Integer;
304 virtual;
305 procedure DoDisposeData(Data : Pointer);
306 virtual;
307 function DoLoadData(Reader : TReader) : Pointer;
308 virtual;
309 procedure DoStoreData(Writer : TWriter; Data : Pointer);
310 virtual;
311
312 procedure LoadFromFile(const FileName : string);
313 dynamic;
314 {-Create a container and its data from a file}
315 procedure LoadFromStream(S : TStream);
316 dynamic; abstract;
317 {-Create a container and its data from a stream}
318 procedure StoreToFile(const FileName : string);
319 dynamic;
320 {-Create a container and its data from a file}
321 procedure StoreToStream(S : TStream);
322 dynamic; abstract;
323 {-Write a container and its data to a stream}
324
325 property Count : LongInt
326 {-Return the number of elements in the collection}
327 read FCount;
328
329 property Compare : TCompareFunc
330 {-Set or read the node comparison function}
331 read FCompare
332 write SetCompare;
333
334 property DisposeData : TDisposeDataProc
335 {-Set or read the node data dispose function}
336 read FDisposeData
337 write SetDisposeData;
338
339 property LoadData : TLoadDataFunc
340 {-Set or read the node data load function}
341 read FLoadData
342 write SetLoadData;
343
344 property StoreData : TStoreDataProc
345 {-Set or read the node data load function}
346 read FStoreData
347 write SetStoreData;
348
349 {events}
350 property OnCompare : TStCompareEvent
351 read FOnCompare
352 write FOnCompare;
353
354 property OnDisposeData : TStDisposeDataEvent
355 read FOnDisposeData
356 write FOnDisposeData;
357
358 property OnLoadData : TStLoadDataEvent
359 read FOnLoadData
360 write FOnLoadData;
361
362 property OnStoreData : TStStoreDataEvent
363 read FOnStoreData
364 write FOnStoreData;
365 end;
366
367 TAssignRowData = record
368 RowNum : Integer;
369 Data : array [0..0] of Byte;
370 end;
371
372 {.Z+}
373 { base component for SysTools non-visual components}
374 TStComponent = class(TComponent)
375 protected {private}
376 function GetVersion : string;
377 procedure SetVersion(const Value : string);
378
379 published
380 property Version : string
381 read GetVersion
382 write SetVersion
383 stored False;
384 end;
385
386 { base component for TStExpressionEdit component }
387 TStBaseEdit = class(TEdit)
388 protected {private}
389 function GetVersion : string;
390 procedure SetVersion(const Value : string);
391
392 published
393 property Version : string
394 read GetVersion
395 write SetVersion
396 stored False;
397 end;
398 {.Z-}
399
400 {---Generic node routines---}
401 function DestroyNode(Container : TStContainer; Node : TStNode;
402 OtherData : Pointer) : Boolean;
403 {-Generic function to pass to iterator to destroy a container node}
404
405
406 {---WIN32 short string routines---}
407 {$IFDEF WStrings}
408 function AnsiUpperCaseShort32(const S : string) : string;
409 {-Ansi uppercase for H- strings in WIN32}
410
411 function AnsiCompareTextShort32(const S1, S2: string): Integer;
412 {-Case-insensitive compare function for H- strings in WIN32}
413
414 function AnsiCompareStrShort32(const S1, S2: string): Integer;
415 {-Case-sensitive compare function for H- strings in WIN32}
416 {$ENDIF}
417
418
419 {.Z+}
420 {---Huge memory routines---}
421 function HugeCompressRLE(const InBuffer; InLen : Longint;
422 var OutBuffer) : Longint;
423 {-Run length encode a buffer}
424
425 function HugeDecompressRLE(const InBuffer; InLen : Longint;
426 var OutBuffer; OutLen : LongInt) : Longint;
427 {-Run length decode a buffer}
428
429 procedure HugeFillChar(var Dest; Count : Longint; Value : Byte);
430 {-Fill huge memory block with byte value}
431
432 procedure HugeFillStruc(var Dest; Count : Longint;
433 const Value; ValSize : Cardinal);
434 {-Fill huge memory block with structure value}
435
436 procedure HugeMove(const Src; var Dest; Count : LongInt);
437 {-Copy huge memory block to another}
438
439 procedure HugeGetMem(var P : Pointer; Size : LongInt);
440 {-Get huge memory block allocation}
441
442 procedure HugeFreeMem(var P : Pointer; Size : LongInt);
443 {-Free huge memory block allocation}
444 {.Z-}
445
446
447 {---General purpose character manipulation---}
448
449 function Upcase(C : AnsiChar) : AnsiChar; overload;
450 function Upcase(C : WideChar) : WideChar; overload;
451 {-Return the uppercase of a character. Provides international character
452 support.}
453
454 function LoCase(C : AnsiChar) : AnsiChar; overload;
455 function LoCase(C : WideChar) : WideChar; overload;
456 {-Return the lowercase of a character. Provides international character
457 support.}
458
459 {---General comparison and searching---}
460
461 function CompareLetterSets(Set1, Set2 : LongInt) : Cardinal;
462 {-Return the sum of the values of the letters common to Set1 and Set2.}
463
464 function CompStruct(const S1, S2; Size : Cardinal) : Integer;
465 {-Compare two fixed size structures.}
466
467 function Search(const Buffer; BufLength : Cardinal; const Match;
468 MatLength : Cardinal; var Pos : Cardinal) : Boolean;
469 {-Search a buffer for the specified pattern of bytes.}
470
471 function SearchUC(const Buffer; BufLength : Cardinal; const Match;
472 MatLength : Cardinal; var Pos : Cardinal) : Boolean;
473 {-Search a buffer for a specified pattern of bytes. This search is not case
474 sensitive.}
475
476
477 {---Miscellaneous---}
478
479 {.Z+}
480 function IsOrInheritsFrom(Root, Candidate : TClass) : boolean;
481 {-Return true if the classes are equal or Candidate is a descendant of Root}
482
483 procedure RaiseContainerError(Code : longint);
484 {-Internal routine: raise an exception for a container}
485
486 procedure RaiseContainerErrorFmt(Code : Longint; Data : array of const);
487 {-Internal routine: raise an exception for a container}
488
489 function ProductOverflow(A, B : LongInt) : Boolean;
490 {-Return True if A*B exceeds MaxLongInt}
491
492 {$IFNDEF HStrings}
493 function StNewStr(S : string) : PShortString;
494 {-Allocate a short string on the heap}
495
496 procedure StDisposeStr(PS : PShortString);
497 {-Deallocate a short string from the heap}
498 {$ENDIF}
499 {.Z-}
500
501
502 {---primitives for converting strings to integers}
503 procedure ValLongInt(S : ShortString; var LI : Longint; var ErrorCode : integer);
504 procedure ValSmallint(const S : ShortString; var SI : smallint; var ErrorCode : integer);
505 procedure ValWord(const S : ShortString; var Wd : word; var ErrorCode : integer);
506
507 {.Z+}
508 {general routine to raise a specific class of SysTools exception}
509 procedure RaiseStError(ExceptionClass : EStExceptionClass; Code : LongInt);
510 {.Z-}
511
512 {.Z+}
513 {general routines to raise a specific Win32 exception in SysTools}
514 procedure RaiseStWin32Error(ExceptionClass : EStExceptionClass; Code : LongInt);
515 procedure RaiseStWin32ErrorEx(ExceptionClass : EStExceptionClass; Code : LongInt; Info : string);
516 {.Z-}
517
518 {$IFDEF VERSION3ONLY}
519 var
520 StHexDigitsW : WideString;
521 DosDelimSetW : WideString;
522 {$ENDIF}
523
524
525 implementation
526
527 procedure RaiseStError(ExceptionClass : EStExceptionClass; Code : LongInt);
528 var
529 E : EStException;
530 begin
531 E := ExceptionClass.CreateResTP(Code, 0);
532 E.ErrorCode := Code;
533 raise E;
534 end;
535
536 procedure RaiseStWin32Error(ExceptionClass : EStExceptionClass; Code : LongInt);
537 var
538 E : EStException;
539 begin
540 E := ExceptionClass.Create(SysErrorMessage(Code));
541 E.ErrorCode := Code;
542 raise E;
543 end;
544
545 procedure RaiseStWin32ErrorEx(ExceptionClass : EStExceptionClass; Code : LongInt;
546 Info : string);
547 var
548 E : EStException;
549 begin
550 E := ExceptionClass.Create(SysErrorMessage(Code) + ' [' + Info + ']');
551 E.ErrorCode := Code;
552 raise E;
553 end;
554
555 constructor EStException.CreateResTP(Ident : LongInt; Dummy : Word);
556 begin
557 inherited Create(SysToolsStr(Ident));
558 end;
559
560 constructor EStException.CreateResFmtTP(Ident : Longint;
561 const Args : array of const; Dummy : Word);
562 begin
563 inherited CreateFmt(SysToolsStr(Ident), Args);
564 end;
565
566 constructor EStExprError.CreateResTPCol(Ident : Longint; Column : Integer; Dummy : Integer);
567 begin
568 inherited CreateResTP(Ident, 0);
569
570 FErrorCol := Column;
571 end;
572
573
574 function AbstractCompare(Data1, Data2 : Pointer) : Integer; far;
575 begin
576 raise ESTContainerError.CreateResTP(stscNoCompare, 0);
577 end;
578
579 {$IFDEF WStrings}
580 function AnsiCompareStrShort32(const S1, S2: AnsiString): Integer; assembler;
581 asm
582 push esi
583 push edi
584 mov esi,S1
585 mov edi,S2
586 xor eax,eax
587 xor edx,edx
588 xor ecx,ecx
589 mov dl,[esi]
590 inc esi
591 mov dh,[edi]
592 inc edi
593 mov cl,dl
594 cmp cl,dh
595 jbe @1
596 mov cl,dh
597 @1:
598 or ecx, ecx
599 je @CheckLengths
600 repe cmpsb
601 jb @LT
602 ja @GT
603 @CheckLengths:
604 cmp dl, dh
605 je @Exit
606 jb @LT
607 @GT:
608 inc eax
609 inc eax
610 @LT:
611 dec eax
612 @Exit:
613 pop edi
614 pop esi
615 end;
616
617 function AnsiCompareTextShort32(const S1, S2: string): Integer;
618 begin
619 Result := AnsiCompareStrShort32(AnsiUpperCaseShort32(S1),
620 AnsiUpperCaseShort32(S2));
621 end;
622
623 function AnsiUpperCaseShort32(const S : string) : string;
624 begin
625 Result := S;
626 AnsiUpperBuff(PChar(@Result[1]), Length(S));
627 end;
628 {$ENDIF}
629
630 function DestroyNode(Container : TStContainer;
631 Node : TStNode;
632 OtherData : Pointer) : Boolean;
633 begin
634 Container.DisposeNodeData(Node);
635 Node.Free;
636 Result := True;
637 end;
638
639 procedure HugeFillChar(var Dest; Count : Longint; Value : Byte);
640 begin
641 FillChar(Dest, Count, Value);
642 end;
643
644 function HugeCompressRLE(const InBuffer; InLen : Longint;
645 var OutBuffer) : Longint;
646 {assumes OutBuffer is at least InLen long}
647 {returns -1 if InLen <= 1 or if output length would exceed InLen}
648 {otherwise returns compressed length}
649 {does not initialize OutBuffer if the result is -1}
650 asm
651 {InBuffer = eax, InLen = edx, OutBuffer = ecx}
652 push ebx
653 push esi
654 push edi
655
656 push OutBuffer {save output base for later}
657
658 cmp InLen,1
659 jle @A {can't compress if input length <= 1}
660
661 mov esi,InBuffer {esi = current input offset}
662 mov edi,OutBuffer {edi = current output offset}
663 mov eax,InLen
664 mov ebx,edi {ebx = control byte offset}
665 mov byte ptr [ebx],0 {reset first control byte}
666 mov edx,edi
667 add edx,eax {edx = endpoint of output buffer}
668 dec edx {reserve an extra space for control byte}
669 mov ecx,esi
670 add ecx,eax {ecx = endpoint of input buffer}
671 dec ecx {reduce by one for convenience below}
672 dec esi {decrement first time through}
673
674 @1: inc esi {next input byte}
675 cmp esi,ecx
676 ja @9 {exit at end of input}
677 mov al,[esi] {load compare byte}
678 jae @5 {can't be a match if on last byte of input}
679 cmp [esi+1],al {is it a run?}
680 jne @5 {jump if not}
681
682 {starting a run}
683 mov ebx,edi {start a new control sequence}
684 mov byte ptr [ebx],1 {first byte in run}
685 mov [ebx+1],al {store run byte}
686 @2: inc esi {next input byte}
687 cmp esi,ecx {end of input?}
688 ja @3 {exit this loop if so}
689 cmp [esi],al {next byte a match?}
690 jne @3 {jump if not a run}
691 cmp byte ptr [ebx],StRLEMaxCount {max run length?}
692 je @3 {exit this loop if so}
693 inc byte ptr [ebx] {increment control byte}
694 jmp @2 {stay in the run loop}
695 @3: or byte ptr [ebx],StRLERunMode {flag control byte as a run}
696 inc edi {step past control and run bytes}
697 inc edi
698 cmp edi,edx {filled up output buffer?}
699 jae @A {jump if so}
700 mov ebx,edi {set up new control byte}
701 mov byte ptr [ebx],0 {first byte in non-run}
702 dec esi {back up one byte}
703 jmp @1 {classify run status again}
704
705 @5: {not a run}
706 cmp edi,ebx {the start of a new non-run?}
707 ja @6 {jump if not}
708 inc edi {next output position, guaranteed ok}
709 @6: cmp byte ptr [ebx],StRLEMaxCount {max non-run length?}
710 jb @7
711 mov ebx,edi {start a new control sequence}
712 mov byte ptr [ebx],0 {reset control byte}
713 inc edi {next output position}
714 cmp edi,edx {filled up output buffer?}
715 jae @A {jump if so}
716 @7: inc byte ptr [ebx] {increment control byte}
717 mov [edi],al {copy input byte}
718 inc edi {next output position}
719 cmp edi,edx {filled up output buffer?}
720 jae @A {jump if so}
721 jmp @1 {back to outer loop}
722
723 @9: pop eax {get output base again}
724 sub edi,eax {get output length}
725 jmp @B
726 @A: pop eax {balance stack}
727 mov edi,-1 {could not compress input}
728 @B: mov eax,edi {return output length}
729
730 pop edi
731 pop esi
732 pop ebx
733 end;
734
735 function HugeDecompressRLE(const InBuffer; InLen : Longint;
736 var OutBuffer; OutLen : LongInt) : Longint;
737 {returns -1 if InLen is <= 0 or output length > OutLen}
738 {otherwise returns decompressed length}
739 asm
740 {InBuffer = eax, InLen = edx, OutBuffer = ecx, OutLen = stack}
741 push ebx
742 push esi
743 push edi
744
745 push OutBuffer {save output base for later}
746
747 cmp InLen,0 {anything to decompress?}
748 jle @A {jump if not}
749
750 mov esi,InBuffer {esi = current input offset}
751 mov edi,OutBuffer {edi = current output offset}
752 mov ebx,esi
753 add ebx,InLen {ebx = endpoint of input buffer}
754 mov edx,OutLen {edx = space free in output buffer}
755
756 @1: cmp esi,ebx {end of input?}
757 jae @9 {jump if so}
758 mov al,[esi] {get next control byte}
759 inc esi {move to run data byte}
760 mov cl,al
761 and ecx,StRLEMaxCount{ecx = bytes for output}
762 sub edx,ecx {is there space?}
763 jc @A {jump if not}
764 test al,StRLERunMode {is it a run?}
765 jz @5 {jump if not}
766
767 {a run}
768 mov al,[esi] {get run data}
769 inc esi {next input position}
770 rep stosb {store it}
771 jmp @1 {loop}
772
773 @5: {not a run}
774 rep movsb {copy them}
775 jmp @1 {loop}
776
777 @9: pop eax {get output base again}
778 sub edi,eax {get output length}
779 jmp @B
780 @A: pop eax {balance stack}
781 mov edi,-1 {could not decompress input}
782 @B: mov eax,edi {return output length}
783
784 pop edi
785 pop esi
786 pop ebx
787 end;
788
789 procedure HugeFillStruc(var Dest; Count : Longint;
790 const Value; ValSize : Cardinal); assembler;
791 register;
792 asm
793 {eax = Dest, edx = Count, ecx = Value}
794 push ebx
795 push esi
796 push edi
797 mov edi,Dest {edi -> Dest}
798 mov eax,Value {eax -> Value}
799 {mov edx,Count} {edx = Count, register parameter}
800 mov ebp,ValSize {ebp = ValSize}
801 jmp @2
802 @1: mov ecx,ebp {ecx = element ValSize}
803 mov esi,eax {esi -> Value}
804 mov bx,cx
805 shr ecx,2
806 rep movsd
807 mov cx,bx
808 and cx,3
809 rep movsb
810 @2: sub edx,1 {decrement elements left to fill}
811 jnc @1 {loop for all elements}
812 pop edi
813 pop esi
814 pop ebx
815 end;
816
817 procedure HugeFreeMem(var P : Pointer; Size : LongInt);
818 begin
819 if Assigned(P) then begin
820 FreeMem(P, Size);
821 P := nil;
822 end;
823 end;
824
825 procedure HugeGetMem(var P : Pointer; Size : LongInt);
826 begin
827 GetMem(P, Size);
828 end;
829
830 procedure HugeMove(const Src; var Dest; Count : LongInt);
831 begin
832 Move(Src, Dest, Count);
833 end;
834
835 function UpCase(C: AnsiChar) : AnsiChar;
836 asm
837 and eax, 0FFh
838 push eax
839 call CharUpperA
840 end;
841
842 function UpCase(C: WideChar) : WideChar;
843 asm
844 and eax, 0FFFFh
845 push eax
846 call CharUpperW
847 end;
848
849 function LoCase(C: AnsiChar) : AnsiChar; assembler;
850 asm
851 and eax, 0FFh
852 push eax
853 call CharLowerA
854 end;
855
856 function LoCase(C: WideChar) : WideChar; assembler;
857 asm
858 and eax, 0FFFFh
859 push eax
860 call CharLowerW
861 end;
862
863
864 function ProductOverflow(A, B : LongInt) : Boolean;
865 register;
866 asm
867 mov ecx,False
868 {A is in eax already, B is in edx already}
869 imul eax,edx
870 jno @1
871 mov ecx,True
872 @1:
873 mov eax,ecx
874 end;
875
876 function CompareLetterSets(Set1, Set2 : LongInt) : Cardinal;
877 {-Returns the sum of the values of the letters common to Set1 and Set2.}
878 asm
879 push ebx { Save registers }
880 push edi
881 and eax, edx { EAX = EAX and EDX }
882 xor edx, edx { Zero EDX }
883 mov ecx, ('Z'-'A') { Set up counter }
884 mov edi, offset StLetterValues{ Point EBX to table }
885 xor ebx, ebx
886 jmp @@Start
887
888 @@Next:
889 dec ecx { Decrement counter }
890 shl eax, 1 { Shift next bit into position }
891
892 @@Start:
893 test eax, 2000000h { Test 26th bit }
894 jnz @@Add { If set, add corresponding letter value }
895 or ecx, ecx
896 jz @@Exit { Done if ECX is zero }
897 jmp @@Next { Test next bit }
898
899 @@Add:
900 mov bl, [ecx+edi] { Do table lookup }
901 add edx, ebx { Add value to result }
902 or ecx, ecx
903 jnz @@Next { Test next bit }
904
905 @@Exit:
906 mov eax, edx { Move EDX to result }
907 pop edi { Restore registers }
908 pop ebx
909 end;
910
911 function CompStruct(const S1, S2; Size : Cardinal) : Integer;
912 {-Compare two fixed size structures}
913 asm
914 push edi
915 push esi
916 mov esi, eax
917 mov edi, edx
918 xor eax, eax
919 or ecx, ecx
920 jz @@CSDone
921
922 repe cmpsb
923 je @@CSDone
924
925 inc eax
926 ja @@CSDone
927 or eax, -1
928
929 @@CSDone:
930 pop esi
931 pop edi
932 end;
933
934
935 function Search(const Buffer; BufLength : Cardinal; const Match;
936 MatLength : Cardinal; var Pos : Cardinal) : Boolean;
937 asm
938 push ebx
939 push edi
940 push esi
941
942 cld
943 mov edi, eax
944 mov ebx, eax
945 mov esi, ecx
946 mov ecx, edx
947 mov edx, MatLength
948 or edx, edx
949 jz @@NotFound
950
951 mov al, [esi]
952 inc esi
953 dec edx
954 sub ecx, edx
955 jbe @@NotFound
956
957 @@Next:
958 repne scasb
959 jne @@NotFound
960 or edx, edx
961 jz @@Found
962
963 push ecx
964 push edi
965 push esi
966
967 mov ecx, edx
968 repe cmpsb
969
970 pop esi
971 pop edi
972 pop ecx
973
974 jne @@Next {Try again if no match}
975
976 {Calculate number of bytes searched and return}
977 @@Found:
978 mov esi, Pos
979 dec edi
980 sub edi, ebx
981 mov eax, 1
982 mov [esi], edi
983 jmp @@SDone
984
985 {Match was not found}
986 @@NotFound:
987 xor eax, eax
988
989 @@SDone:
990 pop esi
991 pop edi
992 pop ebx
993 end;
994
995 function SearchUC(const Buffer; BufLength : Cardinal; const Match;
996 MatLength: Cardinal; var Pos : Cardinal) : Boolean;
997
998 asm
999 push ebx { Save registers }
1000 push edi
1001 push esi
1002 push eax
1003
1004 mov edi, eax { EDI = ^Buffer }
1005 mov esi, ecx { ESI = ^Match }
1006 mov ecx, edx { ECX = BufLength }
1007 mov edx, MatLength { EDX = MatLength }
1008 xor ebx, ebx { EBX will be used for comparison }
1009 or edx, edx { Is MatLength 0? }
1010 jz @@NotFound
1011
1012 mov al, [esi] { Get first character }
1013 inc esi
1014 and eax, 0FFh { Zero all but lower byte }
1015
1016 push ecx { Save registers }
1017 push edx
1018 push eax
1019 call CharUpper { Upcase character }
1020 pop edx
1021 pop ecx
1022
1023 mov bl, al { Move uppercased char to BL }
1024 dec edx { Dec MatLength }
1025 sub ecx, edx { Is MatLength > BufLength? }
1026 jbe @@NotFound
1027
1028 @@Next:
1029 mov al, [edi]
1030 inc edi
1031
1032 push ecx { Save registers }
1033 push edx
1034 push eax
1035 call CharUpper { Upcase character in buffer }
1036 pop edx
1037 pop ecx
1038
1039 cmp bl, al { Match? }
1040 je @@CompRest { Compare rest of string }
1041 @@RestNoMatch:
1042 dec ecx { End of string? }
1043 jnz @@Next { Try next char }
1044 jmp @@NotFound { Done if not found }
1045
1046 @@CompRest:
1047 or edx, edx { Was there only one character? }
1048 jz @@Found { If so, we're done }
1049
1050 push ebx { Save registers }
1051 push ecx
1052 push edi
1053 push esi
1054
1055 mov ecx, edx
1056
1057 @@CompLoop:
1058 mov al, [esi]
1059 inc esi
1060
1061 push ecx { Save registers }
1062 push edx
1063 push eax
1064 call CharUpper { Upcase character in buffer }
1065
1066 mov bl, al
1067 mov al, [edi]
1068 inc edi
1069
1070 push eax
1071 call CharUpper { Upcase character in buffer }
1072 pop edx
1073 pop ecx
1074
1075 cmp bl, al
1076 jne @@NoComp
1077 dec ecx
1078 jnz @@CompLoop
1079
1080 @@NoComp:
1081 pop esi { Restore registers }
1082 pop edi
1083 pop ecx
1084 pop ebx
1085
1086 jne @@RestNoMatch { Try again if no match }
1087
1088 {Calculate number of bytes searched and return}
1089 @@Found:
1090 pop ebx
1091 mov esi, Pos
1092 dec edi
1093 sub edi, ebx
1094 mov eax, 1
1095 mov [esi], edi
1096 jmp @@SDone
1097
1098 {Match was not found}
1099 @@NotFound:
1100 pop eax
1101 xor eax, eax
1102
1103 @@SDone:
1104 pop esi
1105 pop edi
1106 pop ebx
1107 end;
1108
1109 {---primitives for converting strings to integers---}
1110 procedure ValLongInt(S : ShortString; var LI : Longint; var ErrorCode : integer);
1111 var
1112 LenS : byte absolute S;
1113 Offset : Integer;
1114 NBCInx : Integer;
1115 begin
1116 {trim trailing spaces}
1117 while (LenS > 0) and (S[LenS] = ' ') do
1118 dec(LenS);
1119 {empty strings are invalid}
1120 if (LenS = 0) then begin
1121 LI := 0;
1122 ErrorCode := -1;
1123 end;
1124 {from now on S must have at least one non-blank char}
1125
1126 {find the first non-blank char}
1127 NBCInx := 1;
1128 while (S[NBCInx] = ' ') do
1129 inc(NBCInx);
1130
1131 {check for a string of the form nnnnH}
1132 Offset := 0;
1133 if (stbase.upcase(S[LenS]) = 'H') then begin
1134 {if the first non-blank char is the final character, then the
1135 string is just of the form <spaces>H and is invalid}
1136 if (NBCInx = LenS) then begin
1137 LI := 0;
1138 ErrorCode := LenS;
1139 Exit;
1140 end;
1141 Move(S[NBCInx], S[NBCInx+1], LenS-NBCInx);
1142 S[NBCInx] := '$';
1143 Offset := -1;
1144 end
1145 {check for a string of the form 0Xnnnn}
1146 else begin
1147 if (NBCInx < LenS) and
1148 (S[NBCInx] = '0') and (stbase.upcase(S[NBCInx+1]) = 'X') then begin
1149 S[NBCInx] := ' ';
1150 S[NBCInx+1] := '$';
1151 end;
1152 end;
1153 Val(S, LI, ErrorCode);
1154 if (ErrorCode <> 0) then begin
1155 LI := 0;
1156 Inc(ErrorCode, Offset);
1157 end;
1158 end;
1159
1160 procedure ValSmallint(const S : ShortString; var SI : smallint; var ErrorCode : integer);
1161 const
1162 SmallestInt16 = -32767;
1163 LargestInt16 = 32767;
1164 var
1165 LI : Longint;
1166 begin
1167 ValLongInt(S, LI, ErrorCode);
1168 if (ErrorCode <> 0) then
1169 SI := 0
1170 else {the conversion succeeded} begin
1171 if (SmallestInt16 <= LI) and (LI <= LargestInt16) then
1172 SI := LI
1173 else begin
1174 ErrorCode := length(S);
1175 SI := 0;
1176 end;
1177 end;
1178 end;
1179
1180 procedure ValWord(const S : ShortString; var Wd : word; var ErrorCode : integer);
1181 const
1182 SmallestWord = 0;
1183 LargestWord = 65535;
1184 var
1185 LI : Longint;
1186 begin
1187 ValLongInt(S, LI, ErrorCode);
1188 if (ErrorCode <> 0) then
1189 Wd := 0
1190 else {the conversion succeeded} begin
1191 if (SmallestWord <= LI) and (LI <= LargestWord) then
1192 Wd := LI
1193 else begin
1194 ErrorCode := length(S);
1195 Wd := 0;
1196 end;
1197 end;
1198 end;
1199 {---------------------------------------------------}
1200
1201
1202 function IsOrInheritsFrom(Root, Candidate : TClass) : boolean;
1203 begin
1204 Result := (Root = Candidate) or Candidate.InheritsFrom(Root);
1205 end;
1206
1207 procedure RaiseContainerError(Code : LongInt);
1208 var
1209 E : ESTContainerError;
1210 begin
1211 E := ESTContainerError.CreateResTP(Code, 0);
1212 E.ErrorCode := Code;
1213 raise E;
1214 end;
1215
1216 procedure RaiseContainerErrorFmt(Code : Longint; Data : array of const);
1217 var
1218 E : ESTContainerError;
1219 begin
1220 E := ESTContainerError.CreateResFmtTP(Code, Data, 0);
1221 E.ErrorCode := Code;
1222 raise E;
1223 end;
1224
1225 {$IFNDEF HStrings}
1226 function StNewStr(S : AnsiString) : PShortString;
1227 begin
1228 GetMem(Result, succ(length(S)));
1229 Result^ := S;
1230 end;
1231
1232 procedure StDisposeStr(PS : PShortString);
1233 begin
1234 if (PS <> nil) then
1235 FreeMem(PS, succ(length(PS^)));
1236 end;
1237 {$ENDIF}
1238
1239 {----------------------------------------------------------------------}
1240
1241 constructor TStNode.Create(AData : Pointer);
1242 begin
1243 Data := AData;
1244 end;
1245
1246 {----------------------------------------------------------------------}
1247
1248 function TStContainer.AssignPointers(Source : TPersistent;
1249 AssignData : TIteratePointerFunc) : boolean;
1250 begin
1251 Result := false;
1252 if (Source is TStContainer) then
1253 if TStContainer(Source).StoresPointers then
1254 begin
1255 Clear;
1256 TStContainer(Source).ForEachPointer(AssignData, Self);
1257 Result := true;
1258 end;
1259 end;
1260
1261 function TStContainer.AssignUntypedVars(Source : TPersistent;
1262 AssignData : TIterateUntypedFunc) : boolean;
1263 var
1264 RowCount : Cardinal;
1265 ColCount : Cardinal;
1266 ElSize : Cardinal;
1267 begin
1268 Result := false;
1269 if (Source is TStContainer) then
1270 if TStContainer(Source).StoresUntypedVars then
1271 begin
1272 Clear;
1273 TStContainer(Source).GetArraySizes(RowCount, ColCount, ElSize);
1274 SetArraySizes(RowCount, ColCount, ElSize);
1275 TStContainer(Source).ForEachUntypedVar(AssignData, Self);
1276 Result := true;
1277 end;
1278 end;
1279
1280 procedure TStContainer.ForEachPointer(Action : TIteratePointerFunc;
1281 OtherData : pointer);
1282 begin
1283 {do nothing}
1284 end;
1285
1286 procedure TStContainer.ForEachUntypedVar(Action : TIterateUntypedFunc;
1287 OtherData : pointer);
1288 begin
1289 {do nothing}
1290 end;
1291
1292 procedure TStContainer.GetArraySizes(var RowCount, ColCount, ElSize : Cardinal);
1293 begin
1294 RowCount := 0;
1295 ColCount := 0;
1296 ElSize := 0;
1297 end;
1298
1299 procedure TStContainer.SetArraySizes(RowCount, ColCount, ElSize : Cardinal);
1300 begin
1301 {do nothing}
1302 end;
1303
1304 procedure TStContainer.SetCompare(C : TCompareFunc);
1305 begin
1306 FCompare := C;
1307 end;
1308
1309 procedure TStContainer.SetDisposeData(D : TDisposeDataProc);
1310 begin
1311 FDisposeData := D;
1312 end;
1313
1314 procedure TStContainer.SetLoadData(L : TLoadDataFunc);
1315 begin
1316 FLoadData := L;
1317 end;
1318
1319 procedure TStContainer.SetStoreData(S : TStoreDataProc);
1320 begin
1321 FStoreData := S;
1322 end;
1323
1324 function TStContainer.StoresPointers : boolean;
1325 begin
1326 Result := false;
1327 end;
1328
1329 function TStContainer.StoresUntypedVars : boolean;
1330 begin
1331 Result := false;
1332 end;
1333
1334 constructor TStContainer.CreateContainer(NodeClass : TStNodeClass; Dummy : Integer);
1335 begin
1336 {$IFDEF ThreadSafe}
1337 Windows.InitializeCriticalSection(conThreadSafe);
1338 {$ENDIF}
1339
1340 FCompare := AbstractCompare;
1341 conNodeClass := NodeClass;
1342
1343 inherited Create;
1344 end;
1345
1346 procedure TStContainer.DecNodeProtection;
1347 begin
1348 Dec(conNodeProt);
1349 end;
1350
1351 destructor TStContainer.Destroy;
1352 begin
1353 if conNodeProt = 0 then
1354 Clear;
1355 {$IFDEF ThreadSafe}
1356 Windows.DeleteCriticalSection(conThreadSafe);
1357 {$ENDIF}
1358 inherited Destroy;
1359 end;
1360
1361 procedure TStContainer.DisposeNodeData(P : TStNode);
1362 begin
1363 {$IFDEF ThreadSafe}
1364 EnterCS;
1365 try
1366 {$ENDIF}
1367 if Assigned(P) then
1368 DoDisposeData(P.Data);
1369 {$IFDEF ThreadSafe}
1370 finally
1371 LeaveCS;
1372 end;
1373 {$ENDIF}
1374 end;
1375
1376 function TStContainer.DoCompare(Data1, Data2 : Pointer) : Integer;
1377 begin
1378 Result := 0;
1379 if Assigned(FOnCompare) then
1380 FOnCompare(Self, Data1, Data2, Result)
1381 else if Assigned(FCompare) then
1382 Result := FCompare(Data1, Data2);
1383 end;
1384
1385 procedure TStContainer.DoDisposeData(Data : Pointer);
1386 begin
1387 if Assigned(FOnDisposeData) then
1388 FOnDisposeData(Self, Data)
1389 else if Assigned(FDisposeData) then
1390 FDisposeData(Data);
1391 end;
1392
1393 function TStContainer.DoLoadData(Reader : TReader) : Pointer;
1394 begin
1395 Result := nil;
1396 if Assigned(FOnLoadData) then
1397 FOnLoadData(Self, Reader, Result)
1398 else if Assigned(FLoadData) then
1399 Result := FLoadData(Reader)
1400 else
1401 RaiseContainerError(stscNoLoadData);
1402 end;
1403
1404 procedure TStContainer.DoStoreData(Writer : TWriter; Data : Pointer);
1405 begin
1406 if Assigned(FOnStoreData) then
1407 FOnStoreData(Self, Writer, Data)
1408 else if Assigned(FStoreData) then
1409 FStoreData(Writer, Data)
1410 else
1411 RaiseContainerError(stscNoStoreData);
1412 end;
1413
1414 procedure TStContainer.EnterCS;
1415 begin
1416 {$IFDEF ThreadSafe}
1417 EnterCriticalSection(conThreadSafe);
1418 {$ENDIF}
1419 end;
1420
1421 procedure TStContainer.IncNodeProtection;
1422 begin
1423 Inc(conNodeProt);
1424 end;
1425
1426 procedure TStContainer.LeaveCS;
1427 begin
1428 {$IFDEF ThreadSafe}
1429 LeaveCriticalSection(conThreadSafe);
1430 {$ENDIF}
1431 end;
1432
1433 procedure TStContainer.LoadFromFile(const FileName : string);
1434 var
1435 S : TStream;
1436 begin
1437 S := TFileStream.Create(FileName, fmOpenRead + fmShareDenyWrite);
1438 try
1439 LoadFromStream(S);
1440 finally
1441 S.Free;
1442 end;
1443 end;
1444
1445 procedure TStContainer.StoreToFile(const FileName : string);
1446 var
1447 S : TStream;
1448 begin
1449 S := TFileStream.Create(FileName, fmCreate);
1450 try
1451 StoreToStream(S);
1452 finally
1453 S.Free;
1454 end;
1455 end;
1456
1457
1458 {*** TStComponent ***}
1459
1460 function TStComponent.GetVersion : string;
1461 begin
1462 Result := StVersionStr;
1463 end;
1464
1465 procedure TStComponent.SetVersion(const Value : string);
1466 begin
1467 end;
1468
1469 { TStBaseEdit }
1470
1471 function TStBaseEdit.GetVersion : string;
1472 begin
1473 Result := StVersionStr;
1474 end;
1475
1476 procedure TStBaseEdit.SetVersion(const Value : string);
1477 begin
1478 end;
1479
1480
1481
1482 initialization
1483 {$IFDEF VERSION3ONLY} { Delphi/Builder 3 doesn't like widestring typed constants }
1484 StHexDigitsW := '0123456789ABCDEF';
1485 DosDelimSetW := '\:';
1486 {$ENDIF}
1487 end.
1488
1489

  ViewVC Help
Powered by ViewVC 1.1.20