From c950f5c01776972c580afc36f5f6d332b3bd4fab Mon Sep 17 00:00:00 2001 From: Guille Polito Date: Fri, 27 Nov 2020 13:35:44 +0100 Subject: [PATCH] Remove all static dependencies to DeprecatedFileStreams + remove DeprecatedFileStream package --- .../BaselineOfPharoBootstrap.class.st | 4 +- .../FileExistsException.class.st | 47 - src/DeprecatedFileStream/FileStream.class.st | 844 -------------- .../LimitingLineStreamWrapper.class.st | 205 ---- .../ManifestDeprecatedFileStream.class.st | 13 - .../MultiByteBinaryOrTextStream.class.st | 397 ------- .../MultiByteFileStream.class.st | 742 ------------ .../PositionableStream.extension.st | 8 - .../RWBinaryOrTextStream.class.st | 179 --- .../StandardFileStream.class.st | 1027 ----------------- src/DeprecatedFileStream/package.st | 1 - src/Fuel-Core/StandardFileStream.extension.st | 13 - .../ZnBufferedReadStream.extension.st | 26 + ...BinaryFileStreamSerializationTest.class.st | 12 - .../FLBinaryFileStreamStrategy.class.st | 28 - .../FLFileStreamStrategy.class.st | 91 -- .../FLMultiByteStreamStrategy.class.st | 17 +- .../FLSerializationTest.class.st | 18 - ...andardFileStreamSerializationTest.class.st | 12 - .../StandardFileStream.extension.st | 10 - .../MetacelloPharoCommonPlatform.class.st | 23 +- .../MCDataStreamTest.class.st | 2 +- src/Monticello/MCDataStream.class.st | 60 +- src/Monticello/MCVersionReader.class.st | 5 +- .../MCPseudoFileStream.class.st | 2 +- .../MCWorkingCopyBrowser.class.st | 6 +- src/MonticelloMocks/MCMockClassA.class.st | 3 +- .../ByteTextConverterTest.class.st | 16 +- src/Network-MIME/MIMEDocument.class.st | 2 +- src/Network-Mail/MIMEDocument.extension.st | 18 +- src/Network-Mail/MailMessage.class.st | 32 +- src/Network-Protocols/FTPClient.class.st | 12 +- .../PharoBootstrapInitialization.class.st | 1 - .../ChangeSet.extension.st | 11 +- src/System-Changes/ChangeSet.class.st | 3 +- .../MCMczInstallerTest.class.st | 10 +- .../SessionManager.class.st | 1 - src/Tests/FileStreamTest.class.st | 173 --- src/Tests/TraitFileOutTest.class.st | 12 +- .../ExternalChangesBrowser.class.st | 4 +- src/Tool-FileList/FileList.class.st | 4 +- src/Tool-FileList/FileStream.extension.st | 55 - .../FileStream.extension.st | 25 - src/Zinc-Zodiac/ZnHTTPSTest.class.st | 2 +- 44 files changed, 162 insertions(+), 4014 deletions(-) delete mode 100644 src/DeprecatedFileStream/FileExistsException.class.st delete mode 100644 src/DeprecatedFileStream/FileStream.class.st delete mode 100644 src/DeprecatedFileStream/LimitingLineStreamWrapper.class.st delete mode 100644 src/DeprecatedFileStream/ManifestDeprecatedFileStream.class.st delete mode 100644 src/DeprecatedFileStream/MultiByteBinaryOrTextStream.class.st delete mode 100644 src/DeprecatedFileStream/MultiByteFileStream.class.st delete mode 100644 src/DeprecatedFileStream/PositionableStream.extension.st delete mode 100644 src/DeprecatedFileStream/RWBinaryOrTextStream.class.st delete mode 100644 src/DeprecatedFileStream/StandardFileStream.class.st delete mode 100644 src/DeprecatedFileStream/package.st delete mode 100644 src/Fuel-Core/StandardFileStream.extension.st create mode 100644 src/Fuel-Core/ZnBufferedReadStream.extension.st delete mode 100644 src/Fuel-Tests-Core/FLBinaryFileStreamSerializationTest.class.st delete mode 100644 src/Fuel-Tests-Core/FLBinaryFileStreamStrategy.class.st delete mode 100644 src/Fuel-Tests-Core/FLFileStreamStrategy.class.st delete mode 100644 src/Fuel-Tests-Core/FLStandardFileStreamSerializationTest.class.st delete mode 100644 src/Graphics-Primitives/StandardFileStream.extension.st delete mode 100644 src/Tests/FileStreamTest.class.st delete mode 100644 src/Tool-FileList/FileStream.extension.st delete mode 100644 src/Zinc-Resource-Meta-Core/FileStream.extension.st diff --git a/src/BaselineOfPharoBootstrap/BaselineOfPharoBootstrap.class.st b/src/BaselineOfPharoBootstrap/BaselineOfPharoBootstrap.class.st index b44b7f82be4..215911dda05 100644 --- a/src/BaselineOfPharoBootstrap/BaselineOfPharoBootstrap.class.st +++ b/src/BaselineOfPharoBootstrap/BaselineOfPharoBootstrap.class.st @@ -141,7 +141,6 @@ BaselineOfPharoBootstrap >> baseline: spec [ spec package: 'FileSystem-Core'. spec package: 'FileSystem-Disk'. - spec package: 'DeprecatedFileStream'. spec package: 'SUnit-Core'. spec package: 'SUnit-Tests'. @@ -222,8 +221,7 @@ BaselineOfPharoBootstrap >> baseline: spec [ spec group: 'FileSystemGroup' with: { 'FileSystem-Core'. - 'FileSystem-Disk'. - 'DeprecatedFileStream' }. + 'FileSystem-Disk'}. spec group: 'ToLoadByHermes' with: { 'AdditionalPackages'. diff --git a/src/DeprecatedFileStream/FileExistsException.class.st b/src/DeprecatedFileStream/FileExistsException.class.st deleted file mode 100644 index 5ff918da2be..00000000000 --- a/src/DeprecatedFileStream/FileExistsException.class.st +++ /dev/null @@ -1,47 +0,0 @@ -" -Notify when file exists -" -Class { - #name : #FileExistsException, - #superclass : #FileException, - #instVars : [ - 'fileClass' - ], - #category : #'DeprecatedFileStream-Exceptions' -} - -{ #category : #exceptioninstantiator } -FileExistsException class >> fileName: aFileName fileClass: aClass [ - ^ self new - fileName: aFileName; - fileClass: aClass -] - -{ #category : #deprecation } -FileExistsException class >> isDeprecated [ - ^true -] - -{ #category : #exceptiondescription } -FileExistsException >> defaultAction [ - "The default action taken if the exception is signaled." - - ^ UIManager default fileExistsDefaultAction: self - -] - -{ #category : #accessing } -FileExistsException >> file [ - - ^ self fileClass fileNamed: fileName -] - -{ #category : #accessing } -FileExistsException >> fileClass [ - ^ fileClass ifNil: [StandardFileStream] -] - -{ #category : #accessing } -FileExistsException >> fileClass: aClass [ - fileClass := aClass -] diff --git a/src/DeprecatedFileStream/FileStream.class.st b/src/DeprecatedFileStream/FileStream.class.st deleted file mode 100644 index 23884c3f0da..00000000000 --- a/src/DeprecatedFileStream/FileStream.class.st +++ /dev/null @@ -1,844 +0,0 @@ -" -I'm a deprecated class. -Since the version 5, Pharo provides a new file streams API that makes the old one based on classes like FileStream or MultiByteBinaryOrTextStream deprecated. -Pharo 7 makes the next important steps and removes usages of the old API from the kernel. - -What you should remember: -- use file references as entry points to file streams -- DO NOT USE FileStream class -- 'file.txt' asFileReference readStream and similar methods now return an instance of ZnCharacterReadStream instead of MultiByteFileStream -- 'file.txt' asFileReference writeStream and similar methods now return an instance of ZnCharacterWriteStream instead of MultiByteFileStream -- the new API has a clearer separation between binary and text files - -1. Basic Files -By default files are binary. Not buffered. - -Read UTF-8 text from an existing file -Obsolete code: -FileStream readOnlyFileNamed: '1.txt' do: [ :stream | - stream upToEnd ]. -New code: -(File named: 'name') readStream. -(File named: 'name') readStreamDo: [ :stream | … ]. -'1.txt' asFileReference readStreamDo: [ :stream | - stream upToEnd ]. - -2. Encoding -To add encoding, wrap a stream with a corresponding ZnCharacterRead/WriteStream. -“Reading” -utf8Encoded := ZnCharacterReadStream on: aBinaryStream encoding: ‘utf8’. -utf16Encoded := ZnCharacterReadStream on: aBinaryStream encoding: ‘utf16’. -“Writing” -utf8Encoded := ZnCharacterWriteStream on: aBinaryStream encoding: ‘utf8’. -utf16Encoded := ZnCharacterWriteStream on: aBinaryStream encoding: ‘utf16’. - -Force creation of a new file and write a UTF-8 text -Obsolete code: -FileStream forceNewFileNamed: '1.txt' do: [ :stream | stream nextPutAll: 'a ≠ b' ]. -New code: -(File named: ‘name’) writeStream. -(File named: ‘name’) writeStreamDo: [ :stream | … ]. -'1.txt' asFileReference ensureDelete; - writeStreamDo: [ :stream | stream nextPutAll: 'a ≠ b' ]. - -Get all content of existing UTF-8 file -Obsolete code: -(FileStream readOnlyFileNamed: '1.txt') contentsOfEntireFile. -New code: -'1.txt' asFileReference readStream upToEnd. - -3. Buffering -To add buffering, wrap a stream with a corresponding ZnBufferedRead/WriteStream. -bufferedReadStream := ZnBufferedReadStream on: aStream. -bufferedWriteStream := ZnBufferedWriteStream on: aStream. -It is in general better to buffer the reading on the binary file and apply the encoding on the buffer in memory than the other way around. See -[file := Smalltalk sourcesFile fullName. -(File named: file) readStreamDo: [ :binaryFile | -(ZnCharacterReadStream on: (ZnBufferedReadStream on: binaryFile) encoding: ‘utf8’) upToEnd -]] timeToRun. “0:00:00:09.288” -[file := Smalltalk sourcesFile fullName. -(File named: file) readStreamDo: [ :binaryFile | -(ZnBufferedReadStream on: (ZnCharacterReadStream on: binaryFile encoding: ‘utf8’)) upToEnd -]] timeToRun. “0:00:00:14.189” - -The MultiByteFileStream was buffered. If you create a stream using the expression -'file.txt' asFileReference readStream. -then the ZnCharacterReadStream is not created directly on top of the stream but on top of a buffered stream that uses the file stream internally. - -If you create a ZnCharacterReadStream directly on the file stream, then the characters from the file are read one by one which may be about ten times slower! -ZnCharacterReadStream on: (File openForReadFileNamed: 'file.txt'). - -4. File System -By default, file system files are buffered and utf8 encoded to keep backwards compatibility. -‘name’ asFileReference readStreamDo: [ :bufferedUtf8Stream | … ]. -‘name’ asFileReference writeStreamDo: [ :bufferedUtf8Stream | … ]. -FileStream also provides access to plain binary files using the #binaryRead/WriteStream messages. Binary streams are buffered by default too. -‘name’ asFileReference binaryReadStreamDo: [ :bufferedBinaryStream | … ]. -‘name’ asFileReference binaryWriteStreamDo: [ :bufferedBinaryStream | … ]. -If you want a file with another encoding (to come in the PR https://github.com/pharo-project/pharo/pull/1134), you can specify it while obtaining the stream: -‘name’ asFileReference - readStreamEncoded: ‘utf16’ - do: [ :bufferedUtf16Stream | … ]. -‘name’ asFileReference - writeStreamEncoded: ‘utf8’ - do: [ :bufferedUtf16Stream | … ]. - -Force creation of a new file and write binary data into it -Obsolete code: -(FileStream forceNewFileNamed: '1.bin') - binary; - nextPutAll: #[1 2 3]. -New code: -'1.bin' asFileReference ensureDelete; - binaryWriteStreamDo: [ :stream | stream nextPutAll: #[1 2 3] ]. - -Read binary data from an existing file -Obsolete code: -(FileStream readOnlyFileNamed: '1.bin') binary; contentsOfEntireFile. -New code: -'1.bin' asFileReference binaryReadStream upToEnd. - -Force creation of a new file with a different encoding -Obsolete code: -FileStream forceNewFileNamed: '2.txt' do: [ :stream | - stream converter: (TextConverter newForEncoding: 'cp-1250'). - stream nextPutAll: 'Příliš žluťoučký kůň úpěl ďábelské ódy.' ]. -New code: -('2.txt' asFileReference) ensureDelete; - writeStreamEncoded: 'cp-1250' do: [ :stream | - stream nextPutAll: 'Příliš žluťoučký kůň úpěl ďábelské ódy.' ]. - -Read encoded text from an existing file -Obsolete code: -FileStream readOnlyFileNamed: '2.txt' do: [ :stream | - stream converter: (TextConverter newForEncoding: 'cp-1250'). - stream upToEnd ]. -New code: -('2.txt' asFileReference) - readStreamEncoded: 'cp-1250' do: [ :stream | - stream upToEnd ]. - -Write a UTF-8 text to STDOUT -Obsolete code: -FileStream stdout nextPutAll: 'a ≠ b'; lf. -New code: -(ZnCharacterWriteStream on: Stdio stdout) - nextPutAll: 'a ≠ b'; lf; - flush. - -Write CP-1250 encoded text to STDOUT -Obsolete code: -FileStream stdout - converter: (TextConverter newForEncoding: 'cp-1250'); - nextPutAll: 'Příliš žluťoučký kůň úpěl ďábelské ódy.'; lf. -New code: -(ZnCharacterWriteStream on: Stdio stdout encoding: 'cp1250') - nextPutAll: 'Příliš žluťoučký kůň úpěl ďábelské ódy.'; lf; - flush. - -Read a UTF-8 text from STDIN -CAUTION: Following code will stop your VM until an input on STDIN will be provided! -Obsolete code: -FileStream stdin upTo: Character lf. -New code: -(ZnCharacterReadStream on: Stdio stdin) upTo: Character lf. -Write binary data to STDOUT -obsolete code -FileStream stdout - binary - nextPutAll: #[80 104 97 114 111 10 ]. -New code: -Stdio stdout - nextPutAll: #[80 104 97 114 111 10 ]. - -Read binary data from STDIN -CAUTION: Following code will stop your VM until an input on STDIN will be provided! -Obsolete code: -FileStream stdin binary upTo: 10. -New code: -Stdio stdin upTo: 10. - -Positionable streams -The message #position: always works on the binary level, not on the character level. -'1.txt' asFileReference readStreamDo: [ :stream | - stream position: 4. - stream upToEnd ]. -This will lead to an error (ZnInvalidUTF8: Illegal leading byte for UTF-8 encoding) in case of the file created above because we set the position into the middle of a UTF-8 encoded character. To be safe, you need to read the file from the beginning. -'1.txt' asFileReference readStreamDo: [ :stream | - 3 timesRepeat: [ stream next ]. - stream upToEnd.]. - -5. Line Ending Conventions -If you want to write files following a specific line ending convention, use the ZnNewLineWriterStream. -This stream decorator will transform any line ending (cr, lf, crlf) into a defined line ending. -By default, it chooses the platform line ending convention. -lineWriter := ZnNewLineWriterStream on: aStream. -If you want to choose another line ending convention you can do: -lineWriter forCr. -lineWriter forLf. -lineWriter forCrLf. -lineWriter forPlatformLineEnding. -------------------------------------------- -Old comment: - -I represent a Stream that accesses a FilePage from a File. One use for my instance is to access larger ""virtual Strings"" than can be stored contiguously in main memory. I restrict the objects stored and retrieved to be Integers or Characters. An end of file pointer terminates reading; it can be extended by writing past it, or the file can be explicitly truncated. - -To use the file system for most applications, you typically create a FileStream. This is done by sending a message to a FileDirectory (file:, oldFile:, newFile:, rename:newName:) which creates an instance of me. Accesses to the file are then done via my instance. - -*** On DOS, files cannot be shortened! *** To overwrite a file with a shorter one, first delete the old file (FileDirectory deleteFilePath: 'Hard Disk:aFolder:dataFolder:foo') or (aFileDirectory deleteFileNamed: 'foo'). Then write your new shorter version. -" -Class { - #name : #FileStream, - #superclass : #ReadWriteStream, - #classVars : [ - 'Stderr', - 'Stdin', - 'StdioFiles', - 'Stdout', - 'TheStdioHandles' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #'file reader services' } -FileStream class >> changesFileSuffixes [ - - ^#('changes') - - -] - -{ #category : #'concrete classes' } -FileStream class >> concreteStream [ - "Who should we really direct class queries to? " - ^ MultiByteFileStream. - -] - -{ #category : #utilities } -FileStream class >> convertCRtoLF: fileName [ - "Convert the given file to LF line endings. Put the result in a file with the extention '.lf'" - - | in out c justPutCR | - in := (self readOnlyFileNamed: fileName) binary. - out := (self newFileNamed: fileName, '.lf') binary. - justPutCR := false. - [in atEnd] whileFalse: [ - c := in next. - c = 10 - ifTrue: [ - out nextPut: 13. - justPutCR := true] - ifFalse: [ - (justPutCR and: [c = 10]) ifFalse: [out nextPut: c]. - justPutCR := false]]. - in close. - out close. - -] - -{ #category : #'instance creation' } -FileStream class >> detectFile: aBlock do: anotherBlock [ - ^ aBlock value - ifNotNil: [ :file | - [ anotherBlock value: file ] - ensure: [ file close ] ] -] - -{ #category : #'file reader services' } -FileStream class >> fileIn: fullName [ - "File in the entire contents of the file specified by the name provided" - - | ff fn | - fullName ifNil: [^ self inform: 'Filename is nil.']. - fn := fullName asFileReference. - fn := (Smalltalk hasClassNamed: #GZipReadStream) - ifTrue: [(Smalltalk classNamed: #GZipReadStream) uncompressedFileName: fn fullName] - ifFalse: [fn fullName]. - ff := self readOnlyFileNamed: fn. - ff fileIn. - -] - -{ #category : #'instance creation' } -FileStream class >> fileNamed: fileName [ - ^ self concreteStream fileNamed: (self fullName: fileName) -] - -{ #category : #'instance creation' } -FileStream class >> fileNamed: fileName do: aBlock [ - "Returns the result of aBlock." - - ^ self detectFile: [ self fileNamed: fileName ] do: aBlock -] - -{ #category : #stdio } -FileStream class >> flushAndVoidStdioFiles [ - - StdioFiles ifNotNil: [ - StdioFiles do: [ :file | - file ifNotNil: [ - file isReadOnly ifFalse: [ - [ file flush ] - on: Error - do: [ :ex | "care less" ] ] ] ]. - ]. - - self voidStdioFiles -] - -{ #category : #'instance creation' } -FileStream class >> forceNewFileNamed: fileName [ - "Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, delete it without asking before creating the new file." - - SessionManager default currentSession isReadOnlyAccessMode ifTrue: [ ((CannotDeleteFileException fileName: fileName) - messageText: 'Could not delete the old version of file ' , fileName) signal. - ^ NullStream new ]. - - ^self concreteStream forceNewFileNamed: fileName -] - -{ #category : #'instance creation' } -FileStream class >> forceNewFileNamed: fileName do: aBlock [ - "Returns the result of aBlock." - - ^ self detectFile: [ self forceNewFileNamed: fileName ] do: aBlock -] - -{ #category : #'instance creation' } -FileStream class >> fullName: fileName [ - ^ fileName asFileReference fullName -] - -{ #category : #'initialize-release' } -FileStream class >> initialize [ - TheStdioHandles := Array new: 3. - SessionManager default registerSystemClassNamed: self name -] - -{ #category : #'instance creation' } -FileStream class >> isAFileNamed: fName [ - "return whether a file exists with the given name" - ^self concreteStream isAFileNamed: (self fullName: fName) -] - -{ #category : #'file reader services' } -FileStream class >> isChangesFileSuffix: suffix [ - - ^ self changesFileSuffixes includes: suffix - -] - -{ #category : #deprecation } -FileStream class >> isDeprecated [ - ^true -] - -{ #category : #'file reader services' } -FileStream class >> isSourceFileSuffix: suffix [ - - ^ self sourceFileSuffixes includes: suffix - -] - -{ #category : #'instance creation' } -FileStream class >> new [ - ^ self basicNew -] - -{ #category : #'instance creation' } -FileStream class >> newFileNamed: fileName [ - ^ self concreteStream newFileNamed: (self fullName: fileName) -] - -{ #category : #'instance creation' } -FileStream class >> newFileNamed: fileName do: aBlock [ - "Returns the result of aBlock." - - ^ self detectFile: [ self newFileNamed: fileName ] do: aBlock -] - -{ #category : #stdio } -FileStream class >> newForStdio [ - "This is a hook for subclasses to initialize themselves properly." - - ^self new -] - -{ #category : #'instance creation' } -FileStream class >> oldFileNamed: fileName [ - ^ self concreteStream oldFileNamed: (self fullName: fileName) -] - -{ #category : #'instance creation' } -FileStream class >> oldFileNamed: fileName do: aBlock [ - "Returns the result of aBlock." - - ^ self detectFile: [ self oldFileNamed: fileName ] do: aBlock -] - -{ #category : #'instance creation' } -FileStream class >> oldFileOrNoneNamed: fileName [ - "If the file exists, answer a read-only FileStream on it. If it doesn't, answer nil." - - | fullName | - fullName := self fullName: fileName. - ^ (self concreteStream isAFileNamed: fullName) - ifTrue: [ self concreteStream readOnlyFileNamed: fullName] - ifFalse: [ nil]. - -] - -{ #category : #'instance creation' } -FileStream class >> onHandle: aFileSystemHandle [ - ^ self concreteStream new - open: aFileSystemHandle fullName - forWrite: aFileSystemHandle isWritable -] - -{ #category : #'instance creation' } -FileStream class >> readOnlyFileNamed: fileName [ - ^ self concreteStream readOnlyFileNamed: (self fullName: fileName) -] - -{ #category : #'instance creation' } -FileStream class >> readOnlyFileNamed: fileName do: aBlock [ - "Open the existing file with the given name for read-only access and pass it as argument to aBlock. - Returns the result of aBlock." - - ^ self detectFile: [ self readOnlyFileNamed: fileName ] do: aBlock -] - -{ #category : #'file reader services' } -FileStream class >> removeLineFeeds: fullName [ - | fileContents | - fileContents := ((FileStream readOnlyFileNamed: fullName) wantsLineEndConversion: true) contentsOfEntireFile. - (FileStream newFileNamed: fullName) - nextPutAll: fileContents; - close. -] - -{ #category : #'dnd requests' } -FileStream class >> requestDropStream: dropIndex [ - "Request a read-only stream for some file that was dropped onto the application" - ^self concreteStream new requestDropStream: dropIndex. -] - -{ #category : #'system startup' } -FileStream class >> shutDown: isImageQuitting [ - isImageQuitting ifTrue: [ self flushAndVoidStdioFiles ] -] - -{ #category : #'file reader services' } -FileStream class >> sourceFileSuffixes [ - - ^#('st' 'cs') - - -] - -{ #category : #stdio } -FileStream class >> standardIOStreamNamed: moniker forWrite: forWrite [ - "Create if necessary and store default stdin, stdout and other files based on the their names" - - | index | - - "This is an ugly hack, while waiting for a real fix for windows. There several problems with this approach, but it allow us to run tests, etc." - Smalltalk os isWin32 - ifTrue: [ - [ ^ MultiByteFileStream forceNewFileNamed: moniker asString ] - on: CannotDeleteFileException do: [ - "HACK: if the image is opened a second time windows barks about the already opened locked file" - ^ MultiByteFileStream forceNewFileNamed: moniker asString, '_', (Random new nextInt: SmallInteger maxVal) asString ]]. - - index := #(stdin stdout stderr) identityIndexOf: moniker. - ^((StdioFiles ifNil: [ StdioFiles := Array new: 3 ]) at: index) - ifNil: [ - StdioFiles - at: index - put: ( - (TheStdioHandles at: index) - ifNil: [ ^self error: moniker, ' is unavailable' ] - ifNotNil: [ :handle | - MultiByteFileStream newForStdio - openOnHandle: handle - name: moniker - forWrite: forWrite ]) ] - -] - -{ #category : #'system startup' } -FileStream class >> startUp: isImageStarting [ - isImageStarting - ifFalse: [ ^ self ]. - self voidStdioFiles. - [ TheStdioHandles := self stdioHandles ] - on: Error - do: [ :ex | - TheStdioHandles isArray - ifFalse: [ TheStdioHandles := Array new: 3 ] ] -] - -{ #category : #stdio } -FileStream class >> stderr [ - - ^Stderr ifNil: [ Stderr := self standardIOStreamNamed: #stderr forWrite: true ] -] - -{ #category : #stdio } -FileStream class >> stdin [ - - ^Stdin ifNil: [ - Stdin := self standardIOStreamNamed: #stdin forWrite: false. - Stdin - disableReadBuffering; - yourself ]. -] - -{ #category : #stdio } -FileStream class >> stdioHandles [ - - self primitiveFailed -] - -{ #category : #stdio } -FileStream class >> stdout [ - - ^Stdout ifNil: [ Stdout := self standardIOStreamNamed: #stdout forWrite: true ] -] - -{ #category : #stdio } -FileStream class >> voidStdioFiles [ - - Smalltalk os isWin32 ifTrue: [ - {Stdout . Stderr } do: [ :each | - [ each ifNotNil: [ - each size isZero ifTrue: [ - each close. - each name asFileReference delete - ] - ] - ] onErrorDo: [ ]. - ] - ]. - - Stdin := Stdout := Stderr := StdioFiles := nil -] - -{ #category : #utilities } -FileStream class >> writeSourceCodeFrom: aStream baseName: baseName isSt: stOrCsFlag [ - - | extension converter fileName | - [ extension := stOrCsFlag ifTrue: ['.st'] ifFalse: ['.cs']. - converter := aStream contents isAsciiString - ifTrue: [MacRomanTextConverter new] - ifFalse: [UTF8TextConverter new]. - fileName := baseName, extension. - fileName := FileSystem disk checkName: fileName fixErrors: true. - [FileStream newFileNamed: fileName do: [:fileStream | - fileName := fileStream name. "in case it is changed when handling FileExistsException" - (converter isMemberOf: UTF8TextConverter) - ifTrue: [fileStream binary. - UTF8TextConverter writeBOMOn: fileStream]. - fileStream - text; - converter: converter; - nextPutAll: aStream contents; - close]] on: Abort do: [:e | ^self ] - ] on: Error do: - [ :error | - error isResumable - ifTrue: [ error resumeUnchecked: error defaultAction] - ifFalse: [ error pass ] - ]. - self inform: 'Filed out to: ', String cr, fileName. -] - -{ #category : #converting } -FileStream >> asBinaryOrTextStream [ - "I can switch between binary and text data" - - ^ self -] - -{ #category : #modes } -FileStream >> ascii [ - "Set this file to ascii (text) mode." - - self subclassResponsibility - -] - -{ #category : #testing } -FileStream >> atEnd [ - "Answer true if the current position is >= the end of file position." - - self subclassResponsibility -] - -{ #category : #modes } -FileStream >> binary [ - "Set this file to binary mode." - - self subclassResponsibility - -] - -{ #category : #'open/close' } -FileStream >> close [ - "Close this file." - - self subclassResponsibility - -] - -{ #category : #testing } -FileStream >> closed [ - "Answer true if this file is closed." - - self subclassResponsibility - -] - -{ #category : #accessing } -FileStream >> contents [ - "Return the contents of the receiver. Do not close or otherwise touch the receiver. Return data in whatever mode the receiver is in (e.g., binary or text)." - | s savePos | - savePos := self position. - self position: 0. - s := self next: self size. - self position: savePos. - ^s -] - -{ #category : #accessing } -FileStream >> contentsOfEntireFile [ - "Read all of the contents of the receiver." - - | s binary | - self readOnly. - binary := self isBinary. - self reset. "erases knowledge of whether it is binary" - binary ifTrue: [self binary]. - s := self next: self size. - self close. - ^s -] - -{ #category : #actions } -FileStream >> delete [ - - (File named: self name) delete -] - -{ #category : #actions } -FileStream >> exists [ - - ^ (File named: self name) exists -] - -{ #category : #accessing } -FileStream >> file [ - "Answer the file for the page the receiver is streaming over." - - self subclassResponsibility -] - -{ #category : #ToDeprecate } -FileStream >> fileIn [ - "Guarantee that the receiver is readOnly before fileIn for efficiency and - to eliminate remote sharing conflicts." - - self readOnly. - CodeImporter evaluateFileStream: self. -] - -{ #category : #flushing } -FileStream >> flush [ - "When writing, this flushes the write buffer the stream uses to reduce - the number of write() system calls it makes. This should generally be - used before #sync, but on Windows they do the same thing." - - self subclassResponsibility - -] - -{ #category : #accessing } -FileStream >> localName [ - - ^ self name asFileReference basename - -] - -{ #category : #printing } -FileStream >> longPrintOn: aStream [ - "Do nothing, so it will print short. Called to print the error file. If the error was in a file operation, we can't read the contents of that file. Just print its name instead." - -] - -{ #category : #printing } -FileStream >> longPrintOn: aStream limitedTo: sizeLimit indent: indent [ - - "Do nothing, so it will print short. Called to print the error file. If the error was in a file operation, we can't read the contents of that file. Just print its name instead." - - aStream cr -] - -{ #category : #accessing } -FileStream >> mimeTypes [ - ^ self name asFileReference mimeTypes. -] - -{ #category : #accessing } -FileStream >> name [ - "Answer the name of the file for the page the receiver is streaming over." - - self subclassResponsibility -] - -{ #category : #accessing } -FileStream >> next [ - ^ (position >= readLimit and: [ self atEnd ]) - ifTrue: [ nil ] - ifFalse: [ collection at: (position := position + 1) ] -] - -{ #category : #accessing } -FileStream >> next: anInteger [ - - | newCollection howManyRead increment | - newCollection := self collectionSpecies new: anInteger. - howManyRead := 0. - [howManyRead < anInteger] whileTrue: - [self atEnd ifTrue: - [(howManyRead + 1) to: anInteger do: [:i | newCollection at: i put: (self next)]. - ^newCollection]. - increment := (readLimit - position) min: (anInteger - howManyRead). - newCollection replaceFrom: (howManyRead + 1) - to: (howManyRead := howManyRead + increment) - with: collection - startingAt: (position + 1). - position := position + increment]. - ^newCollection -] - -{ #category : #accessing } -FileStream >> nextPut: aByte [ - "1/31/96 sw: subclassResponsibility" - - self subclassResponsibility -] - -{ #category : #accessing } -FileStream >> nextPutAll: aCollection [ - "1/31/96 sw: made subclass responsibility" - - self subclassResponsibility -] - -{ #category : #positioning } -FileStream >> position [ - "Answer the current character position in the file." - - self subclassResponsibility -] - -{ #category : #positioning } -FileStream >> position: pos [ - "Set the current character position in the file to pos." - - self subclassResponsibility -] - -{ #category : #printing } -FileStream >> printOn: aStream [ - - super printOn: aStream. - aStream nextPutAll: ' on '. - self file printOn: aStream -] - -{ #category : #modes } -FileStream >> readOnly [ - "Set this file's mode to read-only." - - self subclassResponsibility - -] - -{ #category : #modes } -FileStream >> readOnlyStream [ - ^self readOnly -] - -{ #category : #modes } -FileStream >> readWrite [ - "Set this file's mode to read-write." - - self subclassResponsibility - -] - -{ #category : #'open/close' } -FileStream >> reopen [ - "Ensure that the receiver is open, re-open it if necessary." - "Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened." - - self subclassResponsibility - -] - -{ #category : #initialization } -FileStream >> reset [ - "Set the current character position to the beginning of the file." - - self subclassResponsibility -] - -{ #category : #positioning } -FileStream >> setToEnd [ - "Set the current character position to the end of the File. The same as - self position: self size." - - self subclassResponsibility -] - -{ #category : #accessing } -FileStream >> size [ - "Answer the size of the file in characters." - - self subclassResponsibility -] - -{ #category : #positioning } -FileStream >> skip: n [ - "Set the character position to n characters from the current position. - Error if not enough characters left in the file." - - self subclassResponsibility -] - -{ #category : #flushing } -FileStream >> sync [ - "When writing, this syncs any written/flushed data still in the kernel - file system buffers to disk. This should generally be used after #flush, - but on Windows they do the same thing." - - self subclassResponsibility - -] - -{ #category : #modes } -FileStream >> text [ - "Set this file to text (ascii) mode." - - self ascii. - -] - -{ #category : #positioning } -FileStream >> truncate: pos [ - "Truncate file to pos" - - self subclassResponsibility -] diff --git a/src/DeprecatedFileStream/LimitingLineStreamWrapper.class.st b/src/DeprecatedFileStream/LimitingLineStreamWrapper.class.st deleted file mode 100644 index bce57c3460e..00000000000 --- a/src/DeprecatedFileStream/LimitingLineStreamWrapper.class.st +++ /dev/null @@ -1,205 +0,0 @@ -" -I'm a wrapper for a stream optimized for line-by-line access using #nextLine. My instances can be nested. - -I read one line ahead. Reading terminates when the stream ends, or if the limitingBlock evaluated with the line answers true. To skip the delimiting line for further reading use #skipThisLine. - -Character-based reading (#next) is permitted, too. Send #updatePosition when switching from line-based reading. - -See examples at the class side. - ---bf 2/19/1999 12:52 -" -Class { - #name : #LimitingLineStreamWrapper, - #superclass : #Object, - #instVars : [ - 'stream', - 'line', - 'limitingBlock', - 'position' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #examples } -LimitingLineStreamWrapper class >> example1 [ - - "LimitingLineStreamWrapper example1" - "Separate chunks of text delimited by a special string" - | inStream msgStream messages | - inStream := self exampleStream. - msgStream := self on: inStream delimiter: 'From '. - messages := OrderedCollection new. - [inStream atEnd] whileFalse: [ - msgStream skipThisLine. - messages add: msgStream upToEnd]. - ^messages - -] - -{ #category : #examples } -LimitingLineStreamWrapper class >> example2 [ - - "LimitingLineStreamWrapper example2" - "Demo nesting wrappers - get header lines from some messages" - | inStream msgStream headers headerStream | - inStream := self exampleStream. - msgStream := self on: inStream delimiter: 'From '. - headers := OrderedCollection new. - [inStream atEnd] whileFalse: [ - msgStream skipThisLine. "Skip From" - headerStream := self on: msgStream delimiter: ''. - headers add: headerStream linesUpToEnd. - [msgStream nextLine isNil] whileFalse. "Skip Body" - ]. - ^headers - -] - -{ #category : #examples } -LimitingLineStreamWrapper class >> exampleStream [ - - ^ 'From me@somewhere -From: me -To: you -Subject: Test - -Test - -From you@elsewhere -From: you -To: me -Subject: Re: test - -okay -' readStream -] - -{ #category : #deprecation } -LimitingLineStreamWrapper class >> isDeprecated [ - ^true -] - -{ #category : #'instance creation' } -LimitingLineStreamWrapper class >> on: aStream delimiter: aString [ - - ^self new setStream: aStream delimiter: aString - -] - -{ #category : #testing } -LimitingLineStreamWrapper >> atEnd [ - - ^line isNil or: [limitingBlock value: line] -] - -{ #category : #'stream protocol' } -LimitingLineStreamWrapper >> close [ - ^stream close -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> delimiter: aString [ - "Set limitBlock to check for a delimiting string. Be unlimiting if nil" - - self limitingBlock: (aString caseOf: { - [nil] -> [[:aLine | false]]. - [''] -> [[:aLine | aLine size = 0]] - } otherwise: [[:aLine | aLine beginsWith: aString]]) - -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> lastLineRead [ - "Return line last read. At stream end, this is the boundary line or nil" - - ^ line -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> limitingBlock: aBlock [ - "The limitingBlock is evaluated with a line to check if this line terminates the stream" - - limitingBlock := aBlock. - self updatePosition -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> linesUpToEnd [ - - | elements ln | - elements := OrderedCollection new. - [(ln := self nextLine) isNil] whileFalse: [ - elements add: ln]. - ^elements -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> next [ - "Provide character-based access" - - position ifNil: [^nil]. - position < line size ifTrue: [^line at: (position := position + 1)]. - line := stream nextLine. - self updatePosition. - ^ Character cr -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> nextLine [ - - | thisLine | - self atEnd ifTrue: [^nil]. - thisLine := line. - line := stream nextLine. - ^thisLine - -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> peekLine [ - - self atEnd ifTrue: [^nil]. - ^ line -] - -{ #category : #printing } -LimitingLineStreamWrapper >> printOn: aStream [ - - super printOn: aStream. - aStream nextPutAll: ' on '. - stream printOn: aStream -] - -{ #category : #private } -LimitingLineStreamWrapper >> setStream: aStream delimiter: aString [ - - stream := aStream. - line := stream nextLine. - self delimiter: aString. "sets position" - -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> skipThisLine [ - - line := stream nextLine. - self updatePosition. - -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> upToEnd [ - - - ^String streamContents: [:strm | | ln | - [(ln := self nextLine) isNil] whileFalse: [ - strm nextPutAll: ln; cr]] -] - -{ #category : #accessing } -LimitingLineStreamWrapper >> updatePosition [ - "Call this before doing character-based access" - - position := self atEnd ifFalse: [0] -] diff --git a/src/DeprecatedFileStream/ManifestDeprecatedFileStream.class.st b/src/DeprecatedFileStream/ManifestDeprecatedFileStream.class.st deleted file mode 100644 index e1c9899e2cb..00000000000 --- a/src/DeprecatedFileStream/ManifestDeprecatedFileStream.class.st +++ /dev/null @@ -1,13 +0,0 @@ -" -Deprecated package including the old file stream implementations -" -Class { - #name : #ManifestDeprecatedFileStream, - #superclass : #PackageManifest, - #category : #'DeprecatedFileStream-Manifest' -} - -{ #category : #deprecation } -ManifestDeprecatedFileStream class >> isDeprecated [ - ^true -] diff --git a/src/DeprecatedFileStream/MultiByteBinaryOrTextStream.class.st b/src/DeprecatedFileStream/MultiByteBinaryOrTextStream.class.st deleted file mode 100644 index e0d10d5f570..00000000000 --- a/src/DeprecatedFileStream/MultiByteBinaryOrTextStream.class.st +++ /dev/null @@ -1,397 +0,0 @@ -" -It is similar to MultiByteFileStream, but works on in memory stream. -" -Class { - #name : #MultiByteBinaryOrTextStream, - #superclass : #ReadWriteStream, - #instVars : [ - 'isBinary', - 'converter' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #defaults } -MultiByteBinaryOrTextStream class >> defaultConverter [ - ^ Latin1TextConverter new. - -] - -{ #category : #deprecation } -MultiByteBinaryOrTextStream class >> isDeprecated [ - ^true -] - -{ #category : #'instance creation' } -MultiByteBinaryOrTextStream class >> on: aCollection encoding: encodingName [ - | aTextConverter | - encodingName - ifNil: [aTextConverter := TextConverter default] - ifNotNil: [aTextConverter := TextConverter newForEncoding: encodingName]. - ^ (self on: aCollection) - converter: aTextConverter -] - -{ #category : #'instance creation' } -MultiByteBinaryOrTextStream class >> with: aCollection encoding: encodingName [ - | aTextConverter | - encodingName - ifNil: [aTextConverter := TextConverter default] - ifNotNil: [aTextConverter := TextConverter newForEncoding: encodingName]. - ^ (self with: aCollection) - converter: aTextConverter -] - -{ #category : #converting } -MultiByteBinaryOrTextStream >> asBinaryOrTextStream [ - - ^ self - -] - -{ #category : #modes } -MultiByteBinaryOrTextStream >> ascii [ - isBinary := false - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNext [ - | nextChar | - - ^ isBinary - ifTrue: [super next] - ifFalse: [ - (nextChar := super next) - ifNotNil: [nextChar asCharacter]]. -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNext: anInteger [ - - ^ super next: anInteger. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNext: n into: aString [ - - ^ self next: n into: aString. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNext: anInteger putAll: aCollection startingAt: startIndex [ - - ^super next: anInteger putAll: aCollection startingAt: startIndex -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNextInto: aString [ - - ^ self nextInto: aString. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNextPut: char [ - - ^ super nextPut: char. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicNextPutAll: aString [ - - ^ super nextPutAll: aString. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicPeek [ - - ^ super peek - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicPosition [ - - ^ self position. - -] - -{ #category : #private } -MultiByteBinaryOrTextStream >> basicPosition: pos [ - - ^ self position: pos. - -] - -{ #category : #modes } -MultiByteBinaryOrTextStream >> binary [ - isBinary := true - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> contents [ - - | ret state | - state := converter saveStateOf: self. - ret := self upToEnd. - converter restoreStateOf: self with: state. - ^ ret. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> converter [ - - converter ifNil: [converter := self class defaultConverter]. - ^ converter - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> converter: aConverter [ - - converter := aConverter. - -] - -{ #category : #testing } -MultiByteBinaryOrTextStream >> isBinary [ - ^ isBinary -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> next [ - - | n | - n := self converter nextFromStream: self. - n ifNil: [^ nil]. - isBinary and: [n isCharacter ifTrue: [^ n asciiValue]]. - ^ n. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> next: anInteger [ - - | multiString | - self isBinary ifTrue: [^ (super next: anInteger) asByteArray]. - multiString := WideString new: anInteger. - 1 to: anInteger do: [:index | - | character | - (character := self next) ifNotNil: [ - multiString at: index put: character - ] ifNil: [ - multiString := multiString copyFrom: 1 to: index - 1. - ^ multiString - ] - ]. - ^ multiString. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> next: anInteger putAll: aCollection startingAt: startIndex [ - - - (self isBinary or: [ aCollection class == ByteArray ]) ifTrue: [ - ^super next: anInteger putAll: aCollection startingAt: startIndex ]. - ^self converter next: anInteger putAll: aCollection startingAt: startIndex toStream: self -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> nextDelimited: terminator [ - - | out ch pos | - out := (String new: 1000) writeStream. - self atEnd ifTrue: [^ '']. - pos := self position. - self next = terminator ifFalse: [ - "absorb initial terminator" - self position: pos. - ]. - [(ch := self next) == nil] whileFalse: [ - (ch = terminator) ifTrue: [ - self peek = terminator ifTrue: [ - self next. "skip doubled terminator" - ] ifFalse: [ - ^ out contents "terminator is not doubled; we're done!" - ]. - ]. - out nextPut: ch. - ]. - ^ out contents. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> nextMatchAll: aColl [ - - | save | - save := converter saveStateOf: self. - aColl do: [:each | - (self next) = each ifFalse: [ - converter restoreStateOf: self with: save. - ^ false. - ]. - ]. - ^ true. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> nextPut: aCharacter [ - ^ aCharacter isInteger - ifTrue: [ super nextPut: aCharacter asCharacter ] - ifFalse: [ self converter nextPut: aCharacter toStream: self ] -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> nextPutAll: aCollection [ - ^ self isBinary - ifTrue: [ super nextPutAll: aCollection ] - ifFalse: [ aCollection do: [ :each | self nextPut: each ] ] -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> padToEndWith: aChar [ - "We don't have pages, so we are at the end, and don't need to pad." -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> peek [ - "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. " - - | next pos | - self atEnd ifTrue: [^ nil]. - pos := self position. - next := self next. - self position: pos. - ^ next. - - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> peekFor: item [ - - | next state | - "self atEnd ifTrue: [^ false]. -- SFStream will give nil" - state := converter saveStateOf: self. - (next := self next) == nil ifTrue: [^ false]. - item = next ifTrue: [^ true]. - converter restoreStateOf: self with: state. - ^ false. - -] - -{ #category : #initialization } -MultiByteBinaryOrTextStream >> reset [ - - super reset. - isBinary ifNil: [isBinary := false]. - collection class == ByteArray ifTrue: ["Store as String and convert as needed." - collection := collection asString. - isBinary := true]. - - self converter. "ensure that we have a converter." -] - -{ #category : #'file in/out' } -MultiByteBinaryOrTextStream >> setConverterForCode [ - - | current | - current := converter saveStateOf: self. - self position: 0. - self binary. - ((self next: 3) = #[239 187 191]) ifTrue: [ - self converter: UTF8TextConverter new - ] ifFalse: [ - self converter: MacRomanTextConverter new. - ]. - converter restoreStateOf: self with: current. - self text. - -] - -{ #category : #'file in/out' } -MultiByteBinaryOrTextStream >> setEncoderForSourceCodeNamed: streamName [ - - | l | - l := streamName asLowercase. - ((l endsWith: 'cs') or: [ - (l endsWith: 'st') or: [ - (l endsWith: ('st.gz')) or: [ - (l endsWith: ('st.gz'))]]]) ifTrue: [ - self converter: MacRomanTextConverter new. - ^ self. - ]. - self converter: UTF8TextConverter new. - -] - -{ #category : #positioning } -MultiByteBinaryOrTextStream >> skipSeparators [ - - [self atEnd] whileFalse: [ - self basicNext isSeparator ifFalse: [ - ^ self position: self position - 1]] - - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> skipSeparatorsAndPeekNext [ - - "A special function to make nextChunk fast" - | peek pos | - [self atEnd] whileFalse: [ - pos := self position. - (peek := self next) isSeparator ifFalse: [ - self position: pos. - ^ peek. - ]. - ]. - -] - -{ #category : #modes } -MultiByteBinaryOrTextStream >> text [ - isBinary := false - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> upTo: delim [ - - | out ch | - out := (String new: 1000) writeStream. - self atEnd ifTrue: [^ '']. - [(ch := self next) isNil] whileFalse: [ - (ch = delim) ifTrue: [ - ^ out contents "terminator is not doubled; we're done!" - ]. - out nextPut: ch. - ]. - ^ out contents. - -] - -{ #category : #accessing } -MultiByteBinaryOrTextStream >> upToEnd [ - - | newStream element newCollection | - newCollection := self isBinary - ifTrue: [ByteArray new: 100] - ifFalse: [String new: 100]. - newStream := newCollection writeStream. - [(element := self next) notNil] - whileTrue: [newStream nextPut: element]. - ^ newStream contents - -] diff --git a/src/DeprecatedFileStream/MultiByteFileStream.class.st b/src/DeprecatedFileStream/MultiByteFileStream.class.st deleted file mode 100644 index a4a43374175..00000000000 --- a/src/DeprecatedFileStream/MultiByteFileStream.class.st +++ /dev/null @@ -1,742 +0,0 @@ -" -The central class to access the external file. The interface of this object is similar to good old StandardFileStream, but internally it asks the converter, which is a sub-instance of TextConverter, and do the text conversion. - - It also combined the good old CrLfFileStream. CrLfFileStream class>>new now returns an instance of MultiByteFileStream. - - There are several pitfalls: - - * You always have to be careful about the binary/text distinction. In #text mode, it usually interpret the bytes. - * A few file pointer operations treat the file as uninterpreted byte no matter what. This means that if you use 'fileStream skip: -1', 'fileStream position: x', etc. in #text mode, the file position can be in the middle of multi byte character. If you want to implement some function similar to #peek for example, call the saveStateOf: and restoreStateOf: methods to be able to get back to the original state. - * #lineEndConvention: and #wantsLineEndConversion: (and #binary) can cause some puzzling situation because the inst var lineEndConvention and wantsLineEndConversion are mutated. If you have any suggestions to clean up the protocol, please let me know. -" -Class { - #name : #MultiByteFileStream, - #superclass : #StandardFileStream, - #instVars : [ - 'converter', - 'lineEndConvention', - 'wantsLineEndConversion' - ], - #classVars : [ - 'Cr', - 'CrLf', - 'Lf', - 'LineEndDefault', - 'LineEndStrings', - 'LookAheadCount' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #defaults } -MultiByteFileStream class >> defaultToCR [ - - "MultiByteFileStream defaultToCR" - LineEndDefault := #cr. - -] - -{ #category : #defaults } -MultiByteFileStream class >> defaultToCRLF [ - - "MultiByteFileStream defaultToCRLF" - LineEndDefault := #crlf. -] - -{ #category : #defaults } -MultiByteFileStream class >> defaultToLF [ - - "MultiByteFileStream defaultToLF" - LineEndDefault := #lf. - -] - -{ #category : #defaults } -MultiByteFileStream class >> guessDefaultLineEndConvention [ - "Lets try to guess the line end convention from what we know about the - path name delimiter from FileDirectory." - - FileSystem disk delimiter = $: - ifTrue: [^ self defaultToCR]. - - FileSystem disk delimiter = $/ - ifTrue: [^ (Smalltalk os isMacOSX or: [Smalltalk os isUnix]) - ifTrue: [ self defaultToLF] - ifFalse: [ self defaultToCR]]. - - FileSystem disk delimiter = $\ - ifTrue: [^ self defaultToCRLF]. - - "in case we don't know" - ^ self defaultToCR -] - -{ #category : #'class initialization' } -MultiByteFileStream class >> 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. - - SessionManager default registerSystemClassNamed: self name. - self startUp. - -] - -{ #category : #accessing } -MultiByteFileStream class >> lineEndDefault [ - "Answer the default line-ending convention that will be used by default, which was determined at start-up by looking at platform attributes." - ^ LineEndDefault - -] - -{ #category : #'instance creation' } -MultiByteFileStream class >> newFrom: aFileStream [ - - | rw n | - n := aFileStream name. - rw := aFileStream isReadOnly not. - aFileStream close. - ^self new open: n forWrite: rw. - -] - -{ #category : #'system startup' } -MultiByteFileStream class >> startUp [ - self guessDefaultLineEndConvention. - -] - -{ #category : #'system startup' } -MultiByteFileStream class >> startUp: resuming [ - self guessDefaultLineEndConvention. - -] - -{ #category : #remnant } -MultiByteFileStream >> accepts: aSymbol [ - - ^ converter accepts: aSymbol. - -] - -{ #category : #modes } -MultiByteFileStream >> ascii [ - - super ascii. - self detectLineEndConvention. - -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> bareNext [ - - ^ self converter nextFromStream: self. - -] - -{ #category : #'file in/out' } -MultiByteFileStream >> basicChunk [ - "If our buffer in collection contains an chunk with no embedded !'s, nor - any non-ascii characters, return that. - This presumes the source code encoding is unambiguously ascii-compatible" - | bufferIX goodString | - "Not possible if read buffering disabled" - collection ifNil: [^nil]. - ^ ((bufferIX := (collection indexOf: $! startingAt: position + 1) min: readLimit +1) > 0 - and: [bufferIX < collection size - and: [(collection at: bufferIX + 1) - ~= $! - and: [goodString := collection copyFrom: position + 1 to: bufferIX - 1. - goodString isAsciiString]]]) - ifTrue: [ position := bufferIX. - goodString] -] - -{ #category : #private } -MultiByteFileStream >> basicNext: anInteger [ - - ^ super next: anInteger. - -] - -{ #category : #private } -MultiByteFileStream >> basicNext: n into: aString [ - - ^ super next: n into: aString. - -] - -{ #category : #private } -MultiByteFileStream >> basicNext: anInteger putAll: aCollection startingAt: startIndex [ - - - ^super next: anInteger putAll: aCollection startingAt: startIndex -] - -{ #category : #private } -MultiByteFileStream >> basicNextInto: aString [ - - ^ super nextInto: aString. - -] - -{ #category : #private } -MultiByteFileStream >> basicNextPut: char [ - - ^ super nextPut: char. - -] - -{ #category : #private } -MultiByteFileStream >> basicNextPutAll: aString [ - - ^ super nextPutAll: aString. - -] - -{ #category : #private } -MultiByteFileStream >> basicPeek [ - - ^ super peek - -] - -{ #category : #private } -MultiByteFileStream >> basicPosition [ - - ^ super position. - -] - -{ #category : #private } -MultiByteFileStream >> basicPosition: pos [ - - ^ super position: pos. - -] - -{ #category : #private } -MultiByteFileStream >> basicReadInto: byteArray startingAt: startIndex count: count [ - - ^ super readInto: byteArray startingAt: startIndex count: count. - -] - -{ #category : #private } -MultiByteFileStream >> basicSetToEnd [ - - ^ super setToEnd. - -] - -{ #category : #private } -MultiByteFileStream >> basicSkip: n [ - - ^ super skip: n. - -] - -{ #category : #private } -MultiByteFileStream >> basicUpTo: delim [ - - ^ super upTo: delim. - -] - -{ #category : #private } -MultiByteFileStream >> basicVerbatim: aString [ - - ^ super verbatim: aString. - -] - -{ #category : #modes } -MultiByteFileStream >> binary [ - - super binary. - self lineEndConvention: nil -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> convertStringFromCr: aString [ - | inStream outStream | - lineEndConvention ifNil: [^ aString]. - lineEndConvention == #cr ifTrue: [^ aString]. - lineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Cr with: Lf]. - "lineEndConvention == #crlf" - inStream := aString readStream. - outStream := (String new: aString size) writeStream. - [inStream atEnd] - whileFalse: - [outStream nextPutAll: (inStream upTo: Cr). - (inStream atEnd not or: [aString last = Cr]) - ifTrue: [outStream nextPutAll: CrLf]]. - ^ outStream contents -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> convertStringToCr: aString [ - | inStream outStream | - lineEndConvention ifNil: [^ aString]. - lineEndConvention == #cr ifTrue: [^ aString]. - lineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Lf with: Cr]. - "lineEndConvention == #crlf" - inStream := aString readStream. - outStream := (String new: aString size) writeStream. - [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 -] - -{ #category : #accessing } -MultiByteFileStream >> converter [ - - converter ifNil: [self converter: TextConverter defaultSystemConverter]. - ^ converter - -] - -{ #category : #accessing } -MultiByteFileStream >> converter: aConverter [ - - converter := aConverter. - self installLineEndConventionInConverter - -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> detectLineEndConvention [ - "Detect the line end convention used in this stream. The result may be either #cr, #lf or #crlf." - | char numRead state | - self isBinary ifTrue: [^ self error: 'Line end conventions are not used on binary streams']. - wantsLineEndConversion == true ifFalse: [self lineEndConvention: nil. - ^lineEndConvention]. - self closed ifTrue: [self lineEndConvention: LineEndDefault. - ^lineEndConvention]. - - "Default if nothing else found" - numRead := 0. - state := self converter saveStateOf: self. - lineEndConvention := nil. - [super atEnd not and: [numRead < LookAheadCount]] - whileTrue: - [char := self next. - char = Lf - ifTrue: - [converter restoreStateOf: self with: state. - self lineEndConvention: #lf. - ^lineEndConvention]. - char = Cr - ifTrue: - [self peek = Lf - ifTrue: [self lineEndConvention: #crlf] - ifFalse: [self lineEndConvention: #cr]. - converter restoreStateOf: self with: state. - ^ lineEndConvention]. - numRead := numRead + 1]. - converter restoreStateOf: self with: state. - self lineEndConvention: LineEndDefault. - ^ lineEndConvention -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> doConversion [ - - ^wantsLineEndConversion == true and: [ lineEndConvention notNil ] -] - -{ #category : #accessing } -MultiByteFileStream >> fileInEncodingName: aString [ - - self converter: (TextConverter newForEncoding: aString). - super fileIn. - -] - -{ #category : #private } -MultiByteFileStream >> installLineEndConventionInConverter [ - - converter ifNotNil: [ - converter installLineEndConvention: ( - (wantsLineEndConversion == true and: [ lineEndConvention notNil ]) "#doConversion is inlined here" - ifTrue: [ LineEndStrings at: lineEndConvention ] - ifFalse: [ nil ]) ] -] - -{ #category : #accessing } -MultiByteFileStream >> lineEndConvention [ - - ^lineEndConvention -] - -{ #category : #accessing } -MultiByteFileStream >> lineEndConvention: aSymbol [ - - (lineEndConvention := aSymbol) ifNotNil: [wantsLineEndConversion := true]. - self installLineEndConventionInConverter -] - -{ #category : #accessing } -MultiByteFileStream >> next [ - - | char secondChar state | - char := (converter ifNil: [ self converter ]) nextFromStream: self. - (wantsLineEndConversion == true and: [ lineEndConvention notNil ]) "#doConversion is inlined here" - ifTrue: [ - char == Cr ifTrue: [ - state := converter saveStateOf: self. - secondChar := self bareNext. - secondChar ifNotNil: [ - secondChar == Lf ifFalse: [ converter restoreStateOf: self with: state ] ]. - ^Cr ]. - char == Lf ifTrue: [ - ^Cr ] ]. - ^char. - - -] - -{ #category : #accessing } -MultiByteFileStream >> next: anInteger [ - - | multiString | - self isBinary ifTrue: [^ super next: anInteger]. - multiString := String new: anInteger. - 1 to: anInteger do: [:index | - | character | - (character := self next) - ifNotNil: [ multiString at: index put: character ] - ifNil: [ - multiString := multiString copyFrom: 1 to: index - 1. - (wantsLineEndConversion == true and: [ lineEndConvention notNil ]) "#doConversion is inlined here" - ifFalse: [ ^multiString ]. - ^self next: anInteger innerFor: multiString ] ]. - (wantsLineEndConversion == true and: [ lineEndConvention notNil ]) "#doConversion is inlined here" - ifFalse: [ ^multiString ]. - - multiString := self next: anInteger innerFor: multiString. - (multiString size = anInteger or: [self atEnd]) ifTrue: [ ^ multiString]. - ^ multiString, (self next: anInteger - multiString size). - -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> next: n innerFor: aString [ - - | peekChar state | - "if we just read a CR, and the next character is an LF, then skip the LF" - aString size = 0 ifTrue: [^ aString]. - (aString last = Character cr) ifTrue: [ - state := converter saveStateOf: self. - peekChar := self bareNext. "super peek doesn't work because it relies on #next" - (peekChar notNil and: [peekChar ~= Character lf]) ifTrue: [ - converter restoreStateOf: self with: state. - ]. - ]. - - ^ aString withInternalLineEndings. - -] - -{ #category : #accessing } -MultiByteFileStream >> next: anInteger putAll: aCollection startingAt: startIndex [ - - - (self isBinary or: [ aCollection class == ByteArray ]) ifTrue: [ - ^super next: anInteger putAll: aCollection startingAt: startIndex ]. - ^self converter next: anInteger putAll: aCollection startingAt: startIndex toStream: self -] - -{ #category : #'file in/out' } -MultiByteFileStream >> nextChunk [ - "Answer the contents of the receiver, up to the next terminator - character. Doubled terminators indicate an embedded terminator - character." - self skipSeparators. - ^ self - parseLangTagFor: (self basicChunk - ifNil: [String - new: 1000 - streamContents: [:stream | - | character state | - [(character := self next) == nil - or: [character == $! - and: [state := converter saveStateOf: self. - self next ~~ $!]]] - whileFalse: [stream nextPut: character]. - character - ifNotNil: [converter restoreStateOf: self with: state.]]]) -] - -{ #category : #accessing } -MultiByteFileStream >> nextDelimited: terminator [ - - | out ch save | - out := (String new: 1000) writeStream. - self atEnd ifTrue: [^ '']. - save := converter saveStateOf: self. - - self next = terminator ifFalse: [ - "absorb initial terminator" - converter restoreStateOf: self with: save. - ]. - [(ch := self next) == nil] whileFalse: [ - (ch = terminator) ifTrue: [ - self peek = terminator ifTrue: [ - self next. "skip doubled terminator" - ] ifFalse: [ - ^ out contents "terminator is not doubled; we're done!" - ]. - ]. - out nextPut: ch. - ]. - ^ out contents. - -] - -{ #category : #accessing } -MultiByteFileStream >> nextMatchAll: aColl [ - - | save | - save := converter saveStateOf: self. - aColl do: [:each | - (self next) = each ifFalse: [ - converter restoreStateOf: self with: save. - ^ false. - ]. - ]. - ^ true. - -] - -{ #category : #'file in/out' } -MultiByteFileStream >> nextPreamble [ - "Assuming that preamble part does not contain ]lang[ tag" - self skipSeparators. - ^ self basicChunk - ifNil: [String - new: 1000 - streamContents: [:stream | - | character state | - [(character := self next) == nil - or: [character == $! - and: [state := converter saveStateOf: self. - self next ~~ $!]]] - whileFalse: [stream nextPut: character]. - character - ifNotNil: [converter restoreStateOf: self with: state.]]] -] - -{ #category : #accessing } -MultiByteFileStream >> nextPut: aCharacter [ - aCharacter isInteger - ifTrue: [ ^ super nextPut: aCharacter ]. - (wantsLineEndConversion == true and: [ lineEndConvention notNil ]) "#doConversion is inlined here" - ifTrue: [ - aCharacter = Cr - ifTrue: [ converter nextPutAll: (LineEndStrings at: lineEndConvention) toStream: self ] - ifFalse: [ converter nextPut: aCharacter toStream: self ]. - ^aCharacter ]. - ^ self converter nextPut: aCharacter toStream: self - -] - -{ #category : #accessing } -MultiByteFileStream >> nextPutAll: aCollection [ - ^ (self isBinary or: [ aCollection class == ByteArray ]) - ifTrue: [ super nextPutAll: aCollection ] - ifFalse: [ self converter nextPutAll: aCollection toStream: self ] -] - -{ #category : #'open/close' } -MultiByteFileStream >> open: fileName forWrite: writeMode [ - | result | - - (writeMode and: [SessionManager default currentSession isReadOnlyAccessMode]) - ifTrue: [ ((CannotDeleteFileException fileName: fileName) - messageText: 'Attempt to open file ' , fileName, ' as writable on read-only filesystem') signal. ]. - - result := super open: fileName forWrite: writeMode. - result ifNotNil: [ - converter ifNil: [self converter: UTF8TextConverter new]. - lineEndConvention ifNil: [ self detectLineEndConvention ] - ]. - ^result -] - -{ #category : #accessing } -MultiByteFileStream >> peek [ - "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. " - - | next save | - self atEnd ifTrue: [^ nil]. - save := converter saveStateOf: self. - next := self next. - converter restoreStateOf: self with: save. - ^ next. - - -] - -{ #category : #accessing } -MultiByteFileStream >> peekFor: item [ - - | next state | - state := converter saveStateOf: self. - (next := self next) == nil ifTrue: [^ false]. - item = next ifTrue: [^ true]. - converter restoreStateOf: self with: state. - ^ false. - -] - -{ #category : #accessing } -MultiByteFileStream >> readInto: buffer startingAt: offset count: requestedCount [ - "Read up to requestedCount elements into the given buffer starting at offset. - Return the number of elements actually read. - If I am binary or if buffer is a ByteArray, I skip decoding. Yes this is weird. - This is a necessarily inefficient implementation, reading and decoding characters one by one." - - (self isBinary or: [ buffer class == ByteArray ]) - ifTrue: [ ^ super readInto: buffer startingAt: offset count: requestedCount ]. - 0 to: requestedCount - 1 do: [ :count | - | element | - (element := self next) ifNil: [ ^ count ]. - buffer at: offset + count put: element ]. - ^ requestedCount -] - -{ #category : #private } -MultiByteFileStream >> requestDropStream: dropIndex [ - "Needs to install proper converter" - - | result | - result := super requestDropStream: dropIndex. - result ifNotNil: [ - converter ifNil: [self converter: UTF8TextConverter new]. - lineEndConvention ifNil: [ self detectLineEndConvention] ]. - ^result -] - -{ #category : #initialization } -MultiByteFileStream >> reset [ - - super reset. - converter ifNil: [ - self converter: UTF8TextConverter new. - ]. - -] - -{ #category : #private } -MultiByteFileStream >> setConverterForCode [ - - | current | - SourceFiles changesFileStream ifNotNil: [ :aStream | - self fullName = aStream fullName ifTrue: [ ^ self ] ]. - current := self converter saveStateOf: self. - self position: 0. - self binary. - ((self next: 3) = #[ 16rEF 16rBB 16rBF ]) ifTrue: [ - self converter: UTF8TextConverter new - ] ifFalse: [ - self converter: MacRomanTextConverter new. - ]. - converter restoreStateOf: self with: current. - self text. - -] - -{ #category : #positioning } -MultiByteFileStream >> skipSeparators [ - - | state character | - [ - state := converter saveStateOf: self. - (character := self next) - ifNil: [ false ] - ifNotNil: [ character isSeparator ] ] whileTrue. - character ifNotNil: [ - converter restoreStateOf: self with: state ] -] - -{ #category : #accessing } -MultiByteFileStream >> skipSeparatorsAndPeekNext [ - "Same as #skipSeparators, but returns the next character after the separators if such exists." - - | state character | - [ - state := converter saveStateOf: self. - (character := self next) - ifNil: [ false ] - ifNotNil: [ character isSeparator ] ] whileTrue. - character ifNotNil: [ - converter restoreStateOf: self with: state. - ^character ]. - -] - -{ #category : #accessing } -MultiByteFileStream >> upTo: delimiter [ - - ^self collectionSpecies new: 1000 streamContents: [ :stream | - | ch | - [ (ch := self next) == nil or: [ ch = delimiter ] ] - whileFalse: [ stream nextPut: ch ] ] - -] - -{ #category : #accessing } -MultiByteFileStream >> upToAnyOf: delimiters do: aBlock [ - - ^self collectionSpecies new: 1000 streamContents: [ :stream | - | ch | - [ (ch := self next) == nil or: [ (delimiters includes: ch) and: [aBlock value: ch. true] ] ] - whileFalse: [ stream nextPut: ch ] ] -] - -{ #category : #accessing } -MultiByteFileStream >> upToEnd [ - - ^self collectionSpecies - new: self size - self position - streamContents: [ :stream | - | element | - [ (element := self next) == nil ] whileFalse: [ - stream nextPut: element ] ] - -] - -{ #category : #accessing } -MultiByteFileStream >> upToPosition: anInteger [ - "Answer a subcollection containing items starting from the current position and ending including the given position. Usefully different to #next: in that positions measure *bytes* from the file, where #next: wants to measure *characters*." - ^self collectionSpecies new: 1000 streamContents: [ :stream | - | ch | - [ (ch := self next) == nil or: [ position > anInteger ] ] - whileFalse: [ stream nextPut: ch ] ] -] - -{ #category : #'private - crlf' } -MultiByteFileStream >> wantsLineEndConversion [ - - ^wantsLineEndConversion == true - -] - -{ #category : #remnant } -MultiByteFileStream >> wantsLineEndConversion: aBoolean [ - - wantsLineEndConversion := aBoolean. - - lineEndConvention ifNil: [ self detectLineEndConvention ]. -] diff --git a/src/DeprecatedFileStream/PositionableStream.extension.st b/src/DeprecatedFileStream/PositionableStream.extension.st deleted file mode 100644 index 5d20c69f75c..00000000000 --- a/src/DeprecatedFileStream/PositionableStream.extension.st +++ /dev/null @@ -1,8 +0,0 @@ -Extension { #name : #PositionableStream } - -{ #category : #'*DeprecatedFileStream' } -PositionableStream >> asBinaryOrTextStream [ - "Convert to a stream that can switch between bytes and characters" - - ^ (RWBinaryOrTextStream with: self contentsOfEntireFile) reset -] diff --git a/src/DeprecatedFileStream/RWBinaryOrTextStream.class.st b/src/DeprecatedFileStream/RWBinaryOrTextStream.class.st deleted file mode 100644 index 6a7c6683452..00000000000 --- a/src/DeprecatedFileStream/RWBinaryOrTextStream.class.st +++ /dev/null @@ -1,179 +0,0 @@ -" -A simulation of a FileStream, but living totally in memory. Hold the contents of a file or web page from the network. Can then fileIn like a normal FileStream. - -Need to be able to switch between binary and text, as a FileStream does, without recopying the whole collection. Convert to binary upon input and output. Always keep as text internally. -" -Class { - #name : #RWBinaryOrTextStream, - #superclass : #ReadWriteStream, - #instVars : [ - 'isBinary' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #deprecation } -RWBinaryOrTextStream class >> isDeprecated [ - ^true -] - -{ #category : #converting } -RWBinaryOrTextStream >> asBinaryOrTextStream [ - - ^ self -] - -{ #category : #modes } -RWBinaryOrTextStream >> ascii [ - isBinary := false -] - -{ #category : #modes } -RWBinaryOrTextStream >> binary [ - isBinary := true -] - -{ #category : #accessing } -RWBinaryOrTextStream >> contents [ - "Answer with a copy of my collection from 1 to readLimit." - - | newArray | - readLimit := readLimit max: position. - isBinary ifFalse: [ "String" - ^ collection copyFrom: 1 to: readLimit]. - newArray := ByteArray new: readLimit. - ^ newArray replaceFrom: 1 - to: readLimit - with: collection - startingAt: 1. -] - -{ #category : #testing } -RWBinaryOrTextStream >> isBinary [ - ^ isBinary -] - -{ #category : #accessing } -RWBinaryOrTextStream >> next [ - | byte | - ^ isBinary - ifTrue: [ byte := super next. - byte ifNotNil: [ byte asciiValue ] ] - ifFalse: [ super next ] -] - -{ #category : #accessing } -RWBinaryOrTextStream >> next: anInteger [ - "Answer the next anInteger elements of my collection. Must override to get class right." - - | newArray | - newArray := (isBinary ifTrue: [ByteArray] ifFalse: [ByteString]) new: anInteger. - ^ self nextInto: newArray -] - -{ #category : #accessing } -RWBinaryOrTextStream >> next: n into: aCollection startingAt: startIndex [ - "Read n objects into the given collection. - Return aCollection or a partial copy if less than n elements have been read." - - "Overriden for efficiency" - - | max | - max := readLimit - position min: n. - aCollection - replaceFrom: startIndex - to: startIndex + max - 1 - with: collection - startingAt: position + 1. - position := position + max. - ^ max = n - ifTrue: [ aCollection ] - ifFalse: [ aCollection copyFrom: 1 to: startIndex + max - 1 ] -] - -{ #category : #accessing } -RWBinaryOrTextStream >> next: anInteger putAll: aCollection startingAt: startIndex [ - "Optimized for ByteArrays" - aCollection class == ByteArray - ifTrue:[^super next: anInteger putAll: aCollection asString startingAt: startIndex]. - ^super next: anInteger putAll: aCollection startingAt: startIndex -] - -{ #category : #accessing } -RWBinaryOrTextStream >> nextPut: charOrByte [ - ^ super nextPut: charOrByte asCharacter -] - -{ #category : #accessing } -RWBinaryOrTextStream >> nextPutAll: aCollection [ - "Optimized for ByteArrays" - ^ aCollection class == ByteArray - ifTrue: [ super nextPutAll: aCollection asString ] - ifFalse: [ super nextPutAll: aCollection ] -] - -{ #category : #converting } -RWBinaryOrTextStream >> on: aCollection [ - - super on: aCollection. - readLimit := 0 -] - -{ #category : #accessing } -RWBinaryOrTextStream >> padToEndWith: aChar [ - "We don't have pages, so we are at the end, and don't need to pad." -] - -{ #category : #accessing } -RWBinaryOrTextStream >> readInto: aCollection startingAt: startIndex count: n [ - "Read n objects into the given collection. - Return number of elements that have been read." - "Overriden for efficiency" - | max | - max := (readLimit - position) min: n. - aCollection - replaceFrom: startIndex - to: startIndex + max - 1 - with: collection - startingAt: position + 1. - position := position + max. - ^ max -] - -{ #category : #initialization } -RWBinaryOrTextStream >> reset [ - "Set the receiver's position to the beginning of the sequence of objects." - - super reset. - isBinary ifNil: [isBinary := false]. - collection class == ByteArray ifTrue: ["Store as String and convert as needed." - collection := collection asString. - isBinary := true]. - -] - -{ #category : #modes } -RWBinaryOrTextStream >> text [ - isBinary := false -] - -{ #category : #accessing } -RWBinaryOrTextStream >> upTo: anObject [ - "Answer a subcollection from the current access position to the - occurrence (if any, but not inclusive) of anObject in the receiver. If - anObject is not in the collection, answer the entire rest of the receiver." - | newStream element species | - species := isBinary ifTrue:[ByteArray] ifFalse:[String]. - newStream := WriteStream on: (species new: 100). - [self atEnd or: [(element := self next) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents -] - -{ #category : #accessing } -RWBinaryOrTextStream >> upToEnd [ - "Must override to get class right." - | newArray | - newArray := (isBinary ifTrue: [ByteArray] ifFalse: [ByteString]) new: self size - self position. - ^ self nextInto: newArray -] diff --git a/src/DeprecatedFileStream/StandardFileStream.class.st b/src/DeprecatedFileStream/StandardFileStream.class.st deleted file mode 100644 index 25d0a33064f..00000000000 --- a/src/DeprecatedFileStream/StandardFileStream.class.st +++ /dev/null @@ -1,1027 +0,0 @@ -" -Provides a simple, platform-independent, interface to a file system. The instance variable rwmode, inherited from class PositionableStream, here is used to hold a Boolean -- true means opened for read-write, false means opened for read-only. 2/12/96 sw - -I implement a simple read buffering scheme with the variables defined in PositionableStream (which are unused in me otherwise) in the following way: - collection or This is the buffer. - position The relative position in the buffer. Greater or equal to zero. - readLimit The number of bytes buffered. Greater or equal to zero. -Read buffering is enabled with #enableReadBuffering, disabled with #disableReadBuffering and it is enabled by default. The buffer is filled when a read attempt of an unbuffered absolute position is requested, or when a negative repositioning is made (with #position: with an argument < than the current absolute position) to an absolute position which is not buffered. In the first case, the buffer is positioned to the given absolute position. In the latter case the repositioning is made to the requested absolute position minus fourth of the buffer size. This means that further small negative repositionings won't result in buffer flushing. This is really useful when filing in code. -The read buffer is flushed (#flushReadBuffer) whenever a write attempt is made. -The buffer state is valid if and only if collection is not nil and position < readLimit. -" -Class { - #name : #StandardFileStream, - #superclass : #FileStream, - #instVars : [ - 'name', - 'fileID', - 'buffer1', - 'rwmode' - ], - #classVars : [ - 'Registry' - ], - #category : #'DeprecatedFileStream-Base' -} - -{ #category : #'error handling' } -StandardFileStream class >> fileDoesNotExistUserHandling: fullFileName [ - | selection newName | - selection := UIManager default - chooseFrom: - {('create a new file' translated). - ('choose another name' translated). - ('cancel' translated)} - title: fullFileName asFileReference basename , ' does not exist.'. - selection = 1 - ifTrue: [ ^ self new open: fullFileName forWrite: true ]. - selection = 2 - ifFalse: [ ^ self ]. - newName := UIManager default request: 'Enter a new file name' initialAnswer: fullFileName. - ^ self oldFileNamed: (self fullName: newName) -] - -{ #category : #'error handling' } -StandardFileStream class >> fileExistsUserHandling: fullFileName [ - | file localName choice newName newFullFileName | - - file := fullFileName asFileReference. - localName := file basename. - choice := UIManager default chooseFrom:{ - 'overwrite that file'. - 'choose another name'. - 'cancel' - } title: localName, ' already exists.'. - - choice = 1 ifTrue: [ - file delete. - file exists ifTrue: [self error: 'Could not delete the old version of that file']. - ^ self new open: fullFileName forWrite: true]. - - choice = 2 ifTrue: [ - newName := UIManager default request: 'Enter a new file name' initialAnswer: fullFileName. - newName ifNil: [Abort signal]. - newFullFileName := self fullName: newName. - ^ self newFileNamed: newFullFileName]. - - Abort signal: 'Please close this to abort file opening' -] - -{ #category : #'file creation' } -StandardFileStream class >> fileNamed: fileName [ - "Open a file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close." - - ^ self new open: (self fullName: fileName) forWrite: true - -] - -{ #category : #'file creation' } -StandardFileStream class >> forceNewFileNamed: fileName [ - "Create a new file with the given name, and answer a stream opened - for writing on that file. If the file already exists, delete it without - asking before creating the new file." - | dir fullName f | - - SessionManager default currentSession isReadOnlyAccessMode ifTrue: [ ((CannotDeleteFileException fileName: fileName) - messageText: 'Could not delete the old version of file ' , fileName) signal. - ^ NullStream new ]. - - fullName := self fullName: fileName. - (self isAFileNamed: fullName) - ifFalse: [f := self new open: fullName forWrite: true. - ^ f ifNil: ["Failed to open the file" - (FileDoesNotExistException fileName: fullName) signal]]. - - dir := fullName asFileReference. - dir delete. - dir exists ifTrue: [(CannotDeleteFileException new - messageText: 'Could not delete the old version of file ' , fullName) signal]. - - f := self new open: fullName forWrite: true. - ^ f ifNil: ["Failed to open the file" - (FileDoesNotExistException fileName: fullName) signal]. -] - -{ #category : #'file creation' } -StandardFileStream class >> isAFileNamed: fileName [ - "Answer true if a file of the given name exists." - - | f | - f := self new open: fileName forWrite: false. - f ifNil: [^ false]. - f close. - ^ true - -] - -{ #category : #'file creation' } -StandardFileStream class >> newFileNamed: fileName [ - "Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, ask the user what to do." - - | fullName | - fullName := self fullName: fileName. - - ^(self isAFileNamed: fullName) - ifTrue: ["file already exists:" - (FileExistsException fileName: fullName fileClass: self) signal] - ifFalse: [self new open: fullName forWrite: true] - - -] - -{ #category : #'file creation' } -StandardFileStream class >> oldFileNamed: fileName [ - "Open an existing file with the given name for reading and writing. If the name has no directory part, then the default directory will be assumed. If the file does not exist, an exception is signaled. If the file exists, its prior contents may be modified or replaced, but the file will not be truncated on close." - - | fullName | - fullName := self fullName: fileName. - - ^(self isAFileNamed: fullName) - ifTrue: [self new open: fullName forWrite: true] - ifFalse: ["File does not exist..." - (FileDoesNotExistException fileName: fullName) signal] -] - -{ #category : #'error handling' } -StandardFileStream class >> readOnlyFileDoesNotExistUserHandling: fullFileName [ - - | dir files choices selection newName fileName | - - dir := fullFileName asFileReference. - files := dir parent fileNames. - fileName := dir basename. - - choices := fileName correctAgainst: files. - choices add: 'Choose another name'. - choices add: 'Cancel'. - - selection := UIManager default chooseFrom: choices lines: (Array with: 5) - title: (fullFileName asFileReference basename), ' does not exist.'. - - selection = choices size ifTrue:["cancel" ^ nil "should we raise another exception here?"]. - selection < (choices size - 1) ifTrue: [ - newName := dir parent / (choices at: selection)]. - selection = (choices size - 1) ifTrue: [ - newName := UIManager default - request: 'Enter a new file name' - initialAnswer: fileName]. - newName = '' ifFalse: [^ self readOnlyFileNamed: (self fullName: newName)]. - ^ self error: 'Could not open a file' -] - -{ #category : #'file creation' } -StandardFileStream class >> readOnlyFileNamed: fileName [ - "Open an existing file with the given name for reading." - - | fullName f | - fullName := self fullName: fileName. - f := self new open: fullName forWrite: false. - ^ f ifNil: ["File does not exist..." - ((FileDoesNotExistException fileName: fullName) readOnly: true) signal]. - - "StandardFileStream readOnlyFileNamed: 'kjsd.txt' " -] - -{ #category : #registry } -StandardFileStream class >> register: anObject [ - ^self registry add: anObject -] - -{ #category : #registry } -StandardFileStream class >> registry [ - ^Registry ifNil: [Registry := WeakRegistry new] - -] - -{ #category : #registry } -StandardFileStream class >> retryWithGC: execBlock until: testBlock forFileNamed: fullName [ - "Re-implemented to only force GC if a file with the given name exists" - | blockValue foundIt | - blockValue := execBlock value. - (testBlock value: blockValue) ifTrue:[^blockValue]. - "See if we have a file with the given name" - foundIt := self registry keys "hold on strongly for now" - anySatisfy:[:file| file name sameAs: fullName]. - foundIt ifFalse:[^blockValue]. - Smalltalk garbageCollectMost. - blockValue := execBlock value. - (testBlock value: blockValue) ifTrue:[^blockValue]. - Smalltalk garbageCollect. - ^execBlock value. -] - -{ #category : #registry } -StandardFileStream class >> unregister: anObject [ - ^self registry remove: anObject ifAbsent:[] -] - -{ #category : #finalization } -StandardFileStream >> actAsExecutor [ - super actAsExecutor. - name := nil. -] - -{ #category : #modes } -StandardFileStream >> ascii [ - "opposite of binary" - buffer1 := String new: 1. - collection ifNotNil: [ collection := collection asString ] -] - -{ #category : #testing } -StandardFileStream >> atEnd [ - "Answer whether the receiver is at its end. " - - collection ifNotNil: [ - position < readLimit ifTrue: [ ^false ] ]. - ^self primAtEnd: fileID -] - -{ #category : #private } -StandardFileStream >> basicNext [ - "Answer the next byte from this file, or nil if at the end of the file." - - | count | - collection - ifNotNil: [ position < readLimit - ifFalse: [ readLimit := self - primRead: fileID - into: collection - startingAt: 1 - count: collection size. - position := 0. - readLimit = 0 ifTrue: [ ^ nil ] ]. - ^ collection at: (position := position + 1) ]. - count := self - primRead: fileID - into: buffer1 - startingAt: 1 - count: 1. - ^ count = 1 - ifTrue: [ buffer1 at: 1 ] - ifFalse: [ nil ] -] - -{ #category : #modes } -StandardFileStream >> binary [ - buffer1 := ByteArray new: 1. - collection ifNotNil: [ collection := collection asByteArray ] -] - -{ #category : #'open/close' } -StandardFileStream >> close [ - "Close this file." - - fileID ifNotNil: [ - collection ifNotNil: [ - readLimit := position := 0 ]. - self primClose: fileID. - self unregister. - fileID := nil]. - -] - -{ #category : #testing } -StandardFileStream >> closed [ - "Answer true if this file is closed." - - ^ fileID == nil or: [ (self primSizeNoError: fileID) == nil ] - -] - -{ #category : #private } -StandardFileStream >> collectionSpecies [ - "Answer the species of collection into which the receiver can stream" - - ^buffer1 species -] - -{ #category : #accessing } -StandardFileStream >> directory [ - "Return the directory containing this file." - - ^ self fullName asFileReference parent - -] - -{ #category : #private } -StandardFileStream >> disableReadBuffering [ - - collection ifNotNil: [ - position < readLimit - ifTrue: [ - | currentPosition | - currentPosition := self position. - collection := readLimit := position := nil. - self position: currentPosition ] - ifFalse: [ - collection := readLimit := position := nil ] ] - -] - -{ #category : #private } -StandardFileStream >> enableReadBuffering [ - - collection ifNil: [ - buffer1 ifNotNil: [ - collection := self collectionSpecies new: 2048 ] ]. - readLimit := position := 0 -] - -{ #category : #'open/close' } -StandardFileStream >> ensureOpen [ - "Make sure that this file really is open." - - self closed ifTrue: [^ self reopen]. - (self primSizeNoError: fileID) ifNotNil: [^ self]. - self reopen. - -] - -{ #category : #accessing } -StandardFileStream >> file [ - "Answer the object representing the receiver's file. Need for compatibility with some calls -- check senders. " - - ^ self -] - -{ #category : #finalization } -StandardFileStream >> finalize [ - self primCloseNoError: fileID. -] - -{ #category : #accessing } -StandardFileStream >> findString: string [ - "Fast version of #upToAll: to find a String in a file starting from the beginning. - Returns the position and also sets the position there. - If string is not found 0 is returned and position is unchanged." - - | pos buffer count oldPos sz | - oldPos := self position. - self reset. - sz := self size. - pos := 0. - buffer := String new: 2000. - [ buffer := self nextInto: buffer. - (count := buffer findString: string) > 0 - ifTrue: ["Found the string part way into buffer" - self position: pos. - self next: count - 1. - ^self position ]. - pos := ((pos + 2000 - string size) min: sz). - self position: pos. - pos = sz] whileFalse. - "Never found it, and hit end of file" - self position: oldPos. - ^0 -] - -{ #category : #accessing } -StandardFileStream >> findStringFromEnd: string [ - "Fast version to find a String in a file starting from the end. - Returns the position and also sets the position there. - If string is not found 0 is returned and position is unchanged." - - | pos buffer count oldPos | - oldPos := self position. - self setToEnd. - pos := self position. - [ pos := ((pos - 2000 + string size) max: 0). "the [+ string size] allows for the case where the end of the search string is at the beginning of the current buffer" - self position: pos. - buffer := self next: 2000. - (count := buffer findString: string) > 0 - ifTrue: ["Found the string part way into buffer" - self position: pos. - self next: count-1. "use next instead of position:, so that CrLfFileStream can do its magic if it is being used" - ^self position]. - pos = 0] whileFalse. - "Never found it, and hit beginning of file" - self position: oldPos. - ^0 -] - -{ #category : #flushing } -StandardFileStream >> flush [ - "When writing, this flushes the write buffer the stream uses to reduce - the number of write() system calls it makes. This should generally be - used before #sync, but on Windows they do the same thing." - - ^ self primFlush: fileID -] - -{ #category : #private } -StandardFileStream >> flushReadBuffer [ - - collection ifNotNil: [ - position < readLimit ifTrue: [ - | currentPosition | - currentPosition := self position. - position := readLimit := 0. - self primSetPosition: fileID to: currentPosition ] ] -] - -{ #category : #accessing } -StandardFileStream >> fullName [ - "Answer this file's full path name." - - ^ name - -] - -{ #category : #utilities } -StandardFileStream >> insertLineFeeds [ - "(FileStream oldFileNamed: 'BBfix2.st') insertLineFeeds" - | s crLf f | - crLf := String crlf. - s := self next: self size. - self close. - f := FileStream newFileNamed: self name. - s linesDo: [:line | f nextPutAll: line; nextPutAll: crLf]. - f close -] - -{ #category : #testing } -StandardFileStream >> isBinary [ - ^ buffer1 class == ByteArray -] - -{ #category : #testing } -StandardFileStream >> isDirectory [ - "Answer whether the receiver represents a directory. For the post-transition case, uncertain what to do." - ^ false -] - -{ #category : #testing } -StandardFileStream >> isReadOnly [ - - ^ rwmode not - -] - -{ #category : #accessing } -StandardFileStream >> localName [ - ^ name ifNotNil: [ - (name findTokens: FileSystem disk delimiter asString) last] -] - -{ #category : #accessing } -StandardFileStream >> name [ - "Answer this file's full path name." - - ^ name - -] - -{ #category : #accessing } -StandardFileStream >> next [ - "Answer the next byte from this file, or nil if at the end of the file." - - ^ self basicNext -] - -{ #category : #accessing } -StandardFileStream >> next: n [ - "Return a string with the next n characters of the filestream in it." - ^ self nextInto: (self collectionSpecies new: n) -] - -{ #category : #accessing } -StandardFileStream >> next: n into: aString startingAt: startIndex [ - "Read n bytes into the given string. - Return aString or a partial copy if less than - n elements have been read." - |read| - read := (self readInto: aString startingAt: startIndex count: n). - ^read = n - ifTrue: [ aString ] - ifFalse: [ aString copyFrom: 1 to: startIndex + read - 1 ] - -] - -{ #category : #accessing } -StandardFileStream >> next: anInteger putAll: aString startingAt: startIndex [ - "Store the next anInteger elements from the given collection." - rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. - collection ifNotNil: [ - position < readLimit ifTrue: [ self flushReadBuffer ] ]. - self primWrite: fileID from: aString startingAt: startIndex count: anInteger. - ^aString -] - -{ #category : #accessing } -StandardFileStream >> nextPut: char [ - "Write the given character to this file." - - rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. - collection ifNotNil: [ - position < readLimit ifTrue: [ self flushReadBuffer ] ]. - buffer1 at: 1 put: char. - self primWrite: fileID from: buffer1 startingAt: 1 count: 1. - ^ char - -] - -{ #category : #accessing } -StandardFileStream >> nextPutAll: stringOrByteArray [ - "Write all the characters of the given string to this file." - - rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. - collection ifNotNil: [ - position < readLimit ifTrue: [ self flushReadBuffer ] ]. - self primWrite: fileID from: stringOrByteArray startingAt: 1 count: stringOrByteArray basicSize. - ^ stringOrByteArray - -] - -{ #category : #'open/close' } -StandardFileStream >> open [ - "For compatibility with a few existing things." - - ^ self reopen -] - -{ #category : #'open/close' } -StandardFileStream >> open: fileName forWrite: writeMode [ - "Open the file with the given name. If writeMode is true, allow writing, otherwise open the file in read-only mode." - | f | - f := fileName asVmPathName. - - (writeMode and: [ FileSystem disk isWritable not ]) ifTrue: [ ^ nil ]. - - fileID := StandardFileStream retryWithGC:[self primOpen: f writable: writeMode] - until:[:id| id notNil] - forFileNamed: fileName. - fileID ifNil: [^ nil]. "allows sender to detect failure" - name := fileName. - self register. - rwmode := writeMode. - buffer1 := String new: 1. - self enableReadBuffering - -] - -{ #category : #'open/close' } -StandardFileStream >> openOnHandle: aFileID name: streamName forWrite: writeMode [ - "Initialize the file with the given handle. If writeMode is true then - allow writing, otherwise put the file in read-only mode. - N.B. Do _not_ register the stream. We do not want it to be - closed implicitly (e.g. on GC). There may be multiple instances - accessing the same stream. The stream is not a file." - fileID := aFileID. - name := streamName. - rwmode := writeMode. - buffer1 := String new: 1. - self enableReadBuffering -] - -{ #category : #'open/close' } -StandardFileStream >> openReadOnly [ - "Open the receiver as a read-only file." - - ^ self open: name forWrite: false -] - -{ #category : #accessing } -StandardFileStream >> padToEndWith: aChar [ - "On the Mac, files do not truncate. One can delete the old file and write a new one, but sometime deletion fails (file still open? file stale?). This is a sad compromise. Just let the file be the same length but pad it with a harmless character." - - | pad | - self atEnd ifTrue: [^ self]. - pad := self isBinary - ifTrue: [aChar asCharacter asciiValue] "ok for char or number" - ifFalse: [aChar asCharacter]. - self nextPutAll: (self collectionSpecies new: ((self size - self position) min: 20000) - withAll: pad). -] - -{ #category : #accessing } -StandardFileStream >> peek [ - "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. " - | next | - self atEnd ifTrue: [^ nil]. - next := self basicNext. - self position: self position - 1. - ^ next -] - -{ #category : #accessing } -StandardFileStream >> peekFor: item [ - "Answer false and do not advance if the next element is not equal to item, or if this stream is at the end. If the next element is equal to item, then advance over it and return true" - | next | - (next := self next) == nil ifTrue: [^ false]. - item = next ifTrue: [^ true]. - self skip: -1. - ^ false -] - -{ #category : #accessing } -StandardFileStream >> peekLast [ - "Return that item just put at the end of the stream" - - ^ buffer1 size > 0 - ifTrue: [buffer1 last] - ifFalse: [nil] - -] - -{ #category : #positioning } -StandardFileStream >> position [ - "Return the receiver's current file position." - - collection ifNotNil: [ - position < readLimit ifTrue: [ - ^(self primGetPosition: fileID) - readLimit + position ] ]. - ^self primGetPosition: fileID -] - -{ #category : #positioning } -StandardFileStream >> position: pos [ - "Set the receiver's position as indicated." - - collection ifNotNil: [ - position < readLimit ifTrue: [ - | newPosition | - newPosition := pos - (self primGetPosition: fileID) + readLimit. - newPosition < 0 ifTrue: [ - | offsetPos | - self primSetPosition: fileID to: (offsetPos := pos - (collection size // 4) max: 0). - readLimit := self primRead: fileID into: collection startingAt: 1 count: collection size. - position := pos - offsetPos. - ^self ]. - newPosition < readLimit - ifTrue: [ - position := newPosition. - ^self ] - ifFalse: [ - readLimit := position := 0 ] ] ]. - ^self primSetPosition: fileID to: pos -] - -{ #category : #'private - primitives' } -StandardFileStream >> primAtEnd: id [ - "Answer true if the file position is at the end of the file." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primClose: id [ - "Close this file." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primCloseNoError: id [ - "Close this file. Don't raise an error if the primitive fails." - - - -] - -{ #category : #private } -StandardFileStream >> primDropRequestFileHandle: dropIndex [ - "Primitive. Return the (read-only) file handle for some file that was just dropped onto the application. - Fail if dropIndex is out of range or the primitive is not supported." - - ^nil -] - -{ #category : #private } -StandardFileStream >> primDropRequestFileName: dropIndex [ - "Primitive. Return the file name for some file that was just dropped onto the application. - Fail if dropIndex is out of range or the primitive is not supported." - - ^nil -] - -{ #category : #'private - primitives' } -StandardFileStream >> primFlush: id [ - "On Unix, the FilePlugin uses stdio FILE* structs which maintain their - own internal buffer to minimize write() syscalls. This flushes that buffer. - On Windows this and primSync: do the same thing." - - - - "We can't ignore fflush() failing, because it can fail for any of the - reasons write() can." - self primitiveFailed -] - -{ #category : #'private - primitives' } -StandardFileStream >> primGetPosition: id [ - "Get this files current position." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primOpen: fileName writable: writableFlag [ - "Open a file of the given name, and return the file ID obtained. - If writableFlag is true, then - if there is none with this name, then create one - else prepare to overwrite the existing from the beginning - otherwise - if the file exists, open it read-only - else return nil" - - - ^ nil - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primRead: id into: byteArray startingAt: startIndex count: count [ - "Read up to count bytes of data from this file into the given string or byte array starting at the given index. Answer the number of bytes actually read." - - - self closed ifTrue: [^ self error: 'File is closed']. - self error: 'File read failed'. - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primSetPosition: id to: anInteger [ - "Set this file to the given position." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primSize: id [ - "Answer the size of this file." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primSizeNoError: id [ - "Answer the size of this file. Answer nil if the primitive fails; this indicates that the file handle has become stale." - - - ^ nil - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primSync: id [ - "On Unix, this syncs any written or flushed data still in the kernel file - system buffers to disk. On Windows this and primFlush: do the same thing" - - - - "fsync() failing cannot be ignored" - self primitiveFailed -] - -{ #category : #'private - primitives' } -StandardFileStream >> primTruncate: id to: anInteger [ - "Truncate this file to the given position." - - - self primitiveFailed - -] - -{ #category : #'private - primitives' } -StandardFileStream >> primWrite: id from: stringOrByteArray startingAt: startIndex count: count [ - "Write count bytes onto this file from the given string or byte array starting at the given index. Answer the number of bytes written." - - - (FileWriteError fileName: name) - signal: (self closed - ifTrue: [ 'File ', name, ' is closed' ] - ifFalse: [ 'File ', name, ' write failed' ]) -] - -{ #category : #printing } -StandardFileStream >> printOn: aStream [ - "Put a printed version of the receiver onto aStream." - - aStream nextPutAll: self class name; nextPutAll: ': '; print: name -] - -{ #category : #accessing } -StandardFileStream >> readInto: byteArray startingAt: startIndex count: count [ - "Read up to n bytes into the given byteArray. - Return the number of bytes actually read." - - | newN newStartIndex available| - available := 0. - collection - ifNil: [ - newN := count. - newStartIndex := startIndex ] - ifNotNil: [ - byteArray class isBytes - ifFalse: [ - position < readLimit ifTrue: [ self flushReadBuffer ]. - newN := count. - newStartIndex := startIndex ] - ifTrue: [ - (available := readLimit - position) > 0 - ifTrue: [ - | bufferedCount | - bufferedCount := count min: available. - byteArray - replaceFrom: startIndex - to: startIndex + bufferedCount - 1 - with: collection - startingAt: position + 1. - position := position + bufferedCount. - bufferedCount = count ifTrue: [ ^count ] ]. - newN := count - available. - newStartIndex := startIndex + available ] ]. - ^available + (self primRead: fileID into: byteArray - startingAt: newStartIndex count: newN). - -] - -{ #category : #modes } -StandardFileStream >> readOnly [ - "Make this file read-only." - - rwmode := false. - -] - -{ #category : #copying } -StandardFileStream >> readOnlyCopy [ - - ^ self class readOnlyFileNamed: self name. - -] - -{ #category : #modes } -StandardFileStream >> readWrite [ - "Make this file writable." - - rwmode := true. - -] - -{ #category : #registry } -StandardFileStream >> register [ - ^self class register: self -] - -{ #category : #'open/close' } -StandardFileStream >> reopen [ - "Close and reopen this file. The file position is reset to zero." - "Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened." - - fileID ifNotNil: [ - collection ifNotNil: [ - position < readLimit ifTrue: [ - self flushReadBuffer ] ]. - self primCloseNoError: fileID ]. - self open: name forWrite: rwmode. - -] - -{ #category : #'dnd requests' } -StandardFileStream >> requestDropStream: dropIndex [ - "Return a read-only stream for some file the user has just dropped onto the application." - - | rawName | - rawName := self primDropRequestFileName: dropIndex. - name := FilePathEncoder decode: rawName. - fileID := self primDropRequestFileHandle: dropIndex. - fileID == nil - ifTrue: [ ^ nil ]. - self register. - rwmode := false. - buffer1 := String new: 1. - self enableReadBuffering -] - -{ #category : #initialization } -StandardFileStream >> reset [ - self ensureOpen. - self position: 0. -] - -{ #category : #positioning } -StandardFileStream >> setToEnd [ - "Set the position of the receiver to the end of file." - - self position: self size -] - -{ #category : #accessing } -StandardFileStream >> size [ - "Answer the size of the file in characters." - - ^ self primSize: fileID -] - -{ #category : #positioning } -StandardFileStream >> skip: n [ - "Set the character position to n characters from the current position. - Error if not enough characters left in the file." - - collection ifNotNil: [ - position < readLimit ifTrue: [ - | newPosition | - ((newPosition := position + n) >= 0 and: [ newPosition < readLimit ]) - ifTrue: [ - position := newPosition. - ^self ] ] ]. - self position: self position + n -] - -{ #category : #flushing } -StandardFileStream >> sync [ - "When writing, this syncs any written/flushed data still in the kernel - file system buffers to disk. This should generally be used after #flush, - but on Windows they do the same thing." - - ^ self primSync: fileID -] - -{ #category : #positioning } -StandardFileStream >> truncate [ - "Truncate to zero" - - ^ self truncate: 0 -] - -{ #category : #positioning } -StandardFileStream >> truncate: pos [ - "Truncate to this position" - - self position: pos. - ^self primTruncate: fileID to: pos -] - -{ #category : #registry } -StandardFileStream >> unregister [ - ^self class unregister: self -] - -{ #category : #accessing } -StandardFileStream >> upTo: delim [ - "Fast version to speed up nextChunk" - | pos buffer count | - collection ifNotNil: [ - (position < readLimit and: [ - (pos := collection indexOf: delim startingAt: position + 1) <= readLimit and: [ - pos > 0 ] ]) ifTrue: [ - ^collection copyFrom: position + 1 to: (position := pos) - 1 ] ]. - pos := self position. - buffer := self next: 2000. - (count := buffer indexOf: delim) > 0 ifTrue: - ["Found the delimiter part way into buffer" - self position: pos + count. - ^ buffer copyFrom: 1 to: count - 1]. - self atEnd ifTrue: - ["Never found it, and hit end of file" - ^ buffer]. - "Never found it, but there's more..." - ^ buffer , (self upTo: delim) -] - -{ #category : #accessing } -StandardFileStream >> upToAnyOf: delimiters do: aBlock [ - "Fast version to speed up nextChunk" - | pos buffer count result | - collection ifNotNil: [ - (position < readLimit and: [ - (count := collection indexOfAnyOf: delimiters startingAt: position + 1) <= readLimit and: [ - count > 0 ] ]) ifTrue: [ - result := collection copyFrom: position + 1 to: (position := count) - 1. - aBlock value: (collection at: count). - ^result ] ]. - pos := self position. - buffer := self next: 2000. - (count := buffer indexOfAnyOf: delimiters) > 0 ifTrue: - ["Found one of the delimiters part way into buffer" - self position: pos + count. - aBlock value: (buffer at: count). - ^ buffer copyFrom: 1 to: count - 1]. - self atEnd ifTrue: - ["Never found it, and hit end of file" - ^ buffer]. - "Never found it, but there's more..." - ^ buffer , (self upToAnyOf: delimiters do: aBlock) -] - -{ #category : #accessing } -StandardFileStream >> upToEnd [ - "Answer a subcollection from the current access position through the last element of the receiver." - - ^self collectionSpecies streamContents: [ :newStream | - | next | - [ (next := self next) == nil ] whileFalse: [ - newStream nextPut: next ] ] -] diff --git a/src/DeprecatedFileStream/package.st b/src/DeprecatedFileStream/package.st deleted file mode 100644 index f1db65de1a6..00000000000 --- a/src/DeprecatedFileStream/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #DeprecatedFileStream } diff --git a/src/Fuel-Core/StandardFileStream.extension.st b/src/Fuel-Core/StandardFileStream.extension.st deleted file mode 100644 index b2502f15f34..00000000000 --- a/src/Fuel-Core/StandardFileStream.extension.st +++ /dev/null @@ -1,13 +0,0 @@ -Extension { #name : #StandardFileStream } - -{ #category : #'*Fuel-Core' } -StandardFileStream >> fuelNextWordsInto: aWordObject [ - "This method is the same as nextWordsInto: but the restoreEndianness is only done if needed" - self next: aWordObject basicSize into: aWordObject startingAt: 1. - ^ aWordObject -] - -{ #category : #'*Fuel-Core' } -StandardFileStream >> nextBytesPutAll: aCollection [ - self nextPutAll: aCollection -] diff --git a/src/Fuel-Core/ZnBufferedReadStream.extension.st b/src/Fuel-Core/ZnBufferedReadStream.extension.st new file mode 100644 index 00000000000..b2085030cfa --- /dev/null +++ b/src/Fuel-Core/ZnBufferedReadStream.extension.st @@ -0,0 +1,26 @@ +Extension { #name : #ZnBufferedReadStream } + +{ #category : #'*Fuel-Core' } +ZnBufferedReadStream >> fuelNextWordsInto: aWordObject [ + + "This method is the same as nextWordsInto: but the restoreEndianness is only done if needed" + | byteSize source pos blt | + byteSize := aWordObject byteSize. + source := self next: byteSize. + pos := 0. + + "Now use BitBlt to copy the bytes to the bitmap." + blt := (BitBlt + toForm: (Form new hackBits: aWordObject)) + sourceForm: (Form new hackBits: source). + blt combinationRule: Form over. "store" + blt sourceX: 0; + sourceY: pos // 4; + height: byteSize // 4; + width: 4. + blt destX: 0; + destY: 0. + blt copyBits. + + ^ aWordObject +] diff --git a/src/Fuel-Tests-Core/FLBinaryFileStreamSerializationTest.class.st b/src/Fuel-Tests-Core/FLBinaryFileStreamSerializationTest.class.st deleted file mode 100644 index f92259d4986..00000000000 --- a/src/Fuel-Tests-Core/FLBinaryFileStreamSerializationTest.class.st +++ /dev/null @@ -1,12 +0,0 @@ -Class { - #name : #FLBinaryFileStreamSerializationTest, - #superclass : #FLBasicSerializationTest, - #category : #'Fuel-Tests-Core-Base' -} - -{ #category : #running } -FLBinaryFileStreamSerializationTest >> setUp [ - super setUp. - self useBinaryFileStream - -] diff --git a/src/Fuel-Tests-Core/FLBinaryFileStreamStrategy.class.st b/src/Fuel-Tests-Core/FLBinaryFileStreamStrategy.class.st deleted file mode 100644 index a5468d16a74..00000000000 --- a/src/Fuel-Tests-Core/FLBinaryFileStreamStrategy.class.st +++ /dev/null @@ -1,28 +0,0 @@ -" -Specific to BinaryFileStream -" -Class { - #name : #FLBinaryFileStreamStrategy, - #superclass : #FLFileStreamStrategy, - #category : #'Fuel-Tests-Core-StreamStrategies' -} - -{ #category : #reading } -FLBinaryFileStreamStrategy >> readStreamDo: aValuable [ - "Evaluates the argument with a read stream. Answers the result." - - ^ FLPlatform current - fileNamed: self fileName - readStreamDo: [ :aStream | - aValuable value: aStream binary ] -] - -{ #category : #writing } -FLBinaryFileStreamStrategy >> writeStreamDo: aValuable [ - "Evaluates the argument with a write stream. Answers the result." - - ^ FLPlatform current - fileNamed: self fileName - writeStreamDo: [ :aStream | - aValuable value: aStream binary ] -] diff --git a/src/Fuel-Tests-Core/FLFileStreamStrategy.class.st b/src/Fuel-Tests-Core/FLFileStreamStrategy.class.st deleted file mode 100644 index 412a09f9a4f..00000000000 --- a/src/Fuel-Tests-Core/FLFileStreamStrategy.class.st +++ /dev/null @@ -1,91 +0,0 @@ -" -I am a strategy for traditional file streams. -" -Class { - #name : #FLFileStreamStrategy, - #superclass : #FLStreamStrategy, - #instVars : [ - 'fileStreamClass' - ], - #category : #'Fuel-Tests-Core-StreamStrategies' -} - -{ #category : #'instance creation' } -FLFileStreamStrategy class >> new [ - self error: 'Invalid creation method.' -] - -{ #category : #'instance creation' } -FLFileStreamStrategy class >> newWith: aFileStream [ - - ^self basicNew - initializeWith: aFileStream; - yourself -] - -{ #category : #'instance creation' } -FLFileStreamStrategy class >> newWithBinaryFileStream [ - ^ (FLPlatform current isPharo and: [ - FLPlatform current versionNumber >= 5 ]) - ifTrue: [ - FLBinaryFileStreamStrategy basicNew - initialize; - yourself ] - ifFalse: [ self newWithStandardFileStream ] -] - -{ #category : #'instance creation' } -FLFileStreamStrategy class >> newWithMultiByteFileStream [ - - ^self newWith: MultiByteFileStream -] - -{ #category : #'instance creation' } -FLFileStreamStrategy class >> newWithStandardFileStream [ - - ^self newWith: StandardFileStream -] - -{ #category : #writing } -FLFileStreamStrategy >> fileName [ - "Answer a filename to serialize and materialize using it." - - ^ FLPlatform current absolutePathOf: (FLPlatform current imageName, '-tests.fuel') -] - -{ #category : #writing } -FLFileStreamStrategy >> fileStreamClass [ - "Returns the FileStream specific class" - - ^fileStreamClass -] - -{ #category : #writing } -FLFileStreamStrategy >> initializeWith: aFileStreamClass [ - - self initialize. - fileStreamClass := aFileStreamClass. -] - -{ #category : #reading } -FLFileStreamStrategy >> readStreamDo: aValuable [ - "Evaluates the argument with a read stream. Answers the result." - - ^self fileStreamClass - oldFileNamed: self fileName - do: [ :aStream | aValuable value: aStream binary ] -] - -{ #category : #'test support' } -FLFileStreamStrategy >> tearDown [ - FLPlatform current deleteFileNamed: self fileName -] - -{ #category : #writing } -FLFileStreamStrategy >> writeStreamDo: aValuable [ - "Evaluates the argument with a write stream. Answers the result." - - ^self fileStreamClass - forceNewFileNamed: self fileName - do: [ :aStream | aValuable value: aStream binary ] -] diff --git a/src/Fuel-Tests-Core/FLMultiByteStreamStrategy.class.st b/src/Fuel-Tests-Core/FLMultiByteStreamStrategy.class.st index 4f683e4539c..e65c8dd2add 100644 --- a/src/Fuel-Tests-Core/FLMultiByteStreamStrategy.class.st +++ b/src/Fuel-Tests-Core/FLMultiByteStreamStrategy.class.st @@ -5,23 +5,30 @@ Class { #name : #FLMultiByteStreamStrategy, #superclass : #FLStreamStrategy, #instVars : [ - 'inMemoryStream' + 'memoryFileSystem' ], #category : #'Fuel-Tests-Core-StreamStrategies' } +{ #category : #writing } +FLMultiByteStreamStrategy >> initialize [ + + super initialize. + memoryFileSystem := FileSystem memory +] + { #category : #reading } FLMultiByteStreamStrategy >> readStreamDo: aValuable [ "Evaluates the argument with a read stream. Answers the result." - ^aValuable value: inMemoryStream reset + ^ (memoryFileSystem / 'temp') + binaryReadStreamDo: [ :stream | aValuable value: stream ] ] { #category : #writing } FLMultiByteStreamStrategy >> writeStreamDo: aValuable [ "Evaluates the argument with a write stream. Answers the result." - inMemoryStream := MultiByteBinaryOrTextStream on: ''. - ^aValuable value: inMemoryStream binary - + ^ (memoryFileSystem / 'temp') + binaryWriteStreamDo: [ :stream | aValuable value: stream ] ] diff --git a/src/Fuel-Tests-Core/FLSerializationTest.class.st b/src/Fuel-Tests-Core/FLSerializationTest.class.st index 73e33e8c0df..65c65b90023 100644 --- a/src/Fuel-Tests-Core/FLSerializationTest.class.st +++ b/src/Fuel-Tests-Core/FLSerializationTest.class.st @@ -281,12 +281,6 @@ FLSerializationTest >> traitNamePrefix [ ^'FLTraitForTesting' ] -{ #category : #'stream-strategies' } -FLSerializationTest >> useBinaryFileStream [ - - streamFactory := FLFileStreamStrategy newWithBinaryFileStream -] - { #category : #'stream-strategies' } FLSerializationTest >> useGzipInMemoryStream [ @@ -305,18 +299,6 @@ FLSerializationTest >> useMemoryStream [ streamFactory := FLMultiByteStreamStrategy new ] -{ #category : #'stream-strategies' } -FLSerializationTest >> useMultiByteFileStream [ - - streamFactory := FLFileStreamStrategy newWithMultiByteFileStream -] - -{ #category : #'stream-strategies' } -FLSerializationTest >> useStandardFileStream [ - - streamFactory := FLFileStreamStrategy newWithStandardFileStream -] - { #category : #'class-factory' } FLSerializationTest >> withNotificationsNewClass [ ^ self classFactory withNotificationsNewClass diff --git a/src/Fuel-Tests-Core/FLStandardFileStreamSerializationTest.class.st b/src/Fuel-Tests-Core/FLStandardFileStreamSerializationTest.class.st deleted file mode 100644 index e6fbe3e85ec..00000000000 --- a/src/Fuel-Tests-Core/FLStandardFileStreamSerializationTest.class.st +++ /dev/null @@ -1,12 +0,0 @@ -Class { - #name : #FLStandardFileStreamSerializationTest, - #superclass : #FLBasicSerializationTest, - #category : #'Fuel-Tests-Core-Base' -} - -{ #category : #running } -FLStandardFileStreamSerializationTest >> setUp [ - super setUp. - self useStandardFileStream - -] diff --git a/src/Graphics-Primitives/StandardFileStream.extension.st b/src/Graphics-Primitives/StandardFileStream.extension.st deleted file mode 100644 index e5a6ddfe12d..00000000000 --- a/src/Graphics-Primitives/StandardFileStream.extension.st +++ /dev/null @@ -1,10 +0,0 @@ -Extension { #name : #StandardFileStream } - -{ #category : #'*Graphics-Primitives' } -StandardFileStream >> nextWordsInto: aBitmap [ - "Note: The file primitives automatically adjust for word based objects." - - self next: aBitmap basicSize into: aBitmap startingAt: 1. - aBitmap restoreEndianness. - ^ aBitmap -] diff --git a/src/Metacello-PharoCommonPlatform/MetacelloPharoCommonPlatform.class.st b/src/Metacello-PharoCommonPlatform/MetacelloPharoCommonPlatform.class.st index e311897069b..50381edbfe7 100644 --- a/src/Metacello-PharoCommonPlatform/MetacelloPharoCommonPlatform.class.st +++ b/src/Metacello-PharoCommonPlatform/MetacelloPharoCommonPlatform.class.st @@ -138,8 +138,12 @@ MetacelloPharoCommonPlatform >> downloadBasicFile: url to: outputFileName userna | out err proc errorFileName args | "Make a unique name for the error log and ensure that we can write the files" errorFileName := self downloadErrorFileNameFor: outputFileName. - out := FileStream forceNewFileNamed: outputFileName. - err := FileStream forceNewFileNamed: errorFileName. + out := (outputFileName asFileReference) + ensureDelete; + writeStream. + err := (errorFileName asFileReference) + ensureDelete; + writeStream. args := username ifNotNil: [ {'-u' . (username , ':' , pass) . '-L' . url} ] ifNil: [ {'-L' . url} ]. @@ -217,8 +221,12 @@ MetacelloPharoCommonPlatform >> extractRepositoryFrom: zipFile to: directory [ | out err proc errorMessage errorFileName | errorFileName := self downloadErrorFileNameFor: zipFile. - out := FileStream forceNewFileNamed: '/tmp/zip.out'. - err := FileStream forceNewFileNamed: errorFileName. + out := ('/tmp/zip.out'asFileReference) + ensureDelete; + writeStream. + err := (errorFileName asFileReference) + ensureDelete; + writeStream. errorMessage := ''. [ proc := (self class environment at: #OSProcess) thisOSProcess @@ -235,10 +243,9 @@ MetacelloPharoCommonPlatform >> extractRepositoryFrom: zipFile to: directory [ ensure: [ out close. err close ]. - FileStream - fileNamed: errorFileName - do: [ :fileStream | - (errorMessage := fileStream contentsOfEntireFile) notEmpty + errorFileName asFileReference + binaryReadStreamDo: [ :fileStream | + (errorMessage := fileStream upToEnd) notEmpty ifTrue: [ self error: 'unzip failure: ' , errorMessage printString ] ifFalse: [ (self fileHandleOn: '/tmp') diff --git a/src/Monticello-Tests/MCDataStreamTest.class.st b/src/Monticello-Tests/MCDataStreamTest.class.st index ecfcbb97df1..efd2c5ddb41 100644 --- a/src/Monticello-Tests/MCDataStreamTest.class.st +++ b/src/Monticello-Tests/MCDataStreamTest.class.st @@ -18,7 +18,7 @@ MCDataStreamTest >> testFileNamed [ "When" [ MCDataStream fileNamed: fileName do: [ :streamType | streamType nextPut: testString ]. "Then" - MCDataStream fileNamed: fileName do: [ :streamType | self assert: streamType next equals: testString ] ] + MCDataStream readOnlyFileNamed: fileName do: [ :streamType | self assert: streamType next equals: testString ] ] ensure: [ (FileSystem disk workingDirectory / fileName) ensureDelete ] ] diff --git a/src/Monticello/MCDataStream.class.st b/src/Monticello/MCDataStream.class.st index 3b3c4b7c351..f1f418349b3 100644 --- a/src/Monticello/MCDataStream.class.st +++ b/src/Monticello/MCDataStream.class.st @@ -61,7 +61,7 @@ rr nextPut: 'Zork'. rr close. " - ^ self on: (FileStream fileNamed: aString) + ^ self on: aString asFileReference binaryWriteStream ] { #category : #'instance creation' } @@ -149,8 +149,10 @@ MCDataStream class >> newFileNamed: aString [ rr nextPut: 'Zork'. rr close. " - - ^ self on: (FileStream newFileNamed: aString) + | fileReference | + fileReference := aString asFileReference. + fileReference exists ifTrue: [ FileExists signalWith: fileReference ]. + ^ self on: fileReference binaryWriteStream ] { #category : #'instance creation' } @@ -162,10 +164,10 @@ MCDataStream class >> oldFileNamed: aString [ ^ rr nextAndClose. " - | strm ff | - ff := FileStream oldFileOrNoneNamed: aString. - ff ifNil: [^ nil]. - strm := self on: (ff binary). + | strm fileReference | + fileReference := aString asFileReference. + fileReference exists ifFalse: [ ^ nil ]. + strm := self on: fileReference binaryWriteStream. ^ strm ] @@ -174,7 +176,6 @@ MCDataStream class >> on: aStream [ "Open a new DataStream onto a low-level I/O stream." ^ self basicNew setStream: aStream - "aStream binary is in setStream:" ] @@ -188,7 +189,14 @@ MCDataStream class >> readOnlyFileNamed: aString [ rr close. " - ^ self on: (FileStream readOnlyFileNamed: aString) + ^ self on: aString asFileReference binaryReadStream +] + +{ #category : #'instance creation' } +MCDataStream class >> readOnlyFileNamed: fileName do: aBlock [ + "Returns the result of aBlock." + + ^ self detectFile: [ self readOnlyFileNamed: fileName ] do: aBlock ] { #category : #'initialize-release' } @@ -218,8 +226,7 @@ MCDataStream class >> registerWriterSelector: aSelector atIndex: anIndex [ MCDataStream class >> streamedRepresentationOf: anObject [ | file | - file := (RWBinaryOrTextStream on: (ByteArray new: 5000)). - file binary. + file := (ByteArray new: 5000) writeStream. (self on: file) nextPut: anObject. ^file contents ] @@ -230,12 +237,6 @@ MCDataStream class >> typeMap [ ^ TypeMap ] -{ #category : #'instance creation' } -MCDataStream class >> unStream: aString [ - - ^(self on: ((RWBinaryOrTextStream with: aString) reset; binary)) next -] - { #category : #'initialize-release' } MCDataStream class >> writeSelectors [ WriteSelectors ifNil: [ self initializeTypeMap ]. @@ -513,12 +514,16 @@ MCDataStream >> readNil [ { #category : #'write and read' } MCDataStream >> readString [ - | str | - byteStream ascii. - str := byteStream nextString. - byteStream binary. - ^ str + | length aByteArray | + length := byteStream next. "first byte." + length >= 192 ifTrue: [length := length - 192. + 1 to: 3 do: [:ii | length := length * 256 + byteStream next]]. + aByteArray := ByteArray new: length. + byteStream nextInto: aByteArray. + + "An ascii string..." + ^ aByteArray asString. ] { #category : #'write and read' } @@ -565,7 +570,6 @@ MCDataStream >> setCurrentReference: refPosn [ MCDataStream >> setStream: aStream [ "PRIVATE -- Initialization method." - aStream binary. basePos := aStream position. "Remember where we start. Earlier part of file contains a class or method file-in. Allow that to be edited. We don't deal in absolute file locations." byteStream := aStream. ] @@ -661,7 +665,15 @@ MCDataStream >> writeNil: anUndefinedObject [ MCDataStream >> writeString: aString [ "PRIVATE -- Write the contents of a String." - byteStream nextStringPut: aString. + | length | + (length := aString size) < 192 + ifTrue: [byteStream nextPut: length] + ifFalse: + [byteStream nextPut: (length byteAt: 4)+192. + byteStream nextPut: (length byteAt: 3). + byteStream nextPut: (length byteAt: 2). + byteStream nextPut: (length byteAt: 1)]. + byteStream nextPutAll: aString asByteArray. ] { #category : #'write and read' } diff --git a/src/Monticello/MCVersionReader.class.st b/src/Monticello/MCVersionReader.class.st index 63629015808..ecf635028ee 100644 --- a/src/Monticello/MCVersionReader.class.st +++ b/src/Monticello/MCVersionReader.class.st @@ -16,9 +16,8 @@ Class { { #category : #reading } MCVersionReader class >> file: fileName streamDo: aBlock [ - ^ FileStream - readOnlyFileNamed: fileName - do: [:file | aBlock value: file] + ^ fileName asFileReference + readStreamDo: [ :file | aBlock value: file] ] { #category : #'actions - file' } diff --git a/src/MonticelloConfigurations/MCPseudoFileStream.class.st b/src/MonticelloConfigurations/MCPseudoFileStream.class.st index cd8293abd00..8919fb2e340 100644 --- a/src/MonticelloConfigurations/MCPseudoFileStream.class.st +++ b/src/MonticelloConfigurations/MCPseudoFileStream.class.st @@ -3,7 +3,7 @@ A pseudo file stream which can be used for updates. " Class { #name : #MCPseudoFileStream, - #superclass : #RWBinaryOrTextStream, + #superclass : #AnObsoleteRWBinaryOrTextStream, #instVars : [ 'localName' ], diff --git a/src/MonticelloGUI/MCWorkingCopyBrowser.class.st b/src/MonticelloGUI/MCWorkingCopyBrowser.class.st index abdbb25ca56..a928b130efa 100644 --- a/src/MonticelloGUI/MCWorkingCopyBrowser.class.st +++ b/src/MonticelloGUI/MCWorkingCopyBrowser.class.st @@ -469,7 +469,9 @@ MCWorkingCopyBrowser >> inspectWorkingCopy [ { #category : #actions } MCWorkingCopyBrowser >> loadRepositories [ - FileStream fileIn: 'MCRepositories.st'. + + + CodeImporter evaluateFileNamed: 'MCRepositories.st'. self repositoryListChanged. self changedButtons. @@ -735,7 +737,7 @@ MCWorkingCopyBrowser >> revertPackageMenuSpec [ { #category : #actions } MCWorkingCopyBrowser >> saveRepositories [ - FileStream forceNewFileNamed: 'MCRepositories.st' do: [:f | + 'MCRepositories.st' asFileReference writeStreamDo: [:f | MCRepositoryGroup default repositoriesDo: [:r | r asCreationTemplate ifNotNil: [:template | f nextPutAll: 'MCRepositoryGroup default addRepository: (', template , ')!'; cr]]] diff --git a/src/MonticelloMocks/MCMockClassA.class.st b/src/MonticelloMocks/MCMockClassA.class.st index e23e7093fab..256aee82e2a 100644 --- a/src/MonticelloMocks/MCMockClassA.class.st +++ b/src/MonticelloMocks/MCMockClassA.class.st @@ -44,8 +44,7 @@ MCMockClassA class >> touchCVar [ ] { #category : #numeric } -MCMockClassA >> a [ - ^ 'a2' +MCMockClassA >> a [ ^ 'a2' ] { #category : #numeric } diff --git a/src/Multilingual-Tests/ByteTextConverterTest.class.st b/src/Multilingual-Tests/ByteTextConverterTest.class.st index 873706b5a02..e9aa35af7fc 100644 --- a/src/Multilingual-Tests/ByteTextConverterTest.class.st +++ b/src/Multilingual-Tests/ByteTextConverterTest.class.st @@ -16,14 +16,14 @@ ByteTextConverterTest >> testConversionToFrom [ { #category : #testing } ByteTextConverterTest >> testLatin2ToUnicodeConversion [ - | latin2Characters utfCodePoints decodingStream unicodeString | - latin2Characters := #[16rBE 16rFD 16rE1 16rC8] asString. + | latin2Characters utfCodePoints unicodeString | + latin2Characters := #[16rBE 16rFD 16rE1 16rC8]. utfCodePoints := #(16r017E 16rFD 16rE1 16r010C). "Converters assume that characters you want to put/get from a stream are Unicode characters" "So our source is a string of latin 2" - decodingStream := (MultiByteBinaryOrTextStream with: latin2Characters encoding: 'ISO-8859-2') reset. - unicodeString := decodingStream contents. + unicodeString := (ZnCharacterEncoder newForEncoding: 'ISO-8859-2') decodeBytes: latin2Characters. + "our sourcelatin2 string contains characters outside latin1" self assert: unicodeString isWideString. self assert: (unicodeString at: 1) charCode equals: (utfCodePoints at: 1). @@ -34,7 +34,7 @@ ByteTextConverterTest >> testLatin2ToUnicodeConversion [ { #category : #testing } ByteTextConverterTest >> testUnicodeToLatin2Conversion [ - | latin2Bytes internalString encodingStream encodedBytes | + | latin2Bytes internalString encodedBytes | latin2Bytes := #[16rBE 16rFD 16rE1 16rC8]. internalString := String streamContents: [ :s | @@ -45,11 +45,7 @@ ByteTextConverterTest >> testUnicodeToLatin2Conversion [ nextPut: 16r010C asCharacter ]. "Converters assume that characters you want to put/get from a stream are Unicode characters" "So we use a stream with an encoder, then put the internalString to it" - encodingStream := (MultiByteBinaryOrTextStream with: String new encoding: 'ISO-8859-2') reset. - encodingStream nextPutAll: internalString. - "the encoded string in the stream does not contain any characters > 255" - encodedBytes := encodingStream binary reset contents. - + encodedBytes := internalString encodeWith: 'ISO-8859-2'. self assert: (encodedBytes at: 1) equals: (latin2Bytes at: 1). self assert: (encodedBytes at: 2) equals: (latin2Bytes at: 2). diff --git a/src/Network-MIME/MIMEDocument.class.st b/src/Network-MIME/MIMEDocument.class.st index b5926ad035c..10b8a4707f6 100644 --- a/src/Network-MIME/MIMEDocument.class.st +++ b/src/Network-MIME/MIMEDocument.class.st @@ -158,7 +158,7 @@ MIMEDocument >> contentStream [ contentStream ifNil: [contentStream := contents ifNil: [self contentStreamOnURI] - ifNotNil: [(RWBinaryOrTextStream with: self contents) reset]]. + ifNotNil: [self contents readStream]]. ^contentStream ] diff --git a/src/Network-Mail/MIMEDocument.extension.st b/src/Network-Mail/MIMEDocument.extension.st index bc4a3e94fe8..4696ee20bb9 100644 --- a/src/Network-Mail/MIMEDocument.extension.st +++ b/src/Network-Mail/MIMEDocument.extension.st @@ -3,19 +3,23 @@ Extension { #name : #MIMEDocument } { #category : #'*Network-Mail' } MIMEDocument >> parts [ "Return the parts of this message. There is a far more reliable implementation of parts in MailMessage, but for now we are continuing to use this implementation" - | parseStream currLine separator msgStream messages | + | parseStream currLine separator msgStream messages currentLine | self isMultipart ifFalse: [ ^ #() ]. parseStream := self content readStream. currLine := ''. [ '--*' match: currLine ] whileFalse: [ currLine := parseStream nextLine ]. separator := currLine copy. - msgStream := LimitingLineStreamWrapper - on: parseStream - delimiter: separator. + + msgStream := ZnFastLineReader on: parseStream. messages := OrderedCollection new. - [ parseStream atEnd ] whileFalse: - [ messages add: msgStream upToEnd. - msgStream skipThisLine ]. + currentLine := ''. + [ parseStream atEnd or: [ currentLine beginsWith: separator ] ] whileFalse: [ + | message | + message := String streamContents: [:strm | + [(currentLine := msgStream nextLine) isNil] whileFalse: [ + strm nextPutAll: currentLine; cr]]. + messages add: message. + currentLine := msgStream nextLine ]. ^ messages collect: [ :e | MailMessage from: e ] ] diff --git a/src/Network-Mail/MailMessage.class.st b/src/Network-Mail/MailMessage.class.st index 2c6d976e5ac..aa1a3557a8f 100644 --- a/src/Network-Mail/MailMessage.class.st +++ b/src/Network-Mail/MailMessage.class.st @@ -634,7 +634,7 @@ MailMessage >> parseParts [ "If this is not multipart, store an empty collection" - | parseStream msgStream messages separator | + | parseStream msgStream messages separator currentLine | self body isMultipart ifFalse: [ parts := #(). ^ self ]. @@ -647,23 +647,29 @@ MailMessage >> parseParts [ ^ self ]. separator := '--' , separator trimRight. parseStream := self bodyText readStream. - msgStream := LimitingLineStreamWrapper - on: parseStream - delimiter: separator. - msgStream - limitingBlock: [ :aLine | - aLine trimRight = separator - or: [ "Match the separator" aLine trimRight = (separator , '--') ] ]. "or the final separator with --" + msgStream := ZnFastLineReader on: parseStream. "Throw away everything up to and including the first separator" - msgStream upToEnd. - msgStream skipThisLine. + currentLine := ''. + [ currentLine trimRight = separator or: [ "Match the separator" currentLine trimRight = (separator , '--') ] ] + whileFalse: [ currentLine := msgStream nextLine ]. + + "Skip the separator" + currentLine := msgStream nextLine. "Extract each of the multi-parts as strings" messages := OrderedCollection new. - [ parseStream atEnd ] - whileFalse: [ messages add: msgStream upToEnd. - msgStream skipThisLine ]. + [ parseStream atEnd ] whileFalse: [ | message | + message := String streamContents: [ :stream | + [ currentLine trimRight = separator or: [ "Match the separator" currentLine trimRight = (separator , '--') ] ] + whileFalse: [ + stream nextPutAll: currentLine. + currentLine := msgStream nextLine ]. + ]. + messages add: msgStream message. + "Skip the separator" + currentLine := msgStream nextLine + ]. parts := messages collect: [ :e | MailMessage from: e ] ] diff --git a/src/Network-Protocols/FTPClient.class.st b/src/Network-Protocols/FTPClient.class.st index e67247f2b50..7cc512f8764 100644 --- a/src/Network-Protocols/FTPClient.class.st +++ b/src/Network-Protocols/FTPClient.class.st @@ -153,7 +153,7 @@ FTPClient >> get: limit dataInto: dataStream [ FTPClient >> getData [ | dataStream | - dataStream := RWBinaryOrTextStream on: (String new: 4000). + dataStream := (String new: 4000) writeStream. self getDataInto: dataStream. self closeDataSocket. ^dataStream contents @@ -344,13 +344,9 @@ FTPClient >> passive [ FTPClient >> putFileNamed: filePath as: fileNameOnServer [ "FTP a file to the server." - - | fileStream | - fileStream := FileStream readOnlyFileNamed: filePath. - fileStream - ifNil: [(FileDoesNotExistException fileName: filePath) signal]. - self putFileStreamContents: fileStream as: fileNameOnServer - + filePath asFileReference readStreamDo: [ :fileStream | + self putFileStreamContents: fileStream as: fileNameOnServer + ] ] { #category : #protocol } diff --git a/src/PharoBootstrap-Initialization/PharoBootstrapInitialization.class.st b/src/PharoBootstrap-Initialization/PharoBootstrapInitialization.class.st index 4f5003506f7..9fb17f275a6 100644 --- a/src/PharoBootstrap-Initialization/PharoBootstrapInitialization.class.st +++ b/src/PharoBootstrap-Initialization/PharoBootstrapInitialization.class.st @@ -93,7 +93,6 @@ PharoBootstrapInitialization class >> initializeFileSystem [ (env at: #FileLocator) initialize. (env at: #DiskStore) initialize. (env at: #FileHandle) initialize. - (env at: #MultiByteFileStream) initialize. (env at: #File) initialize ] diff --git a/src/System-Changes-FileServices/ChangeSet.extension.st b/src/System-Changes-FileServices/ChangeSet.extension.st index 9733259154d..9597618678f 100644 --- a/src/System-Changes-FileServices/ChangeSet.extension.st +++ b/src/System-Changes-FileServices/ChangeSet.extension.st @@ -4,22 +4,21 @@ Extension { #name : #ChangeSet } ChangeSet class >> fileIntoNewChangeSet: fullName [ "File in all of the contents of the currently selected file, if any, into a new change set." - | fn ff | + | filename | fullName ifNil: [^ self ]. - fn := (Smalltalk hasClassNamed: #GZipReadStream) + filename := (Smalltalk hasClassNamed: #GZipReadStream) ifTrue: [(Smalltalk classNamed: #GZipReadStream) uncompressedFileName: fullName] ifFalse: [fullName]. - [ ff := FileStream readOnlyFileNamed: fn. - self newChangesFromStream: ff named: (fn asFileReference basename)] - ensure: [ff ifNotNil: [ff close]] + filename asFileReference readStreamDo: [ :readStream | + self newChangesFromStream: readStream named: filename asFileReference basename ] ] { #category : #'*System-Changes-FileServices' } ChangeSet class >> fileReaderServicesForFile: fullName suffix: suffix [ - ^ (FileStream isSourceFileSuffix: suffix) + ^ (#('st' 'cs') includes: suffix) ifTrue: [ self services] ifFalse: [#()] ] diff --git a/src/System-Changes/ChangeSet.class.st b/src/System-Changes/ChangeSet.class.st index 5c777b0d87f..d337c0b472e 100644 --- a/src/System-Changes/ChangeSet.class.st +++ b/src/System-Changes/ChangeSet.class.st @@ -959,8 +959,7 @@ ChangeSet >> fileOutOn: stream [ "Write out all the changes the receiver knows about" | classList traits classes traitList list | - (self isEmpty and: [stream isKindOf: FileStream]) - ifTrue: [self inform: 'Warning: no changes to file out']. + self ifEmpty: [self inform: 'Warning: no changes to file out']. traits := self changedClasses select: [:each | each isTrait]. classes := self changedClasses select: [:each | each isBehavior & each isTrait not]. diff --git a/src/System-Installers-Tests/MCMczInstallerTest.class.st b/src/System-Installers-Tests/MCMczInstallerTest.class.st index 491c2e2a448..d6f0502598b 100644 --- a/src/System-Installers-Tests/MCMczInstallerTest.class.st +++ b/src/System-Installers-Tests/MCMczInstallerTest.class.st @@ -87,10 +87,12 @@ MCMczInstallerTest >> testInstallFromFile [ { #category : #tests } MCMczInstallerTest >> testInstallFromStream [ - | stream | - stream := RWBinaryOrTextStream on: ByteArray new. - MCMczWriter fileOut: expected on: stream. - MczInstaller installStream: stream reset. + + | array | + array := ByteArray streamContents: [:stream |. + MCMczWriter fileOut: expected on: stream. + ]. + MczInstaller installStream: array readStream. self assertNoChange. self assertVersionInfoPresent. diff --git a/src/System-SessionManager/SessionManager.class.st b/src/System-SessionManager/SessionManager.class.st index f60710dc468..13c61f4ac0b 100644 --- a/src/System-SessionManager/SessionManager.class.st +++ b/src/System-SessionManager/SessionManager.class.st @@ -149,7 +149,6 @@ SessionManager class >> initializedSessionManager [ registerSystemClassNamed: #Symbol; "System" registerSystemClassNamed: #Locale; "System" registerSystemClassNamed: #WeakArray; "System" - registerSystemClassNamed: #FileStream; "System" registerSystemClassNamed: #BasicCommandLineHandler; "System" registerSystemClassNamed: #NonInteractiveTranscript; "System" registerSystemClassNamed: #ASTCache; "System" diff --git a/src/Tests/FileStreamTest.class.st b/src/Tests/FileStreamTest.class.st deleted file mode 100644 index 3e932288904..00000000000 --- a/src/Tests/FileStreamTest.class.st +++ /dev/null @@ -1,173 +0,0 @@ -Class { - #name : #FileStreamTest, - #superclass : #ClassTestCase, - #category : #'Tests-Files' -} - -{ #category : #private } -FileStreamTest >> doTestsForReading: count intoBufferWithSize: readSize startingAt: startIndex fromFileOfSize: writeSize offsetBy: startOffset [ - "Do the actual assertions for read/write buffers with the given parameters - - If offset > 0, some elements will be fetched from buffer. - If count > writeSize - startOffset, not all will be successfully read." - - | file filename | - filename := 'filestream.tst'. - [ |writeBuffer readBuffer bytesRead| - writeBuffer := (ByteArray new: writeSize). - 0 to: writeSize -1 do: [:ix | writeBuffer at: ix +1 put: (ix \\ 255) + 1]. - - (File named: filename) - writeStreamDo: [ :stream | stream nextPutAll: writeBuffer ]. - file := File openForReadFileNamed: filename. - - readBuffer := ByteArray new: readSize. - - startOffset > 0 ifTrue: [file next: startOffset]. - bytesRead := file - readInto: readBuffer - startingAt: startIndex - count: count. - "Test the count is correct, ie. either read count, or the remaining bytes in write buffer" - self assert: ((writeSize - startOffset) min: count) equals: bytesRead. - - "quick test for total not written" - self assert: readSize - bytesRead equals: (readBuffer occurrencesOf: 0). - - "compare test for readStream and what was in write" - 1 to: readSize do: - [ : n | |expected| - expected := - (n between: startIndex and: startIndex + bytesRead -1) - ifTrue: [ (writeBuffer at: startOffset + n - startIndex +1) ] - ifFalse: [ 0 ]. - self assert: expected equals: (readBuffer at: n) ] ] - ensure: [ - file ifNotNil: [ file close ]. - (FileSystem disk workingDirectory / filename) ensureDelete ] -] - -{ #category : #testing } -FileStreamTest >> testCachingNextChunkPut [ - "Ensure that nextChunkPut:/nextChunk works properly on a caching file" - - | file text read filename | - filename := 'testCachingNextChunkPut'. - [ file := FileStream forceNewFileNamed: filename. - text := 'this is a chunkful of text'. - file nextChunkPut: text. - read := [ file - position: 0; - nextChunk ] valueWithin: 1 seconds onTimeout: [ '' ]. - self assert: read equals: text ] - ensure: [ file close. - (FileSystem disk workingDirectory / filename) ensureDelete ] -] - -{ #category : #testing } -FileStreamTest >> testDetectFileDo [ - | file | - [ file := 'filestream.tst' asFileReference. - file writeStreamDo: [ :s | s nextPutAll: '42' ]. - FileStream - detectFile: [ file readStream ] - do: [ :stream | - self assert: stream notNil. - self deny: stream closed. - self assert: stream upToEnd equals: '42' ] ] - ensure: [ file ensureDelete ] -] - -{ #category : #testing } -FileStreamTest >> testFileTruncation [ - "Ensure that nextChunkPut:/nextChunk works properly on a caching file" - - | file | - file := 'TruncationTest.txt' asFileReference. - [ - file writeStreamDo: [ :s | s nextPutAll: '1234567890' ]. - file - writeStreamDo: [ :s | - s truncate: 4 ]. - file readStreamDo: [ :s | self assert: s contents equals: '1234' ] ] - ensure: [ file ensureDelete ] -] - -{ #category : #testing } -FileStreamTest >> testNextChunkOutOfBounds [ - "Ensure that nextChunkPut:/nextChunk works properly on a caching file" - - | file text read filename | - filename := 'testNextChunkOutOfBounds'. - [ file := FileStream forceNewFileNamed: filename. - text := 'this is a chunkful of text'. - file nextChunkPut: text. - read := [ file - position: 999999; - nextChunk ] valueWithin: 1 seconds onTimeout: [ nil ]. - self assert: read equals: '' ] - ensure: [ file close. - (FileSystem disk workingDirectory / filename) ensureDelete ] -] - -{ #category : #testing } -FileStreamTest >> testNextLine [ - | filename lines text | - filename := 'filestream.tst'. - lines := #('line 1' ' and line 2' '' 'fourth'). - text := lines first , String cr , lines second , String crlf , lines third , String lf , lines fourth. - [ - | file | - (File named: filename) - writeStreamDo: [ :stream | stream nextPutAll: text ]. - file := ZnFastLineReader on: - (ZnCharacterReadStream - on: (File openForReadFileNamed: filename) - encoding: 'utf8'). - lines do: [ :e | self assert: file nextLine equals: e ]. - self assert: file nextLine isNil. - file close ] ensure: [ - (FileSystem disk workingDirectory / filename) ensureDelete ]. -] - -{ #category : #testing } -FileStreamTest >> testReadIntoStartingAtCountAll [ - "Tests for correct count and contents when all could be read, none pre-buffered" - self doTestsForReading: 100 - intoBufferWithSize: 400 - startingAt: 100 - fromFileOfSize: 200 - offsetBy: 0. - -] - -{ #category : #testing } -FileStreamTest >> testReadIntoStartingAtCountBufferedAll [ - "Tests for correct count and contents when all could be read, some pre-buffered" - self doTestsForReading: 5000 - intoBufferWithSize: 6000 - startingAt: 500 - fromFileOfSize: 6000 - offsetBy: 200. -] - -{ #category : #testing } -FileStreamTest >> testReadIntoStartingAtCountBufferedNotAll [ - "Tests for correct count and contents when all could be read, some pre-buffered" - self doTestsForReading: 8000 - intoBufferWithSize: 10000 - startingAt: 500 - fromFileOfSize: 6000 - offsetBy: 200. -] - -{ #category : #testing } -FileStreamTest >> testReadIntoStartingAtCountNotAll [ - - "Tests for correct count and contents when not all could be read, and none pre-buffered" - self doTestsForReading: 500 - intoBufferWithSize: 800 - startingAt: 10 - fromFileOfSize: 300 - offsetBy: 0. -] diff --git a/src/Tests/TraitFileOutTest.class.st b/src/Tests/TraitFileOutTest.class.st index 9bd56a38bc4..7b676b82a72 100644 --- a/src/Tests/TraitFileOutTest.class.st +++ b/src/Tests/TraitFileOutTest.class.st @@ -69,9 +69,8 @@ TraitFileOutTest >> testFileOutCategory [ self class environment organization fileOutCategory: self categoryName. self class environment organization removeSystemCategory: self categoryName. self deny: (testingEnvironment keys asSet includesAnyOf: #(#CA #CB #TA #TB #TC #TD)). - [ - file := FileStream readOnlyFileNamed: self categoryName , '.st'. - file fileIn ] ensure: [ file close ]. + + CodeImporter evaluateFileNamed: (self categoryName , '.st'). self assertCollection: testingEnvironment keys asSet includesAll: #(#CA #CB #TA #TB #TC #TD). ta := testingEnvironment at: #TA. self assert: ta traitComposition asString equals: '((TB + TC) @ {#cc->#c}) - {#c}'. @@ -87,16 +86,15 @@ TraitFileOutTest >> testFileOutCategory [ TraitFileOutTest >> testFileOutTrait [ "fileOut trait T6, remove it from system and then file it in again" - | fileName file | + | fileName | self t6 compile: 'localMethod: argument ^argument'. self t6 classSide compile: 'localClassSideMethod: argument ^argument'. self t6 fileOut. fileName := self t6 asString , '.st'. self resourceClassesAndTraits remove: self t6. self t6 removeFromSystem. - [ - file := FileStream readOnlyFileNamed: fileName. - file fileIn ] ensure: [ file close ]. + + CodeImporter evaluateFileNamed: fileName. self assert: (testingEnvironment includesKey: #T6). TraitsResource current t6: (testingEnvironment at: #T6). self resourceClassesAndTraits add: self t6. diff --git a/src/Tool-ExternalBrowser/ExternalChangesBrowser.class.st b/src/Tool-ExternalBrowser/ExternalChangesBrowser.class.st index 77050b554b2..f639d455d97 100644 --- a/src/Tool-ExternalBrowser/ExternalChangesBrowser.class.st +++ b/src/Tool-ExternalBrowser/ExternalChangesBrowser.class.st @@ -67,8 +67,8 @@ ExternalChangesBrowser class >> fileReaderServicesForFile: fullName suffix: suff | services | services := OrderedCollection new. - (FileStream isSourceFileSuffix: suffix) | - (FileStream isChangesFileSuffix: suffix) | (suffix = '*') + (ExternalBrowser sourceFileSuffixes includes: suffix) | + ('changes' = suffix) | (suffix = '*') ifTrue: [ services add: self serviceBrowseCSOrSTFile ]. ^services ] diff --git a/src/Tool-FileList/FileList.class.st b/src/Tool-FileList/FileList.class.st index c6562bce0ea..321e508e12c 100644 --- a/src/Tool-FileList/FileList.class.st +++ b/src/Tool-FileList/FileList.class.st @@ -585,7 +585,7 @@ FileList >> fileContentsMenu: aMenu shifted: shifted [ [services add: self serviceGetHex]. (#(needToGetShiftJIS needToGetEUCJP needToGetCNGB needToGetEUCKR needToGetUTF8) includes: brevityState) ifFalse: [services add: self serviceGetEncodedText]. - (FileStream sourceFileSuffixes includes: self suffixOfSelectedFile) ifTrue: + (#('st' 'cs') includes: self suffixOfSelectedFile) ifTrue: [services addAll: (self itemsForFile: reference)]. aMenu @@ -1229,7 +1229,7 @@ FileList >> readContentsHex: brevity [ { #category : #'file list' } FileList >> readOnlyStream [ "Answer a read-only stream on the selected file. For the various stream-reading services." - ^ FileStream readOnlyFileNamed: self reference fullName + ^ self reference readStream ] { #category : #accessing } diff --git a/src/Tool-FileList/FileStream.extension.st b/src/Tool-FileList/FileStream.extension.st deleted file mode 100644 index c502814b168..00000000000 --- a/src/Tool-FileList/FileStream.extension.st +++ /dev/null @@ -1,55 +0,0 @@ -Extension { #name : #FileStream } - -{ #category : #'*Tool-FileList' } -FileStream >> edit [ - "Create and schedule an editor on this file." - - Smalltalk tools fileList openEditorOn: self editString: nil. - -] - -{ #category : #'*Tool-FileList' } -FileStream class >> fileReaderServicesForFile: fullName suffix: suffix [ - - "Answer services for the given file" - - ^ ((self isSourceFileSuffix: suffix) or: [ suffix = '*' ]) - ifTrue: - [{self serviceRemoveLineFeeds. - self serviceFileIn}] - ifFalse: - [#()] -] - -{ #category : #'*Tool-FileList' } -FileStream class >> serviceFileIn [ - "Answer a service for filing in an entire file" - - ^ SimpleServiceEntry - provider: self - label: 'FileIn entire file' - selector: #fileIn: - description: 'File in the entire contents of the file, which is expected to contain Smalltalk code in fileout ("chunk") format' - buttonLabel: 'Filein' -] - -{ #category : #'*Tool-FileList' } -FileStream class >> serviceRemoveLineFeeds [ - "Answer a service for removing linefeeds from a file" - - ^ FileModifyingSimpleServiceEntry - provider: self - label: 'Remove line feeds' - selector: #removeLineFeeds: - description: 'Remove line feeds in file' - buttonLabel: 'Remove lfs' -] - -{ #category : #'*Tool-FileList' } -FileStream class >> services [ - - ^ Array - with: self serviceRemoveLineFeeds - with: self serviceFileIn - -] diff --git a/src/Zinc-Resource-Meta-Core/FileStream.extension.st b/src/Zinc-Resource-Meta-Core/FileStream.extension.st deleted file mode 100644 index b9851bf207e..00000000000 --- a/src/Zinc-Resource-Meta-Core/FileStream.extension.st +++ /dev/null @@ -1,25 +0,0 @@ -Extension { #name : #FileStream } - -{ #category : #'*zinc-resource-meta-core' } -FileStream >> asUrl [ - ^ self asZnUrl -] - -{ #category : #'*zinc-resource-meta-core' } -FileStream >> asZnUrl [ - "Convert the receiver in a file:// ZnUrl" - - | fileUrl | - fileUrl := ZnUrl new. - fileUrl scheme: #file. - self directory pathSegments do: [ :each | fileUrl addPathSegment: each ]. - fileUrl addPathSegment: self localName. - ^ fileUrl -] - -{ #category : #'*zinc-resource-meta-core' } -FileStream >> url [ - "Convert my path into a file:// type url String." - - ^self asUrl asString -] diff --git a/src/Zinc-Zodiac/ZnHTTPSTest.class.st b/src/Zinc-Zodiac/ZnHTTPSTest.class.st index 9037a3665da..bfdb53cc9c0 100644 --- a/src/Zinc-Zodiac/ZnHTTPSTest.class.st +++ b/src/Zinc-Zodiac/ZnHTTPSTest.class.st @@ -36,7 +36,7 @@ ZnHTTPSTest class >> generateTestFiles [ (Integer primesUpTo: 100) do: [ :each | | size | size := 1024 * each + each. - FileStream fileNamed: ('test-', size asString, '.txt') do: [ :stream | + ('test-', size asString, '.txt') asFileReference writeStreamDo: [ :stream | stream nextPutAll: (self generateTestData: size) ] ] ]