blueloveTH 2 лет назад
Родитель
Сommit
8f11ce0466
5 измененных файлов с 119 добавлено и 72 удалено
  1. 4 2
      include/pocketpy/str.h
  2. 3 54
      python/builtins.py
  3. 68 0
      src/pocketpy.cpp
  4. 24 16
      src/str.cpp
  5. 20 0
      tests/04_str.py

+ 4 - 2
include/pocketpy/str.h

@@ -65,8 +65,10 @@ struct Str{
     const char* c_str() const;
     std::string_view sv() const;
     std::string str() const;
-    Str lstrip() const;
-    Str strip() const;
+    Str strip(bool left, bool right, const Str& chars) const;
+    Str strip(bool left=true, bool right=true) const;
+    Str lstrip() const { return strip(true, false); }
+    Str rstrip() const { return strip(false, true); }
     Str lower() const;
     Str upper() const;
     Str escape(bool single_quote=true) const;

+ 3 - 54
python/builtins.py

@@ -86,7 +86,7 @@ def sorted(iterable, key=None, reverse=False):
     return a
 
 ##### str #####
-def __f(self: str, *args, **kwargs) -> str:
+def __format_string(self: str, *args, **kwargs) -> str:
     def tokenizeString(s: str):
         tokens = []
         L, R = 0,0
@@ -195,59 +195,8 @@ def __f(self: str, *args, **kwargs) -> str:
     
     return ''.join(final_tokens)
 
-str.format = __f
-
-def __f(self, chars=None):
-    chars = chars or ' \t\n\r'
-    i = 0
-    while i < len(self) and self[i] in chars:
-        ++i
-    return self[i:]
-str.lstrip = __f
-
-def __f(self, chars=None):
-    chars = chars or ' \t\n\r'
-    j = len(self) - 1
-    while j >= 0 and self[j] in chars:
-        --j
-    return self[:j+1]
-str.rstrip = __f
-
-def __f(self, chars=None):
-    chars = chars or ' \t\n\r'
-    i = 0
-    while i < len(self) and self[i] in chars:
-        ++i
-    j = len(self) - 1
-    while j >= 0 and self[j] in chars:
-        --j
-    return self[i:j+1]
-str.strip = __f
-
-def __f(self, width: int):
-    delta = width - len(self)
-    if delta <= 0:
-        return self
-    return '0' * delta + self
-str.zfill = __f
-
-def __f(self, width: int, fillchar=' '):
-    delta = width - len(self)
-    if delta <= 0:
-        return self
-    assert len(fillchar) == 1
-    return fillchar * delta + self
-str.rjust = __f
-
-def __f(self, width: int, fillchar=' '):
-    delta = width - len(self)
-    if delta <= 0:
-        return self
-    assert len(fillchar) == 1
-    return self + fillchar * delta
-str.ljust = __f
-
-del __f
+str.format = __format_string
+del __format_string
 
 
 def help(obj):

+ 68 - 0
src/pocketpy.cpp

@@ -641,6 +641,74 @@ void init_builtins(VM* _vm) {
         return VAR(self.upper());
     });
 
+    _vm->bind(_vm->_t(VM::tp_str), "strip(self, chars=None)", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        if(args[1] == vm->None){
+            return VAR(self.strip());
+        }else{
+            const Str& chars = CAST(Str&, args[1]);
+            return VAR(self.strip(true, true, chars));
+        }
+    });
+
+    _vm->bind(_vm->_t(VM::tp_str), "lstrip(self, chars=None)", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        if(args[1] == vm->None){
+            return VAR(self.lstrip());
+        }else{
+            const Str& chars = CAST(Str&, args[1]);
+            return VAR(self.strip(true, false, chars));
+        }
+    });
+
+    _vm->bind(_vm->_t(VM::tp_str), "rstrip(self, chars=None)", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        if(args[1] == vm->None){
+            return VAR(self.rstrip());
+        }else{
+            const Str& chars = CAST(Str&, args[1]);
+            return VAR(self.strip(false, true, chars));
+        }
+    });
+
+    // zfill
+    _vm->bind(_vm->_t(VM::tp_str), "zfill(self, width)", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        int width = CAST(int, args[1]);
+        int delta = width - self.u8_length();
+        if(delta <= 0) return args[0];
+        SStream ss;
+        for(int i=0; i<delta; i++) ss << '0';
+        ss << self;
+        return VAR(ss.str());
+    });
+
+    // ljust
+    _vm->bind(_vm->_t(VM::tp_str), "ljust(self, width, fillchar=' ')", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        int width = CAST(int, args[1]);
+        int delta = width - self.u8_length();
+        if(delta <= 0) return args[0];
+        const Str& fillchar = CAST(Str&, args[2]);
+        SStream ss;
+        ss << self;
+        for(int i=0; i<delta; i++) ss << fillchar;
+        return VAR(ss.str());
+    });
+
+    // rjust
+    _vm->bind(_vm->_t(VM::tp_str), "rjust(self, width, fillchar=' ')", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        int width = CAST(int, args[1]);
+        int delta = width - self.u8_length();
+        if(delta <= 0) return args[0];
+        const Str& fillchar = CAST(Str&, args[2]);
+        SStream ss;
+        for(int i=0; i<delta; i++) ss << fillchar;
+        ss << self;
+        return VAR(ss.str());
+    });
+
     // tp_list / tp_tuple
     _vm->bind(_vm->_t(VM::tp_list), "sort(self, key=None, reverse=False)", [](VM* vm, ArgsView args) {
         List& self = _CAST(List&, args[0]);

+ 24 - 16
src/str.cpp

@@ -194,24 +194,32 @@ int utf8len(unsigned char c, bool suppress){
         return std::string(data, size);
     }
 
-    Str Str::lstrip() const {
-        std::string copy(data, size);
-        copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
-            // std::isspace(c) does not working on windows (Debug)
-            return c != ' ' && c != '\t' && c != '\r' && c != '\n';
-        }));
-        return Str(copy);
+    Str Str::strip(bool left, bool right, const Str& chars) const {
+        int L = 0;
+        int R = u8_length();
+        if(left){
+            while(L < R && chars.index(u8_getitem(L)) != -1) L++;
+        }
+        if(right){
+            while(L < R && chars.index(u8_getitem(R-1)) != -1) R--;
+        }
+        return u8_slice(L, R, 1);
     }
 
-    Str Str::strip() const {
-        std::string copy(data, size);
-        copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
-            return c != ' ' && c != '\t' && c != '\r' && c != '\n';
-        }));
-        copy.erase(std::find_if(copy.rbegin(), copy.rend(), [](char c) {
-            return c != ' ' && c != '\t' && c != '\r' && c != '\n';
-        }).base(), copy.end());
-        return Str(copy);
+    Str Str::strip(bool left, bool right) const {
+        if(is_ascii){
+            int L = 0;
+            int R = size;
+            if(left){
+                while(L < R && (data[L] == ' ' || data[L] == '\t' || data[L] == '\n' || data[L] == '\r')) L++;
+            }
+            if(right){
+                while(L < R && (data[R-1] == ' ' || data[R-1] == '\t' || data[R-1] == '\n' || data[R-1] == '\r')) R--;
+            }
+            return substr(L, R - L);
+        }else{
+            return strip(left, right, " \t\n\r");
+        }
     }
 
     Str Str::lower() const{

+ 20 - 0
tests/04_str.py

@@ -69,6 +69,26 @@ assert s.strip( '12' ) == "3abcrunoob3"
 assert t.strip( '*' ) == "this is **string** example....wow!!!"
 assert s.strip( '12' ) == "3abcrunoob3"
 
+assert '测试123'.strip('测试') == '123'
+assert '测试123测试'.strip('测试') == '123'
+assert '123测试'.strip('2') == '123测试'
+assert '测试123'.strip('测') == '试123'
+assert '测试123'.strip('试') == '测试123'
+
+assert '测试123测试'.lstrip('测试') == '123测试'
+assert '测试123测试'.rstrip('测试') == '测试123'
+
+assert 'abc'.lstrip('a') == 'bc'
+assert 'abc'.lstrip('b') == 'abc'
+assert 'abc'.lstrip('c') == 'abc'
+assert 'abc'.rstrip('a') == 'abc'
+assert 'abc'.rstrip('b') == 'abc'
+assert 'abc'.rstrip('c') == 'ab'
+
+assert 'abc'.lstrip('abc') == ''
+assert 'abc'.rstrip('abc') == ''
+assert 'abc'.strip('abc') == ''
+
 s = ' asd\n  asd \n'
 assert s.strip() == 'asd\n  asd'