w_form.cpp

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 }

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7