summaryrefslogtreecommitdiff
path: root/shared-bindings/bleio/Address.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-bindings/bleio/Address.c')
-rw-r--r--shared-bindings/bleio/Address.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c
index ec23ff207..d4c24e4e2 100644
--- a/shared-bindings/bleio/Address.c
+++ b/shared-bindings/bleio/Address.c
@@ -33,8 +33,12 @@
#include "shared-bindings/bleio/Address.h"
#include "shared-module/bleio/Address.h"
-#define ADDRESS_LONG_LEN 17 // XX:XX:XX:XX:XX:XX
-#define ADDRESS_SHORT_LEN 12 // XXXXXXXXXXXX
+#define ADDRESS_BYTE_LEN 12
+
+STATIC uint8_t xdigit_8b_value(byte nibble1, byte nibble2) {
+ return unichar_xdigit_value(nibble1) | (unichar_xdigit_value(nibble2) << 4);
+}
+
//| .. currentmodule:: bleio
//|
@@ -49,7 +53,7 @@
//| Create a new Address object encapsulating the address value.
//| The value itself can be one of:
//|
-//| - a `str` value in the format of 'XXXXXXXXXXXX' or 'XX:XX:XX:XX:XX'
+//| - a `str` value in the format of 'XXXXXXXXXXXX' or 'XX:XX:XX:XX:XX:XX' (12 hex digits)
//| - a `bytes` or `bytearray` containing 6 bytes
//| - another Address object
//|
@@ -85,26 +89,41 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t address = args[ARG_address].u_obj;
if (MP_OBJ_IS_STR(address)) {
- GET_STR_DATA_LEN(address, str_data, str_len);
- const bool is_long = (str_len == ADDRESS_LONG_LEN);
- const bool is_short = (str_len == ADDRESS_SHORT_LEN);
+ GET_STR_DATA_LEN(address, str, str_len);
+
+ size_t value_index = 0;
+ size_t str_index = str_len;
+ bool error = false;
+
+ // Loop until fewer than two characters left.
+ while (str_index >= 1 && value_index < sizeof(self->value)) {
+ if (str[str_index] == ':') {
+ // Skip colon separators.
+ str_index--;
+ continue;
+ }
- if (is_long || is_short) {
- size_t i = str_len - 1;
- for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) {
- self->value[b] = unichar_xdigit_value(str_data[i]) |
- unichar_xdigit_value(str_data[i - 1]) << 4;
+ if (!unichar_isxdigit(str[str_index]) ||
+ !unichar_isxdigit(str[str_index-1])) {
+ error = true;
+ break;
+ }
- i -= is_long ? 3 : 2;
+ self->value[value_index] = xdigit_8b_value(str[str_index],
+ str[str_index-1]);
+ value_index += 1;
+ str_index -= 2;
}
- } else {
- mp_raise_ValueError(translate("Wrong address length"));
+ // Check for correct number of hex digits and no parsing errors.
+ if (error || value_index != ADDRESS_BYTE_LEN || str_index != -1) {
+ mp_raise_ValueError_varg(translate("Address is not %d bytes long or is in wrong format"),
+ ADDRESS_BYTE_LEN);
}
} else if (MP_OBJ_IS_TYPE(address, &mp_type_bytearray) || MP_OBJ_IS_TYPE(address, &mp_type_bytes)) {
mp_buffer_info_t buf_info;
mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
if (buf_info.len != BLEIO_ADDRESS_BYTES) {
- mp_raise_ValueError(translate("Wrong number of bytes provided"));
+ mp_raise_ValueError_varg(translate("Address must be %d bytes long"), BLEIO_ADDRESS_BYTES);
}
for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) {