> size_t readFrom(const(char)[] data, size_t start); // same as > readUntil delegate
What happens if the buffer data get exhausted ? The function calling readFrom has no way to know how many characters to put into data to allow the read. What is the point of start ? We could use a delegate to return new characters: void readFrom(const(char)[] delegate(size_t) stream, in char[] format = null); -format is the usual format specifier. -stream is a delegate that takes a size_t argument, discards as many characters from its internal buffer, and returns data to read from. The returned data has any length, but must be empty only when the end of all the data to be read is reached. stream may overwrite previously returned data. Examples of suitable delegates for stream: | const(char)[] delegate(size_t) myStringStream(string str) | { | return (size_t n) { str = str[n..$]; return str; }; | } | const(char)[] delegate(size_t) myFileStream(File file, size_t size) | { | char[] chunk = new char[size]; | int i=0; | chunk = file.rawRead(chunk); // @Bug?: file is read in binary mode... | return (size_t n) | { | i += n; | if (i>=chunk.length) chunk = file.rawRead(chunk); | return chunk[i..$]; | }; | } The readFrom method should looks like that: | // read data from buffer until a whitespace is found and put it in | // string s | void readFrom(ref string s, const(char)[] delegate(size_t) buffer, | in char[] format = null) | { | s = ""; | int r = 0; // number of read character | auto buf = buffer(0); // ask for some data to read. | // readFrom can throw a ReadException: | if (!buf.length) { throw new ReadException(); } | | while (!(buf[r] == ' ' || buf[r] == '\t' || buf[r] == '\n')) | { | ++r; | if (r == buf.length) | { | s ~= buf; | if (!buf.length) // end of stream. | return; | } | } | s ~= buf[0..r]; | buffer(r); // do not forget to tell the stream how much you read | // from it | return; | } But implementation of readFrom will be made easier by the following functions: void read(T...)(const(char)[] delegate(size_t), ref T); void readf(T...)(const(char)[] delegate(size_t), in char[] format, ref T); Example: | struct Point | { | int[3] data; | | void readFrom(const(char)[] delegate(size_t) stream, | in char[] format = null) | { | readf(stream, "[%s, %s, %s]", data[0], data[1], data[2]); | } | } Note: One could make a similar signature for writeTo to be more consistent. I have no idea if this should be more efficient than the currently proposed writeTo. void writeTo(char[] delegate(size_t) stream, in char[] format = null); Note: I replaced "string format=null" by "in char[] format = null" to be consistent with current stdio.readf What are your thoughts about this ? -- Christophe Travert