00001 /** @file rutz/sfmt.cc make a rutz::fstring using printf-style 00002 formatting */ 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 2005-2007 University of Southern California 00006 // Rob Peters <rjpeters at klab dot caltech dot edu> 00007 // 00008 // created: Tue Jul 5 11:02:46 2005 00009 // commit: $Id: sfmt.cc 11268 2009-06-03 23:23:53Z lzc $ 00010 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/sfmt.cc $ 00011 // 00012 // -------------------------------------------------------------------- 00013 // 00014 // This file is part of GroovX. 00015 // [http://www.klab.caltech.edu/rjpeters/groovx/] 00016 // 00017 // GroovX is free software; you can redistribute it and/or modify it 00018 // under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation; either version 2 of the License, or 00020 // (at your option) any later version. 00021 // 00022 // GroovX is distributed in the hope that it will be useful, but 00023 // WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00025 // General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with GroovX; if not, write to the Free Software Foundation, 00029 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00030 // 00031 /////////////////////////////////////////////////////////////////////// 00032 00033 #ifndef GROOVX_RUTZ_SFMT_CC_UTC20050705180246_DEFINED 00034 #define GROOVX_RUTZ_SFMT_CC_UTC20050705180246_DEFINED 00035 00036 #include "rutz/sfmt.h" 00037 00038 #include "rutz/compat_snprintf.h" 00039 #include "rutz/error.h" 00040 00041 #include "rutz/debug.h" 00042 00043 using rutz::fstring; 00044 00045 fstring rutz::vsfmt(const char* fmt, va_list ap) 00046 { 00047 // if we have a null pointer or an empty string, then just return an 00048 // empty fstring 00049 if (fmt == 0 || fmt[0] == '\0') 00050 { 00051 return fstring(); 00052 } 00053 00054 size_t bufsize = 8192; 00055 while (1) 00056 { 00057 // relying on a gcc extension to create stack arrays whose size 00058 // is not a compile-time constant -- could also use alloca or 00059 // std::vector here 00060 char buf[bufsize]; 00061 00062 const int nchars = vsnprintf(buf, bufsize, fmt, ap); 00063 00064 if (nchars < 0) 00065 { 00066 // a negative return code from vsnprintf() means there was 00067 // an actual formatting error (i.e., not just a too-short 00068 // buffer) 00069 char errbuf[1024]; 00070 snprintf(&errbuf[0], sizeof(errbuf), 00071 "vsnprintf failed with format string '%s' " 00072 "and bufsize %lu", fmt, (unsigned long) bufsize); 00073 throw rutz::error(&errbuf[0], SRC_POS); 00074 } 00075 else if (static_cast<size_t>(nchars) >= bufsize) 00076 { 00077 // buffer was too small, so let's double the bufsize and try 00078 // again: 00079 const size_t new_bufsize = bufsize * 2; 00080 // make sure that we haven't overflow the unsigned int 00081 // size_t: 00082 if (new_bufsize < bufsize) 00083 { 00084 char errbuf[1024]; 00085 snprintf(&errbuf[0], sizeof(errbuf), 00086 "buffer size overflow with format string '%s' " 00087 "and bufsize %lu", fmt, (unsigned long) bufsize); 00088 throw rutz::error(&errbuf[0], SRC_POS); 00089 } 00090 00091 bufsize = new_bufsize; 00092 continue; 00093 } 00094 else 00095 { 00096 // OK, the vsnprintf() succeeded: 00097 return fstring(rutz::char_range(&buf[0], nchars)); 00098 } 00099 } 00100 // should never get here: 00101 GVX_ASSERT(0); 00102 /* can't happen: */ return fstring(); 00103 } 00104 00105 fstring rutz::sfmt(const char* fmt, ...) 00106 { 00107 va_list a; 00108 va_start(a, fmt); 00109 const fstring result = rutz::vsfmt(fmt, a); 00110 va_end(a); 00111 return result; 00112 } 00113 00114 static const char __attribute__((used)) vcid_groovx_rutz_sfmt_cc_utc20050705180246[] = "$Id: sfmt.cc 11268 2009-06-03 23:23:53Z lzc $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/sfmt.cc $"; 00115 #endif // !GROOVX_RUTZ_SFMT_CC_UTC20050705180246DEFINED