Parcourir la source

add `SStream`

blueloveTH il y a 2 ans
Parent
commit
e4b6d566a7
6 fichiers modifiés avec 68 ajouts et 129 suppressions
  1. 2 2
      include/pocketpy/cffi.h
  2. 52 12
      include/pocketpy/str.h
  3. 13 0
      include/pocketpy/vector.h
  4. 1 1
      src/pocketpy.cpp
  5. 0 21
      src/str.cpp
  6. 0 93
      tests/99_builtin_func.py

+ 2 - 2
include/pocketpy/cffi.h

@@ -18,8 +18,8 @@ namespace pkpy {
     }                                                                       \
     }                                                                       \
     static PyObject* register_class(VM* vm, PyObject* mod, Type base=0) {   \
     static PyObject* register_class(VM* vm, PyObject* mod, Type base=0) {   \
         if(OBJ_NAME(mod) != #mod) {                                         \
         if(OBJ_NAME(mod) != #mod) {                                         \
-            auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
-            throw std::runtime_error(msg);                                  \
+            Str msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
+            throw std::runtime_error(msg.str());                            \
         }                                                                   \
         }                                                                   \
         PyObject* type = vm->new_type_object(mod, #name, base);             \
         PyObject* type = vm->new_type_object(mod, #name, base);             \
         T::_register(vm, mod, type);                                        \
         T::_register(vm, mod, type);                                        \

+ 52 - 12
include/pocketpy/str.h

@@ -85,13 +85,6 @@ struct Str{
     int u8_length() const;
     int u8_length() const;
 };
 };
 
 
-template<typename... Args>
-std::string fmt(Args&&... args) {
-    std::stringstream ss;
-    (ss << ... << args);
-    return ss.str();
-}
-
 struct StrName {
 struct StrName {
     uint16_t index;
     uint16_t index;
     StrName();
     StrName();
@@ -127,13 +120,60 @@ struct StrName {
     static uint32_t _pesudo_random_index;
     static uint32_t _pesudo_random_index;
 };
 };
 
 
-struct FastStrStream{
-    pod_vector<const Str*> parts;
-    FastStrStream& operator<<(const Str& s);
-    bool empty() const { return parts.empty(); }
-    Str str() const;
+struct SStream{
+    PK_ALWAYS_PASS_BY_POINTER(SStream)
+    // pod_vector<T> is allocated by pool64 so the buffer can be moved into Str without a copy
+    pod_vector<char> buffer;
+    bool empty() const { return buffer.empty(); }
+
+    SStream(){}
+    SStream(int guess_size){ buffer.reserve(guess_size); }
+
+    Str str(){
+        // after this call, the buffer is no longer valid
+        auto detached = buffer.detach();
+        return Str(detached.first, detached.second);
+    }
+
+    SStream& operator<<(const Str& s){
+        buffer.extend(s.begin(), s.end());
+        return *this;
+    }
+
+    SStream& operator<<(const char* s){
+        buffer.extend(s, s + strlen(s));
+        return *this;
+    }
+
+    SStream& operator<<(const std::string& s){
+        buffer.extend(s.data(), s.data() + s.size());
+        return *this;
+    }
+
+    SStream& operator<<(std::string_view s){
+        buffer.extend(s.data(), s.data() + s.size());
+        return *this;
+    }
+
+    SStream& operator<<(char c){
+        buffer.push_back(c);
+        return *this;
+    }
+
+    template<typename T>
+    SStream& operator<<(T val){
+        (*this) << std::to_string(val);
+        return *this;
+    }
 };
 };
 
 
+template<typename... Args>
+Str fmt(Args&&... args) {
+    SStream ss;
+    (ss << ... << args);
+    return ss.str();
+}
+
 struct CString{
 struct CString{
 	const char* ptr;
 	const char* ptr;
 	CString(const char* ptr): ptr(ptr) {}
 	CString(const char* ptr): ptr(ptr) {}

+ 13 - 0
include/pocketpy/vector.h

@@ -72,10 +72,15 @@ struct pod_vector{
 
 
     void pop_back() { _size--; }
     void pop_back() { _size--; }
     T popx_back() { T t = std::move(_data[_size-1]); _size--; return t; }
     T popx_back() { T t = std::move(_data[_size-1]); _size--; return t; }
+    
     void extend(const pod_vector& other){
     void extend(const pod_vector& other){
         for(int i=0; i<other.size(); i++) push_back(other[i]);
         for(int i=0; i<other.size(); i++) push_back(other[i]);
     }
     }
 
 
+    void extend(const T* begin, const T* end){
+        for(auto it=begin; it!=end; it++) push_back(*it);
+    }
+
     T& operator[](int index) { return _data[index]; }
     T& operator[](int index) { return _data[index]; }
     const T& operator[](int index) const { return _data[index]; }
     const T& operator[](int index) const { return _data[index]; }
 
 
@@ -114,6 +119,14 @@ struct pod_vector{
         _size = size;
         _size = size;
     }
     }
 
 
+    std::pair<T*, int> detach() noexcept {
+        T* p = _data;
+        int size = _size;
+        _data = nullptr;
+        _size = 0;
+        return {p, size};
+    }
+
     ~pod_vector() {
     ~pod_vector() {
         if(_data!=nullptr) pool64_dealloc(_data);
         if(_data!=nullptr) pool64_dealloc(_data);
     }
     }

+ 1 - 1
src/pocketpy.cpp

@@ -677,7 +677,7 @@ void init_builtins(VM* _vm) {
     _vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
     _vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
         auto _lock = vm->heap.gc_scope_lock();
         auto _lock = vm->heap.gc_scope_lock();
         const Str& self = _CAST(Str&, args[0]);
         const Str& self = _CAST(Str&, args[0]);
-        FastStrStream ss;
+        SStream ss;
         PyObject* it = vm->py_iter(args[1]);     // strong ref
         PyObject* it = vm->py_iter(args[1]);     // strong ref
         PyObject* obj = vm->py_next(it);
         PyObject* obj = vm->py_next(it);
         while(obj != vm->StopIteration){
         while(obj != vm->StopIteration){

+ 0 - 21
src/str.cpp

@@ -404,25 +404,4 @@ int utf8len(unsigned char c, bool suppress){
         const std::string& str = _r_interned()[index];
         const std::string& str = _r_interned()[index];
         return std::string_view(str);
         return std::string_view(str);
     }
     }
-
-    FastStrStream& FastStrStream::operator<<(const Str& s){
-        parts.push_back(&s);
-        return *this;
-    }
-
-    Str FastStrStream::str() const{
-        int len = 0;
-        bool is_ascii = true;
-        for(auto& s: parts){
-            len += s->length();
-            is_ascii &= s->is_ascii;
-        }
-        Str result(len, is_ascii);
-        char* p = result.data;
-        for(auto& s: parts){
-            memcpy(p, s->data, s->length());
-            p += s->length();
-        }
-        return result;    
-    }
 } // namespace pkpy
 } // namespace pkpy

+ 0 - 93
tests/99_builtin_func.py

@@ -220,33 +220,6 @@ for i in range(128):
 assert l == ['0 \x00', '1 \x01', '2 \x02', '3 \x03', '4 \x04', '5 \x05', '6 \x06', '7 \x07', '8 \x08', '9 \t', '10 \n', '11 \x0b', '12 \x0c', '13 \r', '14 \x0e', '15 \x0f', '16 \x10', '17 \x11', '18 \x12', '19 \x13', '20 \x14', '21 \x15', '22 \x16', '23 \x17', '24 \x18', '25 \x19', '26 \x1a', '27 \x1b', '28 \x1c', '29 \x1d', '30 \x1e', '31 \x1f', '32  ', '33 !', '34 "', '35 #', '36 $', '37 %', '38 &', "39 '", '40 (', '41 )', '42 *', '43 +', '44 ,', '45 -', '46 .', '47 /', '48 0', '49 1', '50 2', '51 3', '52 4', '53 5', '54 6', '55 7', '56 8', '57 9', '58 :', '59 ;', '60 <', '61 =', '62 >', '63 ?', '64 @', '65 A', '66 B', '67 C', '68 D', '69 E', '70 F', '71 G', '72 H', '73 I', '74 J', '75 K', '76 L', '77 M', '78 N', '79 O', '80 P', '81 Q', '82 R', '83 S', '84 T', '85 U', '86 V', '87 W', '88 X', '89 Y', '90 Z', '91 [', '92 \\', '93 ]', '94 ^', '95 _', '96 `', '97 a', '98 b', '99 c', '100 d', '101 e', '102 f', '103 g', '104 h', '105 i', '106 j', '107 k', '108 l', '109 m', '110 n', '111 o', '112 p', '113 q', '114 r', '115 s', '116 t', '117 u', '118 v', '119 w', '120 x', '121 y', '122 z', '123 {', '124 |', '125 }', '126 ~', '127 \x7f']
 assert l == ['0 \x00', '1 \x01', '2 \x02', '3 \x03', '4 \x04', '5 \x05', '6 \x06', '7 \x07', '8 \x08', '9 \t', '10 \n', '11 \x0b', '12 \x0c', '13 \r', '14 \x0e', '15 \x0f', '16 \x10', '17 \x11', '18 \x12', '19 \x13', '20 \x14', '21 \x15', '22 \x16', '23 \x17', '24 \x18', '25 \x19', '26 \x1a', '27 \x1b', '28 \x1c', '29 \x1d', '30 \x1e', '31 \x1f', '32  ', '33 !', '34 "', '35 #', '36 $', '37 %', '38 &', "39 '", '40 (', '41 )', '42 *', '43 +', '44 ,', '45 -', '46 .', '47 /', '48 0', '49 1', '50 2', '51 3', '52 4', '53 5', '54 6', '55 7', '56 8', '57 9', '58 :', '59 ;', '60 <', '61 =', '62 >', '63 ?', '64 @', '65 A', '66 B', '67 C', '68 D', '69 E', '70 F', '71 G', '72 H', '73 I', '74 J', '75 K', '76 L', '77 M', '78 N', '79 O', '80 P', '81 Q', '82 R', '83 S', '84 T', '85 U', '86 V', '87 W', '88 X', '89 Y', '90 Z', '91 [', '92 \\', '93 ]', '94 ^', '95 _', '96 `', '97 a', '98 b', '99 c', '100 d', '101 e', '102 f', '103 g', '104 h', '105 i', '106 j', '107 k', '108 l', '109 m', '110 n', '111 o', '112 p', '113 q', '114 r', '115 s', '116 t', '117 u', '118 v', '119 w', '120 x', '121 y', '122 z', '123 {', '124 |', '125 }', '126 ~', '127 \x7f']
 
 
 
 
-
-
-
-
-
-
-
-
-
-# 未完全测试准确性-----------------------------------------------
-#       116:  269:    _vm->bind_builtin_func<1>("bin", [](VM* vm, ArgsView args) {
-#     #####:  270:        std::stringstream ss;
-#     #####:  271:        i64 x = CAST(i64, args[0]);
-#     #####:  272:        if(x < 0){ ss << "-"; x = -x; }
-#     #####:  273:        ss << "0b";
-#     #####:  274:        std::string bits;
-#     #####:  275:        while(x){
-#     #####:  276:            bits += (x & 1) ? '1' : '0';
-#     #####:  277:            x >>= 1;
-#         -:  278:        }
-#     #####:  279:        std::reverse(bits.begin(), bits.end());
-#     #####:  280:        if(bits.empty()) bits = "0";
-#     #####:  281:        ss << bits;
-#     #####:  282:        return VAR(ss.str());
-#     #####:  283:    });
-# test bin:
-
 assert type(bin(1234)) is str
 assert type(bin(1234)) is str
 
 
 # 无法测试, 不能覆盖-----------------------------------------------
 # 无法测试, 不能覆盖-----------------------------------------------
@@ -265,15 +238,6 @@ assert type(bin(1234)) is str
 #        10:  297:    });
 #        10:  297:    });
 # test dir:
 # test dir:
 
 
-
-# 未完全测试准确性-----------------------------------------------
-#       116:  299:    _vm->bind__repr__(_vm->tp_object, [](VM* vm, PyObject* obj) {
-#     #####:  300:        if(is_tagged(obj)) FATAL_ERROR();
-#     #####:  301:        std::stringstream ss;
-#     #####:  302:        ss << "<" << OBJ_NAME(vm->_t(obj)) << " object at 0x";
-#     #####:  303:        ss << std::hex << reinterpret_cast<intptr_t>(obj) << ">";
-#     #####:  304:        return VAR(ss.str());
-#     #####:  305:    });
 # test __repr__:
 # test __repr__:
 class A():
 class A():
     def __init__(self):
     def __init__(self):
@@ -361,14 +325,6 @@ except:
     pass
     pass
 
 
 # /************ str ************/
 # /************ str ************/
-# 未完全测试准确性-----------------------------------------------
-#       116:  495:    _vm->bind_method<1>("str", "__rmul__", [](VM* vm, ArgsView args) {
-#     #####:  496:        const Str& self = _CAST(Str&, args[0]);
-#     #####:  497:        i64 n = CAST(i64, args[1]);
-#     #####:  498:        std::stringstream ss;
-#     #####:  499:        for(i64 i = 0; i < n; i++) ss << self.sv();
-#     #####:  500:        return VAR(ss.str());
-#     #####:  501:    });
 # test str.__rmul__:
 # test str.__rmul__:
 assert type(12 * '12') is str
 assert type(12 * '12') is str
 
 
@@ -600,16 +556,6 @@ assert type(hash(bytes([0x41, 0x42, 0x43]))) is int
 
 
 
 
 # 未完全测试准确性-----------------------------------------------
 # 未完全测试准确性-----------------------------------------------
-#       116:  928:    _vm->bind__repr__(_vm->tp_bytes, [](VM* vm, PyObject* obj) {
-#     #####:  929:        const Bytes& self = _CAST(Bytes&, obj);
-#     #####:  930:        std::stringstream ss;
-#     #####:  931:        ss << "b'";
-#     #####:  932:        for(int i=0; i<self.size(); i++){
-#     #####:  933:            ss << "\\x" << std::hex << std::setw(2) << std::setfill('0') << self[i];
-#         -:  934:        }
-#     #####:  935:        ss << "'";
-#     #####:  936:        return VAR(ss.str());
-#     #####:  937:    });
 # test bytes.__repr__:
 # test bytes.__repr__:
 assert type(repr(bytes([0x41, 0x42, 0x43]))) is str
 assert type(repr(bytes([0x41, 0x42, 0x43]))) is str
 
 
@@ -641,15 +587,6 @@ assert s.step == 3
 assert slice.__dict__['start'].__signature__ == 'start'
 assert slice.__dict__['start'].__signature__ == 'start'
 
 
 # 未完全测试准确性-----------------------------------------------
 # 未完全测试准确性-----------------------------------------------
-#       116:  957:    _vm->bind__repr__(_vm->tp_slice, [](VM* vm, PyObject* obj) {
-#     #####:  958:        const Slice& self = _CAST(Slice&, obj);
-#     #####:  959:        std::stringstream ss;
-#     #####:  960:        ss << "slice(";
-#     #####:  961:        ss << CAST(Str, vm->py_repr(self.start)) << ", ";
-#     #####:  962:        ss << CAST(Str, vm->py_repr(self.stop)) << ", ";
-#     #####:  963:        ss << CAST(Str, vm->py_repr(self.step)) << ")";
-#     #####:  964:        return VAR(ss.str());
-#     #####:  965:    });
 # test slice.__repr__
 # test slice.__repr__
 assert type(repr(slice(1,1,1))) is str
 assert type(repr(slice(1,1,1))) is str
 
 
@@ -744,19 +681,6 @@ except TypeError:
     pass
     pass
 
 
 # 未完全测试准确性-----------------------------------------------
 # 未完全测试准确性-----------------------------------------------
-#       116: 1009:    _vm->bind__repr__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj) {
-#     #####: 1010:        MappingProxy& self = _CAST(MappingProxy&, obj);
-#     #####: 1011:        std::stringstream ss;
-#     #####: 1012:        ss << "mappingproxy({";
-#         -: 1013:        bool first = true;
-#     #####: 1014:        for(auto& item : self.attr().items()){
-#     #####: 1015:            if(!first) ss << ", ";
-#         -: 1016:            first = false;
-#     #####: 1017:            ss << item.first.escape() << ": " << CAST(Str, vm->py_repr(item.second));
-#         -: 1018:        }
-#     #####: 1019:        ss << "})";
-#     #####: 1020:        return VAR(ss.str());
-#     #####: 1021:    });
 # test mappingproxy.__repr__:
 # test mappingproxy.__repr__:
 class A():
 class A():
     def __init__(self):
     def __init__(self):
@@ -859,23 +783,6 @@ except:
     pass
     pass
 
 
 # 未完全测试准确性-----------------------------------------------
 # 未完全测试准确性-----------------------------------------------
-#       116: 1151:    _vm->bind__repr__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
-#     #####: 1152:        Dict& self = _CAST(Dict&, obj);
-#     #####: 1153:        std::stringstream ss;
-#     #####: 1154:        ss << "{";
-#     #####: 1155:        bool first = true;
-#         -: 1156:
-#     #####: 1157:        self.apply([&](PyObject* k, PyObject* v){
-#     #####: 1158:            if(!first) ss << ", ";
-#     #####: 1159:            first = false;
-#     #####: 1160:            Str key = CAST(Str&, vm->py_repr(k));
-#     #####: 1161:            Str value = CAST(Str&, vm->py_repr(v));
-#     #####: 1162:            ss << key << ": " << value;
-#     #####: 1163:        });
-#         -: 1164:
-#     #####: 1165:        ss << "}";
-#     #####: 1166:        return VAR(ss.str());
-#     #####: 1167:    });
 # test dict.__repr__
 # test dict.__repr__
 assert type(repr({1:2, 3:4})) is str
 assert type(repr({1:2, 3:4})) is str