shithub: femtolisp

Download patch

ref: 76a7c66de3702ff0486900f7d4fa626407b953c3
parent: c1b99838564a31cba20b227c1f4a9ffa51d5c74e
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Nov 18 20:30:17 EST 2024

read_string: use read context buffer (increase its size) to avoid allocations

--- a/read.c
+++ b/read.c
@@ -15,7 +15,7 @@
 struct Rctx {
 	uint32_t toktype;
 	value_t tokval;
-	char buf[256];
+	char buf[1024];
 };
 
 static value_t do_read_sexpr(Rctx *ctx, value_t label);
@@ -415,22 +415,28 @@
 }
 
 static value_t
-read_string(void)
+read_string(Rctx *ctx)
 {
 	char *buf, *temp;
 	char eseq[10];
-	size_t i = 0, j, sz = 64, ndig;
+	size_t i = 0, j, sz, ndig;
 	int c;
 	value_t s;
 	Rune r = 0;
 
-	buf = MEM_ALLOC(sz);
+	sz = sizeof(ctx->buf);
+	buf = ctx->buf;
 	while(1){
 		if(i >= sz-UTFmax){ // -UTFmax: leaves room for longest utf8 sequence
 			sz *= 2;
-			temp = MEM_REALLOC(buf, sz);
+			if(buf == ctx->buf){
+				if((temp = MEM_ALLOC(sz)) != nil)
+					memcpy(temp, ctx->buf, i);
+			}else
+				temp = MEM_REALLOC(buf, sz);
 			if(temp == nil){
-				MEM_FREE(buf);
+				if(buf == ctx->buf)
+					MEM_FREE(buf);
 				parse_error("out of memory reading string");
 			}
 			buf = temp;
@@ -437,7 +443,8 @@
 		}
 		c = ios_getc(RS);
 		if(c == IOS_EOF){
-			MEM_FREE(buf);
+			if(buf != ctx->buf)
+				MEM_FREE(buf);
 			parse_error("unexpected end of input in string");
 		}
 		if(c == '"')
@@ -445,7 +452,8 @@
 		else if(c == '\\'){
 			c = ios_getc(RS);
 			if(c == IOS_EOF){
-				MEM_FREE(buf);
+				if(buf != ctx->buf)
+					MEM_FREE(buf);
 				parse_error("end of input in escape sequence");
 			}
 			j = 0;
@@ -473,7 +481,8 @@
 				if(j)
 					r = strtol(eseq, nil, 16);
 				if(!j || r > Runemax){
-					MEM_FREE(buf);
+					if(buf != ctx->buf)
+						MEM_FREE(buf);
 					parse_error("invalid escape sequence");
 				}
 				if(ndig == 2)
@@ -485,7 +494,8 @@
 			}else{
 				char esc = read_escape_control_char((char)c);
 				if(esc == (char)c && !strchr("\\'\"`", esc)){
-					MEM_FREE(buf);
+					if(buf != ctx->buf)
+						MEM_FREE(buf);
 					parse_error("invalid escape sequence: \\%c", (char)c);
 				}
 				buf[i++] = esc;
@@ -496,7 +506,8 @@
 	}
 	s = cvalue_string(i);
 	memcpy(cvalue_data(s), buf, i);
-	MEM_FREE(buf);
+	if(buf != ctx->buf)
+		MEM_FREE(buf);
 	return s;
 }
 
@@ -671,7 +682,7 @@
 			*pv = gensym();
 		return *pv;
 	case TOK_DOUBLEQUOTE:
-		return read_string();
+		return read_string(ctx);
 	}
 	return FL(unspecified);
 }