diff --git a/include/pocketpy/common/str.h b/include/pocketpy/common/str.h index 9f12b56c..398d2ca9 100644 --- a/include/pocketpy/common/str.h +++ b/include/pocketpy/common/str.h @@ -7,16 +7,16 @@ #include /* string */ -typedef struct c11_string{ +typedef struct c11_string { // int size | char[] | '\0' int size; - const char data[]; // flexible array member + char data[]; // flexible array member } c11_string; /* bytes */ -typedef struct c11_bytes{ +typedef struct c11_bytes { int size; - unsigned char data[]; // flexible array member + unsigned char data[]; // flexible array member } c11_bytes; bool c11_bytes__eq(c11_bytes* self, c11_bytes* other); @@ -33,6 +33,7 @@ c11_string* c11_string__new2(const char* data, int size); c11_string* c11_string__new3(const char* fmt, ...); void c11_string__ctor(c11_string* self, const char* data); void c11_string__ctor2(c11_string* self, const char* data, int size); +void c11_string__ctor3(c11_string* self, int size); c11_string* c11_string__copy(c11_string* self); void c11_string__delete(c11_string* self); c11_sv c11_string__sv(c11_string* self); @@ -55,8 +56,8 @@ bool c11_sv__endswith(c11_sv self, c11_sv suffix); 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_vector/* T=c11_sv */ c11_sv__split(c11_sv self, char sep); -c11_vector/* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep); +c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep); +c11_vector /* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep); // misc int c11__unicode_index_to_byte(const char* data, int i); @@ -65,7 +66,7 @@ int c11__byte_index_to_unicode(const char* data, int n); bool c11__is_unicode_Lo_char(int c); int c11__u8_header(unsigned char c, bool suppress); -typedef enum IntParsingResult{ +typedef enum IntParsingResult { IntParsing_SUCCESS, IntParsing_FAILURE, IntParsing_OVERFLOW, diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 0a69ed71..8d5df06e 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -153,8 +153,10 @@ PK_EXPORT void py_newfloat(py_OutRef, py_f64); PK_EXPORT void py_newbool(py_OutRef, bool); /// Create a `str` object from a null-terminated string (utf-8). PK_EXPORT void py_newstr(py_OutRef, const char*); -/// Create a `str` object from a char array (utf-8). -PK_EXPORT void py_newstrn(py_OutRef, const char*, int); +/// Create a `str` object with `n` UNINITIALIZED bytes plus `'\0'`. +PK_EXPORT char* py_newstrn(py_OutRef, int); +/// Create a `str` object from a `c11_sv`. +PK_EXPORT void py_newstrv(py_OutRef, c11_sv); /// Create a `bytes` object with `n` UNINITIALIZED bytes. PK_EXPORT unsigned char* py_newbytes(py_OutRef, int n); /// Create a `None` object. @@ -504,6 +506,7 @@ PK_EXPORT void py_clearexc(py_StackRef p0); #define NameError(n) py_exception(tp_NameError, "name '%n' is not defined", (n)) #define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__) #define RuntimeError(...) py_exception(tp_RuntimeError, __VA_ARGS__) +#define IOError(...) py_exception(tp_IOError, __VA_ARGS__) #define ValueError(...) py_exception(tp_ValueError, __VA_ARGS__) #define IndexError(...) py_exception(tp_IndexError, __VA_ARGS__) #define ImportError(...) py_exception(tp_ImportError, __VA_ARGS__) diff --git a/include/pybind11/internal/types.h b/include/pybind11/internal/types.h index 70896877..f20ba9cb 100644 --- a/include/pybind11/internal/types.h +++ b/include/pybind11/internal/types.h @@ -136,7 +136,7 @@ iterator interface::end() const { class str : public object { PKBIND_TYPE_IMPL(object, str, tp_str); - str(const char* data, int size) : object(alloc_t{}) { py_newstrn(m_ptr, data, size); } + str(const char* data, int size) : object(alloc_t{}) { py_newstrv(m_ptr, (c11_sv){data, size}); } str(const char* data) : str(data, static_cast(strlen(data))) {} diff --git a/src/common/sstream.c b/src/common/sstream.c index 10ceba9a..5b12dde8 100644 --- a/src/common/sstream.c +++ b/src/common/sstream.c @@ -148,7 +148,7 @@ c11_string* c11_sbuf__submit(c11_sbuf* self) { void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out) { c11_string* res = c11_sbuf__submit(self); - py_newstrn(out, res->data, res->size); + py_newstrv(out, (c11_sv){res->data, res->size}); c11_string__delete(res); } diff --git a/src/common/str.c b/src/common/str.c index 88dee8a8..1b5a9df0 100644 --- a/src/common/str.c +++ b/src/common/str.c @@ -38,6 +38,12 @@ void c11_string__ctor2(c11_string* self, const char* data, int size) { p[size] = '\0'; } +void c11_string__ctor3(c11_string* self, int size) { + self->size = size; + char* p = (char*)self->data; + p[size] = '\0'; +} + c11_string* c11_string__copy(c11_string* self) { int total_size = sizeof(c11_string) + self->size + 1; c11_string* retval = malloc(total_size); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 3fd4c9cb..e5474dc3 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1209,7 +1209,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) { return *val; } else { py_TValue tmp; - py_newstrn(&tmp, key.data, key.size); + py_newstrv(&tmp, key); c11_vector__push(py_TValue, &self->co->consts, tmp); int index = self->co->consts.length - 1; c11_smallmap_s2n__set(&self->co_consts_string_dedup_map, diff --git a/src/modules/linalg.c b/src/modules/linalg.c index d7030d11..1905cd72 100644 --- a/src/modules/linalg.c +++ b/src/modules/linalg.c @@ -163,7 +163,7 @@ static bool vec2__repr__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); char buf[64]; int size = snprintf(buf, 64, "vec2(%.4f, %.4f)", argv[0]._vec2.x, argv[0]._vec2.y); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } @@ -355,7 +355,7 @@ static bool mat3x3__repr__(int argc, py_Ref argv) { m->data[6], m->data[7], m->data[8]); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } @@ -660,7 +660,7 @@ static bool vec2i__repr__(int argc, py_Ref argv) { c11_vec2i data = py_tovec2i(argv); char buf[64]; int size = snprintf(buf, 64, "vec2i(%d, %d)", data.x, data.y); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } @@ -693,7 +693,7 @@ static bool vec3i__repr__(int argc, py_Ref argv) { c11_vec3i data = py_tovec3i(argv); char buf[64]; int size = snprintf(buf, 64, "vec3i(%d, %d, %d)", data.x, data.y, data.z); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } @@ -730,7 +730,7 @@ static bool vec3__repr__(int argc, py_Ref argv) { c11_vec3 data = py_tovec3(argv); char buf[64]; int size = snprintf(buf, 64, "vec3(%.4f, %.4f, %.4f)", data.x, data.y, data.z); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } diff --git a/src/public/modules.c b/src/public/modules.c index d5d82ec1..df1a928a 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -43,7 +43,7 @@ py_Ref py_newmodule(const char* path) { const char* start = path + last_dot + 1; py_newstr(r1, start); py_setdict(r0, __name__, r1); - py_newstrn(r1, path, last_dot); + py_newstrv(r1, (c11_sv){path, last_dot}); py_setdict(r0, __package__, r1); } @@ -404,7 +404,8 @@ static bool builtins_chr(int argc, py_Ref argv) { PY_CHECK_ARG_TYPE(0, tp_int); py_i64 val = py_toint(py_arg(0)); if(val < 0 || val > 128) { return ValueError("chr() arg not in range(128)"); } - py_newstrn(py_retval(), (const char*)&val, 1); + char* data = py_newstrn(py_retval(), 1); + data[0] = (char)val; return true; } diff --git a/src/public/py_number.c b/src/public/py_number.c index 78fa9ddc..5a89315f 100644 --- a/src/public/py_number.c +++ b/src/public/py_number.c @@ -210,7 +210,7 @@ static bool int__repr__(int argc, py_Ref argv) { py_i64 val = py_toint(&argv[0]); char buf[32]; int size = snprintf(buf, sizeof(buf), "%lld", (long long)val); - py_newstrn(py_retval(), buf, size); + py_newstrv(py_retval(), (c11_sv){buf, size}); return true; } diff --git a/src/public/py_str.c b/src/public/py_str.c index 8ebce09c..279fa85a 100644 --- a/src/public/py_str.c +++ b/src/public/py_str.c @@ -6,17 +6,23 @@ #include "pocketpy/interpreter/vm.h" #include "pocketpy/common/sstream.h" -void py_newstr(py_Ref out, const char* data) { py_newstrn(out, data, strlen(data)); } +void py_newstr(py_Ref out, const char* data) { py_newstrv(out, (c11_sv){data, strlen(data)}); } -void py_newstrn(py_Ref out, const char* data, int size) { +char* py_newstrn(py_Ref out, int size) { ManagedHeap* heap = &pk_current_vm->heap; int total_size = sizeof(c11_string) + size + 1; PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size); c11_string* ud = PyObject__userdata(obj); - c11_string__ctor2(ud, data, size); + c11_string__ctor3(ud, size); out->type = tp_str; out->is_ptr = true; out->_obj = obj; + return ud->data; +} + +void py_newstrv(py_OutRef out, c11_sv sv) { + char* data = py_newstrn(out, sv.size); + memcpy(data, sv.data, sv.size); } unsigned char* py_newbytes(py_Ref out, int size) { @@ -97,7 +103,7 @@ static bool str__add__(int argc, py_Ref argv) { int total_size = sizeof(c11_string) + self->size + other->size + 1; c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size); res->size = self->size + other->size; - char* p = (char*)res->data; + char* p = res->data; memcpy(p, self->data, self->size); memcpy(p + self->size, other->data, other->size); p[res->size] = '\0'; @@ -118,7 +124,7 @@ static bool str__mul__(int argc, py_Ref argv) { int total_size = sizeof(c11_string) + self->size * n + 1; c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size); res->size = self->size * n; - char* p = (char*)res->data; + char* p = res->data; for(int i = 0; i < n; i++) { memcpy(p + i * self->size, self->data, self->size); } @@ -174,14 +180,14 @@ static bool str__getitem__(int argc, py_Ref argv) { int index = py_toint(py_arg(1)); if(!pk__normalize_index(&index, self.size)) return false; c11_sv res = c11_sv__u8_getitem(self, index); - py_newstrn(py_retval(), res.data, res.size); + py_newstrv(py_retval(), res); return true; } else if(_1->type == tp_slice) { int start, stop, step; bool ok = pk__parse_int_slice(_1, c11_sv__u8_length(self), &start, &stop, &step); if(!ok) return false; c11_string* res = c11_sv__u8_slice(self, start, stop, step); - py_newstrn(py_retval(), res->data, res->size); + py_newstrv(py_retval(), (c11_sv){res->data, res->size}); c11_string__delete(res); return true; } else { @@ -218,7 +224,7 @@ static bool str_lower(int argc, py_Ref argv) { int total_size = sizeof(c11_string) + self->size + 1; c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size); res->size = self->size; - char* p = (char*)res->data; + char* p = res->data; for(int i = 0; i < self->size; i++) { char c = self->data[i]; p[i] = c >= 'A' && c <= 'Z' ? c + 32 : c; @@ -233,7 +239,7 @@ static bool str_upper(int argc, py_Ref argv) { int total_size = sizeof(c11_string) + self->size + 1; c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size); res->size = self->size; - char* p = (char*)res->data; + char* p = res->data; for(int i = 0; i < self->size; i++) { char c = self->data[i]; p[i] = c >= 'a' && c <= 'z' ? c - 32 : c; @@ -303,7 +309,7 @@ static bool str_replace(int argc, py_Ref argv) { c11_string* new_ = py_touserdata(&argv[2]); c11_string* res = c11_sv__replace2(c11_string__sv(self), c11_string__sv(old), c11_string__sv(new_)); - py_newstrn(py_retval(), res->data, res->size); + py_newstrv(py_retval(), (c11_sv){res->data, res->size}); c11_string__delete(res); return true; } @@ -325,7 +331,7 @@ static bool str_split(int argc, py_Ref argv) { py_newlistn(py_retval(), res.length); for(int i = 0; i < res.length; i++) { c11_sv item = c11__getitem(c11_sv, &res, i); - py_newstrn(py_list_getitem(py_retval(), i), item.data, item.size); + py_newstrv(py_list_getitem(py_retval(), i), item); } c11_vector__dtor(&res); return true; @@ -353,7 +359,7 @@ static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) { return TypeError("strip() takes at most 2 arguments"); } c11_sv res = c11_sv__strip(self, chars, left, right); - py_newstrn(py_retval(), res.data, res.size); + py_newstrv(py_retval(), res); return true; } @@ -506,7 +512,7 @@ static bool str_iterator__next__(int argc, py_Ref argv) { int start = *ud; int len = c11__u8_header(data[*ud], false); *ud += len; - py_newstrn(py_retval(), data + start, len); + py_newstrv(py_retval(), (c11_sv){data + start, len}); return true; } @@ -629,7 +635,7 @@ static bool bytes_decode(int argc, py_Ref argv) { PY_CHECK_ARGC(1); int size; unsigned char* data = py_tobytes(&argv[0], &size); - py_newstrn(py_retval(), (const char*)data, size); + py_newstrv(py_retval(), (c11_sv){(const char*)data, size}); return true; }