/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */ /* $Id: cmnPrintf.cpp,v 1.6 2007/04/26 19:33:56 anton Exp $ Author(s): Ofri Sadowsky Created on: 2006-02-15 (C) Copyright 2006-2007 Johns Hopkins University (JHU), All Rights Reserved. --- begin cisst license - do not edit --- This software is provided "as is" under an open source license, with no warranty. The complete license can be found in license.txt and http://www.cisst.org/cisst/license.txt. --- end cisst license --- */ #include #include #include const char * cmnPrintfParser::TypeIdCharset = "cCdiouxXeDfgGnpsS%"; const char * cmnPrintfParser::IntegerTypeIds = "cCdiouxX"; const char * cmnPrintfParser::FloatTypeIds = "eEfgG"; const char * cmnPrintfParser::StringTypeIds = "sS"; #ifdef CISST_COMPILER_IS_MSVC #define snprintf _snprintf #endif cmnPrintfParser::cmnPrintfParser(std::ostream & output, const cmnPrintf & outputFormatter) : OutputStream(output) , OutputFormatter(outputFormatter) { NextFormatTextPosition = OutputFormatter.GetFormat(); NextFormatTextCharacter = *NextFormatTextPosition; FormatSequence = 0; NextTypeIdCharacter = 0; DumpUntilPercent(); ProcessPercent(); } void cmnPrintfParser::DumpUntilPercent() { if (NextFormatTextPosition == 0) return; char * firstPosition = NextFormatTextPosition; *firstPosition = NextFormatTextCharacter; NextFormatTextPosition = strchr(firstPosition, '%'); if (NextFormatTextPosition != 0) { *NextFormatTextPosition = 0; NextFormatTextCharacter = '%'; } OutputStream << firstPosition; } void cmnPrintfParser::ProcessPercent() { if (NextFormatTextPosition == 0) return; *NextFormatTextPosition = NextFormatTextCharacter; char * firstPosition = NextFormatTextPosition; NextFormatTextPosition = strpbrk(NextFormatTextPosition+1, TypeIdCharset); if (NextFormatTextPosition == 0) { return; } if (*NextFormatTextPosition == '%') { OutputStream << "%"; ++NextFormatTextPosition; NextFormatTextCharacter = *NextFormatTextPosition; DumpUntilPercent(); ProcessPercent(); return; } NextTypeIdCharacter = *NextFormatTextPosition; ++NextFormatTextPosition; NextFormatTextCharacter = *NextFormatTextPosition; *NextFormatTextPosition = 0; FormatSequence = firstPosition; return; } bool cmnPrintfParser::NextTypeIdCharIsOneOf(const char * typeIdCharset) const { if (strchr(typeIdCharset, NextTypeIdCharacter)) { return true; } return false; } template bool cmnTypePrintfForIntegers(cmnPrintfParser & parser, const _intType number) { if (parser.NextTypeIdCharIsOneOf(cmnPrintfParser::FloatTypeIds)) { return cmnTypePrintf(parser, static_cast(number)); } if (!parser.NextTypeIdCharIsOneOf(cmnPrintfParser::IntegerTypeIds)) { std::cerr << "cmnTypePrintf : Expected type identified by <" << parser.GetNextTypeIdCharacter() << ">, received int instead. Suspending output" << std::endl; parser.SuspendOutput(); return false; } char formatBuffer[cmnPrintfParser::BUFFER_SIZE + 1]; formatBuffer[cmnPrintfParser::BUFFER_SIZE] = 0; const int printLength = snprintf(formatBuffer, cmnPrintfParser::BUFFER_SIZE, parser.GetNextFormatSequence(), number); parser.RawOutput(formatBuffer); if ( (printLength < 0) || (printLength > cmnPrintfParser::BUFFER_SIZE) ) { parser.RawOutput(" (truncated)"); } return true; } bool cmnTypePrintf(cmnPrintfParser & parser, const int number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const unsigned int number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const short number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const unsigned short number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const long number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const unsigned long number) { return cmnTypePrintfForIntegers(parser, number); } bool cmnTypePrintf(cmnPrintfParser & parser, const double number) { if (!parser.NextTypeIdCharIsOneOf(cmnPrintfParser::FloatTypeIds)) { std::cerr << "FormatterStream::Format : Expected type identified by <" << parser.GetNextTypeIdCharacter() << ">, received double instead. Suspending output" << std::endl; parser.SuspendOutput(); return false; } char formatBuffer[cmnPrintfParser::BUFFER_SIZE + 1]; formatBuffer[cmnPrintfParser::BUFFER_SIZE] = 0; const int printLength = snprintf(formatBuffer, cmnPrintfParser::BUFFER_SIZE, parser.GetNextFormatSequence(), number); parser.RawOutput(formatBuffer); if ( (printLength < 0) || (printLength > cmnPrintfParser::BUFFER_SIZE) ) { parser.RawOutput(" (truncated)"); } return true; } bool cmnTypePrintf(cmnPrintfParser & parser, const char * text) { if (!parser.NextTypeIdCharIsOneOf(cmnPrintfParser::StringTypeIds)) { std::cerr << "FormatterStream::Format : Expected type identified by <" << parser.GetNextTypeIdCharacter() << ">, received char * instead. Suspending output" << std::endl; parser.SuspendOutput(); return false; } char formatBuffer[cmnPrintfParser::BUFFER_SIZE + 1]; formatBuffer[cmnPrintfParser::BUFFER_SIZE] = 0; const int printLength = snprintf(formatBuffer, cmnPrintfParser::BUFFER_SIZE, parser.GetNextFormatSequence(), text); parser.RawOutput(formatBuffer); if ( (printLength < 0) || (printLength > cmnPrintfParser::BUFFER_SIZE) ) { parser.RawOutput(" (truncated)"); } return true; } // **************************************************************************** // Change History // **************************************************************************** // // $Log: cmnPrintf.cpp,v $ // Revision 1.6 2007/04/26 19:33:56 anton // All files in libraries: Applied new license text, separate copyright and // updated dates, added standard header where missing. // // Revision 1.5 2007/01/30 15:51:28 ofri // cmnPrintf: Generalized support for integer types. Added implementation for new output integer types. // See ticket #265 // // Revision 1.4 2006/11/20 20:33:19 anton // Licensing: Applied new license to cisstCommon, cisstVector, cisstNumerical, // cisstInteractive, cisstImage and cisstOSAbstraction. // // Revision 1.3 2006/06/30 13:38:47 ofri // cmnPrintf : Added explicit specialization for unsigned int. // // Revision 1.2 2006/02/16 16:37:42 anton // cmnPrintf: Modified conditional compilation for _snprintf to support all // versions of Microsoft compilers (so far, .net 2000 and 2003). // // Revision 1.1 2006/02/16 00:21:00 ofri // Added formatted output files cmnPrintf and vctPrintf in the respective // directories (code, include) // // // ****************************************************************************