WriteStream.st
branchjv
changeset 18301 d0a478542bbf
parent 18192 32a7c53ef4d0
parent 18294 5c7b472ab445
child 19478 1f5aa87f6170
equal deleted inserted replaced
18292:8d4fe353a2d2 18301:d0a478542bbf
    45     from pieces - create a writeStream, add the pieces (with #nextPut: or
    45     from pieces - create a writeStream, add the pieces (with #nextPut: or
    46     #nextPutAll:) and finally fetch the concatenated string via #contents.
    46     #nextPutAll:) and finally fetch the concatenated string via #contents.
    47     This is much better than constructing the big string by concatenating via
    47     This is much better than constructing the big string by concatenating via
    48     the comma (,) operator, since less intermediate garbage objects are created.
    48     the comma (,) operator, since less intermediate garbage objects are created.
    49 
    49 
    50     This implementation currently DOES change the 
    50     This implementation currently DOES change the
    51     identity if the streamed-upon collection IF it cannot grow easily. 
    51     identity if the streamed-upon collection IF it cannot grow easily.
    52     Collections which cannot grow easily are for example: Array, ByteArray and String.
    52     Collections which cannot grow easily are for example: Array, ByteArray and String.
    53     Thus it is slightly incompatible to ST-80 since 'aStream contents' does 
    53     Thus it is slightly incompatible to ST-80 since 'aStream contents' does
    54     not always return the original collection. This may change.
    54     not always return the original collection. This may change.
    55 
    55 
    56     [caveat:]
    56     [caveat:]
    57         Basing capabilities like readability/writability/positionability/peekability on inheritance makes
    57 	Basing capabilities like readability/writability/positionability/peekability on inheritance makes
    58         the class hierarchy ugly and leads to strange and hard to teach redefinitions (aka. NonPositionableStream
    58 	the class hierarchy ugly and leads to strange and hard to teach redefinitions (aka. NonPositionableStream
    59         below PositionableStream or ExternalReadStream under WriteStream)
    59 	below PositionableStream or ExternalReadStream under WriteStream)
    60 
    60 
    61     [author:]
    61     [author:]
    62         Claus Gittinger
    62 	Claus Gittinger
    63 
    63 
    64     [see also:]
    64     [see also:]
    65         CharacterWriteStream (if streaming for a unicode string)
    65 	CharacterWriteStream (if streaming for a unicode string)
    66 "
    66 "
    67 !
    67 !
    68 
    68 
    69 examples
    69 examples
    70 "
    70 "
   123 
   123 
   124     |lastIndex|
   124     |lastIndex|
   125 
   125 
   126     lastIndex := position.
   126     lastIndex := position.
   127     collection size == lastIndex ifFalse:[
   127     collection size == lastIndex ifFalse:[
   128         collection isFixedSize ifTrue:[
   128 	collection isFixedSize ifTrue:[
   129             "
   129 	    "
   130              grow is expensive - return a copy.
   130 	     grow is expensive - return a copy.
   131              (is this what users of writeStream expect ?)
   131 	     (is this what users of writeStream expect ?)
   132             "
   132 	    "
   133             collection := collection copyFrom:1 to:lastIndex
   133 	    collection := collection copyFrom:1 to:lastIndex
   134         ] ifFalse:[
   134 	] ifFalse:[
   135             collection grow:lastIndex
   135 	    collection grow:lastIndex
   136         ]
   136 	]
   137     ].
   137     ].
   138     ^ collection
   138     ^ collection
   139 
   139 
   140     "Modified: / 19.2.1997 / 08:57:28 / stefan"
   140     "Modified: / 19.2.1997 / 08:57:28 / stefan"
   141     "Modified: / 30.10.1997 / 16:21:23 / cg"
   141     "Modified: / 30.10.1997 / 16:21:23 / cg"
   149     "
   149     "
   150      |s|
   150      |s|
   151 
   151 
   152      s := '' writeStream.
   152      s := '' writeStream.
   153      s nextPut:$a.
   153      s nextPut:$a.
   154      s last.       
   154      s last.
   155      s nextPut:$b.
   155      s nextPut:$b.
   156      s last.        
   156      s last.
   157      s nextPut:$c.
   157      s nextPut:$c.
   158      s last.        
   158      s last.
   159     "
   159     "
   160 !
   160 !
   161 
   161 
   162 last:n
   162 last:n
   163     "return the last n elements as species of the underlying collection;
   163     "return the last n elements as species of the underlying collection;
   168     "
   168     "
   169      |s|
   169      |s|
   170 
   170 
   171      s := '' writeStream.
   171      s := '' writeStream.
   172      s nextPut:$a.
   172      s nextPut:$a.
   173      s last:1.       
   173      s last:1.
   174      s nextPut:$b.
   174      s nextPut:$b.
   175      s last:1.        
   175      s last:1.
   176      s last:2.        
   176      s last:2.
   177      s nextPut:$c.
   177      s nextPut:$c.
   178      s last:1.        
   178      s last:1.
   179      s last:2.        
   179      s last:2.
   180      s last:3.        
   180      s last:3.
   181     "
   181     "
   182 !
   182 !
   183 
   183 
   184 reset
   184 reset
   185     "reset the stream; write anew.
   185     "reset the stream; write anew.
   284     ^ self position == 0
   284     ^ self position == 0
   285 
   285 
   286     "Created: 14.10.1997 / 20:44:37 / cg"
   286     "Created: 14.10.1997 / 20:44:37 / cg"
   287 !
   287 !
   288 
   288 
   289 isReadable 
   289 isReadable
   290     "return true if the receiver supports reading - thats not true"
   290     "return true if the receiver supports reading - thats not true"
   291 
   291 
   292     ^ false
   292     ^ false
   293 
   293 
   294     "Created: / 8.11.1997 / 14:06:07 / cg"
   294     "Created: / 8.11.1997 / 14:06:07 / cg"
   313     |final|
   313     |final|
   314 
   314 
   315     count == 0 ifTrue:[^ self].
   315     count == 0 ifTrue:[^ self].
   316 
   316 
   317     (collection isNil or:[writeLimit notNil]) ifTrue:[
   317     (collection isNil or:[writeLimit notNil]) ifTrue:[
   318         super next:count put:anObject.
   318 	super next:count put:anObject.
   319         ^ self.
   319 	^ self.
   320     ].
   320     ].
   321 
   321 
   322     final := position + count.
   322     final := position + count.
   323     (final > collection size) ifTrue:[
   323     (final > collection size) ifTrue:[
   324         self growCollection:final
   324 	self growCollection:final
   325     ].
   325     ].
   326 
   326 
   327     collection from:position + 1 to:final put:anObject.
   327     collection from:position + 1 to:final put:anObject.
   328     position := position + count.
   328     position := position + count.
   329     (position >= readLimit) ifTrue:[readLimit := position].
   329     (position >= readLimit) ifTrue:[readLimit := position].
   343      |s|
   343      |s|
   344 
   344 
   345      s := '' writeStream.
   345      s := '' writeStream.
   346      s nextPutAll:'hello '.
   346      s nextPutAll:'hello '.
   347      s next:5 putAll:'1234world012345' startingAt:5.
   347      s next:5 putAll:'1234world012345' startingAt:5.
   348      s contents   
   348      s contents
   349     "
   349     "
   350 
   350 
   351     "Modified: 12.7.1996 / 10:31:36 / cg"
   351     "Modified: 12.7.1996 / 10:31:36 / cg"
   352 !
   352 !
   353 
   353 
   366 
   366 
   367     coll = __INST(collection);
   367     coll = __INST(collection);
   368     p = __INST(position);
   368     p = __INST(position);
   369 
   369 
   370     if (__isNonNilObject(coll) && __isSmallInteger(p)) {
   370     if (__isNonNilObject(coll) && __isSmallInteger(p)) {
   371         pos = __intVal(p);
   371 	pos = __intVal(p);
   372         /* make 1-based */
   372 	/* make 1-based */
   373         pos = pos + 1;
   373 	pos = pos + 1;
   374         wL = __INST(writeLimit);
   374 	wL = __INST(writeLimit);
   375 
   375 
   376         if ((wL == nil)
   376 	if ((wL == nil)
   377          || (__isSmallInteger(wL) && (pos <= __intVal(wL)))) {
   377 	 || (__isSmallInteger(wL) && (pos <= __intVal(wL)))) {
   378             OBJ cls;
   378 	    OBJ cls;
   379 
   379 
   380             cls = __qClass(coll);
   380 	    cls = __qClass(coll);
   381 
   381 
   382             rL = __INST(readLimit);
   382 	    rL = __INST(readLimit);
   383             if (__isSmallInteger(rL)) {
   383 	    if (__isSmallInteger(rL)) {
   384                 __readLimit = __intVal(rL);
   384 		__readLimit = __intVal(rL);
   385             }
   385 	    }
   386 
   386 
   387             if (cls == @global(String)) {
   387 	    if (cls == @global(String)) {
   388                 if (__isCharacter(anObject) 
   388 		if (__isCharacter(anObject)
   389                  && ((ch = __intVal(__characterVal(anObject))) <= 255) /* ch is unsigned */
   389 		 && ((ch = __intVal(__characterVal(anObject))) <= 255) /* ch is unsigned */
   390                  && (pos <= __stringSize(coll))) {
   390 		 && (pos <= __stringSize(coll))) {
   391                     __StringInstPtr(coll)->s_element[pos-1] = ch;
   391 		    __StringInstPtr(coll)->s_element[pos-1] = ch;
   392 advancePositionAndReturn: ;            
   392 advancePositionAndReturn: ;
   393                     if ((__readLimit >= 0) && (pos >= __readLimit)) {
   393 		    if ((__readLimit >= 0) && (pos >= __readLimit)) {
   394                         __INST(readLimit) = __mkSmallInteger(pos);
   394 			__INST(readLimit) = __mkSmallInteger(pos);
   395                     }
   395 		    }
   396                     __INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1);
   396 		    __INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1);
   397                     RETURN ( anObject );
   397 		    RETURN ( anObject );
   398                 }
   398 		}
   399             } else if (cls == @global(ByteArray)) {
   399 	    } else if (cls == @global(ByteArray)) {
   400                 if (__isSmallInteger(anObject) 
   400 		if (__isSmallInteger(anObject)
   401                  && ((ch = __intVal(anObject)) <= 0xFF) /* ch is unsigned */
   401 		 && ((ch = __intVal(anObject)) <= 0xFF) /* ch is unsigned */
   402                  && (pos <= __byteArraySize(coll))) {
   402 		 && (pos <= __byteArraySize(coll))) {
   403                     __ByteArrayInstPtr(coll)->ba_element[pos-1] = ch;
   403 		    __ByteArrayInstPtr(coll)->ba_element[pos-1] = ch;
   404                     goto advancePositionAndReturn;
   404 		    goto advancePositionAndReturn;
   405                 }
   405 		}
   406             } else if (cls == @global(Array)) {
   406 	    } else if (cls == @global(Array)) {
   407                 if (pos <= __arraySize(coll)) {
   407 		if (pos <= __arraySize(coll)) {
   408                      __ArrayInstPtr(coll)->a_element[pos-1] = anObject;
   408 		     __ArrayInstPtr(coll)->a_element[pos-1] = anObject;
   409                     __STORE(coll, anObject);
   409 		    __STORE(coll, anObject);
   410                     goto advancePositionAndReturn;
   410 		    goto advancePositionAndReturn;
   411                 }
   411 		}
   412             } else if (cls == @global(Unicode16String)) {
   412 	    } else if (cls == @global(Unicode16String)) {
   413                 if (__isCharacter(anObject) 
   413 		if (__isCharacter(anObject)
   414                  && ((ch = __intVal(__characterVal(anObject))) <= 0xFFFF) /* ch is unsigned */
   414 		 && ((ch = __intVal(__characterVal(anObject))) <= 0xFFFF) /* ch is unsigned */
   415                  && (pos <= __unicode16StringSize(coll))) {
   415 		 && (pos <= __unicode16StringSize(coll))) {
   416                      __Unicode16StringInstPtr(coll)->s_element[pos-1] = ch;
   416 		     __Unicode16StringInstPtr(coll)->s_element[pos-1] = ch;
   417                     goto advancePositionAndReturn;
   417 		    goto advancePositionAndReturn;
   418                 }
   418 		}
   419             } else if (cls == @global(Unicode32String)) {
   419 	    } else if (cls == @global(Unicode32String)) {
   420                 if (__isCharacter(anObject) 
   420 		if (__isCharacter(anObject)
   421                  && (pos <= __unicode32StringSize(coll))) {
   421 		 && (pos <= __unicode32StringSize(coll))) {
   422                      __Unicode32StringInstPtr(coll)->s_element[pos-1] = __intVal(__characterVal(anObject));
   422 		     __Unicode32StringInstPtr(coll)->s_element[pos-1] = __intVal(__characterVal(anObject));
   423                     goto advancePositionAndReturn;
   423 		    goto advancePositionAndReturn;
   424                 }
   424 		}
   425             }
   425 	    }
   426         }
   426 	}
   427     }
   427     }
   428 #endif
   428 #endif
   429 %}.
   429 %}.
   430     (writeLimit isNil
   430     (writeLimit isNil
   431     or:[(position + 1) <= writeLimit]) ifTrue:[
   431     or:[(position + 1) <= writeLimit]) ifTrue:[
   432         (position >= collection size) ifTrue:[self growCollection].
   432 	(position >= collection size) ifTrue:[self growCollection].
   433         collection at:(position + 1) put:anObject.
   433 	collection at:(position + 1) put:anObject.
   434         (position >= readLimit) ifTrue:[readLimit := (position + 1)].
   434 	(position >= readLimit) ifTrue:[readLimit := (position + 1)].
   435         position := position + 1.
   435 	position := position + 1.
   436     ] ifFalse:[
   436     ] ifFalse:[
   437         WriteError raiseErrorString:'write beyond writeLimit'
   437 	WriteError raiseErrorString:'write beyond writeLimit'
   438     ].
   438     ].
   439     ^anObject
   439     ^anObject
   440 !
   440 !
   441 
   441 
   442 nextPutAll:aCollection
   442 nextPutAll:aCollection
   445      instead a single grow on the final size is performed."
   445      instead a single grow on the final size is performed."
   446 
   446 
   447     |nMore "{ Class: SmallInteger }"
   447     |nMore "{ Class: SmallInteger }"
   448      final "{ Class: SmallInteger }" |
   448      final "{ Class: SmallInteger }" |
   449 
   449 
   450     (collection isNil or:[aCollection isSequenceable not]) ifTrue:[
   450     (collection notNil and:[aCollection isSequenceable]) ifFalse:[
   451         "/ fallback
   451 	"/ fallback
   452         super nextPutAll:aCollection.
   452 	super nextPutAll:aCollection.
   453         ^ self.
   453 	^ self.
   454     ].
   454     ].
   455 
   455 
   456     nMore := aCollection size.
   456     nMore := aCollection size.
   457     nMore == 0 ifTrue:[
   457     nMore == 0 ifTrue:[
   458         "/ for the programmer..
   458 	"/ for the programmer..
   459         aCollection isCollection ifFalse:[
   459 	aCollection isCollection ifFalse:[
   460             self error:'invalid argument (not a collection)' mayProceed:true
   460 	    self error:'invalid argument (not a collection)' mayProceed:true
   461         ].
   461 	].
   462     ].
   462     ].
   463 
   463 
   464     final := position + nMore.
   464     final := position + nMore.
   465     (writeLimit notNil
   465     (writeLimit notNil
   466     and:[final > writeLimit]) ifTrue:[
   466     and:[final > writeLimit]) ifTrue:[
   467         final := writeLimit.
   467 	final := writeLimit.
   468         nMore := final - position
   468 	nMore := final - position
   469     ].
   469     ].
   470     (final > collection size) ifTrue:[
   470     (final > collection size) ifTrue:[
   471         self growCollection:final
   471 	self growCollection:final
   472     ].
   472     ].
   473     collection 
   473     collection
   474         replaceFrom:(position + 1)
   474 	replaceFrom:(position + 1)
   475         to:final
   475 	to:final
   476         with:aCollection 
   476 	with:aCollection
   477         startingAt:1.
   477 	startingAt:1.
   478 
   478 
   479     (position >= readLimit) ifTrue:[readLimit := position].
   479     (position >= readLimit) ifTrue:[readLimit := position].
   480     position := position + nMore.
   480     position := position + nMore.
   481     "/ ^ aCollection -- self
   481     "/ ^ aCollection -- self
   482 
   482 
   489      instead a single grow on the final size is performed."
   489      instead a single grow on the final size is performed."
   490 
   490 
   491     |nMore final|
   491     |nMore final|
   492 
   492 
   493     collection isNil ifTrue:[
   493     collection isNil ifTrue:[
   494         ^ super nextPutAll:aCollection startingAt:pos1 to:pos2
   494 	^ super nextPutAll:aCollection startingAt:pos1 to:pos2
   495     ].
   495     ].
   496 
   496 
   497     nMore := pos2 - pos1 + 1.
   497     nMore := pos2 - pos1 + 1.
   498     final := position + nMore.
   498     final := position + nMore.
   499     (writeLimit notNil
   499     (writeLimit notNil
   500     and:[final > writeLimit]) ifTrue:[
   500     and:[final > writeLimit]) ifTrue:[
   501         final := writeLimit.
   501 	final := writeLimit.
   502         nMore := final - position
   502 	nMore := final - position
   503     ].
   503     ].
   504     (final > collection size) ifTrue:[
   504     (final > collection size) ifTrue:[
   505         self growCollection:final
   505 	self growCollection:final
   506     ].
   506     ].
   507 
   507 
   508     collection replaceFrom:position + 1
   508     collection replaceFrom:position + 1
   509                         to:final
   509 			to:final
   510                       with:aCollection 
   510 		      with:aCollection
   511                 startingAt:pos1.
   511 		startingAt:pos1.
   512 
   512 
   513     position := position + nMore.
   513     position := position + nMore.
   514     (position >= readLimit) ifTrue:[readLimit := position].
   514     (position >= readLimit) ifTrue:[readLimit := position].
   515     "/ ^ aCollection -- return self
   515     "/ ^ aCollection -- return self
   516 
   516 
   528 
   528 
   529 nextPutAllUnicode:aString
   529 nextPutAllUnicode:aString
   530     "normal streams can not handle multi-byte characters, so convert them to utf8"
   530     "normal streams can not handle multi-byte characters, so convert them to utf8"
   531 
   531 
   532     "this code is not perfect if you use both #nextPutAll: and #nextPutAllUnicode:
   532     "this code is not perfect if you use both #nextPutAll: and #nextPutAllUnicode:
   533      with the same stream, since 8-bit characters (with the highest bits set) 
   533      with the same stream, since 8-bit characters (with the highest bits set)
   534      are not stored as UTF, so we get some inconsistent string"
   534      are not stored as UTF, so we get some inconsistent string"
   535 
   535 
   536     collection isString ifTrue:[
   536     collection isString ifTrue:[
   537         collection bitsPerCharacter == 16 ifTrue:[
   537 	collection bitsPerCharacter == 16 ifTrue:[
   538             self nextPutAllUtf16:aString.
   538 	    self nextPutAllUtf16:aString.
   539         ] ifFalse:[
   539 	] ifFalse:[
   540             self nextPutAllUtf8:aString.
   540 	    self nextPutAllUtf8:aString.
   541         ].
   541 	].
   542     ] ifFalse:[
   542     ] ifFalse:[
   543         self nextPutAll:aString
   543 	self nextPutAll:aString
   544     ].
   544     ].
   545 
   545 
   546     "Modified: / 28-09-2011 / 16:15:52 / cg"
   546     "Modified: / 28-09-2011 / 16:15:52 / cg"
   547 !
   547 !
   548 
   548 
   560 
   560 
   561     coll = __INST(collection);
   561     coll = __INST(collection);
   562     p = __INST(position);
   562     p = __INST(position);
   563 
   563 
   564     if (__isNonNilObject(coll) && __isSmallInteger(p) && __isSmallInteger(anObject)) {
   564     if (__isNonNilObject(coll) && __isSmallInteger(p) && __isSmallInteger(anObject)) {
   565         unsigned ch;
   565 	unsigned ch;
   566 
   566 
   567         ch = __intVal(anObject);
   567 	ch = __intVal(anObject);
   568 
   568 
   569         pos = __intVal(p);
   569 	pos = __intVal(p);
   570         /* make 1-based */
   570 	/* make 1-based */
   571         pos = pos + 1 - __intVal( @global(PositionableStream:ZeroPosition));
   571 	pos = pos + 1 - __intVal( @global(PositionableStream:ZeroPosition));
   572         wL = __INST(writeLimit);
   572 	wL = __INST(writeLimit);
   573 
   573 
   574         if ((wL == nil)
   574 	if ((wL == nil)
   575          || (__isSmallInteger(wL) && (pos <= __intVal(wL)))) {
   575 	 || (__isSmallInteger(wL) && (pos <= __intVal(wL)))) {
   576             OBJ cls;
   576 	    OBJ cls;
   577 
   577 
   578             cls = __qClass(coll);
   578 	    cls = __qClass(coll);
   579 
   579 
   580             rL = __INST(readLimit);
   580 	    rL = __INST(readLimit);
   581             if (__isSmallInteger(rL)) {
   581 	    if (__isSmallInteger(rL)) {
   582                 __readLimit = __intVal(rL);
   582 		__readLimit = __intVal(rL);
   583             }
   583 	    }
   584 
   584 
   585             if (cls == @global(String)) {
   585 	    if (cls == @global(String)) {
   586                 if ((pos <= __stringSize(coll))
   586 		if ((pos <= __stringSize(coll))
   587                  && (ch <= 0xFF)) { /* ch is unsigned */
   587 		 && (ch <= 0xFF)) { /* ch is unsigned */
   588                     __StringInstPtr(coll)->s_element[pos-1] = ch;
   588 		    __StringInstPtr(coll)->s_element[pos-1] = ch;
   589     advancePositionAndReturn: ;            
   589     advancePositionAndReturn: ;
   590                     if ((__readLimit >= 0) && (pos >= __readLimit)) {
   590 		    if ((__readLimit >= 0) && (pos >= __readLimit)) {
   591                         __INST(readLimit) = __mkSmallInteger(pos);
   591 			__INST(readLimit) = __mkSmallInteger(pos);
   592                     }
   592 		    }
   593                     __INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1);
   593 		    __INST(position) = __mkSmallInteger(__intVal(__INST(position)) + 1);
   594                     RETURN ( anObject );
   594 		    RETURN ( anObject );
   595                 }
   595 		}
   596             } else if (cls == @global(ByteArray)) {
   596 	    } else if (cls == @global(ByteArray)) {
   597                 if ((pos <= __byteArraySize(coll))
   597 		if ((pos <= __byteArraySize(coll))
   598                  && (ch <= 0xFF)) { /* ch is unsigned */
   598 		 && (ch <= 0xFF)) { /* ch is unsigned */
   599                     __ByteArrayInstPtr(coll)->ba_element[pos-1] = ch;
   599 		    __ByteArrayInstPtr(coll)->ba_element[pos-1] = ch;
   600                     goto advancePositionAndReturn;
   600 		    goto advancePositionAndReturn;
   601                 }
   601 		}
   602             }
   602 	    }
   603         }
   603 	}
   604     }
   604     }
   605 #endif
   605 #endif
   606 %}.
   606 %}.
   607     ^ super nextPutByte:anObject
   607     ^ super nextPutByte:anObject
   608 !
   608 !
   609 
   609 
   610 nextPutBytes:count from:anObject startingAt:start
   610 nextPutBytes:count from:anObject startingAt:start
   611     "write count bytes from an object starting at index start.
   611     "write count bytes from an object starting at index start.
   612      Return the number of bytes written.
   612      Return the number of bytes written.
   613      The object must have non-pointer indexed instvars 
   613      The object must have non-pointer indexed instvars
   614      (i.e. be a ByteArray, String, Float- or DoubleArray).     
   614      (i.e. be a ByteArray, String, Float- or DoubleArray).
   615      Use with care - non object oriented i/o.
   615      Use with care - non object oriented i/o.
   616      This is provided for compatibility with externalStream;
   616      This is provided for compatibility with externalStream;
   617      to support binary storage"
   617      to support binary storage"
   618 
   618 
   619     anObject isByteCollection ifTrue:[
   619     anObject isByteCollection ifTrue:[
   620         self nextPutAll:anObject startingAt:start to:(start + count - 1).
   620 	self nextPutAll:anObject startingAt:start to:(start + count - 1).
   621         ^ count.
   621 	^ count.
   622     ].
   622     ].
   623     ^ super nextPutBytes:count from:anObject startingAt:start
   623     ^ super nextPutBytes:count from:anObject startingAt:start
   624 !
   624 !
   625 
   625 
   626 nextPutUnicode:aCharacter
   626 nextPutUnicode:aCharacter
   627     "normal streams can not handle multi-byte characters, so convert them to utf8"
   627     "normal streams can not handle multi-byte characters, so convert them to utf8"
   628 
   628 
   629     "this code is not perfect if you use both #nextPut: and #nextPutUnicode:
   629     "this code is not perfect if you use both #nextPut: and #nextPutUnicode:
   630      with the same stream, since 8-bit characters (with the highest bits set) 
   630      with the same stream, since 8-bit characters (with the highest bits set)
   631      are not stored as UTF, so we get some inconsistent string"
   631      are not stored as UTF, so we get some inconsistent string"
   632 
   632 
   633     collection isString ifTrue:[
   633     collection isString ifTrue:[
   634         collection bitsPerCharacter == 16 ifTrue:[
   634 	collection bitsPerCharacter == 16 ifTrue:[
   635             self nextPutUtf16:aCharacter.
   635 	    self nextPutUtf16:aCharacter.
   636         ] ifFalse:[
   636 	] ifFalse:[
   637             self nextPutUtf8:aCharacter.
   637 	    self nextPutUtf8:aCharacter.
   638         ].
   638 	].
   639     ] ifFalse:[
   639     ] ifFalse:[
   640         self nextPut:aCharacter.
   640 	self nextPut:aCharacter.
   641     ].
   641     ].
   642 ! !
   642 ! !
   643 
   643 
   644 !WriteStream class methodsFor:'documentation'!
   644 !WriteStream class methodsFor:'documentation'!
   645 
   645 
   646 version
   646 version
   647     ^ '$Header: /cvs/stx/stx/libbasic/WriteStream.st,v 1.96 2015-03-26 23:32:34 cg Exp $'
   647     ^ '$Header: /cvs/stx/stx/libbasic/WriteStream.st,v 1.97 2015-04-27 17:04:19 cg Exp $'
   648 !
   648 !
   649 
   649 
   650 version_CVS
   650 version_CVS
   651     ^ '$Header: /cvs/stx/stx/libbasic/WriteStream.st,v 1.96 2015-03-26 23:32:34 cg Exp $'
   651     ^ '$Header: /cvs/stx/stx/libbasic/WriteStream.st,v 1.97 2015-04-27 17:04:19 cg Exp $'
   652 ! !
   652 ! !
   653