1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- S Y S T E M . S T R I N G S . S T R E A M _ O P S --
9 -- Copyright (C) 2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 pragma Warnings (Off);
38 with Ada.Streams; use Ada.Streams;
39 with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
40 with Ada.Unchecked_Conversion;
42 with System.Stream_Attributes; use System;
44 package body System.Strings.Stream_Ops is
46 -- The following type describes the low-level IO mechanism used in package
47 -- Stream_Ops_Internal.
49 type IO_Kind is (Byte_IO, Block_IO);
51 -- The following package provides an IO framework for strings. Depending
52 -- on the version of System.Stream_Attributes as well as the size of
53 -- formal parameter Character_Type, the package will either utilize block
54 -- IO or character-by-character IO.
57 type Character_Type is private;
58 type String_Type is array (Positive range <>) of Character_Type;
60 package Stream_Ops_Internal is
62 (Strm : access Root_Stream_Type'Class;
63 IO : IO_Kind) return String_Type;
66 (Strm : access Root_Stream_Type'Class;
71 (Strm : access Root_Stream_Type'Class;
72 Item : out String_Type;
76 (Strm : access Root_Stream_Type'Class;
79 end Stream_Ops_Internal;
81 -------------------------
82 -- Stream_Ops_Internal --
83 -------------------------
85 package body Stream_Ops_Internal is
87 -- The following value represents the number of BITS allocated for the
88 -- default block used in string IO. The sizes of all other types are
89 -- calculated relative to this value.
91 Default_Block_Size : constant := 512 * 8;
93 -- Shorthand notation for stream element and character sizes
95 C_Size : constant Integer := Character_Type'Size;
96 SE_Size : constant Integer := Stream_Element'Size;
98 -- The following constants describe the number of stream elements or
99 -- characters that can fit into a default block.
101 C_In_Default_Block : constant Integer := Default_Block_Size / C_Size;
102 SE_In_Default_Block : constant Integer := Default_Block_Size / SE_Size;
106 subtype Default_Block is Stream_Element_Array
107 (1 .. Stream_Element_Offset (SE_In_Default_Block));
109 subtype String_Block is String_Type (1 .. C_In_Default_Block);
111 -- Conversions to and from Default_Block
113 function To_Default_Block is
114 new Ada.Unchecked_Conversion (String_Block, Default_Block);
116 function To_String_Block is
117 new Ada.Unchecked_Conversion (Default_Block, String_Block);
124 (Strm : access Root_Stream_Type'Class;
125 IO : IO_Kind) return String_Type
129 raise Constraint_Error;
137 -- Read the bounds of the string
139 Positive'Read (Strm, Low);
140 Positive'Read (Strm, High);
143 Item : String_Type (Low .. High);
146 -- Read the character content of the string
148 Read (Strm, Item, IO);
160 (Strm : access Root_Stream_Type'Class;
166 raise Constraint_Error;
169 -- Write the bounds of the string
171 Positive'Write (Strm, Item'First);
172 Positive'Write (Strm, Item'Last);
174 -- Write the character content of the string
176 Write (Strm, Item, IO);
184 (Strm : access Root_Stream_Type'Class;
185 Item : out String_Type;
190 raise Constraint_Error;
193 -- Nothing to do if the desired string is empty
195 if Item'Length = 0 then
202 and then Stream_Attributes.Block_IO_OK
205 -- Determine the size in BITS of the block necessary to contain
208 Block_Size : constant Natural :=
209 (Item'Last - Item'First + 1) * C_Size;
211 -- Item can be larger than what the default block can store,
212 -- determine the number of whole reads necessary to read the
215 Blocks : constant Natural := Block_Size / Default_Block_Size;
217 -- The size of Item may not be a multiple of the default block
218 -- size, determine the size of the remaining chunk in BITS.
220 Rem_Size : constant Natural :=
221 Block_Size mod Default_Block_Size;
225 Low : Positive := Item'First;
226 High : Positive := Low + C_In_Default_Block - 1;
228 -- End of stream error detection
230 Last : Stream_Element_Offset := 0;
231 Sum : Stream_Element_Offset := 0;
234 -- Step 1: If the string is too large, read in individual
235 -- chunks the size of the default block.
239 Block : Default_Block;
242 for Counter in 1 .. Blocks loop
243 Read (Strm.all, Block, Last);
244 Item (Low .. High) := To_String_Block (Block);
247 High := Low + C_In_Default_Block - 1;
254 -- Step 2: Read in any remaining elements
258 subtype Rem_Block is Stream_Element_Array
259 (1 .. Stream_Element_Offset (Rem_Size / SE_Size));
261 subtype Rem_String_Block is
262 String_Type (1 .. Rem_Size / C_Size);
264 function To_Rem_String_Block is new
265 Ada.Unchecked_Conversion (Rem_Block, Rem_String_Block);
270 Read (Strm.all, Block, Last);
271 Item (Low .. Item'Last) := To_Rem_String_Block (Block);
277 -- Step 3: Potential error detection. The sum of all the
278 -- chunks is less than we initially wanted to read. In other
279 -- words, the stream does not contain enough elements to fully
282 if (Integer (Sum) * SE_Size) / C_Size < Item'Length then
294 for Index in Item'First .. Item'Last loop
295 Character_Type'Read (Strm, C);
307 (Strm : access Root_Stream_Type'Class;
313 raise Constraint_Error;
316 -- Nothing to do if the input string is empty
318 if Item'Length = 0 then
325 and then Stream_Attributes.Block_IO_OK
328 -- Determine the size in BITS of the block necessary to contain
331 Block_Size : constant Natural := Item'Length * C_Size;
333 -- Item can be larger than what the default block can store,
334 -- determine the number of whole writes necessary to output the
337 Blocks : constant Natural := Block_Size / Default_Block_Size;
339 -- The size of Item may not be a multiple of the default block
340 -- size, determine the size of the remaining chunk.
342 Rem_Size : constant Natural :=
343 Block_Size mod Default_Block_Size;
347 Low : Positive := Item'First;
348 High : Positive := Low + C_In_Default_Block - 1;
351 -- Step 1: If the string is too large, write out individual
352 -- chunks the size of the default block.
354 for Counter in 1 .. Blocks loop
355 Write (Strm.all, To_Default_Block (Item (Low .. High)));
358 High := Low + C_In_Default_Block - 1;
361 -- Step 2: Write out any remaining elements
365 subtype Rem_Block is Stream_Element_Array
366 (1 .. Stream_Element_Offset (Rem_Size / SE_Size));
368 subtype Rem_String_Block is
369 String_Type (1 .. Rem_Size / C_Size);
371 function To_Rem_Block is new
372 Ada.Unchecked_Conversion (Rem_String_Block, Rem_Block);
375 Write (Strm.all, To_Rem_Block (Item (Low .. Item'Last)));
383 for Index in Item'First .. Item'Last loop
384 Character_Type'Write (Strm, Item (Index));
388 end Stream_Ops_Internal;
390 -- Specific instantiations for all Ada string types
392 package String_Ops is
393 new Stream_Ops_Internal
394 (Character_Type => Character,
395 String_Type => String);
397 package Wide_String_Ops is
398 new Stream_Ops_Internal
399 (Character_Type => Wide_Character,
400 String_Type => Wide_String);
402 package Wide_Wide_String_Ops is
403 new Stream_Ops_Internal
404 (Character_Type => Wide_Wide_Character,
405 String_Type => Wide_Wide_String);
411 function String_Input
412 (Strm : access Ada.Streams.Root_Stream_Type'Class) return String
415 return String_Ops.Input (Strm, Byte_IO);
418 -------------------------
419 -- String_Input_Blk_IO --
420 -------------------------
422 function String_Input_Blk_IO
423 (Strm : access Ada.Streams.Root_Stream_Type'Class) return String
426 return String_Ops.Input (Strm, Block_IO);
427 end String_Input_Blk_IO;
433 procedure String_Output
434 (Strm : access Ada.Streams.Root_Stream_Type'Class;
438 String_Ops.Output (Strm, Item, Byte_IO);
441 --------------------------
442 -- String_Output_Blk_IO --
443 --------------------------
445 procedure String_Output_Blk_IO
446 (Strm : access Ada.Streams.Root_Stream_Type'Class;
450 String_Ops.Output (Strm, Item, Block_IO);
451 end String_Output_Blk_IO;
457 procedure String_Read
458 (Strm : access Ada.Streams.Root_Stream_Type'Class;
462 String_Ops.Read (Strm, Item, Byte_IO);
465 ------------------------
466 -- String_Read_Blk_IO --
467 ------------------------
469 procedure String_Read_Blk_IO
470 (Strm : access Ada.Streams.Root_Stream_Type'Class;
474 String_Ops.Read (Strm, Item, Block_IO);
475 end String_Read_Blk_IO;
481 procedure String_Write
482 (Strm : access Ada.Streams.Root_Stream_Type'Class;
486 String_Ops.Write (Strm, Item, Byte_IO);
489 -------------------------
490 -- String_Write_Blk_IO --
491 -------------------------
493 procedure String_Write_Blk_IO
494 (Strm : access Ada.Streams.Root_Stream_Type'Class;
498 String_Ops.Write (Strm, Item, Block_IO);
499 end String_Write_Blk_IO;
501 -----------------------
502 -- Wide_String_Input --
503 -----------------------
505 function Wide_String_Input
506 (Strm : access Ada.Streams.Root_Stream_Type'Class) return Wide_String
509 return Wide_String_Ops.Input (Strm, Byte_IO);
510 end Wide_String_Input;
512 ------------------------------
513 -- Wide_String_Input_Blk_IO --
514 ------------------------------
516 function Wide_String_Input_Blk_IO
517 (Strm : access Ada.Streams.Root_Stream_Type'Class) return Wide_String
520 return Wide_String_Ops.Input (Strm, Block_IO);
521 end Wide_String_Input_Blk_IO;
523 ------------------------
524 -- Wide_String_Output --
525 ------------------------
527 procedure Wide_String_Output
528 (Strm : access Ada.Streams.Root_Stream_Type'Class;
532 Wide_String_Ops.Output (Strm, Item, Byte_IO);
533 end Wide_String_Output;
535 -------------------------------
536 -- Wide_String_Output_Blk_IO --
537 -------------------------------
539 procedure Wide_String_Output_Blk_IO
540 (Strm : access Ada.Streams.Root_Stream_Type'Class;
544 Wide_String_Ops.Output (Strm, Item, Block_IO);
545 end Wide_String_Output_Blk_IO;
547 ----------------------
548 -- Wide_String_Read --
549 ----------------------
551 procedure Wide_String_Read
552 (Strm : access Ada.Streams.Root_Stream_Type'Class;
553 Item : out Wide_String)
556 Wide_String_Ops.Read (Strm, Item, Byte_IO);
557 end Wide_String_Read;
559 -----------------------------
560 -- Wide_String_Read_Blk_IO --
561 -----------------------------
563 procedure Wide_String_Read_Blk_IO
564 (Strm : access Ada.Streams.Root_Stream_Type'Class;
565 Item : out Wide_String)
568 Wide_String_Ops.Read (Strm, Item, Block_IO);
569 end Wide_String_Read_Blk_IO;
571 -----------------------
572 -- Wide_String_Write --
573 -----------------------
575 procedure Wide_String_Write
576 (Strm : access Ada.Streams.Root_Stream_Type'Class;
580 Wide_String_Ops.Write (Strm, Item, Byte_IO);
581 end Wide_String_Write;
583 ------------------------------
584 -- Wide_String_Write_Blk_IO --
585 ------------------------------
587 procedure Wide_String_Write_Blk_IO
588 (Strm : access Ada.Streams.Root_Stream_Type'Class;
592 Wide_String_Ops.Write (Strm, Item, Block_IO);
593 end Wide_String_Write_Blk_IO;
595 ----------------------------
596 -- Wide_Wide_String_Input --
597 ----------------------------
599 function Wide_Wide_String_Input
600 (Strm : access Ada.Streams.Root_Stream_Type'Class) return Wide_Wide_String
603 return Wide_Wide_String_Ops.Input (Strm, Byte_IO);
604 end Wide_Wide_String_Input;
606 -----------------------------------
607 -- Wide_Wide_String_Input_Blk_IO --
608 -----------------------------------
610 function Wide_Wide_String_Input_Blk_IO
611 (Strm : access Ada.Streams.Root_Stream_Type'Class) return Wide_Wide_String
614 return Wide_Wide_String_Ops.Input (Strm, Block_IO);
615 end Wide_Wide_String_Input_Blk_IO;
617 -----------------------------
618 -- Wide_Wide_String_Output --
619 -----------------------------
621 procedure Wide_Wide_String_Output
622 (Strm : access Ada.Streams.Root_Stream_Type'Class;
623 Item : Wide_Wide_String)
626 Wide_Wide_String_Ops.Output (Strm, Item, Byte_IO);
627 end Wide_Wide_String_Output;
629 ------------------------------------
630 -- Wide_Wide_String_Output_Blk_IO --
631 ------------------------------------
633 procedure Wide_Wide_String_Output_Blk_IO
634 (Strm : access Ada.Streams.Root_Stream_Type'Class;
635 Item : Wide_Wide_String)
638 Wide_Wide_String_Ops.Output (Strm, Item, Block_IO);
639 end Wide_Wide_String_Output_Blk_IO;
641 ---------------------------
642 -- Wide_Wide_String_Read --
643 ---------------------------
645 procedure Wide_Wide_String_Read
646 (Strm : access Ada.Streams.Root_Stream_Type'Class;
647 Item : out Wide_Wide_String)
650 Wide_Wide_String_Ops.Read (Strm, Item, Byte_IO);
651 end Wide_Wide_String_Read;
653 ----------------------------------
654 -- Wide_Wide_String_Read_Blk_IO --
655 ----------------------------------
657 procedure Wide_Wide_String_Read_Blk_IO
658 (Strm : access Ada.Streams.Root_Stream_Type'Class;
659 Item : out Wide_Wide_String)
662 Wide_Wide_String_Ops.Read (Strm, Item, Block_IO);
663 end Wide_Wide_String_Read_Blk_IO;
665 ----------------------------
666 -- Wide_Wide_String_Write --
667 ----------------------------
669 procedure Wide_Wide_String_Write
670 (Strm : access Ada.Streams.Root_Stream_Type'Class;
671 Item : Wide_Wide_String)
674 Wide_Wide_String_Ops.Write (Strm, Item, Byte_IO);
675 end Wide_Wide_String_Write;
677 -----------------------------------
678 -- Wide_Wide_String_Write_Blk_IO --
679 -----------------------------------
681 procedure Wide_Wide_String_Write_Blk_IO
682 (Strm : access Ada.Streams.Root_Stream_Type'Class;
683 Item : Wide_Wide_String)
686 Wide_Wide_String_Ops.Write (Strm, Item, Block_IO);
687 end Wide_Wide_String_Write_Blk_IO;
689 end System.Strings.Stream_Ops;