version 1.1.1.2, 2000/09/09 14:12:52 |
version 1.1.1.3, 2003/08/25 16:06:33 |
|
|
result. If STRING is not NULL, the caller must ensure enough space is |
result. If STRING is not NULL, the caller must ensure enough space is |
available to store the result. |
available to store the result. |
|
|
Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. |
Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2002 Free Software Foundation, |
|
Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
|
|
Line 23 along with the GNU MP Library; see the file COPYING.LI |
|
Line 24 along with the GNU MP Library; see the file COPYING.LI |
|
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
MA 02111-1307, USA. */ |
MA 02111-1307, USA. */ |
|
|
|
#include <string.h> /* for strlen */ |
#include "gmp.h" |
#include "gmp.h" |
#include "gmp-impl.h" |
#include "gmp-impl.h" |
|
#include "longlong.h" |
|
|
char * |
char * |
#if __STDC__ |
|
mpz_get_str (char *res_str, int base, mpz_srcptr x) |
mpz_get_str (char *res_str, int base, mpz_srcptr x) |
#else |
|
mpz_get_str (res_str, base, x) |
|
char *res_str; |
|
int base; |
|
mpz_srcptr x; |
|
#endif |
|
{ |
{ |
mp_ptr xp; |
mp_ptr xp; |
mp_size_t x_size = x->_mp_size; |
mp_size_t x_size = x->_mp_size; |
unsigned char *str; |
char *str; |
char *return_str; |
char *return_str; |
size_t str_size; |
size_t str_size; |
|
size_t alloc_size = 0; |
char *num_to_text; |
char *num_to_text; |
int i; |
int i; |
TMP_DECL (marker); |
TMP_DECL (marker); |
|
|
TMP_MARK (marker); |
|
if (base >= 0) |
if (base >= 0) |
{ |
{ |
if (base == 0) |
if (base == 0) |
Line 58 mpz_get_str (res_str, base, x) |
|
Line 54 mpz_get_str (res_str, base, x) |
|
num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
} |
} |
|
|
/* We allways allocate space for the string. If the caller passed a |
/* allocate string for the user if necessary */ |
NULL pointer for RES_STR, we allocate permanent space and return |
if (res_str == NULL) |
a pointer to that to the caller. */ |
|
str_size = ((size_t) (ABS (x_size) * BITS_PER_MP_LIMB |
|
* __mp_bases[base].chars_per_bit_exactly)) + 3; |
|
if (res_str == 0) |
|
{ |
{ |
/* We didn't get a string from the user. Allocate one (and return |
/* digits, null terminator, possible minus sign */ |
a pointer to it). */ |
MPN_SIZEINBASE (alloc_size, PTR(x), ABS(x_size), base); |
res_str = (char *) (*_mp_allocate_func) (str_size); |
alloc_size += 1 + (x_size<0); |
/* Make str, the variable used for raw result from mpn_get_str, |
res_str = (char *) (*__gmp_allocate_func) (alloc_size); |
point to the same string, but just after a possible minus sign. */ |
|
str = (unsigned char *) res_str + 1; |
|
} |
} |
else |
|
{ |
|
/* Use TMP_ALLOC to get temporary space, since we need a few extra bytes |
|
that we can't expect to caller to supply us with. */ |
|
str = (unsigned char *) TMP_ALLOC (str_size); |
|
} |
|
|
|
return_str = res_str; |
return_str = res_str; |
|
|
if (x_size == 0) |
|
{ |
|
res_str[0] = '0'; |
|
res_str[1] = 0; |
|
TMP_FREE (marker); |
|
return res_str; |
|
} |
|
if (x_size < 0) |
if (x_size < 0) |
{ |
{ |
*res_str++ = '-'; |
*res_str++ = '-'; |
x_size = -x_size; |
x_size = -x_size; |
} |
} |
|
|
/* Move the number to convert into temporary space, since mpn_get_str |
/* mpn_get_str clobbers its input on non power-of-2 bases */ |
clobbers its argument + needs one extra high limb.... */ |
TMP_MARK (marker); |
xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB); |
xp = x->_mp_d; |
MPN_COPY (xp, x->_mp_d, x_size); |
if (! POW2_P (base)) |
|
{ |
|
xp = TMP_ALLOC_LIMBS (x_size + 1); /* +1 in case x_size==0 */ |
|
MPN_COPY (xp, x->_mp_d, x_size); |
|
} |
|
|
str_size = mpn_get_str (str, base, xp, x_size); |
str_size = mpn_get_str ((unsigned char *) res_str, base, xp, x_size); |
|
ASSERT (alloc_size == 0 || str_size <= alloc_size - (SIZ(x) < 0)); |
|
|
/* mpn_get_str might make some leading zeros. Skip them. */ |
/* might have a leading zero, skip it */ |
while (*str == 0) |
str = res_str; |
|
if (*res_str == 0 && str_size != 1) |
{ |
{ |
str_size--; |
str_size--; |
str++; |
str++; |
|
ASSERT (*str != 0); /* at most one leading zero */ |
} |
} |
|
|
/* Translate result to printable chars and move result to RES_STR. */ |
/* Convert result to printable chars, and move down if there was a leading |
|
zero. */ |
for (i = 0; i < str_size; i++) |
for (i = 0; i < str_size; i++) |
res_str[i] = num_to_text[str[i]]; |
res_str[i] = num_to_text[str[i]]; |
res_str[str_size] = 0; |
res_str[str_size] = 0; |
|
|
TMP_FREE (marker); |
TMP_FREE (marker); |
|
|
|
/* if allocated then resize down to the actual space required */ |
|
if (alloc_size != 0) |
|
{ |
|
size_t actual_size = str_size + 1 + (res_str - return_str); |
|
ASSERT (actual_size == strlen (return_str) + 1); |
|
__GMP_REALLOCATE_FUNC_MAYBE_TYPE (return_str, alloc_size, actual_size, |
|
char); |
|
} |
return return_str; |
return return_str; |
} |
} |