added File.Get_Line and File.Put_Line. rewritten io procedures to reply on the current and the last position instead of the length
This commit is contained in:
parent
b441709a02
commit
0286526bf1
@ -86,6 +86,7 @@ declare
|
|||||||
Buffer: H2.Slim.String (1 .. 200);
|
Buffer: H2.Slim.String (1 .. 200);
|
||||||
BufferW: H2.Wide.String (1 .. 27);
|
BufferW: H2.Wide.String (1 .. 27);
|
||||||
IL, OL: H2.System_Length;
|
IL, OL: H2.System_Length;
|
||||||
|
Option: File.Option_Record;
|
||||||
begin
|
begin
|
||||||
--File.Open (F, H2.Slim.String'("/etc/passwd"), FL);
|
--File.Open (F, H2.Slim.String'("/etc/passwd"), FL);
|
||||||
--File.Read (F, Buffer, Length);
|
--File.Read (F, Buffer, Length);
|
||||||
@ -111,16 +112,18 @@ ada.text_io.put_line ("------------------");
|
|||||||
File.Set_Flag_Bits (FL, File.FLAG_CREATE);
|
File.Set_Flag_Bits (FL, File.FLAG_CREATE);
|
||||||
File.Set_Flag_Bits (FL, File.FLAG_TRUNCATE);
|
File.Set_Flag_Bits (FL, File.FLAG_TRUNCATE);
|
||||||
File.Open (F2, H2.Wide.String'("/tmp/yyy"), FL);
|
File.Open (F2, H2.Wide.String'("/tmp/yyy"), FL);
|
||||||
|
File.Set_Option_Bits (Option, File.Option_CRLF);
|
||||||
|
File.Set_Option (F2, Option);
|
||||||
|
|
||||||
loop
|
loop
|
||||||
|
|
||||||
File.Get_Line (F, BufferW, IL);
|
File.Get_Line (F, Buffer, IL);
|
||||||
|
|
||||||
ada.wide_text_io.put_line (standard.wide_string(bufferw(1..il)));
|
--ada.wide_text_io.put_line (standard.wide_string(bufferw(1..il)));
|
||||||
--File.Read (F, BufferW, IL);
|
--File.Read (F, BufferW, IL);
|
||||||
exit when IL <= 0;
|
exit when IL <= 0;
|
||||||
|
|
||||||
File.Write_Line (F2, BufferW(BufferW'First .. BufferW'First + IL - 1), OL);
|
File.Put_Line (F2, Buffer(Buffer'First .. Buffer'First + IL - 1), OL);
|
||||||
pragma Assert (IL = OL);
|
pragma Assert (IL = OL);
|
||||||
|
|
||||||
--Ada.Text_IO.PUt (Standard.String(Buffer(Buffer'First .. Buffer'First + IL - 1)));
|
--Ada.Text_IO.PUt (Standard.String(Buffer(Buffer'First .. Buffer'First + IL - 1)));
|
||||||
|
@ -18,13 +18,26 @@ package body File is
|
|||||||
File.EOF := (Length <= 0);
|
File.EOF := (Length <= 0);
|
||||||
end OS_Read_File;
|
end OS_Read_File;
|
||||||
|
|
||||||
procedure Shift_Buffer (Buffer: in out File_Buffer;
|
--procedure Shift_Buffer (Buffer: in out File_Buffer;
|
||||||
Length: in System_Length) is
|
-- Length: in System_Length) is
|
||||||
pragma Inline (Shift_Buffer);
|
-- pragma Inline (Shift_Buffer);
|
||||||
|
--begin
|
||||||
|
-- Buffer.Length := Buffer.Length - Length;
|
||||||
|
-- Buffer.Data(Buffer.Data'First .. Buffer.Data'First + Buffer.Length - 1) := Buffer.Data(Buffer.Data'First + Length .. Buffer.Data'First + Length + Buffer.Length - 1);
|
||||||
|
--end Shift_Buffer;
|
||||||
|
|
||||||
|
procedure Compact_Buffer (Buffer: in out File_Buffer) is
|
||||||
|
A, B, L: System_Length;
|
||||||
begin
|
begin
|
||||||
Buffer.Length := Buffer.Length - Length;
|
A := Buffer.Pos;
|
||||||
Buffer.Data(Buffer.Data'First .. Buffer.Data'First + Buffer.Length - 1) := Buffer.Data(Buffer.Data'First + Length .. Buffer.Data'First + Length + Buffer.Length - 1);
|
B := Buffer.Last;
|
||||||
end Shift_Buffer;
|
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;
|
||||||
|
|
||||||
procedure Copy_Array (Dst: in out System_Byte_Array;
|
procedure Copy_Array (Dst: in out System_Byte_Array;
|
||||||
Src: in System_Byte_Array;
|
Src: in System_Byte_Array;
|
||||||
@ -34,10 +47,36 @@ package body File is
|
|||||||
Dst(Dst'First .. Dst'First + Length - 1) := Src(Src'First .. Src'First + Length - 1);
|
Dst(Dst'First .. Dst'First + Length - 1) := Src(Src'First .. Src'First + Length - 1);
|
||||||
end Copy_Array;
|
end Copy_Array;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
Slim_Line_Terminator: Slim_String := Get_Line_Terminator;
|
Slim_Line_Terminator: Slim_String := Get_Line_Terminator;
|
||||||
--Wide_Line_Terminator: Wide_String := Get_Line_Terminator;
|
--Wide_Line_Terminator: Wide_String := Get_Line_Terminator;
|
||||||
|
|
||||||
|
|
||||||
|
procedure Set_Option_Bits (Option: in out Option_Record;
|
||||||
|
Bits: in Option_Bits) is
|
||||||
|
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;
|
||||||
|
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
--| OPEN AND CLOSE
|
--| OPEN AND CLOSE
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
@ -53,11 +92,10 @@ package body File is
|
|||||||
pragma Assert (not Is_Open(File));
|
pragma Assert (not Is_Open(File));
|
||||||
begin
|
begin
|
||||||
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
||||||
File.Rbuf.First := 0;
|
|
||||||
File.Rbuf.Last := 0;
|
Set_Length (File.Rbuf, 0);
|
||||||
File.Rbuf.Length := 0;
|
Set_Length (File.Wbuf, 0);
|
||||||
|
|
||||||
File.Wbuf.Length := 0;
|
|
||||||
File.EOF := Standard.False;
|
File.EOF := Standard.False;
|
||||||
--File.Slim_Line_Break := Get_Line_Terminator;
|
--File.Slim_Line_Break := Get_Line_Terminator;
|
||||||
--File.Wide_Line_Break := Get_Line_Terminator;
|
--File.Wide_Line_Break := Get_Line_Terminator;
|
||||||
@ -70,8 +108,10 @@ package body File is
|
|||||||
pragma Assert (not Is_Open(File));
|
pragma Assert (not Is_Open(File));
|
||||||
begin
|
begin
|
||||||
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
OS.File.Open (File.File, Name, Flag, Pool => Pool);
|
||||||
File.Rbuf.Length := 0;
|
|
||||||
File.Wbuf.Length := 0;
|
Set_Length (File.Rbuf, 0);
|
||||||
|
Set_Length (File.Wbuf, 0);
|
||||||
|
|
||||||
File.EOF := Standard.False;
|
File.EOF := Standard.False;
|
||||||
--File.Slim_Line_Break := Get_Line_Terminator;
|
--File.Slim_Line_Break := Get_Line_Terminator;
|
||||||
--File.Wide_Line_Break := Get_Line_Terminator;
|
--File.Wide_Line_Break := Get_Line_Terminator;
|
||||||
@ -85,18 +125,15 @@ package body File is
|
|||||||
File.File := null;
|
File.File := null;
|
||||||
end Close;
|
end Close;
|
||||||
|
|
||||||
function Is_Empty (Buf: in File_Buffer) return Standard.Boolean is
|
procedure Set_Option (File: in out File_Record; Option: in Option_Record) is
|
||||||
pragma Inline (Is_Empty);
|
|
||||||
begin
|
begin
|
||||||
return Buf.First >= Buf.Last;
|
File.Option := Option;
|
||||||
end Is_Empty;
|
end Set_Option;
|
||||||
|
|
||||||
procedure Set_Length (Buf: in out File_Buffer; Length: in System_Length) is
|
function Get_Option (File: in File_Record) return Option_Record is
|
||||||
pragma Inline (Set_Length);
|
|
||||||
begin
|
begin
|
||||||
Buf.First := Buf.Data'First - 1; -- this should be 0
|
return File.Option;
|
||||||
Buf.Last := Buf.First + Length;
|
end Get_Option;
|
||||||
end Set_Length;
|
|
||||||
|
|
||||||
procedure Load_Bytes (File: in out File_Record) is
|
procedure Load_Bytes (File: in out File_Record) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
@ -127,8 +164,8 @@ package body File is
|
|||||||
else
|
else
|
||||||
-- Consume 1 byte
|
-- Consume 1 byte
|
||||||
Available := Standard.True;
|
Available := Standard.True;
|
||||||
File.Rbuf.First := File.Rbuf.First + 1;
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
||||||
Item := File.Rbuf.Data(File.Rbuf.First);
|
Item := File.Rbuf.Data(File.Rbuf.Pos);
|
||||||
end if;
|
end if;
|
||||||
end Fetch_Byte;
|
end Fetch_Byte;
|
||||||
|
|
||||||
@ -142,7 +179,7 @@ package body File is
|
|||||||
-- raise EOF EXCEPTION. ???
|
-- raise EOF EXCEPTION. ???
|
||||||
Length := 0;
|
Length := 0;
|
||||||
else
|
else
|
||||||
L1 := File.Rbuf.Last - File.Rbuf.First;
|
L1 := File.Rbuf.Last - File.Rbuf.Pos;
|
||||||
if L1 > 0 then
|
if L1 > 0 then
|
||||||
-- Copy the residue over to the output buffer
|
-- Copy the residue over to the output buffer
|
||||||
if Item'Length <= L1 then
|
if Item'Length <= L1 then
|
||||||
@ -151,8 +188,8 @@ package body File is
|
|||||||
L2 := L1;
|
L2 := L1;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Copy_Array (Item, File.Rbuf.Data(File.Rbuf.First + 1 .. File.Rbuf.Last), L2);
|
Copy_Array (Item, File.Rbuf.Data(File.Rbuf.Pos + 1 .. File.Rbuf.Last), L2);
|
||||||
File.Rbuf.First := File.Rbuf.First + L2;
|
File.Rbuf.Pos := File.Rbuf.Pos + L2;
|
||||||
|
|
||||||
Length := L2;
|
Length := L2;
|
||||||
else
|
else
|
||||||
@ -161,7 +198,7 @@ package body File is
|
|||||||
|
|
||||||
if Item'Length > L1 then
|
if Item'Length > L1 then
|
||||||
-- Item is not full. the internal read buffer must be empty.
|
-- Item is not full. the internal read buffer must be empty.
|
||||||
pragma Assert (File.Rbuf.First >= File.Rbuf.Last);
|
pragma Assert (File.Rbuf.Pos >= File.Rbuf.Last);
|
||||||
|
|
||||||
L2 := Item'Length - Length; -- Remaining capacity
|
L2 := Item'Length - Length; -- Remaining capacity
|
||||||
If L2 >= File.Rbuf.Data'Length then
|
If L2 >= File.Rbuf.Data'Length then
|
||||||
@ -183,7 +220,7 @@ package body File is
|
|||||||
-- Copy as many bytes as needed into the output buffer.
|
-- Copy as many bytes as needed into the output buffer.
|
||||||
Copy_Array (Item(Item'First + Length .. Item'Last), File.Rbuf.Data, L2);
|
Copy_Array (Item(Item'First + Length .. Item'Last), File.Rbuf.Data, L2);
|
||||||
Length := Length + L2;
|
Length := Length + L2;
|
||||||
File.Rbuf.First := File.Rbuf.First + L2;
|
File.Rbuf.Pos := File.Rbuf.Pos + L2;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
@ -223,10 +260,10 @@ package body File is
|
|||||||
exit when Is_Empty(File.Rbuf);
|
exit when Is_Empty(File.Rbuf);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
while File.Rbuf.First < File.Rbuf.Last loop
|
while File.Rbuf.Pos < File.Rbuf.Last loop
|
||||||
K := K + 1;
|
K := K + 1;
|
||||||
File.Rbuf.First := File.Rbuf.First + 1;
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
||||||
Outbuf(K) := File.Rbuf.Data(File.Rbuf.First);
|
Outbuf(K) := File.Rbuf.Data(File.Rbuf.Pos);
|
||||||
if K >= Outbuf'Last or else Outbuf(K) = Slim_Ascii.Pos.LF then -- TODO: different line terminator
|
if K >= Outbuf'Last or else Outbuf(K) = Slim_Ascii.Pos.LF then -- TODO: different line terminator
|
||||||
exit outer; -- Done
|
exit outer; -- Done
|
||||||
end if;
|
end if;
|
||||||
@ -260,9 +297,9 @@ package body File is
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not Is_Empty(File.Rbuf) then
|
if not Is_Empty(File.Rbuf) then
|
||||||
if File.Rbuf.Data(File.Rbuf.First + 1) = Slim_Ascii.Pos.LF then
|
if File.Rbuf.Data(File.Rbuf.Pos + 1) = Slim_Ascii.Pos.LF then
|
||||||
-- Consume LF held in the internal read buffer.
|
-- Consume LF held in the internal read buffer.
|
||||||
File.Rbuf.First := File.Rbuf.First + 1;
|
File.Rbuf.Pos := File.Rbuf.Pos + 1;
|
||||||
-- Switch CR to LF (End-result: CR/LF to LF)
|
-- Switch CR to LF (End-result: CR/LF to LF)
|
||||||
Buffer(Last) := Slim_Ascii.LF;
|
Buffer(Last) := Slim_Ascii.LF;
|
||||||
end if;
|
end if;
|
||||||
@ -274,7 +311,6 @@ package body File is
|
|||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
--| READ WIDE STRING
|
--| READ WIDE STRING
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
|
|
||||||
procedure Read_Wide (File: in out File_Record;
|
procedure Read_Wide (File: in out File_Record;
|
||||||
Buffer: out Wide_String;
|
Buffer: out Wide_String;
|
||||||
Length: out System_Length;
|
Length: out System_Length;
|
||||||
@ -297,17 +333,17 @@ package body File is
|
|||||||
exit when Is_Empty(File.Rbuf);
|
exit when Is_Empty(File.Rbuf);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
while File.Rbuf.First < File.Rbuf.Last and K < Outbuf'Last loop
|
while File.Rbuf.Pos < File.Rbuf.Last and K < Outbuf'Last loop
|
||||||
I := File.Rbuf.First + 1;
|
I := File.Rbuf.Pos + 1;
|
||||||
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
||||||
|
|
||||||
if L3 <= 0 then
|
if L3 <= 0 then
|
||||||
-- Potentially illegal sequence
|
-- Potentially illegal sequence
|
||||||
K := K + 1;
|
K := K + 1;
|
||||||
Outbuf(K) := Wide_Ascii.Question;
|
Outbuf(K) := Wide_Ascii.Question;
|
||||||
File.Rbuf.First := I;
|
File.Rbuf.Pos := I;
|
||||||
else
|
else
|
||||||
L4 := File.Rbuf.Last - File.Rbuf.First; -- Avaliable number of bytes available in the internal buffer
|
L4 := File.Rbuf.Last - File.Rbuf.Pos; -- Avaliable number of bytes available in the internal buffer
|
||||||
if L4 < L3 then
|
if L4 < L3 then
|
||||||
-- Insufficient data available. Exit the inner loop to read more.
|
-- Insufficient data available. Exit the inner loop to read more.
|
||||||
exit;
|
exit;
|
||||||
@ -315,14 +351,14 @@ package body File is
|
|||||||
|
|
||||||
K := K + 1;
|
K := K + 1;
|
||||||
begin
|
begin
|
||||||
J := File.Rbuf.First + L3;
|
J := File.Rbuf.Pos + L3;
|
||||||
Outbuf(K..K) := Slim_To_Wide(Inbuf(I .. J));
|
Outbuf(K..K) := Slim_To_Wide(Inbuf(I .. J));
|
||||||
exception
|
exception
|
||||||
when others =>
|
when others =>
|
||||||
Outbuf(K) := Wide_Ascii.Question;
|
Outbuf(K) := Wide_Ascii.Question;
|
||||||
J := I; -- Override J to skip 1 byte only.
|
J := I; -- Override J to skip 1 byte only.
|
||||||
end;
|
end;
|
||||||
File.Rbuf.First := J;
|
File.Rbuf.Pos := J;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if Terminator'Length > 0 and then
|
if Terminator'Length > 0 and then
|
||||||
@ -385,10 +421,10 @@ package body File is
|
|||||||
L3, I, J: System_Length;
|
L3, I, J: System_Length;
|
||||||
W: Wide_String(1..1);
|
W: Wide_String(1..1);
|
||||||
begin
|
begin
|
||||||
I := File.Rbuf.First + 1;
|
I := File.Rbuf.Pos + 1;
|
||||||
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
L3 := Sequence_Length(Inbuf(I)); -- Required number of bytes to compose a wide character
|
||||||
if L3 in 1 .. File.Rbuf.Last - File.Rbuf.First then
|
if L3 in 1 .. File.Rbuf.Last - File.Rbuf.Pos then
|
||||||
J := File.Rbuf.First + L3;
|
J := File.Rbuf.Pos + L3;
|
||||||
begin
|
begin
|
||||||
W := Slim_To_Wide(Inbuf(I .. J));
|
W := Slim_To_Wide(Inbuf(I .. J));
|
||||||
exception
|
exception
|
||||||
@ -397,7 +433,7 @@ package body File is
|
|||||||
end;
|
end;
|
||||||
if W(1) = Wide_Ascii.LF then
|
if W(1) = Wide_Ascii.LF then
|
||||||
-- Consume LF held in the internal read buffer.
|
-- Consume LF held in the internal read buffer.
|
||||||
File.Rbuf.First := J;
|
File.Rbuf.Pos := J;
|
||||||
-- Switch CR to LF (End-result: CR/LF to LF)
|
-- Switch CR to LF (End-result: CR/LF to LF)
|
||||||
Buffer(Last) := Wide_Ascii.LF;
|
Buffer(Last) := Wide_Ascii.LF;
|
||||||
end if;
|
end if;
|
||||||
@ -416,8 +452,6 @@ package body File is
|
|||||||
Length: out System_Length) is
|
Length: out System_Length) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
|
|
||||||
Wbuf: File_Buffer renames File.Wbuf;
|
|
||||||
|
|
||||||
Inbuf: System_Byte_Array (Buffer'Range);
|
Inbuf: System_Byte_Array (Buffer'Range);
|
||||||
for Inbuf'Address use Buffer'Address;
|
for Inbuf'Address use Buffer'Address;
|
||||||
|
|
||||||
@ -427,16 +461,20 @@ package body File is
|
|||||||
-- However, under a certain condition, it may not be able to
|
-- However, under a certain condition, it may not be able to
|
||||||
-- process the input buffer in full.
|
-- process the input buffer in full.
|
||||||
|
|
||||||
if Wbuf.Length > 0 then
|
if not Is_Empty(File.Wbuf) then
|
||||||
-- Some residue data in the internal buffer.
|
-- Some residue data in the internal buffer.
|
||||||
|
|
||||||
if Inbuf'Length <= Wbuf.Data'Length - Wbuf.Length then
|
if Inbuf'Length <= File.Wbuf.Data'Last - File.Wbuf.Last then
|
||||||
-- Copy the input to the internal buffer to reduce OS calls
|
-- Copy the input to the internal buffer to reduce OS calls
|
||||||
F := Wbuf.Data'First + Wbuf.Length - 1;
|
|
||||||
|
F := File.Wbuf.Last + 1;
|
||||||
L := F + Inbuf'Length - 1;
|
L := F + Inbuf'Length - 1;
|
||||||
Wbuf.Data(F .. L) := Inbuf;
|
File.Wbuf.Data(F .. L) := Inbuf;
|
||||||
|
File.Wbuf.Last := L;
|
||||||
Flush (File);
|
Flush (File);
|
||||||
|
|
||||||
|
-- The resulting length is the length of input buffer given.
|
||||||
|
-- The residue in the internal write buffer is not counted.
|
||||||
Length := Inbuf'Length;
|
Length := Inbuf'Length;
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
@ -448,7 +486,7 @@ package body File is
|
|||||||
L := 0;
|
L := 0;
|
||||||
while L < Inbuf'Length loop
|
while L < Inbuf'Length loop
|
||||||
--begin
|
--begin
|
||||||
OS.File.Write (File.File, Inbuf, F);
|
OS.File.Write (File.File, Inbuf(Inbuf'First + L .. Inbuf'Last), F);
|
||||||
--exception
|
--exception
|
||||||
-- when OS.Would_Block_Exception =>
|
-- when OS.Would_Block_Exception =>
|
||||||
-- -- Cannot write the input in full.
|
-- -- Cannot write the input in full.
|
||||||
@ -469,48 +507,107 @@ package body File is
|
|||||||
Length: out System_Length) is
|
Length: out System_Length) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
|
|
||||||
Wbuf: File_Buffer renames File.Wbuf;
|
|
||||||
|
|
||||||
Inbuf: System_Byte_Array (Buffer'Range);
|
Inbuf: System_Byte_Array (Buffer'Range);
|
||||||
for Inbuf'Address use Buffer'Address;
|
for Inbuf'Address use Buffer'Address;
|
||||||
|
|
||||||
I, J, LF: System_Length;
|
L, I, LF: System_Length;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
-- This procedure attempts to write the input up to the last line
|
-- This procedure attempts to write the input up to the last line
|
||||||
-- terminator. It buffers the remaining input after the terminator.
|
-- terminator. It buffers the remaining input after the terminator.
|
||||||
-- The input may not include any line terminators.
|
-- The input may not include any line terminators.
|
||||||
|
|
||||||
LF := Wbuf.Data'First - 1;
|
LF := File.Wbuf.Data'First - 1;
|
||||||
I := Inbuf'First - 1;
|
I := Inbuf'First - 1;
|
||||||
|
|
||||||
while I < Inbuf'Last loop
|
while I < Inbuf'Last loop
|
||||||
I := I + 1;
|
if File.Wbuf.Last >= File.Wbuf.Data'Last then
|
||||||
J := Wbuf.Data'First + Wbuf.Length;
|
|
||||||
Wbuf.Data(J) := Inbuf(I);
|
|
||||||
Wbuf.Length := Wbuf.Length + 1;
|
|
||||||
if Wbuf.Data(J) = Slim_Ascii.Pos.LF then -- TODO: different line terminator
|
|
||||||
-- Remeber the index of the line terminator
|
|
||||||
LF := J;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if Wbuf.Length >= Wbuf.Data'Length then
|
|
||||||
-- The internal write buffer is full.
|
-- The internal write buffer is full.
|
||||||
Flush (File);
|
Flush (File);
|
||||||
LF := Wbuf.Data'First - 1;
|
LF := File.Wbuf.Data'First - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
I := I + 1;
|
||||||
|
File.Wbuf.Last := File.Wbuf.Last + 1;
|
||||||
|
File.Wbuf.Data(File.Wbuf.Last) := Inbuf(I);
|
||||||
|
if File.Wbuf.Data(File.Wbuf.Last) = Slim_Ascii.Pos.LF then -- TODO: different line terminator
|
||||||
|
-- Remeber the index of the line terminator
|
||||||
|
LF := File.Wbuf.Last;
|
||||||
end if;
|
end if;
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
-- The line terminator was found. Write up to the terminator.
|
-- The line terminator was found. Write up to the terminator.
|
||||||
-- Keep the rest in the internal buffer.
|
-- Keep the rest in the internal buffer.
|
||||||
while LF in Wbuf.Data'First .. Wbuf.Length loop
|
if LF in File.Wbuf.Data'Range then
|
||||||
OS.File.Write (File.File, Wbuf.Data(Wbuf.Data'First .. LF), J);
|
while File.Wbuf.Pos < LF loop
|
||||||
Shift_Buffer (Wbuf, J);
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
||||||
LF := LF - J;
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
||||||
end loop;
|
end loop;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
||||||
|
Compact_Buffer (File.Wbuf);
|
||||||
|
end if;
|
||||||
|
|
||||||
Length := I - Inbuf'First + 1;
|
Length := I - Inbuf'First + 1;
|
||||||
end Write_Line;
|
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
|
||||||
|
if (File.Option.Bits and OPTION_CRLF) /= 0 and then
|
||||||
|
not Injected and then Inbuf(I + 1) = Slim_Ascii.Pos.LF then
|
||||||
|
X := Slim_Ascii.Pos.CR;
|
||||||
|
Injected := Standard.True;
|
||||||
|
else
|
||||||
|
I := I + 1;
|
||||||
|
X := Inbuf(I);
|
||||||
|
Injected := Standard.False;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
File.Wbuf.Last := File.Wbuf.Last + 1;
|
||||||
|
File.Wbuf.Data(File.Wbuf.Last) := X;
|
||||||
|
if File.Wbuf.Data(File.Wbuf.Last) = Slim_Ascii.Pos.LF then -- TODO: different line terminator
|
||||||
|
-- Remeber the index of the line terminator
|
||||||
|
LF := File.Wbuf.Last;
|
||||||
|
end if;
|
||||||
|
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 Put_Line;
|
||||||
|
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
--| WRITE WIDE STRING
|
--| WRITE WIDE STRING
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
@ -519,8 +616,7 @@ package body File is
|
|||||||
Length: out System_Length) is
|
Length: out System_Length) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
|
|
||||||
Wbuf: File_Buffer renames File.Wbuf;
|
L, I: System_Length;
|
||||||
F, L, I: System_Length;
|
|
||||||
begin
|
begin
|
||||||
I := Buffer'First - 1;
|
I := Buffer'First - 1;
|
||||||
while I < Buffer'Last loop
|
while I < Buffer'Last loop
|
||||||
@ -530,20 +626,18 @@ package body File is
|
|||||||
Tmp2: System_Byte_Array(Tmp'Range);
|
Tmp2: System_Byte_Array(Tmp'Range);
|
||||||
for Tmp2'Address use Tmp'Address;
|
for Tmp2'Address use Tmp'Address;
|
||||||
begin
|
begin
|
||||||
F := Wbuf.Data'First + Wbuf.Length;
|
L := File.Wbuf.Last + Tmp2'Length;
|
||||||
L := F + Tmp2'Length - 1;
|
|
||||||
|
|
||||||
if L > Wbuf.Data'Last then
|
if L > File.Wbuf.Data'Last then
|
||||||
-- The multi-byte sequence for the current character
|
-- The multi-byte sequence for the current character
|
||||||
-- can't fit into the internal buffer. Flush the
|
-- can't fit into the internal buffer. Flush the
|
||||||
-- buffer and attempt to fit it in.
|
-- buffer and attempt to fit it in.
|
||||||
Flush (File);
|
Flush (File);
|
||||||
F := Wbuf.Data'First;
|
L := File.Wbuf.Pos + Tmp2'Length;
|
||||||
L := F + Tmp2'Length - 1;
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Wbuf.Data(F..L) := Tmp2;
|
File.Wbuf.Data(File.Wbuf.Last + 1 .. L) := Tmp2;
|
||||||
Wbuf.Length := Wbuf.Length + Tmp2'Length;
|
File.Wbuf.Last := L;
|
||||||
end;
|
end;
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
@ -556,56 +650,115 @@ package body File is
|
|||||||
Length: out System_Length) is
|
Length: out System_Length) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
|
|
||||||
Wbuf: File_Buffer renames File.Wbuf;
|
L, I, LF: System_Length;
|
||||||
F, L, I, LF: System_Length;
|
|
||||||
begin
|
begin
|
||||||
LF := Wbuf.Data'First - 1;
|
|
||||||
|
LF := File.Wbuf.Data'First - 1;
|
||||||
I := Buffer'First - 1;
|
I := Buffer'First - 1;
|
||||||
while I < Buffer'Last loop
|
while I < Buffer'Last loop
|
||||||
I := I + 1;
|
I := I + 1;
|
||||||
|
|
||||||
--if Buffer(I) = Wide_Ascii.LF then
|
|
||||||
--else
|
|
||||||
--end if;
|
|
||||||
|
|
||||||
declare
|
declare
|
||||||
Tmp: Slim_String := Wide_To_Slim(Buffer(I..I));
|
Tmp: Slim_String := Wide_To_Slim(Buffer(I..I));
|
||||||
Tmp2: System_Byte_Array(Tmp'Range);
|
Tmp2: System_Byte_Array(Tmp'Range);
|
||||||
for Tmp2'Address use Tmp'Address;
|
for Tmp2'Address use Tmp'Address;
|
||||||
begin
|
begin
|
||||||
F := Wbuf.Data'First + Wbuf.Length;
|
L := File.Wbuf.Last + Tmp2'Length;
|
||||||
L := F + Tmp2'Length - 1;
|
|
||||||
|
|
||||||
if L > Wbuf.Data'Last then
|
if L > File.Wbuf.Data'Last then
|
||||||
-- The multi-byte sequence for the current character
|
-- The multi-byte sequence for the current character
|
||||||
-- can't fit into the internal buffer. Flush the
|
-- can't fit into the internal buffer. Flush the
|
||||||
-- buffer and attempt to fit it in.
|
-- buffer and attempt to fit it in.
|
||||||
Flush (File);
|
Flush (File);
|
||||||
F := Wbuf.Data'First;
|
|
||||||
L := F + Tmp2'Length - 1;
|
|
||||||
LF := Wbuf.Data'First - 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
Wbuf.Data(F..L) := Tmp2;
|
L := File.Wbuf.Pos + Tmp2'Length;
|
||||||
Wbuf.Length := Wbuf.Length + Tmp2'Length;
|
LF := File.Wbuf.Data'First - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
if Buffer(I) = Wide_Ascii.LF then -- TODO: different line terminator
|
if Buffer(I) = Wide_Ascii.LF then -- TODO: different line terminator
|
||||||
LF := L;
|
LF := L;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
File.Wbuf.Data(File.Wbuf.Last + 1 .. L) := Tmp2;
|
||||||
|
File.Wbuf.Last := L;
|
||||||
end;
|
end;
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
-- The line terminator was found. Write up to the terminator.
|
if LF in File.Wbuf.Data'Range then
|
||||||
-- Keep the rest in the internal buffer.
|
while File.Wbuf.Pos < LF loop
|
||||||
while LF in Wbuf.Data'First .. Wbuf.Length loop
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. LF), L);
|
||||||
OS.File.Write (File.File, Wbuf.Data(Wbuf.Data'First .. LF), L);
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
||||||
Shift_Buffer (Wbuf, L);
|
end loop;
|
||||||
LF := LF - L;
|
end if;
|
||||||
end loop;
|
|
||||||
|
if File.Wbuf.Pos >= File.Wbuf.Data'First then
|
||||||
|
Compact_Buffer (File.Wbuf);
|
||||||
|
end if;
|
||||||
|
|
||||||
Length := I - Buffer'First + 1;
|
Length := I - Buffer'First + 1;
|
||||||
end Write_Line;
|
end Write_Line;
|
||||||
|
|
||||||
|
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;
|
||||||
|
X: Wide_String(1..2) := (Wide_Ascii.CR, Wide_Ascii.LF);
|
||||||
|
begin
|
||||||
|
|
||||||
|
LF := File.Wbuf.Data'First - 1;
|
||||||
|
I := Buffer'First - 1;
|
||||||
|
while I < Buffer'Last loop
|
||||||
|
I := I + 1;
|
||||||
|
|
||||||
|
X(2) := Buffer(I);
|
||||||
|
if (File.Option.Bits and OPTION_CRLF) /= 0 and then
|
||||||
|
Buffer(I) = Wide_Ascii.LF then
|
||||||
|
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;
|
||||||
|
|
||||||
|
if Buffer(I) = Wide_Ascii.LF then
|
||||||
|
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;
|
||||||
|
|
||||||
--|-----------------------------------------------------------------------
|
--|-----------------------------------------------------------------------
|
||||||
--| FLUSH AND DRAIN
|
--| FLUSH AND DRAIN
|
||||||
@ -613,12 +766,11 @@ package body File is
|
|||||||
procedure Flush (File: in out File_Record) is
|
procedure Flush (File: in out File_Record) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
|
|
||||||
Wbuf: File_Buffer renames File.Wbuf;
|
L: System_Length;
|
||||||
Length: System_Length;
|
|
||||||
begin
|
begin
|
||||||
while Wbuf.Length > 0 loop
|
while not Is_Empty(File.Wbuf) loop
|
||||||
--begin
|
--begin
|
||||||
OS.File.Write (File.File, Wbuf.Data(Wbuf.Data'First .. Wbuf.Length), Length);
|
OS.File.Write (File.File, File.Wbuf.Data(File.Wbuf.Pos + 1 .. File.Wbuf.Last), L);
|
||||||
--exception
|
--exception
|
||||||
-- when Would_Block_Exception =>
|
-- when Would_Block_Exception =>
|
||||||
-- -- Flush must write all it can.
|
-- -- Flush must write all it can.
|
||||||
@ -626,14 +778,16 @@ package body File is
|
|||||||
-- when others =>
|
-- when others =>
|
||||||
-- raise;
|
-- raise;
|
||||||
--end;
|
--end;
|
||||||
Shift_Buffer (Wbuf, Length);
|
File.Wbuf.Pos := File.Wbuf.Pos + L;
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
|
Set_Length (File.Wbuf, 0);
|
||||||
end Flush;
|
end Flush;
|
||||||
|
|
||||||
procedure Drain (File: in out File_Record) is
|
procedure Drain (File: in out File_Record) is
|
||||||
pragma Assert (Is_Open(File));
|
pragma Assert (Is_Open(File));
|
||||||
begin
|
begin
|
||||||
File.Wbuf.Length := 0;
|
Set_Length (File.Wbuf, 0);
|
||||||
end Drain;
|
end Drain;
|
||||||
|
|
||||||
end File;
|
end File;
|
||||||
|
@ -34,6 +34,14 @@ package H2.IO is
|
|||||||
FLAG_SYNC: constant Flag_Bits := OS.File.FLAG_SYNC;
|
FLAG_SYNC: constant Flag_Bits := OS.File.FLAG_SYNC;
|
||||||
FLAG_NOFOLLOW: constant Flag_Bits := OS.File.FLAG_NOFOLLOW;
|
FLAG_NOFOLLOW: constant Flag_Bits := OS.File.FLAG_NOFOLLOW;
|
||||||
|
|
||||||
|
type Option_Bits is new System_Word;
|
||||||
|
type Option_Record is record
|
||||||
|
Bits: Option_Bits := 0;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
-- Convert LF to CR/LF in Put_Line
|
||||||
|
OPTION_CRLF: constant Option_Bits := 2#0000_0000_0000_0001#;
|
||||||
|
|
||||||
type File_Buffer is private;
|
type File_Buffer is private;
|
||||||
type File_Record is limited private;
|
type File_Record is limited private;
|
||||||
|
|
||||||
@ -43,6 +51,12 @@ package H2.IO is
|
|||||||
procedure Clear_Flag_Bits (Flag: in out Flag_Record;
|
procedure Clear_Flag_Bits (Flag: in out Flag_Record;
|
||||||
Bits: in Flag_Bits) renames OS.File.Clear_Flag_Bits;
|
Bits: in Flag_Bits) renames OS.File.Clear_Flag_Bits;
|
||||||
|
|
||||||
|
procedure Set_Option_Bits (Option: in out Option_Record;
|
||||||
|
Bits: in Option_Bits);
|
||||||
|
|
||||||
|
procedure Clear_Option_Bits (Option: in out Option_Record;
|
||||||
|
Bits: in Option_Bits);
|
||||||
|
|
||||||
function Is_Open (File: in File_Record) return Standard.Boolean;
|
function Is_Open (File: in File_Record) return Standard.Boolean;
|
||||||
pragma Inline (Is_Open);
|
pragma Inline (Is_Open);
|
||||||
|
|
||||||
@ -56,9 +70,12 @@ package H2.IO is
|
|||||||
Flag: in Flag_Record;
|
Flag: in Flag_Record;
|
||||||
Pool: in Storage_Pool_Pointer := null);
|
Pool: in Storage_Pool_Pointer := null);
|
||||||
|
|
||||||
|
|
||||||
procedure Close (File: in out File_Record);
|
procedure Close (File: in out File_Record);
|
||||||
|
|
||||||
|
procedure Set_Option (File: in out File_Record; Option: in Option_Record);
|
||||||
|
|
||||||
|
function Get_Option (File: in File_Record) return Option_Record;
|
||||||
|
|
||||||
-- The Read procedure reads as many characters as the buffer
|
-- The Read procedure reads as many characters as the buffer
|
||||||
-- can hold with a single system call at most.
|
-- can hold with a single system call at most.
|
||||||
procedure Read (File: in out File_Record;
|
procedure Read (File: in out File_Record;
|
||||||
@ -102,6 +119,11 @@ package H2.IO is
|
|||||||
Buffer: in Slim_String;
|
Buffer: in Slim_String;
|
||||||
Length: out System_Length);
|
Length: out System_Length);
|
||||||
|
|
||||||
|
procedure Put_Line (File: in out File_Record;
|
||||||
|
Buffer: in Slim_String;
|
||||||
|
Length: out System_Length);
|
||||||
|
|
||||||
|
|
||||||
procedure Write (File: in out File_Record;
|
procedure Write (File: in out File_Record;
|
||||||
Buffer: in Wide_String;
|
Buffer: in Wide_String;
|
||||||
Length: out System_Length);
|
Length: out System_Length);
|
||||||
@ -110,6 +132,10 @@ package H2.IO is
|
|||||||
Buffer: in Wide_String;
|
Buffer: in Wide_String;
|
||||||
Length: out System_Length);
|
Length: out System_Length);
|
||||||
|
|
||||||
|
procedure Put_Line (File: in out File_Record;
|
||||||
|
Buffer: in Wide_String;
|
||||||
|
Length: out System_Length);
|
||||||
|
|
||||||
procedure Flush (File: in out File_Record);
|
procedure Flush (File: in out File_Record);
|
||||||
procedure Drain (File: in out File_Record);
|
procedure Drain (File: in out File_Record);
|
||||||
|
|
||||||
@ -123,8 +149,7 @@ package H2.IO is
|
|||||||
-- The Data array size must be as large as the longest
|
-- The Data array size must be as large as the longest
|
||||||
-- multi-byte sequence for a single wide character.
|
-- multi-byte sequence for a single wide character.
|
||||||
Data: System_Byte_Array (1 .. 2048);
|
Data: System_Byte_Array (1 .. 2048);
|
||||||
Length: System_Length := 0;
|
Pos: System_Length := 0;
|
||||||
First: System_Length := 0;
|
|
||||||
Last: System_Length := 0;
|
Last: System_Length := 0;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
@ -133,6 +158,7 @@ package H2.IO is
|
|||||||
Rbuf: File_Buffer;
|
Rbuf: File_Buffer;
|
||||||
Wbuf: File_Buffer;
|
Wbuf: File_Buffer;
|
||||||
EOF: Standard.Boolean := false;
|
EOF: Standard.Boolean := false;
|
||||||
|
Option: Option_Record;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
end File;
|
end File;
|
||||||
|
Loading…
Reference in New Issue
Block a user