mirror of
https://github.com/pocketpy/pocketpy
synced 2026-02-04 06:30:17 +00:00
Compare commits
8 Commits
f95b765207
...
1e17b49403
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e17b49403 | ||
|
|
550f8c9d0e | ||
|
|
0c004a9a16 | ||
|
|
2684038ccf | ||
|
|
a094dcb34d | ||
|
|
3731efba5c | ||
|
|
6cad72453b | ||
|
|
5c7fb79a14 |
@ -1,4 +1,5 @@
|
||||
#include "pocketpy.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define CUTE_PNG_IMPLEMENTATION
|
||||
#include "cute_png.h"
|
||||
@ -9,7 +10,7 @@ static bool cute_png_loads(int argc, py_Ref argv) {
|
||||
int size;
|
||||
unsigned char* data = py_tobytes(argv, &size);
|
||||
cp_image_t image = cp_load_png_mem(data, size);
|
||||
if(image.pix == NULL) return ValueError("cute_png: %s", cp_error_reason);
|
||||
if(image.pix == NULL) return ValueError("cp_load_png_mem() failed");
|
||||
py_newarray2d(py_retval(), image.w, image.h);
|
||||
for(int y = 0; y < image.h; y++) {
|
||||
for(int x = 0; x < image.w; x++) {
|
||||
@ -73,7 +74,19 @@ static bool cute_png_Image__from_bytes_STATIC(int argc, py_Ref argv) {
|
||||
int size;
|
||||
unsigned char* data = py_tobytes(argv, &size);
|
||||
cp_image_t image = cp_load_png_mem(data, size);
|
||||
if(image.pix == NULL) return ValueError("cute_png: %s", cp_error_reason);
|
||||
if(image.pix == NULL) return ValueError("cp_load_png_mem() failed");
|
||||
cp_image_t* ud =
|
||||
py_newobject(py_retval(), py_gettype("cute_png", py_name("Image")), 0, sizeof(cp_image_t));
|
||||
*ud = image;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_Image__from_file_STATIC(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
const char* path = py_tostr(argv);
|
||||
cp_image_t image = cp_load_png(path);
|
||||
if(image.pix == NULL) return ValueError("cp_load_png() failed");
|
||||
cp_image_t* ud =
|
||||
py_newobject(py_retval(), py_gettype("cute_png", py_name("Image")), 0, sizeof(cp_image_t));
|
||||
*ud = image;
|
||||
@ -147,10 +160,41 @@ static bool cute_png_Image__clear(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_Image__to_rgb565_bytes(int argc, py_Ref argv) {
|
||||
static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
cp_image_t* image = py_touserdata(argv);
|
||||
unsigned char* data = py_newbytes(py_retval(), image->w * image->h * 2);
|
||||
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
|
||||
assert(saved_image.data != NULL);
|
||||
unsigned char* data = py_newbytes(py_retval(), saved_image.size);
|
||||
memcpy(data, saved_image.data, saved_image.size);
|
||||
CUTE_PNG_FREE(saved_image.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_Image__to_png_file(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
cp_image_t* image = py_touserdata(argv);
|
||||
const char* path = py_tostr(py_arg(1));
|
||||
FILE* fp = fopen(path, "wb");
|
||||
if(fp == NULL) return OSError("cannot open file '%s' for writing", path);
|
||||
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
|
||||
assert(saved_image.data != NULL);
|
||||
size_t size = fwrite(saved_image.data, saved_image.size, 1, fp);
|
||||
CUTE_PNG_FREE(saved_image.data);
|
||||
fclose(fp);
|
||||
py_newint(py_retval(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_Image__to_rgb565_file(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
cp_image_t* image = py_touserdata(argv);
|
||||
const char* path = py_tostr(py_arg(1));
|
||||
FILE* fp = fopen(path, "wb");
|
||||
if(fp == NULL) return OSError("cannot open file '%s' for writing", path);
|
||||
size_t size = 0;
|
||||
for(int y = 0; y < image->h; y++) {
|
||||
for(int x = 0; x < image->w; x++) {
|
||||
size_t idx = y * image->w + x;
|
||||
@ -160,21 +204,15 @@ static bool cute_png_Image__to_rgb565_bytes(int argc, py_Ref argv) {
|
||||
uint16_t b = (pixel.b >> 3) & 0x1F;
|
||||
uint16_t rgb565 = (r << 11) | (g << 5) | b;
|
||||
// use little-endian
|
||||
data[idx * 2 + 0] = rgb565 & 0xFF;
|
||||
data[idx * 2 + 1] = (rgb565 >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
size_t delta = fwrite(&rgb565, 1, 2, fp);
|
||||
size += delta;
|
||||
if(delta != 2) {
|
||||
py_newint(py_retval(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
cp_image_t* image = py_touserdata(argv);
|
||||
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
|
||||
assert(saved_image.data != NULL);
|
||||
unsigned char* data = py_newbytes(py_retval(), saved_image.size);
|
||||
memcpy(data, saved_image.data, saved_image.size);
|
||||
CUTE_PNG_FREE(saved_image.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
py_newint(py_retval(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -188,6 +226,7 @@ void pk__add_module_cute_png() {
|
||||
|
||||
py_bindmethod(tp_image, "__new__", cute_png_Image__new__);
|
||||
py_bindstaticmethod(tp_image, "from_bytes", cute_png_Image__from_bytes_STATIC);
|
||||
py_bindstaticmethod(tp_image, "from_file", cute_png_Image__from_file_STATIC);
|
||||
|
||||
py_bindproperty(tp_image, "width", cute_png_Image__width, NULL);
|
||||
py_bindproperty(tp_image, "height", cute_png_Image__height, NULL);
|
||||
@ -196,6 +235,7 @@ void pk__add_module_cute_png() {
|
||||
py_bindmethod(tp_image, "getpixel", cute_png_Image__getpixel);
|
||||
py_bindmethod(tp_image, "clear", cute_png_Image__clear);
|
||||
|
||||
py_bindmethod(tp_image, "to_rgb565_bytes", cute_png_Image__to_rgb565_bytes);
|
||||
py_bindmethod(tp_image, "to_png_bytes", cute_png_Image__to_png_bytes);
|
||||
py_bindmethod(tp_image, "to_png_file", cute_png_Image__to_png_file);
|
||||
py_bindmethod(tp_image, "to_rgb565_file", cute_png_Image__to_rgb565_file);
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
uint64_t hash;
|
||||
@ -22,3 +23,9 @@ typedef c11_vector List;
|
||||
|
||||
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack);
|
||||
void function__gc_mark(void* ud, c11_vector* p_stack);
|
||||
|
||||
typedef struct {
|
||||
FILE* file; // cute_png will cast the whole userdata to FILE**
|
||||
const char* path;
|
||||
const char* mode;
|
||||
} io_FileIO;
|
||||
|
||||
@ -11,13 +11,17 @@ class Image:
|
||||
|
||||
@staticmethod
|
||||
def from_bytes(data: bytes) -> "Image": ...
|
||||
@staticmethod
|
||||
def from_file(path: str) -> "Image": ...
|
||||
|
||||
def setpixel(self, x: int, y: int, color: color32) -> None: ...
|
||||
def getpixel(self, x: int, y: int) -> color32: ...
|
||||
def clear(self, color: color32) -> None: ...
|
||||
|
||||
def to_rgb565_bytes(self) -> bytes: ...
|
||||
def to_png_bytes(self) -> bytes: ...
|
||||
def to_png_file(self, path: str) -> int: ...
|
||||
def to_rgb565_file(self, path: str) -> int: ...
|
||||
|
||||
|
||||
def loads(data: bytes) -> array2d[color32]: ...
|
||||
def dumps(image: array2d[color32]) -> bytes: ...
|
||||
|
||||
17
include/typings/io.pyi
Normal file
17
include/typings/io.pyi
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
class FileIO:
|
||||
def __new__(cls, file: str, mode: str) -> "FileIO": ...
|
||||
|
||||
def __enter__(self) -> "FileIO": ...
|
||||
def __exit__(self) -> None: ...
|
||||
|
||||
def read(self, size: int | None = None) -> bytes: ...
|
||||
def write(self, data: bytes) -> int: ...
|
||||
def close(self) -> None: ...
|
||||
def tell(self) -> int: ...
|
||||
def seek(self, offset: int, whence: int) -> None: ...
|
||||
def flush(self) -> None: ...
|
||||
|
||||
SEEK_SET: int
|
||||
SEEK_CUR: int
|
||||
SEEK_END: int
|
||||
@ -580,6 +580,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
// [cls, NULL, args..., kwargs...]
|
||||
py_Ref new_f = py_tpfindmagic(py_totype(p0), __new__);
|
||||
assert(new_f && py_isnil(p0 + 1));
|
||||
bool is_default_new = new_f->type == tp_nativefunc && new_f->_cfunc == pk__object_new;
|
||||
|
||||
// prepare a copy of args and kwargs
|
||||
int span = self->stack.sp - argv;
|
||||
@ -603,6 +604,13 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
// [__init__, self, args..., kwargs...]
|
||||
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||
*py_retval() = p0[1]; // restore the new instance
|
||||
} else {
|
||||
if(is_default_new) {
|
||||
if(argc != 0 || kwargc != 0) {
|
||||
TypeError("%t() takes no arguments", py_totype(p0));
|
||||
return RES_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
// reset the stack
|
||||
self->stack.sp = p0;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/interpreter/types.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#if PK_ENABLE_OS
|
||||
@ -101,12 +102,6 @@ void pk__add_module_os() {
|
||||
py_newdict(py_emplacedict(mod, py_name("environ")));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
const char* mode;
|
||||
FILE* file;
|
||||
} io_FileIO;
|
||||
|
||||
static bool io_FileIO__new__(int argc, py_Ref argv) {
|
||||
// __new__(cls, file, mode)
|
||||
PY_CHECK_ARGC(3);
|
||||
@ -213,6 +208,14 @@ static bool io_FileIO_write(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool io_FileIO_flush(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
io_FileIO* ud = py_touserdata(py_arg(0));
|
||||
fflush(ud->file);
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_io() {
|
||||
py_Ref mod = py_newmodule("io");
|
||||
|
||||
@ -226,6 +229,7 @@ void pk__add_module_io() {
|
||||
py_bindmethod(FileIO, "close", io_FileIO_close);
|
||||
py_bindmethod(FileIO, "tell", io_FileIO_tell);
|
||||
py_bindmethod(FileIO, "seek", io_FileIO_seek);
|
||||
py_bindmethod(FileIO, "flush", io_FileIO_flush);
|
||||
|
||||
py_newint(py_emplacedict(mod, py_name("SEEK_SET")), SEEK_SET);
|
||||
py_newint(py_emplacedict(mod, py_name("SEEK_CUR")), SEEK_CUR);
|
||||
|
||||
@ -167,8 +167,26 @@ static bool list__setitem__(int argc, py_Ref argv) {
|
||||
|
||||
static bool list__delitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
|
||||
if(py_istype(py_arg(1), tp_slice)) {
|
||||
int start, stop, step;
|
||||
bool ok = pk__parse_int_slice(py_arg(1), self->length, &start, &stop, &step);
|
||||
if(!ok) return false;
|
||||
if(step != 1) return ValueError("slice step must be 1 for deletion");
|
||||
int n = stop - start;
|
||||
if(n > 0) {
|
||||
py_TValue* p = self->data;
|
||||
for(int i = stop; i < self->length; i++) {
|
||||
p[start + i - stop] = p[i];
|
||||
}
|
||||
self->length -= n;
|
||||
}
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
int index = py_toint(py_arg(1));
|
||||
if(!pk__normalize_index(&index, self->length)) return false;
|
||||
c11_vector__erase(py_TValue, self, index);
|
||||
|
||||
@ -160,6 +160,16 @@ b = [(1, 2), (3, 3), (5, 1)]
|
||||
b.sort(key=lambda x:x[1])
|
||||
assert b == [(5, 1), (1, 2), (3,3)]
|
||||
|
||||
# test del slice
|
||||
a = [1, 2, 3, 4]
|
||||
b = a.copy(); del b[:2]; assert b == [3, 4]
|
||||
b = a.copy(); del b[1:3]; assert b == [1, 4]
|
||||
b = a.copy(); del b[2:]; assert b == [1, 2]
|
||||
b = a.copy(); del b[:-1]; assert b == [4]
|
||||
b = a.copy(); del b[-1:]; assert b == [1, 2, 3]
|
||||
b = a.copy(); del b[:]; assert b == []
|
||||
assert a == [1, 2, 3, 4]
|
||||
|
||||
# test cyclic reference
|
||||
# a = []
|
||||
# a.append(0)
|
||||
|
||||
@ -136,3 +136,23 @@ assert MyClass.c == 2
|
||||
assert MyClass.d == 3
|
||||
|
||||
assert MyClass(1, 2).m == 1
|
||||
|
||||
class E: pass
|
||||
try:
|
||||
E(1,2,3)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
class E1:
|
||||
def __new__(cls, a, b):
|
||||
o = object.__new__(cls)
|
||||
o.a = a
|
||||
o.b = b
|
||||
return o
|
||||
|
||||
def sum(self):
|
||||
return self.a + self.b
|
||||
|
||||
e1 = E1(3,4)
|
||||
assert e1.sum() == 7
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user