how would I go about creating a Socket receiveAll method?

Unazed Spectaculum unazed at spec.org
Tue Dec 12 21:03:54 UTC 2017


On Tuesday, 12 December 2017 at 20:27:04 UTC, Ali Çehreli wrote:
> On 12/12/2017 12:10 PM, Unazed Spectaculum wrote:
> > string receiveAll(T)(T socket, int segment_size = 1024)
> > {
> >      char[segment_size][] data;
>
> Unrelated, you most likely want to use ubyte. (char is for 
> UTF-8.)
>
> The problem is, char[segment_size] is a static array, where the 
> length must be known at compile time because length is a part 
> of its type.
>
> So, depending on what you need you have two options:
>
> a) Use dynamic array if the length is known at run time
>
> b) Although (a) will work just fine, use template parameter for 
> length if the length is known at compile time and you want to 
> avoid dynamic allocation.
>
> However, too large arrays won't fit on the stack. (Further 
> however, your 'data' is a slice anyway, just the elements are 
> static.)
>
> The following program shows the two options with 
> one-dimensional arrays:
>
> // Size is known at run time
> void foo(T)(T t, size_t size = 1024) {
>     auto data = new ubyte[](size);
> }
>
> // Size is known at compile time
> void bar(size_t size = 1024, T)(T t) {
>     ubyte[size] data;
> }
>
> void main() {
>     int i;
>     foo(i, 10);
>     bar!20(i);
> }
>
> Here is one with two-dimensional arrays:
>
> import std.stdio;
>
> size_t counter = 0;
> bool done() {
>     return (++counter % 4) == 0;
> }
>
> // Size is known at run time
> void foo(T)(T t, size_t size = 1024) {
>     ubyte[][] data;
>
>     while (!done) {
>         data ~= new ubyte[size];
>         // Use data[$-1]
>         writeln("a) Will read here: ", data[$-1]);
>     }
> }
>
> // Size is known at compile time
> void bar(size_t size = 1024, T)(T t) {
>     ubyte[size][] data;
>
>     while (!done) {
>         ++data.length;
>         writeln("b) Will read here: ", data[$-1]);
>     }
> }
>
> void main() {
>     int i;
>     foo(i, 10);
>     bar!20(i);
> }
>
> Ali

string receiveAll(T)(T socket, size_t segment_size = 1024)
{
	ubyte[][] data;
	size_t count = 0;

	while (true)
	{
		data ~= new ubyte[segment_size];

		auto received = socket.receive(data[count]);
		data[count] = data[count][0 .. received];

		if (!received)
			break;
		else if (received < segment_size)
			break;  /* early exit */

		++count;
	}

	char[] stringData;

	foreach (elem; data)
		stringData ~= elem;

	return to!string(stringData);
}


I've decided to go for the run-time approach to this, it works 
fine with all of my tests so you have my greatest gratitude.

I might have created some weird inefficiencies but don't worry 
take time telling me about them unless they're going to blow up 
my program since I think you've explained enough already :D.

Since I'm only a few days into D I wouldn't expect much of my 
code, I'm moreover from the generic Python and thereabouts C-ish 
background.

again, thanks.


More information about the Digitalmars-d-learn mailing list