On 12/12/2017 10:21 PM, bauss wrote:
> On Tuesday, 12 December 2017 at 22:11:37 UTC, Adam D. Ruppe wrote:
>> On Tuesday, 12 December 2017 at 21:52:57 UTC, Ali Çehreli wrote:
>>> The same buffer is used for all segments and socket.receive should be
>>> inside while.
>>
>> The buffer is copied by the ~= operator, but indeed you're right that
>> I forgot to receive again inside the loop! That would just spin until
>> it ran out of memory lol.
>>
>> But I did put receive outside the loop for a reason: it just needs to
>> prime the return value before it gets checked the first time. But
>> then, of course, it should receive again at the end of the loop to
>> advance to the next chunk.
>
> do while would work better.

It's a bummer that the loop variable must be defined outside of do-while:

    bool done = false;    // Can't be inside
    do {
        // ...
    } while(!done);

That's why I think an unconditional loop with an explicit break is better in such situations:

    while (true) {
        // ... everything inside ...
        if (!got) {
            break;
        }
        // ...
    }

Here is a short program that I played with:

import std.stdio;
import std.range;
import std.algorithm;

int[] makeData(int len) {
    return iota(len).array;
}

struct SomeSource {
    int[] data;

    this(int len) {
        this.data = makeData(len);
    }

    // Alternatively, this can return int[]
    size_t read(int[] buffer) {
        const len = min(data.length, buffer.length);
        buffer[0..len] = data[0..len];
        data = data[len..$];    // Alternatively, popFrontN
        return len;
    }
}

void main() {
    enum len = 50;
    auto foo = SomeSource(len);

    int[] result;
    while (true) {    // <-- UNCONDITIONAL LOOP
        int[17] buffer;
        const got = foo.read(buffer[]);
        if (!got) {
            break;
        }
        result ~= buffer[0..got];
    }
    assert(result == makeData(len));
    writeln(result);
}

Ali

Reply via email to