ref: 31e59bb74dcaa3273e93a6585e902df407f17ac6
parent: 52d518b5e346b66e9023ec35101480f706810977
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jan 28 20:02:46 EST 2025
string-width: fix for strings containing \0
--- a/src/print.c
+++ b/src/print.c
@@ -17,18 +17,17 @@
FL(hpos)++;
}
-static void
-outs(ios_t *f, const char *s)
+static inline void
+outsn(ios_t *f, const char *s, size_t n)
{
- ios_puts(f, s);
- FL(hpos) += u8_strwidth(s);
+ ios_write(f, s, n);
+ FL(hpos) += u8_strwidth(s, n);
}
-static void
-outsn(ios_t *f, const char *s, size_t n)
+static inline void
+outs(ios_t *f, const char *s)
{
- ios_write(f, s, n);
- FL(hpos) += u8_strwidth(s);
+ outsn(f, s, strlen(s));
}
static int
@@ -167,8 +166,10 @@
static inline int
tinyp(value_t v)
{
- if(issymbol(v))
- return u8_strwidth(symbol_name(v)) < SMALL_STR_LEN;
+ if(issymbol(v)){
+ const char *s = symbol_name(v);
+ return u8_strwidth(s, strlen(s)) < SMALL_STR_LEN;
+ }
if(fl_isstring(v))
return cv_len(ptr(v)) < SMALL_STR_LEN;
return (
@@ -215,8 +216,10 @@
lengthestimate(value_t v)
{
// get the width of an expression if we can do so cheaply
- if(issymbol(v))
- return u8_strwidth(symbol_name(v));
+ if(issymbol(v)){
+ const char *s = symbol_name(v);
+ return u8_strwidth(s, strlen(s));
+ }
if(iscprim(v) && ptr(v) != nil && cp_class(ptr(v)) == FL(runetype))
return 4;
return -1;
--- a/src/string.c
+++ b/src/string.c
@@ -51,7 +51,11 @@
return w < 0 ? FL_f : fixnum(w);
}
}
- return size_wrap(u8_strwidth(tostring(args[0])));
+ if(!fl_isstring(args[0]))
+ type_error("string", args[0]);
+ char *str = tostring(args[0]);
+ size_t len = cv_len(ptr(args[0]));
+ return size_wrap(u8_strwidth(str, len));
}
BUILTIN("string-reverse", string_reverse)
--- a/src/utf8.c
+++ b/src/utf8.c
@@ -62,12 +62,12 @@
}
size_t
-u8_strwidth(const char *s)
+u8_strwidth(const char *s, size_t n)
{
size_t i, w;
Rune r;
- for(i = w = 0; s[i];){
+ for(i = w = 0; i < n;){
i += chartorune(&r, s+i);
w += fl_wcwidth(r);
}
--- a/src/utf8.h
+++ b/src/utf8.h
@@ -49,7 +49,7 @@
char *u8_memchr(char *s, Rune ch, size_t sz, size_t *charn);
/* number of columns occupied by a string */
-size_t u8_strwidth(const char *s) fl_purefn;
+size_t u8_strwidth(const char *s, size_t n) fl_purefn;
/* determine whether a sequence of bytes is valid UTF-8. length is in bytes */
int u8_isvalid(const char *str, int length) fl_purefn;
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -514,5 +514,8 @@
(assert (equal? "" (string-reverse "")))
(assert (equal? "й" (string-reverse "й")))
+(assert (eq? 10 (string-width s)))
+(assert (eq? 0 (string-width "")))
+
(princ "all tests pass")
(newline)