author | Claus Gittinger <cg@exept.de> |
Wed, 26 Jun 2019 22:06:12 +0200 | |
changeset 24369 | e796791ea838 |
parent 24029 | b34b5808b448 |
child 24630 | 861b42a1a269 |
permissions | -rw-r--r-- |
10846 | 1 |
" |
2 |
COPYRIGHT (c) 2005 by eXept Software AG |
|
3 |
All Rights Reserved |
|
4 |
||
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
8299 | 12 |
"{ Package: 'stx:libbasic' }" |
8298 | 13 |
|
17622 | 14 |
"{ NameSpace: Smalltalk }" |
15 |
||
8298 | 16 |
WriteStream subclass:#CharacterWriteStream |
17 |
instanceVariableNames:'currentCharacterSize' |
|
18 |
classVariableNames:'' |
|
19 |
poolDictionaries:'' |
|
20 |
category:'Streams' |
|
21 |
! |
|
22 |
||
8321 | 23 |
!CharacterWriteStream class methodsFor:'documentation'! |
24 |
||
10846 | 25 |
copyright |
26 |
" |
|
27 |
COPYRIGHT (c) 2005 by eXept Software AG |
|
28 |
All Rights Reserved |
|
29 |
||
30 |
This software is furnished under a license and may be used |
|
31 |
only in accordance with the terms of that license and with the |
|
32 |
inclusion of the above copyright notice. This software may not |
|
33 |
be provided or otherwise made available to, or used by, any |
|
34 |
other person. No title to or ownership of the software is |
|
35 |
hereby transferred. |
|
36 |
" |
|
37 |
! |
|
38 |
||
8321 | 39 |
documentation |
40 |
" |
|
41 |
This is a WriteStream, which automagically changes the underlying collection, |
|
18795 | 42 |
if a character does not fit into the current collection |
18796 | 43 |
(i.e. String -> Unicode16String -> Unicode32Sting ) |
8321 | 44 |
|
45 |
[author:] |
|
46 |
Stefan Vogel (stefan@zwerg) |
|
47 |
||
48 |
[instance variables:] |
|
49 |
||
50 |
[class variables:] |
|
51 |
||
52 |
[see also:] |
|
10280 | 53 |
String Unicode16String Unicode32Sting |
8321 | 54 |
" |
55 |
! |
|
56 |
||
57 |
examples |
|
58 |
" |
|
59 |
||
60 |
[exBegin] |
|
61 |
|stream| |
|
62 |
||
63 |
stream := CharacterWriteStream on:(String new:32). |
|
64 |
stream nextPutAll:'abc'. |
|
65 |
stream nextPut:(Character value:16r2c00). |
|
66 |
stream contents inspect |
|
67 |
[exEnd] |
|
68 |
||
69 |
" |
|
70 |
! ! |
|
71 |
||
18265 | 72 |
!CharacterWriteStream class methodsFor:'instance creation'! |
73 |
||
74 |
new |
|
75 |
"I know, that I operate on strings" |
|
76 |
||
18282 | 77 |
^ self on:(String uninitializedNew:10) |
18265 | 78 |
! |
79 |
||
80 |
new:count |
|
81 |
"I know, that I operate on strings" |
|
82 |
||
18282 | 83 |
^ self on:(String uninitializedNew:count) |
18265 | 84 |
! ! |
85 |
||
14607 | 86 |
!CharacterWriteStream methodsFor:'accessing'! |
87 |
||
88 |
reset |
|
19647 | 89 |
"reset the stream, to write again over the existing (or already written) contents. |
14607 | 90 |
See the comment in WriteStream>>contents" |
91 |
||
19886 | 92 |
"start with 8-bit String again" |
14607 | 93 |
collection := String new:collection size. |
94 |
currentCharacterSize := collection bitsPerCharacter. |
|
19886 | 95 |
position := 0. |
14607 | 96 |
! ! |
97 |
||
8321 | 98 |
!CharacterWriteStream methodsFor:'private'! |
99 |
||
18598 | 100 |
characterSizeChangedTo:newCharacterSize size:additionalSize |
101 |
"change aCollection to fit the size of newCharacterSize" |
|
8321 | 102 |
|
18598 | 103 |
|sz newSz| |
8321 | 104 |
|
18598 | 105 |
currentCharacterSize < newCharacterSize ifTrue:[ |
106 |
newSz := sz := collection size. |
|
17622 | 107 |
position + additionalSize >= sz ifTrue:[ |
18598 | 108 |
newSz := newSz + additionalSize + 100. "add some more space, maybe more will be added" |
8321 | 109 |
]. |
18598 | 110 |
collection := ((CharacterArray speciesForCharacterSize:newCharacterSize) new:newSz) |
18613 | 111 |
replaceFrom:1 to:position with:collection startingAt:1. |
18598 | 112 |
currentCharacterSize := collection bitsPerCharacter. |
8321 | 113 |
]. |
114 |
! ! |
|
115 |
||
116 |
!CharacterWriteStream methodsFor:'private-accessing'! |
|
117 |
||
118 |
on:aCollection |
|
19647 | 119 |
"return a stream for writing into aCollection" |
120 |
||
8321 | 121 |
currentCharacterSize := aCollection bitsPerCharacter. |
122 |
^ super on:aCollection. |
|
123 |
! |
|
124 |
||
125 |
on:aCollection from:start to:stop |
|
19647 | 126 |
"return a stream for writing into part of aCollection. |
127 |
This will position the stream to start writing at start-index, |
|
128 |
and setup a writeLimit at stop-index. |
|
129 |
Contents after stop-index will not be overwritten." |
|
130 |
||
8321 | 131 |
currentCharacterSize := aCollection bitsPerCharacter. |
132 |
^ super on:aCollection from:start to:stop. |
|
19647 | 133 |
|
134 |
"notice: only the first 6 characters are overwritten: |
|
135 |
||
136 |
|str s| |
|
137 |
str := 'hello world bla'. |
|
138 |
s := CharacterWriteStream on:str from:6 to:11. |
|
139 |
s nextPutAll:'1234567890'. |
|
140 |
str |
|
141 |
" |
|
8321 | 142 |
! |
143 |
||
144 |
with:aCollection |
|
19647 | 145 |
"return a stream for writing into aCollection. |
146 |
This will position the stream to the end, and append written elements |
|
147 |
after the initial contents. |
|
148 |
I.e. the effect is similar to creating an empty stream first and then write |
|
149 |
aCollection." |
|
150 |
||
8321 | 151 |
currentCharacterSize := aCollection bitsPerCharacter. |
152 |
^ super with:aCollection. |
|
19647 | 153 |
|
154 |
" |
|
155 |
|s| |
|
156 |
s := CharacterWriteStream with:'hello'. |
|
157 |
s nextPutAll:'1234567890'. |
|
158 |
s contents |
|
159 |
" |
|
8321 | 160 |
! ! |
161 |
||
8298 | 162 |
!CharacterWriteStream methodsFor:'writing'! |
163 |
||
8321 | 164 |
next:count put:aCharacter |
165 |
"append anObject count times to the receiver. |
|
166 |
Redefined to avoid count grows of the underlying collection - |
|
167 |
instead a single grow on the final size is performed." |
|
168 |
||
18598 | 169 |
|needCharacterSize| |
170 |
||
171 |
needCharacterSize := aCharacter characterSize. |
|
172 |
needCharacterSize > currentCharacterSize ifTrue:[ |
|
173 |
self characterSizeChangedTo:needCharacterSize size:count. |
|
8321 | 174 |
]. |
12133 | 175 |
super next:count put:aCharacter |
8321 | 176 |
! |
177 |
||
178 |
nextPut:aCharacter |
|
179 |
"append the argument, aCharacter to the stream. |
|
18598 | 180 |
Specially tuned for appending to String, Unicode16String and Unicode32String streams." |
8298 | 181 |
|
182 |
%{ /* NOCONTEXT */ |
|
183 |
||
184 |
#ifndef NO_PRIM_STREAM |
|
18598 | 185 |
OBJ coll = __INST(collection); |
186 |
OBJ p = __INST(position); |
|
8298 | 187 |
|
8321 | 188 |
if (__isNonNilObject(coll) && __isSmallInteger(p) && __isCharacter(aCharacter)) { |
18598 | 189 |
REGISTER int pos = __intVal(p) + 1; /* make 1-based */ |
190 |
OBJ wL = __INST(writeLimit); |
|
8298 | 191 |
|
192 |
if ((wL == nil) |
|
193 |
|| (__isSmallInteger(wL) && (pos <= __intVal(wL)))) { |
|
18598 | 194 |
OBJ cls = __qClass(coll); |
195 |
unsigned ch = __intVal(__characterVal(aCharacter)); |
|
196 |
OBJ rL = __INST(readLimit); |
|
197 |
int __readLimit = -1; |
|
8298 | 198 |
|
199 |
if (__isSmallInteger(rL)) { |
|
200 |
__readLimit = __intVal(rL); |
|
201 |
} |
|
202 |
||
203 |
if (cls == @global(String)) { |
|
204 |
if (ch > 0xFF) { |
|
205 |
goto resize; |
|
206 |
} |
|
207 |
if (pos <= __stringSize(coll)) { |
|
208 |
__StringInstPtr(coll)->s_element[pos-1] = ch; |
|
209 |
if ((__readLimit >= 0) && (pos >= __readLimit)) { |
|
8913 | 210 |
__INST(readLimit) = __mkSmallInteger(pos); |
8298 | 211 |
} |
8913 | 212 |
__INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1); |
8321 | 213 |
RETURN ( aCharacter ); |
8298 | 214 |
} |
215 |
} else if (cls == @global(Unicode16String)) { |
|
216 |
if (ch > 0xFFFF) { |
|
217 |
goto resize; |
|
218 |
} |
|
219 |
if (pos <= __unicode16StringSize(coll)) { |
|
220 |
__Unicode16StringInstPtr(coll)->s_element[pos-1] = ch; |
|
221 |
if ((__readLimit >= 0) && (pos >= __readLimit)) { |
|
8913 | 222 |
__INST(readLimit) = __mkSmallInteger(pos); |
8298 | 223 |
} |
8913 | 224 |
__INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1); |
8321 | 225 |
RETURN ( aCharacter ); |
8298 | 226 |
} |
227 |
} else if (cls == @global(Unicode32String)) { |
|
228 |
if ((pos <= __unicode32StringSize(coll))) { |
|
229 |
__Unicode32StringInstPtr(coll)->s_element[pos-1] = ch; |
|
230 |
if ((__readLimit >= 0) && (pos >= __readLimit)) { |
|
8913 | 231 |
__INST(readLimit) = __mkSmallInteger(pos); |
8298 | 232 |
} |
8913 | 233 |
__INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1); |
8321 | 234 |
RETURN ( aCharacter ); |
8298 | 235 |
} |
236 |
} |
|
237 |
} |
|
238 |
} |
|
239 |
resize:; |
|
240 |
#endif |
|
241 |
%}. |
|
242 |
||
8321 | 243 |
|
8298 | 244 |
(writeLimit isNil |
15349
7c2c460c5feb
class: CharacterWriteStream
Claus Gittinger <cg@exept.de>
parents:
14607
diff
changeset
|
245 |
or:[(position + 1) <= writeLimit]) ifTrue:[ |
18598 | 246 |
|needCharacterSize| |
247 |
||
248 |
needCharacterSize := aCharacter characterSize. |
|
249 |
needCharacterSize > currentCharacterSize ifTrue:[ |
|
250 |
self characterSizeChangedTo:needCharacterSize size:1. |
|
251 |
] ifFalse:[ |
|
252 |
(position >= collection size) ifTrue:[self growCollection]. |
|
8321 | 253 |
]. |
15349
7c2c460c5feb
class: CharacterWriteStream
Claus Gittinger <cg@exept.de>
parents:
14607
diff
changeset
|
254 |
collection at:(position + 1) put:aCharacter. |
15358
6b69ebd9785c
class: CharacterWriteStream
Claus Gittinger <cg@exept.de>
parents:
15349
diff
changeset
|
255 |
(position >= readLimit) ifTrue:[readLimit := (position + 1)]. |
8298 | 256 |
position := position + 1. |
257 |
] ifFalse:[ |
|
8321 | 258 |
WriteError raiseErrorString:'write beyond writeLimit' |
259 |
]. |
|
260 |
^ aCharacter |
|
261 |
! |
|
262 |
||
263 |
nextPutAll:aCollection |
|
11319 | 264 |
"append aCollection to the receiver. |
22419 | 265 |
Redefined to convert to a string of the needed character size." |
8321 | 266 |
|
18598 | 267 |
|needCharacterSize| |
268 |
||
269 |
needCharacterSize := aCollection characterSize. |
|
270 |
needCharacterSize > currentCharacterSize ifTrue:[ |
|
271 |
self characterSizeChangedTo:needCharacterSize size:aCollection size. |
|
8298 | 272 |
]. |
12133 | 273 |
super nextPutAll:aCollection |
22419 | 274 |
|
275 |
"Modified (comment): / 15-01-2018 / 08:29:39 / mawalch" |
|
8321 | 276 |
! |
277 |
||
278 |
nextPutAll:aCollection startingAt:start to:stop |
|
24029 | 279 |
"append the elements from first index to last index |
280 |
of the argument, aCollection onto the receiver (i.e. both outstreams)" |
|
281 |
||
18598 | 282 |
|needCharacterSize| |
283 |
||
22675 | 284 |
aCollection isCharacters ifFalse:[ |
285 |
aCollection isByteArray ifTrue:[ |
|
23541 | 286 |
super nextPutAll:aCollection startingAt:start to:stop |
22675 | 287 |
] |
288 |
]. |
|
289 |
||
18598 | 290 |
needCharacterSize := aCollection characterSize. |
291 |
needCharacterSize > currentCharacterSize ifTrue:[ |
|
292 |
self characterSizeChangedTo:needCharacterSize size:stop-start+1. |
|
8321 | 293 |
]. |
23541 | 294 |
super nextPutAll:aCollection startingAt:start to:stop |
295 |
||
296 |
"Modified: / 22-11-2018 / 12:53:10 / Stefan Vogel" |
|
24029 | 297 |
"Modified (comment): / 01-04-2019 / 17:13:06 / Claus Gittinger" |
11319 | 298 |
! |
299 |
||
300 |
nextPutAllUnicode:aCollection |
|
301 |
^ self nextPutAll:aCollection |
|
302 |
! |
|
303 |
||
304 |
nextPutUnicode:aCharacter |
|
305 |
^ self nextPut:aCharacter |
|
8298 | 306 |
! ! |
307 |
||
8321 | 308 |
!CharacterWriteStream class methodsFor:'documentation'! |
309 |
||
310 |
version |
|
18590 | 311 |
^ '$Header$' |
12133 | 312 |
! |
313 |
||
314 |
version_CVS |
|
18590 | 315 |
^ '$Header$' |
8321 | 316 |
! ! |
14607 | 317 |