Merge from vendor branch HEIMDAL:
[dragonfly.git] / contrib / libio / stream.cc
1 /* 
2 Copyright (C) 1993 Free Software Foundation
3
4 This file is part of the GNU IO Library.  This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING.  If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
24
25 #include <stdarg.h>
26 #include <string.h>
27 #include "libioP.h"
28 #include "stream.h"
29 #include "strstream.h"
30
31 static char Buffer[_IO_BUFSIZ];
32 #define EndBuffer (Buffer+_IO_BUFSIZ)
33 static char* next_chunk = Buffer; // Start of available part of Buffer.
34
35 char* form(const char* format, ...)
36 {
37     int space_left = EndBuffer - next_chunk;
38     // If less that 25% of the space is available start over.
39     if (space_left < (_IO_BUFSIZ>>2))
40         next_chunk = Buffer;
41     char* buf = next_chunk;
42
43     strstreambuf stream(buf, EndBuffer-buf-1, buf);
44     va_list ap;
45     va_start(ap, format);
46     int count = stream.vform(format, ap);
47     va_end(ap);
48     stream.sputc(0);
49     next_chunk = buf + stream.pcount();
50     return buf;
51 }
52
53 #define u_long unsigned long
54
55 static char* itoa(unsigned long i, int size, int neg, int base)
56 {
57     // Conservative estimate: If base==2, might need 8 characters
58     // for each input byte, but normally 3 is plenty.
59     int needed = size ? size
60         : (base >= 8 ? 3 : 8) * sizeof(unsigned long) + 2;
61     int space_left = EndBuffer - next_chunk;
62     if (space_left <= needed)
63         next_chunk = Buffer; // start over.
64
65     char* buf = next_chunk;
66
67     register char* ptr = buf+needed+1;
68     next_chunk = ptr;
69
70     if (needed < (2+neg) || ptr > EndBuffer)
71         return NULL;
72     *--ptr = 0;
73     
74     if (i == 0)
75         *--ptr = '0';
76     while (i != 0 && ptr > buf) {
77         int ch = i % base;
78         i = i / base;
79         if (ch >= 10)
80             ch += 'a' - 10;
81         else
82             ch += '0';
83         *--ptr = ch;
84     }
85     if (neg)
86         *--ptr = '-';
87     if (size == 0)
88         return ptr;
89     while (ptr > buf)
90         *--ptr = ' ';
91     return buf;
92 }
93
94 char* dec(long i, int len /* = 0 */)
95 {
96     if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
97     else return itoa((unsigned long)(-i), len, 1, 10);
98 }
99 char* dec(int i, int len /* = 0 */)
100 {
101     if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
102     else return itoa((unsigned long)(-i), len, 1, 10);
103 }
104 char* dec(unsigned long i, int len /* = 0 */)
105 {
106     return itoa(i, len, 0, 10);
107 }
108 char* dec(unsigned int i, int len /* = 0 */)
109 {
110     return itoa(i, len, 0, 10);
111 }
112
113 char* hex(long i, int len /* = 0 */)
114 {
115     return itoa((unsigned long)i, len, 0, 16);
116 }
117 char* hex(int i, int len /* = 0 */)
118 {
119     return itoa((unsigned long)i, len, 0, 16);
120 }
121 char* hex(unsigned long i, int len /* = 0 */)
122 {
123     return itoa(i, len, 0, 16);
124 }
125 char* hex(unsigned int i, int len /* = 0 */)
126 {
127     return itoa(i, len, 0, 16);
128 }
129
130 char* oct(long i, int len /* = 0 */)
131 {
132     return itoa((unsigned long)i, len, 0, 8);
133 }
134 char* oct(int i, int len /* = 0 */)
135 {
136     return itoa((unsigned long)i, len, 0, 8);
137 }
138 char* oct(unsigned long i, int len /* = 0 */)
139 {
140     return itoa(i, len, 0, 8);
141 }
142 char* oct(unsigned int i, int len /* = 0 */)
143 {
144     return itoa(i, len, 0, 8);
145 }
146
147 static char *str(const char* s, int len, int width)
148 {
149   if (width < len)
150     width = len;
151   int space_left = EndBuffer - next_chunk;
152   if (space_left <= width + 1)
153     next_chunk = Buffer; // start over.
154   char* buf = next_chunk;
155   memset (buf, ' ', width - len);
156   memcpy (buf + width - len, s, len);
157   buf[width] = 0;
158   return buf;
159 }
160
161 char* str(const char* s, int width)
162 {
163   return str (s, strlen (s), width);
164 }
165
166 char* chr(char ch, int width)
167 {
168   char c = ch;
169   return str (&c, 1, width);
170 }