aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/config/gre/files
Commit message (Collapse)AuthorAgeFilesLines
* trunk-47381HEADmasterJames2015-11-041-0/+237
id='n54' href='#n54'>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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
--  Lists data type.
--  Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold
--
--  GHDL is free software; you can redistribute it and/or modify it under
--  the terms of the GNU General Public License as published by the Free
--  Software Foundation; either version 2, or (at your option) any later
--  version.
--
--  GHDL 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
--  along with GHDL; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.
with Tables;

package body Lists is
   type List_Record is record
      First : Chunk_Index_Type;
      Last : Chunk_Index_Type;
      Chunk_Idx : Nat32;
      Nbr : Natural;
   end record;

   package Listt is new Tables
     (Table_Component_Type => List_Record,
      Table_Index_Type => List_Type,
      Table_Low_Bound => 2,
      Table_Initial => 128);

   package Chunkt is new Tables
     (Table_Component_Type => Chunk_Type,
      Table_Index_Type => Chunk_Index_Type,
      Table_Low_Bound => 1,
      Table_Initial => 128);

   Chunk_Free_List : Chunk_Index_Type := No_Chunk_Index;

   procedure Free_Chunk (Idx : Chunk_Index_Type) is
   begin
      Chunkt.Table (Idx).Next := Chunk_Free_List;
      Chunk_Free_List := Idx;
   end Free_Chunk;

   function Get_Free_Chunk return Chunk_Index_Type
   is
      Res : Chunk_Index_Type;
   begin
      if Chunk_Free_List /= No_Chunk_Index then
         Res := Chunk_Free_List;
         Chunk_Free_List := Chunkt.Table (Res).Next;
         return Res;
      else
         return Chunkt.Allocate;
      end if;
   end Get_Free_Chunk;

   function Get_Nbr_Elements (List: List_Type) return Natural is
   begin
      return Listt.Table (List).Nbr;
   end Get_Nbr_Elements;

   function Is_Empty (List : List_Type) return Boolean is
   begin
      return Listt.Table (List).Nbr = 0;
   end Is_Empty;

   procedure Append_Element (List: List_Type; Element: El_Type)
   is
      L : List_Record renames Listt.Table (List);
      C : Chunk_Index_Type;
   begin
      L.Chunk_Idx := L.Chunk_Idx + 1;
      if L.Chunk_Idx < Chunk_Len then
         Chunkt.Table (L.Last).Els (L.Chunk_Idx) := Element;
      else
         C := Get_Free_Chunk;
         Chunkt.Table (C).Next := No_Chunk_Index;
         Chunkt.Table (C).Els (0) := Element;
         L.Chunk_Idx := 0;
         if L.Nbr = 0 then
            L.First := C;
         else
            Chunkt.Table (L.Last).Next := C;
         end if;
         L.Last := C;
      end if;
      L.Nbr := L.Nbr + 1;
   end Append_Element;

   function Get_First_Element (List: List_Type) return El_Type
   is
      L : List_Record renames Listt.Table (List);
   begin
      pragma Assert (L.Nbr > 0);
      return Chunkt.Table (L.First).Els (0);
   end Get_First_Element;

   -- Add (append) an element only if it was not already present in the list.
   procedure Add_Element (List: List_Type; El: El_Type)
   is
      It : Iterator;
   begin
      It := Iterate (List);
      while Is_Valid (It) loop
         if Get_Element (It) = El then
            return;
         end if;
         Next (It);
      end loop;

      Append_Element (List, El);
   end Add_Element;

   --  Chain of unused lists.
   List_Free_Chain : List_Type := Null_List;

   function Create_List return List_Type
   is
      Res : List_Type;
   begin
      if List_Free_Chain = Null_List then
         Listt.Increment_Last;
         Res := Listt.Last;
      else
         Res := List_Free_Chain;
         List_Free_Chain := List_Type (Listt.Table (Res).Chunk_Idx);
      end if;
      Listt.Table (Res) := List_Record'(First => No_Chunk_Index,
                                        Last => No_Chunk_Index,
                                        Chunk_Idx => Chunk_Len,
                                        Nbr => 0);
      return Res;
   end Create_List;

   procedure Destroy_List (List : in out List_Type)
   is
      C, Next_C : Chunk_Index_Type;
   begin
      if List = Null_List then
         return;
      end if;

      C := Listt.Table (List).First;
      while C /= No_Chunk_Index loop
         Next_C := Chunkt.Table (C).Next;
         Free_Chunk (C);
         C := Next_C;
      end loop;

      Listt.Table (List).Chunk_Idx := Nat32 (List_Free_Chain);
      List_Free_Chain := List;

      List := Null_List;
   end Destroy_List;

   procedure Initialize is
   begin
      Listt.Free;
      Listt.Init;
      Chunkt.Free;
      Chunkt.Init;
      List_Free_Chain := Null_List;
      Chunk_Free_List := No_Chunk_Index;
   end Initialize;

   function Iterate (List : List_Type) return Iterator
   is
      L : List_Record renames Listt.Table (List);
   begin
      return Iterator'(Chunk => L.First,
                       Chunk_Idx => 0,
                       Remain => Int32 (L.Nbr));
   end Iterate;

   function Iterate_Safe (List : List_Type) return Iterator is
   begin
      if List = Null_List then
         return Iterator'(Chunk => No_Chunk_Index,
                          Chunk_Idx => 0,
                          Remain => 0);
      end if;
      return Iterate (List);
   end Iterate_Safe;

   function Is_Valid (It : Iterator) return Boolean is
   begin
      return It.Remain > 0;
   end Is_Valid;

   procedure Next (It : in out Iterator) is
   begin
      It.Chunk_Idx := It.Chunk_Idx + 1;
      if It.Chunk_Idx = Chunk_Len then
         It.Chunk := Chunkt.Table (It.Chunk).Next;
         It.Chunk_Idx := 0;
      end if;
      It.Remain := It.Remain - 1;
   end Next;

   function Get_Element (It : Iterator) return El_Type is
   begin
      return Chunkt.Table (It.Chunk).Els (It.Chunk_Idx);
   end Get_Element;

   procedure Set_Element (It : Iterator; El : El_Type) is
   begin
      Chunkt.Table (It.Chunk).Els (It.Chunk_Idx) := El;
   end Set_Element;
end Lists;