--  with Interfaces.C;            use Interfaces.C;
--  with Interfaces.C.Strings;    use Interfaces.C.Strings;

with Ada.Finalization;        use Ada.Finalization;

with System;                  use System;
--  with System.Storage_Elements; use System.Storage_Elements;

package Jwa.Strings is
   pragma Preelaborate;

   subtype Char_8 is Character;

   type String_8_Data (Length : Natural) is record
      chr : aliased String (1 .. Length);
      Terminator : aliased Character := Character'Val (0);
   end record;
   pragma Pack (String_8_Data);

   type String_8_Ptr is access all String_8_Data;

   Null_String_8_Ptr : constant String_8_Ptr;

   type String_8 is new Controlled with private;
   pragma Preelaborable_Initialization (String_8);

      -- String_8 specific functions
      function Create (Ptr : String_8_Ptr) return String_8;
      procedure Unique (Item : in out String_8);
      function p (Item : String_8) return String_8_Ptr;
      --

      -- create/convert

      function Create (Source : String) return String_8;
      function To_String_8 (Source : String) return String_8 renames Create;
      function "+" (Source : String) return String_8 renames Create;

      function Create (Length : Natural) return String_8;

      function To_Ada (Source : String_8) return String;
      function To_String (Source : String_8) return String renames To_Ada;
      function "+" (Source : String_8) return String renames To_Ada;

      -- set
      procedure Set (Target : out String_8; Ptr : String_8_Ptr);
      procedure Set_String_8 (Target : out String_8; Ptr : String_8_Ptr)
        renames Set;

      procedure Set (Target : out String_8; Source : String);
      procedure Set_String_8 (Target : out String_8; Source : String)
        renames Set;

      procedure Set_Length (Target : in out String_8; Length : Natural);

      -- Mere string facilities --
      function Length (Source : String_8) return Natural;

      -- procedure Append (Source : in out String_8; New_Item : String_8);


   -- end String_8;

   Null_String_8 : constant String_8;

private

   Null_String_8_Data : aliased String_8_Data (0);
   Null_String_8_Ptr : constant String_8_Ptr :=
     Null_String_8_Data'Access;

   type Reference_Counter_Type is record
      rc : Integer := 1;
      pragma Volatile (rc);
   end record;

--     Reference_Counter_Size : constant Storage_Count :=
--       Reference_Counter_Type'Max_Size_In_Storage_Elements;

   type String_8_Internal (Length : Integer) is record
      Counter : aliased Reference_Counter_Type;
      Data : aliased String_8_Data (Length);
   end record;
   pragma Pack (String_8_Internal);

   type String_8_Internal_Ptr is access all String_8_Internal;

   type String_8 is new Controlled with record
      Ptr : String_8_Internal_Ptr;
   end record;

   overriding procedure Adjust (Object : in out String_8);
   overriding procedure Finalize (Object : in out String_8);

   Null_String_8 : constant String_8 :=
     (Controlled with Ptr => null);

end Jwa.Strings;
