Q about ctype.narrow

Martin Sebor sebor@roguewave.com
Tue Nov 25 20:03:00 GMT 2003


Jerry Quinn wrote:

...
> Now, call narrow(125, 5) followed by narrow(125,10).  Assuming the
> table was inited with 0's, table[125] will get 5, the first time
> through, and the second time, we'll return 5 instead of 10.

Good point. I hadn't thought of that.

> 
> Fixing this starts to get uglier.  I think you need to detect that
> default may get returned and not cache the result in that case:
> 
> char ctype<char>::narrow(char c, char default)
> {
>   if (table[c]) return table[c];
>   char x = do_narrow(c, default);
>   if (x != default) table[c] = x;
>   return x;
> }
> 
> Maybe this still speeds things up over always doing do_narrow, but the
> complexity seems unpleasant.

Is it really that bad? The only thing that needs to be optimized
is successful table lookups, everything else can be outlined:

inline char ctype<char>::narrow(char c, char dfault)
{
   if (table[c]) return table[c];
   return __narrow (c, dfault);
}

/* out-of-line */ char ctype<char>::__narrow(char c, char dfault)
{
   char x = do_narrow(c, dfault);
   if (x != dfault) table[c] = x;
   return x;
}

> 
> I actually first tried filling in the complete table when narrow is
> first called, but that also breaks due to the default issue.  And is
> probably harder to fix.

This too I think should be possible if you just don't fill the cache
in those cases:

inline char ctype<char>::narrow(char c, char dfault)
{
   if (table[c]) return table[c];
   return __narrow (c, dfault);
}

/* out-of-line */ char ctype<char>::__narrow(char c, char dfault)
{
   if (cache_empty) {
     const char s[] = { \000, \001, ..., \0377 };
     do_narrow (s, s + sizeof s, table, 0);   // fill cache
     cache_empty = false;
   }

   // and still call corresponding do_narrow() to make users happy
   char x = do_narrow(c, dfault);
   assert (x == dfault || x == table [c]);

   return x;
}

Martin




More information about the Libstdc++ mailing list