www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15363] New: std.stream is depricated, which leaves missing

https://issues.dlang.org/show_bug.cgi?id=15363

          Issue ID: 15363
           Summary: std.stream is depricated, which leaves missing
                    features
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: phobos
          Assignee: nobody puremagic.com
          Reporter: jason spashett.com

Since std.stream is to be removed, there will be some missing features that
really should be part of the language, in my opinion. It probably would have
been better to implement the replacement functinality before deprecating
std.stream.


The following two things I have ran into (so far):

There is no longer a 'stream' concept. Instead one has to say
File.byChunk(x).joiner on File objects.

It's important to have an abstract notion of a stream type thing for working
on:

files
memory
sockets
...etc

i.e. the need to pass said abstract thing into a function, that can then
perform the needed operation, weather it be from a file, memory, socket...

This, undoubtedly should be a range in D, but getting one by using
.byChunk(x).joiner on the File object is not very obvious at all. (See example
code for stream demonstration) This sort of range type should be made available
on all things that can have stream like facilities, and it should be an
InputRange, so as the result can be used with a wide variety of algorithms.


The lineSplitter algorithm does not work unless the range it's given has
slicing and length. This is a drawback if you want to use it with a "steam."
i.e. it's useless.

A different lineSplitter is required I think (see example code). This will have
to allocate a line buffer though.


----- example implementation --------

module missing;

import std.algorithm;
import std.stdio;


/* test.txt

the quick brown fox 
jumped over 
the lazy dogs.

*/



unittest {

    /*
     * A file Stream.
     * This is similar to File.byChunk(n).join() but a bit less odd
     */
    {
        std.stdio.File f = std.stdio.File("test.txt");
        assert(f.isOpen());
        //auto s = f.byChunk(4).joiner;
        auto s = f.stream(4);
        assert(!s.empty);
        foreach (char c; s) {
            writef("%c", c);
        }
    }

    /*
     * Line split without reading the whole file.
     */
    {
        std.stdio.File f = std.stdio.File("test.txt");
        assert(f.isOpen());
        auto s = f.stream(4);
        assert(!s.empty);

        auto lines = lineSpliterCopy(s);
        foreach (char[] line; lines) {
            writefln("Line: %s", line);
        }
    }
    import std.c.stdlib;
    exit(1);
}


/*
** Return range of chars
*/
auto stream(std.stdio.File f, size_t bufferSize = 4096)
{
    struct Stream
    {
        this(std.stdio.File f, size_t bufferSize)
        {
            file = f;
            buffer = new char[bufferSize];
            fill();
        }
        void popFront()
        {
            slice = slice[1..$];
            if (empty)
                fill();
        }
        char front()
        {
            return slice[0];
        }

         property
        bool empty() const {
            return slice.length == 0;
        }

    private:
        void fill()
        {
            slice = file.rawRead(buffer);
        }
        char[] buffer, slice;
        std.stdio.File file;
    }
    return Stream(f, bufferSize);
}


/*
** A inputRange range that returns lines. Allocating a single line
*/
auto lineSpliterCopy(Range)(Range range)
{

    struct Splitter
    {
        this(Range range)
        {
            this.source = range;
            popFront();
        }

        void popFront()
        {
            line = null;
            while (!source.empty() ) {
                char c = source.front();
                if (c == '\n') {
                    source.popFront();
                    break;
                }
                line ~= c;
                source.popFront();
            }
        }

        char[] front()
        {
            return line;
        }

        bool empty() {
            return line is null;
        }

    private:
        Range     source;
        char[]    line;
    }
    return Splitter(range);
}

--
Nov 19 2015