#2060 eachByte and eachChar for sys::InStream

endragor Thu 15 Nov 2012

To iterate over sys::InStream contents until EOF I have to write old-fashioned loops like this:

while (in.peek != null)
{
  byte := in.read
  //do something with the byte
}

I think having eachByte and eachChar methods in sys::InStream would follow Fantom's API style and make iterating over stream contents more pretty and convenient.

alex_panchenko Thu 15 Nov 2012

If you want to handle all the stream contents, then for performance reasons it makes sense to read into some buffer. I would suggest implementing it similar to guava ByteProcessor, which in java looks like this:

interface ByteProcessor {
  processBytes(byte[] buf, int off, int len)
}

readBytes(ByteProcessor processor)

And it can be also implemented for sys::File, sys::Buf, etc.

endragor Thu 15 Nov 2012

Fantom's streams are buffered by default.

brian Thu 15 Nov 2012

It might be nice for consistency, but that seems like a pretty odd use case. Of all the I/O work I've done, I've never actually wanted to iterate byte by byte or char by char. Can you maybe explain the use case more?

endragor Fri 16 Nov 2012

I had to implement percent encoding because I didn't find it in language API (seems like using API you can encode query or uri but not just any string and I needed it). The implementation looks like this:

static Str percentEncode(Str str)
{
  result := StrBuf()

  bytes := str.toBuf
  while (bytes.peek != null)
  {
    byte := bytes.read
    if (byte.isAlphaNum || byte == '-' || byte == '.' || byte == '_' || byte == '~')
    {
      result.addChar(byte)
    }
    else
    {
      result.addChar('%').add(byte.toHex(2).upper)
    }
  }

  return result.toStr
}

jodastephen Fri 16 Nov 2012

As a data point, I've written character by charater looping for parsing input a few times in the last 10 years.

Login or Signup to reply.