blob: 44b691d2d1c1d6c5ea61a0fdcc237786cf3e1853 [file] [log] [blame] [edit]
/* See LICENSE file for copyright and license details. */
#include "utf.h"
size_t
utfnlen(const char *s, size_t len)
{
unsigned char c, i, m, n, x;
const char *p;
size_t k;
Rune r;
for(k = 0; *(p = s) != '\0'; len -= s - p, k++) {
if(len == 0) /* can't even look at s[0] */
return k;
c = *s++;
if((c & 0300) != 0300) /* not a leading byte */
continue;
n = utftab[c & 077];
if(n == 0) /* illegal byte */
continue;
if(len == 1) /* reached len limit */
return k;
if((*s & 0300) != 0200) /* not a continuation byte */
continue;
x = 0377 >> n;
r = c & x;
r = (r << 6) | (*s++ & 077);
if(r <= x) /* overlong sequence */
continue;
m = (len < n) ? len : n;
for(i = 2; i < m; i++) {
if((*s & 0300) != 0200) /* not a continuation byte */
break;
s++;
}
if(i < m) /* broke out of loop early */
continue;
if(i < n) /* must have reached len limit */
return k;
}
return k;
}
size_t
utflen(const char *s)
{
return utfnlen(s, (size_t)-1);
}