with Bits; use Bits;
package body Keccak_C is
   -- C interface

   procedure C_Get_Size(Size: out Interfaces.C.size_t) is
   begin
      Size := C_Context'Size / 8;
   end C_Get_Size;

   function C_Begin return C_Context_Access is
      Result : C_Context_Access;
   begin
      Result := new C_Context;
      KeccakBegin(Result.all);
      return Result;
   end C_Begin;

   procedure C_Hash(Ctx: in C_Context_Access;
                    Input: Char_Star;
                    Len: Interfaces.C.size_t) is
      L: Natural := Natural(Len);
      S: String(1..L);
      B: Bitstream(1..S'Length*8);
      Ptr: Char_Star := Input;
   begin
      if Input = null then
         raise Strings.Dereference_Error;
      end if;
      for Chr of S loop
         Chr := Character(Ptr.all);
         Char_Ptrs.Increment(Ptr);
      end loop;
      ToBitstream(S, B);
      KeccakHash(Ctx.all, B);
   end C_Hash;

   procedure C_End(Ctx: C_Context_Access;
                   Output: Char_Star;
                   Len: Interfaces.C.Size_T) is
      L: Natural := Natural(Len);
      S: String(1..L);
      B: Bitstream(1..S'Length*8);
      Ptr: Char_Star := Output;
   begin
      if Output = null then
         raise Strings.Dereference_Error;
      end if;
      KeccakEnd(Ctx.all, B);
      ToString(B, S);
      for Chr of S loop
         Ptr.all := Interfaces.C.char(Chr);
         Char_Ptrs.Increment(Ptr);
      end loop;
      -- Len = Count
   end C_End;

   procedure C_Context_Deallocate is new Ada.Unchecked_Deallocation
     (C_Context, C_Context_Access);

   procedure C_Deallocate(Ctx: in out C_Context_Access) is
   begin
      C_Context_Deallocate(Ctx);
   end C_Deallocate;
end Keccak_C;
