'From Squeak 1.3 of Jan 16, 1998 on 20 January 1998 at 4:23:06 pm'! StandardFileStream subclass: #CrLfFileStream instanceVariableNames: 'lineEndConvention ' classVariableNames: 'Cr CrLf Lf LineEndDefault LineEndStrings LookAheadCount ' poolDictionaries: '' category: 'System-Files'! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ar 7/10/97 10:28'! lf ^self value: 10! ! !CrLfFileStream methodsFor: 'open/close' stamp: 'ar 1/20/98 16:15'! open: aFileName forWrite: writeMode "Open the receiver. If writeMode is true, allow write, else access will be read-only. " | result | result _ super open: aFileName forWrite: writeMode. result ifNotNil: [self detectLineEndConvention]. ^ result! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:16'! ascii super ascii. self detectLineEndConvention! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:16'! binary super binary. lineEndConvention _ nil! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:17'! detectLineEndConvention "Detect the line end convention used in this stream. The result may be either #cr, #lf or #crlf." | char numRead pos | self isBinary ifTrue: [^ self error: 'Line end conventions are not used on binary streams']. lineEndConvention _ LineEndDefault. "Default if nothing else found" numRead _ 0. pos _ self position. [self atEnd not and: [numRead < LookAheadCount]] whileTrue: [char _ self next. char = Lf ifTrue: [self position: pos. ^ lineEndConvention _ #lf]. char = Cr ifTrue: [self peek = Lf ifTrue: [lineEndConvention _ #crlf] ifFalse: [lineEndConvention _ #cr]. self position: pos. ^ lineEndConvention]. numRead _ numRead + 1]. self position: pos. ^ lineEndConvention! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:17'! next | char | char _ super next. lineEndConvention ifNil: [^ char]. (LineEndStrings at: lineEndConvention) first = char ifTrue: [lineEndConvention = #crlf ifTrue: [self peek = Character lf ifTrue: [super next. ^ Cr] ifFalse: [^ char]] ifFalse: [^ Cr]] ifFalse: [^ char] ! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:17'! next: n | string | string _ super next: n. lineEndConvention ifNil: [^ string]. lineEndConvention == #crlf ifTrue: ["Special case for last character" (string last = Cr and: [self peek = Lf]) ifTrue: [self next]]. ^ self convertStringToCr: string! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:18'! nextPut: char (lineEndConvention notNil and: [char = Cr]) ifTrue: [super nextPutAll: (LineEndStrings at: lineEndConvention)] ifFalse: [super nextPut: char]. ^ char! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:18'! nextPutAll: aString super nextPutAll: (self convertStringFromCr: aString). ^ aString ! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:18'! verbatim: aString super verbatim: (self convertStringFromCr: aString). ^ aString! ! !CrLfFileStream methodsFor: 'private' stamp: 'ar 1/20/98 16:21'! convertStringFromCr: aString | inStream outStream | lineEndConvention ifNil: [^ aString]. lineEndConvention == #cr ifTrue: [^ aString]. lineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Cr with: Lf]. "lineEndConvention == #crlf" inStream _ ReadStream on: aString. outStream _ WriteStream on: (String new: aString size). [inStream atEnd] whileFalse: [outStream nextPutAll: (inStream upTo: Cr). (inStream atEnd not or: [aString last = Cr]) ifTrue: [outStream nextPutAll: CrLf]]. ^ outStream contents! ! !CrLfFileStream methodsFor: 'private' stamp: 'ar 1/20/98 16:21'! convertStringToCr: aString | inStream outStream | lineEndConvention ifNil: [^ aString]. lineEndConvention == #cr ifTrue: [^ aString]. lineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Lf with: Cr]. "lineEndConvention == #crlf" inStream _ ReadStream on: aString. outStream _ WriteStream on: (String new: aString size). [inStream atEnd] whileFalse: [outStream nextPutAll: (inStream upTo: Cr). (inStream atEnd not or: [aString last = Cr]) ifTrue: [outStream nextPut: Cr. inStream peek = Lf ifTrue: [inStream next]]]. ^ outStream contents! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToCR "CrLfFileStream defaultToCR" LineEndDefault := #cr.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToCRLF "CrLfFileStream defaultToCRLF" LineEndDefault := #crlf.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToLF "CrLfFileStream defaultToLF" LineEndDefault := #lf.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:13'! guessDefaultLineEndConvention "Lets try to guess the line end convention from what we know about the path name delimiter from FileDirectory." FileDirectory pathNameDelimiter = $: ifTrue:[^self defaultToCR]. FileDirectory pathNameDelimiter = $/ ifTrue:[^self defaultToLF]. FileDirectory pathNameDelimiter = $\ ifTrue:[^self defaultToCRLF]. "in case we don't know" ^self defaultToCR! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:14'! initialize "CrLfFileStream initialize" Cr := Character cr. Lf := Character lf. CrLf := String with: Cr with: Lf. LineEndStrings := Dictionary new. LineEndStrings at: #cr put: (String with: Character cr). LineEndStrings at: #lf put: (String with: Character lf). LineEndStrings at: #crlf put: (String with: Character cr with: Character lf). LookAheadCount := 2048. self guessDefaultLineEndConvention.! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 1/20/98 16:22'! replaceAll: oldObject with: newObject "Replace all occurences of oldObject with newObject" | index | index _ self indexOf: oldObject startingAt: 1 ifAbsent: [0]. [index = 0] whileFalse: [self at: index put: newObject. index _ self indexOf: oldObject startingAt: index + 1 ifAbsent: [0]]! ! CrLfFileStream initialize!