LCOV - code coverage report
Current view: top level - py - objint.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.24.0-7-g548babf8a.info Lines: 149 149 100.0 %
Date: 2024-10-30 09:06:48 Functions: 9 9 100.0 %
Branches: 115 133 86.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of the MicroPython project, http://micropython.org/
       3                 :            :  *
       4                 :            :  * The MIT License (MIT)
       5                 :            :  *
       6                 :            :  * Copyright (c) 2013, 2014 Damien P. George
       7                 :            :  *
       8                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :            :  * of this software and associated documentation files (the "Software"), to deal
      10                 :            :  * in the Software without restriction, including without limitation the rights
      11                 :            :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :            :  * copies of the Software, and to permit persons to whom the Software is
      13                 :            :  * furnished to do so, subject to the following conditions:
      14                 :            :  *
      15                 :            :  * The above copyright notice and this permission notice shall be included in
      16                 :            :  * all copies or substantial portions of the Software.
      17                 :            :  *
      18                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :            :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :            :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      24                 :            :  * THE SOFTWARE.
      25                 :            :  */
      26                 :            : 
      27                 :            : #include <stdlib.h>
      28                 :            : #include <assert.h>
      29                 :            : #include <string.h>
      30                 :            : 
      31                 :            : #include "py/parsenum.h"
      32                 :            : #include "py/smallint.h"
      33                 :            : #include "py/objint.h"
      34                 :            : #include "py/objstr.h"
      35                 :            : #include "py/runtime.h"
      36                 :            : #include "py/binary.h"
      37                 :            : 
      38                 :            : #if MICROPY_PY_BUILTINS_FLOAT
      39                 :            : #include <math.h>
      40                 :            : #endif
      41                 :            : 
      42                 :            : // This dispatcher function is expected to be independent of the implementation of long int
      43                 :     324656 : 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) {
      44                 :     324656 :     (void)type_in;
      45                 :     324656 :     mp_arg_check_num(n_args, n_kw, 0, 2, false);
      46                 :            : 
      47      [ +  +  + ]:     324656 :     switch (n_args) {
      48                 :            :         case 0:
      49                 :            :             return MP_OBJ_NEW_SMALL_INT(0);
      50                 :            : 
      51                 :     324452 :         case 1: {
      52                 :     324452 :             mp_buffer_info_t bufinfo;
      53                 :     324452 :             mp_obj_t o = mp_unary_op(MP_UNARY_OP_INT_MAYBE, args[0]);
      54         [ +  + ]:     324448 :             if (o != MP_OBJ_NULL) {
      55                 :            :                 return o;
      56         [ +  + ]:     165149 :             } else if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
      57                 :            :                 // a textual representation, parse it
      58                 :        646 :                 return mp_parse_num_integer(bufinfo.buf, bufinfo.len, 0, NULL);
      59                 :            :             #if MICROPY_PY_BUILTINS_FLOAT
      60   [ -  +  -  +  :     164503 :             } else if (mp_obj_is_float(args[0])) {
          -  +  +  -  +  
                      + ]
      61                 :     164499 :                 return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
      62                 :            :             #endif
      63                 :            :             } else {
      64                 :          4 :                 mp_raise_TypeError_int_conversion(args[0]);
      65                 :            :             }
      66                 :            :         }
      67                 :            : 
      68                 :        192 :         case 2:
      69                 :            :         default: {
      70                 :            :             // should be a string, parse it
      71                 :        192 :             size_t l;
      72                 :        192 :             const char *s = mp_obj_str_get_data(args[0], &l);
      73                 :        192 :             return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
      74                 :            :         }
      75                 :            :     }
      76                 :            : }
      77                 :            : 
      78                 :            : #if MICROPY_PY_BUILTINS_FLOAT
      79                 :            : 
      80                 :            : typedef enum {
      81                 :            :     MP_FP_CLASS_FIT_SMALLINT,
      82                 :            :     MP_FP_CLASS_FIT_LONGINT,
      83                 :            :     MP_FP_CLASS_OVERFLOW
      84                 :            : } mp_fp_as_int_class_t;
      85                 :            : 
      86                 :     164831 : static mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
      87                 :     164831 :     union {
      88                 :            :         mp_float_t f;
      89                 :            :         #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
      90                 :            :         uint32_t i;
      91                 :            :         #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
      92                 :            :         uint32_t i[2];
      93                 :            :         #endif
      94                 :     164831 :     } u = {val};
      95                 :            : 
      96                 :     164831 :     uint32_t e;
      97                 :            :     #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
      98                 :            :     e = u.i;
      99                 :            :     #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
     100                 :     164831 :     e = u.i[MP_ENDIANNESS_LITTLE];
     101                 :            :     #endif
     102                 :            : #define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32)
     103                 :            : #define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32)
     104                 :            : 
     105         [ +  + ]:     164831 :     if (e & (1U << MP_FLOAT_SIGN_SHIFT_I32)) {
     106                 :            :         #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
     107                 :     159095 :         e |= u.i[MP_ENDIANNESS_BIG] != 0;
     108                 :            :         #endif
     109         [ +  + ]:     159095 :         if ((e & ~(1U << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {
     110                 :            :             // handle case of -0 (when sign is set but rest of bits are zero)
     111                 :            :             e = 0;
     112                 :            :         } else {
     113                 :     159071 :             e += ((1U << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
     114                 :            :         }
     115                 :            :     } else {
     116                 :       5736 :         e &= ~((1U << MP_FLOAT_EXP_SHIFT_I32) - 1);
     117                 :            :     }
     118                 :            :     // 8 * sizeof(uintptr_t) counts the number of bits for a small int
     119                 :            :     // TODO provide a way to configure this properly
     120         [ +  + ]:     164807 :     if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) {
     121                 :     160375 :         return MP_FP_CLASS_FIT_SMALLINT;
     122                 :            :     }
     123                 :            :     #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
     124                 :            :     if (e <= (((sizeof(long long) * MP_BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) {
     125                 :            :         return MP_FP_CLASS_FIT_LONGINT;
     126                 :            :     }
     127                 :            :     #endif
     128                 :            :     #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
     129                 :            :     return MP_FP_CLASS_FIT_LONGINT;
     130                 :            :     #else
     131                 :            :     return MP_FP_CLASS_OVERFLOW;
     132                 :            :     #endif
     133                 :            : }
     134                 :            : #undef MP_FLOAT_SIGN_SHIFT_I32
     135                 :            : #undef MP_FLOAT_EXP_SHIFT_I32
     136                 :            : 
     137                 :     164931 : mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
     138                 :     164931 :     mp_float_union_t u = {val};
     139                 :            :     // IEEE-754: if biased exponent is all 1 bits...
     140         [ +  + ]:     164931 :     if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
     141                 :            :         // ...then number is Inf (positive or negative) if fraction is 0, else NaN.
     142         [ +  + ]:        100 :         if (u.p.frc == 0) {
     143                 :         60 :             mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
     144                 :            :         } else {
     145                 :         40 :             mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
     146                 :            :         }
     147                 :            :     } else {
     148                 :     164831 :         mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
     149         [ +  + ]:     164831 :         if (icl == MP_FP_CLASS_FIT_SMALLINT) {
     150                 :     160375 :             return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
     151                 :            :         #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
     152                 :            :         } else {
     153                 :       4456 :             mp_obj_int_t *o = mp_obj_int_new_mpz();
     154                 :       4456 :             mpz_set_from_float(&o->mpz, val);
     155                 :       4456 :             return MP_OBJ_FROM_PTR(o);
     156                 :            :         }
     157                 :            :         #else
     158                 :            :         #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
     159                 :            :         } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
     160                 :            :             return mp_obj_new_int_from_ll((long long)val);
     161                 :            :         #endif
     162                 :            :         } else {
     163                 :            :             mp_raise_ValueError(MP_ERROR_TEXT("float too big"));
     164                 :            :         }
     165                 :            :         #endif
     166                 :            :     }
     167                 :            : }
     168                 :            : 
     169                 :            : #endif
     170                 :            : 
     171                 :            : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
     172                 :            : typedef mp_longint_impl_t fmt_int_t;
     173                 :            : typedef unsigned long long fmt_uint_t;
     174                 :            : #else
     175                 :            : typedef mp_int_t fmt_int_t;
     176                 :            : typedef mp_uint_t fmt_uint_t;
     177                 :            : #endif
     178                 :            : 
     179                 :     178334 : void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     180                 :     178334 :     (void)kind;
     181                 :            :     // The size of this buffer is rather arbitrary. If it's not large
     182                 :            :     // enough, a dynamic one will be allocated.
     183                 :     178334 :     char stack_buf[sizeof(fmt_int_t) * 4];
     184                 :     178334 :     char *buf = stack_buf;
     185                 :     178334 :     size_t buf_size = sizeof(stack_buf);
     186                 :     178334 :     size_t fmt_size;
     187                 :            : 
     188                 :     178334 :     char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0');
     189                 :     178334 :     mp_print_str(print, str);
     190                 :            : 
     191         [ +  + ]:     178334 :     if (buf != stack_buf) {
     192                 :       8500 :         m_del(char, buf, buf_size);
     193                 :            :     }
     194                 :     178334 : }
     195                 :            : 
     196                 :            : static const uint8_t log_base2_floor[] = {
     197                 :            :     0, 1, 1, 2,
     198                 :            :     2, 2, 2, 3,
     199                 :            :     3, 3, 3, 3,
     200                 :            :     3, 3, 3, 4,
     201                 :            :     /* if needed, these are the values for higher bases
     202                 :            :     4, 4, 4, 4,
     203                 :            :     4, 4, 4, 4,
     204                 :            :     4, 4, 4, 4,
     205                 :            :     4, 4, 4, 5
     206                 :            :     */
     207                 :            : };
     208                 :            : 
     209                 :     257276 : size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) {
     210         [ -  + ]:     257276 :     assert(2 <= base && base <= 16);
     211                 :     257276 :     size_t num_digits = num_bits / log_base2_floor[base - 1] + 1;
     212         [ +  + ]:     257276 :     size_t num_commas = comma ? num_digits / 3 : 0;
     213         [ +  + ]:     257276 :     size_t prefix_len = prefix ? strlen(prefix) : 0;
     214                 :     257276 :     return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte
     215                 :            : }
     216                 :            : 
     217                 :            : // This routine expects you to pass in a buffer and size (in *buf and *buf_size).
     218                 :            : // If, for some reason, this buffer is too small, then it will allocate a
     219                 :            : // buffer and return the allocated buffer and size in *buf and *buf_size. It
     220                 :            : // is the callers responsibility to free this allocated buffer.
     221                 :            : //
     222                 :            : // The resulting formatted string will be returned from this function and the
     223                 :            : // formatted size will be in *fmt_size.
     224                 :     257276 : char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
     225                 :            :     int base, const char *prefix, char base_char, char comma) {
     226                 :     257276 :     fmt_int_t num;
     227                 :            :     #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
     228                 :            :     // Only have small ints; get the integer value to format.
     229                 :            :     num = MP_OBJ_SMALL_INT_VALUE(self_in);
     230                 :            :     #else
     231         [ +  + ]:     257276 :     if (mp_obj_is_small_int(self_in)) {
     232                 :            :         // A small int; get the integer value to format.
     233                 :     234606 :         num = MP_OBJ_SMALL_INT_VALUE(self_in);
     234                 :            :     } else {
     235   [ +  -  -  + ]:      22670 :         assert(mp_obj_is_exact_type(self_in, &mp_type_int));
     236                 :            :         // Not a small int.
     237                 :            :         #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
     238                 :            :         const mp_obj_int_t *self = self_in;
     239                 :            :         // Get the value to format; mp_obj_get_int truncates to mp_int_t.
     240                 :            :         num = self->val;
     241                 :            :         #else
     242                 :            :         // Delegate to the implementation for the long int.
     243                 :      22670 :         return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);
     244                 :            :         #endif
     245                 :            :     }
     246                 :            :     #endif
     247                 :            : 
     248                 :     234606 :     char sign = '\0';
     249         [ +  + ]:     234606 :     if (num < 0) {
     250                 :       4272 :         num = -num;
     251                 :       4272 :         sign = '-';
     252                 :            :     }
     253                 :            : 
     254                 :     234606 :     size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma);
     255         [ +  + ]:     234608 :     if (needed_size > *buf_size) {
     256                 :        784 :         *buf = m_new(char, needed_size);
     257                 :        784 :         *buf_size = needed_size;
     258                 :            :     }
     259                 :     234608 :     char *str = *buf;
     260                 :            : 
     261                 :     234608 :     char *b = str + needed_size;
     262                 :     234608 :     *(--b) = '\0';
     263                 :     234608 :     char *last_comma = b;
     264                 :            : 
     265         [ +  + ]:     234608 :     if (num == 0) {
     266                 :      62773 :         *(--b) = '0';
     267                 :            :     } else {
     268                 :     337715 :         do {
     269                 :            :             // The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic
     270                 :     337715 :             int c = (fmt_uint_t)num % base;
     271                 :     337715 :             num = (fmt_uint_t)num / base;
     272         [ +  + ]:     337715 :             if (c >= 10) {
     273                 :      21046 :                 c += base_char - 10;
     274                 :            :             } else {
     275                 :     316669 :                 c += '0';
     276                 :            :             }
     277                 :     337715 :             *(--b) = c;
     278   [ +  +  +  -  :     337715 :             if (comma && num != 0 && b > str && (last_comma - b) == 3) {
                   +  + ]
     279                 :          8 :                 *(--b) = comma;
     280                 :          8 :                 last_comma = b;
     281                 :            :             }
     282                 :            :         }
     283         [ +  + ]:     337715 :         while (b > str && num != 0);
     284                 :            :     }
     285         [ +  + ]:     234608 :     if (prefix) {
     286                 :      23460 :         size_t prefix_len = strlen(prefix);
     287                 :      23460 :         char *p = b - prefix_len;
     288         [ +  + ]:      23460 :         if (p > str) {
     289                 :      25499 :             b = p;
     290         [ +  + ]:      25499 :             while (*prefix) {
     291                 :       2040 :                 *p++ = *prefix++;
     292                 :            :             }
     293                 :            :         }
     294                 :            :     }
     295         [ +  + ]:     234608 :     if (sign && b > str) {
     296                 :       4272 :         *(--b) = sign;
     297                 :            :     }
     298                 :     234608 :     *fmt_size = *buf + needed_size - b - 1;
     299                 :            : 
     300                 :     234608 :     return b;
     301                 :            : }
     302                 :            : 
     303                 :            : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
     304                 :            : 
     305                 :            : int mp_obj_int_sign(mp_obj_t self_in) {
     306                 :            :     mp_int_t val = mp_obj_get_int(self_in);
     307                 :            :     if (val < 0) {
     308                 :            :         return -1;
     309                 :            :     } else if (val > 0) {
     310                 :            :         return 1;
     311                 :            :     } else {
     312                 :            :         return 0;
     313                 :            :     }
     314                 :            : }
     315                 :            : 
     316                 :            : // This is called for operations on SMALL_INT that are not handled by mp_unary_op
     317                 :            : mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
     318                 :            :     return MP_OBJ_NULL; // op not supported
     319                 :            : }
     320                 :            : 
     321                 :            : // This is called for operations on SMALL_INT that are not handled by mp_binary_op
     322                 :            : mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     323                 :            :     return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
     324                 :            : }
     325                 :            : 
     326                 :            : // This is called only with strings whose value doesn't fit in SMALL_INT
     327                 :            : mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
     328                 :            :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("long int not supported in this build"));
     329                 :            :     return mp_const_none;
     330                 :            : }
     331                 :            : 
     332                 :            : // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
     333                 :            : mp_obj_t mp_obj_new_int_from_ll(long long val) {
     334                 :            :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
     335                 :            :     return mp_const_none;
     336                 :            : }
     337                 :            : 
     338                 :            : // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
     339                 :            : mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
     340                 :            :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
     341                 :            :     return mp_const_none;
     342                 :            : }
     343                 :            : 
     344                 :            : mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
     345                 :            :     // SMALL_INT accepts only signed numbers, so make sure the input
     346                 :            :     // value fits completely in the small-int positive range.
     347                 :            :     if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
     348                 :            :         return MP_OBJ_NEW_SMALL_INT(value);
     349                 :            :     }
     350                 :            :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
     351                 :            :     return mp_const_none;
     352                 :            : }
     353                 :            : 
     354                 :            : mp_obj_t mp_obj_new_int(mp_int_t value) {
     355                 :            :     if (MP_SMALL_INT_FITS(value)) {
     356                 :            :         return MP_OBJ_NEW_SMALL_INT(value);
     357                 :            :     }
     358                 :            :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
     359                 :            :     return mp_const_none;
     360                 :            : }
     361                 :            : 
     362                 :            : mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
     363                 :            :     return MP_OBJ_SMALL_INT_VALUE(self_in);
     364                 :            : }
     365                 :            : 
     366                 :            : mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
     367                 :            :     return MP_OBJ_SMALL_INT_VALUE(self_in);
     368                 :            : }
     369                 :            : 
     370                 :            : #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
     371                 :            : 
     372                 :            : // This dispatcher function is expected to be independent of the implementation of long int
     373                 :            : // It handles the extra cases for integer-like arithmetic
     374                 :        492 : mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     375         [ +  + ]:        492 :     if (rhs_in == mp_const_false) {
     376                 :            :         // false acts as 0
     377                 :          8 :         return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));
     378         [ +  + ]:        484 :     } else if (rhs_in == mp_const_true) {
     379                 :            :         // true acts as 0
     380                 :          9 :         return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));
     381         [ +  + ]:        475 :     } else if (op == MP_BINARY_OP_MULTIPLY) {
     382   [ +  +  +  -  :        422 :         if (mp_obj_is_str_or_bytes(rhs_in) || mp_obj_is_type(rhs_in, &mp_type_tuple) || mp_obj_is_type(rhs_in, &mp_type_list)) {
          +  -  +  +  -  
          +  -  +  -  +  
          +  -  +  +  -  
          +  -  +  -  +  
             +  -  +  + ]
     383                 :            :             // multiply is commutative for these types, so delegate to them
     384                 :        418 :             return mp_binary_op(op, rhs_in, lhs_in);
     385                 :            :         }
     386                 :            :     }
     387                 :            :     return MP_OBJ_NULL; // op not supported
     388                 :            : }
     389                 :            : 
     390                 :            : // this is a classmethod
     391                 :         72 : static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
     392                 :            :     // TODO: Support signed param (assumes signed=False at the moment)
     393                 :            : 
     394                 :            :     // get the buffer info
     395                 :         72 :     mp_buffer_info_t bufinfo;
     396                 :         72 :     mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
     397                 :            : 
     398                 :         72 :     const byte *buf = (const byte *)bufinfo.buf;
     399                 :         72 :     int delta = 1;
     400   [ +  +  +  + ]:         72 :     bool big_endian = n_args < 3 || args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little);
     401         [ +  + ]:         72 :     if (!big_endian) {
     402                 :         48 :         buf += bufinfo.len - 1;
     403                 :         48 :         delta = -1;
     404                 :            :     }
     405                 :            : 
     406                 :         72 :     mp_uint_t value = 0;
     407                 :         72 :     size_t len = bufinfo.len;
     408         [ +  + ]:        756 :     for (; len--; buf += delta) {
     409                 :            :         #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
     410         [ +  + ]:        708 :         if (value > (MP_SMALL_INT_MAX >> 8)) {
     411                 :            :             // Result will overflow a small-int so construct a big-int
     412                 :         24 :             return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
     413                 :            :         }
     414                 :            :         #endif
     415                 :        684 :         value = (value << 8) | *buf;
     416                 :            :     }
     417                 :         48 :     return mp_obj_new_int_from_uint(value);
     418                 :            : }
     419                 :            : 
     420                 :            : static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 4, int_from_bytes);
     421                 :            : static MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj));
     422                 :            : 
     423                 :        228 : static mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) {
     424                 :            :     // TODO: Support signed (currently behaves as if signed=(val < 0))
     425                 :        228 :     bool overflow;
     426                 :            : 
     427         [ +  + ]:        228 :     mp_int_t dlen = n_args < 2 ? 1 : mp_obj_get_int(args[1]);
     428         [ +  + ]:        220 :     if (dlen < 0) {
     429                 :          4 :         mp_raise_ValueError(NULL);
     430                 :            :     }
     431   [ +  +  +  + ]:        224 :     bool big_endian = n_args < 3 || args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little);
     432                 :            : 
     433                 :        224 :     vstr_t vstr;
     434                 :        224 :     vstr_init_len(&vstr, dlen);
     435                 :        224 :     byte *data = (byte *)vstr.buf;
     436                 :            : 
     437                 :            :     #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
     438         [ +  + ]:        224 :     if (!mp_obj_is_small_int(args[0])) {
     439                 :        100 :         overflow = !mp_obj_int_to_bytes_impl(args[0], big_endian, dlen, data);
     440                 :            :     } else
     441                 :            :     #endif
     442                 :            :     {
     443                 :        124 :         mp_int_t val = MP_OBJ_SMALL_INT_VALUE(args[0]);
     444                 :        124 :         int slen = 0;  // Number of bytes to represent val
     445                 :            : 
     446                 :            :         // This logic has a twin in objint_longlong.c
     447         [ +  + ]:        124 :         if (val > 0) {
     448                 :         80 :             slen = (sizeof(mp_int_t) * 8 - mp_clz_mpi(val) + 7) / 8;
     449         [ +  + ]:         44 :         } else if (val < -1) {
     450                 :         24 :             slen = (sizeof(mp_int_t) * 8 - mp_clz_mpi(~val) + 8) / 8;
     451                 :            :         } else {
     452                 :            :             // clz of 0 is defined, so 0 and -1 map to 0 and 1
     453                 :         20 :             slen = -val;
     454                 :            :         }
     455                 :            : 
     456         [ +  + ]:        124 :         if (slen <= dlen) {
     457         [ +  + ]:         96 :             memset(data, val < 0 ? 0xFF : 0x00, dlen);
     458         [ +  + ]:         96 :             mp_binary_set_int(slen, big_endian, data + (big_endian ? (dlen - slen) : 0), val);
     459                 :         96 :             overflow = false;
     460                 :            :         } else {
     461                 :            :             overflow = true;
     462                 :            :         }
     463                 :            :     }
     464                 :            : 
     465         [ +  + ]:        196 :     if (overflow) {
     466                 :         48 :         mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("buffer too small"));
     467                 :            :     }
     468                 :            : 
     469                 :        176 :     return mp_obj_new_bytes_from_vstr(&vstr);
     470                 :            : }
     471                 :            : static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 1, 4, int_to_bytes);
     472                 :            : 
     473                 :            : static const mp_rom_map_elem_t int_locals_dict_table[] = {
     474                 :            :     { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },
     475                 :            :     { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },
     476                 :            : };
     477                 :            : 
     478                 :            : static MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);
     479                 :            : 
     480                 :            : MP_DEFINE_CONST_OBJ_TYPE(
     481                 :            :     mp_type_int,
     482                 :            :     MP_QSTR_int,
     483                 :            :     MP_TYPE_FLAG_NONE,
     484                 :            :     make_new, mp_obj_int_make_new,
     485                 :            :     print, mp_obj_int_print,
     486                 :            :     unary_op, mp_obj_int_unary_op,
     487                 :            :     binary_op, mp_obj_int_binary_op,
     488                 :            :     locals_dict, &int_locals_dict
     489                 :            :     );

Generated by: LCOV version 1.15-5-g462f71d