3 ms·
FWIW, part of the fun of strjcpy is that it is also much easier to write than strxcpy (and watch as I go further and further out on a limb with sketchy C that i
by saurik 5y ago
FWIW, part of the fun of strjcpy is that it is also much easier to write than strxcpy (and watch as I go further and further out on a limb with sketchy C that is likely wrong, lol... I did test it, at least! ;P):
char *strjcpy(char *restrict dst, const char *restrict src, size_t len) {
for (;; ++dst, --len)
if (!len || !(*dst = *src++))
return dst;
}
(edit) Oh, I have an even cuter implementation (which might look "too clever" but actually demonstrates something important about the function)! Essentially, what makes strjcpy so "pure" is that the NULL return is really a "special case" in strxcpy that you're having to "undo" in that wrapper, whereas the semantics of strjcpy--which may sound a bit weird--are mapping directly to what naturally terminates the loop: running out of space on one of the two inputs. This purity then gets taken advantage of by the caller to get such easy call chaining and error propagation, as one of these loops can "continue through" into the next loop without any adaptation logic.
char *strjcpy(char *restrict dst, const char *restrict src, size_t len) {
for (; len && (*dst = *src++); ++dst, --len);
return dst;
}
(edit) Ok: one difference is that this implementation of strjcpy (this isn't intrinsic to the return value surface I described: just to the gloriously simple versions in this comment; your adapted version, for example, is "fine") doesn't put a NUL byte in case of truncation... though, I personally am not at all sold on doing that: I want to firmly fail the operation, rather than try to "use" the truncated data :/. Adding that special case would still result in strjcpy being simpler than strxcpy (and doesn't break its semantics advantages: just make sure to return the address of dst+len, not that extra NUL), but it isn't quite so amazingly simpler at that point ;P.
- FabHK 5y ago> doesn't put a NUL byte in case of truncation which was an explicit design goal for the author of the article.
- saurik 5y agoWhich is the reason I wrote that paragraph... right? ;P I could repeat the content of that paragraph--which explicitly states... no no no: wait, you're tricking me!--but instead I will use this opportunity (as I had run out of edit time on my comment a while back) to connect it to the original thought of how personal some of these thoughts are and then to provide the trivial patch that adds this functionality to my "elegant" implementation of strjcpy without making it as complicated as strxcpy: [redacted, as actually, omg... I immediately noticed it didn't work! Saagar's implementation of my function does have that property, of course. fixing it for real requires two of statements, one before the loop and the other after it, which is demoralizing as strxcpy arguably asked for semantics which were impossible to do well for 0-sized buffers because of this termination step] If you make the loop more complicated (more like my first copy) you can avoid the duplicate comparison, but I continue to find the elegant second copy much more elucidating, as this demonstrates visceral how the termination is a duplication of effort when chaining, as you are effectively concatenation the loops but then tacking on what should be a single termination step at the end into every intermediate loop. Really, you should just not... ooo: almost repeated that previous paragraph again ;P.