[Ace-users] [ace-users] Proposal: ACE_OS::asprintf(), etc.
Johnny Willemsen
jwillemsen at remedy.nl
Fri Oct 26 14:10:22 CDT 2007
Hi JT,
Added asprintf() as wrapper is ok. The patch hard to review, a lot of checks
for defines are removed, if you make sure that things keep working for all
tests and users, feel free to commit this, but keep a very good watch at the
scoreboard.
Regards,
Johnny Willemsen
Remedy IT
Postbus 101
2650 AC Berkel en Rodenrijs
The Netherlands
www.theaceorb.nl / www.remedy.nl
*** Integrated compile and test statistics see
http://scoreboard.theaceorb.nl ***
*** Commercial service and support for ACE/TAO/CIAO ***
*** See http://www.theaceorb.nl/en/support.html ***
> Similar to the getprogname() issue I mentioned yesterday, another
> thing we ran into while porting our system from NetBSD to Solaris
> was the use of asprintf() and vasprintf().
>
> asprintf() is similar to sprintf(), but instead of passing a char *
> you pass the address of a char*, which is set to a malloc() buffer
> containing the formatted output. This is useful in cases where you
> don't know the size of the buffer needed. While you can do the same
> thing with two calls to snprintf() -- the first to find the buffer
> size, the second to format the string into an appropriately sized
> buffer -- asprintf() nicely ties this together in a single call.
>
> The asprintf(), etc. functions are fairly widely implemented: *BSD,
> Linux, etc. It appears they may even become part of the C standard
> some time in the future. While preparing this message, I googled up a
> *.pdf of C Standard Committee Draft N1248 --- See
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1248.pdf for details.
>
> I think that adding ACE_OS::asprintf() wrapper facades would be
> generally useful.
>
> While implementing these functions, I noticed some anomalies in some
> of the other ACE_OS::*printf() wrapper facades:
>
> * There was no wide character version of ACE_OS::printf().
>
> * There were no wide or narrow versions of ACE_OS::vprintf().
>
> * There were no wide or narrow versions of ACE_OS::vfprintf().
>
> * In some cases, ACE_OS::*printf() was implemented in terms of the
> corresponding ACE_OS::v*printf() function; in others it was done
> in terms of the system's ::v*printf() function.
>
> Some of this was because of missing ACE_OS::vprintf() and
> ACE_OS::vfprintf() as noted above. But now that I've added those
> functions, I changed ACE_OS::*printf() to use ACE_OS::v*printf().
> This ensures consistent behavior (ACE_OS::{v,}s{n,}printf() has
> a pretty complicated nest of conditionals, and the code appears
> to have diverged (hopefully only syntactically) over the years).
>
> In most cases, ACE_OS::v*printf() is an inline that simply invokes
> ::v*printf(), so there should be no time or space overhead.
>
> Here is the patch I'm proposing.
>
> --jtc
>
> Index: OS_NS_stdio.cpp
> ===================================================================
> --- OS_NS_stdio.cpp (revision 79869)
> +++ OS_NS_stdio.cpp (working copy)
> @@ -257,14 +257,17 @@
>
> #endif /* ACE_WIN32 */
>
> +// The following *printf functions aren't inline because
> +// they use varargs.
> +
> int
> ACE_OS::fprintf (FILE *fp, const char *format, ...)
> {
> - ACE_OS_TRACE ("ACE_OS::fprintf");
> + // ACE_OS_TRACE ("ACE_OS::fprintf");
> int result = 0;
> va_list ap;
> va_start (ap, format);
> - ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result);
> + result = ACE_OS::vfprintf (fp, format, ap);
> va_end (ap);
> return result;
> }
> @@ -273,28 +276,41 @@
> int
> ACE_OS::fprintf (FILE *fp, const wchar_t *format, ...)
> {
> - ACE_OS_TRACE ("ACE_OS::fprintf");
> -
> -# if !defined (ACE_HAS_VFWPRINTF)
> - ACE_UNUSED_ARG (fp);
> - ACE_UNUSED_ARG (format);
> - ACE_NOTSUP_RETURN (-1);
> -
> -# else
> + // ACE_OS_TRACE ("ACE_OS::fprintf");
> int result = 0;
> va_list ap;
> va_start (ap, format);
> - ACE_OSCALL (ACE_STD_NAMESPACE::vfwprintf (fp, format, ap),
> int, -1, result);
> + result = ACE_OS::vfprintf (fp, format, ap);
> va_end (ap);
> return result;
> -
> -# endif /* ACE_HAS_VFWPRINTF */
> }
> #endif /* ACE_HAS_WCHAR */
>
> +int
> +ACE_OS::asprintf (char **bufp, const char *format, ...)
> +{
> + // ACE_OS_TRACE ("ACE_OS::aprintf");
> + int result;
> + va_list ap;
> + va_start (ap, format);
> + result = ACE_OS::vasprintf (bufp, format, ap);
> + va_end (ap);
> + return result;
> +}
>
> -// The following *printf functions aren't inline because
> -// they use varargs.
> +#if defined (ACE_HAS_WCHAR)
> +int
> +ACE_OS::asprintf (wchar_t **bufp, const wchar_t *format, ...)
> +{
> + // ACE_OS_TRACE ("ACE_OS::aprintf");
> + int result;
> + va_list ap;
> + va_start (ap, format);
> + result = ACE_OS::vasprintf (bufp, format, ap);
> + va_end (ap);
> + return result;
> +}
> +#endif /* ACE_HAS_WCHAR */
>
> int
> ACE_OS::printf (const char *format, ...)
> @@ -303,12 +319,26 @@
> int result;
> va_list ap;
> va_start (ap, format);
> - ACE_OSCALL (::vprintf (format, ap), int, -1, result);
> + result = ACE_OS::vprintf (format, ap);
> va_end (ap);
> return result;
> }
>
> +#if defined (ACE_HAS_WCHAR)
> int
> +ACE_OS::printf (const wchar_t *format, ...)
> +{
> + // ACE_OS_TRACE ("ACE_OS::printf");
> + int result;
> + va_list ap;
> + va_start (ap, format);
> + result = ACE_OS::vprintf (format, ap);
> + va_end (ap);
> + return result;
> +}
> +#endif /* ACE_HAS_WCHAR */
> +
> +int
> ACE_OS::snprintf (char *buf, size_t maxlen, const char *format, ...)
> {
> // ACE_OS_TRACE ("ACE_OS::snprintf");
> @@ -321,53 +351,16 @@
> }
>
> #if defined (ACE_HAS_WCHAR)
> -
> int
> ACE_OS::snprintf (wchar_t *buf, size_t maxlen, const wchar_t
> *format, ...)
> {
> // ACE_OS_TRACE ("ACE_OS::snprintf");
> -# if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500) || \
> - (defined (sun) && !defined (_XPG4) || defined(_XPG5)) || \
> - defined (ACE_WIN32) || defined (ACE_HAS_VSWPRINTF)
> int result;
> va_list ap;
> va_start (ap, format);
> -# if 0 /* defined (ACE_HAS_TR24731_2005_CRT) */
> - // _vsnwprintf_s() doesn't report the length needed when
> it truncates. This
> - // info is needed for the API contract return value, so
> don't use this.
> - // There's adequate protection via the maxlen.
> - result = _vsnwprintf_s (buf, maxlen, _TRUNCATE, format, ap);
> -# elif defined (ACE_WIN32)
> - // Microsoft's vswprintf() doesn't have the maxlen argument that
> - // XPG4/UNIX98 define. They do, however, recommend use of
> _vsnwprintf()
> - // as a substitute, which does have the same signature as
> the UNIX98 one.
> - ACE_OSCALL (::_vsnwprintf (buf, maxlen, format, ap), int,
> -1, result);
> - // Win32 doesn't regard a full buffer with no 0-terminate
> as an overrun.
> - if (result == static_cast <int> (maxlen))
> - result = -1;
> -
> - // Win32 doesn't 0-terminate the string if it overruns maxlen.
> - if (result == -1)
> - buf[maxlen-1] = '\0';
> -# else
> - ACE_OSCALL (::vswprintf (buf, maxlen, format, ap), int,
> -1, result);
> -# endif /* ACE_WIN32 */
> + result = ACE_OS::vsnprintf (buf, maxlen, format, ap);
> va_end (ap);
> - // In out-of-range conditions, C99 defines vsnprintf to
> return the number
> - // of characters that would have been written if enough
> space was available.
> - // Earlier variants of the vsnprintf() (e.g. UNIX98)
> defined it to return
> - // -1. This method follows the C99 standard, but needs to
> guess at the
> - // value; uses maxlen + 1.
> - if (result == -1)
> - result = static_cast <int> (maxlen + 1);
> return result;
> -
> -# else
> - ACE_UNUSED_ARG (buf);
> - ACE_UNUSED_ARG (maxlen);
> - ACE_UNUSED_ARG (format);
> - ACE_NOTSUP_RETURN (-1);
> -# endif /* _XOPEN_SOURCE ... */
> }
> #endif /* ACE_HAS_WCHAR */
>
> @@ -375,11 +368,10 @@
> ACE_OS::sprintf (char *buf, const char *format, ...)
> {
> // ACE_OS_TRACE ("ACE_OS::sprintf");
> -
> int result;
> va_list ap;
> va_start (ap, format);
> - ACE_OSCALL (::vsprintf (buf, format, ap), int, -1, result);
> + result = ACE_OS::vsprintf (buf, format, ap);
> va_end (ap);
> return result;
> }
> @@ -388,46 +380,77 @@
> int
> ACE_OS::sprintf (wchar_t *buf, const wchar_t *format, ...)
> {
> - ACE_OS_TRACE ("ACE_OS::sprintf");
> -
> -# if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500) || \
> - (defined (sun) && !defined (_XPG4) || defined(_XPG5)) || \
> - defined (ACE_HAS_DINKUM_STL) || defined (__DMC__) || \
> - defined (ACE_HAS_VSWPRINTF) || \
> - (defined (ACE_WIN32_VC8) && !defined (ACE_HAS_WINCE) && \
> - _MSC_FULL_VER > 140050000)
> -
> - // The XPG4/UNIX98/C99 signature of the wide-char sprintf has a
> - // maxlen argument. Since this method doesn't supply one, pass in
> - // a length that works (ULONG_MAX doesn't on all platform
> since some check
> - // to see if the operation will remain in bounds). If this
> isn't ok, use
> - // ACE_OS::snprintf().
> + // ACE_OS_TRACE ("ACE_OS::sprintf");
> int result;
> va_list ap;
> va_start (ap, format);
> - ACE_OSCALL (ACE_STD_NAMESPACE::vswprintf (buf, 4096,
> format, ap), int, -1, result);
> + result = ACE_OS::vsprintf (buf, format, ap);
> va_end (ap);
> return result;
> +}
> +#endif /* ACE_HAS_WCHAR */
>
> -# elif defined (ACE_WIN32)
> - // Pre-VC8 Windows has vswprintf, but the signature is
> from the older ISO C
> - // standard. Also see ACE_OS::snprintf() for more info on this.
> +#if !defined (ACE_HAS_VASPRINTF)
> +int
> +ACE_OS::vasprintf_emulation(char **bufp, const char *format,
> va_list argptr)
> +{
> + int size;
>
> - int result;
> va_list ap;
> - va_start (ap, format);
> - ACE_OSCALL (::vswprintf (buf, format, ap), int, -1, result);
> + va_copy (ap, argptr);
> + size = ACE_OS::vsnprintf(NULL, 0, format, ap);
> va_end (ap);
> - return result;
>
> -# else
> + if (size != -1)
> + {
> + char *buf = reinterpret_cast<char*>(ACE_OS::malloc(size + 1));
> + if (!buf)
> + return -1;
>
> - ACE_UNUSED_ARG (buf);
> - ACE_UNUSED_ARG (format);
> - ACE_NOTSUP_RETURN (-1);
> + va_list aq;
> + va_copy (aq, argptr);
> + size = ACE_OS::vsnprintf(buf, size + 1, format, aq);
> + va_end (aq);
>
> -# endif /* XPG5 || ACE_HAS_DINKUM_STL */
> + if (size != -1)
> + *bufp = buf;
> + }
> +
> + return size;
> }
> +#endif /* !ACE_HAS_VASPRINTF */
> +
> +#if defined (ACE_HAS_WCHAR)
> +#if !defined (ACE_HAS_VASWPRINTF)
> +int
> +ACE_OS::vaswprintf_emulation(wchar_t **bufp, const wchar_t
> *format, va_list argptr)
> +{
> + int size;
> +
> + va_list ap;
> + va_copy (ap, argptr);
> + size = ACE_OS::vsnprintf(NULL, 0, format, ap);
> + va_end (ap);
> +
> + if (size != -1)
> + {
> + wchar_t *buf = reinterpret_cast<wchar_t*>
> + (ACE_OS::malloc((size + 1) * sizeof(wchar_t)));
> + if (!buf)
> + return -1;
> +
> + va_list aq;
> + va_copy (aq, argptr);
> + size = ACE_OS::vsnprintf(buf, size + 1, format, aq);
> + va_end (aq);
> +
> + if (size != -1)
> + *bufp = buf;
> + }
> +
> + return size;
> +}
> +#endif /* !ACE_HAS_VASWPRINTF */
> #endif /* ACE_HAS_WCHAR */
>
> ACE_END_VERSIONED_NAMESPACE_DECL
> Index: OS_NS_stdio.h
> ===================================================================
> --- OS_NS_stdio.h (revision 79869)
> +++ OS_NS_stdio.h (working copy)
> @@ -208,6 +208,14 @@
> # endif /* ACE_LACKS_CUSERID */
> //@}
>
> + extern ACE_Export
> + int asprintf (char **bufp, const char* format, ...);
> +
> +# if defined (ACE_HAS_WCHAR)
> + extern ACE_Export
> + int asprintf (wchar_t **bufp, const wchar_t* format, ...);
> +#endif /* ACE_HAS_WCHAR */
> +
> ACE_NAMESPACE_INLINE_FUNCTION
> int fclose (FILE *fp);
>
> @@ -408,6 +416,11 @@
> extern ACE_Export
> int printf (const char *format, ...);
>
> +#if defined (ACE_HAS_WCHAR)
> + extern ACE_Export
> + int printf (const wchar_t *format, ...);
> +#endif
> +
> ACE_NAMESPACE_INLINE_FUNCTION
> int puts (const char *s);
>
> @@ -458,6 +471,15 @@
> #endif /* ACE_HAS_WCHAR */
>
> ACE_NAMESPACE_INLINE_FUNCTION
> + int vasprintf (char **bufp, const char *format, va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> + int vprintf (const char *format, va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> + int vfprintf (FILE *fp, const char *format, va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> int vsprintf (char *buffer, const char *format, va_list argptr);
>
> ACE_NAMESPACE_INLINE_FUNCTION
> @@ -465,12 +487,33 @@
>
> # if defined (ACE_HAS_WCHAR)
> ACE_NAMESPACE_INLINE_FUNCTION
> + int vasprintf (wchar_t **bufp, const wchar_t *format,
> va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> + int vprintf (const wchar_t *format, va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> + int vfprintf (FILE *fp, const wchar_t *format, va_list argptr);
> +
> + ACE_NAMESPACE_INLINE_FUNCTION
> int vsprintf (wchar_t *buffer, const wchar_t *format,
> va_list argptr);
>
> ACE_NAMESPACE_INLINE_FUNCTION
> int vsnprintf (wchar_t *buffer, size_t maxlen, const
> wchar_t *format, va_list argptr);
> # endif /* ACE_HAS_WCHAR */
>
> +#if !defined (ACE_HAS_VASPRINTF)
> + extern ACE_Export
> + int vasprintf_emulation (char **bufp, const char *format,
> va_list argptr);
> +#endif /* !ACE_HAS_VASPRINTF */
> +
> +#if defined (ACE_HAS_WCHAR)
> +#if !defined (ACE_HAS_VASWPRINTF)
> + extern ACE_Export
> + int vaswprintf_emulation (wchar_t **bufp, const wchar_t
> *format, va_list argptr);
> +#endif /* !ACE_HAS_VASWPRINTF */
> +#endif /* ACE_HAS_WCHAR */
> +
> } /* namespace ACE_OS */
>
> ACE_END_VERSIONED_NAMESPACE_DECL
> Index: OS_NS_stdio.inl
> ===================================================================
> --- OS_NS_stdio.inl (revision 79869)
> +++ OS_NS_stdio.inl (working copy)
> @@ -949,6 +949,69 @@
> #endif /* ACE_HAS_WCHAR */
>
> ACE_INLINE int
> +ACE_OS::vasprintf (char **bufp, const char* format, va_list argptr)
> +{
> +#if defined (ACE_HAS_VASPRINTF)
> + return ::vasprintf (bufp, format, argptr);
> +#else
> + return ACE_OS::vasprintf_emulation (bufp, format, argptr);
> +#endif /* ACE_HAS_VASPRINTF */
> +}
> +
> +#if defined (ACE_HAS_WCHAR)
> +ACE_INLINE int
> +ACE_OS::vasprintf (wchar_t **bufp, const wchar_t* format,
> va_list argptr)
> +{
> +#if defined (ACE_HAS_VASWPRINTF)
> + return ::vaswprintf (bufp, format, argptr);
> +#else
> + return ACE_OS::vaswprintf_emulation (bufp, format, argptr);
> +#endif /* ACE_HAS_VASWPRINTF */
> +}
> +#endif /* ACE_HAS_WCHAR */
> +
> +ACE_INLINE int
> +ACE_OS::vprintf (const char *format, va_list argptr)
> +{
> + return ::vprintf (format, argptr);
> +}
> +
> +#if defined (ACE_HAS_WCHAR)
> +ACE_INLINE int
> +ACE_OS::vprintf (const wchar_t *format, va_list argptr)
> +{
> +#if defined (ACE_HAS_VWPRINTF)
> + return ::vwprintf (format, argptr);
> +#else
> + ACE_UNUSED_ARG (format);
> + ACE_UNUSED_ARG (argptr);
> + ACE_NOTSUP_RETURN (-1);
> +#endif /* ACE_HAS_VWPRINTF */
> +}
> +#endif /* ACE_HAS_WCHAR */
> +
> +ACE_INLINE int
> +ACE_OS::vfprintf (FILE *fp, const char *format, va_list argptr)
> +{
> + return ::vfprintf (fp, format, argptr);
> +}
> +
> +#if defined (ACE_HAS_WCHAR)
> +ACE_INLINE int
> +ACE_OS::vfprintf (FILE *fp, const wchar_t *format, va_list argptr)
> +{
> +#if defined (ACE_HAS_VFWPRINTF)
> + return ::vfwprintf (fp, format, argptr);
> +#else
> + ACE_UNUSED_ARG (fp);
> + ACE_UNUSED_ARG (format);
> + ACE_UNUSED_ARG (argptr);
> + ACE_NOTSUP_RETURN (-1);
> +#endif /* ACE_HAS_VFWPRINTF */
> +}
> +#endif /* ACE_HAS_WCHAR */
> +
> +ACE_INLINE int
> ACE_OS::vsprintf (char *buffer, const char *format, va_list argptr)
> {
> return ::vsprintf (buffer, format, argptr);
>
>
> --
> J.T. Conklin
>
> _______________________________________________
> ace-users mailing list
> ace-users at mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users
>
More information about the Ace-users
mailing list