00001 /*<std-header orig-src='shore'> 00002 00003 $Id: w_form.cpp,v 1.10 2010/05/26 01:20:24 nhall Exp $ 00004 00005 SHORE -- Scalable Heterogeneous Object REpository 00006 00007 Copyright (c) 1994-99 Computer Sciences Department, University of 00008 Wisconsin -- Madison 00009 All Rights Reserved. 00010 00011 Permission to use, copy, modify and distribute this software and its 00012 documentation is hereby granted, provided that both the copyright 00013 notice and this permission notice appear in all copies of the 00014 software, derivative works or modified versions, and any portions 00015 thereof, and that both notices appear in supporting documentation. 00016 00017 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00018 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00019 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00020 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00021 00022 This software was developed with support by the Advanced Research 00023 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00024 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00025 Further funding for this work was provided by DARPA through 00026 Rome Research Laboratory Contract No. F30602-97-2-0247. 00027 00028 */ 00029 00030 #include "w_defines.h" 00031 00032 /* -- do not edit anything above this line -- </std-header>*/ 00033 00034 00035 /* 00036 * This software is Copyright 1989, 1991, 1992, 1993, 1994, 1998 by: 00037 * 00038 * Josef Burger <bolo@cs.wisc.edu> 00039 * 00040 * All Rights Reserved. 00041 * 00042 * This software may be freely used as long as credit is given 00043 * to the author and this copyright is maintained. 00044 */ 00045 00046 /* 00047 * An implementation of the 'form' function, an IO stream helper 00048 * for c++ that is equivalent to sprintf for stdio. 00049 * 00050 * This is also an improvement over most c++ library implementations 00051 * in that it allows the buffers for multiple formats to exist 00052 * simultaneously, instead of always over-writing one static buffer. 00053 * This also provides some sanity in threaded environments; more than 00054 * one thread can form() at once. 00055 * 00056 * Configuration options: 00057 * BUF_SLOTS Number of outstanding formatted output buffers. 00058 * MAX_BUFFER Maximum length of each formatted output buffer. 00059 * 00060 * FORM_PRE_ALLOCATE 00061 * if defined, all buffer space that form() uses is 00062 * statically allocated. When this is not defined, 00063 * a single static buffer exists to provide formatting 00064 * in case memory allocatin fails. 00065 * HAVE_VSNPRINTF If defined uses the 'n' format of vsprintf which 00066 * prevents the buffer from being written past its end. 00067 */ 00068 00069 #include <cstdarg> 00070 #include <cstdio> 00071 00072 00073 #define BUF_SLOTS 16 00074 #define MAX_BUFFER 1024 00075 00076 #ifdef FORM_PRE_ALLOCATE 00077 static char buffers[BUF_SLOTS][MAX_BUFFER]; 00078 #else 00079 static char *buffers[BUF_SLOTS]; 00080 static char default_buffer[MAX_BUFFER]; 00081 #endif 00082 static unsigned slot = 0; 00083 00084 /**\cond skip */ 00085 struct form_cleanup 00086 { 00087 ~form_cleanup() { 00088 for(int i=0; i < BUF_SLOTS; i++) 00089 { 00090 delete[] buffers[i]; 00091 buffers[i]=NULL; 00092 } 00093 } 00094 } __cleanup__; 00095 /**\endcond skip */ 00096 00097 00098 /* XXX Yes, this is not thread safe at the moment. */ 00099 00100 const char *form(const char *format, ...) 00101 { 00102 va_list ap; 00103 char *buffer; 00104 unsigned me; 00105 00106 /* XXX Buffer allocation is the only thing that needs to 00107 be protected to be trivially thread safe. */ 00108 me = slot; 00109 slot = (slot + 1) % BUF_SLOTS; 00110 00111 #ifndef FORM_PRE_ALLOCATE 00112 if (!buffers[me]) { 00113 buffers[me] = new char[MAX_BUFFER]; 00114 /* backup strategy ... use one static buffer to guarantee 00115 output in case everything goes to hell. */ 00116 if (!buffers[me]) 00117 buffers[me] = default_buffer; 00118 } 00119 #endif 00120 buffer = buffers[me]; 00121 00122 va_start(ap, format); 00123 #ifdef HAVE_VSNPRINTF 00124 vsnprintf(buffer, MAX_BUFFER, format, ap); 00125 #else 00126 #ifdef HAVE_VPRINTF 00127 vsprintf(buffer, format, ap); 00128 #else 00129 #error need vsprintf 00130 #endif 00131 00132 #endif 00133 va_end(ap); 00134 00135 buffer[MAX_BUFFER-1] = '\0'; /* Paranoia */ 00136 00137 return buffer; 00138 }