author | Claus Gittinger <cg@exept.de> |
Thu, 23 Nov 1995 02:16:37 +0100 | |
changeset 605 | 8b17f96bf05a |
parent 530 | 07d0bce293c9 |
child 611 | 80bb0f1a7bab |
permissions | -rw-r--r-- |
1 | 1 |
" |
5 | 2 |
COPYRIGHT (c) 1989 by Claus Gittinger |
252 | 3 |
All Rights Reserved |
1 | 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 |
" |
|
12 |
||
13 |
PositionableStream subclass:#WriteStream |
|
369 | 14 |
instanceVariableNames:'' |
1 | 15 |
classVariableNames:'' |
16 |
poolDictionaries:'' |
|
17 |
category:'Streams' |
|
18 |
! |
|
19 |
||
68 | 20 |
!WriteStream class methodsFor:'documentation'! |
1 | 21 |
|
88 | 22 |
copyright |
23 |
" |
|
24 |
COPYRIGHT (c) 1989 by Claus Gittinger |
|
252 | 25 |
All Rights Reserved |
88 | 26 |
|
27 |
This software is furnished under a license and may be used |
|
28 |
only in accordance with the terms of that license and with the |
|
29 |
inclusion of the above copyright notice. This software may not |
|
30 |
be provided or otherwise made available to, or used by, any |
|
31 |
other person. No title to or ownership of the software is |
|
32 |
hereby transferred. |
|
33 |
" |
|
34 |
! |
|
35 |
||
36 |
version |
|
530
07d0bce293c9
uff - version methods changed to return stings
Claus Gittinger <cg@exept.de>
parents:
384
diff
changeset
|
37 |
^ '$Header: /cvs/stx/stx/libbasic/Attic/WriteStr.st,v 1.21 1995-11-11 15:28:41 cg Exp $' |
88 | 38 |
! |
39 |
||
68 | 40 |
documentation |
41 |
" |
|
88 | 42 |
Streams for writing into - this implementation currently DOES change the |
261 | 43 |
identity if the streamed-upon collection IF it cannot grow easily. |
44 |
Collections which cannot grow easily are for example: Array, ByteArray and String. |
|
88 | 45 |
Thus it is slightly incompatible to ST-80 since 'aStream contents' does |
46 |
not always return the original collection. This may change. |
|
68 | 47 |
" |
48 |
! ! |
|
1 | 49 |
|
369 | 50 |
!WriteStream methodsFor:'queries'! |
51 |
||
52 |
isWritable |
|
53 |
^ true |
|
54 |
! ! |
|
55 |
||
56 |
!WriteStream methodsFor:'private accessing'! |
|
1 | 57 |
|
58 |
on:aCollection from:start to:last |
|
59 |
"create and return a new stream for writing onto aCollection, where |
|
60 |
writing is limited to the elements in the range start to last." |
|
61 |
||
369 | 62 |
super on:aCollection from:start to:last. |
63 |
writeLimit := last. |
|
345 | 64 |
! ! |
65 |
||
1 | 66 |
!WriteStream methodsFor:'accessing'! |
67 |
||
68 |
contents |
|
345 | 69 |
"return the current contents (a collection) of the stream. |
70 |
Currently, this returns the actual collection if possible |
|
71 |
(and reset is implemented to create a new one) in contrast to |
|
72 |
ST80, where contents returns a copy and reset only sets the writePointer. |
|
73 |
The ST/X behavior creates less temporary garbage in the normal case |
|
74 |
(whre things are written for the contents only) but may be incompatible |
|
75 |
with some applications. Time will show, if this is to be changed." |
|
1 | 76 |
|
260 | 77 |
|lastIndex| |
78 |
||
79 |
lastIndex := position - 1. |
|
80 |
collection size == lastIndex ifFalse:[ |
|
252 | 81 |
collection isFixedSize ifTrue:[ |
260 | 82 |
" |
83 |
grow is expensive - return a copy. |
|
84 |
(is this what users of writeStream expect ? |
|
85 |
" |
|
86 |
collection := collection copyFrom:1 to:lastIndex |
|
252 | 87 |
] ifFalse:[ |
260 | 88 |
collection grow:lastIndex |
252 | 89 |
] |
1 | 90 |
]. |
91 |
^ collection |
|
92 |
! |
|
93 |
||
329 | 94 |
reset |
345 | 95 |
"reset the stream; write anew. |
96 |
See the comment in WriteStream>>contnts" |
|
329 | 97 |
|
98 |
collection := collection species new:(collection size). |
|
99 |
super reset |
|
1 | 100 |
! ! |
101 |
||
63 | 102 |
!WriteStream methodsFor:'reading'! |
1 | 103 |
|
104 |
next |
|
10 | 105 |
"catch read access to write stream - report an error" |
1 | 106 |
|
10 | 107 |
self shouldNotImplement |
1 | 108 |
! |
109 |
||
110 |
peek |
|
10 | 111 |
"catch read access to write stream - report an error" |
1 | 112 |
|
10 | 113 |
self shouldNotImplement |
63 | 114 |
! ! |
115 |
||
369 | 116 |
!WriteStream methodsFor:'positioning'! |
117 |
||
118 |
position:index |
|
119 |
"redefined to allow positioning past the readLimit" |
|
120 |
||
121 |
((index > (collection size + 1)) or:[index < 0]) ifTrue: [^ self positionError]. |
|
122 |
position := index |
|
123 |
! ! |
|
124 |
||
63 | 125 |
!WriteStream methodsFor:'writing'! |
1 | 126 |
|
127 |
nextPut:anObject |
|
128 |
"append the argument, anObject to the stream" |
|
129 |
||
63 | 130 |
%{ /* NOCONTEXT */ |
131 |
||
132 |
REGISTER int pos; |
|
133 |
unsigned ch; |
|
134 |
OBJ coll; |
|
252 | 135 |
OBJ p, l; |
63 | 136 |
|
137 |
coll = _INST(collection); |
|
252 | 138 |
p = _INST(position); |
63 | 139 |
|
293 | 140 |
if (__isNonNilObject(coll) && __isSmallInteger(p)) { |
68 | 141 |
|
252 | 142 |
pos = _intVal(p); |
293 | 143 |
l = _INST(writeLimit); |
63 | 144 |
|
293 | 145 |
if ((l == nil) |
329 | 146 |
|| (__isSmallInteger(l) && (pos <= _intVal(l)))) { |
252 | 147 |
OBJ cls; |
148 |
||
329 | 149 |
cls = __qClass(coll); |
293 | 150 |
|
252 | 151 |
if (cls == String) { |
152 |
if (__isCharacter(anObject) |
|
153 |
&& (pos <= _stringSize(coll))) { |
|
293 | 154 |
ch = _intVal(_characterVal(anObject)); |
155 |
if ((ch >= 0) && (ch <= 255)) { |
|
329 | 156 |
_StringInstPtr(coll)->s_element[pos-1] = ch; |
157 |
_INST(position) = _MKSMALLINT(pos + 1); |
|
158 |
if (__isSmallInteger(_INST(readLimit)) |
|
159 |
&& (pos >= _intVal(_INST(readLimit)))) { |
|
359 | 160 |
_INST(readLimit) = _MKSMALLINT(pos); |
329 | 161 |
} |
162 |
RETURN ( anObject ); |
|
252 | 163 |
} |
164 |
} |
|
293 | 165 |
} else { |
329 | 166 |
if (cls == ByteArray) { |
293 | 167 |
if (__isSmallInteger(anObject) |
168 |
&& ((ch = _intVal(anObject)) >= 0) |
|
169 |
&& (ch <= 255) |
|
170 |
&& (pos <= _byteArraySize(coll))) { |
|
329 | 171 |
_ByteArrayInstPtr(coll)->ba_element[pos-1] = ch; |
172 |
_INST(position) = _MKSMALLINT(pos + 1); |
|
173 |
if (__isSmallInteger(_INST(readLimit)) |
|
174 |
&& (pos >= _intVal(_INST(readLimit)))) { |
|
359 | 175 |
_INST(readLimit) = _MKSMALLINT(pos); |
329 | 176 |
} |
177 |
RETURN ( anObject ); |
|
252 | 178 |
} |
329 | 179 |
} else { |
180 |
if (cls == Array) { |
|
181 |
if (pos <= _arraySize(coll)) { |
|
182 |
_ArrayInstPtr(coll)->a_element[pos-1] = anObject; |
|
183 |
__STORE(coll, anObject); |
|
184 |
_INST(position) = _MKSMALLINT(pos + 1); |
|
185 |
if (__isSmallInteger(_INST(readLimit)) |
|
186 |
&& (pos >= _intVal(_INST(readLimit)))) { |
|
359 | 187 |
_INST(readLimit) = _MKSMALLINT(pos); |
329 | 188 |
} |
189 |
RETURN ( anObject ); |
|
190 |
} |
|
293 | 191 |
} |
252 | 192 |
} |
193 |
} |
|
194 |
} |
|
63 | 195 |
} |
260 | 196 |
%}. |
293 | 197 |
(writeLimit isNil |
198 |
or:[position <= writeLimit]) ifTrue:[ |
|
199 |
(position > collection size) ifTrue:[self growCollection]. |
|
200 |
collection at:position put:anObject. |
|
201 |
(position > readLimit) ifTrue:[readLimit := position]. |
|
202 |
position := position + 1. |
|
203 |
]. |
|
1 | 204 |
^anObject |
205 |
! |
|
206 |
||
63 | 207 |
next:count put:anObject |
208 |
"append anObject count times to the receiver. |
|
209 |
Redefined to avoid count grows of the underlying collection - |
|
210 |
instead a single grow on the final size is performed." |
|
211 |
||
68 | 212 |
|final| |
63 | 213 |
|
293 | 214 |
(collection isNil or:[writeLimit notNil]) ifTrue:[ |
260 | 215 |
^ super next:count put:anObject |
77 | 216 |
]. |
217 |
||
63 | 218 |
final := position + count - 1. |
219 |
(final > collection size) ifTrue:[ |
|
252 | 220 |
self growCollection:final |
63 | 221 |
]. |
222 |
||
260 | 223 |
position to:final do:[:index | |
224 |
collection at:index put:anObject. |
|
225 |
]. |
|
63 | 226 |
position := position + count. |
227 |
(position > readLimit) ifTrue:[readLimit := position - 1]. |
|
228 |
^ anObject |
|
229 |
! |
|
230 |
||
1 | 231 |
nextPutAll:aCollection |
63 | 232 |
"append all elements of the argument, aCollection to the stream. |
233 |
Redefined to avoid count grows of the underlying collection - |
|
234 |
instead a single grow on the final size is performed." |
|
1 | 235 |
|
236 |
|nMore final| |
|
237 |
||
77 | 238 |
collection isNil ifTrue:[ |
260 | 239 |
^ super nextPutAll:aCollection |
77 | 240 |
]. |
241 |
||
1 | 242 |
nMore := aCollection size. |
243 |
final := position + nMore - 1. |
|
293 | 244 |
(writeLimit notNil |
245 |
and:[final > writeLimit]) ifTrue:[ |
|
246 |
final := writeLimit. |
|
247 |
nMore := final - position + 1 |
|
248 |
]. |
|
1 | 249 |
(final > collection size) ifTrue:[ |
252 | 250 |
self growCollection:final |
1 | 251 |
]. |
252 |
collection replaceFrom:position |
|
252 | 253 |
to:final |
254 |
with:aCollection |
|
255 |
startingAt:1. |
|
1 | 256 |
|
257 |
position := position + nMore. |
|
258 |
(position > readLimit) ifTrue:[readLimit := position - 1]. |
|
259 |
^ aCollection |
|
260 |
! ! |
|
261 |
||
10 | 262 |
!WriteStream methodsFor:'ignored'! |
263 |
||
264 |
bold |
|
63 | 265 |
"change font to bold - ignored here. |
266 |
- this allows WriteStreams to be compatible to PrinterStreams" |
|
10 | 267 |
! |
268 |
||
269 |
italic |
|
63 | 270 |
"change font to italic - ignored here. |
271 |
- this allows WriteStreams to be compatible to PrinterStreams" |
|
10 | 272 |
! |
273 |
||
77 | 274 |
boldItalic |
275 |
"change font to italic - ignored here. |
|
276 |
- this allows WriteStreams to be compatible to PrinterStreams" |
|
277 |
! |
|
278 |
||
10 | 279 |
normal |
63 | 280 |
"change font to normal - ignored here. |
281 |
- this allows WriteStreams to be compatible to PrinterStreams" |
|
10 | 282 |
! ! |
283 |
||
1 | 284 |
!WriteStream methodsFor:'private'! |
285 |
||
286 |
growCollection |
|
252 | 287 |
self growCollection:10 |
288 |
! |
|
289 |
||
290 |
growCollection:minNewSize |
|
291 |
"grow the streamed collection to at least minNewSize" |
|
292 |
||
1 | 293 |
|oldSize newSize newColl| |
294 |
||
295 |
oldSize := collection size. |
|
296 |
(oldSize == 0) ifTrue:[ |
|
252 | 297 |
newSize := minNewSize |
1 | 298 |
] ifFalse:[ |
252 | 299 |
newSize := oldSize * 2. |
300 |
[newSize < minNewSize] whileTrue:[ |
|
301 |
newSize := newSize * 2 |
|
302 |
] |
|
1 | 303 |
]. |
304 |
collection isFixedSize ifTrue:[ |
|
252 | 305 |
newColl := collection species new:newSize. |
306 |
newColl replaceFrom:1 to:oldSize with:collection startingAt:1. |
|
307 |
collection := newColl |
|
1 | 308 |
] ifFalse:[ |
252 | 309 |
collection grow:newSize |
1 | 310 |
]. |
311 |
! ! |