From 875c0c2d16fbcaa61bfc46da58533ab0890bf513 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 26 Feb 2016 22:34:14 -0800 Subject: Functions for converting between buffers and integers. These functions convert between positive integers, and fixed-size memory buffers representing pure binary numbers in big endian byte order. This functionality will be used in some upcoming networking code. * arith.c (num_from_buffer, num_to_buffer): New functions. * arith.h (num_from_buffer, num_to_buffer): Declared. * mpi/mpi.c (mp_to_unsigned_buf): New function. * mpi/mpi.h (mp_to_unsigned_buf): Declared. --- arith.c | 31 +++++++++++++++++++++++++++++++ arith.h | 2 ++ mpi/mpi.c | 26 ++++++++++++++++++++++++++ mpi/mpi.h | 1 + 4 files changed, 60 insertions(+) diff --git a/arith.c b/arith.c index 497aefa7..ecb3e03e 100644 --- a/arith.c +++ b/arith.c @@ -90,6 +90,37 @@ val bignum_from_uintptr(uint_ptr_t u) return n; } +val num_from_buffer(mem_t *buf, int bytes) +{ + val n = make_bignum(); + mp_read_unsigned_bin(mp(n), buf, bytes); + return normalize(n); +} + +int num_to_buffer(val num, mem_t *buf, int bytes) +{ + switch (type(num)) { + case CHR: case NUM: + { + cnum n = coerce(cnum, num) >> TAG_SHIFT; + mem_t *ptr = buf + bytes; + + for (; n != 0; n >>= 8) { + if (ptr == buf) + return 0; + *--ptr = n & 0xff; + } + while (ptr > buf) + *--ptr = 0; + } + return 1; + case BGNUM: + return mp_to_unsigned_buf(mp(num), buf, bytes) == MP_OKAY ? 1 : 0; + default: + type_mismatch(lit("~s is not an integer"), num, nao); + } +} + #if HAVE_DOUBLE_INTPTR_T static val bignum_dbl_ipt(double_intptr_t di) diff --git a/arith.h b/arith.h index 083a8a19..bc3a0568 100644 --- a/arith.h +++ b/arith.h @@ -28,6 +28,8 @@ val make_bignum(void); val bignum(cnum cn); val bignum_from_long(long l); val bignum_from_uintptr(uint_ptr_t u); +val num_from_buffer(mem_t *buf, int bytes); +int num_to_buffer(val num, mem_t *buf, int bytes); int highest_bit(int_ptr_t n); val normalize(val bignum); val in_int_ptr_range(val bignum); diff --git a/mpi/mpi.c b/mpi/mpi.c index c52e47bd..64cfb25a 100644 --- a/mpi/mpi.c +++ b/mpi/mpi.c @@ -3010,6 +3010,32 @@ mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str) /* }}} */ +mp_err mp_to_unsigned_buf(mp_int *mp, unsigned char *str, int size) +{ + mp_digit *dp, *end; + unsigned char *spos; + + ARGCHK(mp != NULL && str != NULL && size >= 0, MP_BADARG); + + for (spos = str + size, dp = DIGITS(mp), end = dp + USED(mp); dp < end; dp++) { + int ix; + mp_digit d = *dp; + + for (ix = 0; ix < (int) sizeof(mp_digit); ++ix) { + if (dp + 1 == end && d == 0) + break; + ARGCHK(spos >= str, MP_RANGE); + *--spos = d & 0xFF; + d >>= 8; + } + } + + while (spos > str) + *--spos = 0; + + return MP_OKAY; +} + /* {{{ mp_count_bits(mp) */ int mp_count_bits(mp_int *mp) diff --git a/mpi/mpi.h b/mpi/mpi.h index 0e000643..cd7e823d 100644 --- a/mpi/mpi.h +++ b/mpi/mpi.h @@ -217,6 +217,7 @@ mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str); mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len); int mp_unsigned_bin_size(mp_int *mp); mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str); +mp_err mp_to_unsigned_buf(mp_int *mp, unsigned char *str, int size); int mp_count_bits(mp_int *mp); int mp_is_pow_two(mp_int *mp); -- cgit v1.2.3