January 07, 2022
On Fri, Jan 07, 2022 at 07:54:28PM +0000, eugene via Digitalmars-d-learn wrote: [...]
> * Does .until() make a copy of original string? And GC then will take
> care of it?

No, it's one of the lazy range functions that lazily evaluates the string and does not allocate.


> * So many ways to do simple C printf("%s", (char*)buf)... I am feeling
> like Buridan's ass

D strings are different from C strings.  Although D *can* handle C strings, it should not be surprising there's a bit of friction.

The simplest way to handle a C string from D is just to use .fromStringz:

	import std.string : fromStringz;
	char *buf = some_c_function();
	writeln(buf.fromStringz);

Note that fromStringz is @nogc, since it only takes a slice of the C string and does not copy anything. So it should be good even for GC-phobic code.


T

-- 
What do you get if you drop a piano down a mineshaft? A flat minor.
January 07, 2022

On Sunday, 2 January 2022 at 15:13:06 UTC, Paul Backus wrote:

>

On Sunday, 2 January 2022 at 09:15:32 UTC, eugene wrote:

>
p1.d(9): Error: cannot cast expression `until(b[], '\x0a', Flag.yes)` of type `Until!("a == b", ubyte[], char)` to `char[]`

Here's a working version:

import std.stdio;
import std.string;
import std.algorithm : until, map;
import std.conv : to;

void main() {
    ubyte[8] b = [0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00, 0x00];
    /* "hello\n\0\0" */
    writefln("'%-(%s%), world'", b[].until('\n').map!(to!char));
}

This code uses map!(to!char) to convert the elements of the range from ubyte to char, then uses a %-(...%) format specifier to print out each element of the range using the format string inside the parentheses (in this case, %s).

Well, just a Gross!
But I am not a fun of functional programming style :)
(sorry for replying late)

January 07, 2022
On Friday, 7 January 2022 at 20:08:00 UTC, H. S. Teoh wrote:
> The simplest way to handle a C string from D is just to use .fromStringz:

yes, this approach was used in some my previous traival

January 07, 2022
On Friday, 7 January 2022 at 20:08:00 UTC, H. S. Teoh wrote:
> So it should be good even for GC-phobic code.

Nice term - "GC-phobic" :)

But looking from my cave  - it's not a phobia, it's an observation.
We've got a huge and complex project at my job, and...

* python guys have memory leaks
* js guys have memory leaks

Both "systems" (I mean python and javascript) are GC-systems.
And? Should I trust D with GC or accurate C-programmers? :)

January 07, 2022
On Friday, 7 January 2022 at 20:33:05 UTC, eugene wrote:
> * python guys have memory leaks
> * js guys have memory leaks

GC isn't actually there to prevent memory leaks. Its main job is to guard against use-after-free memory corruption bugs.

Actually, technically, the paradigm is "infinite lifetime" and the garbage collection is just there as a practical matter because computers don't have infinite memory. They do a reasonably good job on memory leaks too, but that's not the main goal so they'd rather let memory leak than risk a use after free.

That's why D lets you do a hybrid approach easily: where the lifetime is trivial, you can easily do it yourself to optimize memory use. But when it isn't so obvious, you can use the GC to play it safe at the cost of a lil more memory use.
January 07, 2022

On 1/7/22 2:54 PM, eugene wrote:

>

A couple of impressions...

  • Does .until() make a copy of original string? And GC then will take care of it?

No, until will iterate the string one character at a time until it sees that character (excluding it). It doesn't make a copy of the data.

In effect, it's doing the "trim" and the iteration to print in one step. In your chosen solution earlier, you were doing it 3 times -- once to find the end of the null-terminated string (via fromStringz), once to strip the newline (well, this isn't too bad, since it goes from both ends), and once to actually print it.

>
  • So many ways to do simple C printf("%s", (char*)buf)... I am feeling like Buridan's ass

There are a million ways to get what you want. I like to go for ones that:

  1. don't allocate needlessly (I hate allocating a string just to print it, and then throw it away, regardless of whether it's GC or not)
  2. read concisely and clearly.
  3. Are as efficient as possible.

The one wart here is the cast, but that's impossible to avoid unless you want to allocate. Adhering to 2 and 3 above sometimes are in conflict. But rule 1 is essential for performance.

In C you have one choice (printf), but that choice may not fit your needs.

-Steve

January 07, 2022

On Friday, 7 January 2022 at 20:40:02 UTC, Adam D Ruppe wrote:

>

On Friday, 7 January 2022 at 20:33:05 UTC, eugene wrote:

>
  • python guys have memory leaks
  • js guys have memory leaks

GC isn't actually there to prevent memory leaks.

Aha, unless you'll build GC into OS core :)

>

Its main job is to guard against use-after-free memory corruption bugs

if (ptr) {
    free(ptr);
    ptr = NULL;
}

...

    if (NULL == someptr)
        BUG()/PANIC()/WHATEVER()
>

because computers don't have infinite memory

first time I've heard this )))
tell that to py/js super-coders :)

>

where the lifetime is trivial, you can easily do it yourself to optimize memory use. But when it isn't so obvious, you can use the GC to play it safe at the cost of a lil more memory use.

other way around

  • when the lifetime is trivial (whithin a function, including thread function) - trust GC
  • when the lifetime is not trivial (ptr goes through or a self-pipe or similar) - GC has no info about that
January 07, 2022

On Friday, 7 January 2022 at 21:17:33 UTC, Steven Schveighoffer wrote:

>

In C you have one choice (printf), but that choice may not fit your needs.

There are 2 buffers (RX one and TX one, both of 'reasonable' size)
(it's the effing echo-server, nothing more)

  • print content of RX-buffer, ommiting terminating '\n' ('\n' is the 'end of request') to (log/journal file)/stdout/

  • ouptut received 'message' back to client, with terminating '\n'

January 07, 2022

On Thursday, 30 December 2021 at 09:34:27 UTC, eugene wrote:

>
char[] s = cast(char[])ioCtx.buf[0 .. strlen(cast(char*)ioCtx.buf.ptr) - 1];
// -1 is to eliminate terminating '\n'
writefln("got '%s' from '%s:%d'", s, client.addr, client.port);

Is there some more concise/elegant way to do that?

Try auto s = fromStringz(cast(char*)ioCtx.buf.ptr).

January 08, 2022

On Friday, 7 January 2022 at 22:04:28 UTC, eugene wrote:

>

There are 2 buffers (RX one and TX one, both of 'reasonable' size)
(it's the effing echo-server, nothing more)

  • print content of RX-buffer, ommiting terminating '\n' ('\n' is the 'end of request') to (log/journal file)/stdout/

  • ouptut received 'message' back to client, with terminating '\n'

However, you should not rely on a terminating '\n' even you are the source. You determine the length of string trough '\n' but maybe your buffer doesn't contain it (yet) if the connection wasn't blocking or the message is longer as the buffer size or you received just error data.

Then, accessing the ubyte[] data directly via .ptr/ casting it to char* without knowing the possible content seems not a good idea - if you are using any function that returns bytes till it finds a needle or terminating '\0'.

I know it's a little bit off topic but if the question is about the best concise way, the solution you choose should respect that too.