9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR --
-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN --
-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF --
-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --
------------------------------------------------------------------------------
with Ada.Unchecked_Deallocation;
package body Natools.Smaz.Tools is
package Sx renames Natools.S_Expressions;
function Build_Node
(Map : Dictionary_Maps.Map;
Empty_Value : Natural)
return Trie_Node;
function Dummy_Hash (Value : String) return Natural;
-- Placeholder for Hash member, always raises Program_Error
function Image (B : Boolean) return String;
-- Return correctly-cased image of B
procedure Free is new Ada.Unchecked_Deallocation
(Trie_Node, Trie_Node_Access);
------------------------------
-- Local Helper Subprograms --
------------------------------
function Build_Node
(Map : Dictionary_Maps.Map;
Empty_Value : Natural)
return Trie_Node
is
function First_Character (S : String) return Character
is (S (S'First));
function Is_Current (Cursor : Dictionary_Maps.Cursor; C : Character)
return Boolean
is (Dictionary_Maps.Has_Element (Cursor)
and then First_Character (Dictionary_Maps.Key (Cursor)) = C);
function Suffix (S : String) return String;
function Suffix (S : String) return String is
begin
return S (S'First + 1 .. S'Last);
end Suffix;
use type Ada.Containers.Count_Type;
Cursor : Dictionary_Maps.Cursor;
Result : Trie_Node
:= (Ada.Finalization.Controlled with
Is_Leaf => False,
Index => Empty_Value,
Children => (others => null));
begin
pragma Assert (Dictionary_Maps.Length (Map) >= 1);
Cursor := Dictionary_Maps.Find (Map, "");
if Dictionary_Maps.Has_Element (Cursor) then
Result.Index := Natural (Dictionary_Maps.Element (Cursor));
end if;
for C in Character'Range loop
Cursor := Dictionary_Maps.Ceiling (Map, (1 => C));
if Is_Current (Cursor, C) then
if not Is_Current (Dictionary_Maps.Next (Cursor), C)
and then Dictionary_Maps.Key (Cursor) = (1 => C)
then
Result.Children (C)
:= new Trie_Node'(Ada.Finalization.Controlled with
Is_Leaf => True,
Index => Natural (Dictionary_Maps.Element (Cursor)));
else
declare
New_Map : Dictionary_Maps.Map;
begin
loop
Dictionary_Maps.Insert
(New_Map,
Suffix (Dictionary_Maps.Key (Cursor)),
Dictionary_Maps.Element (Cursor));
Dictionary_Maps.Next (Cursor);
exit when not Is_Current (Cursor, C);
end loop;
Result.Children (C)
:= new Trie_Node'(Build_Node (New_Map, Empty_Value));
end;
end if;
end if;
end loop;
return Result;
end Build_Node;
function Dummy_Hash (Value : String) return Natural is
pragma Unreferenced (Value);
begin
raise Program_Error with "Dummy_Hash called";
return 0;
end Dummy_Hash;
|
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
end To_Dictionary;
---------------------------------
-- Dynamic Dictionary Searches --
---------------------------------
overriding procedure Adjust (Node : in out Trie_Node) is
begin
if not Node.Is_Leaf then
for C in Node.Children'Range loop
if Node.Children (C) /= null then
Node.Children (C) := new Trie_Node'(Node.Children (C).all);
end if;
end loop;
end if;
end Adjust;
overriding procedure Finalize (Node : in out Trie_Node) is
begin
if not Node.Is_Leaf then
for C in Node.Children'Range loop
Free (Node.Children (C));
end loop;
end if;
end Finalize;
procedure Initialize (Trie : out Search_Trie; Dict : in Dictionary) is
Map : Dictionary_Maps.Map;
begin
for I in Dict.Offsets'Range loop
Dictionary_Maps.Insert (Map, Dict_Entry (Dict, I), I);
end loop;
Trie := (Not_Found => Natural (Dict.Dict_Last) + 1,
Root => Build_Node (Map, Natural (Dict.Dict_Last) + 1));
end Initialize;
function Linear_Search (Value : String) return Natural is
Result : Ada.Streams.Stream_Element := 0;
begin
for S of List_For_Linear_Search loop
exit when S = Value;
Result := Result + 1;
|
361
362
363
364
365
366
367
368
369
370
371
372
373
374
|
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
if Dictionary_Maps.Has_Element (Cursor) then
return Natural (Dictionary_Maps.Element (Cursor));
else
return Natural (Ada.Streams.Stream_Element'Last);
end if;
end Map_Search;
function Search (Trie : in Search_Trie; Value : in String) return Natural is
Index : Positive := Value'First;
Position : Trie_Node_Access;
begin
if Value'Length = 0 then
return Trie.Not_Found;
end if;
Position := Trie.Root.Children (Value (Index));
loop
if Position = null then
return Trie.Not_Found;
end if;
Index := Index + 1;
if Index not in Value'Range then
return Position.Index;
elsif Position.Is_Leaf then
return Trie.Not_Found;
end if;
Position := Position.Children (Value (Index));
end loop;
end Search;
procedure Set_Dictionary_For_Map_Search (Dict : in Dictionary) is
begin
Dictionary_Maps.Clear (Search_Map);
for I in Dict.Offsets'Range loop
Dictionary_Maps.Insert (Search_Map, Dict_Entry (Dict, I), I);
|