The easiest way to make the original range of bytes from a file is to simply read it all in memory:
import std.file; auto data = cast(ubyte[]) read("filename");
If the file is too large to make sense, you can try the memory mapping file http://dlang.org/phobos/std_mmfile.html and use opSlice to get an array from it. Since this is an array, you get full-featured functions, but since it is the memory displayed by the operating system, you get lazy reading when you touch the file.
For a simple InputRange, there is a LockingTextReader (undocumented) in Phobos, or you can build it yourself on byChunk or even fgetc , the C. fgetc function would be easiest to write:
struct FileByByte { ubyte front; void popFront() { front = cast(ubyte) fgetc(fp); } bool empty() { return feof(fp); } FILE* fp; this(FILE* fp) { this.fp = fp; popFront(); } }
I really have not tested this, but I'm sure it will work. (BTW open and close the file separately from this, because ranges should be just views in the data, not managed containers. You would not want the file to be closed only because you passed this range to the function.)
However, this is not a direct and arbitrary range of access. This is more difficult to do in streams without a lot of buffering code, and I think it would be a mistake to try to write - usually ranges should be cheap and not emulating functions that the base container does not support.
EDIT: another answer has a non-buffering way! fooobar.com/questions/987330 / ... This is awesome.
source share