1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- G N A T . S P I T B O L --
9 -- Copyright (C) 1998-2002 Ada Core Technologies, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada
.Strings
; use Ada
.Strings
;
35 with Ada
.Strings
.Unbounded
.Aux
; use Ada
.Strings
.Unbounded
.Aux
;
37 with GNAT
.Debug_Utilities
; use GNAT
.Debug_Utilities
;
38 with GNAT
.IO
; use GNAT
.IO
;
40 with Unchecked_Deallocation
;
42 package body GNAT
.Spitbol
is
48 function "&" (Num
: Integer; Str
: String) return String is
53 function "&" (Str
: String; Num
: Integer) return String is
58 function "&" (Num
: Integer; Str
: VString
) return VString
is
63 function "&" (Str
: VString
; Num
: Integer) return VString
is
72 function Char
(Num
: Natural) return Character is
74 return Character'Val (Num
);
84 Pad
: Character := ' ')
88 if Length
(Str
) >= Len
then
91 return Tail
(Str
, Len
, Pad
);
98 Pad
: Character := ' ')
102 if Str
'Length >= Len
then
107 R
: String (1 .. Len
);
110 for J
in 1 .. Len
- Str
'Length loop
114 R
(Len
- Str
'Length + 1 .. Len
) := Str
;
121 (Str
: in out VString
;
123 Pad
: Character := ' ')
126 if Length
(Str
) >= Len
then
129 Tail
(Str
, Len
, Pad
);
137 function N
(Str
: VString
) return Integer is
139 return Integer'Value (Get_String
(Str
).all);
146 function Reverse_String
(Str
: VString
) return VString
is
147 Len
: constant Natural := Length
(Str
);
148 Chars
: constant String_Access
:= Get_String
(Str
);
149 Result
: String (1 .. Len
);
152 for J
in 1 .. Len
loop
153 Result
(J
) := Chars
(Len
+ 1 - J
);
159 function Reverse_String
(Str
: String) return VString
is
160 Result
: String (1 .. Str
'Length);
163 for J
in 1 .. Str
'Length loop
164 Result
(J
) := Str
(Str
'Last + 1 - J
);
170 procedure Reverse_String
(Str
: in out VString
) is
171 Len
: constant Natural := Length
(Str
);
172 Chars
: constant String_Access
:= Get_String
(Str
);
176 for J
in 1 .. Len
/ 2 loop
178 Chars
(J
) := Chars
(Len
+ 1 - J
);
179 Chars
(Len
+ 1 - J
) := Temp
;
190 Pad
: Character := ' ')
194 if Length
(Str
) >= Len
then
197 return Head
(Str
, Len
, Pad
);
204 Pad
: Character := ' ')
208 if Str
'Length >= Len
then
213 R
: String (1 .. Len
);
216 for J
in Str
'Length + 1 .. Len
loop
220 R
(1 .. Str
'Length) := Str
;
227 (Str
: in out VString
;
229 Pad
: Character := ' ')
232 if Length
(Str
) >= Len
then
236 Head
(Str
, Len
, Pad
);
244 function S
(Num
: Integer) return String is
245 Buf
: String (1 .. 30);
246 Ptr
: Natural := Buf
'Last + 1;
247 Val
: Natural := abs (Num
);
252 Buf
(Ptr
) := Character'Val (Val
mod 10 + Character'Pos ('0'));
262 return Buf
(Ptr
.. Buf
'Last);
276 if Start
> Length
(Str
) then
279 elsif Start
+ Len
- 1 > Length
(Str
) then
283 return V
(Get_String
(Str
).all (Start
.. Start
+ Len
- 1));
294 if Start
> Str
'Length then
297 elsif Start
+ Len
> Str
'Length then
302 V
(Str
(Str
'First + Start
- 1 .. Str
'First + Start
+ Len
- 2));
310 package body Table
is
312 procedure Free
is new
313 Unchecked_Deallocation
(Hash_Element
, Hash_Element_Ptr
);
315 -----------------------
316 -- Local Subprograms --
317 -----------------------
319 function Hash
(Str
: String) return Unsigned_32
;
320 -- Compute hash function for given String
326 procedure Adjust
(Object
: in out Table
) is
327 Ptr1
: Hash_Element_Ptr
;
328 Ptr2
: Hash_Element_Ptr
;
331 for J
in Object
.Elmts
'Range loop
332 Ptr1
:= Object
.Elmts
(J
)'Unrestricted_Access;
334 if Ptr1
.Name
/= null then
336 Ptr1
.Name
:= new String'(Ptr1.Name.all);
337 exit when Ptr1.Next = null;
339 Ptr1.Next := new Hash_Element'(Ptr2
.all);
350 procedure Clear
(T
: in out Table
) is
351 Ptr1
: Hash_Element_Ptr
;
352 Ptr2
: Hash_Element_Ptr
;
355 for J
in T
.Elmts
'Range loop
356 if T
.Elmts
(J
).Name
/= null then
357 Free
(T
.Elmts
(J
).Name
);
358 T
.Elmts
(J
).Value
:= Null_Value
;
360 Ptr1
:= T
.Elmts
(J
).Next
;
361 T
.Elmts
(J
).Next
:= null;
363 while Ptr1
/= null loop
373 ----------------------
374 -- Convert_To_Array --
375 ----------------------
377 function Convert_To_Array
(T
: Table
) return Table_Array
is
378 Num_Elmts
: Natural := 0;
379 Elmt
: Hash_Element_Ptr
;
382 for J
in T
.Elmts
'Range loop
383 Elmt
:= T
.Elmts
(J
)'Unrestricted_Access;
385 if Elmt
.Name
/= null then
387 Num_Elmts
:= Num_Elmts
+ 1;
389 exit when Elmt
= null;
395 TA
: Table_Array
(1 .. Num_Elmts
);
399 for J
in T
.Elmts
'Range loop
400 Elmt
:= T
.Elmts
(J
)'Unrestricted_Access;
402 if Elmt
.Name
/= null then
404 Set_String
(TA
(P
).Name
, Elmt
.Name
.all);
405 TA
(P
).Value
:= Elmt
.Value
;
408 exit when Elmt
= null;
415 end Convert_To_Array
;
421 procedure Copy
(From
: in Table
; To
: in out Table
) is
422 Elmt
: Hash_Element_Ptr
;
427 for J
in From
.Elmts
'Range loop
428 Elmt
:= From
.Elmts
(J
)'Unrestricted_Access;
429 if Elmt
.Name
/= null then
431 Set
(To
, Elmt
.Name
.all, Elmt
.Value
);
433 exit when Elmt
= null;
443 procedure Delete
(T
: in out Table
; Name
: Character) is
445 Delete
(T
, String'(1 => Name));
448 procedure Delete (T : in out Table; Name : VString) is
450 Delete (T, Get_String (Name).all);
453 procedure Delete (T : in out Table; Name : String) is
454 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
455 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
456 Next : Hash_Element_Ptr;
459 if Elmt.Name = null then
462 elsif Elmt.Name.all = Name then
465 if Elmt.Next = null then
466 Elmt.Value := Null_Value;
471 Elmt.Name := Next.Name;
472 Elmt.Value := Next.Value;
473 Elmt.Next := Next.Next;
485 elsif Next.Name.all = Name then
487 Elmt.Next := Next.Next;
502 procedure Dump (T : Table; Str : String := "Table") is
503 Num_Elmts : Natural := 0;
504 Elmt : Hash_Element_Ptr;
507 for J in T.Elmts'Range loop
508 Elmt := T.Elmts (J)'Unrestricted_Access;
510 if Elmt.Name /= null then
512 Num_Elmts := Num_Elmts + 1;
514 (Str & '<' & Image (Elmt.Name.all) & "> = " &
517 exit when Elmt = null;
522 if Num_Elmts = 0 then
523 Put_Line (Str & " is empty");
527 procedure Dump (T : Table_Array; Str : String := "Table_Array") is
530 Put_Line (Str & " is empty");
533 for J in T'Range loop
535 (Str & '(' & Image (To_String (T (J).Name)) & ") = " &
545 procedure Finalize (Object : in out Table) is
546 Ptr1 : Hash_Element_Ptr;
547 Ptr2 : Hash_Element_Ptr;
550 for J in Object.Elmts'Range loop
551 Ptr1 := Object.Elmts (J).Next;
552 Free (Object.Elmts (J).Name);
553 while Ptr1 /= null loop
566 function Get (T : Table; Name : Character) return Value_Type is
568 return Get (T, String'(1 => Name
));
571 function Get
(T
: Table
; Name
: VString
) return Value_Type
is
573 return Get
(T
, Get_String
(Name
).all);
576 function Get
(T
: Table
; Name
: String) return Value_Type
is
577 Slot
: constant Unsigned_32
:= Hash
(Name
) mod T
.N
+ 1;
578 Elmt
: Hash_Element_Ptr
:= T
.Elmts
(Slot
)'Unrestricted_Access;
581 if Elmt
.Name
= null then
586 if Name
= Elmt
.Name
.all then
604 function Hash
(Str
: String) return Unsigned_32
is
605 Result
: Unsigned_32
:= Str
'Length;
608 for J
in Str
'Range loop
609 Result
:= Rotate_Left
(Result
, 1) +
610 Unsigned_32
(Character'Pos (Str
(J
)));
620 function Present
(T
: Table
; Name
: Character) return Boolean is
622 return Present
(T
, String'(1 => Name));
625 function Present (T : Table; Name : VString) return Boolean is
627 return Present (T, Get_String (Name).all);
630 function Present (T : Table; Name : String) return Boolean is
631 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
632 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
635 if Elmt.Name = null then
640 if Name = Elmt.Name.all then
658 procedure Set (T : in out Table; Name : VString; Value : Value_Type) is
660 Set (T, Get_String (Name).all, Value);
663 procedure Set (T : in out Table; Name : Character; Value : Value_Type) is
665 Set (T, String'(1 => Name
), Value
);
674 if Value
= Null_Value
then
679 Slot
: constant Unsigned_32
:= Hash
(Name
) mod T
.N
+ 1;
680 Elmt
: Hash_Element_Ptr
:= T
.Elmts
(Slot
)'Unrestricted_Access;
682 subtype String1
is String (1 .. Name
'Length);
685 if Elmt
.Name
= null then
686 Elmt
.Name
:= new String'(String1 (Name));
692 if Name = Elmt.Name.all then
696 elsif Elmt.Next = null then
697 Elmt.Next := new Hash_Element'(
698 Name
=> new String'(String1 (Name)),
717 function Trim (Str : VString) return VString is
719 return Trim (Str, Right);
722 function Trim (Str : String) return VString is
724 for J in reverse Str'Range loop
725 if Str (J) /= ' ' then
726 return V (Str (Str'First .. J));
733 procedure Trim (Str : in out VString) is
742 function V (Num : Integer) return VString is
743 Buf : String (1 .. 30);
744 Ptr : Natural := Buf'Last + 1;
745 Val : Natural := abs (Num);
750 Buf (Ptr) := Character'Val (Val mod 10 + Character'Pos ('0'));
760 return V (Buf (Ptr .. Buf'Last));