-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with GNAT.Heap_Sort_G;

package body GNAT.Table.Sort is

   ----------------
   -- Sort_Table --
   ----------------

   procedure Sort_Table is

      Temp : Table_Component_Type;
      --  A temporary position to simulate index 0

      --  Local subprograms

      function Index_Of (Idx : Natural) return Table_Index_Type;
      --  Return index of Idx'th element of table

      function Lower_Than (Op1, Op2 : Natural) return Boolean;
      --  Compare two components

      procedure Move (From : Natural;
                      To   : Natural);
      --  Move one component

      package Heap_Sort is new GNAT.Heap_Sort_G (Move, Lower_Than);

      --------------
      -- Index_Of --
      --------------

      function Index_Of (Idx : Natural) return Table_Index_Type is
         J : constant Integer'Base := Table_Index_Type'Pos (First) + Idx - 1;
      begin
         return Table_Index_Type'Val (J);
      end Index_Of;

      ----------
      -- Move --
      ----------

      procedure Move (From : Natural;
                      To   : Natural) is
      begin
         if From = 0 then
            Table (Index_Of (To))  := Temp;

         elsif To = 0 then
            Temp := Table (Index_Of (From));

         else
            Table (Index_Of (To))  := Table (Index_Of (From));
         end if;
      end Move;

      ----------------
      -- Lower_Than --
      ----------------

      function Lower_Than (Op1, Op2 : Natural) return Boolean is
      begin
         if Op1 = 0 then
            return Lt (Temp, Table (Index_Of (Op2)));

         elsif Op2 = 0 then
            return Lt (Table (Index_Of (Op1)), Temp);

         else
            return Lt (Table (Index_Of (Op1)), Table (Index_Of (Op2)));
         end if;
      end Lower_Than;

      --  Start of processing for Sort_Table

   begin
      Heap_Sort.Sort (Natural (Last - First) + 1);
   end Sort_Table;

end GNAT.Table.Sort;
