spat_1.3.0_4ad4ab14/src/core/spat-entity-tree.adb

 1
 2
 3
 4
 5
 6
 7
 8
 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
------------------------------------------------------------------------------
--  Copyright (C) 2020 by Heisenbug Ltd. (gh+spat@heisenbug.eu)
--
--  This work is free. You can redistribute it and/or modify it under the
--  terms of the Do What The Fuck You Want To Public License, Version 2,
--  as published by Sam Hocevar. See the LICENSE file for more details.
------------------------------------------------------------------------------
pragma License (Unrestricted);

with Ada.Containers.Bounded_Vectors;

package body SPAT.Entity.Tree is

   package body Generic_Sorting is

      package Cursor_Lists is new
        Ada.Containers.Bounded_Vectors (Index_Type   => Positive,
                                        Element_Type => Cursor,
                                        "="          => "=");

      ------------------------------------------------------------------------
      --  Sort
      --
      --  This is a "sort by proxy".  The way it works that we first copy the
      --  children's cursors into a vector which then gets sorted.  After this
      --  step, we rearrange the subtree in the order of elements in the
      --  vector.
      ------------------------------------------------------------------------
      procedure Sort (Tree   : in out T;
                      Parent : in     Cursor) is
         Num_Children : constant Ada.Containers.Count_Type :=
           Entity.Tree.Child_Count (Parent => Parent);
         use type Ada.Containers.Count_Type;
         The_List : Cursor_Lists.Vector (Capacity => Num_Children);
      begin
         if Num_Children < 2 then
            --  No elements to sort.
            return;
         end if;

         --  Copy the tree's cursor into The_List.
         for C in Tree.Iterate_Children (Parent => Parent) loop
            The_List.Append (New_Item => C);
         end loop;

         --  Sort the list with our tree cursors.
         declare
            ------------------------------------------------------------------
            --  Before
            --
            --  Comparison operator.
            ------------------------------------------------------------------
            function Before (Left  : in Cursor;
                             Right : in Cursor) return Boolean is
              (Before -- from the generic instance
                 (Left  => Entity.Tree.Element (Position => Left),
                  Right => Entity.Tree.Element (Position => Right)));

            package Sorting is new
              Cursor_Lists.Generic_Sorting ("<" => Before);
         begin
            Sorting.Sort (Container => The_List);
         end;

         --  Now rearrange the subtree according to our sorting order.
         for C of The_List loop
            Tree.Splice_Subtree (Parent   => Parent,
                                 Before   => Entity.Tree.No_Element,
                                 Position => C);
         end loop;
      end Sort;

   end Generic_Sorting;

end SPAT.Entity.Tree;