mirror of
https://github.com/janet-lang/janet
synced 2025-05-01 15:04:15 +00:00
Add option to marshal values without cycle detection.
This commit is contained in:
parent
0817e627ee
commit
a575f5df36
@ -37,6 +37,7 @@ typedef struct {
|
|||||||
JanetFuncEnv **seen_envs;
|
JanetFuncEnv **seen_envs;
|
||||||
JanetFuncDef **seen_defs;
|
JanetFuncDef **seen_defs;
|
||||||
int32_t nextid;
|
int32_t nextid;
|
||||||
|
int maybe_cycles;
|
||||||
} MarshalState;
|
} MarshalState;
|
||||||
|
|
||||||
/* Lead bytes in marshaling protocol */
|
/* Lead bytes in marshaling protocol */
|
||||||
@ -364,13 +365,15 @@ void janet_marshal_janet(JanetMarshalContext *ctx, Janet x) {
|
|||||||
|
|
||||||
void janet_marshal_abstract(JanetMarshalContext *ctx, void *abstract) {
|
void janet_marshal_abstract(JanetMarshalContext *ctx, void *abstract) {
|
||||||
MarshalState *st = (MarshalState *)(ctx->m_state);
|
MarshalState *st = (MarshalState *)(ctx->m_state);
|
||||||
|
if (st->maybe_cycles) {
|
||||||
janet_table_put(&st->seen,
|
janet_table_put(&st->seen,
|
||||||
janet_wrap_abstract(abstract),
|
janet_wrap_abstract(abstract),
|
||||||
janet_wrap_integer(st->nextid++));
|
janet_wrap_integer(st->nextid++));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MARK_SEEN() \
|
#define MARK_SEEN() \
|
||||||
janet_table_put(&st->seen, x, janet_wrap_integer(st->nextid++))
|
do { if (st->maybe_cycles) janet_table_put(&st->seen, x, janet_wrap_integer(st->nextid++)); } while (0)
|
||||||
|
|
||||||
static void marshal_one_abstract(MarshalState *st, Janet x, int flags) {
|
static void marshal_one_abstract(MarshalState *st, Janet x, int flags) {
|
||||||
void *abstract = janet_unwrap_abstract(x);
|
void *abstract = janet_unwrap_abstract(x);
|
||||||
@ -428,12 +431,15 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
|
|
||||||
/* Check reference and registry value */
|
/* Check reference and registry value */
|
||||||
{
|
{
|
||||||
Janet check = janet_table_get(&st->seen, x);
|
Janet check;
|
||||||
|
if (st->maybe_cycles) {
|
||||||
|
check = janet_table_get(&st->seen, x);
|
||||||
if (janet_checkint(check)) {
|
if (janet_checkint(check)) {
|
||||||
pushbyte(st, LB_REFERENCE);
|
pushbyte(st, LB_REFERENCE);
|
||||||
pushint(st, janet_unwrap_integer(check));
|
pushint(st, janet_unwrap_integer(check));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (st->rreg) {
|
if (st->rreg) {
|
||||||
check = janet_table_get(st->rreg, x);
|
check = janet_table_get(st->rreg, x);
|
||||||
if (janet_checktype(check, JANET_SYMBOL)) {
|
if (janet_checktype(check, JANET_SYMBOL)) {
|
||||||
@ -613,6 +619,7 @@ void janet_marshal(
|
|||||||
st.seen_defs = NULL;
|
st.seen_defs = NULL;
|
||||||
st.seen_envs = NULL;
|
st.seen_envs = NULL;
|
||||||
st.rreg = rreg;
|
st.rreg = rreg;
|
||||||
|
st.maybe_cycles = !(flags & JANET_MARSHAL_NO_CYCLES);
|
||||||
janet_table_init(&st.seen, 0);
|
janet_table_init(&st.seen, 0);
|
||||||
marshal_one(&st, x, flags);
|
marshal_one(&st, x, flags);
|
||||||
janet_table_deinit(&st.seen);
|
janet_table_deinit(&st.seen);
|
||||||
@ -1471,16 +1478,17 @@ JANET_CORE_FN(cfun_env_lookup,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_marshal,
|
JANET_CORE_FN(cfun_marshal,
|
||||||
"(marshal x &opt reverse-lookup buffer)",
|
"(marshal x &opt reverse-lookup buffer no-cycles)",
|
||||||
"Marshal a value into a buffer and return the buffer. The buffer "
|
"Marshal a value into a buffer and return the buffer. The buffer "
|
||||||
"can then later be unmarshalled to reconstruct the initial value. "
|
"can then later be unmarshalled to reconstruct the initial value. "
|
||||||
"Optionally, one can pass in a reverse lookup table to not marshal "
|
"Optionally, one can pass in a reverse lookup table to not marshal "
|
||||||
"aliased values that are found in the table. Then a forward "
|
"aliased values that are found in the table. Then a forward "
|
||||||
"lookup table can be used to recover the original value when "
|
"lookup table can be used to recover the original value when "
|
||||||
"unmarshalling.") {
|
"unmarshalling.") {
|
||||||
janet_arity(argc, 1, 3);
|
janet_arity(argc, 1, 4);
|
||||||
JanetBuffer *buffer;
|
JanetBuffer *buffer;
|
||||||
JanetTable *rreg = NULL;
|
JanetTable *rreg = NULL;
|
||||||
|
uint32_t flags = 0;
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
rreg = janet_gettable(argv, 1);
|
rreg = janet_gettable(argv, 1);
|
||||||
}
|
}
|
||||||
@ -1489,7 +1497,10 @@ JANET_CORE_FN(cfun_marshal,
|
|||||||
} else {
|
} else {
|
||||||
buffer = janet_buffer(10);
|
buffer = janet_buffer(10);
|
||||||
}
|
}
|
||||||
janet_marshal(buffer, argv[0], rreg, 0);
|
if (argc > 3 && janet_truthy(argv[3])) {
|
||||||
|
flags |= JANET_MARSHAL_NO_CYCLES;
|
||||||
|
}
|
||||||
|
janet_marshal(buffer, argv[0], rreg, flags);
|
||||||
return janet_wrap_buffer(buffer);
|
return janet_wrap_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1671,6 +1671,7 @@ JANET_API JanetModule janet_native(const char *name, JanetString *error);
|
|||||||
|
|
||||||
/* Marshaling */
|
/* Marshaling */
|
||||||
#define JANET_MARSHAL_UNSAFE 0x20000
|
#define JANET_MARSHAL_UNSAFE 0x20000
|
||||||
|
#define JANET_MARSHAL_NO_CYCLES 0x40000
|
||||||
|
|
||||||
JANET_API void janet_marshal(
|
JANET_API void janet_marshal(
|
||||||
JanetBuffer *buf,
|
JanetBuffer *buf,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user