Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #164369 > unrolled thread

Re: UTF-8 strings in C

Started byBonita Montero <Bonita.Montero@gmail.com>
First post2022-01-10 07:17 +0100
Last post2022-02-07 09:02 -0800
Articles 20 on this page of 31 — 9 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-10 07:17 +0100
    Re: UTF-8 strings in C Mateusz Viste <mateusz@xyz.invalid> - 2022-01-10 09:32 +0100
      Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-10 11:26 +0100
        Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-10 11:55 +0100
          Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-10 14:38 +0100
            Re: UTF-8 strings in C om@iki.fi (Otto J. Makela) - 2022-01-14 14:26 +0200
              Re: UTF-8 strings in C om@iki.fi (Otto J. Makela) - 2022-01-14 16:07 +0200
                Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 15:42 +0100
                Re: UTF-8 strings in C Philipp Klaus Krause <pkk@spth.de> - 2022-01-15 09:08 +0100
                  Re: UTF-8 strings in C om@iki.fi (Otto J. Makela) - 2022-01-22 11:44 +0200
                    Re: UTF-8 strings in C Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-01-22 04:48 -0800
                      Re: UTF-8 strings in C Richard Damon <Richard@Damon-Family.org> - 2022-01-22 08:27 -0500
                    Re: UTF-8 strings in C James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-01-22 14:25 -0500
                      Re: UTF-8 strings in C om@iki.fi (Otto J. Makela) - 2022-01-27 13:32 +0200
                    Re: UTF-8 strings in C om@iki.fi (Otto J. Makela) - 2022-01-27 13:33 +0200
                      Re: UTF-8 strings in C James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-01-27 11:08 -0500
                        Re: UTF-8 strings in C Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-02-03 22:23 -0800
            Re: UTF-8 strings in C Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-01-14 04:41 -0800
              Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 14:43 +0100
                Re: UTF-8 strings in C Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-01-14 05:45 -0800
                  Re: UTF-8 strings in C Mateusz Viste <mateusz@xyz.invalid> - 2022-01-14 15:10 +0100
                    Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 15:43 +0100
                      Re: UTF-8 strings in C Bart <bc@freeuk.com> - 2022-01-14 15:50 +0000
                        Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 17:50 +0100
                      Re: UTF-8 strings in C Mateusz Viste <mateusz@xyz.invalid> - 2022-01-14 17:17 +0100
                        Re: UTF-8 strings in C Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-01-14 08:34 -0800
                          Re: UTF-8 strings in C Mateusz Viste <mateusz@xyz.invalid> - 2022-01-14 17:42 +0100
                        Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 17:51 +0100
                          Re: UTF-8 strings in C Mateusz Viste <mateusz@xyz.invalid> - 2022-01-14 18:07 +0100
                            Re: UTF-8 strings in C Bonita Montero <Bonita.Montero@gmail.com> - 2022-01-14 18:19 +0100
                        Re: UTF-8 strings in C Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-02-07 09:02 -0800

Page 1 of 2  [1] 2  Next page →


#164369 — Re: UTF-8 strings in C

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-10 07:17 +0100
SubjectRe: UTF-8 strings in C
Message-ID<srgj1m$p9s$1@dont-email.me>
Then write your own UTF-8 strlen().

[toc] | [next] | [standalone]


#164374

FromMateusz Viste <mateusz@xyz.invalid>
Date2022-01-10 09:32 +0100
Message-ID<srgqvn$5gn$1@gioia.aioe.org>
In reply to#164369
2022-01-10 at 07:17 +0100, Bonita Montero wrote:
> Then write your own UTF-8 strlen().

That wouldn't be CPU efficient. At this point it might be saner to
implement a special utf-8 string type that keeps the string's
render-width in a separate field.

Mateusz

[toc] | [prev] | [next] | [standalone]


#164377

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-10 11:26 +0100
Message-ID<srh1kj$epo$1@dont-email.me>
In reply to#164374
Am 10.01.2022 um 09:32 schrieb Mateusz Viste:
> 2022-01-10 at 07:17 +0100, Bonita Montero wrote:
>> Then write your own UTF-8 strlen().
> 
> That wouldn't be CPU efficient. ...

I'll bet it woudln't be relevant slower than strlen()
because the memory-latency here is the limit.

[toc] | [prev] | [next] | [standalone]


#164378

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-10 11:55 +0100
Message-ID<srh3b9$q0m$1@dont-email.me>
In reply to#164377
Am 10.01.2022 um 11:26 schrieb Bonita Montero:
> Am 10.01.2022 um 09:32 schrieb Mateusz Viste:
>> 2022-01-10 at 07:17 +0100, Bonita Montero wrote:
>>> Then write your own UTF-8 strlen().
>>
>> That wouldn't be CPU efficient. ...

Ok, it would be slower, but I think this is the fastest possible
implementation (C++20):

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<unsigned char>( ~c )];
		if( !enc.lenIncr ) [[unlikely]]
			return -1;
		len += enc.lenIncr;
		str += enc.strIncr;
	}
	return len;
}

[toc] | [prev] | [next] | [standalone]


#164386

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-10 14:38 +0100
Message-ID<srhcti$tvd$1@dont-email.me>
In reply to#164378
Am 10.01.2022 um 11:55 schrieb Bonita Montero:
> Am 10.01.2022 um 11:26 schrieb Bonita Montero:
>> Am 10.01.2022 um 09:32 schrieb Mateusz Viste:
>>> 2022-01-10 at 07:17 +0100, Bonita Montero wrote:
>>>> Then write your own UTF-8 strlen().
>>>
>>> That wouldn't be CPU efficient. ...
> 
> Ok, it would be slower, but I think this is the fastest possible
> implementation (C++20):

This is more correct since it completely detects encoding-errors:

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<unsigned 
char>( ~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;
}

[toc] | [prev] | [next] | [standalone]


#164400

Fromom@iki.fi (Otto J. Makela)
Date2022-01-14 14:26 +0200
Message-ID<87lezih5b5.fsf@tigger.extechop.net>
In reply to#164386
Bonita Montero <Bonita.Montero@gmail.com> wrote:

> This is more correct since it completely detects encoding-errors:
>
> 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<unsigned
>         char>( ~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;
> }

Took me a while to realize the countl_zero stuff was a C++ library call,
with the accompanying syntax.

However, this is comp.lang.c, so C solutions are appreciated.
-- 
   /* * * Otto J. Makela <om@iki.fi> * * * * * * * * * */
  /* Phone: +358 40 765 5772, ICBM: N 60 10' E 24 55' */
 /* Mail: Mechelininkatu 26 B 27,  FI-00100 Helsinki */
/* * * Computers Rule 01001111 01001011 * * * * * * */

[toc] | [prev] | [next] | [standalone]


#164404

Fromom@iki.fi (Otto J. Makela)
Date2022-01-14 16:07 +0200
Message-ID<87h7a6h0lp.fsf@tigger.extechop.net>
In reply to#164400
om@iki.fi (Otto J. Makela) wrote:

> Took me a while to realize the countl_zero stuff was a C++ library
> call, with the accompanying syntax.
>
> However, this is comp.lang.c, so C solutions are appreciated.

How about this? It of course does not count the slightly odder
compositions (like flags) correctly.

----

int utf8Strlen( char const *str ) {
  int length = 0;
  int multibyte = 0;
  unsigned char c;

  while(c = *str++) {
    if(multibyte) {
      multibyte--;
      if((c & 0xC0) != 0x80 ) // UTF8 encoding error
	return -1;
    } else {
      length++;
      if (c < 0x80) // Normal 7-bit ASCII
	multibyte = 0;
      else if ((c & 0xE0) == 0xC0) // Single following byte
	multibyte = 1;
      else if ((c & 0xF0) == 0xE0) // Two following bytes
	multibyte = 2;
      else if ((c & 0xF8) == 0xF0) // Three following bytes
	multibyte = 3;
      else // UTF8 encoding error
	return -1;
    }
  }

  if(multibyte) // Ran out of string in the middle of multibyte character
    return -1;
  return length;
}

-- 
   /* * * Otto J. Makela <om@iki.fi> * * * * * * * * * */
  /* Phone: +358 40 765 5772, ICBM: N 60 10' E 24 55' */
 /* Mail: Mechelininkatu 26 B 27,  FI-00100 Helsinki */
/* * * Computers Rule 01001111 01001011 * * * * * * */

[toc] | [prev] | [next] | [standalone]


#164406

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-14 15:42 +0100
Message-ID<srs24f$4n1$1@dont-email.me>
In reply to#164404
Am 14.01.2022 um 15:07 schrieb Otto J. Makela:
> om@iki.fi (Otto J. Makela) wrote:
> 
>> Took me a while to realize the countl_zero stuff was a C++ library
>> call, with the accompanying syntax.
>>
>> However, this is comp.lang.c, so C solutions are appreciated.
> 
> How about this? It of course does not count the slightly odder
> compositions (like flags) correctly.
> 
> ----
> 
> int utf8Strlen( char const *str ) {
>    int length = 0;
>    int multibyte = 0;
>    unsigned char c;
> 
>    while(c = *str++) {
>      if(multibyte) {
>        multibyte--;
>        if((c & 0xC0) != 0x80 ) // UTF8 encoding error
> 	return -1;
>      } else {
>        length++;
>        if (c < 0x80) // Normal 7-bit ASCII
> 	multibyte = 0;
>        else if ((c & 0xE0) == 0xC0) // Single following byte
> 	multibyte = 1;
>        else if ((c & 0xF0) == 0xE0) // Two following bytes
> 	multibyte = 2;
>        else if ((c & 0xF8) == 0xF0) // Three following bytes
> 	multibyte = 3;
>        else // UTF8 encoding error
> 	return -1;
>      }
>    }
> 
>    if(multibyte) // Ran out of string in the middle of multibyte character
>      return -1;
>    return length;
> }
> 

A lot of unpredictible branches.
That's what I want to prevent with the table.

[toc] | [prev] | [next] | [standalone]


#164417

FromPhilipp Klaus Krause <pkk@spth.de>
Date2022-01-15 09:08 +0100
Message-ID<srtvd7$143n0$2@solani.org>
In reply to#164404
On 14.01.22 15:07, Otto J. Makela wrote:
> 
> How about this? It of course does not count the slightly odder
> compositions (like flags) correctly.
> 

Why not just call mblen() in the loop instead?

[toc] | [prev] | [next] | [standalone]


#164534

Fromom@iki.fi (Otto J. Makela)
Date2022-01-22 11:44 +0200
Message-ID<87k0es9kag.fsf@tigger.extechop.net>
In reply to#164417
Philipp Klaus Krause <pkk@spth.de> wrote:

> On 14.01.22 15:07, Otto J. Makela wrote:
>> How about this? It of course does not count the slightly odder
>> compositions (like flags) correctly.
>
> Why not just call mblen() in the loop instead?

Firstly, I will fully admit wasn't aware of its existance.

Secondly, on quick tests I can't seem to find the settings it needs to
be happy even with 2-byte characters. Apparently I don't understand it,
or my environment isn't correctly set up?

----

#include <stdio.h>
#include <stdlib.h>

int main() {
  unsigned char str[10]="Ä";

  printf("'%s' %02x %02x %02x %d\n",
         str,str[0],str[1],str[3],mblen(str,10));
  exit(0);
}

----

Produces output:

'Ä' c3 84 00 -1

-- 
   /* * * Otto J. Makela <om@iki.fi> * * * * * * * * * */
  /* Phone: +358 40 765 5772, ICBM: N 60 10' E 24 55' */
 /* Mail: Mechelininkatu 26 B 27,  FI-00100 Helsinki */
/* * * Computers Rule 01001111 01001011 * * * * * * */

[toc] | [prev] | [next] | [standalone]


#164536

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2022-01-22 04:48 -0800
Message-ID<a47139af-611d-4556-bae4-7399ea12942fn@googlegroups.com>
In reply to#164534
On Saturday, 22 January 2022 at 09:44:52 UTC, Otto J. Makela wrote:
> Philipp Klaus Krause <p...@spth.de> wrote: 
> 
> > On 14.01.22 15:07, Otto J. Makela wrote: 
> >> How about this? It of course does not count the slightly odder 
> >> compositions (like flags) correctly. 
> > 
> > Why not just call mblen() in the loop instead?
> Firstly, I will fully admit wasn't aware of its existance. 
> 
> Secondly, on quick tests I can't seem to find the settings it needs to 
> be happy even with 2-byte characters. Apparently I don't understand it, 
> or my environment isn't correctly set up? 
> 
> ---- 
> 
> #include <stdio.h> 
> #include <stdlib.h> 
> 
> int main() { 
> unsigned char str[10]="Ä"; 
> 
> printf("'%s' %02x %02x %02x %d\n", 
> str,str[0],str[1],str[3],mblen(str,10)); 
> exit(0); 
> } 
> 
> ---- 
> 
> Produces output: 
> 
> 'Ä' c3 84 00 -1
> 
Something is wrong.
Try resetting the "shift state" with mblen(NULL, 0);

I doubt that's the problem, but it's worth a try.

[toc] | [prev] | [next] | [standalone]


#164538

FromRichard Damon <Richard@Damon-Family.org>
Date2022-01-22 08:27 -0500
Message-ID<ICTGJ.53031$Y01.30902@fx45.iad>
In reply to#164536
On 1/22/22 7:48 AM, Malcolm McLean wrote:
> On Saturday, 22 January 2022 at 09:44:52 UTC, Otto J. Makela wrote:
>> Philipp Klaus Krause <p...@spth.de> wrote:
>>
>>> On 14.01.22 15:07, Otto J. Makela wrote:
>>>> How about this? It of course does not count the slightly odder
>>>> compositions (like flags) correctly.
>>>
>>> Why not just call mblen() in the loop instead?
>> Firstly, I will fully admit wasn't aware of its existance.
>>
>> Secondly, on quick tests I can't seem to find the settings it needs to
>> be happy even with 2-byte characters. Apparently I don't understand it,
>> or my environment isn't correctly set up?
>>
>> ----
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int main() {
>> unsigned char str[10]="Ä";
>>
>> printf("'%s' %02x %02x %02x %d\n",
>> str,str[0],str[1],str[3],mblen(str,10));
>> exit(0);
>> }
>>
>> ----
>>
>> Produces output:
>>
>> 'Ä' c3 84 00 -1
>>
> Something is wrong.
> Try resetting the "shift state" with mblen(NULL, 0);
> 
> I doubt that's the problem, but it's worth a try.

Could it be that the library isn't in a 'Unicode' mode but an 'ASCII' mode.

I thought that mblen was locale dependent, and if the default 'C' local 
defines the character set at 'ASCII', then the first byte of 0xC3 is in 
fact, an invalid character.

One of the limits of the C language is that it does not default 
(necessarily) to assuming Unicode, so the code may need an 
implementation specific call to set the locale to one that uses Unicode, 
if one exists (which isn't required).

[toc] | [prev] | [next] | [standalone]


#164546

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2022-01-22 14:25 -0500
Message-ID<sshlmu$vqi$1@dont-email.me>
In reply to#164534
On 1/22/22 04:44, Otto J. Makela wrote:
> #include <stdio.h>
> #include <stdlib.h>
> 
> int main() {
>   unsigned char str[10]="Ä";
> 
>   printf("'%s' %02x %02x %02x %d\n",
>          str,str[0],str[1],str[3],mblen(str,10));
>   exit(0);
> }

The set of valid extended characters is locale-dependent (5.2.1p1). In
the "C" locale on my system, there are none - only the basic character
set is supported. It's not clear to me that the C standard requires
this, but it certainly allows it.

You need to use setlocale() to select a locale that supports UTF-8.
Which locales are supported depend upon your implementation. On my
platform, the default locale (the one chosen if the second argument of
setlocale() is "") is determined by the LC_LANG environment, which I
have set to "en_US.UTF-8". When I insert setlocale(LC_CTYPE, "") in your
program before the mblen() call, I get the following results:

 'Ä' c3 84 00 2

[toc] | [prev] | [next] | [standalone]


#164671

Fromom@iki.fi (Otto J. Makela)
Date2022-01-27 13:32 +0200
Message-ID<87lez1pg6c.fsf@tigger.extechop.net>
In reply to#164546
James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

> The set of valid extended characters is locale-dependent (5.2.1p1). In
> the "C" locale on my system, there are none - only the basic character
> set is supported. It's not clear to me that the C standard requires
> this, but it certainly allows it.
>
> You need to use setlocale() to select a locale that supports UTF-8.
> Which locales are supported depend upon your implementation. On my
> platform, the default locale (the one chosen if the second argument of
> setlocale() is "") is determined by the LC_LANG environment, which I
> have set to "en_US.UTF-8". When I insert setlocale(LC_CTYPE, "") in
> your program before the mblen() call, I get the following results:
>
>  'Ä' c3 84 00 2

Yep, that setlocale() call did it. I actually have the semi-joke value
of LANG=en_DK.UTF-8 in my environment, produces good results for me.

https://unix.stackexchange.com/questions/62316/why-is-there-no-euro-english-locale
-- 
   /* * * Otto J. Makela <om@iki.fi> * * * * * * * * * */
  /* Phone: +358 40 765 5772, ICBM: N 60 10' E 24 55' */
 /* Mail: Mechelininkatu 26 B 27,  FI-00100 Helsinki */
/* * * Computers Rule 01001111 01001011 * * * * * * */

[toc] | [prev] | [next] | [standalone]


#164672

Fromom@iki.fi (Otto J. Makela)
Date2022-01-27 13:33 +0200
Message-ID<87k0elpg4l.fsf@tigger.extechop.net>
In reply to#164534
ram@zedat.fu-berlin.de (Stefan Ram) wrote:

>   Here:

The end result is exactly the same as with my program,
mblen() returns -1.

James Kuyper <jameskuyper@alumni.caltech.edu> understood it, I need to
ask for the default locale. I'm a bit stumped as to why so.

-- 
   /* * * Otto J. Makela <om@iki.fi> * * * * * * * * * */
  /* Phone: +358 40 765 5772, ICBM: N 60 10' E 24 55' */
 /* Mail: Mechelininkatu 26 B 27,  FI-00100 Helsinki */
/* * * Computers Rule 01001111 01001011 * * * * * * */

[toc] | [prev] | [next] | [standalone]


#164674

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2022-01-27 11:08 -0500
Message-ID<ssug22$pd6$1@dont-email.me>
In reply to#164672
On 1/27/22 06:33, Otto J. Makela wrote:
> ram@zedat.fu-berlin.de (Stefan Ram) wrote:
>
>> Here:
>
> The end result is exactly the same as with my program,
> mblen() returns -1.
>
> James Kuyper <jameskuyper@alumni.caltech.edu> understood it, I need to
> ask for the default locale. I'm a bit stumped as to why so.

Note: while I referred to it as the "default" locale, that's a bad term
for it, since the "C" locale is the true default:

"At program startup, the equivalent of
setlocale(LC_ALL, "C");
is executed." (7.11.1.1p4)

"... a value of "" for locale specifies the locale-specific native
environment." (7.11.1.1p3), so it would be better to call it the
"native" locale.

"In the "C" locale, isalpha returns true only for the characters for
which isupper or islower is true." (7.4.1.2p2)

"In the "C" locale, islower returns true only for the lowercase letters
(as defined in 5.2.1)." (7.4.1.7p2)

"In the "C" locale, isupper returns true only for the uppercase letters
(as defined in 5.2.1)." (7.4.1.11p2)

"... the 26 _uppercase letters_ of the Latin alphabet
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

the 26 _lowercase letters_ of the Latin alphabet
a b c d e f g h i j k l m
n o p q r s t u v w x y z" (5.2.1p2)

Note that the phrases "uppercase letters" and "lowercase letters" are in
italics, an ISO convention indicating that the clause in which they
appear constitutes the official definition for those terms within this
document.

Thus, isalpha() can only be true in the "C" locale for the 26 letters of
the latin alphabet. That's not quite the same as requiring that those be
the only valid character encodings. Note, in particular, that it's not
possible to pass a member of the extended character set to isalpha() if
that member's encoding takes more than 1 byte, so nothing the standard
says about isalpha() can constrain how such characters are treated. Such
a character could be converted to wchar_t and passed to iswalpha(), but
that function has no special specifications for the "C" locale. However,
those facts certainly don't encourage support for additional valid
character encodings in the "C" locale.

[toc] | [prev] | [next] | [standalone]


#164768

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-02-03 22:23 -0800
Message-ID<86o83nkv5b.fsf@linuxsc.com>
In reply to#164674
James Kuyper <jameskuyper@alumni.caltech.edu> writes:

> On 1/27/22 06:33, Otto J. Makela wrote:
>
>> ram@zedat.fu-berlin.de (Stefan Ram) wrote:
>>
>>> Here:
>>
>> The end result is exactly the same as with my program,
>> mblen() returns -1.
>>
>> James Kuyper <jameskuyper@alumni.caltech.edu> understood it, I need to
>> ask for the default locale.  I'm a bit stumped as to why so.
>
> Note: while I referred to it as the "default" locale, that's a bad
> term for it, since the "C" locale is the true default:
>
> "At program startup, the equivalent of
> setlocale(LC_ALL, "C");
> is executed."  (7.11.1.1p4)
>
> "... a value of "" for locale specifies the locale-specific native
> environment."  (7.11.1.1p3), so it would be better to call it the
> "native" locale.
>
> "In the "C" locale, isalpha returns true only for the characters for
> which isupper or islower is true."  (7.4.1.2p2)
>
> "In the "C" locale, islower returns true only for the lowercase
> letters (as defined in 5.2.1)."  (7.4.1.7p2)
>
> "In the "C" locale, isupper returns true only for the uppercase
> letters (as defined in 5.2.1)."  (7.4.1.11p2)
>
> "... the 26 _uppercase letters_ of the Latin alphabet
> A B C D E F G H I J K L M
> N O P Q R S T U V W X Y Z
>
> the 26 _lowercase letters_ of the Latin alphabet
> a b c d e f g h i j k l m
> n o p q r s t u v w x y z" (5.2.1p2)
>
> Note that the phrases "uppercase letters" and "lowercase letters"
> are in italics, an ISO convention indicating that the clause in
> which they appear constitutes the official definition for those
> terms within this document.
>
> Thus, isalpha() can only be true in the "C" locale for the 26
> letters of the latin alphabet.  [...]

What I think you mean is that in the "C" locale isalpha() can be
true only for the 26 letters of the latin alphabet.

[toc] | [prev] | [next] | [standalone]


#164401

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2022-01-14 04:41 -0800
Message-ID<afd871a5-960a-436e-abde-382a667a55f5n@googlegroups.com>
In reply to#164386
On Friday, 14 January 2022 at 12:18:42 UTC, Otto J. Makela wrote:
> Bonita Montero <Bonita....@gmail.com> wrote: 
> 
> > This is more correct since it completely detects encoding-errors: 
> > 
> > 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<unsigned 
> > char>( ~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; 
> > }
> I must be getting a bit old here, I don't seem to understand 
> what that countl_zero stuff (and the syntax thereabouts) is? 
> 
> PS. Also, shouldn't the first struct line be a typedef, 
> at least you seem to use it at bit later like it was? 
> PPS. And shouldn't const be before type, not after? 
>
Also, it would be safer to make the function return an int.
size_t is unsigned, and the return is -1 for error. So code like

size_t Nchars = utf8Strlen(utf8str);
size_t i;

for (i =0; i < Nchars; i++)
{
}

will run through quintillions of iterations, instead of being
a no-op, if the utf8 is malformed.

[toc] | [prev] | [next] | [standalone]


#164402

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-01-14 14:43 +0100
Message-ID<srrul5$c2h$1@dont-email.me>
In reply to#164401
Am 14.01.2022 um 13:41 schrieb Malcolm McLean:
> On Friday, 14 January 2022 at 12:18:42 UTC, Otto J. Makela wrote:
>> Bonita Montero <Bonita....@gmail.com> wrote:
>>
>>> This is more correct since it completely detects encoding-errors:
>>>
>>> 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<unsigned
>>> char>( ~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;
>>> }
>> I must be getting a bit old here, I don't seem to understand
>> what that countl_zero stuff (and the syntax thereabouts) is?
>>
>> PS. Also, shouldn't the first struct line be a typedef,
>> at least you seem to use it at bit later like it was?
>> PPS. And shouldn't const be before type, not after?
>>
> Also, it would be safer to make the function return an int.
> size_t is unsigned, and the return is -1 for error. ...

All compilers support this because it is very common.

> 
> size_t Nchars = utf8Strlen(utf8str);
> size_t i;
> 
> for (i =0; i < Nchars; i++)
> {
> }
> 
> will run through quintillions of iterations, instead of being
> a no-op, if the utf8 is malformed.

[toc] | [prev] | [next] | [standalone]


#164403

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2022-01-14 05:45 -0800
Message-ID<2d6fffa5-9748-4d64-8ba6-a164caef70c6n@googlegroups.com>
In reply to#164402
On Friday, 14 January 2022 at 13:43:16 UTC, Bonita Montero wrote:
> Am 14.01.2022 um 13:41 schrieb Malcolm McLean: 
> > On Friday, 14 January 2022 at 12:18:42 UTC, Otto J. Makela wrote: 
> >> Bonita Montero <Bonita....@gmail.com> wrote: 
> >> 
> >>> This is more correct since it completely detects encoding-errors: 
> >>> 
> >>> 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<unsigned 
> >>> char>( ~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; 
> >>> } 
> >> I must be getting a bit old here, I don't seem to understand 
> >> what that countl_zero stuff (and the syntax thereabouts) is? 
> >> 
> >> PS. Also, shouldn't the first struct line be a typedef, 
> >> at least you seem to use it at bit later like it was? 
> >> PPS. And shouldn't const be before type, not after? 
> >> 
> > Also, it would be safer to make the function return an int.
> > size_t is unsigned, and the return is -1 for error. ... 
> 
> All compilers support this because it is very common.
>
Yes. It should compile cleanly. That's not the objection.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web