struct.pack() tested passed

This commit is contained in:
Lyon 2023-08-17 19:51:00 +08:00
parent fb868b0aab
commit cf7990adda
14 changed files with 125 additions and 47 deletions

27
examples/struct/pack.py Normal file
View File

@ -0,0 +1,27 @@
import struct
# Test strings and fixed-length strings
assert struct.pack('5s', b'Hello') == b'Hello'
assert struct.pack('10s', b'World') == b'World\x00\x00\x00\x00\x00'
assert struct.pack(
'hhl', 1, 2, 3) == b'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'
# Test signed short, unsigned short, and signed long
assert struct.pack(
'hHl', -1, 255, 1234567890) == b'\xff\xff\xff\x00\x00\x00\x00\x00\xd2\x02\x96I\x00\x00\x00\x00'
# Test single precision float and double precision float
assert struct.pack(
'fd', 3.14159, 123.45678901234567) == b'\xd0\x0fI@\x00\x00\x00\x00\x98L\xfb\x07<\xdd^@'
# Test byte order and alignment
assert struct.pack('>ih5s', 256, 6553,
b'Python') == b'\x00\x00\x01\x00\x19\x99Pytho'
# Test combination of multiple values
#! NOT SUPPORTED
# assert struct.pack('chHiIq', b'A', 127, 3268, 2147, 42945, 9220) == \
# b'A\x00\x7f\x00\xc4\x0c\x00\x00c\x08\x00\x00\xc1\xa7\x00\x00\x04$\x00\x00\x00\x00\x00\x00'
print('PASS')

View File

@ -71,10 +71,9 @@ STATIC mp_uint_t get_fmt_num(const char** p) {
while (unichar_isdigit(*++num)) {
len++;
}
char* buff = pika_platform_malloc(len + 1);
pika_platform_memset(buff, 0, len + 1);
char buff[11] = {0};
pika_platform_memcpy(buff, *p, len);
mp_uint_t val = (mp_uint_t)fast_atoi((char*)num);
mp_uint_t val = (mp_uint_t)fast_atoi((char*)buff);
*p = num;
return val;
}
@ -198,9 +197,10 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in,
if (bufinfo.len < to_copy) {
to_copy = bufinfo.len;
}
memcpy(p, bufinfo.buf, to_copy);
memset(p + to_copy, 0, cnt - to_copy);
pika_platform_memcpy(p, bufinfo.buf, to_copy);
pika_platform_memset(p + to_copy, 0, cnt - to_copy);
p += cnt;
mp_buff_info_deinit(&bufinfo);
} else {
// If we run out of args then we just finish; CPython would raise
// struct.error
@ -212,19 +212,25 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in,
}
}
#ifndef _SKIP_COMPILE
STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t* args) {
// TODO: "The arguments must match the values required by the format
// exactly."
mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
vstr_t vstr;
vstr_init_len(&vstr, size);
byte* p = (byte*)vstr.buf;
memset(p, 0, size);
struct_pack_into_internal(args[0], p, n_args - 1, &args[1]);
return mp_obj_new_bytes_from_vstr(&vstr);
Arg* _struct_pack(PikaObj* self, char* fmt, PikaTuple* vars) {
Arg* aFmt = arg_newStr(fmt);
size_t varlen = pikaTuple_getSize(vars);
Arg* aSize = struct_calcsize(aFmt);
Arg** args = pikaMalloc(sizeof(Arg) * varlen);
for (size_t i = 0; i < varlen; i++) {
args[i] = pikaTuple_get(vars, i);
}
size_t size = arg_getInt(aSize);
Arg* byte = arg_newBytes(NULL, size);
uint8_t* p = arg_getBytes(byte);
struct_pack_into_internal(aFmt, p, varlen, args);
pikaFree(args, sizeof(Arg) * varlen);
arg_deinit(aFmt);
arg_deinit(aSize);
return byte;
}
#ifndef _SKIP_COMPILE
STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t* args) {
mp_buffer_info_t bufinfo;

View File

@ -0,0 +1 @@
def pack(fmt: str, *vars) -> bytes: ...

4
package/struct/struct.py Normal file
View File

@ -0,0 +1,4 @@
import _struct
def pack(fmt, *args):
return _struct.pack(fmt, *args)

View File

@ -12,7 +12,7 @@
// "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
"args": [
// "--gtest_filter=vm.keyword_2"
"--gtest_filter=builtin.fn_del"
"--gtest_filter=struct.pack"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",

View File

@ -0,0 +1 @@
def pack(fmt: str, *vars) -> bytes: ...

View File

@ -3,7 +3,7 @@ import random, re, modbus, socket, unittest, binascii, ctypes, requests, mqtt
import pika_lua, pika_cjson, cjson_test, json
import GTestTask, TempDevTest
import cb_test
import configparser, network, math
import configparser, network, math, struct
import test_module1, test_cmodule, test_module4, import_test
import hashlib, hmac, aes, base64, time, os, zlib
import _thread, weakref, eventloop

View File

@ -71,10 +71,9 @@ STATIC mp_uint_t get_fmt_num(const char** p) {
while (unichar_isdigit(*++num)) {
len++;
}
char* buff = pika_platform_malloc(len + 1);
pika_platform_memset(buff, 0, len + 1);
char buff[11] = {0};
pika_platform_memcpy(buff, *p, len);
mp_uint_t val = (mp_uint_t)fast_atoi((char*)num);
mp_uint_t val = (mp_uint_t)fast_atoi((char*)buff);
*p = num;
return val;
}
@ -198,9 +197,10 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in,
if (bufinfo.len < to_copy) {
to_copy = bufinfo.len;
}
memcpy(p, bufinfo.buf, to_copy);
memset(p + to_copy, 0, cnt - to_copy);
pika_platform_memcpy(p, bufinfo.buf, to_copy);
pika_platform_memset(p + to_copy, 0, cnt - to_copy);
p += cnt;
mp_buff_info_deinit(&bufinfo);
} else {
// If we run out of args then we just finish; CPython would raise
// struct.error
@ -212,19 +212,25 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in,
}
}
#ifndef _SKIP_COMPILE
STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t* args) {
// TODO: "The arguments must match the values required by the format
// exactly."
mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
vstr_t vstr;
vstr_init_len(&vstr, size);
byte* p = (byte*)vstr.buf;
memset(p, 0, size);
struct_pack_into_internal(args[0], p, n_args - 1, &args[1]);
return mp_obj_new_bytes_from_vstr(&vstr);
Arg* _struct_pack(PikaObj* self, char* fmt, PikaTuple* vars) {
Arg* aFmt = arg_newStr(fmt);
size_t varlen = pikaTuple_getSize(vars);
Arg* aSize = struct_calcsize(aFmt);
Arg** args = pikaMalloc(sizeof(Arg) * varlen);
for (size_t i = 0; i < varlen; i++) {
args[i] = pikaTuple_get(vars, i);
}
size_t size = arg_getInt(aSize);
Arg* byte = arg_newBytes(NULL, size);
uint8_t* p = arg_getBytes(byte);
struct_pack_into_internal(aFmt, p, varlen, args);
pikaFree(args, sizeof(Arg) * varlen);
arg_deinit(aFmt);
arg_deinit(aSize);
return byte;
}
#ifndef _SKIP_COMPILE
STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t* args) {
mp_buffer_info_t bufinfo;

View File

@ -0,0 +1,4 @@
import _struct
def pack(fmt, *args):
return _struct.pack(fmt, *args)

View File

@ -629,6 +629,8 @@ TEST_RUN_SINGLE_FILE(modbus,
TEST_RUN_SINGLE_FILE_PASS(proxy, proxy3, "test/python/proxy/proxy3.py")
TEST_RUN_SINGLE_FILE_PASS(struct, pack, "test/python/struct/pack.py")
#endif
TEST_END

View File

@ -0,0 +1,27 @@
import struct
# Test strings and fixed-length strings
assert struct.pack('5s', b'Hello') == b'Hello'
assert struct.pack('10s', b'World') == b'World\x00\x00\x00\x00\x00'
assert struct.pack(
'hhl', 1, 2, 3) == b'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'
# Test signed short, unsigned short, and signed long
assert struct.pack(
'hHl', -1, 255, 1234567890) == b'\xff\xff\xff\x00\x00\x00\x00\x00\xd2\x02\x96I\x00\x00\x00\x00'
# Test single precision float and double precision float
assert struct.pack(
'fd', 3.14159, 123.45678901234567) == b'\xd0\x0fI@\x00\x00\x00\x00\x98L\xfb\x07<\xdd^@'
# Test byte order and alignment
assert struct.pack('>ih5s', 256, 6553,
b'Python') == b'\x00\x00\x01\x00\x19\x99Pytho'
# Test combination of multiple values
#! NOT SUPPORTED
# assert struct.pack('chHiIq', b'A', 127, 3268, 2147, 42945, 9220) == \
# b'A\x00\x7f\x00\xc4\x0c\x00\x00c\x08\x00\x00\xc1\xa7\x00\x00\x04$\x00\x00\x00\x00\x00\x00'
print('PASS')

View File

@ -111,7 +111,7 @@ impl MethodInfo {
pub fn method_api_name(&self) -> String {
return format!(
"void {}_{}Method(PikaObj *self, Args *args)",
"void {}_{}Method(PikaObj *self, Args *_args_)",
self.class_name, self.name
);
}

View File

@ -22,7 +22,7 @@ impl PyArg {
}
pub fn get_local_arg(&self) -> String {
return format!(
" {} {} = {}(args, \"{}\");\n",
" {} {} = {}(_args_, \"{}\");\n",
self.c_type(),
self.name(),
self.py_type.get_fn(),

View File

@ -82,30 +82,30 @@ impl PyType {
}
pub fn return_fn(&self) -> String {
if self.type_name == "int" {
return " method_returnInt(args, res);\n".to_string();
return " method_returnInt(_args_, res);\n".to_string();
}
if self.type_name == "int64" {
return " method_returnInt(args, res);\n".to_string();
return " method_returnInt(_args_, res);\n".to_string();
}
if self.type_name == "bool" {
return " method_returnBool(args, res);\n".to_string();
return " method_returnBool(_args_, res);\n".to_string();
}
if self.type_name == "float" {
return " method_returnFloat(args, res);\n".to_string();
return " method_returnFloat(_args_, res);\n".to_string();
}
if self.type_name == "pointer" {
return " method_returnPtr(args, res);\n".to_string();
return " method_returnPtr(_args_, res);\n".to_string();
}
if self.type_name == "str" {
return " method_returnStr(args, res);\n".to_string();
return " method_returnStr(_args_, res);\n".to_string();
}
if self.type_name == "bytes" {
return " method_returnArg(args, res);\n".to_string();
return " method_returnArg(_args_, res);\n".to_string();
}
if self.type_name == "any" {
return " method_returnArg(args, res);\n".to_string();
return " method_returnArg(_args_, res);\n".to_string();
}
return " method_returnObj(args, res);\n".to_string();
return " method_returnObj(_args_, res);\n".to_string();
}
// pub fn set_fn(&self) -> String {
// if self.type_name == "int" {