diff options
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. |