blob: e548eb833e78f2c41a780904918c02c99463edea [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python 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
Damien George660aef62014-04-02 12:22:07 +010027#include <stdlib.h>
Damien George45b43c22014-01-05 01:50:45 +000028#include <assert.h>
Dave Hylandsc4029e52014-04-07 11:19:51 -070029#include <string.h>
Damien George45b43c22014-01-05 01:50:45 +000030
Damien George51dfcb42015-01-01 20:27:54 +000031#include "py/nlr.h"
32#include "py/parsenum.h"
33#include "py/smallint.h"
34#include "py/objint.h"
35#include "py/objstr.h"
36#include "py/runtime0.h"
37#include "py/runtime.h"
Damien George271d18e2015-04-25 23:16:39 +010038#include "py/binary.h"
Paul Sokolovsky48b35722014-01-12 17:30:48 +020039
Damien Georgefb510b32014-06-01 13:32:54 +010040#if MICROPY_PY_BUILTINS_FLOAT
Damien George6433bd92014-03-30 23:13:16 +010041#include <math.h>
42#endif
43
Damien Georgee8208a72014-04-04 15:08:23 +010044// This dispatcher function is expected to be independent of the implementation of long int
Damien Georgea0c97812016-01-03 09:59:18 +000045STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +000046 (void)type_in;
Damien Georgeee7a8802014-05-11 18:37:21 +010047 mp_arg_check_num(n_args, n_kw, 0, 2, false);
Damien George20006db2014-01-18 14:10:48 +000048
Damien George45b43c22014-01-05 01:50:45 +000049 switch (n_args) {
50 case 0:
51 return MP_OBJ_NEW_SMALL_INT(0);
52
53 case 1:
Damien George813ed3b2014-05-28 14:09:46 +010054 if (MP_OBJ_IS_INT(args[0])) {
55 // already an int (small or long), just return it
56 return args[0];
Dave Hylandsb7f7c652014-08-26 12:44:46 -070057 } else if (MP_OBJ_IS_STR_OR_BYTES(args[0])) {
Damien George5573f9f2014-01-15 22:58:39 +000058 // a string, parse it
Damien Georged182b982014-08-30 14:19:41 +010059 mp_uint_t l;
Damien George698ec212014-02-08 18:17:23 +000060 const char *s = mp_obj_str_get_data(args[0], &l);
Damien George7d414a12015-02-08 01:57:40 +000061 return mp_parse_num_integer(s, l, 0, NULL);
Damien Georgefb510b32014-06-01 13:32:54 +010062#if MICROPY_PY_BUILTINS_FLOAT
Damien Georgeaaef1852015-08-20 23:30:12 +010063 } else if (mp_obj_is_float(args[0])) {
Paul Sokolovsky12033df2014-12-30 00:22:10 +020064 return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
Damien George6433bd92014-03-30 23:13:16 +010065#endif
Damien George5573f9f2014-01-15 22:58:39 +000066 } else {
Damien George813ed3b2014-05-28 14:09:46 +010067 // try to convert to small int (eg from bool)
Damien George5573f9f2014-01-15 22:58:39 +000068 return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0]));
69 }
Damien George45b43c22014-01-05 01:50:45 +000070
xybc178ea42014-01-14 21:39:05 +080071 case 2:
Damien Georgeee7a8802014-05-11 18:37:21 +010072 default: {
Damien George5573f9f2014-01-15 22:58:39 +000073 // should be a string, parse it
74 // TODO proper error checking of argument types
Damien Georged182b982014-08-30 14:19:41 +010075 mp_uint_t l;
Damien George698ec212014-02-08 18:17:23 +000076 const char *s = mp_obj_str_get_data(args[0], &l);
Damien George7d414a12015-02-08 01:57:40 +000077 return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
Damien George5fa93b62014-01-22 14:35:10 +000078 }
Damien George45b43c22014-01-05 01:50:45 +000079 }
80}
81
David Steinbergca377b12015-01-13 15:21:17 +000082#if MICROPY_PY_BUILTINS_FLOAT
83mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
84 union {
85 mp_float_t f;
86#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
87 uint32_t i;
88#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
89 uint32_t i[2];
90#endif
91 } u = {val};
92
93 uint32_t e;
94#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
95 e = u.i;
96#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
97 e = u.i[MP_ENDIANNESS_LITTLE];
98#endif
99#define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32)
100#define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32)
101
102 if (e & (1 << MP_FLOAT_SIGN_SHIFT_I32)) {
103#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
104 e |= u.i[MP_ENDIANNESS_BIG] != 0;
105#endif
106 e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
107 } else {
108 e &= ~((1 << MP_FLOAT_EXP_SHIFT_I32) - 1);
109 }
Damien Georgeda3dffa2016-01-08 17:57:30 +0000110 // 8 * sizeof(uintptr_t) counts the number of bits for a small int
111 // TODO provide a way to configure this properly
112 if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) {
David Steinbergca377b12015-01-13 15:21:17 +0000113 return MP_FP_CLASS_FIT_SMALLINT;
114 }
115#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
116 if (e <= (((sizeof(long long) * BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) {
117 return MP_FP_CLASS_FIT_LONGINT;
118 }
119#endif
120#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
121 return MP_FP_CLASS_FIT_LONGINT;
122#else
123 return MP_FP_CLASS_OVERFLOW;
124#endif
125}
126#undef MP_FLOAT_SIGN_SHIFT_I32
127#undef MP_FLOAT_EXP_SHIFT_I32
128#endif
129
Damien George7f9d1d62015-04-09 23:56:15 +0100130void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000131 (void)kind;
Dave Hylandsc4029e52014-04-07 11:19:51 -0700132 // The size of this buffer is rather arbitrary. If it's not large
133 // enough, a dynamic one will be allocated.
Damien George40f3c022014-07-03 13:25:24 +0100134 char stack_buf[sizeof(mp_int_t) * 4];
Dave Hylandsc4029e52014-04-07 11:19:51 -0700135 char *buf = stack_buf;
Damien George42f3de92014-10-03 17:44:14 +0000136 mp_uint_t buf_size = sizeof(stack_buf);
137 mp_uint_t fmt_size;
Dave Hylandsc4029e52014-04-07 11:19:51 -0700138
139 char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0');
Damien George7f9d1d62015-04-09 23:56:15 +0100140 mp_print_str(print, str);
Dave Hylandsc4029e52014-04-07 11:19:51 -0700141
142 if (buf != stack_buf) {
Damien George4d77e1a2015-02-27 09:34:51 +0000143 m_del(char, buf, buf_size);
Damien George5fa93b62014-01-22 14:35:10 +0000144 }
Damien George45b43c22014-01-05 01:50:45 +0000145}
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200146
Dave Hylandsc4029e52014-04-07 11:19:51 -0700147#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
Damien George88d7bba2014-04-08 23:30:46 +0100148typedef mp_longint_impl_t fmt_int_t;
Dave Hylandsc4029e52014-04-07 11:19:51 -0700149#else
Damien George40f3c022014-07-03 13:25:24 +0100150typedef mp_int_t fmt_int_t;
Dave Hylandsc4029e52014-04-07 11:19:51 -0700151#endif
152
Damien George1c70cbf2014-08-30 00:38:16 +0100153STATIC const uint8_t log_base2_floor[] = {
Dave Hylandsc4029e52014-04-07 11:19:51 -0700154 0,
155 0, 1, 1, 2,
156 2, 2, 2, 3,
157 3, 3, 3, 3,
158 3, 3, 3, 4,
159 4, 4, 4, 4,
160 4, 4, 4, 4,
161 4, 4, 4, 4,
162 4, 4, 4, 5
163};
164
Damien George88d7bba2014-04-08 23:30:46 +0100165STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) {
Dave Hylandsc4029e52014-04-07 11:19:51 -0700166 if (base < 2 || base > 32) {
167 return 0;
168 }
169
170 uint num_digits = sizeof(fmt_int_t) * 8 / log_base2_floor[base] + 1;
171 uint num_commas = comma ? num_digits / 3: 0;
172 uint prefix_len = prefix ? strlen(prefix) : 0;
173 return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte
174}
175
Paul Sokolovskyd72bc272014-06-06 23:08:37 +0300176// This routine expects you to pass in a buffer and size (in *buf and *buf_size).
Dave Hylandsc4029e52014-04-07 11:19:51 -0700177// If, for some reason, this buffer is too small, then it will allocate a
178// buffer and return the allocated buffer and size in *buf and *buf_size. It
179// is the callers responsibility to free this allocated buffer.
180//
181// The resulting formatted string will be returned from this function and the
182// formatted size will be in *fmt_size.
Damien George42f3de92014-10-03 17:44:14 +0000183char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,
Dave Hylandsc4029e52014-04-07 11:19:51 -0700184 int base, const char *prefix, char base_char, char comma) {
Damien George88d7bba2014-04-08 23:30:46 +0100185 fmt_int_t num;
186 if (MP_OBJ_IS_SMALL_INT(self_in)) {
187 // A small int; get the integer value to format.
188 num = mp_obj_get_int(self_in);
189#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
190 } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
191 // Not a small int.
192#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
Damien George503d6112014-05-28 14:07:21 +0100193 const mp_obj_int_t *self = self_in;
Damien George40f3c022014-07-03 13:25:24 +0100194 // Get the value to format; mp_obj_get_int truncates to mp_int_t.
Damien George88d7bba2014-04-08 23:30:46 +0100195 num = self->val;
196#else
197 // Delegate to the implementation for the long int.
198 return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);
199#endif
200#endif
201 } else {
202 // Not an int.
Paul Sokolovskyd72bc272014-06-06 23:08:37 +0300203 **buf = '\0';
Dave Hylandsc4029e52014-04-07 11:19:51 -0700204 *fmt_size = 0;
205 return *buf;
206 }
Damien George88d7bba2014-04-08 23:30:46 +0100207
Dave Hylandsc4029e52014-04-07 11:19:51 -0700208 char sign = '\0';
209 if (num < 0) {
210 num = -num;
211 sign = '-';
212 }
213
214 uint needed_size = int_as_str_size_formatted(base, prefix, comma);
215 if (needed_size > *buf_size) {
216 *buf = m_new(char, needed_size);
217 *buf_size = needed_size;
218 }
219 char *str = *buf;
220
221 char *b = str + needed_size;
222 *(--b) = '\0';
223 char *last_comma = b;
224
225 if (num == 0) {
226 *(--b) = '0';
227 } else {
228 do {
229 int c = num % base;
230 num /= base;
231 if (c >= 10) {
232 c += base_char - 10;
233 } else {
234 c += '0';
235 }
236 *(--b) = c;
237 if (comma && num != 0 && b > str && (last_comma - b) == 3) {
238 *(--b) = comma;
239 last_comma = b;
240 }
241 }
242 while (b > str && num != 0);
243 }
244 if (prefix) {
245 size_t prefix_len = strlen(prefix);
246 char *p = b - prefix_len;
247 if (p > str) {
248 b = p;
249 while (*prefix) {
250 *p++ = *prefix++;
251 }
252 }
253 }
254 if (sign && b > str) {
255 *(--b) = sign;
256 }
257 *fmt_size = *buf + needed_size - b - 1;
258
259 return b;
260}
261
Damien George88d7bba2014-04-08 23:30:46 +0100262#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
263
Damien Georged6b31e42016-01-07 14:29:12 +0000264int mp_obj_int_sign(mp_obj_t self_in) {
265 mp_int_t val = mp_obj_get_int(self_in);
266 if (val < 0) {
267 return -1;
268 } else if (val > 0) {
269 return 1;
270 } else {
271 return 0;
272 }
Dave Hylandsc4029e52014-04-07 11:19:51 -0700273}
Dave Hylandsc4029e52014-04-07 11:19:51 -0700274
Damien George6837d462015-03-14 22:07:30 +0000275// This must handle int and bool types, and must raise a
276// TypeError if the argument is not integral
277mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
278 mp_int_t val = mp_obj_get_int(self_in);
279 if (val < 0) {
280 val = -val;
281 }
282 return MP_OBJ_NEW_SMALL_INT(val);
283}
284
Damien George660aef62014-04-02 12:22:07 +0100285// This is called for operations on SMALL_INT that are not handled by mp_unary_op
Damien Georgeecc88e92014-08-30 00:35:11 +0100286mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
Damien George6ac5dce2014-05-21 19:42:43 +0100287 return MP_OBJ_NULL; // op not supported
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +0200288}
289
Damien George660aef62014-04-02 12:22:07 +0100290// This is called for operations on SMALL_INT that are not handled by mp_binary_op
Damien Georgeecc88e92014-08-30 00:35:11 +0100291mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien Georgee8208a72014-04-04 15:08:23 +0100292 return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200293}
294
295// This is called only with strings whose value doesn't fit in SMALL_INT
Damien George4abff752014-08-30 14:59:21 +0100296mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
Damien Georgeea13f402014-04-05 18:32:08 +0100297 nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build"));
Damien George23005372014-01-13 19:39:01 +0000298 return mp_const_none;
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200299}
300
Damien George9d68e9c2014-03-12 15:38:15 +0000301// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
302mp_obj_t mp_obj_new_int_from_ll(long long val) {
Damien Georgeea13f402014-04-05 18:32:08 +0100303 nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
Damien George9d68e9c2014-03-12 15:38:15 +0000304 return mp_const_none;
305}
306
Damien George95307432014-09-10 22:10:33 +0100307// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
308mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
309 nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
310 return mp_const_none;
311}
312
Damien George40f3c022014-07-03 13:25:24 +0100313mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200314 // SMALL_INT accepts only signed numbers, of one bit less size
315 // then word size, which totals 2 bits less for unsigned numbers.
316 if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
317 return MP_OBJ_NEW_SMALL_INT(value);
318 }
Damien Georgeea13f402014-04-05 18:32:08 +0100319 nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
Damien George23005372014-01-13 19:39:01 +0000320 return mp_const_none;
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200321}
322
Paul Sokolovskyf79cd6a2014-12-30 00:33:32 +0200323#if MICROPY_PY_BUILTINS_FLOAT
324mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
David Steinberg0fb17f62015-01-13 15:22:30 +0000325 int cl = fpclassify(val);
326 if (cl == FP_INFINITE) {
327 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
328 } else if (cl == FP_NAN) {
329 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
330 } else {
331 mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
332 if (icl == MP_FP_CLASS_FIT_SMALLINT) {
333 return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
334 } else {
335 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
336 }
337 }
Paul Sokolovskyf79cd6a2014-12-30 00:33:32 +0200338}
339#endif
340
Damien George40f3c022014-07-03 13:25:24 +0100341mp_obj_t mp_obj_new_int(mp_int_t value) {
Damien Georged1e355e2014-05-28 14:51:12 +0100342 if (MP_SMALL_INT_FITS(value)) {
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200343 return MP_OBJ_NEW_SMALL_INT(value);
344 }
Damien Georgeea13f402014-04-05 18:32:08 +0100345 nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
Damien George23005372014-01-13 19:39:01 +0000346 return mp_const_none;
Paul Sokolovsky48b35722014-01-12 17:30:48 +0200347}
Paul Sokolovskyd26b3792014-01-18 16:07:16 +0200348
Damien Georgebe6d8be2014-12-05 23:13:52 +0000349mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
Paul Sokolovskyd26b3792014-01-18 16:07:16 +0200350 return MP_OBJ_SMALL_INT_VALUE(self_in);
351}
352
Damien George40f3c022014-07-03 13:25:24 +0100353mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
Paul Sokolovskyd26b3792014-01-18 16:07:16 +0200354 return MP_OBJ_SMALL_INT_VALUE(self_in);
355}
356
Damien Georgefb510b32014-06-01 13:32:54 +0100357#if MICROPY_PY_BUILTINS_FLOAT
Damien Georgeeabdf672014-03-22 20:54:01 +0000358mp_float_t mp_obj_int_as_float(mp_obj_t self_in) {
359 return MP_OBJ_SMALL_INT_VALUE(self_in);
360}
361#endif
362
Damien George5fa93b62014-01-22 14:35:10 +0000363#endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
364
Damien Georgee8208a72014-04-04 15:08:23 +0100365// This dispatcher function is expected to be independent of the implementation of long int
366// It handles the extra cases for integer-like arithmetic
Damien Georgeecc88e92014-08-30 00:35:11 +0100367mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien Georgee8208a72014-04-04 15:08:23 +0100368 if (rhs_in == mp_const_false) {
369 // false acts as 0
370 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));
371 } else if (rhs_in == mp_const_true) {
372 // true acts as 0
373 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));
374 } else if (op == MP_BINARY_OP_MULTIPLY) {
Damien George9b7a8ee2014-08-13 13:22:24 +0100375 if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_bytes) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
Damien Georgee8208a72014-04-04 15:08:23 +0100376 // multiply is commutative for these types, so delegate to them
377 return mp_binary_op(op, rhs_in, lhs_in);
378 }
379 }
Damien George6ac5dce2014-05-21 19:42:43 +0100380 return MP_OBJ_NULL; // op not supported
Damien Georgee8208a72014-04-04 15:08:23 +0100381}
382
Damien George5213eb32014-04-13 12:24:13 +0100383// this is a classmethod
Damien George4b72b3a2016-01-03 14:21:40 +0000384STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
Paul Sokolovskya985b452014-04-09 00:40:58 +0300385 // TODO: Support long ints
Damien George5213eb32014-04-13 12:24:13 +0100386 // TODO: Support byteorder param (assumes 'little' at the moment)
387 // TODO: Support signed param (assumes signed=False at the moment)
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000388 (void)n_args;
Damien George5213eb32014-04-13 12:24:13 +0100389
390 // get the buffer info
Damien George57a4b4f2014-04-18 22:29:21 +0100391 mp_buffer_info_t bufinfo;
Damien Georgeb11b85a2014-04-18 22:59:24 +0100392 mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
Damien George5213eb32014-04-13 12:24:13 +0100393
394 // convert the bytes to an integer
Damien George40f3c022014-07-03 13:25:24 +0100395 mp_uint_t value = 0;
stijn01d6be42014-05-05 12:18:27 +0200396 for (const byte* buf = (const byte*)bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) {
Damien Georgeb9e7ed42014-04-13 12:40:50 +0100397 value = (value << 8) | *buf;
Damien George5213eb32014-04-13 12:24:13 +0100398 }
399
400 return mp_obj_new_int_from_uint(value);
Paul Sokolovskya985b452014-04-09 00:40:58 +0300401}
402
Damien George5213eb32014-04-13 12:24:13 +0100403STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_from_bytes);
Damien Georgecbf76742015-11-27 13:38:15 +0000404STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj));
Paul Sokolovskya985b452014-04-09 00:40:58 +0300405
Damien George4b72b3a2016-01-03 14:21:40 +0000406STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) {
Damien Georgefcdb2392014-10-06 13:45:34 +0000407 // TODO: Support byteorder param (assumes 'little')
408 // TODO: Support signed param (assumes signed=False)
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000409 (void)n_args;
Damien Georgefcdb2392014-10-06 13:45:34 +0000410
Damien George963a5a32015-01-16 17:47:07 +0000411 mp_uint_t len = MP_OBJ_SMALL_INT_VALUE(args[1]);
Damien Georgefcdb2392014-10-06 13:45:34 +0000412
Damien George05005f62015-01-21 22:48:37 +0000413 vstr_t vstr;
414 vstr_init_len(&vstr, len);
415 byte *data = (byte*)vstr.buf;
Paul Sokolovskya985b452014-04-09 00:40:58 +0300416 memset(data, 0, len);
Damien Georgefcdb2392014-10-06 13:45:34 +0000417
Damien George271d18e2015-04-25 23:16:39 +0100418 #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
419 if (!MP_OBJ_IS_SMALL_INT(args[0])) {
420 mp_obj_int_to_bytes_impl(args[0], false, len, data);
421 } else
422 #endif
423 {
424 mp_int_t val = MP_OBJ_SMALL_INT_VALUE(args[0]);
425 mp_binary_set_int(MIN((size_t)len, sizeof(val)), false, data, val);
Damien Georgefcdb2392014-10-06 13:45:34 +0000426 }
427
Damien George05005f62015-01-21 22:48:37 +0000428 return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
Paul Sokolovskya985b452014-04-09 00:40:58 +0300429}
Paul Sokolovskya985b452014-04-09 00:40:58 +0300430STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 2, 4, int_to_bytes);
431
Damien Georgecbf76742015-11-27 13:38:15 +0000432STATIC const mp_rom_map_elem_t int_locals_dict_table[] = {
433 { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },
434 { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },
Paul Sokolovskya985b452014-04-09 00:40:58 +0300435};
436
437STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);
438
Damien George3e1a5c12014-03-29 13:43:38 +0000439const mp_obj_type_t mp_type_int = {
Damien Georgec5966122014-02-15 16:10:44 +0000440 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000441 .name = MP_QSTR_int,
Damien Georgee8208a72014-04-04 15:08:23 +0100442 .print = mp_obj_int_print,
443 .make_new = mp_obj_int_make_new,
444 .unary_op = mp_obj_int_unary_op,
445 .binary_op = mp_obj_int_binary_op,
Damien George999cedb2015-11-27 17:01:44 +0000446 .locals_dict = (mp_obj_dict_t*)&int_locals_dict,
Damien George5fa93b62014-01-22 14:35:10 +0000447};