Files
strans/str.c
Hojun-Cho bdf05e3c4a str, bench: three checks that guard nothing
sinit sets s->n = 0 as its first statement and no failure path restores
it, so stail's sclear after a failed sinit could never change anything;
say so in sinit's comment instead, where the contract belongs.  bench
compared a uintmax_t against UINT64_MAX and a size_t against UINT64_MAX,
both constant on any host this builds for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 16:14:16 +09:00

113 lines
1.6 KiB
C

#include "dat.h"
#include "fn.h"
/* Fills s from n bytes of UTF-8; whole, valid, and at most Maxrunes.
* Anything else leaves s empty. */
int
sinit(Str *s, char *src, int n)
{
Str tmp = {0};
Rune r;
int len;
s->n = 0;
while(n > 0){
if(tmp.n >= Maxrunes || !fullrune(src, n))
return 0;
len = chartorune(&r, src);
if((r == Runeerror && len == 1) || (r >= 0xd800 && r <= 0xdfff))
return 0;
tmp.r[tmp.n++] = r;
src += len;
n -= len;
}
*s = tmp;
return 1;
}
/* The last runes of n bytes of UTF-8, as many as a Str holds. */
void
stail(Str *s, char *src, int n)
{
Rune r;
char *p;
int nr;
nr = utfnlen(src, n);
for(p = src; nr > Maxrunes; nr--)
p += chartorune(&r, p);
sinit(s, p, n - (p - src));
}
void
sclear(Str *s)
{
s->n = 0;
}
void
sputr(Str *s, Rune r)
{
/* Str is a capped value; appends at capacity leave it unchanged. */
if(s->n >= Maxrunes)
return;
s->r[s->n++] = r;
}
void
spopr(Str *s)
{
if(s->n > 0)
s->r[--s->n] = 0;
}
void
sappend(Str *dst, Str *src)
{
int i, n;
n = src->n;
for(i = 0; i < n && dst->n < Maxrunes; i++)
dst->r[dst->n++] = src->r[i];
}
int
scmp(Str *a, Str *b)
{
int i;
if(a->n != b->n)
return 1;
for(i = 0; i < a->n; i++)
if(a->r[i] != b->r[i])
return 1;
return 0;
}
/* UTF-8 of s into buf[sz], NUL-terminated, whole runes only. */
int
stoutf(Str *s, char *buf, int sz)
{
char tmp[UTFmax];
int i, n, len;
n = 0;
for(i = 0; i < s->n; i++){
len = runetochar(tmp, &s->r[i]);
if(len > sz - n - 1)
break;
memmove(buf + n, tmp, len);
n += len;
}
buf[n] = '\0';
return n;
}
Rune
slastr(Str *s)
{
if(s->n < 1)
return 0;
return s->r[s->n-1];
}