diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-16 14:55:49 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-16 14:55:49 -0300 |
| commit | f8d30826dda6ee8e99200de57a1997734b853db2 (patch) | |
| tree | d3a24665802f41fe3216714252ed189006f302cd /ltable.c | |
| parent | 351ccd733298e08c41937c1baf22a68e62bfeca9 (diff) | |
| download | lua-f8d30826dda6ee8e99200de57a1997734b853db2.tar.gz lua-f8d30826dda6ee8e99200de57a1997734b853db2.tar.bz2 lua-f8d30826dda6ee8e99200de57a1997734b853db2.zip | |
New table API for 'set' functions
Diffstat (limited to 'ltable.c')
| -rw-r--r-- | ltable.c | 120 |
1 files changed, 100 insertions, 20 deletions
| @@ -719,15 +719,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { | |||
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | 721 | ||
| 722 | /* | 722 | static const TValue *getintfromarray (Table *t, lua_Integer key) { |
| 723 | ** Search function for integers. If integer is inside 'alimit', get it | ||
| 724 | ** directly from the array part. Otherwise, if 'alimit' is not equal to | ||
| 725 | ** the real size of the array, key still can be in the array part. In | ||
| 726 | ** this case, try to avoid a call to 'luaH_realasize' when key is just | ||
| 727 | ** one more than the limit (so that it can be incremented without | ||
| 728 | ** changing the real size of the array). | ||
| 729 | */ | ||
| 730 | const TValue *luaH_getint (Table *t, lua_Integer key) { | ||
| 731 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ | 723 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ |
| 732 | return &t->array[key - 1]; | 724 | return &t->array[key - 1]; |
| 733 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ | 725 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ |
| @@ -736,19 +728,40 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
| 736 | t->alimit = cast_uint(key); /* probably '#t' is here now */ | 728 | t->alimit = cast_uint(key); /* probably '#t' is here now */ |
| 737 | return &t->array[key - 1]; | 729 | return &t->array[key - 1]; |
| 738 | } | 730 | } |
| 739 | else { | 731 | else return NULL; /* key is not in the array part */ |
| 740 | Node *n = hashint(t, key); | 732 | } |
| 741 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 733 | |
| 742 | if (keyisinteger(n) && keyival(n) == key) | 734 | |
| 743 | return gval(n); /* that's it */ | 735 | static const TValue *getintfromhash (Table *t, lua_Integer key) { |
| 744 | else { | 736 | Node *n = hashint(t, key); |
| 745 | int nx = gnext(n); | 737 | lua_assert(l_castS2U(key) - 1u >= luaH_realasize(t)); |
| 746 | if (nx == 0) break; | 738 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
| 747 | n += nx; | 739 | if (keyisinteger(n) && keyival(n) == key) |
| 748 | } | 740 | return gval(n); /* that's it */ |
| 741 | else { | ||
| 742 | int nx = gnext(n); | ||
| 743 | if (nx == 0) break; | ||
| 744 | n += nx; | ||
| 749 | } | 745 | } |
| 750 | return &absentkey; | ||
| 751 | } | 746 | } |
| 747 | return &absentkey; | ||
| 748 | } | ||
| 749 | |||
| 750 | |||
| 751 | /* | ||
| 752 | ** Search function for integers. If integer is inside 'alimit', get it | ||
| 753 | ** directly from the array part. Otherwise, if 'alimit' is not equal to | ||
| 754 | ** the real size of the array, key still can be in the array part. In | ||
| 755 | ** this case, try to avoid a call to 'luaH_realasize' when key is just | ||
| 756 | ** one more than the limit (so that it can be incremented without | ||
| 757 | ** changing the real size of the array). | ||
| 758 | */ | ||
| 759 | const TValue *luaH_getint (Table *t, lua_Integer key) { | ||
| 760 | const TValue *slot = getintfromarray(t, key); | ||
| 761 | if (slot != NULL) | ||
| 762 | return slot; | ||
| 763 | else | ||
| 764 | return getintfromhash(t, key); | ||
| 752 | } | 765 | } |
| 753 | 766 | ||
| 754 | 767 | ||
| @@ -832,6 +845,58 @@ int luaH_get1 (Table *t, const TValue *key, TValue *res) { | |||
| 832 | } | 845 | } |
| 833 | 846 | ||
| 834 | 847 | ||
| 848 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { | ||
| 849 | if (!ttisnil(slot)) { | ||
| 850 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | ||
| 851 | return HOK; /* success */ | ||
| 852 | } | ||
| 853 | else if (isabstkey(slot)) | ||
| 854 | return HNOTFOUND; /* no slot with that key */ | ||
| 855 | else return (cast(Node*, slot) - t->node) + HFIRSTNODE; /* node encoded */ | ||
| 856 | } | ||
| 857 | |||
| 858 | |||
| 859 | int luaH_setint1 (Table *t, lua_Integer key, TValue *val) { | ||
| 860 | const TValue *slot = getintfromarray(t, key); | ||
| 861 | if (slot != NULL) { | ||
| 862 | if (!ttisnil(slot)) { | ||
| 863 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | ||
| 864 | return HOK; /* success */ | ||
| 865 | } | ||
| 866 | else | ||
| 867 | return ~cast_int(key); /* empty slot in the array part */ | ||
| 868 | } | ||
| 869 | else | ||
| 870 | return finishnodeset(t, getintfromhash(t, key), val); | ||
| 871 | } | ||
| 872 | |||
| 873 | |||
| 874 | int luaH_setshortstr1 (Table *t, TString *key, TValue *val) { | ||
| 875 | return finishnodeset(t, luaH_getshortstr(t, key), val); | ||
| 876 | } | ||
| 877 | |||
| 878 | |||
| 879 | int luaH_setstr1 (Table *t, TString *key, TValue *val) { | ||
| 880 | return finishnodeset(t, luaH_getstr(t, key), val); | ||
| 881 | } | ||
| 882 | |||
| 883 | |||
| 884 | int luaH_set1 (Table *t, const TValue *key, TValue *val) { | ||
| 885 | switch (ttypetag(key)) { | ||
| 886 | case LUA_VSHRSTR: return luaH_setshortstr1(t, tsvalue(key), val); | ||
| 887 | case LUA_VNUMINT: return luaH_setint1(t, ivalue(key), val); | ||
| 888 | case LUA_VNIL: return HNOTFOUND; | ||
| 889 | case LUA_VNUMFLT: { | ||
| 890 | lua_Integer k; | ||
| 891 | if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ | ||
| 892 | return luaH_setint1(t, k, val); /* use specialized version */ | ||
| 893 | /* else... */ | ||
| 894 | } /* FALLTHROUGH */ | ||
| 895 | default: | ||
| 896 | return finishnodeset(t, getgeneric(t, key, 0), val); | ||
| 897 | } | ||
| 898 | } | ||
| 899 | |||
| 835 | /* | 900 | /* |
| 836 | ** Finish a raw "set table" operation, where 'slot' is where the value | 901 | ** Finish a raw "set table" operation, where 'slot' is where the value |
| 837 | ** should have been (the result of a previous "get table"). | 902 | ** should have been (the result of a previous "get table"). |
| @@ -847,6 +912,21 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, | |||
| 847 | } | 912 | } |
| 848 | 913 | ||
| 849 | 914 | ||
| 915 | void luaH_finishset1 (lua_State *L, Table *t, const TValue *key, | ||
| 916 | TValue *value, int aux) { | ||
| 917 | if (aux == HNOTFOUND) { | ||
| 918 | luaH_newkey(L, t, key, value); | ||
| 919 | } | ||
| 920 | else if (aux > 0) { /* regular Node? */ | ||
| 921 | setobj2t(L, gval(gnode(t, aux - HFIRSTNODE)), value); | ||
| 922 | } | ||
| 923 | else { /* array entry */ | ||
| 924 | aux = ~aux; /* real index */ | ||
| 925 | val2arr(t, aux, getArrTag(t, aux), value); | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 929 | |||
| 850 | /* | 930 | /* |
| 851 | ** beware: when using this function you probably need to check a GC | 931 | ** beware: when using this function you probably need to check a GC |
| 852 | ** barrier and invalidate the TM cache. | 932 | ** barrier and invalidate the TM cache. |
