Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 1 participants
- 144633 messages
Re: [Pharo-dev] Executive Summary of the recent FileStream Changes
by monty
> Sent: Thursday, March 15, 2018 at 4:01 PM
> From: "Sven Van Caekenberghe" <sven(a)stfx.eu>
> To: "Pharo Development List" <pharo-dev(a)lists.pharo.org>
> Subject: [Pharo-dev] Executive Summary of the recent FileStream Changes
>
> Executive Summary of the recent FileStream Changes
>
> In Pharo 7 Guille Polito recently committed a heroic set of changes that we were planning to do for a long time but were afraid to take on.
>
> The idea is to replace a couple of fat, overly complex, multi-functional, do-all classes with a set of simpler single purpose classes that can be combined as needed.
>
> The classes that we want to get rid of can be found in the package DeprecatedFileSystem, in particular FileStream, StandardFileStream, MultiByteFileStream, MultiByteBinaryOrTextStream and RWBinaryOrTextStream.
StandardFileStream, at least, should remain for backwards compatibility and cross-platform compatibility with Squeak. It's a no-frills, non-decoding, non-LE normalizing stream that is heavily depended on.
> The replacements are can be found in packages Files and Zinc-Character-Encoding-Core.
>
> Encoding and decoding characters to and from bytes is done using classes that you wrap around a more primitive binary stream. The same goes for buffering or translating line endings.
>
> For example,
>
> '/Users/sven/Desktop/foo.txt' asFileReference binaryReadStream.
>
> gives you a ZnBufferedWriteStream wrapping a BinaryWriteStream.
>
> While,
>
> '/Users/sven/Desktop/foo.txt' asFileReference readStream.
What do you think about this algorithm for encoding detection: http://www.yaml.org/spec/1.2/spec.html#id2771184
I have an implementation (with tests), if you're interested. (I was waiting to propose it until the FileSystem API switched over to using Zn streams and encoders. The TextConverter API doesn't support UTF-32.)
> gives a ZnCharacterReadStream wrapping a ZnBufferedWriteStream wrapping a BinaryWriteStream.
>
> To translate line endings, we would wrap a ZnCharacterWriteStream using a ZnCrPortableWriteStream.
>
> There are a couple of more specialised streams to cover special cases (like read and writing at the same time).
>
> SocketStream remains another fat, overly complex, multi-functional, do-all class, for which usable replacements exist in the form of ZdcSocketStream and ZdcSecureSocketStream, which are simpler, cleaner and binary only.
>
> Of course, switching is more than replacing one class with a 100% compatible alternative, that would give us the same complex result. The challenge is to use a simpler API as well, to rethink how the streams are used. You know, KISS.
>
> Of course, we are far from done and need more testing, debugging and help from as many people as possible.
>
> Sven
>
>
> --
> Sven Van Caekenberghe
> Proudly supporting Pharo
> http://pharo.org
> http://association.pharo.org
> http://consortium.pharo.org
>
>
>
>
>
>
March 16, 2018
Re: [Pharo-dev] [Vm-dev] Reproducible VM crash from commit 4749358 onwards
by Eliot Miranda
Hi Alistair,
I can reproduce this on Mac OS too. Thanks very much for the report.
Looking at it now.
On Thu, Mar 15, 2018 at 2:43 PM, Alistair Grant <akgrant0710(a)gmail.com>
wrote:
>
> Hi Everyone,
>
> If I download a recent Pharo 64 bit image, e.g.:
>
> http://files.pharo.org/image/70/latest-64.zip
>
> And use a Pharo VM from commit:
>
> commit 4749358b5717b9a2f7e1d44f9baac48ed5d80431
> Author: Eliot Miranda <eliot.miranda(a)gmail.com>
> Date: Wed Mar 7 15:11:21 2018 -0800
>
> or later, the following will reliably crash the VM:
>
>
> ./pharo Pharo7.0-64bit-a26248b.image eval "OCBytecodeGeneratorTest
> run: #testExample2"
>
>
> Earlier VMs don't crash.
>
> Stack dump below my signature.
>
> I'm a bit out of my depth beyond that...
>
> OS: Ubuntu 16.04 64 bit
>
>
> Cheers,
> Alistair
>
>
> Segmentation fault Thu Mar 15 22:39:13 2018
>
>
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo
> Pharo VM version: 5.0-201803072311 Thursday 15 March 22:35:05 CET
> 2018 c99 [Production Spur 64-bit VM]
> Built from: CoInterpreter VMMaker.oscog-eem.2347 uuid:
> 062614a7-e3da-4b30-997a-9568911b9ff5 Mar 15 2018
> With: StackToRegisterMappingCogit VMMaker.oscog-eem.2347 uuid:
> 062614a7-e3da-4b30-997a-9568911b9ff5 Mar 15 2018
> Revision: VM: 201803072311
> alistair@59fbe1b42048:vmmaker/opensmalltalk-vm $ Date: Wed Mar 7
> 15:11:21 2018 -0800 $ Plugins: 201803072311
> alistair@59fbe1b42048:vmmaker/opensmalltalk-vm $
> Build host: Linux 59fbe1b42048 4.13.0-36-generic #40~16.04.1-Ubuntu
> SMP Fri Feb 16 23:25:58 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
> plugin path: /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311
> [default: /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/]
>
>
> C stack backtrace & registers:
> rax 0x13ab4880 rbx 0x13ab4710 rcx 0x13ab4938 rdx 0x13ab47c8
> rdi 0x13ab44e8 rsi 0x13ab44e8 rbp 0x13ab4658 rsp 0x13ab49f0
> r8 0x13ab3f28 r9 0x13ab3fe0 r10 0x13ab4098 r11 0x13ab4150
> r12 0x13ab4208 r13 0x13ab42c0 r14 0x13ab4378 r15 0x13ab4430
> rip 0x13ab4aa8
> *[0x7ffd13ab4aa8]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x41aca2]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x41c87e]
> /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f78ad605390]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(lengthOf+0x0)[0x42aca0]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(
> cogselector+0x27)[0x49bf77]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x45b15c]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x45b444]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(
> interpret+0xb238)[0x469208]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x46a4db]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(
> interpret+0x246)[0x45e216]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(main+0x2f8)[0x419f98]
> /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f78acf41830]
> /home/alistair/vmmaker/opensmalltalk-vm/products/
> cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(_start+0x29)[0x41a309]
> [0x0]
>
>
> Smalltalk stack dump:
> 0x7ffd13ad4550 I CompiledMethod>valueWithReceiver:arguments:
> 0x1d7e790: a(n) CompiledMethod
> 0x7ffd13ad45a0 M OCBytecodeGeneratorTest>testExample2 0x1d78910:
> a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad1ea0 I OCBytecodeGeneratorTest(TestCase)>performTest
> 0x1d78910: a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad1ed0 M [] in OCBytecodeGeneratorTest(TestCase)>runCase
> 0x1d78910: a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad1f10 M BlockClosure>ensure: 0x1d7a450: a(n) BlockClosure
> 0x7ffd13ad1f58 I OCBytecodeGeneratorTest(TestCase)>runCase
> 0x1d78910: a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad1f90 M [] in
> TestExecutionEnvironment>runTestCaseSafelly: 0x1d78f28: a(n)
> TestExecutionEnvironment
> 0x7ffd13ad1fc0 M BlockClosure>on:do: 0x1d7a330: a(n) BlockClosure
> 0x7ffd13ad2008 M [] in
> TestExecutionEnvironment>runTestCaseSafelly: 0x1d78f28: a(n)
> TestExecutionEnvironment
> 0x7ffd13ad2038 M BlockClosure>on:do: 0x1d7a1a8: a(n) BlockClosure
> 0x7ffd13ad2088 I TestExecutionEnvironment>runTestCaseSafelly:
> 0x1d78f28: a(n) TestExecutionEnvironment
> 0x7ffd13ad20c8 M [] in TestExecutionEnvironment>runTestCase:
> 0x1d78f28: a(n) TestExecutionEnvironment
> 0x7ffd13ad2108 M BlockClosure>ensure: 0x1d7a0a8: a(n) BlockClosure
> 0x7ffd13ad2148 M [] in TestExecutionEnvironment>runTestCase:
> 0x1d78f28: a(n) TestExecutionEnvironment
> 0x7ffd13ad2188 M BlockClosure>ifCurtailed: 0x1d79fa8: a(n) BlockClosure
> 0x7ffd13ad21d0 I TestExecutionEnvironment>runTestCase: 0x1d78f28:
> a(n) TestExecutionEnvironment
> 0x7ffd13ad2218 M [] in DefaultExecutionEnvironment>runTestCase:
> 0x23f7c30: a(n) DefaultExecutionEnvironment
> 0x7ffd13ad2258 M [] in CurrentExecutionEnvironment
> class>activate:for: 0x2404bf8: a(n) CurrentExecutionEnvironment class
> 0x7ffd13ad2298 M BlockClosure>ensure: 0x1d79280: a(n) BlockClosure
> 0x7ffd13ad22e8 I CurrentExecutionEnvironment class>activate:for:
> 0x2404bf8: a(n) CurrentExecutionEnvironment class
> 0x7ffd13ad2338 I
> TestExecutionEnvironment(ExecutionEnvironment)>beActiveDuring:
> 0x1d78f28: a(n) TestExecutionEnvironment
> 0x7ffd13ad2388 I DefaultExecutionEnvironment>runTestCase:
> 0x23f7c30: a(n) DefaultExecutionEnvironment
> 0x7ffd13ad23d0 I CurrentExecutionEnvironment class>runTestCase:
> 0x2404bf8: a(n) CurrentExecutionEnvironment class
> 0x7ffd13ad2418 I OCBytecodeGeneratorTest(TestCase)>runCaseManaged
> 0x1d78910: a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad2450 M [] in TestResult>runCase: 0x1d78930: a(n) TestResult
> 0x7ffd13ad2480 M BlockClosure>on:do: 0x1d78d50: a(n) BlockClosure
> 0x7ffd13ad24d0 I TestResult>runCase: 0x1d78930: a(n) TestResult
> 0x7ffd13ad2510 M [] in OCBytecodeGeneratorTest(TestCase)>run
> 0x1d78910: a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad2550 M BlockClosure>ensure: 0x1d78c50: a(n) BlockClosure
> 0x7ffd13ad25a0 I OCBytecodeGeneratorTest(TestCase)>run 0x1d78910:
> a(n) OCBytecodeGeneratorTest
> 0x7ffd13ad0100 I OCBytecodeGeneratorTest class(TestCase
> class)>run: 0x36155c8: a(n) OCBytecodeGeneratorTest class
> 0x7ffd13ad0138 M UndefinedObject>DoIt 0x23e78e0: a(n) UndefinedObject
> 0x7ffd13ad0198 I OpalCompiler>evaluate 0x1c76f90: a(n) OpalCompiler
> 0x7ffd13ad01d8 I OpalCompiler(AbstractCompiler)>evaluate:
> 0x1c76f90: a(n) OpalCompiler
> 0x7ffd13ad0220 M [] in EvaluateCommandLineHandler>evaluate:
> 0x1c770e8: a(n) EvaluateCommandLineHandler
> 0x7ffd13ad0250 M BlockClosure>on:do: 0x1c77118: a(n) BlockClosure
> 0x7ffd13ad02a8 I EvaluateCommandLineHandler>evaluate: 0x1c770e8:
> a(n) EvaluateCommandLineHandler
> 0x7ffd13ad02f8 I EvaluateCommandLineHandler>evaluateArguments
> 0x1c770e8: a(n) EvaluateCommandLineHandler
> 0x7ffd13ad0338 I EvaluateCommandLineHandler>activate 0x1c770e8:
> a(n) EvaluateCommandLineHandler
> 0x7ffd13ad0378 I EvaluateCommandLineHandler
> class(CommandLineHandler class)>activateWith: 0x252d400: a(n)
> EvaluateCommandLineHandler class
> 0x7ffd13ad03b8 M [] in
> PharoCommandLineHandler(BasicCommandLineHandler)>activateSubCommand:
> 0x55380b8: a(n) PharoCommandLineHandler
> 0x7ffd13ad03e8 M BlockClosure>on:do: 0x1c77390: a(n) BlockClosure
> 0x7ffd13ad0428 M
> PharoCommandLineHandler(BasicCommandLineHandler)>activateSubCommand:
> 0x55380b8: a(n) PharoCommandLineHandler
> 0x7ffd13ad0478 I
> PharoCommandLineHandler(BasicCommandLineHandler)>handleSubcommand
> 0x55380b8: a(n) PharoCommandLineHandler
> 0x7ffd13ad04b8 I
> PharoCommandLineHandler(BasicCommandLineHandler)>handleArgument:
> 0x55380b8: a(n) PharoCommandLineHandler
> 0x7ffd13ad04f0 M [] in
> PharoCommandLineHandler(BasicCommandLineHandler)>activate 0x55380b8:
> a(n) PharoCommandLineHandler
> 0x7ffd13ad0520 M BlockClosure>on:do: 0x1c77628: a(n) BlockClosure
> 0x7ffd13ad0560 M [] in
> PharoCommandLineHandler(BasicCommandLineHandler)>activate 0x55380b8:
> a(n) PharoCommandLineHandler
> 0x7ffd13ad05a0 I [] in BlockClosure>newProcess 0x1c77720: a(n)
> BlockClosure
>
> Most recent primitives
> stringHash:initialHash:
> basicNew
> successorSequences
> basicNew
> basicNew
> basicNew
> **StackOverflow**
> basicNew
> basicNew
> basicIdentityHash
> basicNew
> basicNew
> stringHash:initialHash:
> stringHash:initialHash:
> stringHash:initialHash:
> literal
> parameterAt:
> stringHash:initialHash:
> isInteger
> stringHash:initialHash:
> stringHash:initialHash:
> size
> findSubstring:in:startingAt:matchTable:
> indexOfAscii:inString:startingAt:
> indexOfAscii:inString:startingAt:
> stringHash:initialHash:
> stringHash:initialHash:
> *
> *
> size
> size
> copyWith:
> bitShift:
> bitShift:
> numTemps
> numTemps
> numTemps
> numTemps
> numTemps
> numTemps
> basicIdentityHash
> basicNew:
> size
> basicNew
> at:put:
> at:put:
> basicNew:
> stringHash:initialHash:
> compare:with:collated:
> perform:
> encodeNoTrailer
> encodeNoTrailer
> encodeNoTrailer
> encodeNoTrailer
> encodeNoTrailer
> encodeNoTrailer
> encodeNoTrailer
> at:put:
> at:put:
> at:put:
> at:put:
> basicNew
> size
> at:put:
> at:put:
> at:put:
> at:put:
> objectAt:put:
> objectAt:put:
> objectAt:put:
> objectAt:put:
> objectAt:put:
> collect:
> basicNew
> bitAnd:
> **PrimitiveFailure**
> bitAnd:
> **PrimitiveFailure**
> bitOr:
> **PrimitiveFailure**
> bitOr:
> **PrimitiveFailure**
> bitClear:
> new:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:put:
> stringHash:initialHash:
> objectAt:put:
> withArgs:executeMethod:
> basicNew
> class
> basicNew
> primUTCMicrosecondsClock
> *
> **PrimitiveFailure**
> digitMultiply:neg:
> basicNew
> primOffset
> digitCompare:
> //
> \\
> valueNoContextSwitch
> class
> class
> basicNew
> class
> class
> value
> class
> **StackOverflow**
> basicIdentityHash
> basicNew
> basicNew
> basicNew
> new:
> valueNoContextSwitch
> size
> new:
> size
> size
> at:put:
> basicNew:
> stackp:
> basicNew
> size
> at:
> at:
> at:
> at:
> psValueAt:put:
> psValueAt:put:
> psValueAt:put:
> psValueAt:put:
> psValueAt:put:
> primitiveResume
> repeat
> wait
> class
> millisecondClockValue
> basicNew
> signal
> primUTCMicrosecondsClock
> millisecondDelayDuration
> +
> primSignal:atUTCMicroseconds:
> wait
> wait
> class
> signal
> basicNew
> valueNoContextSwitch
> signal
> primUTCMicrosecondsClock
> at:put:
> at:
> at:put:
> primSignal:atUTCMicroseconds:
> wait
> wait
> valueNoContextSwitch
> wait
> ifCurtailed:
> basicNew
> value
> class
> valueNoContextSwitch
> perform:
> **StackOverflow**
> basicNew
> basicNew
> basicNew
> basicIdentityHash
> **StackOverflow**
> **StackOverflow**
> size
> indexOfAscii:inString:startingAt:
> at:
> at:
> at:
> basicIdentityHash
> value
> class
> linkTo:
> basicNew
> value
> basicIdentityHash
> stringHash:initialHash:
> stringHash:initialHash:
> size
> stringHash:initialHash:
> stringHash:initialHash:
> basicNew
> -
> class
> new:
> at:put:
> perform:withArguments:
> from:if:goto:otherwise:
> size
> size
> size
> at:
> ~=
> size
> at:put:
> basicNew:
> stringHash:initialHash:
> compare:with:collated:
> newMethod:header:
> at:put:
> at:put:
> at:put:
> at:put:
> basicNew
> size
> size
> size
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> at:put:
> objectAt:put:
> objectAt:put:
> objectAt:put:
> objectAt:put:
> from:if:goto:otherwise:
> from:if:goto:otherwise:
> from:if:goto:otherwise:
> objectAt:put:
> new:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:
> at:put:
> objectAt:
> at:put:
> class
> @
> withArgs:executeMethod:
>
> stack page bytes 8192 available headroom 5576 minimum unused headroom 6032
>
> (Segmentation fault)
>
--
_,,,^..^,,,_
best, Eliot
March 15, 2018
Re: [Pharo-dev] Executive Summary of the recent FileStream Changes
by Nicolas Cellier
Very good initiative!
It's worth a few hick-ups.
I've tried to reduce RWBinaryOrTextStream usage in Squeak maybe 10 years
ago, but you know it very well, the last places which are resisting are the
more intricated and convoluted.
I call it the SwiisKnifeStream and allways wandered why we would have to
carry so many subclasses of Stream, since we have one capable of almost
everything!
Managing the states in such a hierarchy was an art, if ever torture is an
art... and we are loosing a great can of worms for fishing the bugs.
So, R.I.P. and no regret!
2018-03-15 21:01 GMT+01:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Executive Summary of the recent FileStream Changes
>
> In Pharo 7 Guille Polito recently committed a heroic set of changes that
> we were planning to do for a long time but were afraid to take on.
>
> The idea is to replace a couple of fat, overly complex, multi-functional,
> do-all classes with a set of simpler single purpose classes that can be
> combined as needed.
>
> The classes that we want to get rid of can be found in the package
> DeprecatedFileSystem, in particular FileStream, StandardFileStream,
> MultiByteFileStream, MultiByteBinaryOrTextStream and RWBinaryOrTextStream.
>
> The replacements are can be found in packages Files and
> Zinc-Character-Encoding-Core.
>
> Encoding and decoding characters to and from bytes is done using classes
> that you wrap around a more primitive binary stream. The same goes for
> buffering or translating line endings.
>
> For example,
>
> '/Users/sven/Desktop/foo.txt' asFileReference binaryReadStream.
>
> gives you a ZnBufferedWriteStream wrapping a BinaryWriteStream.
>
> While,
>
> '/Users/sven/Desktop/foo.txt' asFileReference readStream.
>
> gives a ZnCharacterReadStream wrapping a ZnBufferedWriteStream wrapping a
> BinaryWriteStream.
>
> To translate line endings, we would wrap a ZnCharacterWriteStream using a
> ZnCrPortableWriteStream.
>
> There are a couple of more specialised streams to cover special cases
> (like read and writing at the same time).
>
> SocketStream remains another fat, overly complex, multi-functional, do-all
> class, for which usable replacements exist in the form of ZdcSocketStream
> and ZdcSecureSocketStream, which are simpler, cleaner and binary only.
>
> Of course, switching is more than replacing one class with a 100%
> compatible alternative, that would give us the same complex result. The
> challenge is to use a simpler API as well, to rethink how the streams are
> used. You know, KISS.
>
> Of course, we are far from done and need more testing, debugging and help
> from as many people as possible.
>
> Sven
>
>
> --
> Sven Van Caekenberghe
> Proudly supporting Pharo
> http://pharo.org
> http://association.pharo.org
> http://consortium.pharo.org
>
>
>
>
>
>
March 15, 2018
Reproducible VM crash from commit 4749358 onwards
by Alistair Grant
Hi Everyone,
If I download a recent Pharo 64 bit image, e.g.:
http://files.pharo.org/image/70/latest-64.zip
And use a Pharo VM from commit:
commit 4749358b5717b9a2f7e1d44f9baac48ed5d80431
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: Wed Mar 7 15:11:21 2018 -0800
or later, the following will reliably crash the VM:
./pharo Pharo7.0-64bit-a26248b.image eval "OCBytecodeGeneratorTest
run: #testExample2"
Earlier VMs don't crash.
Stack dump below my signature.
I'm a bit out of my depth beyond that...
OS: Ubuntu 16.04 64 bit
Cheers,
Alistair
Segmentation fault Thu Mar 15 22:39:13 2018
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo
Pharo VM version: 5.0-201803072311 Thursday 15 March 22:35:05 CET
2018 c99 [Production Spur 64-bit VM]
Built from: CoInterpreter VMMaker.oscog-eem.2347 uuid:
062614a7-e3da-4b30-997a-9568911b9ff5 Mar 15 2018
With: StackToRegisterMappingCogit VMMaker.oscog-eem.2347 uuid:
062614a7-e3da-4b30-997a-9568911b9ff5 Mar 15 2018
Revision: VM: 201803072311
alistair@59fbe1b42048:vmmaker/opensmalltalk-vm $ Date: Wed Mar 7
15:11:21 2018 -0800 $ Plugins: 201803072311
alistair@59fbe1b42048:vmmaker/opensmalltalk-vm $
Build host: Linux 59fbe1b42048 4.13.0-36-generic #40~16.04.1-Ubuntu
SMP Fri Feb 16 23:25:58 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
plugin path: /home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311
[default: /home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/]
C stack backtrace & registers:
rax 0x13ab4880 rbx 0x13ab4710 rcx 0x13ab4938 rdx 0x13ab47c8
rdi 0x13ab44e8 rsi 0x13ab44e8 rbp 0x13ab4658 rsp 0x13ab49f0
r8 0x13ab3f28 r9 0x13ab3fe0 r10 0x13ab4098 r11 0x13ab4150
r12 0x13ab4208 r13 0x13ab42c0 r14 0x13ab4378 r15 0x13ab4430
rip 0x13ab4aa8
*[0x7ffd13ab4aa8]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x41aca2]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x41c87e]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f78ad605390]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(lengthOf+0x0)[0x42aca0]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(cogselector+0x27)[0x49bf77]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x45b15c]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x45b444]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(interpret+0xb238)[0x469208]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo[0x46a4db]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(interpret+0x246)[0x45e216]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(main+0x2f8)[0x419f98]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f78acf41830]
/home/alistair/vmmaker/opensmalltalk-vm/products/cogspur64linuxht/lib/pharo/5.0-201803072311/pharo(_start+0x29)[0x41a309]
[0x0]
Smalltalk stack dump:
0x7ffd13ad4550 I CompiledMethod>valueWithReceiver:arguments:
0x1d7e790: a(n) CompiledMethod
0x7ffd13ad45a0 M OCBytecodeGeneratorTest>testExample2 0x1d78910:
a(n) OCBytecodeGeneratorTest
0x7ffd13ad1ea0 I OCBytecodeGeneratorTest(TestCase)>performTest
0x1d78910: a(n) OCBytecodeGeneratorTest
0x7ffd13ad1ed0 M [] in OCBytecodeGeneratorTest(TestCase)>runCase
0x1d78910: a(n) OCBytecodeGeneratorTest
0x7ffd13ad1f10 M BlockClosure>ensure: 0x1d7a450: a(n) BlockClosure
0x7ffd13ad1f58 I OCBytecodeGeneratorTest(TestCase)>runCase
0x1d78910: a(n) OCBytecodeGeneratorTest
0x7ffd13ad1f90 M [] in
TestExecutionEnvironment>runTestCaseSafelly: 0x1d78f28: a(n)
TestExecutionEnvironment
0x7ffd13ad1fc0 M BlockClosure>on:do: 0x1d7a330: a(n) BlockClosure
0x7ffd13ad2008 M [] in
TestExecutionEnvironment>runTestCaseSafelly: 0x1d78f28: a(n)
TestExecutionEnvironment
0x7ffd13ad2038 M BlockClosure>on:do: 0x1d7a1a8: a(n) BlockClosure
0x7ffd13ad2088 I TestExecutionEnvironment>runTestCaseSafelly:
0x1d78f28: a(n) TestExecutionEnvironment
0x7ffd13ad20c8 M [] in TestExecutionEnvironment>runTestCase:
0x1d78f28: a(n) TestExecutionEnvironment
0x7ffd13ad2108 M BlockClosure>ensure: 0x1d7a0a8: a(n) BlockClosure
0x7ffd13ad2148 M [] in TestExecutionEnvironment>runTestCase:
0x1d78f28: a(n) TestExecutionEnvironment
0x7ffd13ad2188 M BlockClosure>ifCurtailed: 0x1d79fa8: a(n) BlockClosure
0x7ffd13ad21d0 I TestExecutionEnvironment>runTestCase: 0x1d78f28:
a(n) TestExecutionEnvironment
0x7ffd13ad2218 M [] in DefaultExecutionEnvironment>runTestCase:
0x23f7c30: a(n) DefaultExecutionEnvironment
0x7ffd13ad2258 M [] in CurrentExecutionEnvironment
class>activate:for: 0x2404bf8: a(n) CurrentExecutionEnvironment class
0x7ffd13ad2298 M BlockClosure>ensure: 0x1d79280: a(n) BlockClosure
0x7ffd13ad22e8 I CurrentExecutionEnvironment class>activate:for:
0x2404bf8: a(n) CurrentExecutionEnvironment class
0x7ffd13ad2338 I
TestExecutionEnvironment(ExecutionEnvironment)>beActiveDuring:
0x1d78f28: a(n) TestExecutionEnvironment
0x7ffd13ad2388 I DefaultExecutionEnvironment>runTestCase:
0x23f7c30: a(n) DefaultExecutionEnvironment
0x7ffd13ad23d0 I CurrentExecutionEnvironment class>runTestCase:
0x2404bf8: a(n) CurrentExecutionEnvironment class
0x7ffd13ad2418 I OCBytecodeGeneratorTest(TestCase)>runCaseManaged
0x1d78910: a(n) OCBytecodeGeneratorTest
0x7ffd13ad2450 M [] in TestResult>runCase: 0x1d78930: a(n) TestResult
0x7ffd13ad2480 M BlockClosure>on:do: 0x1d78d50: a(n) BlockClosure
0x7ffd13ad24d0 I TestResult>runCase: 0x1d78930: a(n) TestResult
0x7ffd13ad2510 M [] in OCBytecodeGeneratorTest(TestCase)>run
0x1d78910: a(n) OCBytecodeGeneratorTest
0x7ffd13ad2550 M BlockClosure>ensure: 0x1d78c50: a(n) BlockClosure
0x7ffd13ad25a0 I OCBytecodeGeneratorTest(TestCase)>run 0x1d78910:
a(n) OCBytecodeGeneratorTest
0x7ffd13ad0100 I OCBytecodeGeneratorTest class(TestCase
class)>run: 0x36155c8: a(n) OCBytecodeGeneratorTest class
0x7ffd13ad0138 M UndefinedObject>DoIt 0x23e78e0: a(n) UndefinedObject
0x7ffd13ad0198 I OpalCompiler>evaluate 0x1c76f90: a(n) OpalCompiler
0x7ffd13ad01d8 I OpalCompiler(AbstractCompiler)>evaluate:
0x1c76f90: a(n) OpalCompiler
0x7ffd13ad0220 M [] in EvaluateCommandLineHandler>evaluate:
0x1c770e8: a(n) EvaluateCommandLineHandler
0x7ffd13ad0250 M BlockClosure>on:do: 0x1c77118: a(n) BlockClosure
0x7ffd13ad02a8 I EvaluateCommandLineHandler>evaluate: 0x1c770e8:
a(n) EvaluateCommandLineHandler
0x7ffd13ad02f8 I EvaluateCommandLineHandler>evaluateArguments
0x1c770e8: a(n) EvaluateCommandLineHandler
0x7ffd13ad0338 I EvaluateCommandLineHandler>activate 0x1c770e8:
a(n) EvaluateCommandLineHandler
0x7ffd13ad0378 I EvaluateCommandLineHandler
class(CommandLineHandler class)>activateWith: 0x252d400: a(n)
EvaluateCommandLineHandler class
0x7ffd13ad03b8 M [] in
PharoCommandLineHandler(BasicCommandLineHandler)>activateSubCommand:
0x55380b8: a(n) PharoCommandLineHandler
0x7ffd13ad03e8 M BlockClosure>on:do: 0x1c77390: a(n) BlockClosure
0x7ffd13ad0428 M
PharoCommandLineHandler(BasicCommandLineHandler)>activateSubCommand:
0x55380b8: a(n) PharoCommandLineHandler
0x7ffd13ad0478 I
PharoCommandLineHandler(BasicCommandLineHandler)>handleSubcommand
0x55380b8: a(n) PharoCommandLineHandler
0x7ffd13ad04b8 I
PharoCommandLineHandler(BasicCommandLineHandler)>handleArgument:
0x55380b8: a(n) PharoCommandLineHandler
0x7ffd13ad04f0 M [] in
PharoCommandLineHandler(BasicCommandLineHandler)>activate 0x55380b8:
a(n) PharoCommandLineHandler
0x7ffd13ad0520 M BlockClosure>on:do: 0x1c77628: a(n) BlockClosure
0x7ffd13ad0560 M [] in
PharoCommandLineHandler(BasicCommandLineHandler)>activate 0x55380b8:
a(n) PharoCommandLineHandler
0x7ffd13ad05a0 I [] in BlockClosure>newProcess 0x1c77720: a(n) BlockClosure
Most recent primitives
stringHash:initialHash:
basicNew
successorSequences
basicNew
basicNew
basicNew
**StackOverflow**
basicNew
basicNew
basicIdentityHash
basicNew
basicNew
stringHash:initialHash:
stringHash:initialHash:
stringHash:initialHash:
literal
parameterAt:
stringHash:initialHash:
isInteger
stringHash:initialHash:
stringHash:initialHash:
size
findSubstring:in:startingAt:matchTable:
indexOfAscii:inString:startingAt:
indexOfAscii:inString:startingAt:
stringHash:initialHash:
stringHash:initialHash:
*
*
size
size
copyWith:
bitShift:
bitShift:
numTemps
numTemps
numTemps
numTemps
numTemps
numTemps
basicIdentityHash
basicNew:
size
basicNew
at:put:
at:put:
basicNew:
stringHash:initialHash:
compare:with:collated:
perform:
encodeNoTrailer
encodeNoTrailer
encodeNoTrailer
encodeNoTrailer
encodeNoTrailer
encodeNoTrailer
encodeNoTrailer
at:put:
at:put:
at:put:
at:put:
basicNew
size
at:put:
at:put:
at:put:
at:put:
objectAt:put:
objectAt:put:
objectAt:put:
objectAt:put:
objectAt:put:
collect:
basicNew
bitAnd:
**PrimitiveFailure**
bitAnd:
**PrimitiveFailure**
bitOr:
**PrimitiveFailure**
bitOr:
**PrimitiveFailure**
bitClear:
new:
objectAt:
at:put:
objectAt:
at:put:
objectAt:
at:put:
objectAt:
at:put:
objectAt:
at:put:
objectAt:put:
stringHash:initialHash:
objectAt:put:
withArgs:executeMethod:
basicNew
class
basicNew
primUTCMicrosecondsClock
*
**PrimitiveFailure**
digitMultiply:neg:
basicNew
primOffset
digitCompare:
//
\\
valueNoContextSwitch
class
class
basicNew
class
class
value
class
**StackOverflow**
basicIdentityHash
basicNew
basicNew
basicNew
new:
valueNoContextSwitch
size
new:
size
size
at:put:
basicNew:
stackp:
basicNew
size
at:
at:
at:
at:
psValueAt:put:
psValueAt:put:
psValueAt:put:
psValueAt:put:
psValueAt:put:
primitiveResume
repeat
wait
class
millisecondClockValue
basicNew
signal
primUTCMicrosecondsClock
millisecondDelayDuration
+
primSignal:atUTCMicroseconds:
wait
wait
class
signal
basicNew
valueNoContextSwitch
signal
primUTCMicrosecondsClock
at:put:
at:
at:put:
primSignal:atUTCMicroseconds:
wait
wait
valueNoContextSwitch
wait
ifCurtailed:
basicNew
value
class
valueNoContextSwitch
perform:
**StackOverflow**
basicNew
basicNew
basicNew
basicIdentityHash
**StackOverflow**
**StackOverflow**
size
indexOfAscii:inString:startingAt:
at:
at:
at:
basicIdentityHash
value
class
linkTo:
basicNew
value
basicIdentityHash
stringHash:initialHash:
stringHash:initialHash:
size
stringHash:initialHash:
stringHash:initialHash:
basicNew
-
class
new:
at:put:
perform:withArguments:
from:if:goto:otherwise:
size
size
size
at:
~=
size
at:put:
basicNew:
stringHash:initialHash:
compare:with:collated:
newMethod:header:
at:put:
at:put:
at:put:
at:put:
basicNew
size
size
size
at:put:
at:put:
at:put:
at:put:
at:put:
at:put:
at:put:
at:put:
at:put:
at:put:
objectAt:put:
objectAt:put:
objectAt:put:
objectAt:put:
from:if:goto:otherwise:
from:if:goto:otherwise:
from:if:goto:otherwise:
objectAt:put:
new:
objectAt:
at:put:
objectAt:
at:put:
objectAt:
at:put:
objectAt:
at:put:
class
@
withArgs:executeMethod:
stack page bytes 8192 available headroom 5576 minimum unused headroom 6032
(Segmentation fault)
March 15, 2018
Executive Summary of the recent FileStream Changes
by Sven Van Caekenberghe
Executive Summary of the recent FileStream Changes
In Pharo 7 Guille Polito recently committed a heroic set of changes that we were planning to do for a long time but were afraid to take on.
The idea is to replace a couple of fat, overly complex, multi-functional, do-all classes with a set of simpler single purpose classes that can be combined as needed.
The classes that we want to get rid of can be found in the package DeprecatedFileSystem, in particular FileStream, StandardFileStream, MultiByteFileStream, MultiByteBinaryOrTextStream and RWBinaryOrTextStream.
The replacements are can be found in packages Files and Zinc-Character-Encoding-Core.
Encoding and decoding characters to and from bytes is done using classes that you wrap around a more primitive binary stream. The same goes for buffering or translating line endings.
For example,
'/Users/sven/Desktop/foo.txt' asFileReference binaryReadStream.
gives you a ZnBufferedWriteStream wrapping a BinaryWriteStream.
While,
'/Users/sven/Desktop/foo.txt' asFileReference readStream.
gives a ZnCharacterReadStream wrapping a ZnBufferedWriteStream wrapping a BinaryWriteStream.
To translate line endings, we would wrap a ZnCharacterWriteStream using a ZnCrPortableWriteStream.
There are a couple of more specialised streams to cover special cases (like read and writing at the same time).
SocketStream remains another fat, overly complex, multi-functional, do-all class, for which usable replacements exist in the form of ZdcSocketStream and ZdcSecureSocketStream, which are simpler, cleaner and binary only.
Of course, switching is more than replacing one class with a 100% compatible alternative, that would give us the same complex result. The challenge is to use a simpler API as well, to rethink how the streams are used. You know, KISS.
Of course, we are far from done and need more testing, debugging and help from as many people as possible.
Sven
--
Sven Van Caekenberghe
Proudly supporting Pharo
http://pharo.org
http://association.pharo.org
http://consortium.pharo.org
March 15, 2018
FileHandle creates a buffered stream on a buffered stream
by Sven Van Caekenberghe
Hi (Guille),
FileHandle creates a buffered stream on a buffered stream when sent #readStream.
Note how #binaryReadStream adds a bufferer stream as well as #readStreamEncoded:
Probably the latter should not do this
Sven
March 15, 2018
Re: [Pharo-dev] Experiment: New Download page based on Pharo Launcher
by Marcus Denker
-> better structure
-> simplified the large print (no need to talk about downloading zip files)
TODO:
- add back a section about downloading images.
> On 14 Mar 2018, at 18:18, Marcus Denker <marcus.denker(a)inria.fr> wrote:
>
> Ok, I will fix that in the next pass.
>
>> On 9 Mar 2018, at 18:10, Sean P. DeNigris <sean(a)clipperadams.com> wrote:
>>
>> Marcus Denker-4 wrote
>>> comments welcome…
>>
>> IHMO the structure is a little confusing because the first heading "Usage"
>> (Launcher implied) is on the same level as other methods like "Linux
>> Packages". I think there needs to be something like a header one level
>> higher like "Other Options" between these two sections.
>>
>>
>>
>> -----
>> Cheers,
>> Sean
>> --
>> Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html
>>
>
March 15, 2018
Re: [Pharo-dev] Pharo 7 new file stream encoders
by Sven Van Caekenberghe
I think the idea is to use ZnCrPortableWriteStream for that.
> On 15 Mar 2018, at 14:58, Thierry Goubier <thierry.goubier(a)gmail.com> wrote:
>
> Hi all,
>
> how does one create a file stream in Pharo 7 that forces a specific
> line end convention ? For example, for forcing all end of lines to be
> Character lf.
>
> The old way,
>
> fileStream lineEndConvention: #'lf'.
>
> does not work anymore.
>
> Thanks,
>
> Thierry
>
March 15, 2018
Pharo 7 new file stream encoders
by Thierry Goubier
Hi all,
how does one create a file stream in Pharo 7 that forces a specific
line end convention ? For example, for forcing all end of lines to be
Character lf.
The old way,
fileStream lineEndConvention: #'lf'.
does not work anymore.
Thanks,
Thierry
March 15, 2018
Re: [Pharo-dev] Base64MimeConverter class>>mimeDecodeToBytes: change breaks image load
by Sven Van Caekenberghe
And in PNGReadWriter>>nextImage we should remove stream reset and stream binary.
This probably goes for the other image readers as well.
> On 15 Mar 2018, at 13:38, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
> Yeah, right, good catch.
>
> But what is this nonsense:
>
> PNGReadWriter>>on: aStream
> (stream := aStream) reset.
> stream binary
> "Note that 'reset' makes a file be text. Must do this after."
>
> Of course you can only read an image from a binary stream, there should be nothing else there but
>
> stream := aStream
>
>> On 15 Mar 2018, at 13:31, Alistair Grant <akgrant0710(a)gmail.com> wrote:
>>
>> Also:
>>
>> 'apicture.png' asFileReference inspect.
>>
>> Will raise a "image format not recognised" because:
>>
>> - AbstractFileReference>>binaryReadStreamDo: ultimately uses a
>> ZnBufferedReadStream
>> - ImageReadWriter>>on: sends #reset to the stream
>>
>> and ZnBufferedReadStream doesn't implement #reset.
>>
>> My guess is that ZnBufferedReadStream should implement #reset (it has
>> #position:). But I'm not familiar with the current thinking on stream
>> rationalisation.
>>
>> I'll raise some fogbugz issues a bit later.
>>
>> Image downloaded today:
>>
>> Pharo 7.0
>> Build information:
>> Pharo-7.0+alpha.build.696.sha.a26248bb90ee8dfba131f2f4d71ba2bbbad5d00d
>> (64 Bit)
>>
>>
>>
>> Thanks,
>> Alistair
>>
>>
>> On 15 March 2018 at 13:08, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>>> BTW, for the record, we should deprecate Base64MimeConverter, and remove/change the following convenience methods:
>>>
>>> Remove
>>>
>>> String>>#base64Encoded.
>>>
>>> Change
>>>
>>> ByteArray>>#base64Encoded
>>> "Encode the receiver using Base64, see ZnBase64Encoder"
>>>
>>> ^ ZnBase64Encoder new encode: self
>>>
>>> String>>#base64Decoded
>>> "Decode the receiver using Base64, see ZnBase64Encoder"
>>>
>>> ^ ZnBase64Encoder new decode: self
>>>
>>> The thing is, Base64 is defined as going from bytes -> characters and vice versa. Not as going from characters -> characters. For that you need to use an explicit character encoder as in ZnUtils class>>#decodeBase64: and ZnUtils>>#encodeBase64:
>>>
>>> So yes, this would be a breaking change, but an easy one to follow since Base64 is really very simple as a concept.
>>>
>>>> On 15 Mar 2018, at 12:47, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>>>>
>>>>
>>>>
>>>>> On 15 Mar 2018, at 12:28, Alistair Grant <akgrant0710(a)gmail.com> wrote:
>>>>>
>>>>> Hi Guille & Pavel,
>>>>>
>>>>> On 6 Feb Guille changed Base64MimeConverter class>>mimeDecodeToBytes:
>>>>> so that it doesn't reset the dataStream position back to the start of
>>>>> the stream. This breaks Pavel's PlayingCard, part of FreeCell (you
>>>>> can see that I only load important stuff :-)).
>>>>>
>>>>> PlayingCard class>>initialize
>>>>> "PlayingCard initialize"
>>>>> | forms f |
>>>>> "Read the stored forms from mime-encoded data in imageData."
>>>>> f := Base64MimeConverter mimeDecodeToBytes: (ReadStream on: self imageData).
>>>>> forms := OrderedCollection new.
>>>>> f next = 2 ifFalse: [self error: 'corrupted imageData'].
>>>>> [f atEnd] whileFalse: [forms add: (Form new readFrom: f)].
>>>>> ...
>>>>>
>>>>>
>>>>> Previously, f would be at the start of the stream (which makes sense
>>>>> given this usage), but now it is at the end of the stream, so returns
>>>>> nil and "f next = 2" fails.
>>>>>
>>>>> Guille, can you explain the change. The commit log just says "make tests run".
>>>>>
>>>>> Note that a lot of users of this won't fail as they just call
>>>>> #contents of the stream after #mimeDecodeToBytes:, which works
>>>>> regardless of the current position.
>>>>
>>>> So doing
>>>>
>>>> f reset
>>>>
>>>> at the caller site would fix it then ?
>>>>
>>>> Note that there is the newer ZnBase64Encoder that can be used as follows:
>>>>
>>>> f := (ZnBase64Encoder new decode: self imageData) readStream.
>>>>
>>>> Sven
>>>
>>>
>>
>
March 15, 2018