FileText.st
author claus
Mon, 04 Oct 1993 11:32:27 +0100
changeset 1 85d662a8509f
parent 0 1cf8d1747859
child 2 07d9ee98e092
permissions -rw-r--r--
2.7.2

"
 COPYRIGHT (c) 1989/90/91 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

Text subclass:#FileText
       instanceVariableNames:'myStream lastLineKnown lastLineOfFile
                              cachedLines cacheLineNr'
       classVariableNames:''
       poolDictionaries:''
       category:'Collections-Text'
!

FileText comment:'

COPYRIGHT (c) 1989/90/91 by Claus Gittinger
              All Rights Reserved

FileText represents the contents of a text-file;
in core only the offsets of the text-lines are stored in an array
to save space; the at: method fetches the line from the file.
Individual textlines may be replaced by strings.
the underlying file is NOT updated in this case

@(#)FileText.st	2.3 92/06/06
'!

!FileText class methodsFor:'instance creation'!

of:aStream
    "return a new FileText object for the stream aStream"

    ^ (self new:1) of:aStream
!

ofFile:aFileName
    "return a new FileText object for the named file"

    |aStream|

    aStream := FileStream readonlyFileNamed:aFileName.
    aStream isNil ifTrue:[^ nil].
    ^ (self new:1) of:aStream
! !

!FileText methodsFor:'accessing'!

of:aStream
    myStream := aStream.
    lastLineOfFile := nil.
    lastLineKnown := 0.
    cachedLines := nil
! !

!FileText methodsFor:'accessing'!

at:index
    |entry oldPosition|

    (index > lastLineKnown) ifTrue:[
        self scanUpToLine:index.
        (lastLineOfFile notNil) ifTrue:[
            (index > lastLineOfFile) ifTrue:[
                ^ self subscriptBoundsError
            ]
        ]
    ].

    entry := super at:index.
    (entry isMemberOf:String) ifTrue:[^ entry].

    cachedLines isNil ifTrue:[
        cachedLines := Array new:50.
        cacheLineNr := -9999
    ].
    ((index < cacheLineNr)
     or:[index >= (cacheLineNr + cachedLines size)]) ifTrue:[
        oldPosition := myStream position.
        myStream position:entry.
        1 to:(cachedLines size) do:[:cacheIndex|
            cachedLines at:cacheIndex put:(myStream nextLine)
        ].
        myStream position:oldPosition.
        cacheLineNr := index
    ].

    ^ cachedLines at:(index - cacheLineNr + 1)
!
    
size
    "return the number of text-lines - have to scan file the first time"

    (lastLineOfFile isNil) ifTrue:[
        self scanUpToEnd
    ].
    ^ lastLineOfFile
! !

!FileText methodsFor:'enumerating'!

do:aBlock
    self from:1 to:(self size) do:aBlock
!

from:index1 to:index2 do:aBlock
    "must be redefined back since elements are indices into file, not the elements themselfes"

    |index "{ Class: SmallInteger }"
     stop  "{ Class: SmallInteger }" |

    index := index1.
    stop := index2.
    [index <= stop] whileTrue:[
        aBlock value:(self at:index).
        index := index + 1
    ]

! !

!FileText methodsFor:'private'!

scanUpToEnd
    "scan myStream up to the end of file"

    (lastLineOfFile notNil) ifTrue:[^ self].
    [true] whileTrue:[
        lastLineKnown := lastLineKnown + 1.
        (super size < lastLineKnown) ifTrue:[
            super grow:(super size * 2 + 1)
        ].
        super at:lastLineKnown put:(myStream position).
        myStream skipLine isNil ifTrue:[
            lastLineOfFile := lastLineKnown.
            ^ self
        ]
    ]
!

scanUpToLine:index
    "scan myStream up to line index and save line-start-positions"

    (lastLineOfFile notNil) ifTrue:[
        (index > lastLineOfFile) ifTrue:[^ self]
    ].
    [lastLineKnown <= index] whileTrue:[
        lastLineKnown := lastLineKnown + 1.
        (super size < lastLineKnown) ifTrue:[
            super grow:(super size * 2 + 1)
        ].
        super at:lastLineKnown put:(myStream position).
        myStream skipLine isNil ifTrue:[
            lastLineOfFile := lastLineKnown.
            ^ self
        ]
    ]
! !