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