1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-27 00:40:26 +00:00

implement typed array marshal/unmarshal and

generic marshaling capabilities to abstract types.
This commit is contained in:
J.-F. Cap 2019-02-23 16:58:47 +01:00
parent 7cb1c7cef2
commit 0cc6c6ff33
4 changed files with 182 additions and 52 deletions

View File

@ -319,7 +319,7 @@ static int marshal_one_abstract(MarshalState *st, Janet x, int flags) {
if (! info) return 1 ; /* unregistered type skip marshalling*/ if (! info) return 1 ; /* unregistered type skip marshalling*/
if (info->marshal) { if (info->marshal) {
MARK_SEEN(); MARK_SEEN();
JanetMarshalContext context={st,NULL,flags}; JanetMarshalContext context={st,NULL,flags,NULL};
pushbyte(st, LB_ABSTRACT); pushbyte(st, LB_ABSTRACT);
pushint(st,info->tag); pushint(st,info->tag);
info->marshal(janet_unwrap_abstract(x),&context); info->marshal(janet_unwrap_abstract(x),&context);
@ -576,7 +576,8 @@ enum {
UMR_EXPECTED_STRING, UMR_EXPECTED_STRING,
UMR_INVALID_REFERENCE, UMR_INVALID_REFERENCE,
UMR_INVALID_BYTECODE, UMR_INVALID_BYTECODE,
UMR_INVALID_FIBER UMR_INVALID_FIBER,
UMR_INVALID_ABSTRACT
} UnmarshalResult; } UnmarshalResult;
const char *umr_strings[] = { const char *umr_strings[] = {
@ -590,7 +591,8 @@ const char *umr_strings[] = {
"expected string", "expected string",
"invalid reference", "invalid reference",
"invalid bytecode", "invalid bytecode",
"invalid fiber" "invalid fiber",
"invalid abstract",
}; };
/* Helper to read a 32 bit integer from an unmarshal state */ /* Helper to read a 32 bit integer from an unmarshal state */
@ -954,6 +956,59 @@ error:
return NULL; return NULL;
} }
void janet_unmarshal_int(JanetMarshalContext *ctx,int32_t* i) {
UnmarshalState *st =(UnmarshalState *)(ctx->u_state);
*i=readint(st,&(ctx->data));
};
void janet_unmarshal_uint(JanetMarshalContext *ctx,uint32_t* i) {
UnmarshalState *st =(UnmarshalState *)(ctx->u_state);
*i=(uint32_t)readint(st,&(ctx->data));
};
void janet_unmarshal_size(JanetMarshalContext *ctx,size_t* i) {
UnmarshalState *st =(UnmarshalState *)(ctx->u_state);
*i=(size_t)readint(st,&(ctx->data));
};
void janet_unmarshal_byte(JanetMarshalContext *ctx,uint8_t* b) {
*b=*(ctx->data++);
};
void janet_unmarshal_bytes(JanetMarshalContext *ctx,uint8_t *dest, int32_t len) {
memcpy(dest,ctx->data,len);
ctx->data+=len;
}
void janet_unmarshal_janet(JanetMarshalContext *ctx,Janet *out) {
UnmarshalState *st =(UnmarshalState *)(ctx->u_state);
ctx->data=unmarshal_one(st,ctx->data,out,ctx->flags);
}
static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) {
uint32_t tag=readint(st,&data);
const JanetAbstractTypeInfo *info = janet_get_abstract_type_info(tag);
if (info==NULL) goto error;
if (info->unmarshal) {
void *p = janet_abstract(info->at,info->size);
JanetMarshalContext context={NULL,st,flags,data};
info->unmarshal(p,&context);
*out=janet_wrap_abstract(p);
return data;
}
return 0;
error:
longjmp(st->err, UMR_INVALID_ABSTRACT);
return NULL;
}
static const uint8_t *unmarshal_one( static const uint8_t *unmarshal_one(
UnmarshalState *st, UnmarshalState *st,
const uint8_t *data, const uint8_t *data,
@ -1067,6 +1122,10 @@ static const uint8_t *unmarshal_one(
} }
return data; return data;
} }
case LB_ABSTRACT: {
data++;
return unmarshal_one_abstract(st,data,out,flags);
}
case LB_REFERENCE: case LB_REFERENCE:
case LB_ARRAY: case LB_ARRAY:
case LB_TUPLE: case LB_TUPLE:

View File

@ -80,8 +80,7 @@ static size_t ta_type_sizes[] = {
sizeof(ta_float64_t), sizeof(ta_float64_t),
}; };
#define TA_COUNT_TYPES (TA_TYPE_float64 + 1) #define TA_COUNT_TYPES (TA_TYPE_float64 + 1)
#define TA_ATOM_MAXSIZE 8; #define TA_ATOM_MAXSIZE 8
#define TA_FLAG_BIG_ENDIAN 1 #define TA_FLAG_BIG_ENDIAN 1
static TA_Type get_ta_type_by_name(const uint8_t *name) { static TA_Type get_ta_type_by_name(const uint8_t *name) {
@ -99,7 +98,7 @@ static TA_Type get_ta_type_by_name(const uint8_t *name) {
typedef struct { typedef struct {
uint8_t *data; uint8_t *data;
size_t size; size_t size;
int32_t flags; uint32_t flags;
} TA_Buffer; } TA_Buffer;
static TA_Buffer *ta_buffer_init(TA_Buffer *buf, size_t size) { static TA_Buffer *ta_buffer_init(TA_Buffer *buf, size_t size) {
@ -127,12 +126,25 @@ static void ta_buffer_marshal(void *p, JanetMarshalContext *ctx) {
janet_marshal_bytes(ctx,buf->data,buf->size); janet_marshal_bytes(ctx,buf->data,buf->size);
} }
static void ta_buffer_unmarshal(void *p, JanetMarshalContext *ctx) {
TA_Buffer *buf = (TA_Buffer *)p;
uint32_t size;
janet_unmarshal_uint(ctx,&size);
ta_buffer_init(buf,size); // warning if indianess <> platform ??
janet_unmarshal_uint(ctx,&(buf->flags));
janet_unmarshal_bytes(ctx,buf->data,buf->size);
}
static const JanetAbstractType ta_buffer_type={"ta/buffer", ta_buffer_gc, NULL, NULL, NULL}; static const JanetAbstractType ta_buffer_type={"ta/buffer", ta_buffer_gc, NULL, NULL, NULL};
static const JanetAbstractTypeInfo ta_buffer_typeinfo={ static const JanetAbstractTypeInfo ta_buffer_typeinfo={
&ta_buffer_type, &ta_buffer_type,
sizeof(TA_Buffer),
1000, 1000,
0,
ta_buffer_marshal, ta_buffer_marshal,
ta_buffer_unmarshal,
}; };
@ -154,13 +166,30 @@ static int ta_mark(void *p, size_t s) {
static void ta_view_marshal(void *p, JanetMarshalContext *ctx) { static void ta_view_marshal(void *p, JanetMarshalContext *ctx) {
TA_View *view = (TA_View *)p; TA_View *view = (TA_View *)p;
size_t offset = (view->buffer->data - (uint8_t *)(view->data));
janet_marshal_int(ctx,view->size); janet_marshal_int(ctx,view->size);
janet_marshal_int(ctx,view->stride); janet_marshal_int(ctx,view->stride);
janet_marshal_int(ctx,view->type); janet_marshal_int(ctx,view->type);
janet_marshal_int(ctx,offset);
janet_marshal_janet(ctx,janet_wrap_abstract(view->buffer)); janet_marshal_janet(ctx,janet_wrap_abstract(view->buffer));
} }
static void ta_view_unmarshal(void *p, JanetMarshalContext *ctx) {
TA_View *view = (TA_View *)p;
size_t offset;
Janet buffer;
janet_unmarshal_size(ctx,&(view->size));
janet_unmarshal_size(ctx,&(view->stride));
janet_unmarshal_uint(ctx,&(view->type));
janet_unmarshal_size(ctx,&offset);
janet_unmarshal_janet(ctx,&buffer);
view->buffer=(TA_Buffer *)janet_unwrap_abstract(buffer);
view->data=view->buffer->data+offset;
}
#define DEFINE_VIEW_TYPE(thetype) \ #define DEFINE_VIEW_TYPE(thetype) \
@ -250,11 +279,11 @@ BUILD_TYPE(float64)
#undef DEFINE_VIEW_INITIALIZER #undef DEFINE_VIEW_INITIALIZER
#undef DEFINE_VIEW_ABSTRACT_TYPE #undef DEFINE_VIEW_ABSTRACT_TYPE
#define VIEW_ABSTRACT_INFO_INIT(type,tag) {&ta_view_##type##_t,tag,ta_view_marshal} #define VIEW_ABSTRACT_INFO_INIT(type,salt) {&ta_view_##type##_t,sizeof(TA_View),salt,0,ta_view_marshal,ta_view_unmarshal}
static const JanetAbstractTypeInfo ta_array_types[] = { static const JanetAbstractTypeInfo ta_array_types[] = {
VIEW_ABSTRACT_INFO_INIT(uint8,1001), VIEW_ABSTRACT_INFO_INIT(uint8,1001),
VIEW_ABSTRACT_INFO_INT(int8,1002), VIEW_ABSTRACT_INFO_INIT(int8,1002),
VIEW_ABSTRACT_INFO_INIT(uint16,1003), VIEW_ABSTRACT_INFO_INIT(uint16,1003),
VIEW_ABSTRACT_INFO_INIT(int16,1004), VIEW_ABSTRACT_INFO_INIT(int16,1004),
VIEW_ABSTRACT_INFO_INIT(uint32,1005), VIEW_ABSTRACT_INFO_INIT(uint32,1005),
@ -371,28 +400,41 @@ static Janet cfun_abstract_properties(int32_t argc, Janet *argv) {
if (info==NULL) { if (info==NULL) {
return janet_wrap_nil(); return janet_wrap_nil();
} }
JanetKV *props = janet_struct_begin(2); JanetKV *props = janet_struct_begin(5);
janet_struct_put(props, janet_ckeywordv("tag"), janet_wrap_number(info->tag)); janet_struct_put(props, janet_ckeywordv("tag"), janet_wrap_number(info->tag));
janet_struct_put(props, janet_ckeywordv("salt"), janet_wrap_number(info->salt));
janet_struct_put(props, janet_ckeywordv("name"), janet_ckeywordv(info->at->name)); janet_struct_put(props, janet_ckeywordv("name"), janet_ckeywordv(info->at->name));
janet_struct_put(props, janet_ckeywordv("size"), janet_wrap_number(info->size));
janet_struct_put(props, janet_ckeywordv("marshal"), janet_wrap_boolean((info->marshal !=NULL) && (info->unmarshal!=NULL)));
return janet_wrap_struct(janet_struct_end(props)); return janet_wrap_struct(janet_struct_end(props));
} }
/*
static Janet cfun_typed_array_copy_bytes(int32_t argc, Janet *argv) { static Janet cfun_typed_array_copy_bytes(int32_t argc, Janet *argv) {
janet_fixarity(argc, 4); janet_arity(argc, 4, 5);
if (is_ta_type(argv[0]) && is_ta_type(argv[2])) { if (is_ta_type(argv[0]) && is_ta_type(argv[2])) {
TA_View *src = (TA_View *)janet_unwrap_abstract(argv[0]); TA_View *src = (TA_View *)janet_unwrap_abstract(argv[0]);
size_t index_src=(size_t)janet_getinteger(argv, 1); size_t index_src=(size_t)janet_getinteger(argv, 1);
TA_View *dst = (TA_View *)janet_unwrap_abstract(argv[2]); TA_View *dst = (TA_View *)janet_unwrap_abstract(argv[2]);
size_t index_dst=(size_t)janet_getinteger(argv, 3); size_t index_dst=(size_t)janet_getinteger(argv, 3);
size_t count=(argc == 5)? (size_t)janet_getinteger(argv, 4) : 1;
size_t src_atom_size=ta_type_sizes[src->type]; size_t src_atom_size=ta_type_sizes[src->type];
size_t dst_atom_size=ta_type_sizes[dst->type]; size_t dst_atom_size=ta_type_sizes[dst->type];
size_t pos_src=((uint8_t *)(src->data) - src->buffer->data)+(index_src*src->stride*src_atom_size); size_t step_src=src->stride*src_atom_size;
size_t pos_dst=((uint8_t *)(dst->data) - dst->buffer->data)+(index_dst*dst->stride*dst_atom_size); size_t step_dst=dst->stride*dst_atom_size;
if (pos_dst+src_atom_size <= dst->buffer->size) size_t pos_src=((uint8_t *)(src->data) - src->buffer->data)+(index_src*step_src);
memmove(dst->buffer->data+pos_dst,src->buffer->data+pos_src,src_atom_size); size_t pos_dst=((uint8_t *)(dst->data) - dst->buffer->data)+(index_dst*step_dst);
uint8_t * ps=src->buffer->data+pos_src,* pd=dst->buffer->data+pos_dst;
if ((pos_dst+(count-1)*step_dst+src_atom_size <= dst->buffer->size) &&
(pos_src+(count-1)*step_src+src_atom_size <= src->buffer->size)) {
for (size_t i=0;i<count;i++) {
memmove(pd,ps,src_atom_size);
pd+=step_dst;
ps+=step_src;
}
}
else else
janet_panic("typed array out of bound"); janet_panic("typed array copy out of bound");
} else { } else {
janet_panic("expected typed array"); janet_panic("expected typed array");
} }
@ -400,32 +442,39 @@ static Janet cfun_typed_array_copy_bytes(int32_t argc, Janet *argv) {
} }
static Janet cfun_typed_array_swap_bytes(int32_t argc, Janet *argv) { static Janet cfun_typed_array_swap_bytes(int32_t argc, Janet *argv) {
janet_fixarity(argc, 4); janet_arity(argc, 4, 5);
if (is_ta_type(argv[0]) && is_ta_type(argv[2])) { if (is_ta_type(argv[0]) && is_ta_type(argv[2])) {
TA_View *src = (TA_View *)janet_unwrap_abstract(argv[0]); TA_View *src = (TA_View *)janet_unwrap_abstract(argv[0]);
size_t index_src=(size_t)janet_getinteger(argv, 1); size_t index_src=(size_t)janet_getinteger(argv, 1);
TA_View *dst = (TA_View *)janet_unwrap_abstract(argv[2]); TA_View *dst = (TA_View *)janet_unwrap_abstract(argv[2]);
size_t index_dst=(size_t)janet_getinteger(argv, 3); size_t index_dst=(size_t)janet_getinteger(argv, 3);
size_t count=(argc == 5)? (size_t)janet_getinteger(argv, 4) : 1;
size_t src_atom_size=ta_type_sizes[src->type]; size_t src_atom_size=ta_type_sizes[src->type];
size_t dst_atom_size=ta_type_sizes[dst->type]; size_t dst_atom_size=ta_type_sizes[dst->type];
size_t pos_src=((uint8_t *)(src->data) - src->buffer->data)+(index_src*src->stride*src_atom_size); size_t step_src=src->stride*src_atom_size;
size_t pos_dst=((uint8_t *)(dst->data) - dst->buffer->data)+(index_dst*dst->stride*dst_atom_size); size_t step_dst=dst->stride*dst_atom_size;
size_t pos_src=((uint8_t *)(src->data) - src->buffer->data)+(index_src*step_src);
size_t pos_dst=((uint8_t *)(dst->data) - dst->buffer->data)+(index_dst*step_dst);
uint8_t * ps=src->buffer->data+pos_src,* pd=dst->buffer->data+pos_dst;
uint8_t temp[TA_ATOM_MAXSIZE]; uint8_t temp[TA_ATOM_MAXSIZE];
if (pos_dst+src_atom_size <= dst->buffer->size) { if ((pos_dst+(count-1)*step_dst+src_atom_size <= dst->buffer->size) &&
uint8_t * src_ptr=src->buffer->data+pos_src; (pos_src+(count-1)*step_src+src_atom_size <= src->buffer->size)) {
uint8_t * dst_ptr=dst->buffer->data+pos_dst; for (size_t i=0;i<count;i++) {
memcpy(temp,src_ptr,src_atom_size); memcpy(temp,ps,src_atom_size);
memcpy(src_ptr,dst_ptr,src_atom_size); memcpy(ps,pd,src_atom_size);
memcpy(dst_ptr,temp,src_atom_size); memcpy(pd,temp,src_atom_size);
pd+=step_dst;
ps+=step_src;
}
} }
else else
janet_panic("typed array buffer out of bound"); janet_panic("typed array swap out of bound");
} else { } else {
janet_panic("expected typed array"); janet_panic("expected typed array");
} }
return janet_wrap_nil(); return janet_wrap_nil();
} }
*/
static const JanetReg ta_cfuns[] = { static const JanetReg ta_cfuns[] = {
@ -449,6 +498,22 @@ static const JanetReg ta_cfuns[] = {
JDOC("(tarray/properties array )\n\n" JDOC("(tarray/properties array )\n\n"
"return typed array properties as a struct") "return typed array properties as a struct")
}, },
{
"tarray/copy-bytes", cfun_typed_array_copy_bytes,
JDOC("(tarray/copy-bytes src sindex dst dindex [count=1])\n\n"
"copy count elements of src array from index sindex \n"
"to dst array at position dindex \n"
"memory can overlap"
)
},
{
"tarray/swap-bytes", cfun_typed_array_swap_bytes,
JDOC("(tarray/swap-bytes src sindex dst dindex [count=1])\n\n"
"swap count elements between src array from index sindex \n"
"and dst array at position dindex \n"
"memory can overlap"
)
},
{ {
"abstract/properties", cfun_abstract_properties, "abstract/properties", cfun_abstract_properties,
JDOC("(abstract/properties tag)\n\n" JDOC("(abstract/properties tag)\n\n"

View File

@ -284,31 +284,30 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns)
} }
} }
/* Abstract type introspection */
static const JanetAbstractType type_info = {"core/type_info", NULL, NULL, NULL, NULL}; static const JanetAbstractType type_info = {"core/type_info", NULL, NULL, NULL, NULL};
/* static uint32_t janet_abstract_type_gentag(const char * name,uint32_t salt) {
void janet_register_abstract_type(const JanetAbstractType *atype,uint32_t tag) { /* something smarter should propably done here ? */
JanetAbstractTypeInfo * abstract =(JanetAbstractTypeInfo *)janet_abstract(&type_info,sizeof(JanetAbstractTypeInfo)); int32_t len = strlen(name);
abstract->type=*atype; const char *end = name + len;
abstract->tag=tag; uint32_t hash = 5381+salt;
if (!(janet_checktype(janet_table_get(janet_vm_registry,janet_wrap_number(tag)),JANET_NIL)) || while (name < end)
!(janet_checktype(janet_table_get(janet_vm_registry,janet_ckeywordv(atype->name)),JANET_NIL))) { hash = (hash << 5) + hash + *name++;
janet_panic("Register abstract type fail, a type with same name or tag exist"); return (int32_t) hash;
}
janet_table_put(janet_vm_registry,janet_wrap_number(tag), janet_wrap_abstract(abstract));
janet_table_put(janet_vm_registry,janet_ckeywordv(atype->name), janet_wrap_abstract(abstract));
} }
*/
void janet_register_abstract_type(const JanetAbstractTypeInfo * info) { void janet_register_abstract_type(const JanetAbstractTypeInfo * info) {
JanetAbstractTypeInfo * abstract =(JanetAbstractTypeInfo *)janet_abstract(&type_info,sizeof(JanetAbstractTypeInfo)); JanetAbstractTypeInfo * abstract =(JanetAbstractTypeInfo *)janet_abstract(&type_info,sizeof(JanetAbstractTypeInfo));
memcpy(abstract,info,sizeof(JanetAbstractTypeInfo)); memcpy(abstract,info,sizeof(JanetAbstractTypeInfo));
if (!(janet_checktype(janet_table_get(janet_vm_registry,janet_wrap_number(info->tag)),JANET_NIL)) || abstract->tag=janet_abstract_type_gentag(info->at->name,info->salt);
!(janet_checktype(janet_table_get(janet_vm_registry,janet_ckeywordv(info->at->name)),JANET_NIL))) { if (!(janet_checktype(janet_table_get(janet_vm_registry,janet_wrap_number(abstract->tag)),JANET_NIL)) ||
!(janet_checktype(janet_table_get(janet_vm_registry,janet_ckeywordv(abstract->at->name)),JANET_NIL))) {
janet_panic("Register abstract type fail, a type with same name or tag exist"); janet_panic("Register abstract type fail, a type with same name or tag exist");
} }
janet_table_put(janet_vm_registry,janet_wrap_number(info->tag), janet_wrap_abstract(abstract)); janet_table_put(janet_vm_registry,janet_wrap_number(abstract->tag), janet_wrap_abstract(abstract));
janet_table_put(janet_vm_registry,janet_ckeywordv(info->at->name), janet_wrap_abstract(abstract)); janet_table_put(janet_vm_registry,janet_ckeywordv(abstract->at->name), janet_wrap_abstract(abstract));
} }

View File

@ -1243,30 +1243,37 @@ JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv);
JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which);
JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which);
typedef struct { typedef struct {
void * m_state; /* void* to not expose MarshalState ?*/ void * m_state; /* void* to not expose MarshalState ?*/
void * u_state; void * u_state;
int flags; int flags;
const uint8_t * data;
} JanetMarshalContext; } JanetMarshalContext;
void janet_marshal_int(JanetMarshalContext *ctx,int32_t value); JANET_API void janet_marshal_int(JanetMarshalContext *ctx,int32_t value);
void janet_marshal_byte(JanetMarshalContext *ctx,uint8_t value); JANET_API void janet_marshal_byte(JanetMarshalContext *ctx,uint8_t value);
void janet_marshal_bytes(JanetMarshalContext *ctx,const uint8_t *bytes, int32_t len); JANET_API void janet_marshal_bytes(JanetMarshalContext *ctx,const uint8_t *bytes, int32_t len);
void janet_marshal_janet(JanetMarshalContext *ctx,Janet x); JANET_API void janet_marshal_janet(JanetMarshalContext *ctx,Janet x);
JANET_API void janet_unmarshal_int(JanetMarshalContext *ctx,int32_t* i);
JANET_API void janet_unmarshal_uint(JanetMarshalContext *ctx,uint32_t* i);
JANET_API void janet_unmarshal_size(JanetMarshalContext *ctx,size_t * i);
JANET_API void janet_unmarshal_byte(JanetMarshalContext *ctx,uint8_t* b);
JANET_API void janet_unmarshal_bytes(JanetMarshalContext *ctx,uint8_t *dest, int32_t len);
JANET_API void janet_unmarshal_janet(JanetMarshalContext *ctx,Janet *out);
typedef struct { typedef struct {
const JanetAbstractType *at; const JanetAbstractType *at;
const uint32_t tag; size_t size; /* abstract type size */
const uint32_t salt; /* salt */
uint32_t tag; /* unique tag computed by janet (hash of name and salt) */
void (* marshal)(void *p,JanetMarshalContext *ctx); void (* marshal)(void *p,JanetMarshalContext *ctx);
void (* unmarshal)(void *p,JanetMarshalContext *ctx);
} JanetAbstractTypeInfo; } JanetAbstractTypeInfo;
JANET_API void janet_register_abstract_type(const JanetAbstractTypeInfo * info); JANET_API void janet_register_abstract_type(const JanetAbstractTypeInfo * info);
JANET_API JanetAbstractTypeInfo * janet_get_abstract_type_info(uint32_t tag); JANET_API JanetAbstractTypeInfo * janet_get_abstract_type_info(uint32_t tag);
/*JANET_API uint32_t janet_get_abstract_type_tag(const JanetAbstractType *atype);*/
JANET_API JanetAbstractTypeInfo * janet_get_abstract_type_info_byname(const char * name); JANET_API JanetAbstractTypeInfo * janet_get_abstract_type_info_byname(const char * name);