--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/format.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,107 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <cstdio> +#include "format.h" + +// +// Throws an error while formatting the string +// +static auto format_error (String fmtstr, const String errdescribe, int pos) -> void +{ + fmtstr.replace ("\n", " "); + fmtstr.replace ("\t", " "); + String errmsg ("With format string:\n" + fmtstr + "\n"); + + for (int x = 0; x < pos; ++x) + errmsg += "-"; + + errmsg += "^\n" + errdescribe; + // throw std::logic_error (errmsg.stdString()); + std::fprintf (stderr, "%s", errmsg.chars()); + std::exit (EXIT_FAILURE); +} + +// +// Main formatter algorithm autoion. Processes @fmtstr with @args and returns +// the result. +// +auto format_args (const String& fmtstr, const Vector<String>& args) -> String +{ + String fmt = fmtstr; + int pos = 0; + + while ((pos = fmt.find ("%", pos)) != -1) + { + if (fmt[pos + 1] == '%') + { + fmt.replace (pos, 2, "%"); + pos++; + continue; + } + + int ofs = 1; + char mod = '\0'; + + // handle modifiers + if (fmt[pos + ofs] == 's' or fmt[pos + ofs] == 'x' or fmt[pos + ofs] == 'd') + { + mod = fmt[pos + ofs]; + ofs++; + } + + if (fmt[pos + ofs] < '1' or fmt[pos + ofs] > '9') + { + format_error (fmtstr, "bad format string, expected non-zero digit with " + "optional modifier after '%%'", pos); + } + + int i = fmt[pos + ofs] - '0'; + + if (i > args.size()) + format_error (fmtstr, String ("Format argument #") + i + " used but not defined.", pos); + + String replacement = args[i - 1]; + + switch (mod) + { + case 's': replacement = (replacement == "1") ? "" : "s"; break; + case 'd': replacement.sprintf ("%d", replacement[0]); break; + case 'x': replacement.sprintf ("0x%x", replacement.to_int()); break; + default: break; + } + + fmt.replace (pos, 1 + ofs, replacement); + pos += replacement.length(); + } + + return fmt; +} +