-------------------------------------------------------------------------------
--
--  This file is part of AdaBrowse.
--
-- <STRONG>Copyright (c) 2002 by Thomas Wolf.</STRONG>
-- <BLOCKQUOTE>
--    AdaBrowse 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. AdaBrowse is distributed in the hope that it will be
--    useful, but <EM>without any warranty</EM>; without even the implied
--    warranty of <EM>merchantability or fitness for a particular purpose.</EM>
--    See the GNU General Public License for  more details. You should have
--    received a copy of the GNU General Public License with this distribution,
--    see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
--    Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
--    USA.
-- </BLOCKQUOTE>
--
-- <DL><DT><STRONG>
-- Author:</STRONG><DD>
--   Thomas Wolf  (TW)
--   <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
--
-- <DL><DT><STRONG>
-- Purpose:</STRONG><DD>
--   Handling of "pathes": prefix URLs defined for cross-references.</DL>
--
-- <!--
-- Revision History
--
--   20-AUG-2002   TW  Created from old AD.Pathes.
--   28-AUG-2002   TW  Correction in 'Add_Path' for redefinitions.
-- -->
-------------------------------------------------------------------------------

pragma License (GPL);

with Ada.Strings.Unbounded;
with Ada.Unchecked_Deallocation;

with Util.Strings;

package body AD.HTML.Pathes is

   package ASU renames Ada.Strings.Unbounded;

   use Util.Strings;

   --  We do longest-prefix matches in 'Get_Path' below. Probably the most
   --  efficient data structure for this would be a trie, but since I assume
   --  that there won't be too many different pathes with keys that them-
   --  selves are prefixes of one another, this would be overkill.

   type Path;
   type Path_Ptr is access Path;
   type Path is
      record
         Key   : ASU.Unbounded_String;
         Value : ASU.Unbounded_String;
         Next  : Path_Ptr;
      end record;

   procedure Free is
      new Ada.Unchecked_Deallocation (Path, Path_Ptr);

   Anchor : Path_Ptr;

   procedure Add_Path
     (Key   : in String;
      Value : in String)
   is
      use type ASU.Unbounded_String;

      P, Q : Path_Ptr;
      K    : ASU.Unbounded_String :=
        ASU.To_Unbounded_String (To_Lower (Key));
   begin
      P := Anchor;
      while P /= null loop
         exit when Key'Length > ASU.Length (P.Key);
         if K = P.Key then
            --  Hey, we already have that exact key!
            if Value'Last < Value'First then
               --  Value is the empty string: let's remove this path
               --  altogether.
               if Q = null then
                  Anchor := P.Next;
               else
                  Q.Next := P.Next;
               end if;
               Free (P);
            else
               --  Overwrite the existing entry!
               P.Value := ASU.To_Unbounded_String (Value);
            end if;
            return;
         end if;
         Q := P; P := P.Next;
      end loop;
      --  New entry.
      if Q = null then
         Anchor := new Path'(K, ASU.To_Unbounded_String (Value), P);
      else
         Q.Next := new Path'(K, ASU.To_Unbounded_String (Value), P);
      end if;
      --  The list is ordered by key length, earlier keys first.
   end Add_Path;

   function Get_Path
     (Unit_Name : in String)
     return String
   is
      P : Path_Ptr := Anchor;
      U : constant String := To_Lower (Unit_Name);
   begin
      while P /= null loop
         if Is_Prefix (U, ASU.To_String (P.Key)) then
            return ASU.To_String (P.Value);
         end if;
         P := P.Next;
      end loop;
      return "";
   end Get_Path;

end AD.HTML.Pathes;
