2014-06-05 15:26:37 +00:00
|
|
|
with H2.Ascii;
|
|
|
|
|
2014-06-04 17:15:52 +00:00
|
|
|
separate (H2.IO)
|
|
|
|
|
|
|
|
package body File is
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| PRIVATE ROUTINES
|
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
procedure OS_Read_File (File: in out File_Record;
|
|
|
|
Buffer: in out System_Byte_Array;
|
|
|
|
Length: out System_Length) is
|
|
|
|
begin
|
|
|
|
OS.File.Read (File.File, Buffer, Length);
|
|
|
|
File.EOF := (Length <= 0);
|
|
|
|
end OS_Read_File;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
procedure Compact_Buffer (Buffer: in out File_Buffer) is
|
|
|
|
A, B, L: System_Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
A := Buffer.Pos;
|
|
|
|
B := Buffer.Last;
|
|
|
|
L := Buffer.Pos - Buffer.Data'First + 1;
|
|
|
|
|
|
|
|
Buffer.Pos := Buffer.Pos - L; -- should be same as Buffer.Data'First - 1
|
|
|
|
Buffer.Last := Buffer.Last - L;
|
|
|
|
|
|
|
|
Buffer.Data(Buffer.Pos + 1 .. Buffer.Last) := Buffer.Data(A + 1 .. B);
|
|
|
|
end Compact_Buffer;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
|
|
|
procedure Copy_Array (Dst: in out System_Byte_Array;
|
|
|
|
Src: in System_Byte_Array;
|
|
|
|
Length: in System_Length) is
|
|
|
|
pragma Inline (Copy_Array);
|
|
|
|
begin
|
|
|
|
Dst(Dst'First .. Dst'First + Length - 1) := Src(Src'First .. Src'First + Length - 1);
|
|
|
|
end Copy_Array;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
function Is_Empty (Buf: in File_Buffer) return Standard.Boolean is
|
|
|
|
pragma Inline (Is_Empty);
|
|
|
|
begin
|
|
|
|
return Buf.Pos >= Buf.Last;
|
|
|
|
end Is_Empty;
|
|
|
|
|
|
|
|
procedure Set_Length (Buf: in out File_Buffer; Length: in System_Length) is
|
|
|
|
pragma Inline (Set_Length);
|
|
|
|
begin
|
|
|
|
Buf.Pos := Buf.Data'First - 1; -- this should be 0
|
|
|
|
Buf.Last := Buf.Pos + Length;
|
|
|
|
end Set_Length;
|
|
|
|
|
|
|
|
procedure Set_Option_Bits (Option: in out Option_Record;
|
2014-06-21 16:31:49 +00:00
|
|
|
Bits: in Option_Bits) is
|
2014-06-19 14:13:19 +00:00
|
|
|
begin
|
|
|
|
Option.Bits := Option.Bits or Bits;
|
|
|
|
end Set_Option_Bits;
|
|
|
|
|
|
|
|
procedure Clear_Option_Bits (Option: in out Option_Record;
|
|
|
|
Bits: in Option_Bits) is
|
|
|
|
begin
|
|
|
|
Option.Bits := Option.Bits and not Bits;
|
|
|
|
end Clear_Option_Bits;
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
|
|
|
|
-- This function is platform dependent. It is placed separately in a
|
|
|
|
-- platform specific directory.
|
|
|
|
function Get_Default_Option return Option_Record is separate;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| OPEN AND CLOSE
|
|
|
|
--|-----------------------------------------------------------------------
|
2014-06-17 15:23:35 +00:00
|
|
|
function Is_Open (File: in File_Record) return Standard.Boolean is
|
|
|
|
begin
|
|
|
|
return OS.File."/="(File.File, null);
|
|
|
|
end Is_Open;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-04 17:15:52 +00:00
|
|
|
procedure Open (File: in out File_Record;
|
|
|
|
Name: in Slim_String;
|
|
|
|
Flag: in Flag_Record;
|
|
|
|
Pool: in Storage_Pool_Pointer := null) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (not Is_Open(File));
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-05 15:26:37 +00:00
|
|
|
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
Set_Length (File.Rbuf, 0);
|
|
|
|
Set_Length (File.Wbuf, 0);
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
File.Option := Get_Default_Option;
|
2014-06-05 15:26:37 +00:00
|
|
|
File.EOF := Standard.False;
|
2014-06-04 17:15:52 +00:00
|
|
|
end Open;
|
|
|
|
|
|
|
|
procedure Open (File: in out File_Record;
|
|
|
|
Name: in Wide_String;
|
|
|
|
Flag: in Flag_Record;
|
|
|
|
Pool: in Storage_Pool_Pointer := null) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (not Is_Open(File));
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-05 15:26:37 +00:00
|
|
|
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
Set_Length (File.Rbuf, 0);
|
|
|
|
Set_Length (File.Wbuf, 0);
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
File.Option := Get_Default_Option;
|
2014-06-05 15:26:37 +00:00
|
|
|
File.EOF := Standard.False;
|
2014-06-04 17:15:52 +00:00
|
|
|
end Open;
|
|
|
|
|
|
|
|
procedure Close (File: in out File_Record) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-06 16:44:45 +00:00
|
|
|
Flush (File);
|
2014-06-05 15:26:37 +00:00
|
|
|
OS.File.Close (File.File);
|
2014-06-04 17:15:52 +00:00
|
|
|
File.File := null;
|
|
|
|
end Close;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
procedure Set_Option (File: in out File_Record; Option: in Option_Record) is
|
2014-06-17 15:23:35 +00:00
|
|
|
begin
|
2014-06-21 16:31:49 +00:00
|
|
|
if Slim_Character'Val(Option.LF) = Slim_Character'First or else
|
|
|
|
Wide_Character'Val(Option.LF) = Wide_Character'First then
|
|
|
|
raise Constraint_Error; -- TODO: different exception name
|
|
|
|
end if;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Option := Option;
|
|
|
|
end Set_Option;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
function Get_Option (File: in File_Record) return Option_Record is
|
2014-06-17 15:23:35 +00:00
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
return File.Option;
|
|
|
|
end Get_Option;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
|
|
|
procedure Load_Bytes (File: in out File_Record) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
pragma Assert (Is_Empty(File.Rbuf));
|
|
|
|
L1: System_Length;
|
|
|
|
begin
|
|
|
|
if File.EOF then
|
|
|
|
-- raise EOF EXCEPTION. ???
|
|
|
|
null;
|
|
|
|
else
|
|
|
|
-- Read bytes into the buffer
|
|
|
|
OS_Read_File (File, File.Rbuf.Data, L1);
|
|
|
|
Set_Length (File.Rbuf, L1);
|
|
|
|
end if;
|
|
|
|
end Load_Bytes;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
procedure Fetch_Byte (File: in out File_Record;
|
|
|
|
Item: out System_Byte;
|
|
|
|
Available: out Standard.Boolean) is
|
|
|
|
begin
|
|
|
|
-- NOTE: If no data is available, Item is not initialized in this procedure
|
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
Load_Bytes (File);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
Available := Standard.False;
|
|
|
|
else
|
|
|
|
-- Consume 1 byte
|
|
|
|
Available := Standard.True;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
|
|
|
Item := File.Rbuf.Data(File.Rbuf.Pos);
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
|
|
|
end Fetch_Byte;
|
|
|
|
|
|
|
|
procedure Fetch_Bytes (File: in out File_Record;
|
|
|
|
Item: out System_Byte_Array;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-05 15:26:37 +00:00
|
|
|
L1, L2: System_Length;
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-17 15:23:35 +00:00
|
|
|
if Is_Empty(File.Rbuf) and then File.EOF then
|
2014-06-05 15:26:37 +00:00
|
|
|
-- raise EOF EXCEPTION. ???
|
|
|
|
Length := 0;
|
2014-06-17 15:23:35 +00:00
|
|
|
else
|
2014-06-19 14:13:19 +00:00
|
|
|
L1 := File.Rbuf.Last - File.Rbuf.Pos;
|
2014-06-17 15:23:35 +00:00
|
|
|
if L1 > 0 then
|
|
|
|
-- Copy the residue over to the output buffer
|
|
|
|
if Item'Length <= L1 then
|
|
|
|
L2 := Item'Length;
|
|
|
|
else
|
|
|
|
L2 := L1;
|
|
|
|
end if;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
Copy_Array (Item, File.Rbuf.Data(File.Rbuf.Pos + 1 .. File.Rbuf.Last), L2);
|
|
|
|
File.Rbuf.Pos := File.Rbuf.Pos + L2;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
Length := L2;
|
|
|
|
else
|
|
|
|
Length := 0;
|
2014-06-05 15:26:37 +00:00
|
|
|
end if;
|
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
if Item'Length > L1 then
|
|
|
|
-- Item is not full. the internal read buffer must be empty.
|
2014-06-19 14:13:19 +00:00
|
|
|
pragma Assert (File.Rbuf.Pos >= File.Rbuf.Last);
|
2014-06-17 15:23:35 +00:00
|
|
|
|
|
|
|
L2 := Item'Length - Length; -- Remaining capacity
|
|
|
|
If L2 >= File.Rbuf.Data'Length then
|
|
|
|
-- The remaining capacity of the output buffer is
|
|
|
|
-- higher than that of the internal buffer. So read
|
|
|
|
-- directly into the output buffer.
|
|
|
|
OS_Read_File (File, Item(Item'First + Length .. Item'Last), L2);
|
|
|
|
Length := Length + L2;
|
|
|
|
else
|
|
|
|
-- Read into the internal buffer.
|
|
|
|
OS_Read_File (File, File.Rbuf.Data, L1);
|
|
|
|
Set_Length (File.Rbuf, L1);
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
if L1 < L2 then
|
|
|
|
-- the actual bytes read may be less than the remaining capacity
|
|
|
|
L2 := L1;
|
|
|
|
end if;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
-- Copy as many bytes as needed into the output buffer.
|
|
|
|
Copy_Array (Item(Item'First + Length .. Item'Last), File.Rbuf.Data, L2);
|
|
|
|
Length := Length + L2;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Rbuf.Pos := File.Rbuf.Pos + L2;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
2014-06-05 15:26:37 +00:00
|
|
|
end if;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
|
|
|
end Fetch_Bytes;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| READ SLIM STRING
|
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
procedure Read (File: in out File_Record;
|
|
|
|
Buffer: out Slim_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
pragma Assert (Buffer'Length > 0);
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
Outbuf: System_Byte_Array (Buffer'Range);
|
|
|
|
for Outbuf'Address use Buffer'Address;
|
|
|
|
begin
|
|
|
|
Fetch_Bytes (File, Outbuf, Length);
|
2014-06-04 17:15:52 +00:00
|
|
|
end Read;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
procedure Read_Line (File: in out File_Record;
|
2014-06-17 15:23:35 +00:00
|
|
|
Buffer: out Slim_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-05 15:26:37 +00:00
|
|
|
pragma Assert (Buffer'Length > 0);
|
2014-06-06 16:44:45 +00:00
|
|
|
|
|
|
|
Outbuf: System_Byte_Array (Buffer'Range);
|
|
|
|
for Outbuf'Address use Buffer'Address;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
K: System_Length;
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-05 15:26:37 +00:00
|
|
|
K := Outbuf'First - 1;
|
|
|
|
|
|
|
|
outer: loop
|
2014-06-17 15:23:35 +00:00
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
Load_Bytes (File);
|
|
|
|
exit when Is_Empty(File.Rbuf);
|
2014-06-05 15:26:37 +00:00
|
|
|
end if;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
while File.Rbuf.Pos < File.Rbuf.Last loop
|
2014-06-05 15:26:37 +00:00
|
|
|
K := K + 1;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
|
|
|
Outbuf(K) := File.Rbuf.Data(File.Rbuf.Pos);
|
2014-06-21 16:31:49 +00:00
|
|
|
if K >= Outbuf'Last or else Outbuf(K) = File.Option.LF then
|
2014-06-06 16:44:45 +00:00
|
|
|
exit outer; -- Done
|
|
|
|
end if;
|
2014-06-05 15:26:37 +00:00
|
|
|
end loop;
|
|
|
|
end loop outer;
|
|
|
|
|
|
|
|
Length := K + 1 - Outbuf'First;
|
2014-06-06 16:44:45 +00:00
|
|
|
end Read_Line;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
procedure Get_Line (File: in out File_Record;
|
|
|
|
Buffer: out Slim_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
pragma Assert (Buffer'Length > 0);
|
|
|
|
|
|
|
|
Last: System_Length;
|
|
|
|
begin
|
|
|
|
Read_Line (File, Buffer, Length);
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if Length <= 0 or else (File.Option.Bits and OPTION_CRLF_IN) = 0 then
|
|
|
|
return;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
Last := Buffer'First + Length - 1;
|
|
|
|
if Buffer(Last) = Slim_Character'Val(File.Option.LF) then
|
|
|
|
if Last > Buffer'First and then
|
|
|
|
Buffer(Last - 1) = Slim_Character'Val(File.Option.CR) then
|
|
|
|
|
|
|
|
|
|
|
|
-- Switch CR/LF to LF
|
|
|
|
Length := Length - 1;
|
|
|
|
Buffer(Last - 1) := Slim_Character'Val(File.Option.LF);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
elsif Buffer(Last) = Slim_Character'Val(File.Option.CR) then
|
|
|
|
|
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
Load_Bytes (File);
|
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
if Is_Empty(File.Rbuf) then
|
2014-06-21 16:31:49 +00:00
|
|
|
return;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
2014-06-21 16:31:49 +00:00
|
|
|
end if;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if File.Rbuf.Data(File.Rbuf.Pos + 1) = File.Option.LF then
|
|
|
|
-- Consume LF held in the internal read buffer.
|
|
|
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
|
|
|
-- Switch CR to LF (End-result: CR/LF to LF)
|
|
|
|
Buffer(Last) := Slim_Character'Val(File.Option.LF);
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
|
|
|
end if;
|
2014-06-21 16:31:49 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
end Get_Line;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| READ WIDE STRING
|
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
procedure Read_Wide (File: in out File_Record;
|
2014-06-17 15:23:35 +00:00
|
|
|
Buffer: out Wide_String;
|
2014-06-06 16:44:45 +00:00
|
|
|
Length: out System_Length;
|
2014-06-21 16:31:49 +00:00
|
|
|
Terminator: in Wide_Character) is
|
2014-06-17 15:23:35 +00:00
|
|
|
|
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-05 15:26:37 +00:00
|
|
|
pragma Assert (Buffer'Length > 0);
|
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
Outbuf: Wide_String renames Buffer;
|
|
|
|
Inbuf: Slim_String (File.Rbuf.Data'Range);
|
|
|
|
for Inbuf'Address use File.Rbuf.Data'Address;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
L3, L4, I, J, K: System_Length;
|
2014-06-05 15:26:37 +00:00
|
|
|
begin
|
|
|
|
K := Outbuf'First - 1;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
outer: while K < Outbuf'Last loop
|
2014-06-17 15:23:35 +00:00
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
Load_Bytes (File);
|
|
|
|
exit when Is_Empty(File.Rbuf);
|
2014-06-05 15:26:37 +00:00
|
|
|
end if;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
while File.Rbuf.Pos < File.Rbuf.Last and K < Outbuf'Last loop
|
|
|
|
I := File.Rbuf.Pos + 1;
|
2014-06-06 16:44:45 +00:00
|
|
|
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
|
|
|
|
|
|
|
if L3 <= 0 then
|
|
|
|
-- Potentially illegal sequence
|
|
|
|
K := K + 1;
|
2014-06-21 16:31:49 +00:00
|
|
|
Outbuf(K) := Ascii.Wide.Question;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Rbuf.Pos := I;
|
2014-06-06 16:44:45 +00:00
|
|
|
else
|
2014-06-19 14:13:19 +00:00
|
|
|
L4 := File.Rbuf.Last - File.Rbuf.Pos; -- Avaliable number of bytes available in the internal buffer
|
2014-06-06 16:44:45 +00:00
|
|
|
if L4 < L3 then
|
|
|
|
-- Insufficient data available. Exit the inner loop to read more.
|
|
|
|
exit;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
K := K + 1;
|
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
J := File.Rbuf.Pos + L3;
|
2014-06-17 15:23:35 +00:00
|
|
|
Outbuf(K..K) := Slim_To_Wide(Inbuf(I .. J));
|
2014-06-06 16:44:45 +00:00
|
|
|
exception
|
|
|
|
when others =>
|
2014-06-21 16:31:49 +00:00
|
|
|
Outbuf(K) := Ascii.Wide.Question;
|
2014-06-17 15:23:35 +00:00
|
|
|
J := I; -- Override J to skip 1 byte only.
|
2014-06-06 16:44:45 +00:00
|
|
|
end;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Rbuf.Pos := J;
|
2014-06-06 16:44:45 +00:00
|
|
|
end if;
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if Terminator /= Wide_Character'First and then Outbuf(K) = Terminator then
|
2014-06-06 16:44:45 +00:00
|
|
|
exit outer;
|
2014-06-05 15:26:37 +00:00
|
|
|
end if;
|
|
|
|
end loop;
|
|
|
|
end loop outer;
|
|
|
|
|
|
|
|
Length := K + 1 - Outbuf'First;
|
2014-06-06 16:44:45 +00:00
|
|
|
end Read_Wide;
|
2014-06-05 15:26:37 +00:00
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
procedure Read (File: in out File_Record;
|
2014-06-17 15:23:35 +00:00
|
|
|
Buffer: out Wide_String;
|
2014-06-06 16:44:45 +00:00
|
|
|
Length: out System_Length) is
|
|
|
|
begin
|
2014-06-21 16:31:49 +00:00
|
|
|
Read_Wide (File, Buffer, Length, Wide_Character'First);
|
2014-06-06 16:44:45 +00:00
|
|
|
end Read;
|
|
|
|
|
|
|
|
procedure Read_Line (File: in out File_Record;
|
2014-06-17 15:23:35 +00:00
|
|
|
Buffer: out Wide_String;
|
2014-06-06 16:44:45 +00:00
|
|
|
Length: out System_Length) is
|
2014-06-05 15:26:37 +00:00
|
|
|
begin
|
2014-06-21 16:31:49 +00:00
|
|
|
Read_Wide (File, Buffer, Length, Wide_Character'Val(File.Option.LF));
|
2014-06-05 15:26:37 +00:00
|
|
|
end Read_Line;
|
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
procedure Get_Line (File: in out File_Record;
|
|
|
|
Buffer: out Wide_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
pragma Assert (Buffer'Length > 0);
|
|
|
|
|
|
|
|
Last: System_Length;
|
|
|
|
begin
|
|
|
|
Read_Line (File, Buffer, Length);
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if Length <= 0 or else (File.Option.Bits and OPTION_CRLF_IN) = 0 then
|
|
|
|
return;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
Last := Buffer'First + Length - 1;
|
|
|
|
|
|
|
|
if Buffer(Last) = Wide_Character'Val(File.Option.LF) then
|
|
|
|
-- if the last character in the output bufer is LF.
|
|
|
|
-- inspect the previous character to check if it's CR.
|
|
|
|
|
|
|
|
if Last > Buffer'First and then
|
|
|
|
Buffer(Last - 1) = Wide_Character'Val(File.Option.CR) then
|
|
|
|
-- Switch CR/LF to LF
|
|
|
|
Length := Length - 1;
|
|
|
|
Buffer(Last - 1) := Wide_Character'Val(File.Option.LF);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
elsif Buffer(Last) = Wide_Character'Val(File.Option.CR) then
|
|
|
|
|
|
|
|
-- if the last character in the output buffer is CR,
|
|
|
|
-- i need to inspect the first character in the internal
|
|
|
|
-- read buffer to determine if it's CR/LF.
|
|
|
|
if Is_Empty(File.Rbuf) then
|
|
|
|
|
|
|
|
Load_Bytes (File);
|
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
if Is_Empty(File.Rbuf) then
|
2014-06-21 16:31:49 +00:00
|
|
|
-- no more data available.
|
|
|
|
return;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
2014-06-21 16:31:49 +00:00
|
|
|
end if;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
-- At least the first byte is available.
|
|
|
|
declare
|
|
|
|
Inbuf: Slim_String (File.Rbuf.Data'Range);
|
|
|
|
for Inbuf'Address use File.Rbuf.Data'Address;
|
|
|
|
L3, I, J: System_Length;
|
|
|
|
W: Wide_String(1..1);
|
|
|
|
begin
|
|
|
|
I := File.Rbuf.Pos + 1;
|
|
|
|
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
|
|
|
if L3 in 1 .. File.Rbuf.Last - File.Rbuf.Pos then
|
|
|
|
-- The next byte in the internal read buffer is a valid sequence leader and
|
|
|
|
-- the internal buffer has enough bytes to build a wide character.
|
|
|
|
J := File.Rbuf.Pos + L3;
|
2014-06-17 15:23:35 +00:00
|
|
|
begin
|
2014-06-21 16:31:49 +00:00
|
|
|
W := Slim_To_Wide(Inbuf(I .. J));
|
|
|
|
exception
|
|
|
|
when others =>
|
|
|
|
-- Don't do anything special despite the conversion error.
|
|
|
|
-- The next call should encounter the error again.
|
|
|
|
J := File.Rbuf.Pos;
|
2014-06-17 15:23:35 +00:00
|
|
|
end;
|
2014-06-21 16:31:49 +00:00
|
|
|
|
|
|
|
if J > File.Rbuf.Pos and then W(1) = Wide_Character'Val(File.Option.LF) then
|
|
|
|
-- Consume LF held in the internal read buffer.
|
|
|
|
File.Rbuf.Pos := J;
|
|
|
|
-- Switch CR to LF (End-result: CR/LF to LF)
|
|
|
|
Buffer(Last) := Wide_Character'Val(File.Option.LF);
|
|
|
|
end if;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
2014-06-21 16:31:49 +00:00
|
|
|
end;
|
2014-06-17 15:23:35 +00:00
|
|
|
end if;
|
2014-06-21 16:31:49 +00:00
|
|
|
|
2014-06-17 15:23:35 +00:00
|
|
|
end Get_Line;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| WRITE SLIM STRING
|
|
|
|
--|-----------------------------------------------------------------------
|
2014-06-04 17:15:52 +00:00
|
|
|
procedure Write (File: in out File_Record;
|
|
|
|
Buffer: in Slim_String;
|
2014-06-05 15:26:37 +00:00
|
|
|
Length: out System_Length) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
Inbuf: System_Byte_Array (Buffer'Range);
|
|
|
|
for Inbuf'Address use Buffer'Address;
|
|
|
|
|
|
|
|
F, L: System_Length;
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-06 16:44:45 +00:00
|
|
|
-- This procedure attempts to write as many bytes as requested.
|
|
|
|
-- However, under a certain condition, it may not be able to
|
|
|
|
-- process the input buffer in full.
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
if not Is_Empty(File.Wbuf) then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- Some residue data in the internal buffer.
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
if Inbuf'Length <= File.Wbuf.Data'Last - File.Wbuf.Last then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- Copy the input to the internal buffer to reduce OS calls
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
F := File.Wbuf.Last + 1;
|
2014-06-06 16:44:45 +00:00
|
|
|
L := F + Inbuf'Length - 1;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Wbuf.Data(F .. L) := Inbuf;
|
|
|
|
File.Wbuf.Last := L;
|
2014-06-06 16:44:45 +00:00
|
|
|
Flush (File);
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
-- The resulting length is the length of input buffer given.
|
|
|
|
-- The residue in the internal write buffer is not counted.
|
2014-06-06 16:44:45 +00:00
|
|
|
Length := Inbuf'Length;
|
|
|
|
return;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
-- Flush the residue first.
|
|
|
|
Flush (File);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
L := 0;
|
|
|
|
while L < Inbuf'Length loop
|
|
|
|
--begin
|
2014-06-19 14:13:19 +00:00
|
|
|
OS.File.Write (File.File, Inbuf(Inbuf'First + L .. Inbuf'Last), F);
|
2014-06-06 16:44:45 +00:00
|
|
|
--exception
|
|
|
|
-- when OS.Would_Block_Exception =>
|
|
|
|
-- -- Cannot write the input in full.
|
|
|
|
-- -- Copy some to to the internal buffer
|
|
|
|
-- L := L + as much as copied;
|
|
|
|
-- exit;
|
|
|
|
-- when others =>
|
|
|
|
-- raise;
|
|
|
|
--end;
|
|
|
|
L := L + F;
|
|
|
|
end loop;
|
|
|
|
|
|
|
|
Length := L;
|
2014-06-04 17:15:52 +00:00
|
|
|
end Write;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
procedure Write_Line (File: in out File_Record;
|
|
|
|
Buffer: in Slim_String;
|
|
|
|
Length: out System_Length) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
Inbuf: System_Byte_Array (Buffer'Range);
|
|
|
|
for Inbuf'Address use Buffer'Address;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
L, I, LF: System_Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
begin
|
|
|
|
-- This procedure attempts to write the input up to the last line
|
|
|
|
-- terminator. It buffers the remaining input after the terminator.
|
|
|
|
-- The input may not include any line terminators.
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
LF := File.Wbuf.Data'First - 1;
|
2014-06-06 16:44:45 +00:00
|
|
|
I := Inbuf'First - 1;
|
2014-06-19 14:13:19 +00:00
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
while I < Inbuf'Last loop
|
2014-06-19 14:13:19 +00:00
|
|
|
if File.Wbuf.Last >= File.Wbuf.Data'Last then
|
|
|
|
-- The internal write buffer is full.
|
|
|
|
Flush (File);
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
end if;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
I := I + 1;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Wbuf.Last := File.Wbuf.Last + 1;
|
|
|
|
File.Wbuf.Data(File.Wbuf.Last) := Inbuf(I);
|
2014-06-21 16:31:49 +00:00
|
|
|
if File.Wbuf.Data(File.Wbuf.Last) = File.Option.LF then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- Remeber the index of the line terminator
|
2014-06-19 14:13:19 +00:00
|
|
|
LF := File.Wbuf.Last;
|
2014-06-06 16:44:45 +00:00
|
|
|
end if;
|
2014-06-19 14:13:19 +00:00
|
|
|
end loop;
|
|
|
|
|
|
|
|
-- The line terminator was found. Write up to the terminator.
|
|
|
|
-- Keep the rest in the internal buffer.
|
|
|
|
if LF in File.Wbuf.Data'Range then
|
|
|
|
while File.Wbuf.Pos < LF loop
|
|
|
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
|
|
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
|
|
|
Compact_Buffer (File.Wbuf);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
Length := I - Inbuf'First + 1;
|
|
|
|
end Write_Line;
|
|
|
|
|
|
|
|
procedure Put_Line (File: in out File_Record;
|
|
|
|
Buffer: in Slim_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
|
|
|
Inbuf: System_Byte_Array (Buffer'Range);
|
|
|
|
for Inbuf'Address use Buffer'Address;
|
|
|
|
|
|
|
|
L, I, LF: System_Length;
|
|
|
|
X: System_Byte;
|
|
|
|
Injected: Standard.Boolean := Standard.False;
|
|
|
|
|
|
|
|
begin
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
I := Inbuf'First - 1;
|
|
|
|
|
|
|
|
while I < Inbuf'Last loop
|
2014-06-21 16:31:49 +00:00
|
|
|
if (File.Option.Bits and OPTION_CRLF_OUT) /= 0 and then
|
|
|
|
not Injected and then Inbuf(I + 1) = File.Option.LF then
|
|
|
|
X := File.Option.CR;
|
2014-06-19 14:13:19 +00:00
|
|
|
Injected := Standard.True;
|
|
|
|
else
|
|
|
|
I := I + 1;
|
|
|
|
X := Inbuf(I);
|
|
|
|
Injected := Standard.False;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if File.Wbuf.Last >= File.Wbuf.Data'Last then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- The internal write buffer is full.
|
|
|
|
Flush (File);
|
2014-06-19 14:13:19 +00:00
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
File.Wbuf.Last := File.Wbuf.Last + 1;
|
|
|
|
File.Wbuf.Data(File.Wbuf.Last) := X;
|
2014-06-21 16:31:49 +00:00
|
|
|
if File.Wbuf.Data(File.Wbuf.Last) = File.Option.LF then
|
2014-06-19 14:13:19 +00:00
|
|
|
-- Remeber the index of the line terminator
|
|
|
|
LF := File.Wbuf.Last;
|
2014-06-06 16:44:45 +00:00
|
|
|
end if;
|
|
|
|
end loop;
|
|
|
|
|
|
|
|
-- The line terminator was found. Write up to the terminator.
|
|
|
|
-- Keep the rest in the internal buffer.
|
2014-06-19 14:13:19 +00:00
|
|
|
if LF in File.Wbuf.Data'Range then
|
|
|
|
while File.Wbuf.Pos < LF loop
|
|
|
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
|
|
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
|
|
|
Compact_Buffer (File.Wbuf);
|
|
|
|
end if;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
|
|
|
Length := I - Inbuf'First + 1;
|
2014-06-19 14:13:19 +00:00
|
|
|
end Put_Line;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| WRITE WIDE STRING
|
|
|
|
--|-----------------------------------------------------------------------
|
2014-06-04 17:15:52 +00:00
|
|
|
procedure Write (File: in out File_Record;
|
|
|
|
Buffer: in Wide_String;
|
2014-06-05 15:26:37 +00:00
|
|
|
Length: out System_Length) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
L, I: System_Length;
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-06 16:44:45 +00:00
|
|
|
I := Buffer'First - 1;
|
|
|
|
while I < Buffer'Last loop
|
|
|
|
I := I + 1;
|
|
|
|
declare
|
|
|
|
Tmp: Slim_String := Wide_To_Slim(Buffer(I..I));
|
|
|
|
Tmp2: System_Byte_Array(Tmp'Range);
|
|
|
|
for Tmp2'Address use Tmp'Address;
|
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
L := File.Wbuf.Last + Tmp2'Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
if L > File.Wbuf.Data'Last then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- The multi-byte sequence for the current character
|
|
|
|
-- can't fit into the internal buffer. Flush the
|
|
|
|
-- buffer and attempt to fit it in.
|
|
|
|
Flush (File);
|
2014-06-19 14:13:19 +00:00
|
|
|
L := File.Wbuf.Pos + Tmp2'Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
end if;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Wbuf.Data(File.Wbuf.Last + 1 .. L) := Tmp2;
|
|
|
|
File.Wbuf.Last := L;
|
2014-06-06 16:44:45 +00:00
|
|
|
end;
|
|
|
|
end loop;
|
|
|
|
|
|
|
|
Flush (File);
|
|
|
|
Length := I - Buffer'First + 1;
|
2014-06-04 17:15:52 +00:00
|
|
|
end Write;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
procedure Write_Line (File: in out File_Record;
|
|
|
|
Buffer: in Wide_String;
|
|
|
|
Length: out System_Length) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
L, I, LF: System_Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
2014-06-06 16:44:45 +00:00
|
|
|
I := Buffer'First - 1;
|
|
|
|
while I < Buffer'Last loop
|
|
|
|
I := I + 1;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
declare
|
|
|
|
Tmp: Slim_String := Wide_To_Slim(Buffer(I..I));
|
|
|
|
Tmp2: System_Byte_Array(Tmp'Range);
|
|
|
|
for Tmp2'Address use Tmp'Address;
|
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
L := File.Wbuf.Last + Tmp2'Length;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
if L > File.Wbuf.Data'Last then
|
2014-06-06 16:44:45 +00:00
|
|
|
-- The multi-byte sequence for the current character
|
|
|
|
-- can't fit into the internal buffer. Flush the
|
|
|
|
-- buffer and attempt to fit it in.
|
|
|
|
Flush (File);
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
L := File.Wbuf.Pos + Tmp2'Length;
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
end if;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if Buffer(I) = Wide_Character'Val(File.Option.LF) then
|
2014-06-06 16:44:45 +00:00
|
|
|
LF := L;
|
|
|
|
end if;
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
File.Wbuf.Data(File.Wbuf.Last + 1 .. L) := Tmp2;
|
|
|
|
File.Wbuf.Last := L;
|
2014-06-06 16:44:45 +00:00
|
|
|
end;
|
|
|
|
end loop;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
if LF in File.Wbuf.Data'Range then
|
|
|
|
while File.Wbuf.Pos < LF loop
|
|
|
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
|
|
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
|
|
|
Compact_Buffer (File.Wbuf);
|
|
|
|
end if;
|
2014-06-06 16:44:45 +00:00
|
|
|
|
|
|
|
Length := I - Buffer'First + 1;
|
|
|
|
end Write_Line;
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
procedure Put_Line (File: in out File_Record;
|
|
|
|
Buffer: in Wide_String;
|
|
|
|
Length: out System_Length) is
|
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
|
|
|
F, L, I, LF: System_Length;
|
2014-06-21 16:31:49 +00:00
|
|
|
X: Wide_String(1..2) := (Wide_Character'Val(File.Option.CR), Wide_Character'Val(File.Option.LF));
|
2014-06-19 14:13:19 +00:00
|
|
|
begin
|
|
|
|
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
I := Buffer'First - 1;
|
|
|
|
while I < Buffer'Last loop
|
|
|
|
I := I + 1;
|
|
|
|
|
|
|
|
X(2) := Buffer(I);
|
2014-06-21 16:31:49 +00:00
|
|
|
if (File.Option.Bits and OPTION_CRLF_OUT) /= 0 and then
|
|
|
|
Buffer(I) = Wide_Character'Val(File.Option.LF) then
|
2014-06-19 14:13:19 +00:00
|
|
|
F := 1;
|
|
|
|
else
|
|
|
|
F := 2;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
declare
|
|
|
|
Tmp: Slim_String := Wide_To_Slim(X(F..2));
|
|
|
|
Tmp2: System_Byte_Array(Tmp'Range);
|
|
|
|
for Tmp2'Address use Tmp'Address;
|
|
|
|
begin
|
|
|
|
L := File.Wbuf.Last + Tmp2'Length;
|
|
|
|
|
|
|
|
if L > File.Wbuf.Data'Last then
|
|
|
|
-- The multi-byte sequence for the current character
|
|
|
|
-- can't fit into the internal buffer. Flush the
|
|
|
|
-- buffer and attempt to fit it in.
|
|
|
|
Flush (File);
|
|
|
|
|
|
|
|
L := File.Wbuf.Pos + Tmp2'Length;
|
|
|
|
LF := File.Wbuf.Data'First - 1;
|
|
|
|
end if;
|
|
|
|
|
2014-06-21 16:31:49 +00:00
|
|
|
if Buffer(I) = Wide_Character'Val(File.Option.LF) then
|
2014-06-19 14:13:19 +00:00
|
|
|
LF := L;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
File.Wbuf.Data(File.Wbuf.Last + 1 .. L) := Tmp2;
|
|
|
|
File.Wbuf.Last := L;
|
|
|
|
end;
|
|
|
|
end loop;
|
|
|
|
|
|
|
|
if LF in File.Wbuf.Data'Range then
|
|
|
|
while File.Wbuf.Pos < LF loop
|
|
|
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
|
|
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
|
|
|
Compact_Buffer (File.Wbuf);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
Length := I - Buffer'First + 1;
|
|
|
|
end Put_Line;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
--|-----------------------------------------------------------------------
|
|
|
|
--| FLUSH AND DRAIN
|
|
|
|
--|-----------------------------------------------------------------------
|
2014-06-04 17:15:52 +00:00
|
|
|
procedure Flush (File: in out File_Record) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
|
|
|
|
2014-06-19 14:13:19 +00:00
|
|
|
L: System_Length;
|
2014-06-04 17:15:52 +00:00
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
while not Is_Empty(File.Wbuf) loop
|
2014-06-06 16:44:45 +00:00
|
|
|
--begin
|
2014-06-19 14:13:19 +00:00
|
|
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. File.Wbuf.Last), L);
|
2014-06-06 16:44:45 +00:00
|
|
|
--exception
|
|
|
|
-- when Would_Block_Exception =>
|
|
|
|
-- -- Flush must write all it can.
|
|
|
|
-- null;
|
|
|
|
-- when others =>
|
|
|
|
-- raise;
|
|
|
|
--end;
|
2014-06-19 14:13:19 +00:00
|
|
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
2014-06-06 16:44:45 +00:00
|
|
|
end loop;
|
2014-06-19 14:13:19 +00:00
|
|
|
|
|
|
|
Set_Length (File.Wbuf, 0);
|
2014-06-04 17:15:52 +00:00
|
|
|
end Flush;
|
|
|
|
|
2014-06-06 16:44:45 +00:00
|
|
|
procedure Drain (File: in out File_Record) is
|
2014-06-17 15:23:35 +00:00
|
|
|
pragma Assert (Is_Open(File));
|
2014-06-06 16:44:45 +00:00
|
|
|
begin
|
2014-06-19 14:13:19 +00:00
|
|
|
Set_Length (File.Wbuf, 0);
|
2014-06-06 16:44:45 +00:00
|
|
|
end Drain;
|
2014-06-17 15:23:35 +00:00
|
|
|
|
2014-06-04 17:15:52 +00:00
|
|
|
end File;
|