On Sunday, 6 September 2015 at 02:19:41 UTC, bitwise wrote:
On Saturday, 5 September 2015 at 23:00:43 UTC, BBasile wrote:
On Saturday, 5 September 2015 at 19:59:03 UTC, bitwise wrote:
On Saturday, 5 September 2015 at 06:15:17 UTC, Jonathan M Davis wrote:
[...]

Thanks for the explanation, but could you give an example of how Stream would be rangified?

this was not addressed to me but here is how it should be done:

---
module runnable;

import std.stdio;
import std.stream;
import std.algorithm;

class RangifiedStream: MemoryStream
{
    auto range()
    {
        return Range(this);
    }

    private struct Range
    {
        MemoryStream _str;
        ulong _curr;

        this(MemoryStream str)
        {
            _str = str;
        }

        void popFront()
        {
            _curr += 1;
        }

        @property ubyte front()
        {
            ubyte result;
            _str.position = _curr;
            _str.read(result);
            _str.position = _str.position - 1;
            return result;
        }

        @property bool empty()
        {
            return _curr == _str.size;
        }
    }
}

void main(string[] args)
{

    import std.range;
    assert( isInputRange!(RangifiedStream.Range));

    RangifiedStream str = new RangifiedStream;
    ubyte[] src = [0,1,2,3,4,5,6,7,8,9];
    str.write(src);

    str.range.each!(a => a.writeln);
}
---

The range has a reference to a stream. The range uses its own position and this is important since several ranges may co-exist at the same time. Here you just have a byte InputRange but it works...

For FileStream the performances will be terrible (bad), because the position is hold by a a structure specific to the OS...

I think I'll add this to my iz streams classes.

If all we had was a flat array of bytes(or any uniform type), then we wouldn't need a stream at all.

My typical usage is something like this:

int a = 1;
float b = 2;
string s = "3";

MemoryStream ms = new MemoryStream();
ms.write(a);
ms.write(b);
ms.write(s);

// stash ms in a file, or send/receive over socket..

int a = ms.readInt();
float b = ms.readFloat();
string s = ms.readString();

doSomething(a, b, s);

I'm not sure how you would go about rangifying something like this.

Sorry but I just wanted to reply to your Q 'how Stream would be rangified?'. Put the primitives...period.

Obviously my previous example is not good because it's only for MemoryStream,
and OutputRange primitives miss.
Think more that the the Range will be defined for the Stream class:

---
struct StreamRange(ST, T)
if (is(ST : Stream))
{
    private:

        ulong _fpos, _bpos;
        ST _str;

    public:

        this(ST str)
        {
            _str = str;
            _bpos = str.size - T.sizeof;
        }

        @property T front()
        {
            T result;
            _str.position = _fpos;
            _str.read(&result, T.sizeof);
            _str.position = _fpos;
            return result;
        }

        @property T back()
        {
            T result;
            _str.position = _bpos;
            _str.read(&result, T.sizeof);
            _str.position = _bpos;
            return result;
        }

        @safe void popFront()
        {
            _fpos += T.sizeof;
        }

        @safe void popBack()
        {
            _bpos -= T.sizeof;
        }

        @property bool empty()
        {
return (_fpos == _str.size) || (_fpos + T.sizeof > _str.size)
                    || (_bpos == 0) || (_bpos - T.sizeof < 0);
        }

        typeof(this) save()
        {
            typeof(this) result = typeof(this)(_str);
            result._fpos = _fpos;
            return result;
        }
}

// ....

auto rng = StreamRange!(MemoryStream,long)(instance);
auto rng = StreamRange!(FileStream,float)(instance);
---

Actually I have nothing against your helper functions (except that they don't make Streams compatible with std.algorithm functions).

Reply via email to