> 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

Reply via email to