void* pony_deserialise_offset(pony_ctx_t* ctx, pony_type_t* t, uintptr_t offset) { // If the high bit of the offset is set, it is either an unserialised // primitive, or an unserialised field in an opaque object. if((offset & HIGH_BIT) != 0) { offset &= ~HIGH_BIT; if(offset > __DescTableSize) return NULL; // Return the global instance, if there is one. It's ok to return null if // there is no global instance, as this will then be an unserialised // field in an opaque object. t = (&__DescTable)[offset]; return t->instance; } // Lookup the offset, return the associated object if there is one. serialise_t k; k.key = offset; serialise_t* s = ponyint_serialise_get(&ctx->serialise, &k); if(s != NULL) return (void*)s->value; // If we haven't been passed a type descriptor, read one. if(t == NULL) { // Make sure we have space to read a type id. if((offset + sizeof(uintptr_t)) > ctx->serialise_size) pony_throw(); // Turn the type id into a descriptor pointer. uintptr_t id = *(uintptr_t*)((uintptr_t)ctx->serialise_buffer + offset); t = (&__DescTable)[id]; } // If it's a primitive, return the global instance. if(t->instance != NULL) return t->instance; // Make sure we have space to read the object. if((offset + t->size) > ctx->serialise_size) pony_throw(); // Allocate the object, memcpy to it. void* object = pony_alloc(ctx, t->size); memcpy(object, (void*)((uintptr_t)ctx->serialise_buffer + offset), t->size); // Store a mapping of offset to object. s = POOL_ALLOC(serialise_t); s->key = offset; s->value = (uintptr_t)object; ponyint_serialise_put(&ctx->serialise, s); recurse(ctx, object, t->deserialise); return object; }
void pony_serialise_reserve(pony_ctx_t* ctx, void* p, size_t size) { // Reserve a block of memory to serialise into. This is only needed for // String and Array[A]. serialise_t k; k.key = (uintptr_t)p; serialise_t* s = ponyint_serialise_get(&ctx->serialise, &k); if(s != NULL) return; // Put an entry in the map and reserve space. s = POOL_ALLOC(serialise_t); s->key = (uintptr_t)p; s->value = ctx->serialise_size; s->t = NULL; s->mutability = PONY_TRACE_OPAQUE; ponyint_serialise_put(&ctx->serialise, s); ctx->serialise_size += size; }
void ponyint_serialise_object(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability) { if(t->serialise == NULL) { // A type without a serialisation function raises an error. // This applies to Pointer[A] and MaybePointer[A]. serialise_cleanup(ctx); pony_throw(); return; } serialise_t k; k.key = (uintptr_t)p; serialise_t* s = ponyint_serialise_get(&ctx->serialise, &k); if(s != NULL) { // If it was traced as opaque, and now is not opaque, change it and trace. if((s->mutability != PONY_TRACE_OPAQUE) || (mutability == PONY_TRACE_OPAQUE)) return; } else { // Put an entry in the map and reserve space. s = POOL_ALLOC(serialise_t); s->key = (uintptr_t)p; s->value = ctx->serialise_size; s->t = t; ponyint_serialise_put(&ctx->serialise, s); ctx->serialise_size += t->size; } // Set (or update) mutability. s->mutability = mutability; if(mutability != PONY_TRACE_OPAQUE) recurse(ctx, p, t->serialise_trace); }