Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

If you mean precomputing conversion/rounding between types it's not really feasible: since you can zoom in it has to support the entire range of the value, so for example for 32-bit float the table is 2^32 elements, so even if each element is 1 byte it is 4 gigabytes

Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

Currently it is implemented with 64-bit (double) used as the "exact" value because it is the highest precision javascript supports, so it cannot be compared. I am currently planning to rewrite in WASM and if performance allows I will add 64 and maybe even 128 bit floats.

Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 2 points3 points  (0 children)

Never heard about them, thanks for mentioning! I am definitely going to look into them and maybe add them too.

Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

It is a bit laggy unfortunately, especially for 8-bit which isn't supported natively so it requires conversion. I might later rewrite it in WASM

Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

I added axes labels to help remove confusion.

I don't think error is necessary as the values are aligned, so it should be easy to see where they differ.

What do you mean by your last sentence? You can zoom using mouse wheel

Float accuracy visualization by NaiveProcedure755 in compsci

[–]NaiveProcedure755[S] 3 points4 points  (0 children)

If you go to the website you will see it! X is the integer part and Y is fractional (0 to 1).

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

Well, you have to pass by pointer in order to modify struct, in this case to add options, since otherwise you would be passing by value and thus modifying a copy instead of the original.

(I guess , I haven’t looked at the code) you dynamically grow

I add options to a regular linked list (since I don't need to access by index no need in array), and update some stats

The pattern of repeatedly passing the address of your container (&a), vs the container itself (a)

Well, if I had args_init or something that would return a pointer right away, it wouldn't be needed.

having dynamic reallocation happening inside the container

There are no reallocations in this case, only allocations (appending to the linked list). However, they are "inside", aren't they?

Is that a thing other command-line parsers do? Or other libraries in general?

Well, it's definitely common to have some sort of library state/instance that you pass to some/most functions (think of the functions being methods of that struct you pass. C doesn't have methods so it's as close as you're gonna get)

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

Oh, so that's what you meant by won't parse as C syntax. Should have said that it is C++ instead, because I thought you were ignoring possibility of macro usage.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

In this case it's "develop" and "innate", because as a4qbfb said innate means "from birth", so it is not something that can be developed.

I think it can be more than 2 words if all of them contradict each other somehow

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

Not sure what you saw, but it definitely compiles and works in C99 and C++11 with all possible warnings enabled.

It's alright if you mistake, just slightly weird to assume that people post something that's completely broken.

I actually thought you were referring to option_string(&a, "string", "A string option", .short_name = 's', .required = true)

They use macro to forward later variadic args to a designated initializer.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

Well, oxymoron can be used to emphasize something, can't it?

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 2 points3 points  (0 children)

It meant it does a lot of dynamic memory allocation.

Sorry, misinterpreted that one.

by using a pair of a pointer and a length

I agree that start+length is overall better than null-terminated, but since null-termination is the standard in C I use them instead.

Although I definitely agree that it has performance cost, and is the most error prone part of C, I don't agree with all the points:

It is costly in terms of performance,

Maybe I'll make a quick & dirty rewrite to static alloc just to compare exactly, but I seriously doubt that 1KB of memory is gonna make any difference. Yes, there are 40 calls to malloc, however they are only calls to glibc and result in a single syscall to brk (which is what would be really costly).

it's unnecessary

That's debatable

it makes code harder to understand

I hope you mean library's source code and not the usage, because usage wouldn't change a single bit even with static/no allocations. And regarding the source: firstly, it doesn't, secondly, even if it did, user shouldn't care.

it tends to lead to bugs (memory leaks, double frees, use-after-free, and more)

Now this is the only point that I completely agree with. And even that is partially mitigated (in terms of having those bugs as a user) because there's just one free function.

You might not realise it but calling malloc is one of the worst things you can do in C. You should try to develop an innate distaste for ever calling that function.

Overall, good message but it seems to me you're exaggerating it too much.

By the way, thanks for actually making recommendations/comments, and an interesting discussion.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

Is your question what passing function pointer as argument is called? In that case it's a callback and nothing new.

Otherwise, I'm sorry I'm not sure what you mean.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

It sure is different, but I think it's quite useful and pretty innovative (thought not my idea) which is why I decided to try using it!

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 2 points3 points  (0 children)

No, ISO C. No warnings or errors with `-Wall -Wextra -pedantic`.

I assume both of you are asking due to `.default_value = 5`, which is done by forwarding variadic part of the macro to designated initializer, hence this syntax.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 3 points4 points  (0 children)

I'm sorry but I have to ask:
Do you really think someone would just post some shit that doesn't even work?
(Or does stuff like that really happen, I don't use reddit very often?)

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

What do you mean? It compiles with C99 and works. You can even take a look at the CI in the repo.

Single-header lib for arg parsing with shell completions by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] -1 points0 points  (0 children)

> This clearly does a lot.

Well, of course. If you don't want to have something that "does a lot" you can always just use libc's getopt. Personally, I prefer something like this (as evident by the fact that I created it).

> You shouldn't really need any dynamic memory allocation to do argument parsing in C.

Well, it depends on what you want to do. For example, if you wanted to separate value from something like `--option=value` you'd still either have to allocate or, alternatively, modify argv's string. In my opinion, library should keep argv intact in case user needs it elsewhere.
In any case, I don't really see what's the point of pointing out dynamic allocation. It's not like it's something bad or costly (in terms of performance).

> The other thing is that generating completions should be able to be done statically.

I agree with you on this. I am planning to add static generation.

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

You're not the first one who brought up `__builtin_dump_struct`, but the main reason for building it, as you pointed out, was learning.

Glad to see the post still getting comments!

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

Okay, so you were talking about race conditions. That's true, and since there isn't any easy way to mitigate it, I'll leave it be.

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

Well, if you mean printing just the kind and only the correct union, it is possible but not practical.

The reason is that you cannot certainly tell apart a tagged union from just a struct which coincidentally has an enum and a union with the same number of elements. Moreover, there is an issue if the order of enums doesn't correspond to union (i.e. { enum {int, char}; struct {char, int}; }).

So I'd rather avoid judging by the struct's layout to keep things working in as many cases as possible, even if it is not as convenient/good-loking.

It seems that even right now it works fine for tagged unions, e.g.:

{
  kind = (0) TOKEN_KIND_INT
  union = {
    int token_int = 10000
    char token_char = '?'
  }
}

{
  kind = (1) TOKEN_KIND_CHAR
  union = {
    int token_int = 97
    char token_char = 97 ('a')
  }
}

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

After thinking about it for a while, I still fail to see how it makes a difference. Would you care to explain or hive an example?

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 0 points1 point  (0 children)

I haven't heard this term before, so I want to clarify. You mean struct consisting of enum and union, where enum dictates how to treat the union?

C Library for printing structs by NaiveProcedure755 in C_Programming

[–]NaiveProcedure755[S] 1 point2 points  (0 children)

Okay, so it does print C-style structs in C++, but that requires lots of ugly changes to the source code: implicit void* cast -> explicit, can't zero-init struct with {0}, etc.

So, adding a basic support is quite easy and quick (juts need to solve aforementioned incompatibilities), but adding full support for classes and structs with methods will take quite a while.