// // Format.cpp // // $Id: //poco/1.3/Foundation/src/Format.cpp#1 $ // // Library: Foundation // Package: Core // Module: Format // // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // 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. Redistributions in any form must be accompanied by information on // how to obtain complete source code for this software and any // accompanying software that uses this software. The source code // must either be included in the distribution or be available for no // more than the cost of distribution plus a nominal fee, and must be // freely redistributable under reasonable conditions. For an // executable file, complete source code means the source code for all // modules it contains. It does not include source code for modules or // files that typically accompany the major components of the operating // system on which the executable file runs. // // 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 OWNER 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 "Poco/Format.h" #include "Poco/Exception.h" #include #include namespace Poco { namespace { void parseFlags(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) { bool isFlag = true; while (isFlag && itFmt != endFmt) { switch (*itFmt) { case '-': str.setf(std::ios_base::left); ++itFmt; break; case '+': str.setf(std::ios_base::showpos); ++itFmt; break; case '0': str.fill('0'); ++itFmt; break; case '#': str.setf(std::ios_base::showpoint | std::ios_base::showbase); ++itFmt; break; default: isFlag = false; break; } } } void parseWidth(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) { int width = 0; while (itFmt != endFmt && isdigit(*itFmt)) { width = 10*width + *itFmt - '0'; ++itFmt; } if (width != 0) str.width(width); } void parsePrec(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) { if (itFmt != endFmt && *itFmt == '.') { ++itFmt; int prec = 0; while (itFmt != endFmt && isdigit(*itFmt)) { prec = 10*prec + *itFmt - '0'; ++itFmt; } if (prec != 0) str.precision(prec); } } char parseMod(std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) { char mod = 0; if (itFmt != endFmt) { switch (*itFmt) { case 'l': case 'h': case 'L': mod = *itFmt++; break; } } return mod; } void prepareFormat(std::ostream& str, char type) { switch (type) { case 'd': case 'i': str << std::dec; break; case 'o': str << std::oct; break; case 'x': str << std::hex; break; case 'X': str << std::hex << std::uppercase; break; case 'e': str << std::scientific; break; case 'E': str << std::scientific << std::uppercase; break; case 'f': str << std::fixed; break; } } void formatOne(std::string& result, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt, std::vector::const_iterator& itVal) { std::ostringstream str; parseFlags(str, itFmt, endFmt); parseWidth(str, itFmt, endFmt); parsePrec(str, itFmt, endFmt); char mod = parseMod(itFmt, endFmt); if (itFmt != endFmt) { char type = *itFmt++; prepareFormat(str, type); switch (type) { case 'c': str << AnyCast(*itVal++); break; case 'd': case 'i': switch (mod) { case 'l': str << AnyCast(*itVal++); break; case 'L': str << AnyCast(*itVal++); break; case 'h': str << AnyCast(*itVal++); break; default: str << AnyCast(*itVal++); break; } break; case 'o': case 'u': case 'x': case 'X': switch (mod) { case 'l': str << AnyCast(*itVal++); break; case 'L': str << AnyCast(*itVal++); break; case 'h': str << AnyCast(*itVal++); break; default: str << AnyCast(*itVal++); break; } break; case 'e': case 'E': case 'f': switch (mod) { case 'l': str << AnyCast(*itVal++); break; case 'L': str << AnyCast(*itVal++); break; case 'h': str << AnyCast(*itVal++); break; default: str << AnyCast(*itVal++); break; } break; case 's': str << RefAnyCast(*itVal++); break; default: str << type; } } result.append(str.str()); } } std::string format(const std::string& fmt, const Any& value) { std::string result; format(result, fmt, value); return result; } std::string format(const std::string& fmt, const Any& value1, const Any& value2) { std::string result; format(result, fmt, value1, value2); return result; } std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3) { std::string result; format(result, fmt, value1, value2, value3); return result; } std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4) { std::string result; format(result, fmt, value1, value2, value3, value4); return result; } std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5) { std::string result; format(result, fmt, value1, value2, value3, value4, value5); return result; } std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6) { std::string result; format(result, fmt, value1, value2, value3, value4, value5, value6); return result; } void format(std::string& result, const std::string& fmt, const Any& value) { std::vector args; args.push_back(value); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2) { std::vector args; args.push_back(value1); args.push_back(value2); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3) { std::vector args; args.push_back(value1); args.push_back(value2); args.push_back(value3); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4) { std::vector args; args.push_back(value1); args.push_back(value2); args.push_back(value3); args.push_back(value4); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5) { std::vector args; args.push_back(value1); args.push_back(value2); args.push_back(value3); args.push_back(value4); args.push_back(value5); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6) { std::vector args; args.push_back(value1); args.push_back(value2); args.push_back(value3); args.push_back(value4); args.push_back(value5); args.push_back(value6); format(result, fmt, args); } void format(std::string& result, const std::string& fmt, const std::vector& values) { std::string::const_iterator itFmt = fmt.begin(); std::string::const_iterator endFmt = fmt.end(); std::vector::const_iterator itVal = values.begin(); std::vector::const_iterator endVal = values.end(); while (itFmt != endFmt) { switch (*itFmt) { case '%': ++itFmt; if (itFmt != endFmt && itVal != endVal) formatOne(result, itFmt, endFmt, itVal); else result += *itFmt; break; default: result += *itFmt; ++itFmt; } } } } // namespace Poco