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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (hide annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 10 months ago) by torben
File size: 40195 byte(s)
Added tpsystools component
1 torben 2671 // 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