core/wire/wire_read.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * @file wire_read.h | ||
| 3 | * @brief Reads the values the phone packs into a message. | ||
| 4 | * | ||
| 5 | * The phone is free to send an integer one, two, or four bytes wide, and it says which by the | ||
| 6 | * length it puts beside the value rather than by the type. The values sit back to back with | ||
| 7 | * nothing between them, so a reader that takes the type's word for the width and grabs four bytes | ||
| 8 | * off a one-byte value walks straight into whatever is packed behind it. That is what these are | ||
| 9 | * for: the width decides how many bytes get read, and anything else is refused. | ||
| 10 | * | ||
| 11 | * Header only on purpose. There is one caller on the watch (tuple_read.c) and the bodies are | ||
| 12 | * smaller than a call would be, so they fold into it and nothing is spent on getting there. | ||
| 13 | * | ||
| 14 | * @ingroup lib_core | ||
| 15 | */ | ||
| 16 | #pragma once | ||
| 17 | #include <stdbool.h> | ||
| 18 | #include <stdint.h> | ||
| 19 | |||
| 20 | #include "io/bytes_le.h" | ||
| 21 | |||
| 22 | /** | ||
| 23 | * @addtogroup lib_core | ||
| 24 | * @{ | ||
| 25 | */ | ||
| 26 | |||
| 27 | /** | ||
| 28 | * @brief Reads a little-endian integer of exactly @p length bytes. | ||
| 29 | * | ||
| 30 | * @param is_signed Whether the value is signed. Decides only what the top bit means. | ||
| 31 | * @param length How many bytes the value occupies. 1, 2, and 4 are the widths a sender may use, | ||
| 32 | * and anything else is refused rather than guessed at. | ||
| 33 | * @param value The first byte of the value. | ||
| 34 | * @param fallback Returned when the width is not one a sender may use, or there is no value. | ||
| 35 | * @return The value, or @p fallback. | ||
| 36 | */ | ||
| 37 | 10 | static inline int32_t wire_int_or(bool is_signed, uint16_t length, const uint8_t *value, int32_t fallback) | |
| 38 | { | ||
| 39 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9 times.
|
10 | if (!value) |
| 40 | { | ||
| 41 | 1 | return fallback; | |
| 42 | } | ||
| 43 | |||
| 44 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
9 | switch (length) |
| 45 | { | ||
| 46 | // a byte read signed is -128 to 127 and unsigned is 0 to 255 | ||
| 47 | // that is the only thing the signedness decides at this width | ||
| 48 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 | case 1: return is_signed ? (int32_t)(int8_t)value[0] : (int32_t)value[0]; |
| 49 | |||
| 50 | // read the pair as signed and take the sign back off when it is not wanted | ||
| 51 | // so the unsigned half lands on 0 to 65535 rather than going negative at the top | ||
| 52 | 1 | case 2: return is_signed ? (int32_t)read_i16_le(value) | |
| 53 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
3 | : (int32_t)(uint16_t)read_i16_le(value); |
| 54 | |||
| 55 | // four bytes fill the whole width either way so the bits are the same | ||
| 56 | // and only the caller's reading of the top one differs | ||
| 57 | 2 | case 4: return read_i32_le(value); | |
| 58 | |||
| 59 | 2 | default: return fallback; | |
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * @brief Whether a string of @p length bytes carries its terminator inside itself. | ||
| 65 | * | ||
| 66 | * A sender is supposed to include the terminator and nothing re-checks that it did. A string | ||
| 67 | * without one is not a string: reading it runs on past the end looking for a zero byte that | ||
| 68 | * belongs to something else, or to nothing at all. | ||
| 69 | * | ||
| 70 | * @param s The first byte of the string. | ||
| 71 | * @param length How many bytes the string occupies, terminator included. | ||
| 72 | * @return Whether it is safe to read as a C string. | ||
| 73 | */ | ||
| 74 | 5 | static inline bool wire_cstring_terminated(const char *s, uint16_t length) | |
| 75 | { | ||
| 76 |
5/6✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
|
5 | return s && length > 0 && s[length - 1] == '\0'; |
| 77 | } | ||
| 78 | |||
| 79 | /** @} */ | ||
| 80 |