From 45a07c57732e2656bfc328f1eff05752c26e2232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=82?= Date: Fri, 15 Jul 2022 02:06:23 +0000 Subject: [PATCH] !58 Support read() builtin * support read(-1) * add example --- examples/BuiltIn/file.py | 11 +++ examples/PikaMath/Quaternion_test.py | 11 +++ package/PikaStdLib/PikaStdData.pyi | 7 ++ package/PikaStdLib/PikaStdData_FILEIO.c | 68 +++++++++++++++++ package/PikaStdLib/PikaStdLib.pyi | 65 ++++++++++------ package/PikaStdLib/PikaStdLib_SysObj.c | 13 ++++ port/linux/package/pikascript/PikaStdData.pyi | 7 ++ port/linux/package/pikascript/PikaStdLib.pyi | 65 ++++++++++------ .../PikaStdLib/PikaStdData_FILEIO.c | 74 +++++++++++++++++++ .../PikaStdLib/PikaStdLib_SysObj.c | 13 ++++ port/linux/test/stddata-test.cpp | 18 +++++ src/PikaPlatform.h | 1 + src/pika_config_valid.h | 12 +++ 13 files changed, 323 insertions(+), 42 deletions(-) create mode 100644 examples/BuiltIn/file.py create mode 100644 examples/PikaMath/Quaternion_test.py create mode 100644 package/PikaStdLib/PikaStdData_FILEIO.c create mode 100644 port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_FILEIO.c diff --git a/examples/BuiltIn/file.py b/examples/BuiltIn/file.py new file mode 100644 index 000000000..aa97bf51a --- /dev/null +++ b/examples/BuiltIn/file.py @@ -0,0 +1,11 @@ +f = open('test/python/main.py', 'r') +s = f.read(10) +print(s) +f.close() +f = open('test/assets/test.jpg', 'rb') +b = f.read(-1) +print(b) +f.close() +f = open('test/assets/write.txt', 'w') +f.write('Hello World!\n') +f.close() diff --git a/examples/PikaMath/Quaternion_test.py b/examples/PikaMath/Quaternion_test.py new file mode 100644 index 000000000..72fd1ad10 --- /dev/null +++ b/examples/PikaMath/Quaternion_test.py @@ -0,0 +1,11 @@ +import PikaMath + +a=Quaternion() +a.set(0.592,0.158,0.592,0.525) + +b=Quaternion() + +a.add(b) +a.mul(b) + + diff --git a/package/PikaStdLib/PikaStdData.pyi b/package/PikaStdLib/PikaStdData.pyi index 26f7fe23d..649a7f095 100644 --- a/package/PikaStdLib/PikaStdData.pyi +++ b/package/PikaStdLib/PikaStdData.pyi @@ -94,6 +94,13 @@ class ByteArray(TinyObj): def decode(self) -> str: ... +class FILEIO: + def init(self, path: str, mode: str): ... + def read(self, size: int) -> any: ... + def write(self, s: any): ... + def close(self): ... + + class Utils: # convert a int to bytes def int_to_bytes(self, val: int) -> bytes: ... diff --git a/package/PikaStdLib/PikaStdData_FILEIO.c b/package/PikaStdLib/PikaStdData_FILEIO.c new file mode 100644 index 000000000..bc9476320 --- /dev/null +++ b/package/PikaStdLib/PikaStdData_FILEIO.c @@ -0,0 +1,68 @@ +#include "PikaStdData_FILEIO.h" +#include + +void PikaStdData_FILEIO_init(PikaObj* self, char* mode, char* path) { + if (obj_isArgExist(self, "_f")) { + /* already initialized */ + return; + } + FILE* f = __platform_fopen(path, mode); + if (f == NULL) { + printf("Error: can't open file %s\n", path); + return; + } + obj_setPtr(self, "_f", f); + obj_setStr(self, "_mode", mode); +} + +void PikaStdData_FILEIO_close(PikaObj* self) { + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + return; + } + __platform_fclose(f); + obj_setPtr(self, "_f", NULL); +} + +Arg* PikaStdData_FILEIO_read(PikaObj* self, int size) { + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + return NULL; + } + Arg* buf_arg = arg_setBytes(NULL, "", NULL, size); + uint8_t* buf = arg_getBytes(buf_arg); + /* read */ + int n = __platform_fread(buf, 1, size, f); + if (n < size) { + /* EOF */ + buf[n] = '\0'; + } + char* mode = obj_getStr(self, "_mode"); + if (strIsContain(mode, 'b')) { + /* binary */ + return buf_arg; + } else { + /* text */ + Arg* res = arg_setStr(NULL, "", (char*)buf); + arg_deinit(buf_arg); + return res; + } +} + +void PikaStdData_FILEIO_write(PikaObj* self, Arg* s) { + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + obj_setErrorCode(self, PIKA_RES_ERR_IO); + __platform_printf("Error: can't write to file\n"); + return; + } + char* mode = obj_getStr(self, "_mode"); + if (strIsContain(mode, 'b')) { + /* binary */ + __platform_fwrite(arg_getBytes(s), 1, arg_getSize(s), f); + } else { + /* text */ + char* str = arg_getStr(s); + __platform_fwrite(str, 1, strlen(str), f); + } +} diff --git a/package/PikaStdLib/PikaStdLib.pyi b/package/PikaStdLib/PikaStdLib.pyi index a4b000440..1b0efcfab 100644 --- a/package/PikaStdLib/PikaStdLib.pyi +++ b/package/PikaStdLib/PikaStdLib.pyi @@ -7,27 +7,50 @@ class MemChecker: class SysObj: - def type(self, arg: any) -> any: ... - def remove(self, argPath: str): ... - def int(self, arg: any) -> int: ... - def float(self, arg: any) -> float: ... - def str(self, arg: any) -> str: ... - def iter(self, arg: any) -> any: ... - def range(self, a1: int, a2: int) -> any: ... - def print(self, *val): ... - def printNoEnd(self, val: any): ... - def __set__(self, obj: any, key: any, val: any) -> any: ... - def __get__(self, obj: any, key: any) -> any: ... - def __slice__(self, obj: any, start: any, end: any, step: int) -> any: ... - def len(self, arg: any) -> int: ... - def list(self) -> any: ... - def dict(self) -> any: ... - def hex(self, val: int) -> str: ... - def ord(self, val: str) -> int: ... - def chr(self, val: int) -> str: ... - def bytes(self, val: any) -> bytes: ... - def cformat(self, fmt: str, *var) -> str: ... - def id(self, obj: any) -> int: ... + @staticmethod + def type(arg: any) -> any: ... + @staticmethod + def remove(argPath: str): ... + @staticmethod + def int(arg: any) -> int: ... + @staticmethod + def float(arg: any) -> float: ... + @staticmethod + def str(arg: any) -> str: ... + @staticmethod + def iter(arg: any) -> any: ... + @staticmethod + def range(a1: int, a2: int) -> any: ... + @staticmethod + def print(*val): ... + @staticmethod + def printNoEnd(val: any): ... + @staticmethod + def __set__(obj: any, key: any, val: any) -> any: ... + @staticmethod + def __get__(obj: any, key: any) -> any: ... + @staticmethod + def __slice__(obj: any, start: any, end: any, step: int) -> any: ... + @staticmethod + def len(arg: any) -> int: ... + @staticmethod + def list() -> any: ... + @staticmethod + def dict() -> any: ... + @staticmethod + def hex(val: int) -> str: ... + @staticmethod + def ord(val: str) -> int: ... + @staticmethod + def chr(val: int) -> str: ... + @staticmethod + def bytes(val: any) -> bytes: ... + @staticmethod + def cformat(fmt: str, *var) -> str: ... + @staticmethod + def id(obj: any) -> int: ... + @staticmethod + def open(path: str, mode: str) -> object: ... class RangeObj: diff --git a/package/PikaStdLib/PikaStdLib_SysObj.c b/package/PikaStdLib/PikaStdLib_SysObj.c index b07a9c01c..c4b4be549 100644 --- a/package/PikaStdLib/PikaStdLib_SysObj.c +++ b/package/PikaStdLib/PikaStdLib_SysObj.c @@ -1,4 +1,5 @@ #include "PikaStdLib_SysObj.h" +#include "PikaStdData_FILEIO.h" #include "PikaStdLib_RangeObj.h" #include "PikaStdLib_StringObj.h" #include "PikaVM.h" @@ -452,3 +453,15 @@ int PikaStdLib_SysObj_id(PikaObj* self, Arg* obj) { } return ptr & (0x7FFFFFFF); } + +PikaObj* PikaStdLib_SysObj_open(PikaObj* self, char* mode, char* path) { +#if PIKA_FILEIO_ENABLE + PikaObj* file = newNormalObj(New_PikaStdData_FILEIO); + PikaStdData_FILEIO_init(file, mode, path); + return file; +#else + obj_setErrorCode(self, 1); + __platform_printf("[Error] PIKA_FILEIO_ENABLE is not enabled.\r\n"); + return NULL; +#endif +} diff --git a/port/linux/package/pikascript/PikaStdData.pyi b/port/linux/package/pikascript/PikaStdData.pyi index 26f7fe23d..649a7f095 100644 --- a/port/linux/package/pikascript/PikaStdData.pyi +++ b/port/linux/package/pikascript/PikaStdData.pyi @@ -94,6 +94,13 @@ class ByteArray(TinyObj): def decode(self) -> str: ... +class FILEIO: + def init(self, path: str, mode: str): ... + def read(self, size: int) -> any: ... + def write(self, s: any): ... + def close(self): ... + + class Utils: # convert a int to bytes def int_to_bytes(self, val: int) -> bytes: ... diff --git a/port/linux/package/pikascript/PikaStdLib.pyi b/port/linux/package/pikascript/PikaStdLib.pyi index a4b000440..1b0efcfab 100644 --- a/port/linux/package/pikascript/PikaStdLib.pyi +++ b/port/linux/package/pikascript/PikaStdLib.pyi @@ -7,27 +7,50 @@ class MemChecker: class SysObj: - def type(self, arg: any) -> any: ... - def remove(self, argPath: str): ... - def int(self, arg: any) -> int: ... - def float(self, arg: any) -> float: ... - def str(self, arg: any) -> str: ... - def iter(self, arg: any) -> any: ... - def range(self, a1: int, a2: int) -> any: ... - def print(self, *val): ... - def printNoEnd(self, val: any): ... - def __set__(self, obj: any, key: any, val: any) -> any: ... - def __get__(self, obj: any, key: any) -> any: ... - def __slice__(self, obj: any, start: any, end: any, step: int) -> any: ... - def len(self, arg: any) -> int: ... - def list(self) -> any: ... - def dict(self) -> any: ... - def hex(self, val: int) -> str: ... - def ord(self, val: str) -> int: ... - def chr(self, val: int) -> str: ... - def bytes(self, val: any) -> bytes: ... - def cformat(self, fmt: str, *var) -> str: ... - def id(self, obj: any) -> int: ... + @staticmethod + def type(arg: any) -> any: ... + @staticmethod + def remove(argPath: str): ... + @staticmethod + def int(arg: any) -> int: ... + @staticmethod + def float(arg: any) -> float: ... + @staticmethod + def str(arg: any) -> str: ... + @staticmethod + def iter(arg: any) -> any: ... + @staticmethod + def range(a1: int, a2: int) -> any: ... + @staticmethod + def print(*val): ... + @staticmethod + def printNoEnd(val: any): ... + @staticmethod + def __set__(obj: any, key: any, val: any) -> any: ... + @staticmethod + def __get__(obj: any, key: any) -> any: ... + @staticmethod + def __slice__(obj: any, start: any, end: any, step: int) -> any: ... + @staticmethod + def len(arg: any) -> int: ... + @staticmethod + def list() -> any: ... + @staticmethod + def dict() -> any: ... + @staticmethod + def hex(val: int) -> str: ... + @staticmethod + def ord(val: str) -> int: ... + @staticmethod + def chr(val: int) -> str: ... + @staticmethod + def bytes(val: any) -> bytes: ... + @staticmethod + def cformat(fmt: str, *var) -> str: ... + @staticmethod + def id(obj: any) -> int: ... + @staticmethod + def open(path: str, mode: str) -> object: ... class RangeObj: diff --git a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_FILEIO.c b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_FILEIO.c new file mode 100644 index 000000000..4c06ceda8 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_FILEIO.c @@ -0,0 +1,74 @@ +#include "PikaStdData_FILEIO.h" +#include + +void PikaStdData_FILEIO_init(PikaObj* self, char* mode, char* path) { + if (obj_isArgExist(self, "_f")) { + /* already initialized */ + return; + } + FILE* f = __platform_fopen(path, mode); + if (f == NULL) { + printf("Error: can't open file %s\n", path); + return; + } + obj_setPtr(self, "_f", f); + obj_setStr(self, "_mode", mode); +} + +void PikaStdData_FILEIO_close(PikaObj* self) { + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + return; + } + __platform_fclose(f); + obj_setPtr(self, "_f", NULL); +} + +Arg* PikaStdData_FILEIO_read(PikaObj* self, int size) { + if (size <= 0) { + /* read all */ + size = PIKA_READ_FILE_BUFF_SIZE; + } + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + return NULL; + } + Arg* buf_arg = arg_setBytes(NULL, "", NULL, size); + uint8_t* buf = arg_getBytes(buf_arg); + /* read */ + int n = __platform_fread(buf, 1, size, f); + if (n < size) { + /* EOF */ + buf[n] = '\0'; + } + char* mode = obj_getStr(self, "_mode"); + if (strIsContain(mode, 'b')) { + /* binary */ + Arg* res = arg_setBytes(NULL, "", buf, n); + arg_deinit(buf_arg); + return res; + } else { + /* text */ + Arg* res = arg_setStr(NULL, "", (char*)buf); + arg_deinit(buf_arg); + return res; + } +} + +void PikaStdData_FILEIO_write(PikaObj* self, Arg* s) { + FILE* f = obj_getPtr(self, "_f"); + if (f == NULL) { + obj_setErrorCode(self, PIKA_RES_ERR_IO); + __platform_printf("Error: can't write to file\n"); + return; + } + char* mode = obj_getStr(self, "_mode"); + if (strIsContain(mode, 'b')) { + /* binary */ + __platform_fwrite(arg_getBytes(s), 1, arg_getSize(s), f); + } else { + /* text */ + char* str = arg_getStr(s); + __platform_fwrite(str, 1, strlen(str), f); + } +} diff --git a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c index b07a9c01c..c4b4be549 100644 --- a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c +++ b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c @@ -1,4 +1,5 @@ #include "PikaStdLib_SysObj.h" +#include "PikaStdData_FILEIO.h" #include "PikaStdLib_RangeObj.h" #include "PikaStdLib_StringObj.h" #include "PikaVM.h" @@ -452,3 +453,15 @@ int PikaStdLib_SysObj_id(PikaObj* self, Arg* obj) { } return ptr & (0x7FFFFFFF); } + +PikaObj* PikaStdLib_SysObj_open(PikaObj* self, char* mode, char* path) { +#if PIKA_FILEIO_ENABLE + PikaObj* file = newNormalObj(New_PikaStdData_FILEIO); + PikaStdData_FILEIO_init(file, mode, path); + return file; +#else + obj_setErrorCode(self, 1); + __platform_printf("[Error] PIKA_FILEIO_ENABLE is not enabled.\r\n"); + return NULL; +#endif +} diff --git a/port/linux/test/stddata-test.cpp b/port/linux/test/stddata-test.cpp index 824c50f25..7fea5b7e9 100644 --- a/port/linux/test/stddata-test.cpp +++ b/port/linux/test/stddata-test.cpp @@ -84,3 +84,21 @@ TEST(stddata, encode_decode) { obj_deinit(pikaMain); } #endif + +#if PIKA_FILEIO_ENABLE +TEST(stddata, fileio) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain); + /* run */ + __platform_printf("BEGIN\r\n"); + pikaVM_runSingleFile(pikaMain, "../../examples/BuiltIn/file.py"); + Arg* s = obj_getArg(pikaMain, "s"); + Arg* b = obj_getArg(pikaMain, "b"); + /* assert */ + EXPECT_EQ(arg_getType(s), ARG_TYPE_STRING); + EXPECT_EQ(arg_getType(b), ARG_TYPE_BYTES); + /* deinit */ + obj_deinit(pikaMain); +} +#endif diff --git a/src/PikaPlatform.h b/src/PikaPlatform.h index 8913a1212..6c76453f8 100644 --- a/src/PikaPlatform.h +++ b/src/PikaPlatform.h @@ -93,6 +93,7 @@ typedef enum { PIKA_RES_ERR_OPERATION_FAILED, PIKA_RES_ERR_UNKNOWN, PIKA_RES_ERR_SYNTAX_ERROR, + PIKA_RES_ERR_IO, } PIKA_RES; /* clang-format off */ diff --git a/src/pika_config_valid.h b/src/pika_config_valid.h index b37844a02..0621ca33b 100644 --- a/src/pika_config_valid.h +++ b/src/pika_config_valid.h @@ -102,6 +102,10 @@ #define PIKA_EVENT_ENABLE 0 #endif + #ifndef PIKA_FILEIO_ENABLE + #define PIKA_FILEIO_ENABLE 0 + #endif + #elif PIKA_SYNTAX_LEVEL == PIKA_SYNTAX_LEVEL_MAXIMAL #ifndef PIKA_SYNTAX_SLICE_ENABLE #define PIKA_SYNTAX_SLICE_ENABLE 1 @@ -130,6 +134,10 @@ #ifndef PIKA_EVENT_ENABLE #define PIKA_EVENT_ENABLE 1 #endif + + #ifndef PIKA_FILEIO_ENABLE + #define PIKA_FILEIO_ENABLE 1 + #endif #endif @@ -226,6 +234,10 @@ #define PIKA_DEBUG_ENABLE 0 #endif + #ifndef PIKA_FILEIO_ENABLE + #define PIKA_FILEIO_ENABLE 1 + #endif + #ifndef PIKA_ARG_NUM_MAX #define PIKA_ARG_NUM_MAX 16 #endif