blueloveTH 1 год назад
Родитель
Сommit
f0ec979815
5 измененных файлов с 69 добавлено и 43 удалено
  1. 3 0
      include/pocketpy/common/str.h
  2. 4 2
      include/pocketpy/common/str.hpp
  3. 60 2
      src/common/str.c
  4. 0 37
      src/common/str.cpp
  5. 2 2
      src/interpreter/vm.cpp

+ 3 - 0
include/pocketpy/common/str.h

@@ -35,6 +35,9 @@ pkpy_Str pkpy_Str__substr(const pkpy_Str* self, int start);
 pkpy_Str pkpy_Str__substr2(const pkpy_Str* self, int start, int size);
 pkpy_Str pkpy_Str__substr2(const pkpy_Str* self, int start, int size);
 pkpy_Str pkpy_Str__lower(const pkpy_Str* self);
 pkpy_Str pkpy_Str__lower(const pkpy_Str* self);
 pkpy_Str pkpy_Str__upper(const pkpy_Str* self);
 pkpy_Str pkpy_Str__upper(const pkpy_Str* self);
+pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote);
+// pkpy_Str pkpy_Str__strip(const pkpy_Str* self, bool left, bool right);
+// pkpy_Str pkpy_Str__strip2(const pkpy_Str* self, bool left, bool right, const pkpy_Str* chars);
 pkpy_Str pkpy_Str__replace(const pkpy_Str* self, char old, char new_);
 pkpy_Str pkpy_Str__replace(const pkpy_Str* self, char old, char new_);
 pkpy_Str pkpy_Str__replace2(const pkpy_Str* self, const pkpy_Str* old, const pkpy_Str* new_);
 pkpy_Str pkpy_Str__replace2(const pkpy_Str* self, const pkpy_Str* old, const pkpy_Str* new_);
 pkpy_Str pkpy_Str__u8_getitem(const pkpy_Str* self, int i);
 pkpy_Str pkpy_Str__u8_getitem(const pkpy_Str* self, int i);

+ 4 - 2
include/pocketpy/common/str.hpp

@@ -177,8 +177,10 @@ struct Str: pkpy_Str {
         return pkpy_Str__replace2(this, &old, &new_);
         return pkpy_Str__replace2(this, &old, &new_);
     }
     }
 
 
-    Str escape(bool single_quote = true) const;
-    void escape_(SStream& ss, bool single_quote = true) const;
+    Str escape(char quote='\'') const{
+        return pkpy_Str__escape(this, quote);
+    }
+
     vector<std::string_view> split(const Str& sep) const;
     vector<std::string_view> split(const Str& sep) const;
     vector<std::string_view> split(char sep) const;
     vector<std::string_view> split(char sep) const;
 
 

+ 60 - 2
src/common/str.c

@@ -118,6 +118,62 @@ pkpy_Str pkpy_Str__upper(const pkpy_Str *self){
     return retval;
     return retval;
 }
 }
 
 
+pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote){
+    assert(quote == '"' || quote == '\'');
+    c11_vector buffer;
+    c11_vector__ctor(&buffer, sizeof(char));
+    c11_vector__reserve(&buffer, self->size);
+    c11_vector__push(char, &buffer, quote);
+    const char* data = pkpy_Str__data(self);
+    for(int i = 0; i < self->size; i++) {
+        char c = data[i];
+        switch(c) {
+            case '"': case '\'':
+                if(c == quote) c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, c);
+                break;
+            case '\\':
+                c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, '\\');
+                break;
+            case '\n':
+                c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, 'n');
+                break;
+            case '\r':
+                c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, 'r');
+                break;
+            case '\t':
+                c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, 't');
+                break;
+            case '\b':
+                c11_vector__push(char, &buffer, '\\');
+                c11_vector__push(char, &buffer, 'b');
+                break;
+            default:
+                if('\x00' <= c && c <= '\x1f') {
+                    c11_vector__push(char, &buffer, '\\');
+                    c11_vector__push(char, &buffer, 'x');
+                    c11_vector__push(char, &buffer, PK_HEX_TABLE[c >> 4]);
+                    c11_vector__push(char, &buffer, PK_HEX_TABLE[c & 0xf]);
+                } else {
+                    c11_vector__push(char, &buffer, c);
+                }
+        }
+    }
+    c11_vector__push(char, &buffer, quote);
+    c11_vector__push(char, &buffer, '\0');
+    pkpy_Str retval = {
+        .size = buffer.count - 1,
+        .is_ascii = self->is_ascii,
+        .is_sso = false,
+        ._ptr = (char*)buffer.data,
+    };
+    return retval;
+}
+
 pkpy_Str pkpy_Str__replace(const pkpy_Str *self, char old, char new_){
 pkpy_Str pkpy_Str__replace(const pkpy_Str *self, char old, char new_){
     pkpy_Str retval = pkpy_Str__copy(self);
     pkpy_Str retval = pkpy_Str__copy(self);
     char* p = (char*)pkpy_Str__data(&retval);
     char* p = (char*)pkpy_Str__data(&retval);
@@ -143,8 +199,9 @@ pkpy_Str pkpy_Str__replace2(const pkpy_Str *self, const pkpy_Str *old, const pkp
     pkpy_Str tmp = pkpy_Str__substr2(self, start, self->size - start);
     pkpy_Str tmp = pkpy_Str__substr2(self, start, self->size - start);
     c11_vector__extend(char, &buffer, pkpy_Str__data(&tmp), tmp.size);
     c11_vector__extend(char, &buffer, pkpy_Str__data(&tmp), tmp.size);
     pkpy_Str__dtor(&tmp);
     pkpy_Str__dtor(&tmp);
+    c11_vector__push(char, &buffer, '\0');
     pkpy_Str retval = {
     pkpy_Str retval = {
-        .size = buffer.count,
+        .size = buffer.count - 1,
         .is_ascii = self->is_ascii && old->is_ascii && new_->is_ascii,
         .is_ascii = self->is_ascii && old->is_ascii && new_->is_ascii,
         .is_sso = false,
         .is_sso = false,
         ._ptr = (char*)buffer.data,
         ._ptr = (char*)buffer.data,
@@ -189,8 +246,9 @@ pkpy_Str pkpy_Str__u8_slice(const pkpy_Str *self, int start, int stop, int step)
             pkpy_Str__dtor(&unicode);
             pkpy_Str__dtor(&unicode);
         }
         }
     }
     }
+    c11_vector__push(char, &buffer, '\0');
     pkpy_Str retval = {
     pkpy_Str retval = {
-        .size = buffer.count,
+        .size = buffer.count - 1,
         .is_ascii = self->is_ascii,
         .is_ascii = self->is_ascii,
         .is_sso = false,
         .is_sso = false,
         ._ptr = (char*)buffer.data,
         ._ptr = (char*)buffer.data,

+ 0 - 37
src/common/str.cpp

@@ -56,43 +56,6 @@ Str Str::strip(bool left, bool right) const {
     }
     }
 }
 }
 
 
-Str Str::escape(bool single_quote) const {
-    SStream ss;
-    escape_(ss, single_quote);
-    return ss.str();
-}
-
-void Str::escape_(SStream& ss, bool single_quote) const {
-    ss << (single_quote ? '\'' : '"');
-    for(int i = 0; i < size; i++) {
-        char c = this->operator[] (i);
-        switch(c) {
-            case '"':
-                if(!single_quote) ss << '\\';
-                ss << '"';
-                break;
-            case '\'':
-                if(single_quote) ss << '\\';
-                ss << '\'';
-                break;
-            case '\\': ss << '\\' << '\\'; break;
-            case '\n': ss << "\\n"; break;
-            case '\r': ss << "\\r"; break;
-            case '\t': ss << "\\t"; break;
-            case '\b': ss << "\\b"; break;
-            default:
-                if('\x00' <= c && c <= '\x1f') {
-                    ss << "\\x";  // << std::hex << std::setw(2) << std::setfill('0') << (int)c;
-                    ss << PK_HEX_TABLE[c >> 4];
-                    ss << PK_HEX_TABLE[c & 0xf];
-                } else {
-                    ss << c;
-                }
-        }
-    }
-    ss << (single_quote ? '\'' : '"');
-}
-
 vector<std::string_view> Str::split(const Str& sep) const {
 vector<std::string_view> Str::split(const Str& sep) const {
     vector<std::string_view> result;
     vector<std::string_view> result;
     std::string_view tmp;
     std::string_view tmp;

+ 2 - 2
src/interpreter/vm.cpp

@@ -38,7 +38,7 @@ struct JsonSerializer {
             if(!is_type(k, VM::tp_str)) {
             if(!is_type(k, VM::tp_str)) {
                 vm->TypeError(_S("json keys must be string, got ", _type_name(vm, vm->_tp(k))));
                 vm->TypeError(_S("json keys must be string, got ", _type_name(vm, vm->_tp(k))));
             }
             }
-            ss << _CAST(Str&, k).escape(false) << ": ";
+            ss << _CAST(Str&, k).escape('"') << ": ";
             write_object(v);
             write_object(v);
         });
         });
         ss << '}';
         ss << '}';
@@ -57,7 +57,7 @@ struct JsonSerializer {
         } else if(obj_t == vm->tp_bool) {
         } else if(obj_t == vm->tp_bool) {
             ss << (obj == vm->True ? "true" : "false");
             ss << (obj == vm->True ? "true" : "false");
         } else if(obj_t == vm->tp_str) {
         } else if(obj_t == vm->tp_str) {
-            _CAST(Str&, obj).escape_(ss, false);
+            ss << _CAST(Str&, obj).escape('"');
         } else if(obj_t == vm->tp_list) {
         } else if(obj_t == vm->tp_list) {
             write_array<List>(_CAST(List&, obj));
             write_array<List>(_CAST(List&, obj));
         } else if(obj_t == vm->tp_tuple) {
         } else if(obj_t == vm->tp_tuple) {