1
----------------------------------------------------------------------
2
-- Binary_Map - Package body --
3
-- Copyright (C) 2005 Adalog --
4
-- Author: J-P. Rosen --
6
-- ADALOG is providing training, consultancy, expertise, --
7
-- assistance and custom developments in Ada and related software --
8
-- engineering techniques. For more info about our services: --
9
-- ADALOG Tel: +33 1 41 24 31 40 --
10
-- 19-21 rue du 8 mai 1945 Fax: +33 1 41 24 07 36 --
11
-- 94110 ARCUEIL E-m: info@adalog.fr --
12
-- FRANCE URL: http://www.adalog.fr --
14
-- This unit is free software; you can redistribute it and/or --
15
-- modify it under terms of the GNU General Public License as --
16
-- published by the Free Software Foundation; either version 2, or --
17
-- (at your option) any later version. This unit is distributed --
18
-- in the hope that it will be useful, but WITHOUT ANY WARRANTY; --
19
-- without even the implied warranty of MERCHANTABILITY or FITNESS --
20
-- FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21
-- for more details. You should have received a copy of the GNU --
22
-- General Public License distributed with this program; see file --
23
-- COPYING. If not, write to the Free Software Foundation, 59 --
24
-- Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
26
-- As a special exception, if other files instantiate generics --
27
-- from this unit, or you link this unit with other files to --
28
-- produce an executable, this unit does not by itself cause the --
29
-- resulting executable to be covered by the GNU General Public --
30
-- License. This exception does not however invalidate any other --
31
-- reasons why the executable file might be covered by the GNU --
33
----------------------------------------------------------------------
35
with Ada.Unchecked_Deallocation;
36
package body Binary_Map is
37
procedure Free is new Ada.Unchecked_Deallocation (Node, Map);
47
function Get_Node (M : Map; Key : Key_Type) return Map is
51
if Current = null then
55
elsif Key < Current.Key then
56
Current := Current.Children (Before);
58
elsif Key > Current.Key then
59
Current := Current.Children (After);
72
procedure Linearize (M : Map; First, Last : out Map; Count : out Natural) is
73
-- Precondition: M is not null
74
-- Postconditions: First is the first element of a linear tree (all Left pointers are null)
75
-- Last is the last element
76
-- Count is the number of elements in the tree
82
if M.Children (Before) /= null then
83
Linearize (M.Children (Before), First, Temp_Map, Temp_Count);
84
Temp_Map.Children (After) := M;
85
Count := Count + Temp_Count;
89
M.Children (Before) := null;
91
if M.Children (After) = null then
94
Linearize (M.Children (After), Temp_Map, Last, Temp_Count);
95
M.Children (After) := Temp_Map;
96
Count := Count + Temp_Count;
104
procedure Rebalance (M : in out Map; Size : Natural; Rest : out Map) is
105
-- Precondition: M is a linear tree (all Left pointers are null)
106
-- Postcondions: M is a balanced tree containing the first Size elements
107
-- Rest is the first of the remaining elements from the linear tree
117
Rest := M.Children (After);
118
M.Children (After) := null;
122
Rebalance (Left, (Size-1) / 2, Top);
123
Top.Children (Before) := Left;
124
Rebalance (Top.Children (After), Size - (Size-1)/2 - 1, Rest);
131
-- Exported subprograms
138
procedure Add (To : in out Map;
140
Value : in Value_type) is
143
To := new Node'(Key, Value, (null, null));
148
Add (To.Children (Before), Key, Value);
149
elsif Key = To.Key then
152
Add (To.Children (After), Key, Value);
160
procedure Balance (The_Map : in out Map) is
164
if The_Map = null then
168
Linearize (The_Map, First, Last, Count);
170
Rebalance (The_Map, Count, First);
177
procedure Delete (From : in out Map; Key : Key_Type) is
178
Count1, Count2: Natural;
180
Parent : Map := null;
182
Cur_Node : Map := From;
186
if Cur_Node = null then
190
elsif Key > Cur_Node.Key then
193
elsif Key < Cur_Node.Key then
201
Cur_Node := Cur_Node.Children (Slot);
204
if Cur_Node.Children (Before) = null then
205
if Cur_Node.Children (After) = null then
208
Result := Cur_Node.Children (After);
211
elsif Cur_Node.Children (After) = null then
212
Result := Cur_Node.Children (Before);
215
-- At this point, deleting the node involves walking down the tree.
216
-- it is not much more effort to rebalance (and actually simpler to program)
217
Linearize (Cur_Node.Children (Before), Result, Last, Count1);
218
Linearize (Cur_Node.Children (After), Last.Children (After), Last, Count2);
219
Rebalance (Result, Count1 + Count2, Last);
222
if Parent = null then
225
Parent.Children (Slot) := Result;
234
function Fetch (From : Map; Key : Key_type) return Value_type is
235
Cur_Node : constant Map := Get_Node (From, Key);
237
if Cur_Node = null then
240
return Cur_Node.Value;
248
function Fetch (From : Map; Key : Key_type; Default_Value : Value_Type) return Value_type is
249
Cur_Node : constant Map := Get_Node (From, Key);
251
if Cur_Node = null then
252
return Default_Value;
254
return Cur_Node.Value;
262
function Is_Present (Within : Map; Key : Key_type) return Boolean is
264
return Get_Node (Within, Key) /= null;
271
procedure Iterate (On : Map) is
277
Iterate(On.Children (Before));
278
Action(On.Key, On.Value);
279
Iterate(On.Children (After));
286
procedure Clear (The_Map : in out Map) is
288
if The_Map = null then
292
Clear (The_Map.Children (Before));
293
Clear (The_Map.Children (After));
297
-------------------------------
298
-- Generic_Clear_And_Release --
299
-------------------------------
301
procedure Generic_Clear_And_Release (The_Map : in out Map) is
303
if The_Map = null then
307
Clear (The_Map.Children (Before));
308
Clear (The_Map.Children (After));
309
Release (The_Map.Value);
311
end Generic_Clear_And_Release;
317
function Is_Empty (The_Map : in Map) return Boolean is
319
return The_Map = null;