Author: sebor
Date: Tue Aug 14 17:53:01 2007
New Revision: 565991
URL: http://svn.apache.org/viewvc?view=rev&rev=565991
Log:
2007-08-14 Travis Vitek <[EMAIL PROTECTED]>
* rw_locale.h (rw_locales): Added new parameter to indicate the
"C" locale should appear at the front of returned locale list.
* locale.cpp (rw_locales): Added support for new parameter.
* testdefs.h: Added convenience macro RW_COUNT_OF that can beused
to get the number of elements in an array.
* 22.locale.money.put.mt.cpp (MyIos, MyStreambuf, MyMoneyData):
Added structures to simplify testing.
(run_test): Build a table of in/outptus for verification in test
threads.
(thread_func): Assert the data written matches expected.
(main): Add support for --nlocales and --shared-locale command
line arguments
* 22.locale.num.put.mt.cpp (MyIos, MyStreambuf, MyNumData): Added
structures to simplify testing.
(run_test): Build a table of in/outptus for verification in test
threads.
(thread_func): Assert the data written matches expected.
(main): Add support for --nlocales and --shared-locale command
line arguments
* 22.locale.time.put.mt.cpp (run_test, thread_func): Use macro
RW_COUNT_OF. Remove "C" locale fallback. Eliminate unnecessary
rdbuf() calls.
Modified:
incubator/stdcxx/trunk/tests/include/rw_locale.h
incubator/stdcxx/trunk/tests/include/testdefs.h
incubator/stdcxx/trunk/tests/localization/22.locale.money.put.mt.cpp
incubator/stdcxx/trunk/tests/localization/22.locale.num.put.mt.cpp
incubator/stdcxx/trunk/tests/localization/22.locale.time.put.mt.cpp
incubator/stdcxx/trunk/tests/src/locale.cpp
Modified: incubator/stdcxx/trunk/tests/include/rw_locale.h
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/rw_locale.h?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/include/rw_locale.h (original)
+++ incubator/stdcxx/trunk/tests/include/rw_locale.h Tue Aug 14 17:53:01 2007
@@ -37,7 +37,7 @@
_TEST_EXPORT char*
-rw_locales (int = _UNUSED_CAT, const char* = 0);
+rw_locales (int = _UNUSED_CAT, const char* = 0, bool = true);
// invokes the locale utility with the arguments specified by 'arg',
Modified: incubator/stdcxx/trunk/tests/include/testdefs.h
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/testdefs.h?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/include/testdefs.h (original)
+++ incubator/stdcxx/trunk/tests/include/testdefs.h Tue Aug 14 17:53:01 2007
@@ -6,22 +6,25 @@
*
***************************************************************************
*
- * Copyright 2005-2006 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Copyright 2003-2006 Rogue Wave Software.
- *
- * Licensed 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
+ * 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
+ * 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.
+ * 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 2005-2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2003-2007 Rogue Wave Software.
*
**************************************************************************/
@@ -161,5 +164,7 @@
((expr) ? (void)0 : _RW::__rw_assert_fail (#expr, __FILE__, __LINE__, 0))
#endif // _RWSTD_NO_PRETTY_FUNCTION, _RWSTD_NO_FUNC
+// convenience macro to get number of elements in a c style array
+#define RW_COUNT_OF(x) (sizeof(x) / sizeof(*x))
#endif // RW_TESTDEFS_H_INCLUDED
Modified: incubator/stdcxx/trunk/tests/localization/22.locale.money.put.mt.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.money.put.mt.cpp?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.money.put.mt.cpp
(original)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.money.put.mt.cpp Tue
Aug 14 17:53:01 2007
@@ -35,10 +35,12 @@
#include <rw_locale.h>
#include <rw_thread.h>
#include <driver.h>
+#include <valcmp.h> // for rw_strncmp ()
// maximum number of threads allowed by the command line interface
-#define MAX_THREADS 32
+#define MAX_THREADS 32
+#define MAX_LOOPS 100000
// default number of threads (will be adjusted to the number
// of processors/cores later)
@@ -48,6 +50,13 @@
// otherwise on the command line)
int rw_opt_nloops = 100000;
+// number of locales to use
+int rw_opt_nlocales = MAX_THREADS;
+
+// should all threads share the same set of locale objects instead
+// of creating their own?
+int rw_opt_shared_locale;
+
/**************************************************************************/
// array of locale names to use for testing
@@ -60,6 +69,88 @@
/**************************************************************************/
+static const char n_money_vals[][20] = {
+ "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678",
+ "-9", "-98", "-987", "-9876", "-98765", "-987654", "-9876543",
+ "1.9", "-12.89", "123.789", "-1234.6789", "-12345.56789"
+};
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+static const wchar_t w_money_vals[][20] = {
+ L"1", L"12", L"123", L"1234", L"12345", L"123456", L"1234567",
+ L"-9", L"-98", L"-987", L"-9876", L"-98765", L"-987654", L"-9876543",
+ L"1.9", L"-12.89", L"123.789", L"-1234.6789", L"-12345.56789"
+};
+
+#endif // _RWSTD_NO_WCHAR_T
+
+//
+struct MyMoneyData
+{
+ enum { BufferSize = 16 };
+
+ enum PutId {
+ put_ldbl,
+ put_string,
+ put_max
+ };
+
+ // name of the locale the data corresponds to
+ const char* locale_name_;
+
+ // optionally set to the named locale for threads to share
+ std::locale locale_;
+
+ // international or domestic format flag
+ bool intl_;
+
+ // the time struct used to generate strings below
+ double money_value_;
+
+ // type of the data we created string from
+ PutId type_;
+
+ // index into string array [n,w]_money_vals
+ unsigned money_index_;
+
+ // narrow representations of money_
+ char ncs_ [BufferSize];
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+ // wide representations of money_
+ wchar_t wcs_ [BufferSize];
+
+#endif // _RWSTD_NO_WCHAR_T
+
+} my_money_data [MAX_THREADS];
+
+
+template <class charT, class Traits>
+struct MyIos: std::basic_ios<charT, Traits>
+{
+ MyIos () {
+ this->init (0);
+ }
+};
+
+
+template <class charT, class Traits>
+struct MyStreambuf: std::basic_streambuf<charT, Traits>
+{
+ typedef std::basic_streambuf<charT, Traits> Base;
+
+ MyStreambuf ()
+ : Base () {
+ }
+
+ void pubsetp (charT *pbeg, std::streamsize n) {
+ this->setp (pbeg, pbeg + n);
+ }
+};
+
+
extern "C" {
bool test_char; // exercise money_put<char>
@@ -69,88 +160,57 @@
static void*
thread_func (void*)
{
- // dummy streambuf-derived object the doesn't do anything
- // but allows ostreambuf_iterator to "think" it can write
- // to it
- struct NarrowBuf: std::streambuf {
- int_type overflow (int_type c) { return c; }
- } sb;
-
- const char str_vals[][20] = {
- "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678",
- "-9", "-98", "-987", "-9876", "-98765", "-987654", "-9876543",
- "1.9", "-12.89", "123.789", "-1234.6789", "-12345.56789"
- };
+ char ncs [MyMoneyData::BufferSize];
+ MyIos<char, std::char_traits<char> > nio;
+ MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
#ifndef _RWSTD_NO_WCHAR_T
-
- struct WideBuf: std::wstreambuf {
- int_type overflow (int_type c) { return c; }
- } wb;
-
- const wchar_t wstr_vals[][20] = {
- L"1", L"12", L"123", L"1234", L"12345", L"123456", L"1234567",
- L"-9", L"-98", L"-987", L"-9876", L"-98765", L"-987654", L"-9876543",
- L"1.9", L"-12.89", L"123.789", L"-1234.6789", L"-12345.56789"
- };
-
-#endif // _RWSTD_NO_WCHAR_T
-
- struct Ios: std::ios {
- Ios () { this->init (0); }
- } io;
+ wchar_t wcs [MyMoneyData::BufferSize];
+ MyIos<wchar_t, std::char_traits<wchar_t> > wio;
+ MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
for (int i = 0; i != rw_opt_nloops; ++i) {
// save the name of the locale
- const char* const locale_name = locales [i % nlocales];
+ const MyMoneyData& data = my_money_data [i % nlocales];
- // construct a named locale and imbue it in the ios object
- // so that the locale is used not only by the money_put facet
- // but also by the numpunct facet
- const std::locale loc (locale_name);
- io.imbue (loc);
-
- enum PutId {
- put_ldbl,
- put_string,
- put_max
- };
-
- io.width (i % 16);
-
- // exercise postive and negative values
- long double ldval = i & 1 ? -i : i;
-
- // add some random fractional digits
- if (i & 2)
- ldval += ldval / 3.14;
-
- // exercise domestic formats every other iteration
- // and international formats the rest
- const bool intl = 0 == (i & 1);
+ // construct a named locale, get a reference to the money_put
+ // facet from it and use it to format a random money value
+ const std::locale loc =
+ rw_opt_shared_locale ? data.locale_
+ : std::locale (data.locale_name_);
if (test_char) {
// exercise the narrow char specialization of the facet
- const std::money_put<char> &mp =
+ const std::money_put<char> &np =
std::use_facet<std::money_put<char> >(loc);
- const std::ostreambuf_iterator<char> iter (&sb);
+ nio.imbue (loc);
+ nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
- switch (i % put_max) {
- case put_ldbl:
- mp.put (iter, intl, io, ' ', ldval);
+ switch (data.type_) {
+ case MyMoneyData::put_ldbl:
+ *np.put (std::ostreambuf_iterator<char>(&nsb),
+ data.intl_, nio, ' ', data.money_value_) = '\0';
break;
-
- case put_string: {
- const char* const strval =
- str_vals [i % sizeof str_vals / sizeof *str_vals];
-
- mp.put (iter, intl, io, ' ', strval);
+ case MyMoneyData::put_string:
+ *np.put (std::ostreambuf_iterator<char>(&nsb),
+ data.intl_, nio, ' ',
+ n_money_vals [data.money_index_]) = '\0';
+ break;
+ case MyMoneyData::put_max:
+ // avoid enumeration value `put_max' not handled in switch
+ // this case should never happen
break;
}
- }
+
+ RW_ASSERT (!nio.fail ());
+ RW_ASSERT (!rw_strncmp(ncs, data.ncs_));
+
}
// both specializations may be tested at the same time
@@ -160,25 +220,31 @@
#ifndef _RWSTD_NO_WCHAR_T
- const std::money_put<wchar_t> &mp =
+ const std::money_put<wchar_t> &wp =
std::use_facet<std::money_put<wchar_t> >(loc);
- const std::ostreambuf_iterator<wchar_t> iter (&wb);
+ wio.imbue (loc);
+ wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
- switch (i % put_max) {
- case put_ldbl:
- mp.put (iter, intl, io, ' ', ldval);
+ switch (data.type_) {
+ case MyMoneyData::put_ldbl:
+ *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+ data.intl_, wio, ' ', data.money_value_) = L'\0';
break;
-
- case put_string: {
- const wchar_t* const strval =
- wstr_vals [i % sizeof wstr_vals / sizeof *wstr_vals];
-
- mp.put (iter, intl, io, ' ', strval);
+ case MyMoneyData::put_string:
+ *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+ data.intl_, wio, ' ',
+ w_money_vals [data.money_index_]) = L'\0';
+ break;
+ case MyMoneyData::put_max:
+ // avoid enumeration value `put_max' not handled in switch
+ // this case should never happen
break;
- }
}
+ RW_ASSERT (!wio.fail ());
+ RW_ASSERT (!rw_strncmp(wcs, data.wcs_));
+
#endif // _RWSTD_NO_WCHAR_T
}
@@ -194,25 +260,137 @@
static int
run_test (int, char**)
{
- // find all installed locales for which setlocale(LC_ALL) succeeds
+ MyIos<char, std::char_traits<char> > nio;
+ MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
+
+#ifndef _RWSTD_NO_WCHAR_T
+ MyIos<wchar_t, std::char_traits<wchar_t> > wio;
+ MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
+
+ // find all installed locales for which setlocale (LC_ALL) succeeds
const char* const locale_list =
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
- const std::size_t maxinx = sizeof locales / sizeof *locales;
+ const std::size_t maxinx = RW_COUNT_OF (locales);
+
+ for (const char* name = locale_list;
+ *name;
+ name += std::strlen (name) + 1) {
+
+ const std::size_t inx = nlocales;
+ locales [inx] = name;
+
+ // fill in the money and results for this locale
+ MyMoneyData& data = my_money_data [inx];
+ data.locale_name_ = name;
+
+ try {
+ const std::locale loc (data.locale_name_);
+
+ // initialize with random but valid values
+
+ data.money_value_ = inx;
+ data.type_ = MyMoneyData::PutId(nlocales % MyMoneyData::put_max);
+ data.money_index_ = inx % RW_COUNT_OF (n_money_vals);
+
+ // exercise domestic formats every other iteration
+ // and international formats the rest
+ data.intl_ = 0 == (inx & 1);
+
+ // exercise postive and negative values
+ if (inx & 1)
+ data.money_value_ *= -1.;
+
+ // add some random fractional digits
+ if (inx & 2)
+ data.money_value_ += data.money_value_ / 3.14;
+
+ const std::money_put<char> &np =
+ std::use_facet<std::money_put<char> >(loc);
+
+ nio.imbue (loc);
+ nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
+
+ switch (data.type_) {
+ case MyMoneyData::put_ldbl:
+ *np.put (std::ostreambuf_iterator<char>(&nsb),
+ data.intl_, nio, ' ', data.money_value_) = '\0';
+ break;
+ case MyMoneyData::put_string:
+ *np.put (std::ostreambuf_iterator<char>(&nsb),
+ data.intl_, nio, ' ',
+ n_money_vals [data.money_index_]) = '\0';
+ break;
+ case MyMoneyData::put_max:
+ // avoid enumeration value `put_max' not handled in switch
+ // this case should never happen
+ break;
+ }
+
+ rw_assert (!nio.fail (), __FILE__, __LINE__,
+ "money_put<char>::put(...) "
+ "failed for locale(%#s)",
+ data.locale_name_);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+ const std::money_put<wchar_t> &wp =
+ std::use_facet<std::money_put<wchar_t> >(loc);
+
+ wio.imbue (loc);
+ wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
+
+ switch (data.type_) {
+ case MyMoneyData::put_ldbl:
+ *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+ data.intl_, wio, L' ', data.money_value_) = '\0';
+ break;
+ case MyMoneyData::put_string:
+ *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+ data.intl_, wio, L' ',
+ w_money_vals [data.money_index_]) = L'\0';
+ break;
+ case MyMoneyData::put_max:
+ // avoid enumeration value `put_max' not handled in switch
+ // this case should never happen
+ break;
+ }
+
+ rw_assert (!nio.fail (), __FILE__, __LINE__,
+ "money_put<wchar_t>::put(...) "
+ "failed for locale(%#s)",
+ data.locale_name_);
+
+#endif // _RWSTD_NO_WCHAR_T
- for (const char *name = locale_list; *name; name += std::strlen (name) +1)
{
- locales [nlocales++] = name;
+ if (rw_opt_shared_locale)
+ data.locale_ = loc;
- if (nlocales == maxinx)
+ nlocales += 1;
+
+ }
+ catch (...) {
+ rw_warn (!rw_opt_locales, 0, __LINE__,
+ "failed to create locale(%#s)", name);
+ }
+
+ if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
break;
}
+ // avoid divide by zero in thread if there are no locales to test
+ rw_fatal (nlocales != 0, 0, __LINE__,
+ "failed to create one or more usable locales!");
+
rw_info (0, 0, 0,
"testing std::money_put<charT> with %d thread%{?}s%{;}, "
- "%zu iteration%{?}s%{;} each, in locales { %{ [EMAIL PROTECTED]
}",
+ "%zu iteration%{?}s%{;} each, in %zu locales { %{ [EMAIL
PROTECTED] }",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops,
- int (nlocales), "%#s", locales);
+ nlocales, int (nlocales), "%#s", locales);
rw_info (0, 0, 0, "exercising std::money_put<char>");
@@ -220,7 +398,7 @@
test_wchar = false;
// create and start a pool of threads and wait for them to finish
- int result =
+ int result =
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
rw_error (result == 0, 0, __LINE__,
@@ -242,7 +420,7 @@
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
rw_opt_nthreads, thread_func);
- // exercise bothe the char and the wchar_t specializations
+ // exercise both the char and the wchar_t specializations
// at the same time
rw_info (0, 0, 0,
@@ -284,9 +462,13 @@
"thread safety", run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
- "|-locales=", // must be provided
+ "|-nlocales#0 " // arg must be non-negative
+ "|-locales= " // must be provided
+ "|-shared-locale# ",
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads,
- &rw_opt_setlocales);
+ &rw_opt_nlocales,
+ &rw_opt_setlocales,
+ &rw_opt_shared_locale);
}
Modified: incubator/stdcxx/trunk/tests/localization/22.locale.num.put.mt.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.num.put.mt.cpp?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.num.put.mt.cpp
(original)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.num.put.mt.cpp Tue Aug
14 17:53:01 2007
@@ -35,18 +35,24 @@
#include <rw_locale.h>
#include <rw_thread.h> // for rw_get_processors (), rw_thread_pool()
#include <driver.h>
+#include <valcmp.h>
-
-// maximum number of threads allowed by the command line interface
-#define MAX_THREADS 32
+#define MAX_THREADS 32
+#define MAX_LOOPS 100000
// default number of threads (will be adjusted to the number
// of processors/cores later)
int rw_opt_nthreads = 1;
-// the number of times each thread should iterate (unless specified
-// otherwise on the command line)
-int rw_opt_nloops = 200000;
+// the number of times each thread should iterate
+int rw_opt_nloops = MAX_LOOPS;
+
+// number of locales to use
+int rw_opt_nlocales = MAX_THREADS;
+
+// should all threads share the same set of locale objects instead
+// of creating their own?
+int rw_opt_shared_locale;
/**************************************************************************/
@@ -58,99 +64,177 @@
static std::size_t
nlocales;
-/**************************************************************************/
-extern "C" {
+struct MyNumData {
-bool test_char; // exercise num_put<char>
-bool test_wchar; // exercise num_put<wchar_t>
+ enum { BufferSize = 32 };
+ enum PutId {
+ put_bool,
+ put_long,
+ put_ulong,
-static void*
-thread_func (void*)
-{
- // dummy streambuf-derived object the doesn't do anything
- // but allows ostreambuf_iterator to "think" it can write
- // to it
- struct NarrowBuf: std::streambuf {
- int_type overflow (int_type c) { return c; }
- } sb;
+#ifndef _RWSTD_NO_LONG_LONG
-#ifndef _RWSTD_NO_WCHAR_T
+ put_llong,
+ put_ullong,
- struct WideBuf: std::wstreambuf {
- int_type overflow (int_type c) { return c; }
- } wb;
+#endif // _RWSTD_NO_LONG_LONG
-#endif // _RWSTD_NO_WCHAR_T
+ put_dbl,
- struct Ios: std::ios {
- Ios () { this->init (0); }
- } io;
-
- const std::ios::fmtflags baseflags[] = {
- std::ios::oct,
- std::ios::dec,
- std::ios::hex
- };
+#ifndef _RWSTD_NO_LONG_DOUBLE
- const std::ios::fmtflags fmtflags[] = {
- std::ios::showpos,
- std::ios::showpoint,
- std::ios::fixed,
- std::ios::scientific
- };
+ put_ldbl,
+
+#endif // _RWSTD_NO_LONG_DOUBLE
- const std::ios::fmtflags adjustflags[] = {
- std::ios::internal,
- std::ios::left,
- std::ios::right
+ put_ptr,
+ put_max
};
- for (int i = 0; i != rw_opt_nloops; ++i) {
+ // name of the locale the data corresponds to
+ const char* locale_name_;
- // save the name of the locale
- const char* const locale_name = locales [i % nlocales];
+ // optionally set to the named locale for threads to share
+ std::locale locale_;
- // construct a named locale and imbue it in the ios object
- // so that the locale is used not only by the num_put facet
- // but also by the numpunct facet
- const std::locale loc (locale_name);
- io.imbue (loc);
-
- enum PutId {
- put_bool,
- put_long,
- put_ulong,
+ // the value that we will be formatting
+ double value_;
+
+ // the type of the data we put
+ PutId type_;
+
+ // holds the narrow/wide character representation of value_ and
+ // the number of used 'charT' in each buffer.
+ char ncs_ [BufferSize];
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+ wchar_t wcs_ [BufferSize];
+
+#endif // _RWSTD_NO_WCHAR_T
+
+} my_num_data [MAX_THREADS];
+
+/**************************************************************************/
+
+template <class charT, class Traits>
+struct MyIos: std::basic_ios<charT, Traits>
+{
+ MyIos () {
+ this->init (0);
+ }
+};
+
+template <class charT, class Traits>
+struct MyStreambuf: std::basic_streambuf<charT, Traits>
+{
+ typedef std::basic_streambuf<charT, Traits> Base;
+
+ MyStreambuf ()
+ : Base () {
+ }
+
+ void pubsetp (charT *pbeg, std::streamsize n) {
+ this->setp (pbeg, pbeg + n);
+ }
+};
+
+template <class charT, class traitT>
+void
+put_data(const MyNumData& data,
+ const std::num_put<charT>& np,
+ const std::ostreambuf_iterator<charT>& iter,
+ std::basic_ios<charT, traitT>& io,
+ charT fill, charT term)
+{
+ switch (data.type_) {
+ case MyNumData::put_bool:
+ *np.put (iter, io, fill,
+ data.value_ < 1.f) = term;
+ break;
+ case MyNumData::put_long:
+ *np.put (iter, io, fill,
+ (long)data.value_) = term;
+ break;
+ case MyNumData::put_ulong:
+ *np.put (iter, io, fill,
+ (unsigned long)data.value_) = term;
+ break;
#ifndef _RWSTD_NO_LONG_LONG
- put_llong,
- put_ullong,
+ case MyNumData::put_llong:
+ *np.put (iter, io, fill,
+ (_RWSTD_LONG_LONG)data.value_) = term;
+ break;
+ case MyNumData::put_ullong:
+ *np.put (iter, io, fill,
+ (unsigned _RWSTD_LONG_LONG)data.value_) = term;
+ break;
#endif // _RWSTD_NO_LONG_LONG
- put_dbl,
- put_ldbl,
- put_ptr,
- put_max
- };
+ case MyNumData::put_dbl:
+ *np.put (iter, io, fill,
+ (double)data.value_) = term;
+
+ break;
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+ case MyNumData::put_ldbl:
+ *np.put (iter, io, fill,
+ (long double)data.value_) = term;
+ break;
+
+#endif // _RWSTD_NO_LONG_DOUBLE
+
+ case MyNumData::put_ptr:
+ *np.put (iter, io, fill,
+ (const void*)&data.value_) = term;
+ break;
+
+ case MyNumData::put_max:
+ // avoid enumeration value `put_max' not handled in switch
+ // this case should never happen
+ break;
+ }
- const std::ios::fmtflags base =
- baseflags [i % (sizeof baseflags / sizeof *baseflags)];
+}
- const std::ios::fmtflags fmt =
- fmtflags [i % (sizeof baseflags / sizeof *baseflags)];
+extern "C" {
- const std::ios::fmtflags adjust =
- adjustflags [i % (sizeof baseflags / sizeof *baseflags)];
+bool test_char; // exercise num_put<char>
+bool test_wchar; // exercise num_put<wchar_t>
- io.flags (base | fmt | adjust);
- io.width (i % 16);
+static void*
+thread_func (void*)
+{
+ char ncs [MyNumData::BufferSize];
+ MyIos<char, std::char_traits<char> > nio;
+ MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
+
+#ifndef _RWSTD_NO_WCHAR_T
+ wchar_t wcs [MyNumData::BufferSize];
+ MyIos<wchar_t, std::char_traits<wchar_t> > wio;
+ MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
+
+ for (int i = 0; i != rw_opt_nloops; ++i) {
- // exercise postive and negative values
- const int ival = i & 1 ? -i : i;
+ // fill in the value and results for this locale
+ const MyNumData& data = my_num_data [i % nlocales];
+
+ // construct a named locale and imbue it in the ios object
+ // so that the locale is used not only by the num_put facet
+ const std::locale loc =
+ rw_opt_shared_locale ? data.locale_
+ : std::locale (data.locale_name_);
if (test_char) {
// exercise the narrow char specialization of the facet
@@ -158,50 +242,14 @@
const std::num_put<char> &np =
std::use_facet<std::num_put<char> >(loc);
- const std::ostreambuf_iterator<char> iter (&sb);
-
- switch (i % put_max) {
- case put_bool:
- if (i & 2)
- io.setf (std::ios::boolalpha);
- else
- io.unsetf (std::ios::boolalpha);
-
- np.put (iter, io, ' ', bool (ival));
- break;
-
- case put_long:
- np.put (iter, io, ' ', long (ival));
- break;
-
- case put_ulong:
- np.put (iter, io, ' ', (unsigned long)ival);
- break;
-
-#ifndef _RWSTD_NO_LONG_LONG
+ nio.imbue (loc);
+ nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
- case put_llong:
- np.put (iter, io, ' ', (_RWSTD_LONG_LONG)ival);
- break;
+ put_data(data, np, std::ostreambuf_iterator<char>(&nsb),
+ nio, ' ', '\0');
-#endif // _RWSTD_NO_LONG_LONG
-
- case put_ullong:
- np.put (iter, io, ' ', (unsigned _RWSTD_LONG_LONG)ival);
- break;
-
- case put_dbl:
- np.put (iter, io, ' ', double (ival));
- break;
-
- case put_ldbl:
- np.put (iter, io, ' ', (long double)ival);
- break;
-
- case put_ptr:
- np.put (iter, io, ' ', (void*)ival);
- break;
- }
+ RW_ASSERT (!nio.fail ());
+ RW_ASSERT (!rw_strncmp (ncs, data.ncs_));
}
// both specializations may be tested at the same time
@@ -211,48 +259,17 @@
#ifndef _RWSTD_NO_WCHAR_T
- const std::num_put<wchar_t> &np =
+ const std::num_put<wchar_t> &wp =
std::use_facet<std::num_put<wchar_t> >(loc);
- const std::ostreambuf_iterator<wchar_t> iter (&wb);
-
- switch (i % put_max) {
- case put_bool:
- np.put (iter, io, L' ', bool (ival));
- break;
-
- case put_long:
- np.put (iter, io, L' ', long (ival));
- break;
-
- case put_ulong:
- np.put (iter, io, L' ', (unsigned long)ival);
- break;
+ wio.imbue (loc);
+ wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
-#ifndef _RWSTD_NO_LONG_LONG
-
- case put_llong:
- np.put (iter, io, L' ', (_RWSTD_LONG_LONG)ival);
- break;
-
- case put_ullong:
- np.put (iter, io, L' ', (unsigned _RWSTD_LONG_LONG)ival);
- break;
+ put_data(data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
+ wio, L' ', L'\0');
-#endif // _RWSTD_NO_LONG_LONG
-
- case put_dbl:
- np.put (iter, io, L' ', double (ival));
- break;
-
- case put_ldbl:
- np.put (iter, io, L' ', (long double)ival);
- break;
-
- case put_ptr:
- np.put (iter, io, L' ', (void*)ival);
- break;
- }
+ RW_ASSERT (!wio.fail ());
+ RW_ASSERT (!rw_strncmp (wcs, data.wcs_));
#endif // _RWSTD_NO_WCHAR_T
@@ -266,29 +283,98 @@
/**************************************************************************/
+
static int
run_test (int, char**)
{
+ MyIos<char, std::char_traits<char> > nio;
+ MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
+
+#ifndef _RWSTD_NO_WCHAR_T
+ MyIos<wchar_t, std::char_traits<wchar_t> > wio;
+ MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
+
// find all installed locales for which setlocale(LC_ALL) succeeds
const char* const locale_list =
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
- const std::size_t maxinx = sizeof locales / sizeof *locales;
+ const std::size_t maxinx = RW_COUNT_OF (locales);
- for (const char *name = locale_list; *name; name += std::strlen (name) +1)
{
+ for (const char *name = locale_list;
+ *name;
+ name += std::strlen (name) + 1) {
- locales [nlocales++] = name;
+ const std::size_t inx = nlocales;
+ locales [inx] = name;
- if (nlocales == maxinx)
+ // fill in the value and results for this locale
+ MyNumData& data = my_num_data [nlocales];
+ data.locale_name_ = name;
+
+ try {
+ const std::locale loc (data.locale_name_);
+
+ data.value_ = nlocales & 1 ? -1 * nlocales : nlocales;
+ data.type_ = MyNumData::PutId(nlocales % MyNumData::put_max);
+
+ // format data into buffers
+ const std::num_put<char> &np =
+ std::use_facet<std::num_put<char> >(loc);
+
+ nio.imbue (loc);
+ nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
+
+ put_data(data, np, std::ostreambuf_iterator<char>(&nsb),
+ nio, ' ', '\0');
+
+ rw_fatal (!nio.fail (), __FILE__, __LINE__,
+ "num_put<char>::put(...) failed for locale(%#s)",
+ data.locale_name_);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+ const std::num_put<wchar_t> &wp =
+ std::use_facet<std::num_put<wchar_t> >(loc);
+
+ wio.imbue (loc);
+ wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
+
+ put_data(data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
+ wio, L' ', L'\0');
+
+ rw_fatal (!wio.fail (), __FILE__, __LINE__,
+ "num_put<wchar_t>::put(...) failed for locale(%#s)",
+ data.locale_name_);
+
+#endif // _RWSTD_NO_WCHAR_T
+
+ if (rw_opt_shared_locale)
+ data.locale_ = loc;
+
+ nlocales += 1;
+ }
+ catch (...) {
+ rw_warn (!rw_opt_locales, 0, __LINE__,
+ "failed to create locale(%#s)", name);
+ }
+
+ if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
break;
}
+ // avoid divide by zero in thread if there are no locales to test
+ rw_fatal (nlocales != 0, 0, __LINE__,
+ "failed to create one or more usable locales!");
+
rw_info (0, 0, 0,
"testing std::num_put<charT> with %d thread%{?}s%{;}, "
- "%zu iteration%{?}s%{;} each, in locales { %{ [EMAIL PROTECTED]
}",
+ "%zu iteration%{?}s%{;} each, in %zu locales { %{ [EMAIL
PROTECTED] }",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops,
- int (nlocales), "%#s", locales);
+ nlocales, int (nlocales), "%#s", locales);
rw_info (0, 0, 0, "exercising std::num_put<char>");
@@ -318,7 +404,7 @@
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
rw_opt_nthreads, thread_func);
- // exercise bothe the char and the wchar_t specializations
+ // exercise both the char and the wchar_t specializations
// at the same time
rw_info (0, 0, 0,
@@ -357,11 +443,15 @@
return rw_test (argc, argv, __FILE__,
"lib.locale.num.put",
"thread safety", run_test,
- "|-nloops#0 " // must be non-negative
- "|-nthreads#0-* " // must be in [0, MAX_THREADS]
- "|-locales=", // must be provided
+ "|-nloops#0 " // must be non-negative
+ "|-nthreads#0-* " // must be in [0, MAX_THREADS]
+ "|-nlocales#0 " // arg must be non-negative
+ "|-locales= " // must be provided
+ "|-shared-locale# ",
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads,
- &rw_opt_setlocales);
+ &rw_opt_nlocales,
+ &rw_opt_setlocales,
+ &rw_opt_shared_locale);
}
Modified: incubator/stdcxx/trunk/tests/localization/22.locale.time.put.mt.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.time.put.mt.cpp?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.time.put.mt.cpp
(original)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.time.put.mt.cpp Tue Aug
14 17:53:01 2007
@@ -124,8 +124,6 @@
};
-#define countof(x) (sizeof (x) / sizeof (*x))
-
extern "C" {
bool test_char; // exercise time_put<char>
@@ -138,11 +136,13 @@
char ncs [MyTimeData::BufferSize];
MyIos<char, std::char_traits<char> > nio;
MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
#ifndef _RWSTD_NO_WCHAR_T
wchar_t wcs [MyTimeData::BufferSize];
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
#endif // _RWSTD_NO_WCHAR_T
for (int i = 0; i != rw_opt_nloops; ++i) {
@@ -164,10 +164,7 @@
std::use_facet<std::time_put<char> >(loc);
nio.imbue (loc);
-
- // assign data buffer to streambuf
- nsb.pubsetp (ncs, countof (ncs));
- nio.rdbuf (&nsb);
+ nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
// format time using provided format specifier
*tp.put (std::ostreambuf_iterator<char>(&nsb),
@@ -189,9 +186,7 @@
std::use_facet<std::time_put<wchar_t> >(loc);
wio.imbue (loc);
-
- wsb.pubsetp (wcs, countof (wcs));
- wio.rdbuf (&wsb);
+ wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
wio, L' ', &data.time_, data.format_) = L'\0';
@@ -216,109 +211,96 @@
{
MyIos<char, std::char_traits<char> > nio;
MyStreambuf<char, std::char_traits<char> > nsb;
+ nio.rdbuf (&nsb);
#ifndef _RWSTD_NO_WCHAR_T
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+ wio.rdbuf (&wsb);
#endif // _RWSTD_NO_WCHAR_T
// find all installed locales for which setlocale (LC_ALL) succeeds
const char* const locale_list =
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
- const std::size_t maxinx = countof (locales);
+ const std::size_t maxinx = RW_COUNT_OF (locales);
- const char* const possible_locale_options[] = {
- locale_list, "C\0", 0
- };
-
- for (int p = 0; possible_locale_options[p]; ++p) {
-
- int j = 0;
- for (const char* name = possible_locale_options[p];
- *name;
- name += std::strlen (name) + 1) {
-
- const std::size_t inx = nlocales;
- locales [inx] = name;
-
- // fill in the time and results for this locale
- MyTimeData& data = my_time_data [inx];
- data.locale_name_ = name;
-
- // initialize tm with random but valid values
- data.time_.tm_sec = ++j % 61;
- data.time_.tm_min = ++j % 60;
- data.time_.tm_hour = ++j % 12;
- data.time_.tm_wday = ++j % 7;
- data.time_.tm_mon = ++j % 12;
- data.time_.tm_mday = ++j % 31;
- data.time_.tm_yday = ++j % 366;
- data.time_.tm_year = ++j;
-
- const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
-
- // get the "random" conversion specifier used to generate
- // the result string
- data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)];
-
- try {
- const std::locale loc (data.locale_name_);
-
- const std::time_put<char> &np =
- std::use_facet<std::time_put<char> >(loc);
-
- nio.imbue (loc);
-
- nsb.pubsetp (data.ncs_, countof (data.ncs_));
- nio.rdbuf (&nsb);
-
- *np.put (std::ostreambuf_iterator<char>(&nsb),
- nio, ' ', &data.time_, data.format_) = '\0';
-
- rw_assert (!nio.fail (), __FILE__, __LINE__,
- "time_put<char>::put(..., %c) "
- "failed for locale(%#s)",
- data.format_, data.locale_name_);
-
-#ifndef _RWSTD_NO_WCHAR_T
+ int j = 0;
+ for (const char* name = locale_list;
+ *name;
+ name += std::strlen (name) + 1) {
+
+ const std::size_t inx = nlocales;
+ locales [inx] = name;
+
+ // fill in the time and results for this locale
+ MyTimeData& data = my_time_data [inx];
+ data.locale_name_ = name;
+
+ // initialize tm with random but valid values
+ data.time_.tm_sec = ++j % 61;
+ data.time_.tm_min = ++j % 60;
+ data.time_.tm_hour = ++j % 12;
+ data.time_.tm_wday = ++j % 7;
+ data.time_.tm_mon = ++j % 12;
+ data.time_.tm_mday = ++j % 31;
+ data.time_.tm_yday = ++j % 366;
+ data.time_.tm_year = ++j;
+
+ const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
+
+ // get the "random" conversion specifier used to generate
+ // the result string
+ data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)];
- const std::time_put<wchar_t> &wp =
- std::use_facet<std::time_put<wchar_t> >(loc);
+ try {
+ const std::locale loc (data.locale_name_);
- wio.imbue (loc);
+ const std::time_put<char> &np =
+ std::use_facet<std::time_put<char> >(loc);
- wsb.pubsetp (data.wcs_, countof (data.wcs_));
- wio.rdbuf (&wsb);
-
- *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
- wio, L' ', &data.time_, data.format_) = L'\0';
-
- rw_assert (!wio.fail (), __FILE__, __LINE__,
- "time_put<wchar_t>::put(..., %c) "
- "failed for locale(%#s)",
- data.format_, data.locale_name_);
+ nio.imbue (loc);
+ nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
+
+ *np.put (std::ostreambuf_iterator<char>(&nsb),
+ nio, ' ', &data.time_, data.format_) = '\0';
-#endif // _RWSTD_NO_WCHAR_T
+ rw_fatal (!nio.fail (), __FILE__, __LINE__,
+ "time_put<char>::put(..., %c) "
+ "failed for locale(%#s)",
+ data.format_, data.locale_name_);
+
+#ifndef _RWSTD_NO_WCHAR_T
- if (rw_opt_shared_locale)
- data.locale_ = loc;
+ const std::time_put<wchar_t> &wp =
+ std::use_facet<std::time_put<wchar_t> >(loc);
- nlocales += 1;
+ wio.imbue (loc);
+ wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
+
+ *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+ wio, L' ', &data.time_, data.format_) = L'\0';
+
+ rw_fatal (!wio.fail (), __FILE__, __LINE__,
+ "time_put<wchar_t>::put(..., %c) "
+ "failed for locale(%#s)",
+ data.format_, data.locale_name_);
- }
- catch (...) {
- rw_warn (!rw_opt_locales, 0, __LINE__,
- "failed to create locale(%#s)", name);
- }
+#endif // _RWSTD_NO_WCHAR_T
- if (nlocales == maxinx || nlocales == std::size_t
(rw_opt_nlocales))
- break;
- }
+ if (rw_opt_shared_locale)
+ data.locale_ = loc;
+
+ nlocales += 1;
- if (nlocales != 0) {
- break; // found at least one locale
}
+ catch (...) {
+ rw_warn (!rw_opt_locales, 0, __LINE__,
+ "failed to create locale(%#s)", name);
+ }
+
+ if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
+ break;
}
// avoid divide by zero in thread if there are no locales to test
Modified: incubator/stdcxx/trunk/tests/src/locale.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/locale.cpp?view=diff&rev=565991&r1=565990&r2=565991
==============================================================================
--- incubator/stdcxx/trunk/tests/src/locale.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/locale.cpp Tue Aug 14 17:53:01 2007
@@ -327,7 +327,7 @@
/**************************************************************************/
_TEST_EXPORT char*
-rw_locales (int loc_cat, const char* grep_exp)
+rw_locales (int loc_cat, const char* grep_exp, bool prepend_c_loc)
{
static char deflocname [3] = "C\0";
static char* slocname = 0;
@@ -402,12 +402,23 @@
char last_name [256];
*last_name = '\0';
+ // put the C locale at the front
+ if (prepend_c_loc) {
+ strcpy(locname, deflocname);
+ locname += strlen(deflocname) + 1;
+ }
+
// if successful, construct a char array with the locales
while (fgets (linebuf, sizeof linebuf, file)) {
const size_t linelen = strlen (linebuf);
linebuf [linelen ? linelen - 1 : 0] = '\0';
+
+ // don't allow C locale to be in the list again
+ // if we put it at the front of the locale list
+ if (prepend_c_loc && !strcmp(linebuf, deflocname))
+ continue;
#ifdef _RWSTD_OS_SUNOS