std.Stream.InputStream convenience functions

BBasile via Digitalmars-d digitalmars-d at puremagic.com
Sat Sep 5 20:42:18 PDT 2015


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).


More information about the Digitalmars-d mailing list