Skip to content

sys/fmt: add hex/bytes sequence converters#8343

Merged
kaspar030 merged 2 commits intoRIOT-OS:masterfrom
aabadie:pr/fmt_hex_bytes
Jan 11, 2018
Merged

sys/fmt: add hex/bytes sequence converters#8343
kaspar030 merged 2 commits intoRIOT-OS:masterfrom
aabadie:pr/fmt_hex_bytes

Conversation

@aabadie
Copy link
Copy Markdown
Contributor

@aabadie aabadie commented Jan 10, 2018

Contribution description

This PR adds 2 new formatting function to the fmt module:

  • fmt_bytes_hex: converts an array of bytes to an array of hex bytes
  • fmt_hex_bytes: converts an array of hex bytes to an array of bytes

Since I twice had the same comment in #8264 and #7505 about this (because I need these converters there), I think it's useful to provide them in a common place.

I also added simple unittests for the new functions.

Issues/PRs references

Related to #8264 and #7505

@aabadie aabadie added the Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation label Jan 10, 2018
sys/fmt/fmt.c Outdated
size_t fmt_bytes_hex(char *out, const uint8_t *ptr, size_t n)
{
size_t i = 0;
while (i < n) {
Copy link
Copy Markdown
Contributor

@kaspar030 kaspar030 Jan 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. all functions in fmt just return the number of bytes that would have written, should out be NULL
  2. while your code might be more readable to some, better keep the style of the rest of the file.

Please replace the while loop with:

if (out) {
  while (n--) {
    out += fmt_byte_hex(out, *ptr++);
  }
}

(untested, but should be equivalent)

@kaspar030
Copy link
Copy Markdown
Contributor

Would you mind splitting this PR and move the hex to byte converter in another?
The reason is that bytes to hex is clear how to do it, but I will discuss the need of that 32b array. ;)

@kaspar030
Copy link
Copy Markdown
Contributor

See aabadie#5. It saves 16b on ARM. Not sure if it is much of an improvement. ;) What do you think?

@aabadie
Copy link
Copy Markdown
Contributor Author

aabadie commented Jan 10, 2018

What do you think?

It looks good and smaller.

@aabadie aabadie force-pushed the pr/fmt_hex_bytes branch 2 times, most recently from 54296bf to d4364ae Compare January 10, 2018 13:03
@aabadie
Copy link
Copy Markdown
Contributor Author

aabadie commented Jan 10, 2018

@kaspar030, I integrated your PR and extended the unit tests (including converting hex >= A).

bytes = fmt_bytes_hex(out, val, 1);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(2, bytes);
TEST_ASSERT_EQUAL_STRING("AA", (char *) out);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please at a n == 0 test also?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all done

hex2[2] = '\0';
val1[0] = 0;
fmt_hex_bytes(val1, hex2);
TEST_ASSERT_EQUAL_INT(0xAB, val1[0]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it would also be nice to test what happens if you hand over an empty string ;-).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And with strings "strlen(str) % 2 != 0" ;-)

/**
* @brief Converts a sequence of hex bytes to an array of bytes
*
* The sequence of hex characters must have an odd length:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests (and your code) suggest that they have to have an even length. Also it is undocumented what happens if you provide a string of the wrong length.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests (and your code) suggest that they have to have an even length

Indeed, I always do this mistake...

TEST_ASSERT_EQUAL_INT(3, bytes);
TEST_ASSERT_EQUAL_INT(1, val3[0]);
TEST_ASSERT_EQUAL_INT(2, val3[1]);
TEST_ASSERT_EQUAL_INT(0xAF, val3[2]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if a character in the string is not in [0-9a-fA-F]?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't work. It's possible to update but I want to keep this simple and trust the user. I added a doxygen comment for this.

sys/fmt/fmt.c Outdated
if (out) {
while (n--) {
out += fmt_byte_hex(out, *ptr++);
len += 2;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a unittest for out==NULL but n > 0.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@kaspar030
Copy link
Copy Markdown
Contributor

@aabadie lot's of work for seemlingy simple functions, eh? ;) Thanks for doing it!

@aabadie
Copy link
Copy Markdown
Contributor Author

aabadie commented Jan 10, 2018

lot's of work for seemlingy simple functions, eh?

I knew that would be the case but that's the game ;)

*
* The sequence of hex characters must have an even length:
* 2 hex character => 1 byte. If the sequence of hex has an odd length, this
* function returns 0 and a NULL out.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add the returns 0 to the documentation of @return as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*
* The sequence of hex characters must have an even length:
* 2 hex character => 1 byte. If the sequence of hex has an odd length, this
* function returns 0 and a NULL out.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a NULL out.:

  1. use @p out to reference a parameter.
  2. out is a pointer, not a pointer to a pointer, so returning NULL is not possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done?

* function returns 0 and a NULL out.
*
* The hex characters sequence must contain valid hexadecimal characters
* otherwise this function returns an invalid byte array.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is "an invalid byte array" in this case? Maybe a better wording would be "[…] otherwise the result in out will be undefined."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

TEST_ASSERT_EQUAL_INT(1, bytes);
TEST_ASSERT_EQUAL_INT(0xEF, val1[0]);

char hex4[6] = "0102aF";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More hex4[7] ? Or hex4[] ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arf, fixed

*
* @param[out] out Pointer to converted bytes, or NULL
* @param[in] hex Pointer to input buffer
* @returns strlen(hex) / 2 for a valid sequence of hex bytes
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal preference, but I would prefer another specification of what a "valid sequence" is here (e.g. "strlen(hex) / 2 when length of @p hex was even"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, done

Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK, please squash.

- fmt_bytes_hex: converts an array of bytes to an array of hex bytes
- fmt_hex_bytes: convert an array of hex bytes to an array of bytes
@aabadie
Copy link
Copy Markdown
Contributor Author

aabadie commented Jan 10, 2018

squashed and rebased

@aabadie aabadie added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jan 10, 2018
@kaspar030 kaspar030 merged commit 7a81386 into RIOT-OS:master Jan 11, 2018
@aabadie aabadie added this to the Release 2018.01 milestone Jan 18, 2018
@aabadie aabadie deleted the pr/fmt_hex_bytes branch February 26, 2018 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants