mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add SStream
This commit is contained in:
parent
3f7435263a
commit
e4b6d566a7
@ -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); \
|
Str msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
|
||||||
throw std::runtime_error(msg); \
|
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); \
|
||||||
|
@ -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{
|
struct SStream{
|
||||||
pod_vector<const Str*> parts;
|
PK_ALWAYS_PASS_BY_POINTER(SStream)
|
||||||
FastStrStream& operator<<(const Str& s);
|
// pod_vector<T> is allocated by pool64 so the buffer can be moved into Str without a copy
|
||||||
bool empty() const { return parts.empty(); }
|
pod_vector<char> buffer;
|
||||||
Str str() const;
|
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) {}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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){
|
||||||
|
21
src/str.cpp
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
|
@ -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
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user