This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Fix some problems in time_get::_M_extract_name
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Sun, 13 Jun 2004 19:00:16 +0200
- Subject: [Patch] Fix some problems in time_get::_M_extract_name
Hi,
the below fixes a few problems, the third one is not completely trivial,
I think. We had
for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
{
__name = __names[__matches[__i3]];
if (__name[__pos] != *__beg)
__matches[__i3] = __matches[--__nmatches];
}
therefore, when the conditional was true, *both* __nmatches was
decreased and
__i3 was increased, i.e., the loop was not eliminating all the non-matching
names, roughly, only half of them.
In turn (besides efficiency issues) this led to the hidden consequence
that the outermost loop ('while (__nmatches > 1)') could be exited with
__nmatches == 1 even when in fact there were no real matching names and we
relied (without explicitly knowing) on the while loop inside the next
conditional 'if (__nmatches == 1)' to detect the last one and eventually
fail.
Unfortunately, since there is no timepunct facet :(, it's not easy to
prepare weird testcases...
Regtested x86-linux, will wait 'til tomorrow,
Paolo.
//////////////
2004-06-14 Paolo Carlini <pcarlini@suse.de>
* include/bits/locale_facets.tcc (time_get<>::_M_extract_name):
Don't use the 'magic number' 10 in the computation of __minlen;
never access __name past __minlen; in the loop over __i3, don't
decrease __nmatches and increase __i3 at once, only either of
the two; tidy.
diff -prN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
*** libstdc++-v3-orig/include/bits/locale_facets.tcc Sun Jun 13 11:25:44 2004
--- libstdc++-v3/include/bits/locale_facets.tcc Sun Jun 13 17:39:43 2004
*************** namespace std
*** 2002,2036 ****
while (__nmatches > 1)
{
// Find smallest matching string.
! size_t __minlen = 10;
! for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
__minlen = std::min(__minlen,
__traits_type::length(__names[__matches[__i2]]));
++__beg;
if (__pos < __minlen && __beg != __end)
! {
! ++__pos;
! for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
! {
! __name = __names[__matches[__i3]];
! if (__name[__pos] != *__beg)
! __matches[__i3] = __matches[--__nmatches];
! }
! }
else
break;
}
if (__nmatches == 1)
{
- // If there was only one match, the first compare is redundant.
- if (__pos == 0)
- {
- ++__pos;
- ++__beg;
- }
-
// Make sure found name is completely extracted.
__name = __names[__matches[0]];
const size_t __len = __traits_type::length(__name);
while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
--- 2002,2031 ----
while (__nmatches > 1)
{
// Find smallest matching string.
! size_t __minlen = __traits_type::length(__names[__matches[0]]);
! for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
__minlen = std::min(__minlen,
__traits_type::length(__names[__matches[__i2]]));
+ ++__pos;
++__beg;
if (__pos < __minlen && __beg != __end)
! for (size_t __i3 = 0; __i3 < __nmatches;)
! {
! __name = __names[__matches[__i3]];
! if (__name[__pos] != *__beg)
! __matches[__i3] = __matches[--__nmatches];
! else
! ++__i3;
! }
else
break;
}
if (__nmatches == 1)
{
// Make sure found name is completely extracted.
+ ++__pos;
+ ++__beg;
__name = __names[__matches[0]];
const size_t __len = __traits_type::length(__name);
while (__pos < __len && __beg != __end && __name[__pos] == *__beg)