Skip to content

Commit

Permalink
py/objint.c: Code review of int_from_bytes().
Browse files Browse the repository at this point in the history
Support signed param:
result = int.int_from_bytes(bytearray(),
order='big'|'little', signed=False|True)

Signed-off-by: Ihor Nehrutsa <[email protected]>
  • Loading branch information
IhorNehrutsa committed Feb 22, 2025
1 parent 8987b39 commit 1f0cf46
Showing 1 changed file with 90 additions and 0 deletions.
90 changes: 90 additions & 0 deletions py/objint.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include <math.h>
#endif

#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n"); // mp_printf(&mp_plat_print, " | func:%s line:%d at %s\n", __FUNCTION__, __LINE__, __FILE__);

// This dispatcher function is expected to be independent of the implementation of long int
static mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
(void)type_in;
Expand Down Expand Up @@ -387,6 +389,7 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp
return MP_OBJ_NULL; // op not supported
}

/*
// this is a classmethod
static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
// TODO: Support signed param (assumes signed=False at the moment)
Expand Down Expand Up @@ -416,6 +419,93 @@ static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
}
return mp_obj_new_int_from_uint(value);
}
*/
static void *reverce_memcpy(void *dest, const void *src, size_t len) {
char *d = (char *)dest + len - 1;
const char *s = src;
while (len--) {
*d-- = *s++;
}
return dest;
}

// this is a classmethod
// result = int.int_from_bytes(bytearray(), order='big', signed=False)
static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
const byte *buf = (const byte *)bufinfo.buf;
bool big_endian = (n_args < 3) || (args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little));
bool signd = (n_args > 3) && mp_obj_is_true(args[3]);

// debug_printf("mp_obj_is_bool(args[3])=%d", mp_obj_is_bool(args[3]));
// debug_printf("n_args=%d, MP_SMALL_INT_MAX=%d, MP_SMALL_INT_MIN=%d", n_args, MP_SMALL_INT_MAX, MP_SMALL_INT_MIN);
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
// if (((1U << (bufinfo.len * 8 - 2)) > (MP_SMALL_INT_MAX + 1)) || (big_endian ? buf[0] & 0x80 : buf[bufinfo.len - 1] & 0x80)) {
if ((1ULL << (bufinfo.len * 8 - 2)) > (MP_SMALL_INT_MAX + 1)) {
debug_printf("//1 Result will overflow a small-int so construct a big-int");
return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
}
#endif

union {
mp_int_t ival;
mp_uint_t uval;
} result;
if (big_endian) {
reverce_memcpy(&result.uval, buf, bufinfo.len);
} else {
memcpy(&result.uval, buf, bufinfo.len);
}
if (signd) {
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
debug_printf("big_endian:%d signed:%d bufinfo.len:%d sizeof(result.ival):%d result.ival:%ld", big_endian, signd, bufinfo.len, sizeof(result.ival), result.ival);
if ((result.ival > MP_SMALL_INT_MAX) || (result.ival < MP_SMALL_INT_MIN)) {
debug_printf("//2 Result will overflow a small-int so construct a big-int");
return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
}
#endif
return mp_obj_new_int(result.ival);
} else {
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
debug_printf("big_endian:%d signed:%d bufinfo.len:%d sizeof(result.uval):%d result.uval:%ld", big_endian, signd, bufinfo.len, sizeof(result.uval), result.uval);
if (result.uval > MP_SMALL_INT_MAX) {
debug_printf("//3 Result will overflow a small-int so construct a big-int");
return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
}
#endif
return mp_obj_new_int_from_uint(result.uval);
}
/*
if (signd) {
mp_int_t result = 0;
if (big_endian) {
reverce_memcpy(&result, buf, bufinfo.len);
} else {
memcpy(&result, buf, bufinfo.len);
}
debug_printf("big_endian:%d signed:%d bufinfo.len:%d sizeof(result):%d result:%ld", big_endian, signd, bufinfo.len, sizeof(result), result);
if ((result > MP_SMALL_INT_MAX) || (result < MP_SMALL_INT_MIN)) {
debug_printf("// Result will overflow a small-int so construct a big-int");
return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
}
return mp_obj_new_int(result);
} else {
mp_uint_t result = 0;
if (big_endian) {
reverce_memcpy(&result, buf, bufinfo.len);
} else {
memcpy(&result, buf, bufinfo.len);
}
debug_printf("big_endian:%d unsigned:%d bufinfo.len:%d sizeof(result):%d result:%ld", big_endian, signd, bufinfo.len, sizeof(result), result);
if ((result > MP_SMALL_INT_MAX) || (result < MP_SMALL_INT_MIN)) {
debug_printf("// Result will overflow a small-int so construct a big-int");
return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
}
return mp_obj_new_int_from_uint(result);
}
*/
}

static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 4, int_from_bytes);
static MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj));
Expand Down

0 comments on commit 1f0cf46

Please sign in to comment.