gid_12.0.0_86d6be08/gid-buffering.adb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
with Ada.IO_Exceptions;

package body GID.Buffering is

  procedure Fill_Buffer (b : in out Input_Buffer);
  --  ^ Spec here to avoid warning by 'Get_Byte' below (GNAT 2009):
  --  warning: call to subprogram with no separate spec prevents inlining

  procedure Fill_Buffer (b : in out Input_Buffer)
  is
    --
    procedure BlockRead (
      buffer       :    out Byte_Array;
      actually_read :    out Natural
    )
    is
      use Ada.Streams;
      Last_Read : Stream_Element_Offset;
    begin
      if is_mapping_possible then
        declare
          SE_Buffer_mapped : Stream_Element_Array (1 .. buffer'Length);
          --  direct mapping: buffer = SE_Buffer_mapped
          for SE_Buffer_mapped'Address use buffer'Address;
          pragma Import (Ada, SE_Buffer_mapped);
        begin
          Read (b.stream.all, SE_Buffer_mapped, Last_Read);
        end;
      else
        declare
          SE_Buffer : Stream_Element_Array (1 .. buffer'Length);
          --  need to copy array (slightly slower)
        begin
          Read (b.stream.all, SE_Buffer, Last_Read);
          for i in buffer'Range loop
            buffer (i) := U8 (SE_Buffer (Stream_Element_Offset (i - buffer'First) + SE_Buffer'First));
          end loop;
        end;
      end if;
      actually_read := Natural (Last_Read);
    end BlockRead;
    --
  begin
    BlockRead (
      buffer        => b.data,
      actually_read => b.MaxInBufIdx
    );
    b.InputEoF := b.MaxInBufIdx = 0;
    b.InBufIdx := 1;
  end Fill_Buffer;

  procedure Attach_Stream (
    b   :    out Input_Buffer;
    stm : in     Stream_Access
  )
  is
  begin
    b.stream := stm;
    --  Fill_Buffer(b) will be performed on first call of Get_Byte
  end Attach_Stream;

  function Is_stream_attached (b : Input_Buffer) return Boolean is
  begin
    return b.stream /= null;
  end Is_stream_attached;

  procedure Get_Byte (b : in out Input_Buffer; byte : out U8) is
  begin
    if b.InBufIdx > b.MaxInBufIdx then
      Fill_Buffer (b);
      if b.InputEoF then
        raise Ada.IO_Exceptions.End_Error;
      end if;
    end if;
    byte := b.data (b.InBufIdx);
    b.InBufIdx := b.InBufIdx + 1;
  end Get_Byte;

end GID.Buffering;