blob: 7fb22fe6b88a5e715123566d697f9b9228164435 [file] [log] [blame]
/***************************************************************************
*
* punct.cpp
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2001-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#define _RWSTD_LIB_SRC
#include <rw/_defs.h>
#include <locale.h> // for lconv, localeconv(), setlocale()
#include <stdio.h> // for sprintf()
#include <stdlib.h> // for mbstowcs()
#include <string.h> // for memcpy()
#include <ios> // for ios_base, needed by <rw/_punct.h>
#include <memory> // for operator new() and delete()
#include "access.h"
#include <loc/_localedef.h>
#include <loc/_moneypunct.h>
#include <loc/_numpunct.h>
#include <rw/_error.h>
#include "setlocale.h"
#include "punct.h"
#if defined (_RWSTD_MSVC) && defined (_WIN64)
// shut up MSVC/Win64 complaints about possible loss of data
# pragma warning (disable: 4244)
#endif // MSVC/Win64
_RWSTD_NAMESPACE (__rw) {
static inline void
__rw_copy (void *dst, const void *src, size_t n)
{
memcpy (dst, src, n);
}
static inline void
__rw_widen (void *dst, const void *src, size_t n)
{
mbstowcs (_RWSTD_STATIC_CAST (wchar_t*, dst),
_RWSTD_STATIC_CAST (const char*, src), n);
}
static const void*
__rw_get_numpunct (const __rw_facet *pfacet, int flags)
{
const int member = flags & ~(__rw_mon | __rw_wide | __rw_intl);
const bool winx = !!(flags & __rw_wide); // wide or narrow index
const void *pdata = pfacet->_C_data (); // mapped locale database
if (pdata) {
const __rw_punct_t* const pun =
_RWSTD_STATIC_CAST (const __rw_punct_t*, pdata);
const __rw_num_t *num;
switch (member) {
case __rw_dp: return pun->decimal_point (winx);
case __rw_ts: return pun->thousands_sep (winx);
case __rw_gr: return pun->grouping ();
case __rw_tn:
num = _RWSTD_STATIC_CAST (const __rw_num_t*, pun->get_ext ());
_RWSTD_ASSERT (num);
return num->truename (winx);
case __rw_fn:
num = _RWSTD_STATIC_CAST (const __rw_num_t*, pun->get_ext ());
_RWSTD_ASSERT (num);
return num->falsename (winx);
default: _RWSTD_ASSERT (!"bad discriminant");
}
return 0;
}
else if (0 == __rw_access::_C_get_name (*pfacet)) { // "C" locale
static const void* const cdata[] = {
".", L".", ",", L",", "", L"", "true", L"true", "false", L"false"
};
switch (member) {
case __rw_dp: return cdata [0 + winx]; // 22.2.3.1.2, p1
case __rw_ts: return cdata [2 + winx]; // 22.2.3.1.2, p2
case __rw_gr: return cdata [4 + winx]; // 22.2.3.1.2, p3
case __rw_tn: return cdata [6 + winx]; // 22.2.3.1.2, p4
case __rw_fn: return cdata [8 + winx];
default: _RWSTD_ASSERT (!"bad discriminant");
}
return 0;
}
const char* const locname = __rw_access::_C_get_name (*pfacet) ?
__rw_access::_C_get_name (*pfacet) : "C";
// set all categories -- need LC_NUMERIC and LC_CTYPE
const __rw_setlocale clocale (locname, _RWSTD_LC_ALL);
if (pfacet->_C_data ()) {
// check to see if another thread may have set _C_data()
// while we were waiting for the lock in __rw_setlocale
// ctor above and, if so, call self recursively on the
// already initialized `impdata'
return __rw_get_numpunct (pfacet, flags);
}
// get the lconv data
const lconv* const pconv = localeconv ();
if (!pconv)
__rw_throw (_RWSTD_ERROR_LOCALE_BAD_NAME, locname);
// be prepared to handle (non-conforming) null pointers
// (e.g., AIX -- see bug #558)
const char* const grp = pconv->grouping ? pconv->grouping : "";
const char* const dp = pconv->decimal_point ? pconv->decimal_point : "";
const char* const ts = pconv->thousands_sep ? pconv->thousands_sep : "";
// the size of the narrow grouping string in bytes
const size_t grsz = strlen (grp) + 1;
// compute the sizes of all members in bytes
size_t dpsz = strlen (dp) + 1;
size_t tssz = strlen (ts) + 1;
size_t tnsz = sizeof "true";
size_t fnsz = sizeof "false";
if (winx) {
// adjust for wide characters
dpsz *= sizeof (wchar_t);
tssz *= sizeof (wchar_t);
tnsz *= sizeof (wchar_t);
fnsz *= sizeof (wchar_t);
}
// compute the actual size of the variable size structure
const size_t size =
sizeof (__rw_punct_t)
+ sizeof (__rw_num_t)
+ sizeof (size_t) // maximum padding for alignment
+ grsz + dpsz + tssz + tnsz + fnsz;
// allocate variable size structure(s)
__rw_punct_t* const pun =
_RWSTD_STATIC_CAST (__rw_punct_t*, ::operator new (size));
// compute offsets into the varaiable size structure
pun->decimal_point_off [winx] = 0;
pun->thousands_sep_off [winx] = pun->decimal_point_off [winx] + int (dpsz);
// point widen to a wrapper for mbstowcs() for wchar_t or memcpy otherwise
void (*widen)(void*, const void*, size_t) =
winx ? __rw_widen : __rw_copy;
// copy strings from lconv data members to the varaiable size structure
char* s = _RWSTD_REINTERPRET_CAST (char*, pun + 1);
widen (s + pun->decimal_point_off [winx], dp, dpsz);
widen (s + pun->thousands_sep_off [winx], ts, tssz);
// set the offset of the extended punctuation data
pun->punct_ext_off = pun->thousands_sep_off [winx] + int (tssz);
// adjust alignment
const size_t misalign = pun->punct_ext_off % sizeof (size_t);
if (misalign)
pun->punct_ext_off += int (sizeof (size_t) - misalign);
s = _RWSTD_REINTERPRET_CAST (char*, pun + 1) + pun->punct_ext_off;
__rw_num_t* const num = _RWSTD_REINTERPRET_CAST (__rw_num_t*, s);
s += sizeof *num;
// invalidate members (offsets) by setting them to 0xff
memset (num, ~0, sizeof *num);
num->truename_off [winx] = 0;
num->falsename_off [winx] = num->truename_off [winx] + int (tnsz);
widen (s + num->truename_off [winx], "true", tnsz);
widen (s + num->falsename_off [winx], "false", fnsz);
// place narrow grouping string last to avoid alignment issues
pun->grouping_off =
_RWSTD_STATIC_CAST (_RWSTD_UINT32_T,
pun->punct_ext_off + sizeof *num + num->falsename_off [winx] + fnsz);
memcpy (s + num->falsename_off [winx] + fnsz, grp, grsz);
// set `impdata' and `impsize' (facet base dtor will delete)
__rw_access::_C_get_impdata (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
pun;
__rw_access::_C_get_impsize (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
(size_t)(-1);
// call self recursively on already initialized `impdata'
return __rw_get_numpunct (pfacet, flags);
}
/***************************************************************************/
static const void*
__rw_get_moneypunct (const __rw_facet *pfacet, int flags)
{
const int member = flags & ~(__rw_mon | __rw_wide | __rw_intl);
const bool winx = !!(flags & __rw_wide); // wide or narrow index
const bool intl = !!(flags & __rw_intl); // international or domestic
const void *pdata = pfacet->_C_data (); // mapped locale database
if (pdata) {
const __rw_punct_t* const pun =
_RWSTD_STATIC_CAST (const __rw_punct_t*, pdata);
const __rw_mon_t *mon;
switch (member) {
case __rw_dp: return pun->decimal_point (winx);
case __rw_ts: return pun->thousands_sep (winx);
case __rw_gr: return pun->grouping ();
}
// get extended data
mon = _RWSTD_STATIC_CAST (const __rw_mon_t*, pun->get_ext ());
_RWSTD_ASSERT (mon);
typedef unsigned char UChar;
switch (member) {
case __rw_cs: return mon->curr_symbol (intl, winx);
case __rw_ps: return mon->positive_sign (winx);
case __rw_ns: return mon->negative_sign (winx);
case __rw_pf: return mon->pos_format [intl];
case __rw_nf: return mon->neg_format [intl];
case __rw_fd:
return _RWSTD_REINTERPRET_CAST (void*, (size_t)
UChar (mon->frac_digits [intl]));
default: _RWSTD_ASSERT (!"bad discriminant");
}
return 0;
}
else if (0 == __rw_access::_C_get_name (*pfacet)) { // "C" locale
static const void* const cdata[] = {
".", L".", ",", L",", "", L"", "", L"", "", L"",
"", L"", "", L"", "\2\3\0\4", "\2\3\0\4",
};
switch (member) {
case __rw_dp: return cdata [0 + winx];
case __rw_ts: return cdata [2 + winx];
case __rw_gr: return cdata [4 + winx];
case __rw_cs: return cdata [6 + winx + 2 * intl];
case __rw_ps: return cdata [10 + winx];
case __rw_ns: return cdata [12 + winx];
case __rw_pf: return cdata [14];
case __rw_nf: return cdata [15];
// the number of fractional digits in the "C" locale is not specified
case __rw_fd: return 0; // no fractional digits
default: _RWSTD_ASSERT (!"bad discriminant");
}
return 0;
}
const char* const locname = __rw_access::_C_get_name (*pfacet) ?
__rw_access::_C_get_name (*pfacet) : "C";
// set all categories -- need LC_NUMERIC and LC_CTYPE
const __rw_setlocale clocale (locname, _RWSTD_LC_ALL);
if (pfacet->_C_data ()) {
// check to see if another thread may have set _C_data()
// while we were waiting for the lock in __rw_setlocale
// ctor above and, if so, call self recursively on the
// already initialized `impdata'
return __rw_get_moneypunct (pfacet, flags);
}
// get the lconv data
const lconv* const pconv = localeconv ();
if (!pconv)
__rw_throw (_RWSTD_ERROR_LOCALE_BAD_NAME, locname);
_RWSTD_ASSERT (pconv->mon_grouping);
_RWSTD_ASSERT (pconv->mon_decimal_point);
_RWSTD_ASSERT (pconv->mon_thousands_sep);
// the size of the narrow grouping string in bytes
const size_t grsz = strlen (pconv->mon_grouping) + 1;
// compute the sizes of all members in bytes
size_t dpsz = strlen (pconv->mon_decimal_point) + 1;
size_t tssz = strlen (pconv->mon_thousands_sep) + 1;
size_t pssz = strlen (pconv->positive_sign) + 1;
size_t nssz = strlen (pconv->negative_sign) + 1;
const char* const cs = intl ? pconv->int_curr_symbol
: pconv->currency_symbol;
size_t cssz = strlen (cs) + 1;
if (winx) {
// adjust for wide characters
dpsz *= sizeof (wchar_t);
tssz *= sizeof (wchar_t);
pssz *= sizeof (wchar_t);
nssz *= sizeof (wchar_t);
cssz *= sizeof (wchar_t);
}
// compute the actual size of the variable size structure
const size_t size =
sizeof (__rw_punct_t)
+ sizeof (__rw_mon_t)
+ sizeof (size_t) // maximum padding for alignment
+ grsz + dpsz + tssz + pssz + nssz + cssz;
// allocate variable size structure(s)
__rw_punct_t* const pun =
_RWSTD_STATIC_CAST (__rw_punct_t*, ::operator new (size));
// compute offsets into the varaiable size structure
pun->decimal_point_off [winx] = 0;
pun->thousands_sep_off [winx] = pun->decimal_point_off [winx] + int (dpsz);
// point widen to a wrapper for mbstowcs() for wchar_t or memcpy otherwise
void (*widen)(void*, const void*, size_t) =
winx ? __rw_widen : __rw_copy;
// copy strings from lconv data members to the varaiable size structure
char* s = _RWSTD_REINTERPRET_CAST (char*, pun + 1);
widen (s + pun->decimal_point_off [winx], pconv->mon_decimal_point, dpsz);
widen (s + pun->thousands_sep_off [winx], pconv->mon_thousands_sep, tssz);
// set the offset of the extended punctuation data
pun->punct_ext_off = pun->thousands_sep_off [winx] + int (tssz);
// adjust alignment
const size_t misalign = pun->punct_ext_off % sizeof (size_t);
if (misalign)
pun->punct_ext_off += int (sizeof (size_t) - misalign);
s = _RWSTD_REINTERPRET_CAST (char*, pun + 1) + pun->punct_ext_off;
__rw_mon_t* const mon = _RWSTD_REINTERPRET_CAST (__rw_mon_t*, s);
s += sizeof *mon;
// invalidate members (offsets) by setting them to 0xff
memset (mon, ~0, sizeof *mon);
mon->positive_sign_off [winx] = 0;
mon->negative_sign_off [winx] = mon->positive_sign_off [winx] + int (pssz);
widen (s + mon->positive_sign_off [winx], pconv->positive_sign, pssz);
widen (s + mon->negative_sign_off [winx], pconv->negative_sign, nssz);
mon->curr_symbol_off [intl][winx] =
mon->negative_sign_off [winx] + int (nssz);
widen (s + mon->curr_symbol_off [intl][winx], cs, cssz);
pun->grouping_off =
_RWSTD_STATIC_CAST (_RWSTD_UINT32_T,
pun->punct_ext_off + sizeof *mon
+ mon->curr_symbol_off [intl][winx] + cssz);
// place narrow grouping string last to avoid alignment issues
memcpy (s + mon->curr_symbol_off [intl][winx] + cssz,
pconv->mon_grouping, grsz);
mon->frac_digits [0] = pconv->frac_digits;
mon->frac_digits [1] = pconv->int_frac_digits;
// initialize domestic C90 formats
mon->p_cs_precedes [0] = pconv->p_cs_precedes;
mon->n_cs_precedes [0] = pconv->n_cs_precedes;
mon->p_sep_by_space [0] = pconv->p_sep_by_space;
mon->n_sep_by_space [0] = pconv->n_sep_by_space;
mon->p_sign_posn [0] = pconv->p_sign_posn;
mon->n_sign_posn [0] = pconv->n_sign_posn;
#ifndef _RWSTD_NO_LCONV_INT_FMAT
// copy international formats from C99 members
mon->p_cs_precedes [1] = pconv->int_p_cs_precedes;
mon->n_cs_precedes [1] = pconv->int_n_cs_precedes;
mon->p_sep_by_space [1] = pconv->int_p_sep_by_space;
mon->n_sep_by_space [1] = pconv->int_n_sep_by_space;
mon->p_sign_posn [1] = pconv->int_p_sign_posn;
mon->n_sign_posn [1] = pconv->int_n_sign_posn;
#else // if defined (_RWSTD_NO_LCONV_INT_FMAT)
// copy international formats from local members
mon->p_cs_precedes [1] = mon->p_cs_precedes [0];
mon->n_cs_precedes [1] = mon->n_cs_precedes [0];
mon->p_sep_by_space [1] = mon->p_sep_by_space [0];
mon->n_sep_by_space [1] = mon->n_sep_by_space [0];
mon->p_sign_posn [1] = mon->p_sign_posn [0];
mon->n_sign_posn [1] = mon->n_sign_posn [0];
#endif // _RWSTD_NO_LCONV_INT_FMAT
enum {
// for syntactic convenience
none = _STD::money_base::none,
space = _STD::money_base::space,
symbol = _STD::money_base::symbol,
sign = _STD::money_base::sign,
value = _STD::money_base::value
};
static const _STD::money_base::pattern pat[] = {
// cs_precedes [0..1]:
//
// An integer set to 1 if the currency_symbol precedes the value
// for a monetary value, and set to 0 if the symbol succeeds
// the value.
// sep_by_space [0..2]:
//
// 0 No space separates the currency_symbol from the value for
// a monetary value.
// 1 If the currency symbol and sign string are adjacent, a space
// separates them from the value; otherwise, a space separates
// the currency symbol from the value.
// 2 If the currency symbol and sign string are adjacent, a space
// separates them; otherwise, a space separates the sign string
// from the value.
// sign_posn [0..4]:
//
// An integer set to a value indicating the positioning of the
// positive_sign for a monetary value. The following integer
// values shall be recognized:
//
// 0 Parentheses enclose the value and the currency_symbol.
// 1 The sign string precedes the value and the currency_symbol.
// 2 The sign string succeeds the value and the currency_symbol.
// 3 The sign string immediately precedes the currency_symbol.
// 4 The sign string immediately succeeds the currency_symbol.
// +-------- cs_precedes
// |+----- sep_by_space
// ||+-- sign_posn
// |||
// VVV .... - 1 $ . // pattern
/* 000: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
/* 001: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
/* 002: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
/* 003: 1-$. */ { { value, sign, symbol, none } }, // "\4\3\2\0"
/* 004: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
/* 010: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
/* 011: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
/* 012: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
/* 013: 1 -$ */ { { value, space, sign, symbol } }, // "\4\3\3\2"
/* 014: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
/* 020: - 1$ */ { { sign, space, value, symbol } }, // "\3\1\4\2"
/* 021: - 1$ */ { { sign, space, value, symbol } }, // "\3\1\4\2"
/* 022: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
/* 023: 1- $ */ { { value, sign, space, symbol } }, // "\4\3\1\2"
/* 024: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
/* 100: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
/* 101: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
/* 102: $1-. */ { { symbol, value, sign, none } }, // "\2\4\3\0"
/* 103: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
/* 104: $-1. */ { { symbol, sign, value, none } }, // "\2\3\4\0"
/* 110: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
/* 111: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
/* 112: $ 1- */ { { symbol, space, value, sign } }, // "\2\1\4\3"
/* 113: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
/* 114: $- 1 */ { { symbol, sign, space, value } }, // "\2\3\1\4"
/* 120: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
/* 121: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
/* 122: $1 - */ { { symbol, value, space, sign } }, // "\2\4\1\3"
/* 123: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
/* 124: $ -1 */ { { symbol, space, sign, value } } // "\2\1\3\4"
};
size_t inx = size_t (mon->p_cs_precedes [intl]) * (3U * 5U)
+ size_t (mon->p_sep_by_space [intl]) * 5U
+ size_t (mon->p_sign_posn [intl]);
if (inx < sizeof pat / sizeof *pat)
memcpy (mon->pos_format [intl], pat + inx, sizeof *pat);
else
memset (mon->pos_format [intl], none, sizeof *pat);
inx = size_t (mon->n_cs_precedes [intl]) * (3U * 5U)
+ size_t (mon->n_sep_by_space [intl]) * 5U
+ size_t (mon->n_sign_posn [intl]);
if (inx < sizeof pat / sizeof *pat)
memcpy (mon->neg_format [intl], pat + inx, sizeof *pat);
else
memset (mon->neg_format [intl], none, sizeof *pat);
// set `impdata' and `impsize' (facet base dtor will delete)
__rw_access::_C_get_impdata (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
pun;
__rw_access::_C_get_impsize(*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
(size_t)(-1);
// call self recursively on already initialized `impdata'
return __rw_get_moneypunct (pfacet, flags);
}
/***************************************************************************/
/* _RWSTD_SPECIALIZED_FUNCTION */ _RWSTD_EXPORT
const char*
__rw_get_punct(const __rw_facet *pfacet, int flags, char)
{
typedef const char *CPChar;
if (flags & __rw_mon)
return CPChar (__rw_get_moneypunct (pfacet, flags & ~__rw_mon));
return CPChar (__rw_get_numpunct (pfacet, flags));
}
#ifndef _RWSTD_NO_WCHAR_T
/* _RWSTD_SPECIALIZED_FUNCTION */ _RWSTD_EXPORT
const wchar_t*
__rw_get_punct(const __rw_facet *pfacet, int flags, wchar_t)
{
flags |= __rw_wide;
typedef const wchar_t *CPWChar;
if (flags & __rw_mon)
return CPWChar (__rw_get_moneypunct (pfacet, flags & ~__rw_mon));
return CPWChar (__rw_get_numpunct (pfacet, flags));
}
#endif // _RWSTD_NO_WCHAR_T
const char*
__rw_get_stdio_fmat (char buf [32], int type, unsigned fmtflags,
_RWSTD_STREAMSIZE prec)
{
char *pbuf = buf;
// format of the specifier:
// "%[+][#](.[0-9]*)(h|l|L|LL)(o|x|X|i|d|e|E|f|F|g|G|p)"
*pbuf++ = '%';
if (fmtflags & _RWSTD_IOS_SHOWPOS)
*pbuf++ = '+';
if (type & __rw_facet::_C_floating) {
if (fmtflags & _RWSTD_IOS_SHOWPOINT)
*pbuf++ = '#';
// follows resolution of lwg issue 231
if (0 <= prec) {
// 7.19.6.1, p5 of C99 specifies that, when given using the
// asterisk, negative precision is treated the same as if
// it were omitted; treat negative precision the same here
pbuf += sprintf (pbuf, ".%ld", long (prec));
}
}
else if (fmtflags & _RWSTD_IOS_SHOWBASE)
*pbuf++ = '#';
enum {
// for convenience
Short = __rw_facet::_C_ushort & __rw_facet::_C_typemask,
Long = __rw_facet::_C_ulong & __rw_facet::_C_typemask,
LLong = __rw_facet::_C_ullong & __rw_facet::_C_typemask,
Double = __rw_facet::_C_double & __rw_facet::_C_typemask,
LDouble = __rw_facet::_C_ldouble & __rw_facet::_C_typemask
};
const int basetype = type & __rw_facet::_C_typemask;
switch (basetype) {
case Short: *pbuf++ = 'h'; break;
case Long:
case Double:
*pbuf++ = 'l';
break;
case LDouble: *pbuf++ = 'L'; break;
case LLong:
#ifdef _RWSTD_LLONG_PRINTF_PREFIX
memcpy (pbuf, _RWSTD_LLONG_PRINTF_PREFIX,
sizeof _RWSTD_LLONG_PRINTF_PREFIX - 1);
pbuf += sizeof _RWSTD_LLONG_PRINTF_PREFIX - 1;
#else
_RWSTD_ASSERT (!"long long printf prefix not configured");
#endif // _RWSTD_LLONG_PRINTF_PREFIX
break;
}
if (type & __rw_facet::_C_floating) {
switch (fmtflags & _RWSTD_IOS_FLOATFIELD) {
case _RWSTD_IOS_FIXED:
*pbuf++ = 'f';
break;
case _RWSTD_IOS_SCIENTIFIC:
*pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'E' : 'e';
break;
default:
*pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'G' : 'g';
}
}
else if (type == __rw_facet::_C_pvoid)
*pbuf++ = 'p';
else if (type == __rw_facet::_C_bool && fmtflags & _RWSTD_IOS_BOOLALPHA)
--pbuf; // empty format indicates bool
else {
switch (fmtflags & _RWSTD_IOS_BASEFIELD) {
case _RWSTD_IOS_OCT: *pbuf++ = 'o'; break;
case _RWSTD_IOS_DEC: *pbuf++ = 'd'; break;
case _RWSTD_IOS_HEX:
*pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'X' : 'x';
break;
default:
*pbuf++ = 'i';
}
}
*pbuf++ = '\0';
_RWSTD_ASSERT (pbuf - buf < 32);
return buf;
}
} // namespace __rw