Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamically allocate space for JQ_COLORS #3282

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

SArpnt
Copy link
Contributor

@SArpnt SArpnt commented Mar 3, 2025

this allows for larger escapes, so you can fit in full rgb foregrounds, background, underlines, and whatever else into every color. only one allocation is used and it only allocates what's needed.

the function should work if called multiple times, i set it up this way only because it seemed to already be set up with that in mind. if that's not needed i can make another commit to throw out unnecessary bits.

you may want to write a few more tests, i didn't bother.

resolves #2426

@SArpnt SArpnt changed the title dynamically allocate space for JQ_COLORS dynamically allocate space for JQ_COLORS (#2426) Mar 3, 2025
@SArpnt SArpnt changed the title dynamically allocate space for JQ_COLORS (#2426) dynamically allocate space for JQ_COLORS Mar 5, 2025
@itchyny
Copy link
Contributor

itchyny commented Mar 6, 2025

Thanks for submitting a PR. My honest impression is the patch makes the implementation too complicated by reducing the number of allocations and avoiding strspn. I submitted #3288 to support longer color configurations like true color, while keeping the code as simple as before. What do you think?

@SArpnt
Copy link
Contributor Author

SArpnt commented Mar 8, 2025

i can't tell which functions are part of libjq and which aren't. if jq_set_colors is part of the library, it's leaking memory. if it's not, then a lot of the code in your function is unneccecary and confusing, and i could write a simpler version of the function than what i gave in this pr. i could also just do a better job on comments and variable names.

i kept close to the original style because i figure that's just what most people from contributions, even for as lax as this project has it. i would've done it differently, most notably better variable names.
i looked into the strspn optimization because i don't like or trust c (considering that gcc didn't optimize it i think i was right to do that), but the original code used it, and i was matching style first. if i had written it from scratch i wouldn't have used strspn in the first place, and there wouldn't be a comment.

i prefer checking the entire string first not just because it saves the allocation but also because it's just clearer that everything gets discarded when any of the colors are invalid.

as for the code style, in the end it's your codebase, your choice, and i don't really write c. but if you're asking what i think on that:
i didn't find the code before simple at all, i was pretty confused by the amount of indirection and extra variables involved, and probably spent an hour going through the old function just to figure out what it was doing. i get confused reading the new one from all the unnecessary bits too.

even reading the new code now, i keep getting color_buf, color_bufs, and color_bufps confused, and i can never remember which one's which a minute after reading the code
this is impossible to make sense of, especially with this code coming before any of these variables even get used.

if ((e = strchr(c, ':')) != NULL)
  l = e++ - c;
else
  e = c + (l = strlen(c));

strncpy(&color_buf[2], c, l); implies l might be longer than the string and this needs to be corrected for, but i don't think that ever happens? a memcpy wouldn't have that implication.

near the start you set colors = def_colors;, but that's after the null check. this implies the function might be called while colors isn't already set to def_colors (so more than once), but that a null string should leave it unchanged?
if you did this though, all the allocations would get leaked.

on that note, the allocations also get leaked if JQ_COLORS is invalid. i also just noticed that on the only call to jq_set_colors, it already doesn't even pass in the environment variable if it's NULL, so the check isn't doing anything.

i get that the tiny leaks don't matter much for performance, but all these little issues throw me off when just trying to make sense of the code.

@SArpnt SArpnt marked this pull request as draft March 8, 2025 05:05
@SArpnt SArpnt marked this pull request as ready for review March 8, 2025 05:05
@SArpnt
Copy link
Contributor Author

SArpnt commented Mar 8, 2025

i made the extra pr before i fully thought things through, ignore it.
here's a bunch of amend/fixup commits to increasingly simplify things.
up to 0be0d2e is just a clearer version of approximately the same code, it's what i should've wrote in the first place.
cherry pick 8f2e9ca (designed to be called only once) if you can, cherry pick 171c99b (strspn instead of switch) if you must.

@itchyny
Copy link
Contributor

itchyny commented Mar 8, 2025

Thank you for your valuable comment! Yes, you're right about the allocation leak, and since the function is included in jq.h, I have to admit that it is an API of libjq and should not leak memory when called twice. I think it should be tested in jq_test.c.

SArpnt added 4 commits March 9, 2025 12:46
valid color escapes can be over 100 characters long,
so a static buffer isn't a good option.

resolves jqlang#2426
change the switch case to a strspn
gcc will do a worse job optimizing this but it makes the code shorter and easier to read
@SArpnt
Copy link
Contributor Author

SArpnt commented Mar 9, 2025

dropped the commit that assumes the function can only be called once, and cleaned up the history a bit. each point in the history builds and passes tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JQ_COLORS truecolor support
2 participants