1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*****************************************************************/
6/* OutString.cpp */
7/*****************************************************************/
8/* A simple, lightweight, character output stream, with very few
9 external dependancies (like sprintf ... ) */
10
11/*
12 Date : 2/1/99 */
13/*****************************************************************/
14
15#include "stdafx.h"
16#include "outstring.h"
17
18
19/*****************************************************************/
20// print out 'count' instances of the character 'c'
21OutString& OutString::pad(size_t count, char c) {
22 if (cur+count > end)
23 Realloc(count);
24 memset(cur, c, count);
25 cur = cur + count;
26 return(*this);
27}
28
29/*****************************************************************/
30// prints out a decimal representation
31OutString& OutString::operator<<(double d) {
32
33 if (d == 0.0) {
34 *this << "0.0";
35 return *this;
36 }
37
38 if (d < 0) {
39 d = -d;
40 *this << '-';
41 }
42
43 // compute the exponent
44 int exponent = 0;
45 while (d > 10.0) {
46 d /= 10;
47 exponent++;
48 if (exponent > 500) { // avoids a possible infinite loop
49 *this << "INF";
50 return *this;
51 }
52 }
53 while (d < 1.0) {
54 d *= 10;
55 --exponent;
56 if (exponent < -500) { // avoids a possible infinite loop
57 *this << "0.0";
58 return *this;
59 }
60 }
61
62 // we now have a normalized d (between 1 and 10)
63 double delta = .5E-10;
64 d += delta; // round to the precision we are displaying
65
66 unsigned trailingZeros = 0;
67 for(unsigned i = 0; i < 10; i++) {
68 int digit = (int) d;
69 d = (d - digit) * 10; // ISSUE: does roundoff ever bite us here?
70
71 if (digit == 0) // defer printing traiing zeros
72 trailingZeros++;
73 else {
74 if (trailingZeros > 0) {
75 this->pad(trailingZeros, '0');
76 trailingZeros = 0;
77 }
78 *this << (char) ('0' + digit);
79 }
80 if (i == 0)
81 *this << '.';
82
83 }
84 if (exponent != 0) {
85 *this << 'E';
86 *this << exponent;
87 }
88 return(*this);
89}
90
91/*****************************************************************/
92// prints out a decimal representation
93OutString& OutString::dec(int i, size_t minWidth) {
94 char buff[12]; // big enough for any number (10 digits, - sign, null term)
95 char* ptr = &buff[11];
96 *ptr = 0;
97
98 unsigned val = i;
99 if (i < 0)
100 val = -i; // note this happens to also work for minint!
101
102 for(;;) {
103 if (val < 10) {
104 *--ptr = '0' + val;
105 break;
106 }
107 *--ptr = '0' + (val % 10);
108 val = val / 10;
109 }
110
111 if (i < 0)
112 *--ptr = '-';
113
114 size_t len = &buff[11] - ptr; // length of string
115 if (len < minWidth)
116 pad(minWidth-len, ' ');
117
118 *this << ptr;
119 return(*this);
120}
121
122/*****************************************************************/
123OutString& OutString::hex(unsigned __int64 i, int minWidth, unsigned flags) {
124
125 unsigned hi = unsigned(i >> 32);
126 unsigned low = unsigned(i);
127
128 if (hi != 0) {
129 minWidth -= 8;
130 hex(hi, minWidth, flags); // print upper bits
131 flags = zeroFill;
132 minWidth = 8;
133 }
134 return hex(low, minWidth, flags); // print lower bits
135}
136
137/*****************************************************************/
138OutString& OutString::hex(unsigned i, int minWidth, unsigned flags) {
139 char buff[12]; // big enough for any number
140 char* ptr = &buff[11];
141 *ptr = 0;
142
143 static const char digits[] = "0123456789ABCDEF";
144
145 for(;;) {
146 if (i < 16) {
147 *--ptr = digits[i];
148 break;
149 }
150 *--ptr = digits[(i % 16)];
151 i = i / 16;
152 }
153
154 size_t len = &buff[11] - ptr; // length of string
155 if (flags & put0x) {
156 if (flags & zeroFill)
157 *this << "0x";
158 else
159 *--ptr = 'x', *--ptr = '0';
160 len += 2;
161 }
162
163 if (len < (size_t)minWidth)
164 pad(minWidth-len, (flags & zeroFill) ? '0' : ' ');
165
166 *this << ptr;
167 return(*this);
168}
169
170/*****************************************************************/
171void OutString::Realloc(size_t neededSpace) {
172 size_t oldSize = cur-start;
173 size_t newSize = (oldSize + neededSpace) * 3 / 2 + 32;
174 char* oldBuff = start;
175 start = new char[newSize+1];
176 memcpy(start, oldBuff, oldSize);
177 cur = &start[oldSize];
178 end = &start[newSize];
179 delete [] oldBuff;
180}
181
182