diff --git a/src/Config.cpp b/src/Config.cpp index 662ce6d14..379b15629 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -640,17 +640,13 @@ const bool Config::getBoolean (const std::string& key) //////////////////////////////////////////////////////////////////////////////// void Config::set (const std::string& key, const int value) { - char v[24]; - sprintf (v, "%d", value); - (*this)[key] = v; + (*this)[key] = format (value); } //////////////////////////////////////////////////////////////////////////////// void Config::set (const std::string& key, const double value) { - char v[32]; - sprintf (v, "%f", value); - (*this)[key] = v; + (*this)[key] = format (value, 1, 8); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Grid.cpp b/src/Grid.cpp index 03fc0b7c5..a95b34d07 100644 --- a/src/Grid.cpp +++ b/src/Grid.cpp @@ -61,6 +61,7 @@ #include #include +#include #include //////////////////////////////////////////////////////////////////////////////// @@ -364,16 +365,14 @@ Grid::Cell::operator double () const Grid::Cell::operator std::string () const { - char s[64] = {0}; - switch (mType) { case CELL_BOOL: return mBool ? "true" : "false"; // TODO i18n - case CELL_CHAR: sprintf (s, "%c", mChar); return std::string (s); - case CELL_INT: sprintf (s, "%d", mInt); return std::string (s); - case CELL_FLOAT: sprintf (s, "%f", mFloat); return std::string (s); - case CELL_DOUBLE: sprintf (s, "%f", mDouble); return std::string (s); - case CELL_STRING: return mString; + case CELL_CHAR: return format (mChar); + case CELL_INT: return format (mInt); + case CELL_FLOAT: return format (mFloat, 1, 6); + case CELL_DOUBLE: return format (mDouble, 1, 8); + case CELL_STRING: return mString; } return std::string (""); diff --git a/src/Nibbler.cpp b/src/Nibbler.cpp index 13bb7ee7b..5bc5bdffe 100644 --- a/src/Nibbler.cpp +++ b/src/Nibbler.cpp @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include "Nibbler.h" @@ -290,6 +291,33 @@ bool Nibbler::getInt (int& result) return false; } +//////////////////////////////////////////////////////////////////////////////// +bool Nibbler::getHex (int& result) +{ + std::string::size_type i = mCursor; + + if (i < mLength) + { + if (mInput[i] == '-') + ++i; + else if (mInput[i] == '+') + ++i; + } + + // TODO Potential for use of find_first_not_of + while (i < mLength && isxdigit (mInput[i])) + ++i; + + if (i > mCursor) + { + result = strtoimax (mInput.substr (mCursor, i - mCursor).c_str (), NULL, 16); + mCursor = i; + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getUnsignedInt (int& result) { diff --git a/src/Nibbler.h b/src/Nibbler.h index 1834d9649..434c37c09 100644 --- a/src/Nibbler.h +++ b/src/Nibbler.h @@ -49,6 +49,7 @@ public: bool getQuoted (char, std::string&, bool quote = false); bool getInt (int&); + bool getHex (int&); bool getUnsignedInt (int&); bool getNumber (double&); bool getLiteral (const std::string&); diff --git a/src/custom.cpp b/src/custom.cpp index 3028c9f05..d4d4fc63d 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -140,20 +140,14 @@ int handleCustomReport (const std::string& report, std::string& outs) table.setColumnWidth (columnCount, Table::minimum); table.setColumnJustification (columnCount, Table::right); - char s[16]; std::string value; int row = 0; foreach (task, tasks) { if (task->id != 0) - { - sprintf (s, "%d", (int) task->id); - value = s; - } + value = format (task->id); else - { value = "-"; - } context.hooks.trigger ("format-id", "id", value); table.addCell (row++, columnCount, value); diff --git a/src/edit.cpp b/src/edit.cpp index 04760c1ff..06009baf0 100644 --- a/src/edit.cpp +++ b/src/edit.cpp @@ -83,9 +83,7 @@ static std::string findDate ( if (value != "") { Date dt (value, context.config.get ("dateformat")); - char epoch [16]; - sprintf (epoch, "%d", (int)dt.toEpoch ()); - return std::string (epoch); + return format ((int) dt.toEpoch ()); } } } diff --git a/src/history.cpp b/src/history.cpp index e0506da57..5d6c77c3a 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -478,12 +478,10 @@ int handleReportGHistoryMonthly (std::string& outs) std::string bar = ""; if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) { - char number[24]; std::string aBar = ""; if (addedGroup[i->first]) { - sprintf (number, "%d", addedGroup[i->first]); - aBar = number; + aBar = format (addedGroup[i->first]); while (aBar.length () < addedBar) aBar = " " + aBar; } @@ -491,8 +489,7 @@ int handleReportGHistoryMonthly (std::string& outs) std::string cBar = ""; if (completedGroup[i->first]) { - sprintf (number, "%d", completedGroup[i->first]); - cBar = number; + cBar = format (completedGroup[i->first]); while (cBar.length () < completedBar) cBar = " " + cBar; } @@ -500,8 +497,7 @@ int handleReportGHistoryMonthly (std::string& outs) std::string dBar = ""; if (deletedGroup[i->first]) { - sprintf (number, "%d", deletedGroup[i->first]); - dBar = number; + dBar = format (deletedGroup[i->first]); while (dBar.length () < deletedBar) dBar = " " + dBar; } @@ -677,12 +673,10 @@ int handleReportGHistoryAnnual (std::string& outs) std::string bar = ""; if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) { - char number[24]; std::string aBar = ""; if (addedGroup[i->first]) { - sprintf (number, "%d", addedGroup[i->first]); - aBar = number; + aBar = format (addedGroup[i->first]); while (aBar.length () < addedBar) aBar = " " + aBar; } @@ -690,8 +684,7 @@ int handleReportGHistoryAnnual (std::string& outs) std::string cBar = ""; if (completedGroup[i->first]) { - sprintf (number, "%d", completedGroup[i->first]); - cBar = number; + cBar = format (completedGroup[i->first]); while (cBar.length () < completedBar) cBar = " " + cBar; } @@ -699,8 +692,7 @@ int handleReportGHistoryAnnual (std::string& outs) std::string dBar = ""; if (deletedGroup[i->first]) { - sprintf (number, "%d", deletedGroup[i->first]); - dBar = number; + dBar = format (deletedGroup[i->first]); while (dBar.length () < deletedBar) dBar = " " + dBar; } diff --git a/src/report.cpp b/src/report.cpp index 1b1a536eb..b21df3c34 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -431,12 +431,9 @@ int handleInfo (std::string& outs) context.hooks.trigger ("pre-display", *task); // id - char svalue[12]; - std::string value; int row = table.addRow (); table.addCell (row, 0, "ID"); - sprintf (svalue, "%d", (int) task->id); - value = svalue; + std::string value = format (task->id); context.hooks.trigger ("format-id", "id", value); table.addCell (row, 1, value); diff --git a/src/tests/nibbler.t.cpp b/src/tests/nibbler.t.cpp index f4a72be26..d0123491d 100644 --- a/src/tests/nibbler.t.cpp +++ b/src/tests/nibbler.t.cpp @@ -33,7 +33,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (155); + UnitTest t (162); try { @@ -54,6 +54,7 @@ int main (int argc, char** argv) t.notok (n.skipAllOneOf ("abc"), "trivial: skipAllOneOf"); t.notok (n.getQuoted ('"', s), "trivial: getQuoted"); t.notok (n.getInt (i), "trivial: getInt"); + t.notok (n.getHex (i), "trivial: getHex"); t.notok (n.getUnsignedInt (i), "trivial: getUnsignedInt"); t.notok (n.getUntilEOL (s), "trivial: getUntilEOL"); t.notok (n.getUntilEOS (s), "trivial: getUntilEOS"); @@ -219,6 +220,16 @@ int main (int argc, char** argv) t.is (i, -4, " '-4' : getInt () -> '-4'"); t.ok (n.depleted (), " '' : depleted () -> true"); + // bool getHex (int&); + t.diag ("Nibbler::getHex"); + n = Nibbler ("123 7b"); + t.ok (n.getHex (i), " '123 7b' : getHex () -> true"); + t.is (i, 291, " '123 7b' : getHex () -> '291'"); + t.ok (n.skip (' '), " ' 7b' : skip (' ') -> true"); + t.ok (n.getHex (i), " '7b' : getHex () -> true"); + t.is (i, 123, " '7b' : getHex () -> '123'"); + t.ok (n.depleted (), " '' : depleted () -> true"); + // bool getUnsignedInt (int&i); t.diag ("Nibbler::getUnsignedInt"); n = Nibbler ("123 4"); diff --git a/src/tests/text.t.cpp b/src/tests/text.t.cpp index 8df77c041..6a5d26431 100644 --- a/src/tests/text.t.cpp +++ b/src/tests/text.t.cpp @@ -34,7 +34,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (194); + UnitTest t (208); // void wrapText (std::vector & lines, const std::string& text, const int width) std::string text = "This is a test of the line wrapping code."; @@ -389,8 +389,32 @@ int main (int argc, char** argv) // int characters (const std::string&); t.is (characters ("Çirçös"), 6, "characters (Çirçös) == 6"); - t.is (characters ("ツネナラム"), 5, "characters (ツネナラム) == 6"); - t.is (characters ("Zwölf Boxkämpfer"), 16, "characters (Zwölf Boxkämpfer) == 6"); + t.is (characters ("ツネナラム"), 5, "characters (ツネナラム) == 5"); + t.is (characters ("Zwölf Boxkämpfer"), 16, "characters (Zwölf Boxkämpfer) == 16"); + + // std::string format (char); + t.is (format ('A'), "A", "format ('A') -> A"); + + // std::string format (int); + t.is (format (0), "0", "format (0) -> 0"); + t.is (format (-1), "-1", "format (-1) -> -1"); + + // std::string formatHex (int); + t.is (formatHex (0), "0", "formatHex (0) -> 0"); + t.is (formatHex (10), "a", "formatHex (10) -> a"); + t.is (formatHex (123), "7b", "formatHex (123) -> 7b"); + + // std::string format (float, int, int); + t.is (format (1.23456789, 8, 1), " 1", "format (1.23456789, 8, 1) -> _______1"); + t.is (format (1.23456789, 8, 2), " 1.2", "format (1.23456789, 8, 2) -> _____1.2"); + t.is (format (1.23456789, 8, 3), " 1.23", "format (1.23456789, 8, 3) -> ____1.23"); + t.is (format (1.23456789, 8, 4), " 1.235", "format (1.23456789, 8, 4) -> ___1.235"); + t.is (format (1.23456789, 8, 5), " 1.2346", "format (1.23456789, 8, 5) -> __1.2346"); + t.is (format (1.23456789, 8, 6), " 1.23457", "format (1.23456789, 8, 6) -> 1.23457"); + t.is (format (1.23456789, 8, 7), "1.234568", "format (1.23456789, 8, 7) -> 1.234568"); + t.is (format (1.23456789, 8, 8), "1.2345679", "format (1.23456789, 8, 8) -> 1.2345679"); + + // std::string format (double, int, int); return 0; } diff --git a/src/text.cpp b/src/text.cpp index a819bbf2d..5a568c970 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -635,6 +635,7 @@ int strippedLength (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// +// UTF8 int characters (const std::string& str) { int byteLength = str.length (); @@ -658,14 +659,59 @@ std::string cutOff (const std::string& str, std::string::size_type len) { if (str.length () > len) { - return (str.substr(0,len-2) + ".."); + return (str.substr (0, len - 2) + ".."); } else { std::string res = str; res.resize (len, ' '); return res; - } + } +} + +//////////////////////////////////////////////////////////////////////////////// +std::string format (char value) +{ + std::stringstream s; + s << value; + return s.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +std::string format (int value) +{ + std::stringstream s; + s << value; + return s.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +std::string formatHex (int value) +{ + std::stringstream s; + s.setf (std::ios::hex, std::ios::basefield); + s << value; + return s.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +std::string format (float value, int width, int precision) +{ + std::stringstream s; + s.width (width); + s.precision (precision); + s << value; + return s.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +std::string format (double value, int width, int precision) +{ + std::stringstream s; + s.width (width); + s.precision (precision); + s << value; + return s.str (); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index 5274f9497..916f13242 100644 --- a/src/text.h +++ b/src/text.h @@ -61,6 +61,11 @@ std::string::size_type find (const std::string&, const std::string&, bool sensit std::string::size_type find (const std::string&, const std::string&, std::string::size_type, bool sensitive = true); int strippedLength (const std::string&); std::string cutOff (const std::string&, std::string::size_type); +std::string format (char); +std::string format (int); +std::string formatHex (int); +std::string format (float, int, int); +std::string format (double, int, int); // UTF-8 aware. int characters (const std::string&);