mirror of https://github.com/arendst/Tasmota.git
Berry bytes solidification (#21558)
* Berry prepare for bytes() solidification * Berry solidification of bytes objects * Berry solidification of `bytes` instances
This commit is contained in:
parent
243411916b
commit
a51c511d52
|
@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## [14.1.0.1]
|
||||
### Added
|
||||
- Berry solidification of `bytes` instances
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
|
|
|
@ -16,28 +16,7 @@
|
|||
#include "be_constobj.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size)
|
||||
#define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size)
|
||||
#define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing
|
||||
|
||||
#define BYTES_SIZE_FIXED -1 // if size is -1, then the bytes object cannot be reized
|
||||
#define BYTES_SIZE_MAPPED -2 // if size is -2, then the bytes object is mapped to a fixed memory region, i.e. cannot be resized
|
||||
|
||||
#define BYTES_RESIZE_ERROR "attribute_error"
|
||||
#define BYTES_RESIZE_MESSAGE "bytes object size if fixed and cannot be resized"
|
||||
/* be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); */
|
||||
|
||||
typedef struct buf_impl {
|
||||
int32_t size; // size in bytes of the buffer
|
||||
int32_t len; // current size of the data in buffer. Invariant: len <= size
|
||||
uint8_t *bufptr; // the actual data
|
||||
int32_t prev_size; // previous value read from the instance
|
||||
int32_t prev_len; // previous value read from the instance
|
||||
uint8_t *prev_bufptr;
|
||||
bbool fixed; // is size fixed? (actually encoded as negative size)
|
||||
bbool mapped;
|
||||
} buf_impl;
|
||||
#include "be_byteslib.h"
|
||||
|
||||
/********************************************************************
|
||||
** Base64 lib from https://github.com/Densaugeo/base64_arduino
|
||||
|
@ -481,7 +460,16 @@ static void buf_add_hex(buf_impl* attr, const char *hex, size_t len)
|
|||
********************************************************************/
|
||||
|
||||
/* if the bufptr is null, don't try to dereference and raise an exception instead */
|
||||
static void check_ptr(bvm *vm, buf_impl* attr) {
|
||||
static void check_ptr(bvm *vm, const buf_impl* attr) {
|
||||
if (!attr->bufptr) {
|
||||
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
|
||||
}
|
||||
}
|
||||
|
||||
static void check_ptr_modifiable(bvm *vm, const buf_impl* attr) {
|
||||
if (attr->solidified) {
|
||||
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||
}
|
||||
if (!attr->bufptr) {
|
||||
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
|
||||
}
|
||||
|
@ -504,10 +492,14 @@ buf_impl m_read_attributes(bvm *vm, int idx)
|
|||
int32_t signed_size = be_toint(vm, -1);
|
||||
attr.fixed = bfalse;
|
||||
attr.mapped = bfalse;
|
||||
attr.solidified = bfalse;
|
||||
if (signed_size < 0) {
|
||||
if (signed_size == BYTES_SIZE_MAPPED) {
|
||||
attr.mapped = btrue;
|
||||
}
|
||||
if (signed_size == BYTES_SIZE_SOLIDIFIED) {
|
||||
attr.solidified = btrue;
|
||||
}
|
||||
signed_size = attr.len;
|
||||
attr.fixed = btrue;
|
||||
}
|
||||
|
@ -516,10 +508,18 @@ buf_impl m_read_attributes(bvm *vm, int idx)
|
|||
return attr;
|
||||
}
|
||||
|
||||
static void m_assert_not_readlonly(bvm *vm, const buf_impl* attr)
|
||||
{
|
||||
if (attr->solidified) {
|
||||
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write back attributes to the bytes instance, only if values changed after loading */
|
||||
/* stack item 1 must contain the instance */
|
||||
void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
||||
{
|
||||
m_assert_not_readlonly(vm, attr);
|
||||
int idx = be_absindex(vm, rel_idx);
|
||||
if (attr->bufptr != attr->prev_bufptr) {
|
||||
be_pushcomptr(vm, attr->bufptr);
|
||||
|
@ -549,6 +549,7 @@ void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
|||
// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size)
|
||||
void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size)
|
||||
{
|
||||
m_assert_not_readlonly(vm, attr);
|
||||
if (!attr->fixed && size < 4) { size = 4; }
|
||||
if (size > vm->bytesmaxsize) { size = vm->bytesmaxsize; }
|
||||
size_t oldsize = attr->bufptr ? attr->size : 0;
|
||||
|
@ -590,7 +591,7 @@ static void bytes_new_object(bvm *vm, size_t size)
|
|||
static int m_init(bvm *vm)
|
||||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */
|
||||
buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */
|
||||
/* size cannot be 0, len cannot be negative */
|
||||
const char * hex_in = NULL;
|
||||
|
||||
|
@ -713,7 +714,7 @@ buf_impl bytes_check_data(bvm *vm, size_t add_size) {
|
|||
return attr;
|
||||
}
|
||||
|
||||
static size_t tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
|
||||
size_t be_bytes_tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
|
||||
static const char * hex = "0123456789ABCDEF";
|
||||
const uint8_t * pin = in;
|
||||
char * pout = out;
|
||||
|
@ -745,7 +746,7 @@ static int m_tostring(bvm *vm)
|
|||
|
||||
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||
size_t l = be_strlcpy(hex_out, "bytes('", hex_len);
|
||||
l += tohex(&hex_out[l], hex_len - l, attr.bufptr, len);
|
||||
l += be_bytes_tohex(&hex_out[l], hex_len - l, attr.bufptr, len);
|
||||
if (truncated) {
|
||||
l += be_strlcpy(&hex_out[l], "...", hex_len - l);
|
||||
}
|
||||
|
@ -767,7 +768,7 @@ static int m_tohex(bvm *vm)
|
|||
size_t hex_len = len * 2 + 1;
|
||||
|
||||
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||
size_t l = tohex(hex_out, hex_len, attr.bufptr, len);
|
||||
size_t l = be_bytes_tohex(hex_out, hex_len, attr.bufptr, len);
|
||||
|
||||
be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
|
||||
be_remove(vm, -2); /* remove buffer */
|
||||
|
@ -795,7 +796,7 @@ static int m_fromstring(bvm *vm)
|
|||
const char *s = be_tostring(vm, 2);
|
||||
int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */
|
||||
buf_impl attr = bytes_check_data(vm, 0);
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed && attr.len != len) {
|
||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||
}
|
||||
|
@ -823,7 +824,7 @@ static int m_add(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||
if (argc >= 2 && be_isint(vm, 2)) {
|
||||
int32_t v = be_toint(vm, 2);
|
||||
|
@ -949,7 +950,7 @@ static int m_set(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
||||
int32_t idx = be_toint(vm, 2);
|
||||
int32_t value = be_toint(vm, 3);
|
||||
|
@ -985,7 +986,7 @@ static int m_setfloat(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (argc >=3 && be_isint(vm, 2) && (be_isint(vm, 3) || be_isreal(vm, 3))) {
|
||||
int32_t idx = be_toint(vm, 2);
|
||||
float val_f = (float) be_toreal(vm, 3);
|
||||
|
@ -1011,7 +1012,7 @@ static int m_addfloat(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||
if (argc >=2 && (be_isint(vm, 2) || be_isreal(vm, 2))) {
|
||||
float val_f = (float) be_toreal(vm, 2);
|
||||
|
@ -1040,7 +1041,7 @@ static int m_setbytes(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (argc >=3 && be_isint(vm, 2) && (be_isbytes(vm, 3))) {
|
||||
int32_t idx = be_toint(vm, 2);
|
||||
size_t from_len_total;
|
||||
|
@ -1084,7 +1085,7 @@ static int m_reverse(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
|
||||
int32_t idx = 0; /* start from index 0 */
|
||||
int32_t len = attr.len; /* entire len */
|
||||
|
@ -1135,7 +1136,7 @@ static int m_setitem(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
||||
int index = be_toint(vm, 2);
|
||||
int val = be_toint(vm, 3);
|
||||
|
@ -1153,7 +1154,7 @@ static int m_item(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (argc >=2 && be_isint(vm, 2)) { /* single byte */
|
||||
int index = be_toint(vm,2);
|
||||
if (index < 0) {
|
||||
|
@ -1215,6 +1216,7 @@ static int m_resize(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
|
||||
if (argc <= 1 || !be_isint(vm, 2)) {
|
||||
be_raise(vm, "type_error", "size must be of type 'int'");
|
||||
|
@ -1237,6 +1239,7 @@ static int m_resize(bvm *vm)
|
|||
static int m_clear(bvm *vm)
|
||||
{
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||
attr.len = 0;
|
||||
m_write_attributes(vm, 1, &attr); /* update instance */
|
||||
|
@ -1293,7 +1296,7 @@ static int m_connect(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||
if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2) || be_isstring(vm, 2))) {
|
||||
if (be_isint(vm, 2)) {
|
||||
|
@ -1390,7 +1393,7 @@ static int m_fromb64(bvm *vm)
|
|||
int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */
|
||||
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed && attr.len != bin_len) {
|
||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||
}
|
||||
|
@ -1429,7 +1432,7 @@ static int m_fromhex(bvm *vm)
|
|||
int32_t bin_len = (s_len - from) / 2;
|
||||
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
check_ptr(vm, &attr);
|
||||
check_ptr_modifiable(vm, &attr);
|
||||
if (attr.fixed && attr.len != bin_len) {
|
||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||
}
|
||||
|
@ -1483,6 +1486,18 @@ static int m_is_mapped(bvm *vm)
|
|||
be_return(vm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns `btrue` if the buffer is solidified and read only
|
||||
*
|
||||
* `isreadonly() -> bool`
|
||||
*/
|
||||
static int m_is_readonly(bvm *vm)
|
||||
{
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
be_pushbool(vm, attr.solidified);
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the pointer to a mapped buffer.
|
||||
*
|
||||
|
@ -1497,6 +1512,9 @@ static int m_change_buffer(bvm *vm)
|
|||
int argc = be_top(vm);
|
||||
if (argc >= 2 && be_iscomptr(vm, 2)) {
|
||||
buf_impl attr = m_read_attributes(vm, 1);
|
||||
if (attr.solidified) {
|
||||
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||
}
|
||||
if (!attr.mapped) {
|
||||
be_raise(vm, "type_error", "bytes() object must be mapped");
|
||||
}
|
||||
|
@ -1764,11 +1782,12 @@ void be_load_byteslib(bvm *vm)
|
|||
{
|
||||
static const bnfuncinfo members[] = {
|
||||
{ ".p", NULL },
|
||||
{ ".size", NULL },
|
||||
{ ".len", NULL },
|
||||
{ ".size", NULL },
|
||||
{ "_buffer", m_buffer },
|
||||
{ "_change_buffer", m_change_buffer },
|
||||
{ "ismapped", m_is_mapped },
|
||||
{ "isreadonly", m_is_readonly },
|
||||
{ "init", m_init },
|
||||
{ "deinit", m_deinit },
|
||||
{ "tostring", m_tostring },
|
||||
|
@ -1810,14 +1829,18 @@ void be_load_byteslib(bvm *vm)
|
|||
be_regclass(vm, "bytes", members);
|
||||
}
|
||||
#else
|
||||
|
||||
#include "../generate/be_const_bytes_def.h"
|
||||
|
||||
/* @const_object_info_begin
|
||||
class be_class_bytes (scope: global, name: bytes) {
|
||||
.p, var
|
||||
.size, var
|
||||
.len, var
|
||||
.size, var
|
||||
_buffer, func(m_buffer)
|
||||
_change_buffer, func(m_change_buffer)
|
||||
ismapped, func(m_is_mapped)
|
||||
isreadonly, func(m_is_readonly)
|
||||
init, func(m_init)
|
||||
deinit, func(m_deinit)
|
||||
tostring, func(m_tostring)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/********************************************************************
|
||||
** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger
|
||||
** This file is part of the Berry default interpreter.
|
||||
** skiars@qq.com, https://github.com/Skiars/berry
|
||||
** See Copyright Notice in the LICENSE file or at
|
||||
** https://github.com/Skiars/berry/blob/master/LICENSE
|
||||
********************************************************************/
|
||||
#ifndef __BE_BYTESLIB_H
|
||||
#define __BE_BYTESLIB_H
|
||||
|
||||
#include "be_object.h"
|
||||
|
||||
#define BYTES_DEFAULT_SIZE 28 /* default pre-reserved size for buffer (keep 4 bytes for len/size) */
|
||||
#define BYTES_OVERHEAD 4 /* bytes overhead to be added when allocating (used to store len and size) */
|
||||
#define BYTES_HEADROOM 8 /* keep a natural headroom of 8 bytes when resizing */
|
||||
|
||||
#define BYTES_SIZE_FIXED -1 /* if size is -1, then the bytes object cannot be reized */
|
||||
#define BYTES_SIZE_MAPPED -2 /* if size is -2, then the bytes object is mapped to a fixed memory region, i.e. cannot be resized */
|
||||
#define BYTES_SIZE_SOLIDIFIED -3 /* is size is -3, then the bytes object is solidified and cannot be resized nor modified */
|
||||
|
||||
#define BYTES_RESIZE_ERROR "attribute_error"
|
||||
#define BYTES_RESIZE_MESSAGE "bytes object size if fixed and cannot be resized"
|
||||
#define BYTES_READ_ONLY_MESSAGE "bytes object is read only"
|
||||
/* be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); */
|
||||
|
||||
typedef struct buf_impl {
|
||||
int32_t size; // size in bytes of the buffer
|
||||
int32_t len; // current size of the data in buffer. Invariant: len <= size
|
||||
uint8_t *bufptr; // the actual data
|
||||
int32_t prev_size; // previous value read from the instance
|
||||
int32_t prev_len; // previous value read from the instance
|
||||
uint8_t *prev_bufptr;
|
||||
bbool fixed; // is size fixed? (actually encoded as negative size)
|
||||
bbool mapped;
|
||||
bbool solidified;
|
||||
} buf_impl;
|
||||
|
||||
size_t be_bytes_tohex(char * out, size_t outsz, const uint8_t * in, size_t insz);
|
||||
|
||||
#if BE_USE_PRECOMPILED_OBJECT
|
||||
#include "../generate/be_const_bytes.h"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -49,6 +49,16 @@ struct binstance {
|
|||
bvalue members[1]; /* members variable data field */
|
||||
};
|
||||
|
||||
/* special structure accepting 3 instance variables used only for bytes() solidification */
|
||||
struct binstance_arg3 {
|
||||
bcommon_header;
|
||||
struct binstance *super;
|
||||
struct binstance *sub;
|
||||
bclass *_class;
|
||||
bgcobject *gray; /* for gc gray list */
|
||||
bvalue members[3]; /* members variable data field */
|
||||
};
|
||||
|
||||
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
|
||||
void be_class_compress(bvm *vm, bclass *c);
|
||||
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
|
||||
|
|
|
@ -19,6 +19,7 @@ extern "C" {
|
|||
#include "be_class.h"
|
||||
#include "be_string.h"
|
||||
#include "be_module.h"
|
||||
#include "be_byteslib.h"
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
|
@ -27,6 +28,25 @@ extern "C" {
|
|||
.type = (_t), \
|
||||
.marked = GC_CONST
|
||||
|
||||
#define be_define_const_bytes(_name, ...) \
|
||||
const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ }
|
||||
|
||||
#define be_const_bytes_instance(_bytes) { \
|
||||
.v.c = ( \
|
||||
& (const binstance_arg3) { \
|
||||
be_const_header(BE_INSTANCE), \
|
||||
.super = NULL, \
|
||||
.sub = NULL, \
|
||||
._class = (bclass*) &be_class_bytes, \
|
||||
.members = { \
|
||||
be_const_comptr(&be_const_bin_##_bytes), \
|
||||
be_const_int(sizeof(#_bytes) / 2), \
|
||||
be_const_int(BYTES_SIZE_SOLIDIFIED) \
|
||||
} \
|
||||
}), \
|
||||
.type = BE_INSTANCE \
|
||||
}
|
||||
|
||||
#define be_define_const_str_weak(_name, _s, _len) \
|
||||
const bcstring be_const_str_##_name = { \
|
||||
.next = NULL, \
|
||||
|
@ -232,6 +252,27 @@ const bntvmodule_t be_native_module(_module) = { \
|
|||
.members = _members \
|
||||
}
|
||||
|
||||
#define be_nested_simple_instance_1_arg(_class_ptr, arg0) \
|
||||
& (const binstance) { \
|
||||
be_const_header(BE_INSTANCE), \
|
||||
.super = NULL, \
|
||||
.sub = NULL, \
|
||||
._class = (bclass*) _class_ptr, \
|
||||
.members = { arg0 } \
|
||||
}
|
||||
|
||||
|
||||
/* only instances with no super and no sub instance are supported */
|
||||
/* primarily for `list` and `map`*/
|
||||
#define be_nested_simple_instance_3_args(_class_ptr, arg0, arg1, arg2) \
|
||||
& (const binstance_arg3) { \
|
||||
be_const_header(BE_INSTANCE), \
|
||||
.super = NULL, \
|
||||
.sub = NULL, \
|
||||
._class = (bclass*) _class_ptr, \
|
||||
.members = { arg0, arg1, arg2 } \
|
||||
}
|
||||
|
||||
#define be_nested_map(_size, _slots) \
|
||||
& (const bmap) { \
|
||||
be_const_header(BE_MAP), \
|
||||
|
@ -298,6 +339,9 @@ const bntvmodule_t be_native_module(_module) = { \
|
|||
|
||||
#else
|
||||
|
||||
#define be_define_const_bytes(_name, ...) \
|
||||
const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ }
|
||||
|
||||
#define be_define_const_str_weak(_name, _s, _len) \
|
||||
const bcstring be_const_str_##_name = { \
|
||||
NULL, \
|
||||
|
@ -440,6 +484,7 @@ const bntvmodule_t be_native_module_##_module = { \
|
|||
/* provide pointers to map and list classes for solidified code */
|
||||
extern const bclass be_class_list;
|
||||
extern const bclass be_class_map;
|
||||
extern const bclass be_class_bytes;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ typedef struct bclosure bclosure;
|
|||
typedef struct bntvclos bntvclos;
|
||||
typedef struct bclass bclass;
|
||||
typedef struct binstance binstance;
|
||||
typedef struct binstance_arg3 binstance_arg3;
|
||||
typedef struct blist blist;
|
||||
typedef struct bmap bmap;
|
||||
typedef struct bupval bupval;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "be_decoder.h"
|
||||
#include "be_sys.h"
|
||||
#include "be_mem.h"
|
||||
#include "be_byteslib.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
@ -24,6 +25,7 @@
|
|||
|
||||
extern const bclass be_class_list;
|
||||
extern const bclass be_class_map;
|
||||
extern const bclass be_class_bytes;
|
||||
|
||||
#if BE_USE_SOLIDIFY_MODULE
|
||||
#include <inttypes.h>
|
||||
|
@ -288,20 +290,32 @@ static void m_solidify_bvalue(bvm *vm, bbool str_literal, const bvalue * value,
|
|||
bclass * cl = ins->_class;
|
||||
if (ins->super || ins->sub) {
|
||||
be_raise(vm, "internal_error", "instance must not have a super/sub class");
|
||||
} else if (cl->nvar != 1) {
|
||||
be_raise(vm, "internal_error", "instance must have only one instance variable");
|
||||
} else if ((cl != &be_class_map && cl != &be_class_list) || 1) { // TODO
|
||||
const char * cl_ptr = "";
|
||||
if (cl == &be_class_map) { cl_ptr = "map"; }
|
||||
if (cl == &be_class_list) { cl_ptr = "list"; }
|
||||
logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr);
|
||||
if (cl == &be_class_map) {
|
||||
logfmt(" be_const_map( * ");
|
||||
else if (cl == &be_class_list) { cl_ptr = "list"; }
|
||||
else if (cl == &be_class_bytes) { cl_ptr = "bytes"; }
|
||||
else { be_raise(vm, "internal_error", "unsupported class"); }
|
||||
|
||||
if (cl == &be_class_bytes) {
|
||||
const void * bufptr = var_toobj(&ins->members[0]);
|
||||
int32_t len = var_toint(&ins->members[1]);
|
||||
size_t hex_len = len * 2 + 1;
|
||||
|
||||
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||
be_bytes_tohex(hex_out, hex_len, bufptr, len);
|
||||
logfmt("be_const_bytes_instance(%s)", hex_out);
|
||||
be_pop(vm, 1);
|
||||
} else {
|
||||
logfmt(" be_const_list( * ");
|
||||
logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr);
|
||||
if (cl == &be_class_map) {
|
||||
logfmt(" be_const_map( * ");
|
||||
} else {
|
||||
logfmt(" be_const_list( * ");
|
||||
}
|
||||
m_solidify_bvalue(vm, str_literal, &ins->members[0], prefixname, key, fout);
|
||||
logfmt(" ) } ))");
|
||||
}
|
||||
m_solidify_bvalue(vm, str_literal, &ins->members[0], prefixname, key, fout);
|
||||
logfmt(" ) } ))");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import json
|
||||
|
||||
class bytes_build:
|
||||
def __init__(self, map):
|
||||
self.map = map.copy()
|
||||
|
||||
def build(self, path):
|
||||
prefix = path + "/be_const_bytes"
|
||||
self.writefile(prefix + "_def.h", self.build_bytes_def())
|
||||
self.writefile(prefix + ".h", self.build_bytes_ext())
|
||||
|
||||
def writefile(self, filename, text):
|
||||
buf = ""
|
||||
try:
|
||||
with open(filename) as f:
|
||||
buf = f.read()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
if buf != text:
|
||||
with open(filename, "w") as f:
|
||||
f.write(text)
|
||||
|
||||
def build_bytes_def(self):
|
||||
ostr = ""
|
||||
ostr += "/* binary arrays */\n"
|
||||
ostr += "be_define_const_bytes(,);\n"
|
||||
for k in self.map:
|
||||
ostr += "be_define_const_bytes("
|
||||
ostr += k + ", " + ", ".join( [ "0x" + k[i:i+2] for i in range(0, len(k), 2)] )
|
||||
ostr += ");\n"
|
||||
|
||||
return ostr
|
||||
|
||||
def build_bytes_ext(self):
|
||||
ostr = ""
|
||||
ostr += "/* extern binary arrays */\n"
|
||||
ostr += "extern const uint8_t be_const_bin_[];\n"
|
||||
for k in self.map:
|
||||
ostr += "extern const uint8_t be_const_bin_" + k + "[];\n"
|
||||
|
||||
return ostr
|
|
@ -4,6 +4,7 @@ import re
|
|||
import os
|
||||
from coc_parser import *
|
||||
from str_build import *
|
||||
from bytes_build import *
|
||||
from block_builder import *
|
||||
from macro_table import *
|
||||
|
||||
|
@ -20,6 +21,7 @@ class builder:
|
|||
self.strmap = {}
|
||||
self.strmap_weak = {}
|
||||
self.strmap_long = {}
|
||||
self.bytesmap = {}
|
||||
|
||||
self.macro = macro_table()
|
||||
for path in self.config:
|
||||
|
@ -30,6 +32,9 @@ class builder:
|
|||
|
||||
sb = str_build(self.strmap, self.strmap_weak, self.strmap_long)
|
||||
sb.build(self.output)
|
||||
|
||||
sbytes = bytes_build(self.bytesmap)
|
||||
sbytes.build(self.output)
|
||||
|
||||
def parse_file(self, filename):
|
||||
if re.search(r"\.(h|c|cc|cpp)$", filename):
|
||||
|
@ -45,6 +50,8 @@ class builder:
|
|||
self.strmap_weak[s] = 0
|
||||
for s in parser.strtab_long:
|
||||
self.strmap_long[s] = 0
|
||||
for s in parser.bintab:
|
||||
self.bytesmap[s] = 0
|
||||
for obj in parser.objects:
|
||||
builder = block_builder(obj, self.macro)
|
||||
for s in builder.strtab:
|
||||
|
|
|
@ -23,10 +23,12 @@ class coc_parser:
|
|||
self.strtab = set()
|
||||
self.strtab_weak = set()
|
||||
self.strtab_long = set()
|
||||
self.bintab = set()
|
||||
self.text = text
|
||||
self.parsers = {
|
||||
"@const_object_info_begin": self.parse_object,
|
||||
"be_const_str_": self.parse_string,
|
||||
"be_const_bytes_instance(": self.parse_bin,
|
||||
"be_const_key(": self.parse_string,
|
||||
"be_nested_str(": self.parse_string,
|
||||
"be_const_key_weak(": self.parse_string_weak,
|
||||
|
@ -77,6 +79,7 @@ class coc_parser:
|
|||
def parse_word(self):
|
||||
self.skip_space()
|
||||
r = re.match(r"\w+", self.text)
|
||||
if not r: return None
|
||||
self.text = self.text[r.end(0):]
|
||||
return r[0]
|
||||
|
||||
|
@ -120,6 +123,7 @@ class coc_parser:
|
|||
def parse_string(self):
|
||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||
ident = self.parse_word()
|
||||
if not ident: return
|
||||
literal = unescape_operator(ident)
|
||||
if not literal in self.strtab:
|
||||
self.strtab.add(literal)
|
||||
|
@ -128,6 +132,7 @@ class coc_parser:
|
|||
def parse_string_weak(self):
|
||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||
ident = self.parse_word()
|
||||
if not ident: return
|
||||
literal = unescape_operator(ident)
|
||||
if not literal in self.strtab:
|
||||
self.strtab_weak.add(literal)
|
||||
|
@ -136,10 +141,19 @@ class coc_parser:
|
|||
def parse_string_long(self):
|
||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||
ident = self.parse_word()
|
||||
if not ident: return
|
||||
literal = unescape_operator(ident)
|
||||
if not literal in self.strtab:
|
||||
self.strtab_long.add(literal)
|
||||
|
||||
def parse_bin(self):
|
||||
ident = self.parse_word()
|
||||
if not ident: return
|
||||
if not re.fullmatch(r"[0-9A-Za-z]*", ident): return
|
||||
if not ident in self.bintab:
|
||||
self.bintab.add(ident)
|
||||
# print(f"str '{ident}' -> {literal}")
|
||||
|
||||
#################################################################################
|
||||
# Parse a block of definition like module, class...
|
||||
#################################################################################
|
||||
|
|
Loading…
Reference in New Issue