1/* mpz_out_str(stream, base, integer) -- Output to STREAM the multi prec.
2   integer INTEGER in base BASE.
3
4Copyright 1991, 1993, 1994, 1996, 2001, 2005 Free Software Foundation, Inc.
5
6This file is part of the GNU MP Library.
7
8The GNU MP Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MP Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
20
21#include <stdio.h>
22#include "gmp.h"
23#include "gmp-impl.h"
24
25size_t
26mpz_out_str (FILE *stream, int base, mpz_srcptr x)
27{
28  mp_ptr xp;
29  mp_size_t x_size = x->_mp_size;
30  unsigned char *str;
31  size_t str_size;
32  size_t i;
33  size_t written;
34  char *num_to_text;
35  TMP_DECL;
36
37  if (stream == 0)
38    stream = stdout;
39
40  if (base >= 0)
41    {
42      num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
43      if (base == 0)
44	base = 10;
45      else if (base > 36)
46	{
47	  num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
48	  if (base > 62)
49	    return 0;
50	}
51    }
52  else
53    {
54      base = -base;
55      num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
56    }
57
58  if (x_size == 0)
59    {
60      fputc ('0', stream);
61      return ferror (stream) ? 0 : 1;
62    }
63
64  written = 0;
65
66  if (x_size < 0)
67    {
68      fputc ('-', stream);
69      x_size = -x_size;
70      written = 1;
71    }
72
73  TMP_MARK;
74  str_size = ((size_t) (x_size * GMP_LIMB_BITS
75			* mp_bases[base].chars_per_bit_exactly)) + 3;
76  str = (unsigned char *) TMP_ALLOC (str_size);
77
78  /* Move the number to convert into temporary space, since mpn_get_str
79     clobbers its argument + needs one extra high limb....  */
80  xp = TMP_ALLOC_LIMBS (x_size + 1);
81  MPN_COPY (xp, x->_mp_d, x_size);
82
83  str_size = mpn_get_str (str, base, xp, x_size);
84
85  /* mpn_get_str might make some leading zeros.  Skip them.  */
86  while (*str == 0)
87    {
88      str_size--;
89      str++;
90    }
91
92  /* Translate to printable chars.  */
93  for (i = 0; i < str_size; i++)
94    str[i] = num_to_text[str[i]];
95  str[str_size] = 0;
96
97  {
98    size_t fwret;
99    fwret = fwrite ((char *) str, 1, str_size, stream);
100    written += fwret;
101  }
102
103  TMP_FREE;
104  return ferror (stream) ? 0 : written;
105}
106