Chronos is one of the many Smalltalk-related blogs syndicated on Planet Smalltalk
χρόνος

Discussion of the Essence# programming language, and related issues and technologies.

Blog Timezone: America/Los_Angeles [Winter: -0800 hhmm | Summer: -0700 hhmm] 
Your local time:  
Showing posts with label Passport. Show all posts
Showing posts with label Passport. Show all posts

2007-02-16

Handling various text file line-end conventions in VW

Martin Kobetic has posted an excellent tutorial on handling different text file line-end conventions in VisualWorks.

The Passport inter-Smalltalk portability library (on which the Chronos Date/Time Library depends) also provides a solution to the same problem:


  • UtilityFunction nextLineFrom: aStream

  • UtilityFunction skipToNextLineOf: aStream

Both of the above functions will work with any of the three text file line-end conventions currently encountered in the wild: CRLF (Windows,) LF (Unix/Linix/MacOS X) and CR (classic MacOS.)

Passport does not provide any support for writing text files using different line-end conventions, for two reasons:

  1. The external WriteStreams provided by most Smalltalk implementations will already convert CR to the host platform's line-end convention.

  2. Given the ability to read text files correctly, regardless of line-end convetion, there is not as much need to be able to write files with any particular line-end convention.

Chronos uses both of the above Passport functions in order to read time zone and other information from text files stored in the Chronos Time Zone Repository. Using those two Passport functions not only provides Chronos with inter-Smalltalk portability, it also means that a single version of the Chronos Time Zone Repository can be used on all host platforms, even when the text files were generated on a different operating system.


2007-01-31

Filenames and Inter-Smalltalk Portability

Troy Brumley, in his blog post File access demo from VW to Squeak (2006-06-03), picks up on some example VisualWorks code posted by James Robertson a day earlier (Simple File I/O Demo, 2006-06-02.) Troy's examples show how to code the same thing in Squeak.

But there is another option: Use the Passport inter-Smalltalk portability library that was implemented in order to make it possible to host The Chronos Date/Time Library on VisualWorks, Squeak and Dolphin. Using Passport, the code will work unchanged in VisualWorks, Squeak and Dolphin.

Here's the Passport version (with Jim's original variable names unchanged, even though they aren't the best names for use with Passport):

"write a simple file"
file := 'myTestFile.txt' asResourcePath.
stream := file writeStream.
stream nextPutAll: 'Line 1'.
stream nextPut: Character cr.
stream nextPutAll: 'Line 2'.
stream nextPut: Character cr.
stream nextPutAll: 'Line 3'.
stream nextPut: Character cr.
stream close.

"read the entire file"
file := 'myTestFile.txt' asResourcePath.
contents := file value.
^contents.

"read line by line"
file := 'myTestFile.txt' asResourcePath.
stream := file readStream.
lines := OrderedCollection new.
[stream atEnd]
whileFalse: [| line |
line := UtilityFunction nextLineFrom: stream.
lines add: line].
stream close.
^lines.

"finding the file"
directory := '.' asResourcePath.
files := OrderedCollection new.
directory contentsDo: [:resourcePath | ('myTest*' match: resourcePath suffixString) ifTrue: [files add: resourcePath]].
^files.

(To see Jim's original VW code, follow this link: Simple File I/O Demo (VW code))

Passport not only makes it possible to write the same file name logic portably among different Smalltalk versions, it also makes it possible to use the same code regardless of whether the host operating system is Unix, MacOS X or Windows. But to do that, there are some constraints:

Firstly, either you can't use absolute pathnames, or else the absolute path must be constructed at run time by appending a well-known path suffix onto a path prefix that is supplied as a parameter at run time (and which will necessarily differ from one host OS to another, and often also even between different computers, even when they all use the same OS.)

Secondly, the relative path suffix must be constructed using a Pathname, as in the following example:
| resourcePath stream |
resourcePath := (Pathname fromString: 'test/folder1') asResourcePath.
resourcePath makeDirectory.
resourcePath := resourcePath, 'junk.txt'.
"The ResoucePath is now [./test/folder1/junk.txt]"
stream := resourcePath newWriteStream.
stream nextPutAll: 'This is a test.'.
stream close.


Typically, one would construct a ResourcePath using a path prefix obtained from your application's configuration parameters, using a well-known (or deterministically computable) path suffix. For example, the Chronos Date/Time Library might construct the path to a Chronos time zone ruleset file as follows:

(ResourcePath
namespace:
(EnvironmentFacade current
valueOfEnvironmentVariableAt: 'CHRONOS_PATH')
pathname:
(Pathname
fromString: 'time-zones/rulesets/Pacific/Honolulu'))
appendingExtension: 'tzn'

On the Windows machine I use for Chronos development, doing a "print it" on the above example would have the following result: H:\Dev\Smalltalk\Chronos\Chronos Versions\VisualWorks\Chronos\time-zones\rulesets\Pacific\Honolulu.tzn.

The Squeak version of Passport is available as two of the files in the version of Chronos.zip distributed for Squeak (namely, "Passport-Kernel.st" and "Passport-Squeak.st.") It's also available from SqueakSource (in the Chronos project.)

The VisualWorks version can be obtained from the Cincom Public StORE. It can also be filed out or parcelled out after installing the VisualWorks version of Chronos (it's in the packages Passport-Kernel and Passport-Kernel-VW.)

The Dolphin version of Passport is available on request (requests (at) chronos-st (dot) org).