summaryrefslogtreecommitdiffstats
path: root/src/lib/sprintf.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/sprintf.C')
-rw-r--r--src/lib/sprintf.C194
1 files changed, 174 insertions, 20 deletions
diff --git a/src/lib/sprintf.C b/src/lib/sprintf.C
index 2cac40421..a8f941448 100644
--- a/src/lib/sprintf.C
+++ b/src/lib/sprintf.C
@@ -30,6 +30,9 @@
namespace Util
{
+// Create a map, to map a numeric value to its character equivalence
+static const char* digits = "0123456789abcdef";
+
struct format_options
{
enum
@@ -181,6 +184,10 @@ void parse_format_options(format_options& opt, const char*& fmt)
++fmt;
break;
+ // Although this modifier can be added to a double, "%lf", it is
+ // ignored. The double to string is a very simple implementation,
+ // not meant to be a full blown implementation, but adding the 'l'
+ // will not cause any harm.
case 'l':
if ((opt.length == opt.LEN_LONG) ||
(opt.length == opt.LEN_LONGLONG))
@@ -256,6 +263,10 @@ void parse_format_options(format_options& opt, const char*& fmt)
opt.type = opt.TYPE_PTR;
break;
+ // Considering that the current implementation of doubles is not being
+ // displayed in hexadecimal, there is no need for 'F' in the output
+ // display. Difference between 'f' and 'F' is that F is uppercase and
+ // only useful when displaying hex values.
case 'f':
opt.type = opt.TYPE_DOUBLE;
break;
@@ -302,6 +313,40 @@ size_t display_post_header(ConsoleBufferInterface& func,
return count;
}
+/* @brief Converts a number into it's ASCII string representation
+ *
+ * @param[out] o_stringOutput - The recipient of the converted number to ASCII
+ * @param[in/out] io_stringOutputIndex - The index into buffer o_stringOutput
+ * @pre The io_stringOutputIndex is an index to where the first character
+ * will be placed
+ * @post The io_stringOutputIndex is one index location after the last
+ * placed character
+ * @param[in] i_number - The number to convert to a string.
+ * @param[in] i_base - The base of the number; 10, 8, etc
+ *
+ * @pre i_base must not be 0. Catastrophic results if so
+ */
+void convert_number_to_ascii(char o_stringOutput[],
+ size_t & io_stringOutputIndex,
+ uint64_t i_number,
+ const uint64_t i_base)
+{
+ if (0 == i_number)
+ {
+ // If no number then use zero
+ o_stringOutput[io_stringOutputIndex++] = digits[0];
+ }
+ else
+ {
+ // Convert number to ASCII.
+ while(i_number)
+ {
+ o_stringOutput[io_stringOutputIndex++] = digits[i_number % i_base];
+ i_number /= i_base;
+ }
+ }
+}
+
size_t display_string(ConsoleBufferInterface& func,
const format_options& f, const char* string)
{
@@ -319,20 +364,9 @@ size_t display_string(ConsoleBufferInterface& func,
return count;
}
-size_t display_double(ConsoleBufferInterface& func,
- const format_options& f, double number)
-{
- // TODO: CQ SW464805 Put in an implementation for double
-
- size_t count(0);
-
- return count;
-}
-
size_t display_number(ConsoleBufferInterface& func,
const format_options& f, uint64_t number)
{
- static const char* digits = "0123456789abcdef";
size_t count = 0;
char output[64];
@@ -414,15 +448,7 @@ size_t display_number(ConsoleBufferInterface& func,
}
// Convert number to ascii.
- while(number)
- {
- output[len++] = digits[number % base];
- number /= base;
- }
- if (len == 0)
- {
- output[len++] = digits[0];
- }
+ convert_number_to_ascii(output, len, number, base);
// Fix up zero pad.
while(len < f.precision)
@@ -476,6 +502,134 @@ size_t display_number(ConsoleBufferInterface& func,
return count;
}
+/* @brief This is just a rudimentary double to string routine.
+ *
+ * @details This routine takes in a value of type double, converts it
+ * two a string, and writes it to the provided ConsoleBufferInterface.
+ *
+ * @note This is a very simple double to string implementation that will
+ * display the double in a format of NNNN.NNNN in base 10, positive
+ * number only. It is advised to only use a double of the simplest
+ * form: NNNN.NNN. Some complicated forms of a double do not convert
+ * well, example 1.2345e-4 converts to 0.958747220502779 (incorrect),
+ * while 1.2345e+4 converts to 12345.0 (correct). Also working with
+ * doubles can produce imprecise results, example 12334.1469 produces
+ * 12334.146899999999 (technically correct), while 3.14159 produces
+ * 3.14158 (also technically correct).
+ * Also some printf modifiers are not honored such as 'F', 'l', 'L',
+ * etc. 'F' is for uppercase which is irrelevant when dealing with only
+ * base 10. 'l' and 'L' deal with long double. Again this is just a
+ * very simple implementation. Also modifiers 'width.precision' punting
+ * on this as well. Not getting into the minutia of how to display
+ * 1.2345e+4 given print format '%3.2f'.
+ * This algorithm works best with doubles of type NNNN.NNNN and print
+ * format of '%f'.
+ *
+ *
+ * @param[out] o_consoleBufferInterface - The recipient of the double in string
+ * form.
+ * @param[in] i_formatOptions - Formatting options of the double. Currently not
+ * being used. Kept to be consistent with current
+ * interfaces and if someone decides to actually
+ * implement all the formatting options.
+ * @param[in] i_doubleNumber - The double to convert to a string.
+ */
+size_t display_double(ConsoleBufferInterface& o_consoleBufferInterface,
+ const format_options& i_formatOptions,
+ double i_doubleNumber)
+{
+ // Extract the integer part from the double. Example: 3 from 3.1415,
+ // 1 from 1.0, 31258 from 31258.00001, 0 from 0.123, etc
+ uint64_t l_integerPart = static_cast<uint64_t>(i_doubleNumber);
+
+ // Make a copy of the double for manipulation purposes.
+ double l_doubleTemp = i_doubleNumber;
+
+ // Make a copy of the integer part for manipulation purposes.
+ uint64_t l_integerPartTemp = l_integerPart;
+
+ // The double multiplier to move all digits found after the decimal point
+ // to before the decimal point.
+ uint64_t l_doubleMultiplier(1);
+
+ // Determine how many digits are there after the decimal point by taking a
+ // double such as 3.1415 multiply it by 10 to get 31.415. Get a copy of the
+ // integer part (31). Subtract the integer part (31.0) from the current
+ // double (31.415) to get 0.415. If 0.415 is greater than 0.0, then repeat
+ // the process until there are no more digits after the decimal point.
+ // The l_doubleMultiplier will be a factor of 10 that is needed to mutiply
+ // the double to move all digits after the decimal point to before the
+ // decimal point.
+ while ((l_doubleTemp - static_cast<double>(l_integerPartTemp)) > 0.0)
+ {
+ // Increase the multiplier until the value is exactly large enough to
+ // move all digits after the decimal point to before the decimal point.
+ l_doubleMultiplier*=10;
+ // Move 'X' digits after the decimal point to before the decimal point.
+ l_doubleTemp*=10;
+ // Extract the integer part out of the double
+ l_integerPartTemp = static_cast<uint64_t>(l_doubleTemp);
+ }
+
+ // Variable to capture to the digits after the decimal point.
+ uint64_t l_integerPartAfterDecimalPoint(0);
+
+ // If there are digits after the decimal point then extract those digits.
+ if (l_doubleMultiplier > 1)
+ {
+ // Extract the integer part, after the decimal point, by removing the
+ // integer part from the double then multiplying whats left by the
+ // multiplier calculated above.
+ l_integerPartAfterDecimalPoint = (i_doubleNumber -
+ static_cast<double>(l_integerPart)) *
+ l_doubleMultiplier;
+ }
+
+ // Length of the character buffer.
+ size_t l_bufferLength(0);
+
+ // Buffer to hold the double in string form.
+ char l_stringBuffer[64] = { 0 };
+
+ // Default base to 10.
+ const uint64_t l_base(10);
+
+ // Convert integer part, after decimal point, to ASCII.
+ convert_number_to_ascii(l_stringBuffer, l_bufferLength,
+ l_integerPartAfterDecimalPoint, l_base);
+
+ // Add the decimal point
+ l_stringBuffer[l_bufferLength++] = '.';
+
+ // Convert integer part, before decimal point, to ASCII.
+ convert_number_to_ascii(l_stringBuffer, l_bufferLength,
+ l_integerPart, l_base);
+
+ // End the string with a NIL terminator. The l_bufferLength is one index
+ // past the last digit character.
+ l_stringBuffer[l_bufferLength] = 0;
+
+ // Reverse the string for printing, by swapping to the two ends until they
+ // meet in the middle.
+ char* l_beginChar = l_stringBuffer;
+ char* l_endChar = &(l_stringBuffer[l_bufferLength -1]);
+ char l_tempChar;
+ while (l_beginChar < l_endChar)
+ {
+ l_tempChar = *l_beginChar;
+ *l_beginChar = *l_endChar;
+ *l_endChar = l_tempChar;
+ ++l_beginChar;
+ --l_endChar;
+ }
+
+ // Display the double in string form.
+ return display_string(o_consoleBufferInterface,
+ i_formatOptions,
+ l_stringBuffer);
+}
+
+
size_t vasprintf(ConsoleBufferInterface& func, const char* fmt, va_list& args)
{
int count = 0;
OpenPOWER on IntegriCloud