File : aws-containers-tables.adb


------------------------------------------------------------------------------

--                              Ada Web Server                              --

--                                                                          --

--                         Copyright (C) 2000-2001                          --

--                                ACT-Europe                                --

--                                                                          --

--  Authors: Dmitriy Anisimkov - Pascal Obry                                --

--                                                                          --

--  This library 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 of the License, or (at   --

--  your option) any later version.                                         --

--                                                                          --

--  This library 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 this library; if not, write to the Free Software Foundation, --

--  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.          --

--                                                                          --

--  As a special exception, if other files instantiate generics from this   --

--  unit, or you link this unit with other files to produce an executable,  --

--  this  unit  does not  by itself cause  the resulting executable to be   --

--  covered by the GNU General Public License. This exception does not      --

--  however invalidate any other reasons why the executable file  might be  --

--  covered by the  GNU Public License.                                     --

------------------------------------------------------------------------------


--  $Id: aws-containers-tables.adb,v 1.1 2003/10/05 19:59:53 Jano Exp $


--  Parameters name/value are put into the GNAT.Dynamic_Tables.Table_Type

--  (Data field). The name as a key and the numeric index as a value is

--  placing to the AVL Tree for the fast find all Name/Value pairs with the

--  same name. Each value of the AVL Tree is a table of numeric indexes

--  in the Data field. The parameters must be accessible

--  through their string index by name and also using an numeric index in

--  the place order. So given a set of parameters (K1=V1, K2=V2...),

--  one must be able to ask for the value for K1 but also the name of the

--  second key or the value of the third key.

--

--  Each K/V pair is then inserted into the Data table for access by numeric

--  index. And its numeric index is placing to the AVL tree indexed by name.

--  The AVL Tree values is a tables of numeric indexes in the Data table.


with Ada.Characters.Handling;

package body AWS.Containers.Tables is

   use Ada.Strings.Unbounded;

   Missing_Item_Error : exception
      renames Index_Table.Missing_Item_Error;

   -----------

   -- Count --

   -----------


   function Count (Table : in Table_Type) return Natural is
   begin
      pragma Assert (Table.Index /= null);
      return Data_Table.Last (Table.Data);
   end Count;

   -----------

   -- Count --

   -----------


   function Count
     (Table : in Table_Type;
      Name           : in String)
      return Natural
   is
      Value : Name_Index_Table;
   begin
      pragma Assert (Table.Index /= null);
      Get_Value
        (Table.Index.all,
         Normalize_Name (Name, not Table.Case_Sensitive),
         Value);

      return Natural (Name_Indexes.Last (Value));

   exception
      when Missing_Item_Error =>
         return 0;
   end Count;

   -----------

   -- Exist --

   -----------


   function Exist
     (Table : in Table_Type;
      Name  : in String)
      return Boolean is
   begin
      pragma Assert (Table.Index /= null);
      return Is_Present
        (Table.Index.all,
         Normalize_Name (Name, not Table.Case_Sensitive));
   end Exist;

   ---------

   -- Get --

   ---------


   function Get
     (Table : in Table_Type;
      Name  : in String;
      N     : in Positive := 1)
      return String is
   begin
      return Internal_Get (Table, Name, N);
   end Get;

   function Get
     (Table : in Table_Type;
      N     : in Positive)
      return Element
   is
   begin
      pragma Assert (Table.Index /= null);

      if N <= Data_Table.Last (Table.Data) then
         return Table.Data.Table (N).all;
      else
         return
           (Name_Length  => 0,
            Value_Length => 0,
            Name         => "",
            Value        => "");
      end if;
   end Get;

   --------------

   -- Get_Name --

   --------------


   function Get_Name
     (Table : in Table_Type;
      N     : in Positive := 1)
      return String is
   begin
      pragma Assert (Table.Index /= null);
      if N <= Data_Table.Last (Table.Data) then
         return Table.Data.Table (N).Name;
      else
         return "";
      end if;
   end Get_Name;

   ---------------

   -- Get_Names --

   ---------------


   function Get_Names
     (Table : in Table_Type;
      Sort  : in Boolean := False)
      return VString_Array
   is

      procedure Process
        (Key      : in     String;
         Value    : in     Name_Index_Table;
         Order    : in     Positive;
         Continue : in out Boolean);

      Result : VString_Array (1 .. Name_Count (Table));

      -------------

      -- Process --

      -------------


      procedure Process
        (Key      : in     String;
         Value    : in     Name_Index_Table;
         Order    : in     Positive;
         Continue : in out Boolean)
      is
         pragma Warnings (Off, Value);
         pragma Warnings (Off, Continue);
      begin
         Result (Order) := To_Unbounded_String (Key);
      end Process;

      -----------------------

      -- Disorder_Traverse --

      -----------------------


      procedure Disorder_Traverse is
         new Index_Table.Disorder_Traverse_G (Process);

      ------------------

      -- Traverse_Asc --

      ------------------


      procedure Traverse_Asc is
         new Index_Table.Traverse_Asc_G (Process);

   begin
      if Table.Index /= null then
         if Sort then
            Traverse_Asc (Index_Table.Table_Type (Table.Index.all));
         else
            Disorder_Traverse (Index_Table.Table_Type (Table.Index.all));
         end if;
      end if;

      return Result;
   end Get_Names;

   ---------------

   -- Get_Value --

   ---------------


   function Get_Value
     (Table : in Table_Type;
      N              : in Positive := 1)
      return String is
   begin
      pragma Assert (Table.Index /= null);

      if N <= Data_Table.Last (Table.Data) then
         return Table.Data.Table (N).Value;
      else
         return "";
      end if;
   end Get_Value;

   ----------------

   -- Get_Values --

   ----------------


   function Get_Values
     (Table : in Table_Type;
      Name  : in String)
      return VString_Array
   is
      Value : Name_Index_Table;
   begin
      pragma Assert (Table.Index /= null);

      Get_Value
        (Table.Index.all,
         Normalize_Name (Name, not Table.Case_Sensitive),
         Value);

      declare
         Last :  Key_Positive := Name_Indexes.Last (Value);
         Result : VString_Array (1 .. Natural (Last));
      begin
         for I in 1 .. Last loop
            Result (Natural (I)) := To_Unbounded_String (Table.Data.Table
               (Value.Table (I)).Value);
         end loop;
         return Result;
      end;

   exception
      when Missing_Item_Error =>
         return (1 .. 0 => Null_Unbounded_String);
   end Get_Values;

   ------------------

   -- Internal_Get --

   ------------------


   function Internal_Get
     (Table : in Table_Type;
      Name  : in String;
      N     : in Natural)
      return String
   is
      Value : Name_Index_Table;
   begin
      pragma Assert (Table.Index /= null);

      Get_Value
        (Table.Index.all,
         Normalize_Name (Name, not Table.Case_Sensitive),
         Value);

      if Key_Positive (N) <= Name_Indexes.Last (Value) then
         return Table.Data.Table (Value.Table (Key_Positive (N))).Value;
      else
         return "";
      end if;

   exception
      when Missing_Item_Error =>
         return "";
   end Internal_Get;

   ----------------

   -- Name_Count --

   ----------------


   function Name_Count (Table : in Table_Type) return Natural is
   begin
      if Table.Index = null then
         return 0;
      else
         return Size (Table.Index.all);
      end if;
   end Name_Count;

   --------------------

   -- Normalize_Name --

   --------------------


   function Normalize_Name
     (Name : in String; To_Upper : in Boolean)
      return String is
   begin
      if To_Upper then
         return Ada.Characters.Handling.To_Upper (Name);
      else
         return Name;
      end if;
   end Normalize_Name;

end AWS.Containers.Tables;