diff options
Diffstat (limited to 'src/deep.c')
-rw-r--r-- | src/deep.c | 43 |
1 files changed, 37 insertions, 6 deletions
@@ -256,7 +256,7 @@ static int deep_userdata_gc( lua_State* L) | |||
256 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 256 | * used in this Lua state (metatable, registring it). Otherwise, increments the |
257 | * reference count. | 257 | * reference count. |
258 | */ | 258 | */ |
259 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, LookupMode mode_) | 259 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) |
260 | { | 260 | { |
261 | DeepPrelude** proxy; | 261 | DeepPrelude** proxy; |
262 | 262 | ||
@@ -283,7 +283,8 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
283 | STACK_GROW( L, 7); | 283 | STACK_GROW( L, 7); |
284 | STACK_CHECK( L, 0); | 284 | STACK_CHECK( L, 0); |
285 | 285 | ||
286 | proxy = lua_newuserdatauv( L, sizeof(DeepPrelude*), 0); // DPC proxy | 286 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
287 | proxy = lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy | ||
287 | ASSERT_L( proxy); | 288 | ASSERT_L( proxy); |
288 | *proxy = prelude; | 289 | *proxy = prelude; |
289 | 290 | ||
@@ -414,7 +415,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
414 | * proxy_ud= deep_userdata( idfunc [, ...] ) | 415 | * proxy_ud= deep_userdata( idfunc [, ...] ) |
415 | * | 416 | * |
416 | * Creates a deep userdata entry of the type defined by 'idfunc'. | 417 | * Creates a deep userdata entry of the type defined by 'idfunc'. |
417 | * Other parameters are passed on to the 'idfunc' "new" invocation. | 418 | * Parameters found on the stack are left as is passed on to the 'idfunc' "new" invocation. |
418 | * | 419 | * |
419 | * 'idfunc' must fulfill the following features: | 420 | * 'idfunc' must fulfill the following features: |
420 | * | 421 | * |
@@ -430,7 +431,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
430 | * | 431 | * |
431 | * Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' | 432 | * Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' |
432 | */ | 433 | */ |
433 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | 434 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) |
434 | { | 435 | { |
435 | char const* errmsg; | 436 | char const* errmsg; |
436 | 437 | ||
@@ -460,7 +461,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | |||
460 | idfunc( L, eDO_delete); | 461 | idfunc( L, eDO_delete); |
461 | return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); | 462 | return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); |
462 | } | 463 | } |
463 | errmsg = push_deep_proxy( universe_get( L), L, prelude, eLM_LaneBody); // proxy | 464 | errmsg = push_deep_proxy( universe_get( L), L, prelude, nuv_, eLM_LaneBody); // proxy |
464 | if( errmsg != NULL) | 465 | if( errmsg != NULL) |
465 | { | 466 | { |
466 | return luaL_error( L, errmsg); | 467 | return luaL_error( L, errmsg); |
@@ -506,12 +507,42 @@ bool_t copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode | |||
506 | { | 507 | { |
507 | char const* errmsg; | 508 | char const* errmsg; |
508 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); | 509 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); |
510 | int nuv = 0; | ||
511 | |||
509 | if( idfunc == NULL) | 512 | if( idfunc == NULL) |
510 | { | 513 | { |
511 | return FALSE; // not a deep userdata | 514 | return FALSE; // not a deep userdata |
512 | } | 515 | } |
513 | 516 | ||
514 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, index), mode_); | 517 | STACK_CHECK( L, 0); |
518 | STACK_CHECK( L2, 0); | ||
519 | |||
520 | // extract all uservalues of the source | ||
521 | while( lua_getiuservalue( L, index, nuv + 1) != LUA_TNONE) // ... u [uv]+ nil | ||
522 | { | ||
523 | ++ nuv; | ||
524 | } | ||
525 | // last call returned TNONE and pushed nil, that we don't need | ||
526 | lua_pop( L, 1); // ... u [uv]+ | ||
527 | STACK_MID( L, nuv); | ||
528 | |||
529 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, index), nuv, mode_); // u | ||
530 | |||
531 | // transfer all uservalues of the source in the destination | ||
532 | { | ||
533 | int const clone_i = lua_gettop( L2); | ||
534 | luaG_inter_move( U, L, L2, nuv, mode_); // ... u // u [uv]+ | ||
535 | while( nuv > 0) | ||
536 | { | ||
537 | // this pops the value from the stack | ||
538 | lua_setiuservalue( L2, clone_i, nuv); // ... u // u | ||
539 | -- nuv; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | STACK_END( L2, 1); | ||
544 | STACK_END( L, 0); | ||
545 | |||
515 | if( errmsg != NULL) | 546 | if( errmsg != NULL) |
516 | { | 547 | { |
517 | // raise the error in the proper state (not the keeper) | 548 | // raise the error in the proper state (not the keeper) |