-
Notifications
You must be signed in to change notification settings - Fork 2k
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
sys/string_utils: add string_writer helper #20843
base: master
Are you sure you want to change the base?
Conversation
That API indeed disarms the usual footguns :) I wonder if there is some BSD / whatever API already that we could steal? |
815f30d
to
b2b49d3
Compare
b2b49d3
to
e52ffe9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All in all looks good. Some nits, some ideas.
You mentioned that this is often done manually in RIOT, could you also replace such instances with this helper right away?
res = swprintf(&sw, "0123456789"); | ||
TEST_ASSERT_EQUAL_INT(res, 10); | ||
res = swprintf(&sw, "01234567891"); | ||
TEST_ASSERT_EQUAL_INT(res, -E2BIG); | ||
res = swprintf(&sw, "###"); | ||
TEST_ASSERT_EQUAL_INT(res, -E2BIG); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is worth it, to use a new string_writer_t
+ buffer. Not because it's technically needed but it signals to the reader "we are testing a new/different behavior". Also, which behavior is tested here? ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No this is all the same string write - we want to append to it until it's full and test at every step that it behaves as expected.
I added comments to better explain what's going on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great improvements.
Squash & Ci? |
6eea402
to
62e0d3f
Compare
62e0d3f
to
ce88749
Compare
ce88749
to
0fe3ac4
Compare
* @return number of bytes written on success | ||
* -E2BIG if the string was truncated | ||
*/ | ||
int swprintf(string_writer_t *sw, const char *restrict format, ...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can add
__attribute__ ((format (printf, 2, 3)))
to enable static printf-like compiler checks for the format string and arguments, see https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html.
#endif | ||
|
||
va_start(args, format); | ||
res = vsnprintf(sw->position, sw->capacity, format, args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang should complain here, you can:
#ifdef __clang__
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wformat-nonliteral\"") \
res = vsnprintf(sw->position, sw->capacity, format, args);
_Pragma("clang diagnostic pop")
#else
res = vsnprintf(sw->position, sw->capacity, format, args);
#endif
res = vsnprintf(sw->position, sw->capacity, format, args); | ||
va_end(args); | ||
|
||
if (res <= (int)sw->capacity) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if res == capacity
, the output was truncated by one character. This check should therefore be <
.
Contribution description
Assembling a string through multiple writes if often open-coded like this
This is error prone (the above example foregoes any error handling) and ugly.
This introduces a small helper function to achieve the same in a much more convenient fasion:
Testing procedure
A new unit test has been added.
Issues/PRs references