Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c++
Subject: Re: Can anyone improve this ?
Date: Mon, 17 Jan 2022 10:28:48 -0800
Organization: A noiseless patient Spider
Lines: 73
Message-ID: <86ee56rzbz.fsf@linuxsc.com>
References:
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="15598caebf32ebbe97649a2f881af1fe"; logging-data="17642"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19OFeprhx0r/MSP/CdSRgToGtMO5QMOsmQ="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:8CoWG+SphpQUxUsZmPxqFFoYhXo= sha1:Ps8nT/Ww0Gnklqiic3+hS5sXoZU=
Xref: csiph.com comp.lang.c++:82802
Bonita Montero writes:
> I had an idea how to write a fast UTF-8 strlen, here it is:
>
> size_t utf8Strlen( char const *str )
> {
> struct encode_t { size_t lenIncr, strIncr; };
> static encode_t const encodes[] =
> {
> { 1, 1 },
> { 0, 0 },
> { 1, 2 },
> { 1, 3 },
> { 1, 4 },
> { 0, 0 },
> { 0, 0 },
> { 0, 0 },
> { 0, 0 }
> };
> size_t len = 0;
> for( unsigned char c; (c = *str); )
> {
> encode_t const &enc =
> encodes[(size_t)countl_zero( ~c )];
> if( !enc.lenIncr ) [[unlikely]]
> return -1;
> len += enc.lenIncr;
> for( char const *cpEnd = str + enc.strIncr; ++str != cpEnd; )
> if( ((unsigned char)*str & 0x0C0) != 0x080 ) [[unlikely]]
> return -1;
> }
> return len;
> }
>
> Has anyone further ideas to improve this ?
Just for fun -
size_t
utf8_units_two( const char *s ){
size_t r = -1;
unsigned char c;
next:
switch( r++, c = *s++, c >> 3 ){
cases(16,17,18,19,20,21,22,23,31): return -1;
cases(30): if( c = *s++, c >> 6 != 2 ) return -1;
cases(28,29): if( c = *s++, c >> 6 != 2 ) return -1;
cases(24,25,26,27): if( c = *s++, c >> 6 != 2 ) return -1;
cases(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15): goto next;
cases(0): if( c != 0 ) goto next;
}
return r;
}
(Note: the cases() macro produces one 'case X:' for each
argument X except the last one where the ':' is omitted,
written using the standard C preprocessor, and left as an
exercise for any ambitious readers.)
Incidentally, this code provides the only example I remember
where using 'goto' is pretty much unavoidable, in that any
re-writing without 'goto' seems awkward or inferior in some
other way. I guess I should say, at least not that I could
find, maybe someone else can do better.
This code also has the interesting property that along the main
code path there are no conditional branches (as compiled by gcc
under -O2).