Просмотр исходного кода

fix(str): handle an empty substring in replace and count (#548)

replace('', x) never advanced past the empty match and grew memory without
bound, and count('') counted bytes instead of characters.

Co-authored-by: youdie006 <youdie006@users.noreply.github.com>
KBS 5 часов назад
Родитель
Сommit
015cdafd51
2 измененных файлов с 17 добавлено и 1 удалено
  1. 13 1
      src/common/str.c
  2. 4 0
      tests/041_str.py

+ 13 - 1
src/common/str.c

@@ -66,6 +66,18 @@ c11_string* c11_sv__replace(c11_sv self, char old, char new_) {
 c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_) {
 c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_) {
     c11_sbuf buf;
     c11_sbuf buf;
     c11_sbuf__ctor(&buf);
     c11_sbuf__ctor(&buf);
+    if(old.size == 0) {
+        // insert new_ before every character and at the end
+        int i = 0;
+        while(i < self.size) {
+            int n = c11__u8_header(self.data[i], false);
+            c11_sbuf__write_sv(&buf, new_);
+            c11_sbuf__write_sv(&buf, (c11_sv){self.data + i, n});
+            i += n;
+        }
+        c11_sbuf__write_sv(&buf, new_);
+        return c11_sbuf__submit(&buf);
+    }
     int start = 0;
     int start = 0;
     while(true) {
     while(true) {
         int i = c11_sv__index2(self, old, start);
         int i = c11_sv__index2(self, old, start);
@@ -168,7 +180,7 @@ int c11_sv__index2(c11_sv self, c11_sv sub, int start) {
 }
 }
 
 
 int c11_sv__count(c11_sv self, c11_sv sub) {
 int c11_sv__count(c11_sv self, c11_sv sub) {
-    if(sub.size == 0) return self.size + 1;
+    if(sub.size == 0) return c11_sv__u8_length(self) + 1;
     int cnt = 0;
     int cnt = 0;
     int start = 0;
     int start = 0;
     while(true) {
     while(true) {

+ 4 - 0
tests/041_str.py

@@ -72,6 +72,10 @@ assert '1111'.count('11') == 2
 assert '11'.count('') == 3
 assert '11'.count('') == 3
 assert ''.count('1') == 0
 assert ''.count('1') == 0
 assert ''.count('') == 1
 assert ''.count('') == 1
+assert 'é日'.count('') == 3
+assert 'ab'.replace('', '-') == '-a-b-'
+assert 'é日'.replace('', '|') == '|é|日|'
+assert ''.replace('', 'x') == 'x'
 
 
 t = "*****this is **string** example....wow!!!*****"
 t = "*****this is **string** example....wow!!!*****"
 s = "123abcrunoob321"
 s = "123abcrunoob321"