This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]