1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . S T R E A M S . S T O R A G E . U N B O U N D E D --
9 -- Copyright (C) 2020-2023, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 ------------------------------------------------------------------------------
29 with Ada
.Unchecked_Deallocation
;
31 package body Ada
.Streams
.Storage
.Unbounded
is
33 procedure Free
is new Ada
.Unchecked_Deallocation
34 (Elements_Type
, Elements_Access
);
40 overriding
procedure Finalize
(X
: in out Controlled_Elements_Access
) is
42 if X
.A
/= Empty_Elements
'Access then
51 overriding
procedure Read
52 (Stream
: in out Stream_Type
; Item
: out Stream_Element_Array
;
53 Last
: out Stream_Element_Offset
)
55 EA
: Stream_Element_Array
renames
56 Stream
.Elements
.A
.EA
(1 .. Element_Count
(Stream
));
58 if Item
'Length = 0 then
59 Last
:= Item
'First - 1;
61 -- If the entire content of the stream fits in Item, then copy it and
62 -- clear the stream. This is likely the usual case.
64 elsif Element_Count
(Stream
) <= Item
'Length then
65 Last
:= Item
'First + Element_Count
(Stream
) - 1;
66 Item
(Item
'First .. Last
) := EA
;
69 -- Otherwise, copy as much into Item as will fit. Then slide the
70 -- remaining part of the stream down, and compute the new Count.
71 -- We expect this to be the unusual case, so the cost of copying
72 -- the remaining part probably doesn't matter.
78 New_Count
: constant Stream_Element_Count
:=
79 Element_Count
(Stream
) - Item
'Length;
81 Item
:= EA
(1 .. Item
'Length);
82 EA
(1 .. New_Count
) :=
83 EA
(Element_Count
(Stream
) - New_Count
+ 1 ..
84 Element_Count
(Stream
));
85 Stream
.Count
:= New_Count
;
94 overriding
procedure Write
95 (Stream
: in out Stream_Type
; Item
: Stream_Element_Array
)
97 New_Count
: constant Stream_Element_Count
:=
98 Element_Count
(Stream
) + Item
'Length;
100 -- Check whether we need to grow the array. If so, then if the Stream is
101 -- empty, allocate a goodly amount. Otherwise double the length, for
102 -- amortized efficiency. In any case, we need to make sure it's at least
103 -- big enough for New_Count.
105 if New_Count
> Stream
.Elements
.A
.Last
then
107 New_Last
: Stream_Element_Index
:=
108 (if Stream
.Elements
.A
.Last
= 0 then 2**10 -- goodly amount
109 else Stream
.Elements
.A
.Last
* 2);
110 Old_Elements
: Elements_Access
:= Stream
.Elements
.A
;
112 if New_Last
< New_Count
then
113 New_Last
:= New_Count
;
116 Stream
.Elements
.A
:= new Elements_Type
(Last
=> New_Last
);
118 if Old_Elements
/= Empty_Elements
'Access then
119 Stream
.Elements
.A
.EA
(Old_Elements
.EA
'Range) := Old_Elements
.EA
;
125 Stream
.Elements
.A
.EA
(Element_Count
(Stream
) + 1 .. New_Count
) := Item
;
126 Stream
.Count
:= New_Count
;
133 overriding
function Element_Count
134 (Stream
: Stream_Type
) return Stream_Element_Count
144 overriding
procedure Clear
(Stream
: in out Stream_Type
) is
147 -- We don't free Stream.Elements here, because we want to reuse it if
148 -- there are more Write calls.
151 end Ada
.Streams
.Storage
.Unbounded
;