On 25 sep, 02:29, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> I'd make a few small changes here. (1) mbtowc tells you how many chars
> it used to make the wide one. *You can use this later on to confirm
> your assumption that the overall length is not changed by
> upper-casing. *(2) you can pass len instead of MB_CUR_MAX so long as
> you update it using the return from mbtowc. *This means there is no
> possibility of ever looked past the end of s even with an ill-formed
> UTF-8 string. *(3) mbtowc might fail (and it call tell you when the
> string has run out) so you can put the call in the while loop test:
>
> * while ((mblen = mbtowc(&wc, s, len)) > 0) ...
>
> > * * * * * * * * * * * * * *wc = towupper(wc);
> > * * * * * * * * * * * * * *mblen = wctomb(p, wc);
>
> I'd use a new variable so that...
>
> > * * * * * * * * * * * * * *p += mblen;
> > * * * * * * * * * * * * * *s += mblen;
>
> ... here you can put the brakes on if you find the two lengths are not
> the same.
>
> > * * * * * * * * * *}
> > * * * * * * * * * **p = '\0';
> > * * * * * * * * * *p -= len;
> > * * * * * *}
> > * *}
> > * *return p;
> > }
Thanks again Ben, I miss Pascal (a lot)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
static char *stoupper(const char *s)
{
char *p = NULL, *oldp;
size_t len;
wchar_t wc;
int wclen, mclen;
if (s) {
len = strlen(s);
oldp = p = malloc(len + MB_CUR_MAX + 1);
if (p) {
while ((wclen = mbtowc(&wc, s, len)) > 0) {
/* I know, too many casts, but makes -Wconversion flag happy */
mclen = wctomb(p, (wchar_t)towupper((wint_t)wc));
/* Strange ... but I always trust Ben

*/
if (mclen > wclen) {
len += (size_t)(mclen - wclen);
mclen = (int)(p - oldp);
/* realloc it's a pain, but what else can I do? */
p = realloc(oldp, len);
if (!p) {
free(oldp);
return NULL;
}
oldp = p;
}
p += mclen;
s += wclen;
}
*p = '\0';
p -= len;
}
}
return p;
}
int main(void)
{
char *s = "María tiene moño, Ramón tiene un camión.";
setlocale(LC_CTYPE, "");
s = stoupper(s);
if (s) {
printf("%s\n", s);
free(s);
}
return 0;
}