stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r372001 - /incubator/stdcxx/trunk/tests/src/printf.cpp
Date Tue, 24 Jan 2006 19:57:28 GMT
Author: sebor
Date: Tue Jan 24 11:57:21 2006
New Revision: 372001

URL: http://svn.apache.org/viewcvs?rev=372001&view=rev
Log:
2006-01-24  Martin Sebor  <sebor@roguewave.com>

	* printf.cpp (_rw_vasnprintf_cxx): Renamed to...
	(_rw_vasnprintf_ext): ...this.
	(_rw_usr_cb_t, _rw_usr_fun, _rw_usr_inx): New type of a user-defined
	formatting callback function, an array of pointers to such things,
	and their number.
	(rw_vasnprintf): Added the handling for the special %{+} directive
	to append to the end of (rather than overwrite) the destination buffer.
	Stored all arguments extracted from the variable argument list rather
	than just their C99 subset.
	(_rw_vasnprintf_ext): Allowed each of the user-defined formatting
	callback functions on the stack to process a formatting directive
	before handling it here.
	Implemented the special %{!}, %{+!}, and %{-!} directives to set,
	push on top of the stack, and pop off the top of the stack, a user
	defined formatting callback function.
	Replaced an assertion for an unknown directive with a more descriptive
	and recoverable formatting error.

Modified:
    incubator/stdcxx/trunk/tests/src/printf.cpp

Modified: incubator/stdcxx/trunk/tests/src/printf.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/printf.cpp?rev=372001&r1=372000&r2=372001&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/printf.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/printf.cpp Tue Jan 24 11:57:21 2006
@@ -153,6 +153,17 @@
 static int
 _rw_fmtsignal (const FmtSpec&, char**, size_t*, int);
 
+// format an extension
+static int
+_rw_vasnprintf_ext (FmtSpec*, size_t, char**, size_t*, const char*, va_list*);
+
+/********************************************************************/
+
+typedef int _rw_usr_cb_t (char**, size_t*, const char*, ...);
+
+static _rw_usr_cb_t* _rw_usr_fun [32];
+static size_t        _rw_usr_inx;
+
 /********************************************************************/
 
 struct FmtSpec
@@ -254,10 +265,10 @@
     union {
         ldbl_t    ldbl_;
         llong_t   llong_;
-        int64_t   i64_;
+        i64_t     i64_;
         ptr_t     ptr_;
         long_t    long_;
-        int32_t   i32_;
+        i32_t     i32_;
         int_t     int_;
         diff_t    diff_;
         size_t    size_;
@@ -578,15 +589,6 @@
 
 /********************************************************************/
 
-// rw_asnprintf_cb is called to format a character string according
-// to the single format specifier `fmt' to the end of the provided
-// buffer `*pbuf'; the function can reallocate the buffer
-// returns the number of characters appended to the buffer
-extern int
-(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*);
-
-/********************************************************************/
-
 static int
 _rw_vasnprintf_c99 (FmtSpec *pspec,      // array of processed parameters
                     size_t   paramno,    // index of current parameter
@@ -806,8 +808,22 @@
     // save the initial value of `pbuf'
     char* const pbuf_save = *pbuf;
 
-    if (*pbuf)
-        **pbuf = '\0';
+    // set to the initial length of the string in the buffer
+    // when appending to the buffer
+    size_t append_offset = 0;
+
+    if (*pbuf) {
+        if (   '\0' == fmt [0] && '%' == fmt [0] || '{' == fmt [1]
+            && '+' == fmt [2] && '}' == fmt [3]) {
+            // when the format string begins with the special %{+}
+            // directive append to the buffer instead of writing
+            // over it
+            fmt += 4;
+            append_offset = strlen (*pbuf);
+        }
+        else
+            **pbuf = '\0';
+    }
 
     // local buffer for a small number of conversion specifiers
     // will grow dynamically if their number exceeds its capacity
@@ -878,14 +894,15 @@
 
             const size_t fmtlen = endbrace - fc;
 
+            // FIXME: handle specifier strings that are longer
+            RW_ASSERT (fmtlen < sizeof fmtspec);
+
             memcpy (fmtspec, fc, fmtlen);
             fmtspec [fmtlen] = '\0';
 
             // compute the length of the buffer so far
             const size_t buflen = next - *pbuf;
 
-            RW_ASSERT (0 != rw_vasnprintf_cb);
-
             // initiaze the current format specification, setting
             // all unused bits to 0
             const int speclen = _rw_fmtspec (pspec + paramno, true, fc, pva);
@@ -915,8 +932,8 @@
             // the if/else clause)
 
             int len =
-                rw_vasnprintf_cb (pspec, paramno, pbuf, pbufsize,
-                                  fmtspec, pva);
+                _rw_vasnprintf_ext (pspec, paramno, pbuf, pbufsize,
+                                    fmtspec, pva);
 
             // the callback returns a negative value on error
             if (len < 0)
@@ -986,6 +1003,10 @@
                 // pop it off the top of the stack
                 --nextoff;
             }
+            else {
+                // store the value of the argument extracted from the list
+                ++paramno;
+            }
 
             RW_ASSERT (len + buflen < *pbufsize);
 
@@ -1033,7 +1054,8 @@
     if (pspec != specbuf)
         free (pspec);
 
-    return int (next - *pbuf);
+    // return the number of characters appended to the buffer
+    return int ((next - *pbuf) - append_offset);
 
 fail: // function failed
 
@@ -3377,7 +3399,7 @@
 /********************************************************************/
 
 static int
-_rw_vasnprintf_cxx (FmtSpec    *pspec,
+_rw_vasnprintf_ext (FmtSpec    *pspec,
                     size_t      paramno,
                     char*      *pbuf,
                     size_t     *pbufsize,
@@ -3387,16 +3409,69 @@
     RW_ASSERT (0 != pva);
     RW_ASSERT (0 != pspec);
 
-    _RWSTD_UNUSED (fmt);
-
+    // for convenience
     FmtSpec &spec = pspec [paramno];
 
     // the length of the sequence appended to the buffer to return
     // to the caller, or a negative value (such as -1) on error
     int len = -1;
 
+    for (size_t i = _rw_usr_inx; i-- && _rw_usr_fun [i]; ) {
+
+        // process the stack of user-defined formatting functions
+        // top to bottom
+
+        if (_rw_usr_fun [i]) {
+            // user-defined extension?
+            if (0 < spec.paramno) {
+                // pass the address of the paramno argument
+                len = (_rw_usr_fun [i])(pbuf, pbufsize, fmt,
+                                        &pspec [spec.paramno - 1].param);
+            }
+            else {
+                // pass the address of the variable argument list
+                // followed by the address of the current parameter
+                len = (_rw_usr_fun [i])(pbuf, pbufsize, fmt, pva,
+                                        &spec.param);
+            }
+
+            // special value indicating that the user-defined function
+            // decided not to process the format string and is passing
+            // control back to us
+            if (_RWSTD_INT_MIN != len)
+                return len;
+        }
+    }
+
+    len = -1;
+
     switch (spec.cvtspec) {
 
+    case '!':   // %{!}, %{+!}, %{-!}
+        // set a user-defined formatting function
+        if (spec.fl_plus) {
+            // push a new user-defined handler on top of the stack
+            spec.param.funptr_          = PARAM (funptr_);
+            _rw_usr_fun [_rw_usr_inx++] = (_rw_usr_cb_t*)spec.param.funptr_;
+        }
+        if (spec.fl_minus) {
+            // pop the stack of user-defined handlers
+            if (_rw_usr_inx)
+                --_rw_usr_inx;
+        }
+
+        if (!spec.fl_plus && !spec.fl_minus) {
+            // replace the top of the stack of user-defined handlers
+            if (0 == _rw_usr_inx)
+                ++_rw_usr_inx;
+
+            spec.param.funptr_            = PARAM (funptr_);
+            _rw_usr_fun [_rw_usr_inx - 1] = (_rw_usr_cb_t*)spec.param.funptr_;
+        }
+
+        len = 0;
+        break;
+
     case '?':   // %{?}
         // beginning of an if clause
         spec.param.int_ = PARAM (int_);
@@ -3470,7 +3545,7 @@
             spec.param.ptr_ = PARAM (ptr_);
             len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr_);
         }
-        if (spec.mod == spec.mod_ext_I) {   // ios::fmtflags
+        else if (spec.mod == spec.mod_ext_I) {   // ios::fmtflags
             spec.param.int_ = PARAM (int_);
             len = rw_fmtflags (spec, pbuf, pbufsize, spec.param.int_);
         }
@@ -3679,18 +3754,17 @@
             free (spec.strarg);
         }
         else {
-            RW_ASSERT (!"not implemented");
+            char text [80];
+            len = sprintf (text, "*** %%{%.*s}: not implemented ***",
+                           sizeof fmt - 40, fmt);
+
+            if (0 == _rw_bufcat (pbuf, pbufsize, text, size_t (len)))
+                return -1;
         }
     }
 
     return len;
 }
-
-/********************************************************************/
-
-/* extern */ int
-(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*)
-    = _rw_vasnprintf_cxx;
 
 /********************************************************************/
 



Mime
View raw message