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

Annotation of /dao/DelphiScanner/Components/tpsystools_4.04/source/StDict.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: 22268 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: StDict.pas 4.04 *}
30     {*********************************************************}
31     {* SysTools: Dictionary class *}
32     {*********************************************************}
33    
34     {$I StDefine.inc}
35    
36     {Notes:
37     Nodes stored in the dictionary must be of type TStDictNode.
38    
39     Duplicate strings are not allowed in the dictionary.
40    
41     Calling Exists moves the found node to the front of its hash bin list.
42    
43     Iterate scans the nodes in hash order.
44    
45     Hashing and comparison is case-insensitive by default.
46    
47     In 16-bit mode, HashSize must be in the range 1..16380. In 32-bit
48     mode, there is no practical limit on HashSize. A particular value
49     of HashSize may lead to a better distribution of symbols in the
50     dictionary, and therefore to better performance. Generally HashSize
51     should be about the same size as the number of symbols expected in
52     the dictionary. A prime number tends to give a better distribution.
53     Based on analysis by D. Knuth, the following values are good
54     choices for HashSize when the dictionary keys are alphanumeric
55     strings:
56    
57     59 61 67 71 73 127 131 137 191 193 197 199 251 257 263 311 313
58     317 379 383 389 439 443 449 457 503 509 521 569 571 577 631 641
59     643 647 701 709 761 769 773 823 827 829 839 887 953 967
60    
61     Good values for larger tables can be computed by the GOODHASH.PAS
62     bonus program.
63     }
64    
65     unit StDict;
66    
67     interface
68    
69     uses
70     Windows, SysUtils, Classes,
71     StConst, StBase;
72    
73     type
74     TStDictNode = class(TStNode)
75     {.Z+}
76     protected
77     dnNext : TStDictNode; {Next node in hash list}
78     dnName : string; {Name of symbol, already a pointer}
79     function GetName : string;
80    
81     {.Z-}
82     public
83     constructor CreateStr(const Name : string; AData : Pointer);
84     {-Initialize node}
85     destructor Destroy; override;
86     {-Free name string and destroy node}
87    
88     property Name : string
89     read GetName;
90     end;
91    
92     {.Z+}
93     TSymbolArray = array[0..(StMaxBlockSize div SizeOf(TStDictNode))-1] of TStDictNode;
94     PSymbolArray = ^TSymbolArray;
95     {.Z-}
96    
97     TDictHashFunc =
98     function(const S : AnsiString; Size : Integer) : Integer;
99    
100     TStDictionary = class(TStContainer)
101     {.Z+}
102     protected
103     {property instance variables}
104     FHashSize : Integer; {Bins in symbol array}
105     FEqual : TStringCompareFunc; {String compare function}
106     FHash : TDictHashFunc;
107    
108     {event variables}
109     FOnEqual : TStStringCompareEvent;
110    
111     {private instance variables}
112     dySymbols : PSymbolArray; {Pointer to symbol array}
113     dyIgnoreDups : Boolean; {Ignore duplicates during Join?}
114    
115     {protected undocumented methods}
116     procedure dySetEqual(E : TStringCompareFunc);
117     procedure dySetHash(H : TDictHashFunc);
118     procedure dySetHashSize(Size : Integer);
119     procedure dyFindNode(const Name : string; var H : Integer;
120     var Prev, This : TStDictNode);
121     {.Z-}
122     public
123     constructor Create(AHashSize : Integer); virtual;
124     {-Initialize an empty dictionary}
125     destructor Destroy; override;
126     {-Destroy a dictionary}
127    
128     procedure LoadFromStream(S : TStream); override;
129     {-Read a dictionary and its data from a stream}
130     procedure StoreToStream(S : TStream); override;
131     {-Write a dictionary and its data to a stream}
132    
133     procedure Clear; override;
134     {-Remove all nodes from container but leave it instantiated}
135     function DoEqual(const String1, String2 : string) : Integer;
136     virtual;
137     function Exists(const Name : string; var Data : Pointer) : Boolean;
138     {-Return True and the Data pointer if Name is in the dictionary}
139     procedure Add(const Name : string; Data : Pointer);
140     {-Add new Name and Data to the dictionary}
141     procedure Delete(const Name : string);
142     {-Delete a Name from the dictionary}
143     procedure GetItems(S : TStrings);
144     {-Fill the string list with all stored strings}
145     procedure SetItems(S : TStrings);
146     {-Fill the container with the strings and objects in S}
147     procedure Update(const Name : string; Data : Pointer);
148     {-Update the data for an existing element}
149     function Find(Data : Pointer; var Name : string) : Boolean;
150     {-Return True and the element Name that matches Data}
151    
152     procedure Assign(Source: TPersistent); override;
153     {-Assign another container's contents to this one}
154     procedure Join(D : TStDictionary; IgnoreDups : Boolean);
155     {-Add dictionary D into this one and dispose D}
156    
157     function Iterate(Action : TIterateFunc;
158     OtherData : Pointer) : TStDictNode;
159     {-Call Action for all the nodes, returning the last node visited}
160    
161     function BinCount(H : Integer) : LongInt;
162     {-Return number of names in a hash bin (for testing)}
163    
164     property Equal : TStringCompareFunc
165     read FEqual
166     write dySetEqual;
167    
168     property Hash : TDictHashFunc
169     read FHash
170     write dySetHash;
171    
172     property HashSize : Integer
173     read FHashSize
174     write dySetHashSize;
175    
176     property OnEqual : TStStringCompareEvent
177     read FOnEqual
178     write FOnEqual;
179     end;
180    
181    
182     function AnsiHashText(const S : AnsiString; Size : Integer) : Integer;
183     {-Case-insensitive hash function that uses the current language driver}
184     function AnsiHashStr(const S : AnsiString; Size : Integer) : Integer;
185     {-Case-sensitive hash function}
186     function AnsiELFHashText(const S : AnsiString; Size : Integer) : Integer;
187     {-Case-insensitive ELF hash function that uses the current language driver}
188     function AnsiELFHashStr(const S : AnsiString; Size : Integer) : Integer;
189     {-Case-sensitive ELF hash function}
190    
191    
192     implementation
193    
194     {$IFDEF UNICODE}
195     uses
196     AnsiStrings;
197     {$ENDIF}
198    
199     {$IFDEF ThreadSafe}
200     var
201     ClassCritSect : TRTLCriticalSection;
202     {$ENDIF}
203    
204     procedure EnterClassCS;
205     begin
206     {$IFDEF ThreadSafe}
207     EnterCriticalSection(ClassCritSect);
208     {$ENDIF}
209     end;
210    
211     procedure LeaveClassCS;
212     begin
213     {$IFDEF ThreadSafe}
214     LeaveCriticalSection(ClassCritSect);
215     {$ENDIF}
216     end;
217    
218    
219     {The following routine was extracted from LockBox and modified}
220     function HashElf(const Buf; BufSize : LongInt) : LongInt;
221     var
222     // Bytes : TByteArray absolute Buf; {!!.02}
223     Bytes : PAnsiChar; {!!.02}
224     I, X : LongInt;
225     begin
226     Bytes := @Buf; {!!.02}
227     Result := 0;
228     for I := 0 to BufSize - 1 do begin
229     Result := (Result shl 4) + Ord(Bytes^); {!!.02}
230     Inc(Bytes); {!!.02}
231     X := LongInt(Result and $F0000000); {!!.02}
232     if (X <> 0) then
233     Result := Result xor (X shr 24);
234     Result := Result and (not X);
235     end;
236     end;
237    
238     function AnsiELFHashText(const S : AnsiString; Size : Integer) : Integer;
239     begin
240     {$IFDEF WStrings}
241     Result := AnsiELFHashStr(AnsiUpperCaseShort32(S), Size);
242     {$ELSE}
243     Result := AnsiELFHashStr(AnsiUpperCase(S), Size);
244     {$ENDIF}
245     end;
246    
247     function AnsiELFHashStr(const S : AnsiString; Size : Integer) : Integer;
248     begin
249     Result := HashElf(S[1], Length(S)) mod Size;
250     if Result < 0 then
251     Inc(Result, Size);
252     end;
253    
254     constructor TStDictNode.CreateStr(const Name : string; AData : Pointer);
255     begin
256     Create(AData);
257     dnName := Name;
258     end;
259    
260     destructor TStDictNode.Destroy;
261     begin
262     dnName := '';
263     inherited Destroy;
264     end;
265    
266     function TStDictNode.GetName : string;
267     begin
268     Result := dnName;
269     end;
270    
271     function AnsiHashStr(const S : AnsiString; Size : Integer) : Integer;
272     {32-bit huge string}
273     register;
274     asm
275     push ebx
276     push esi
277     push edi
278     mov esi,S
279     mov edi,Size
280     xor ebx,ebx {ebx will be hash}
281     or esi,esi {empty literal string comes in as a nil pointer}
282     jz @2
283     mov edx,[esi-4] {edx = length}
284     or edx,edx {length zero?}
285     jz @2
286     xor ecx,ecx {ecx is shift counter}
287     @1:xor eax,eax
288     mov al,[esi] {eax = character}
289     inc esi
290     rol eax,cl {rotate character}
291     xor ebx,eax {xor with hash}
292     inc ecx {increment shift counter (rol uses only bottom 5 bits)}
293     dec edx
294     jnz @1
295     @2:mov eax,ebx
296     xor edx,edx
297     div edi {edi = Size}
298     mov eax,edx {return hash mod size}
299     pop edi
300     pop esi
301     pop ebx
302     end;
303    
304     function AnsiHashText(const S : AnsiString; Size : Integer) : Integer;
305     begin
306     {$IFDEF WStrings}
307     Result := AnsiHashStr(AnsiUpperCaseShort32(S), Size);
308     {$ELSE}
309     Result := AnsiHashStr(AnsiUpperCase(S), Size);
310     {$ENDIF}
311     end;
312    
313     function FindNodeData(Container : TStContainer;
314     Node : TStNode;
315     OtherData : Pointer) : Boolean; far;
316     begin
317     Result := (OtherData <> Node.Data);
318     end;
319    
320     function JoinNode(Container : TStContainer;
321     Node : TStNode;
322     OtherData : Pointer) : Boolean; far;
323     var
324     H : Integer;
325     P, T : TStDictNode;
326     begin
327     Result := True;
328     with TStDictionary(OtherData) do begin
329     dyFindNode(TStDictNode(Node).dnName, H, P, T);
330     if Assigned(T) then
331     if dyIgnoreDups then begin
332     Node.Free;
333     Exit;
334     end else
335     RaiseContainerError(stscDupNode);
336     T := dySymbols^[H];
337     dySymbols^[H] := TStDictNode(Node);
338     dySymbols^[H].dnNext := T;
339     Inc(FCount);
340     end;
341     end;
342    
343     function AssignNode(Container : TStContainer;
344     Node : TStNode;
345     OtherData : Pointer) : Boolean; far;
346     var
347     DictNode : TStDictNode absolute Node;
348     OurDict : TStDictionary absolute OtherData;
349     begin
350     OurDict.Add(DictNode.Name, DictNode.Data);
351     Result := true;
352     end;
353    
354     {----------------------------------------------------------------------}
355    
356     procedure TStDictionary.Add(const Name : string; Data : Pointer);
357     var
358     H : Integer;
359     P, T : TStDictNode;
360     begin
361     {$IFDEF ThreadSafe}
362     EnterCS;
363     try
364     {$ENDIF}
365     dyFindNode(Name, H, P, T);
366     if Assigned(T) then
367     RaiseContainerError(stscDupNode);
368     T := dySymbols^[H];
369     dySymbols^[H] := TStDictNode.CreateStr(Name, Data);
370     dySymbols^[H].dnNext := T;
371     Inc(FCount);
372     {$IFDEF ThreadSafe}
373     finally
374     LeaveCS;
375     end;
376     {$ENDIF}
377     end;
378    
379     procedure TStDictionary.Assign(Source: TPersistent);
380     var
381     i : integer;
382     begin
383     {The only two containers that we allow to be assigned to a string
384     dictionary are (1) another string dictionary and (2) a Delphi string
385     list (TStrings)}
386     if (Source is TStDictionary) then
387     begin
388     Clear;
389     TStDictionary(Source).Iterate(AssignNode, Self);
390     end
391     else if (Source is TStrings) then
392     begin
393     Clear;
394     for i := 0 to pred(TStrings(Source).Count) do
395     Add(TStrings(Source).Strings[i], TStrings(Source).Objects[i]);
396     end
397     else
398     inherited Assign(Source);
399     end;
400    
401     function TStDictionary.BinCount(H : Integer) : LongInt;
402     var
403     C : LongInt;
404     T : TStDictNode;
405     begin
406     {$IFDEF ThreadSafe}
407     EnterCS;
408     try
409     {$ENDIF}
410     C := 0;
411     T := dySymbols^[H];
412     while Assigned(T) do begin
413     inc(C);
414     T := T.dnNext;
415     end;
416     Result := C;
417     {$IFDEF ThreadSafe}
418     finally
419     LeaveCS;
420     end;
421     {$ENDIF}
422     end;
423    
424     procedure TStDictionary.Clear;
425     begin
426     {$IFDEF ThreadSafe}
427     EnterCS;
428     try
429     {$ENDIF}
430     if FCount <> 0 then begin
431     Iterate(DestroyNode, nil);
432     FCount := 0;
433     FillChar(dySymbols^, LongInt(FHashSize)*SizeOf(TStDictNode), 0);
434     end;
435     {$IFDEF ThreadSafe}
436     finally
437     LeaveCS;
438     end;
439     {$ENDIF}
440     end;
441    
442     constructor TStDictionary.Create(AHashSize : Integer);
443     begin
444     CreateContainer(TStDictNode, 0);
445     {FHashSize := 0;}
446     {$IFDEF WStrings}
447     FEqual := AnsiCompareTextShort32;
448     {$ELSE}
449     FEqual := AnsiCompareText;
450     {$ENDIF}
451     FHash := AnsiHashText;
452     HashSize := AHashSize;
453     end;
454    
455     procedure TStDictionary.Delete(const Name : string);
456     var
457     H : Integer;
458     P, T : TStDictNode;
459     begin
460     {$IFDEF ThreadSafe}
461     EnterCS;
462     try
463     {$ENDIF}
464     dyFindNode(Name, H, P, T);
465     if Assigned(T) then begin
466     if Assigned(P) then
467     P.dnNext := T.dnNext
468     else
469     dySymbols^[H] := T.dnNext;
470     DestroyNode(Self, T, nil);
471     Dec(FCount);
472     end;
473     {$IFDEF ThreadSafe}
474     finally
475     LeaveCS;
476     end;
477     {$ENDIF}
478     end;
479    
480     destructor TStDictionary.Destroy;
481     begin
482     if conNodeProt = 0 then
483     Clear;
484     if Assigned(dySymbols) then
485     FreeMem(dySymbols, LongInt(FHashSize)*SizeOf(TStDictNode));
486     IncNodeProtection;
487     inherited Destroy;
488     end;
489    
490     function TStDictionary.DoEqual(const String1, String2 : string) : Integer;
491     begin
492     Result := 0;
493     if Assigned(FOnEqual) then
494     FOnEqual(Self, String1, String2, Result)
495     else if Assigned(FEqual) then
496     Result := FEqual(String1, String2);
497     end;
498    
499     procedure TStDictionary.dyFindNode(const Name : string; var H : Integer;
500     var Prev, This : TStDictNode);
501     var
502     P, T : TStDictNode;
503     begin
504     Prev := nil;
505     This := nil;
506     H := Hash(Name, HashSize);
507     T := dySymbols^[H];
508     P := nil;
509     while Assigned(T) do begin
510     if DoEqual(Name, T.dnName) = 0 then begin
511     Prev := P;
512     This := T;
513     Exit;
514     end;
515     P := T;
516     T := T.dnNext;
517     end;
518    
519     {Not found}
520     This := nil;
521     end;
522    
523     procedure TStDictionary.dySetEqual(E : TStringCompareFunc);
524     begin
525     {$IFDEF ThreadSafe}
526     EnterCS;
527     try
528     {$ENDIF}
529     if Count = 0 then
530     FEqual := E;
531     {$IFDEF ThreadSafe}
532     finally
533     LeaveCS;
534     end;
535     {$ENDIF}
536     end;
537    
538     procedure TStDictionary.dySetHash(H : TDictHashFunc);
539     begin
540     {$IFDEF ThreadSafe}
541     EnterCS;
542     try
543     {$ENDIF}
544     if Count = 0 then
545     FHash := H;
546     {$IFDEF ThreadSafe}
547     finally
548     LeaveCS;
549     end;
550     {$ENDIF}
551     end;
552    
553     procedure TStDictionary.dySetHashSize(Size : Integer);
554     var
555     H, OldSize : Integer;
556     TableSize : LongInt;
557     T, N : TStDictNode;
558     OldSymbols : PSymbolArray;
559     OldDisposeData : TDisposeDataProc;
560     OldOnDisposeData : TStDisposeDataEvent;
561     begin
562     {$IFDEF ThreadSafe}
563     EnterCS;
564     try
565     {$ENDIF}
566     TableSize := LongInt(Size)*SizeOf(TStDictNode);
567     if (Size <= 0) {or (TableSize > MaxBlockSize)} then
568     RaiseContainerError(stscBadSize);
569    
570     if Size <> FHashSize then begin
571     OldSymbols := dySymbols;
572     OldSize := FHashSize;
573    
574     {Get a new hash table}
575     GetMem(dySymbols, TableSize);
576     FillChar(dySymbols^, TableSize, 0);
577     FCount := 0;
578     FHashSize := Size;
579    
580     if OldSize <> 0 then begin
581     {Prevent disposing of the user data while transferring elements}
582     OldDisposeData := DisposeData;
583     DisposeData := nil;
584     OldOnDisposeData := OnDisposeData;
585     OnDisposeData := nil;
586     {Add old symbols into new hash table}
587     for H := 0 to OldSize-1 do begin
588     T := OldSymbols^[H];
589     while Assigned(T) do begin
590     Add(T.dnName, T.Data);
591     N := T.dnNext;
592     {free the node just transferred}
593     T.Free;
594     T := N;
595     end;
596     end;
597     {Dispose of old hash table}
598     FreeMem(OldSymbols, OldSize*SizeOf(TStDictNode));
599     {Reassign the dispose data routine}
600     DisposeData := OldDisposeData;
601     OnDisposeData := OldOnDisposeData;
602     end;
603    
604     {FHashSize := Size;}
605     end;
606     {$IFDEF ThreadSafe}
607     finally
608     LeaveCS;
609     end;
610     {$ENDIF}
611     end;
612    
613     function TStDictionary.Exists(const Name : String; var Data : Pointer) : Boolean;
614     var
615     H : Integer;
616     P, T : TStDictNode;
617     begin
618     {$IFDEF ThreadSafe}
619     EnterCS;
620     try
621     {$ENDIF}
622     dyFindNode(Name, H, P, T);
623     if Assigned(T) then begin
624     if Assigned(P) then begin
625     {Move T to front of list}
626     P.dnNext := T.dnNext;
627     T.dnNext := dySymbols^[H];
628     dySymbols^[H] := T;
629     end;
630     Result := True;
631     Data := T.Data;
632     end else
633     Result := False;
634     {$IFDEF ThreadSafe}
635     finally
636     LeaveCS;
637     end;
638     {$ENDIF}
639     end;
640    
641     function TStDictionary.Find(Data : Pointer; var Name : string) : Boolean;
642     var
643     T : TStDictNode;
644     begin
645     Name := '';
646     {$IFDEF ThreadSafe}
647     EnterCS;
648     try
649     {$ENDIF}
650     T := Iterate(FindNodeData, Data);
651     if Assigned(T) then begin
652     Result := True;
653     Name := T.dnName;
654     end else
655     Result := False;
656     {$IFDEF ThreadSafe}
657     finally
658     LeaveCS;
659     end;
660     {$ENDIF}
661     end;
662    
663     procedure TStDictionary.GetItems(S : TStrings);
664     var
665     H : Integer;
666     T : TStDictNode;
667     begin
668     S.Clear;
669     {$IFDEF ThreadSafe}
670     EnterCS;
671     try
672     {$ENDIF}
673     if FCount <> 0 then begin
674     for H := 0 to FHashSize-1 do begin
675     T := dySymbols^[H];
676     while Assigned(T) do begin
677     S.AddObject(T.Name, T.Data);
678     T := T.dnNext;
679     end;
680     end;
681     end;
682     {$IFDEF ThreadSafe}
683     finally
684     LeaveCS;
685     end;
686     {$ENDIF}
687     end;
688    
689     procedure TStDictionary.SetItems(S : TStrings);
690     var
691     I : Integer;
692     begin
693     {$IFDEF ThreadSafe}
694     EnterCS;
695     try
696     {$ENDIF}
697     Clear;
698     for I := 0 to S.Count-1 do
699     Add(S.Strings[I], S.Objects[I]);
700     {$IFDEF ThreadSafe}
701     finally
702     LeaveCS;
703     end;
704     {$ENDIF}
705     end;
706    
707     function TStDictionary.Iterate(Action : TIterateFunc;
708     OtherData : Pointer) : TStDictNode;
709     var
710     H : Integer;
711     T, N : TStDictNode;
712     begin
713     {$IFDEF ThreadSafe}
714     EnterCS;
715     try
716     {$ENDIF}
717     if FCount <> 0 then begin
718     for H := 0 to FHashSize-1 do begin
719     T := dySymbols^[H];
720     while Assigned(T) do begin
721     N := T.dnNext;
722     if Action(Self, T, OtherData) then
723     T := N
724     else begin
725     Result := T;
726     Exit;
727     end;
728     end;
729     end;
730     end;
731     Result := nil;
732     {$IFDEF ThreadSafe}
733     finally
734     LeaveCS;
735     end;
736     {$ENDIF}
737     end;
738    
739     procedure TStDictionary.Join(D : TStDictionary; IgnoreDups : Boolean);
740     begin
741     {$IFDEF ThreadSafe}
742     EnterClassCS;
743     EnterCS;
744     D.EnterCS;
745     try
746     {$ENDIF}
747     dyIgnoreDups := IgnoreDups;
748     D.Iterate(JoinNode, Self);
749    
750     {Dispose of D, but not its nodes}
751     D.IncNodeProtection;
752     D.Free;
753     {$IFDEF ThreadSafe}
754     finally
755     D.LeaveCS;
756     LeaveCS;
757     LeaveClassCS;
758     end;
759     {$ENDIF}
760     end;
761    
762     procedure TStDictionary.Update(const Name : string; Data : Pointer);
763     var
764     H : Integer;
765     P, T : TStDictNode;
766     begin
767     {$IFDEF ThreadSafe}
768     EnterCS;
769     try
770     {$ENDIF}
771     dyFindNode(Name, H, P, T);
772     if Assigned(T) then
773     T.Data := Data;
774     {$IFDEF ThreadSafe}
775     finally
776     LeaveCS;
777     end;
778     {$ENDIF}
779     end;
780    
781     procedure TStDictionary.LoadFromStream(S : TStream);
782     var
783     Data : pointer;
784     Reader : TReader;
785     StreamedClass : TPersistentClass;
786     StreamedNodeClass : TPersistentClass;
787     StreamedClassName : string;
788     StreamedNodeClassName : string;
789     St : string;
790     begin
791     {$IFDEF ThreadSafe}
792     EnterCS;
793     try
794     {$ENDIF}
795     Clear;
796     Reader := TReader.Create(S, 1024);
797     try
798     with Reader do
799     begin
800     StreamedClassName := ReadString;
801     StreamedClass := GetClass(StreamedClassName);
802     if (StreamedClass = nil) then
803     RaiseContainerErrorFmt(stscUnknownClass, [StreamedClassName]);
804     if (StreamedClass <> Self.ClassType) then
805     RaiseContainerError(stscWrongClass);
806     StreamedNodeClassName := ReadString;
807     StreamedNodeClass := GetClass(StreamedNodeClassName);
808     if (StreamedNodeClass = nil) then
809     RaiseContainerErrorFmt(stscUnknownNodeClass, [StreamedNodeClassName]);
810     if (StreamedNodeClass <> conNodeClass) then
811     RaiseContainerError(stscWrongNodeClass);
812     HashSize := ReadInteger;
813     ReadListBegin;
814     while not EndOfList do
815     begin
816     St := ReadString;
817     Data := DoLoadData(Reader);
818     Add(St, Data);
819     end;
820     ReadListEnd;
821     end;
822     finally
823     Reader.Free;
824     end;
825     {$IFDEF ThreadSafe}
826     finally
827     LeaveCS;
828     end;
829     {$ENDIF}
830     end;
831    
832     procedure TStDictionary.StoreToStream(S : TStream);
833     var
834     H : Integer;
835     Walker : TStDictNode;
836     Writer : TWriter;
837     begin
838     {$IFDEF ThreadSafe}
839     EnterCS;
840     try
841     {$ENDIF}
842     Writer := TWriter.Create(S, 1024);
843     try
844     with Writer do
845     begin
846     WriteString(Self.ClassName);
847     WriteString(conNodeClass.ClassName);
848     WriteInteger(HashSize);
849     WriteListBegin;
850     if (Count <> 0) then
851     for H := 0 to FHashSize-1 do
852     begin
853     Walker := dySymbols^[H];
854     while Assigned(Walker) do
855     begin
856     WriteString(Walker.dnName);
857     DoStoreData(Writer, Walker.Data);
858     Walker := Walker.dnNext;
859     end;
860     end;
861     WriteListEnd;
862     end;
863     finally
864     Writer.Free;
865     end;
866     {$IFDEF ThreadSafe}
867     finally
868     LeaveCS;
869     end;
870     {$ENDIF}
871     end;
872    
873     {$IFDEF ThreadSafe}
874     initialization
875     Windows.InitializeCriticalSection(ClassCritSect);
876     finalization
877     Windows.DeleteCriticalSection(ClassCritSect);
878     {$ENDIF}
879     end.

  ViewVC Help
Powered by ViewVC 1.1.20