Bug Summary

File:dconv/dprint.cpp
Location:line 385, column 9
Description:Value stored to 'bufferSize' is never read

Annotated Source Code

1/******************************************************************************
2 Copyright (c) 2014 Ryan Juckett
3 http://www.ryanjuckett.com/
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20
21 3. This notice may not be removed or altered from any source
22 distribution.
23*******************************************************************************
24 Copyright (c) 2015-2017 Carsten Sonne Larsen <cs@innolan.dk>
25 All rights reserved.
26
27 Redistribution and use in source and binary forms, with or without
28 modification, are permitted provided that the following conditions
29 are met:
30 1. Redistributions of source code must retain the above copyright
31 notice, this list of conditions and the following disclaimer.
32
33 2. Redistributions in binary form must reproduce the above copyright
34 notice, this list of conditions and the following disclaimer in the
35 documentation and/or other materials provided with the distribution.
36
37 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
38 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
41 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
46 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 The origin source code can be obtained from:
49 http://www.ryanjuckett.com/
50
51******************************************************************************/
52
53#include "clib.h"
54#include "dmath.h"
55#include "dprint.h"
56#include "dragon4.h"
57#include <dstandard.h>
58
59#define memcpyMemCopy MemCopy
60#define memmoveMemCopy MemCopy
61
62//******************************************************************************
63// Helper union to decompose a 32-bit IEEE float.
64// sign: 1 bit
65// exponent: 8 bits
66// mantissa: 23 bits
67//******************************************************************************
68union tFloatUnion32
69{
70 tB IsNegative() const {
71 return (m_integer >> 31) != 0;
72 }
73 tU32 GetExponent() const {
74 return (m_integer >> 23) & 0xFF;
75 }
76 tU32 GetMantissa() const {
77 return m_integer & 0x7FFFFF;
78 }
79
80 tF32 m_floatingPoint;
81 tU32 m_integer;
82};
83
84//******************************************************************************
85// Helper union to decompose a 64-bit IEEE float.
86// sign: 1 bit
87// exponent: 11 bits
88// mantissa: 52 bits
89//******************************************************************************
90union tFloatUnion64
91{
92 tB IsNegative() const {
93 return (m_integer >> 63) != 0;
94 }
95 tU32 GetExponent() const {
96 return (m_integer >> 52) & 0x7FF;
97 }
98 tU64 GetMantissa() const {
99 return m_integer & 0xFFFFFFFFFFFFFull;
100 }
101
102 tF64 m_floatingPoint;
103 tU64 m_integer;
104};
105
106//******************************************************************************
107// Outputs the positive number with positional notation: ddddd.dddd
108// The output is always NUL terminated and the output length (not including the
109// NUL) is returned.
110//******************************************************************************
111tU32 FormatPositional
112(
113 tC8 * pOutBuffer, // buffer to output into
114 tU32 bufferSize, // maximum characters that can be printed to pOutBuffer
115 tU64 mantissa, // value significand
116 tS32 exponent, // value exponent in base 2
117 tU32 mantissaHighBitIdx, // index of the highest set mantissa bit
118 tB hasUnequalMargins, // is the high margin twice as large as the low margin
119 tS32 precision, // Negative prints as many digits as are needed for a unique
120 tC8 decimalPoint // Character before the decimals
121 // number. Positive specifies the maximum number of
122 // significant digits to print past the decimal point.
123)
124{
125 RJ_ASSERT(bufferSize > 0);
126
127 tS32 printExponent;
128 tU32 numPrintDigits;
129
130 tU32 maxPrintLen = bufferSize - 1;
131
132 if (precision < 0)
133 {
134 numPrintDigits = Dragon4( mantissa,
135 exponent,
136 mantissaHighBitIdx,
137 hasUnequalMargins,
138 CutoffMode_Unique,
139 0,
140 pOutBuffer,
141 maxPrintLen,
142 &printExponent );
143 }
144 else
145 {
146 numPrintDigits = Dragon4( mantissa,
147 exponent,
148 mantissaHighBitIdx,
149 hasUnequalMargins,
150 CutoffMode_FractionLength,
151 precision,
152 pOutBuffer,
153 maxPrintLen,
154 &printExponent );
155 }
156
157 RJ_ASSERT( numPrintDigits > 0 );
158 RJ_ASSERT( numPrintDigits <= bufferSize );
159
160 // track the number of digits past the decimal point that have been printed
161 tU32 numFractionDigits = 0;
162
163 // if output has a whole number
164 if (printExponent >= 0)
165 {
166 // leave the whole number at the start of the buffer
167 tU32 numWholeDigits = printExponent+1;
168 if (numPrintDigits < numWholeDigits)
169 {
170 // don't overflow the buffer
171 if (numWholeDigits > maxPrintLen)
172 numWholeDigits = maxPrintLen;
173
174 // add trailing zeros up to the decimal point
175 for ( ; numPrintDigits < numWholeDigits; ++numPrintDigits )
176 pOutBuffer[numPrintDigits] = '0';
177 }
178 // insert the decimal point prior to the fraction
179 else if (numPrintDigits > (tU32)numWholeDigits)
180 {
181 numFractionDigits = numPrintDigits - numWholeDigits;
182 tU32 maxFractionDigits = maxPrintLen - numWholeDigits - 1;
183 if (numFractionDigits > maxFractionDigits)
184 numFractionDigits = maxFractionDigits;
185
186 memmoveMemCopy(pOutBuffer + numWholeDigits + 1, pOutBuffer + numWholeDigits, numFractionDigits);
187 pOutBuffer[numWholeDigits] = decimalPoint;
188 numPrintDigits = numWholeDigits + 1 + numFractionDigits;
189 }
190 }
191 else
192 {
193 // shift out the fraction to make room for the leading zeros
194 if (maxPrintLen > 2)
195 {
196 tU32 numFractionZeros = (tU32)-printExponent - 1;
197 tU32 maxFractionZeros = maxPrintLen - 2;
198 if (numFractionZeros > maxFractionZeros)
199 numFractionZeros = maxFractionZeros;
200
201 tU32 digitsStartIdx = 2 + numFractionZeros;
202
203 // shift the significant digits right such that there is room for leading zeros
204 numFractionDigits = numPrintDigits;
205 tU32 maxFractionDigits = maxPrintLen - digitsStartIdx;
206 if (numFractionDigits > maxFractionDigits)
207 numFractionDigits = maxFractionDigits;
208
209 memmoveMemCopy(pOutBuffer + digitsStartIdx, pOutBuffer, numFractionDigits);
210
211 // insert the leading zeros
212 for (tU32 i = 2; i < digitsStartIdx; ++i)
213 pOutBuffer[i] = '0';
214
215 // update the counts
216 numFractionDigits += numFractionZeros;
217 numPrintDigits = numFractionDigits;
218 }
219
220 // add the decimal point
221 if (maxPrintLen > 1)
222 {
223 pOutBuffer[1] = decimalPoint;
224 numPrintDigits += 1;
225 }
226
227 // add the initial zero
228 if (maxPrintLen > 0)
229 {
230 pOutBuffer[0] = '0';
231 numPrintDigits += 1;
232 }
233 }
234
235 // add trailing zeros up to precision length
236 if (precision > (tS32)numFractionDigits && numPrintDigits < maxPrintLen)
237 {
238 // add a decimal point if this is the first fractional digit we are printing
239 if (numFractionDigits == 0)
240 {
241 pOutBuffer[numPrintDigits++] = decimalPoint;
242 }
243
244 // compute the number of trailing zeros needed
245 tU32 totalDigits = numPrintDigits + (precision - numFractionDigits);
246 if (totalDigits > maxPrintLen)
247 totalDigits = maxPrintLen;
248
249 for ( ; numPrintDigits < totalDigits; ++numPrintDigits )
250 pOutBuffer[numPrintDigits] = '0';
251 }
252
253 // terminate the buffer
254 RJ_ASSERT( numPrintDigits <= maxPrintLen );
255 pOutBuffer[numPrintDigits] = '\0';
256
257 return numPrintDigits;
258}
259
260//******************************************************************************
261// Outputs the positive number with scientific notation: d.dddde[sign]ddd
262// The output is always NUL terminated and the output length (not including the
263// NUL) is returned.
264//******************************************************************************
265tU32 FormatScientific
266(
267 tC8 * pOutBuffer, // buffer to output into
268 tU32 bufferSize, // maximum characters that can be printed to pOutBuffer
269 tU64 mantissa, // value significand
270 tS32 exponent, // value exponent in base 2
271 tU32 mantissaHighBitIdx, // index of the highest set mantissa bit
272 tB hasUnequalMargins, // is the high margin twice as large as the low margin
273 tS32 precision, // Negative prints as many digits as are needed for a unique
274 tC8 decimalPoint // Character before the decimals
275 // number. Positive specifies the maximum number of
276 // significant digits to print past the decimal point.
277)
278{
279 RJ_ASSERT(bufferSize > 0);
280
281 tS32 printExponent;
282 tU32 numPrintDigits;
283
284 if (precision < 0)
285 {
286 numPrintDigits = Dragon4( mantissa,
287 exponent,
288 mantissaHighBitIdx,
289 hasUnequalMargins,
290 CutoffMode_Unique,
291 0,
292 pOutBuffer,
293 bufferSize,
294 &printExponent );
295 }
296 else
297 {
298 numPrintDigits = Dragon4( mantissa,
299 exponent,
300 mantissaHighBitIdx,
301 hasUnequalMargins,
302 CutoffMode_TotalLength,
303 precision + 1,
304 pOutBuffer,
305 bufferSize,
306 &printExponent );
307 }
308
309 RJ_ASSERT( numPrintDigits > 0 );
310 RJ_ASSERT( numPrintDigits <= bufferSize );
311
312 tC8 * pCurOut = pOutBuffer;
313
314 // keep the whole number as the first digit
315 if (bufferSize > 1)
316 {
317 pCurOut += 1;
318 bufferSize -= 1;
319 }
320
321 // insert the decimal point prior to the fractional number
322 tU32 numFractionDigits = numPrintDigits-1;
323 if (numFractionDigits > 0 && bufferSize > 1)
324 {
325 tU32 maxFractionDigits = bufferSize-2;
326 if (numFractionDigits > maxFractionDigits)
327 numFractionDigits = maxFractionDigits;
328
329 memmoveMemCopy(pCurOut + 1, pCurOut, numFractionDigits);
330 pCurOut[0] = decimalPoint;
331 pCurOut += (1 + numFractionDigits);
332 bufferSize -= (1 + numFractionDigits);
333 }
334
335 // add trailing zeros up to precision length
336 if (precision > (tS32)numFractionDigits && bufferSize > 1)
337 {
338 // add a decimal point if this is the first fractional digit we are printing
339 if (numFractionDigits == 0)
340 {
341 *pCurOut = decimalPoint;
342 ++pCurOut;
343 --bufferSize;
344 }
345
346 // compute the number of trailing zeros needed
347 tU32 numZeros = (precision - numFractionDigits);
348 if (numZeros > bufferSize-1)
349 numZeros = bufferSize-1;
350
351 for (tC8 * pEnd = pCurOut + numZeros; pCurOut < pEnd; ++pCurOut )
352 *pCurOut = '0';
353 }
354
355 // print the exponent into a local buffer and copy into output buffer
356 if (bufferSize > 1)
357 {
358 tC8 exponentBuffer[5];
359 exponentBuffer[0] = 'e';
360 if (printExponent >= 0)
361 {
362 exponentBuffer[1] = '+';
363 }
364 else
365 {
366 exponentBuffer[1] = '-';
367 printExponent = -printExponent;
368 }
369
370 RJ_ASSERT(printExponent < 1000);
371 tU32 hundredsPlace = printExponent / 100;
372 tU32 tensPlace = (printExponent - hundredsPlace*100) / 10;
373 tU32 onesPlace = (printExponent - hundredsPlace*100 - tensPlace*10);
374
375 exponentBuffer[2] = (tC8)('0' + hundredsPlace);
376 exponentBuffer[3] = (tC8)('0' + tensPlace);
377 exponentBuffer[4] = (tC8)('0' + onesPlace);
378
379 // copy the exponent buffer into the output
380 tU32 maxExponentSize = bufferSize-1;
381 tU32 exponentSize = (5 < maxExponentSize) ? 5 : maxExponentSize;
382 memcpyMemCopy( pCurOut, exponentBuffer, exponentSize );
383
384 pCurOut += exponentSize;
385 bufferSize -= exponentSize;
Value stored to 'bufferSize' is never read
386 }
387
388 RJ_ASSERT( bufferSize > 0 );
389 pCurOut[0] = '\0';
390
391 return pCurOut - pOutBuffer;
392}
393
394//******************************************************************************
395// Print a hexadecimal value with a given width.
396// The output string is always NUL terminated and the string length (not
397// including the NUL) is returned.
398//******************************************************************************
399static tU32 PrintHex(tC8 * pOutBuffer, tU32 bufferSize, tU64 value, tU32 width)
400{
401 const tC8 digits[] = "0123456789abcdef";
402
403 RJ_ASSERT(bufferSize > 0);
404
405 tU32 maxPrintLen = bufferSize-1;
406 if (width > maxPrintLen)
407 width = maxPrintLen;
408
409 tC8 * pCurOut = pOutBuffer;
410 while (width > 0)
411 {
412 --width;
413
414 tU8 digit = (tU8)((value >> 4ull*(tU64)width) & 0xF);
415 *pCurOut = digits[digit];
416
417 ++pCurOut;
418 }
419
420 *pCurOut = '\0';
421 return pCurOut - pOutBuffer;
422}
423
424//******************************************************************************
425// Print special case values for infinities and NaNs.
426// The output string is always NUL terminated and the string length (not
427// including the NUL) is returned.
428//******************************************************************************
429static tU32 PrintInfNan(tC8 * pOutBuffer, tU32 bufferSize, tU64 mantissa, tU32 mantissaHexWidth)
430{
431 RJ_ASSERT(bufferSize > 0);
432
433 tU32 maxPrintLen = bufferSize-1;
434
435 // Check for infinity
436 if (mantissa == 0)
437 {
438 // copy and make sure the buffer is terminated
439 tU32 printLen = (3 < maxPrintLen) ? 3 : maxPrintLen;
440 ::memcpyMemCopy( pOutBuffer, "Inf", printLen );
441 pOutBuffer[printLen] = '\0';
442 return printLen;
443 }
444 else
445 {
446 // copy and make sure the buffer is terminated
447 tU32 printLen = (3 < maxPrintLen) ? 3 : maxPrintLen;
448 ::memcpyMemCopy( pOutBuffer, "NaN", printLen );
449 pOutBuffer[printLen] = '\0';
450
451 // append HEX value
452 if (maxPrintLen > 3)
453 printLen += PrintHex(pOutBuffer+3, bufferSize-3, mantissa, mantissaHexWidth);
454
455 return printLen;
456 }
457}
458
459//******************************************************************************
460// Print a 32-bit floating-point number as a decimal string.
461// The output string is always NUL terminated and the string length (not
462// including the NUL) is returned.
463//******************************************************************************
464tU32 PrintFloat32
465(
466 tC8 * pOutBuffer, // buffer to output into
467 tU32 bufferSize, // size of pOutBuffer
468 tF32 value, // value to print
469 tPrintFloatFormat format, // format to print with
470 tS32 precision, // If negative, the minimum number of digits to represent a
471 tC8 decimalPoint // Character before the decimals
472 // unique 32-bit floating point value is output. Otherwise,
473 // this is the number of digits to print past the decimal point.
474)
475{
476 if (bufferSize == 0)
477 return 0;
478
479 if (bufferSize == 1)
480 {
481 pOutBuffer[0] = '\0';
482 return 1;
483 }
484
485 // deconstruct the floating point value
486 tFloatUnion32 floatUnion;
487 floatUnion.m_floatingPoint = value;
488 tU32 floatExponent = floatUnion.GetExponent();
489 tU32 floatMantissa = floatUnion.GetMantissa();
490
491 // output the sign
492 if (floatUnion.IsNegative())
493 {
494 pOutBuffer[0] = '-';
495 ++pOutBuffer;
496 --bufferSize;
497 RJ_ASSERT(bufferSize > 0);
498 }
499
500 // if this is a special value
501 if (floatExponent == 0xFF)
502 {
503 return PrintInfNan(pOutBuffer, bufferSize, floatMantissa, 6);
504 }
505 // else this is a number
506 else
507 {
508 // factor the value into its parts
509 tU32 mantissa;
510 tS32 exponent;
511 tU32 mantissaHighBitIdx;
512 tB hasUnequalMargins;
513 if (floatExponent != 0)
514 {
515 // normalized
516 // The floating point equation is:
517 // value = (1 + mantissa/2^23) * 2 ^ (exponent-127)
518 // We convert the integer equation by factoring a 2^23 out of the exponent
519 // value = (1 + mantissa/2^23) * 2^23 * 2 ^ (exponent-127-23)
520 // value = (2^23 + mantissa) * 2 ^ (exponent-127-23)
521 // Because of the implied 1 in front of the mantissa we have 24 bits of precision.
522 // m = (2^23 + mantissa)
523 // e = (exponent-127-23)
524 mantissa = (1UL << 23) | floatMantissa;
525 exponent = floatExponent - 127 - 23;
526 mantissaHighBitIdx = 23;
527 hasUnequalMargins = (floatExponent != 1) && (floatMantissa == 0);
528 }
529 else
530 {
531 // denormalized
532 // The floating point equation is:
533 // value = (mantissa/2^23) * 2 ^ (1-127)
534 // We convert the integer equation by factoring a 2^23 out of the exponent
535 // value = (mantissa/2^23) * 2^23 * 2 ^ (1-127-23)
536 // value = mantissa * 2 ^ (1-127-23)
537 // We have up to 23 bits of precision.
538 // m = (mantissa)
539 // e = (1-127-23)
540 mantissa = floatMantissa;
541 exponent = 1 - 127 - 23;
542 mantissaHighBitIdx = LogBase2(mantissa);
543 hasUnequalMargins = false;
544 }
545
546 // format the value
547 switch (format)
548 {
549 case PrintFloatFormat_Positional:
550 return FormatPositional( pOutBuffer,
551 bufferSize,
552 mantissa,
553 exponent,
554 mantissaHighBitIdx,
555 hasUnequalMargins,
556 precision,
557 decimalPoint );
558
559 case PrintFloatFormat_Scientific:
560 return FormatScientific( pOutBuffer,
561 bufferSize,
562 mantissa,
563 exponent,
564 mantissaHighBitIdx,
565 hasUnequalMargins,
566 precision,
567 decimalPoint );
568
569 default:
570 pOutBuffer[0] = '\0';
571 return 0;
572 }
573 }
574}
575
576//******************************************************************************
577// Print a 64-bit floating-point number as a decimal string.
578// The output string is always NUL terminated and the string length (not
579// including the NUL) is returned.
580//******************************************************************************
581tU32 PrintFloat64
582(
583 tC8 * pOutBuffer, // buffer to output into
584 tU32 bufferSize, // size of pOutBuffer
585 tF64 value, // value to print
586 tPrintFloatFormat format, // format to print with
587 tS32 precision, // If negative, the minimum number of digits to represent a
588 tC8 decimalPoint // Character before the decimals
589 // unique 64-bit floating point value is output. Otherwise,
590 // this is the number of digits to print past the decimal point.
591)
592{
593 if (bufferSize == 0)
594 return 0;
595
596 if (bufferSize == 1)
597 {
598 pOutBuffer[0] = '\0';
599 return 1;
600 }
601
602 // deconstruct the floating point value
603 tFloatUnion64 floatUnion;
604 floatUnion.m_floatingPoint = value;
605 tU32 floatExponent = floatUnion.GetExponent();
606 tU64 floatMantissa = floatUnion.GetMantissa();
607
608 // output the sign
609 if (floatUnion.IsNegative())
610 {
611 pOutBuffer[0] = '-';
612 ++pOutBuffer;
613 --bufferSize;
614 RJ_ASSERT(bufferSize > 0);
615 }
616
617 // if this is a special value
618 if (floatExponent == 0x7FF)
619 {
620 return PrintInfNan(pOutBuffer, bufferSize, floatMantissa, 13);
621 }
622 // else this is a number
623 else
624 {
625 // factor the value into its parts
626 tU64 mantissa;
627 tS32 exponent;
628 tU32 mantissaHighBitIdx;
629 tB hasUnequalMargins;
630
631 if (floatExponent != 0)
632 {
633 // normal
634 // The floating point equation is:
635 // value = (1 + mantissa/2^52) * 2 ^ (exponent-1023)
636 // We convert the integer equation by factoring a 2^52 out of the exponent
637 // value = (1 + mantissa/2^52) * 2^52 * 2 ^ (exponent-1023-52)
638 // value = (2^52 + mantissa) * 2 ^ (exponent-1023-52)
639 // Because of the implied 1 in front of the mantissa we have 53 bits of precision.
640 // m = (2^52 + mantissa)
641 // e = (exponent-1023+1-53)
642 mantissa = (1ull << 52) | floatMantissa;
643 exponent = floatExponent - 1023 - 52;
644 mantissaHighBitIdx = 52;
645 hasUnequalMargins = (floatExponent != 1) && (floatMantissa == 0);
646 }
647 else
648 {
649 // subnormal
650 // The floating point equation is:
651 // value = (mantissa/2^52) * 2 ^ (1-1023)
652 // We convert the integer equation by factoring a 2^52 out of the exponent
653 // value = (mantissa/2^52) * 2^52 * 2 ^ (1-1023-52)
654 // value = mantissa * 2 ^ (1-1023-52)
655 // We have up to 52 bits of precision.
656 // m = (mantissa)
657 // e = (1-1023-52)
658 mantissa = floatMantissa;
659 exponent = 1 - 1023 - 52;
660 mantissaHighBitIdx = LogBase2(mantissa);
661 hasUnequalMargins = false;
662 }
663
664 // format the value
665 switch (format)
666 {
667 case PrintFloatFormat_Positional:
668 return FormatPositional( pOutBuffer,
669 bufferSize,
670 mantissa,
671 exponent,
672 mantissaHighBitIdx,
673 hasUnequalMargins,
674 precision,
675 decimalPoint );
676
677 case PrintFloatFormat_Scientific:
678 return FormatScientific( pOutBuffer,
679 bufferSize,
680 mantissa,
681 exponent,
682 mantissaHighBitIdx,
683 hasUnequalMargins,
684 precision,
685 decimalPoint );
686
687 default:
688 pOutBuffer[0] = '\0';
689 return 0;
690 }
691 }
692}