diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-10-14 17:13:31 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-10-14 17:13:31 -0200 |
commit | 4e9f2d13d5b6fa71ca480394e0b7e75463d4aeec (patch) | |
tree | d11eee681ce7b01a273e489f47e070494b51de1a /lbuiltin.c | |
parent | b6ebbb2fee13aa223fdd12921cd0411e02db9dd0 (diff) | |
download | lua-4e9f2d13d5b6fa71ca480394e0b7e75463d4aeec.tar.gz lua-4e9f2d13d5b6fa71ca480394e0b7e75463d4aeec.tar.bz2 lua-4e9f2d13d5b6fa71ca480394e0b7e75463d4aeec.zip |
new implementation of hash tables.
Diffstat (limited to 'lbuiltin.c')
-rw-r--r-- | lbuiltin.c | 73 |
1 files changed, 49 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbuiltin.c,v 1.65 1999/10/07 19:04:30 roberto Exp roberto $ | 2 | ** $Id: lbuiltin.c,v 1.66 1999/10/11 16:13:11 roberto Exp roberto $ |
3 | ** Built-in functions | 3 | ** Built-in functions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -44,13 +44,13 @@ static void pushtagstring (TaggedString *s) { | |||
44 | 44 | ||
45 | static real getsize (const Hash *h) { | 45 | static real getsize (const Hash *h) { |
46 | real max = 0; | 46 | real max = 0; |
47 | int i = nhash(h); | 47 | int i = h->size; |
48 | Node *n = h->node; | 48 | Node *n = h->node; |
49 | while (i--) { | 49 | while (i--) { |
50 | if (ttype(ref(n)) == LUA_T_NUMBER && | 50 | if (ttype(key(n)) == LUA_T_NUMBER && |
51 | ttype(val(n)) != LUA_T_NIL && | 51 | ttype(val(n)) != LUA_T_NIL && |
52 | nvalue(ref(n)) > max) | 52 | nvalue(key(n)) > max) |
53 | max = nvalue(ref(n)); | 53 | max = nvalue(key(n)); |
54 | n++; | 54 | n++; |
55 | } | 55 | } |
56 | return max; | 56 | return max; |
@@ -59,7 +59,7 @@ static real getsize (const Hash *h) { | |||
59 | 59 | ||
60 | static real getnarg (const Hash *a) { | 60 | static real getnarg (const Hash *a) { |
61 | TObject index; | 61 | TObject index; |
62 | TObject *value; | 62 | const TObject *value; |
63 | /* value = table.n */ | 63 | /* value = table.n */ |
64 | ttype(&index) = LUA_T_STRING; | 64 | ttype(&index) = LUA_T_STRING; |
65 | tsvalue(&index) = luaS_new("n"); | 65 | tsvalue(&index) = luaS_new("n"); |
@@ -337,7 +337,13 @@ static void luaB_nextvar (void) { | |||
337 | static void luaB_next (void) { | 337 | static void luaB_next (void) { |
338 | const Hash *a = gethash(1); | 338 | const Hash *a = gethash(1); |
339 | const TObject *k = luaA_Address(luaL_nonnullarg(2)); | 339 | const TObject *k = luaA_Address(luaL_nonnullarg(2)); |
340 | int i = (ttype(k) == LUA_T_NIL) ? 0 : luaH_pos(a, k)+1; | 340 | int i; /* will get first element after `i' */ |
341 | if (ttype(k) == LUA_T_NIL) | ||
342 | i = 0; /* get first */ | ||
343 | else { | ||
344 | i = luaH_pos(a, k)+1; | ||
345 | luaL_arg_check(i != 0, 2, "key not found"); | ||
346 | } | ||
341 | if (luaA_next(a, i) == 0) | 347 | if (luaA_next(a, i) == 0) |
342 | lua_pushnil(); | 348 | lua_pushnil(); |
343 | } | 349 | } |
@@ -408,7 +414,7 @@ static void luaB_foreachi (void) { | |||
408 | stack may be reallocated by the call. Moreover, some C compilers do not | 414 | stack may be reallocated by the call. Moreover, some C compilers do not |
409 | initialize structs, so we must do the assignment after the declaration */ | 415 | initialize structs, so we must do the assignment after the declaration */ |
410 | f = *luaA_Address(luaL_functionarg(2)); | 416 | f = *luaA_Address(luaL_functionarg(2)); |
411 | luaD_checkstack(3); /* for f, ref, and val */ | 417 | luaD_checkstack(3); /* for f, key, and val */ |
412 | for (i=1; i<=n; i++) { | 418 | for (i=1; i<=n; i++) { |
413 | *(L->stack.top++) = f; | 419 | *(L->stack.top++) = f; |
414 | ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i; | 420 | ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i; |
@@ -426,12 +432,12 @@ static void luaB_foreach (void) { | |||
426 | int i; | 432 | int i; |
427 | TObject f; /* see comment in 'foreachi' */ | 433 | TObject f; /* see comment in 'foreachi' */ |
428 | f = *luaA_Address(luaL_functionarg(2)); | 434 | f = *luaA_Address(luaL_functionarg(2)); |
429 | luaD_checkstack(3); /* for f, ref, and val */ | 435 | luaD_checkstack(3); /* for f, key, and val */ |
430 | for (i=0; i<a->nhash; i++) { | 436 | for (i=0; i<a->size; i++) { |
431 | const Node *nd = &(a->node[i]); | 437 | const Node *nd = &(a->node[i]); |
432 | if (ttype(val(nd)) != LUA_T_NIL) { | 438 | if (ttype(val(nd)) != LUA_T_NIL) { |
433 | *(L->stack.top++) = f; | 439 | *(L->stack.top++) = f; |
434 | *(L->stack.top++) = *ref(nd); | 440 | *(L->stack.top++) = *key(nd); |
435 | *(L->stack.top++) = *val(nd); | 441 | *(L->stack.top++) = *val(nd); |
436 | luaD_calln(2, 1); | 442 | luaD_calln(2, 1); |
437 | if (ttype(L->stack.top-1) != LUA_T_NIL) | 443 | if (ttype(L->stack.top-1) != LUA_T_NIL) |
@@ -531,36 +537,37 @@ static int sort_comp (lua_Object f, const TObject *a, const TObject *b) { | |||
531 | } | 537 | } |
532 | 538 | ||
533 | static void auxsort (Hash *a, int l, int u, lua_Object f) { | 539 | static void auxsort (Hash *a, int l, int u, lua_Object f) { |
540 | StkId P = L->stack.top - L->stack.stack; /* temporary place for pivot */ | ||
541 | L->stack.top++; | ||
542 | ttype(L->stack.stack+P) = LUA_T_NIL; | ||
534 | while (l < u) { /* for tail recursion */ | 543 | while (l < u) { /* for tail recursion */ |
535 | TObject *P; | ||
536 | int i, j; | 544 | int i, j; |
537 | /* sort elements a[l], a[(l+u)/2] and a[u] */ | 545 | /* sort elements a[l], a[(l+u)/2] and a[u] */ |
538 | if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[l]>a[u]? */ | 546 | if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[u]<a[l]? */ |
539 | swap(a, l, u); | 547 | swap(a, l, u); |
540 | if (u-l == 1) break; /* only 2 elements */ | 548 | if (u-l == 1) break; /* only 2 elements */ |
541 | i = (l+u)/2; | 549 | i = (l+u)/2; |
542 | P = luaH_getint(a, i); | 550 | *(L->stack.stack+P) = *luaH_getint(a, i); /* P = a[i] */ |
543 | if (sort_comp(f, P, luaH_getint(a, l))) /* a[l]>a[i]? */ | 551 | if (sort_comp(f, L->stack.stack+P, luaH_getint(a, l))) /* a[i]<a[l]? */ |
544 | swap(a, l, i); | 552 | swap(a, l, i); |
545 | else if (sort_comp(f, luaH_getint(a, u), P)) /* a[i]>a[u]? */ | 553 | else if (sort_comp(f, luaH_getint(a, u), L->stack.stack+P)) /* a[u]<a[i]? */ |
546 | swap(a, i, u); | 554 | swap(a, i, u); |
547 | if (u-l == 2) break; /* only 3 elements */ | 555 | if (u-l == 2) break; /* only 3 elements */ |
548 | P = L->stack.top++; | 556 | *(L->stack.stack+P) = *luaH_getint(a, i); /* save pivot on stack (for GC) */ |
549 | *P = *luaH_getint(a, i); /* save pivot on stack (for GC) */ | ||
550 | swap(a, i, u-1); /* put median element as pivot (a[u-1]) */ | 557 | swap(a, i, u-1); /* put median element as pivot (a[u-1]) */ |
551 | /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */ | 558 | /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */ |
552 | i = l; j = u-1; | 559 | i = l; j = u-1; |
553 | for (;;) { | 560 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ |
554 | /* invariant: a[l..i] <= P <= a[j..u] */ | 561 | /* repeat i++ until a[i] >= P */ |
555 | while (sort_comp(f, luaH_getint(a, ++i), P)) /* stop when a[i] >= P */ | 562 | while (sort_comp(f, luaH_getint(a, ++i), L->stack.stack+P)) |
556 | if (i>u) lua_error("invalid order function for sorting"); | 563 | if (i>u) lua_error("invalid order function for sorting"); |
557 | while (sort_comp(f, P, luaH_getint(a, --j))) /* stop when a[j] <= P */ | 564 | /* repeat j-- until a[j] <= P */ |
565 | while (sort_comp(f, (L->stack.stack+P), luaH_getint(a, --j))) | ||
558 | if (j<l) lua_error("invalid order function for sorting"); | 566 | if (j<l) lua_error("invalid order function for sorting"); |
559 | if (j<i) break; | 567 | if (j<i) break; |
560 | swap(a, i, j); | 568 | swap(a, i, j); |
561 | } | 569 | } |
562 | swap(a, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | 570 | swap(a, u-1, i); /* swap pivot (a[u-1]) with a[i] */ |
563 | L->stack.top--; /* remove pivot from stack */ | ||
564 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | 571 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ |
565 | /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ | 572 | /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ |
566 | if (i-l < u-i) { | 573 | if (i-l < u-i) { |
@@ -571,6 +578,7 @@ static void auxsort (Hash *a, int l, int u, lua_Object f) { | |||
571 | } | 578 | } |
572 | auxsort(a, j, i, f); /* call recursively the smaller one */ | 579 | auxsort(a, j, i, f); /* call recursively the smaller one */ |
573 | } /* repeat the routine for the larger one */ | 580 | } /* repeat the routine for the larger one */ |
581 | L->stack.top--; /* remove pivot from stack */ | ||
574 | } | 582 | } |
575 | 583 | ||
576 | static void luaB_sort (void) { | 584 | static void luaB_sort (void) { |
@@ -608,7 +616,23 @@ static void mem_query (void) { | |||
608 | 616 | ||
609 | static void hash_query (void) { | 617 | static void hash_query (void) { |
610 | const TObject *o = luaA_Address(luaL_nonnullarg(1)); | 618 | const TObject *o = luaA_Address(luaL_nonnullarg(1)); |
611 | lua_pushnumber(luaH_hashindex(o)); | 619 | luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "string expected"); |
620 | lua_pushnumber(tsvalue(o)->hash); | ||
621 | } | ||
622 | |||
623 | |||
624 | static void table_query (void) { | ||
625 | const Hash *t = avalue(luaA_Address(luaL_tablearg(1))); | ||
626 | int i = luaL_opt_int(2, -1); | ||
627 | if (i == -1) { | ||
628 | lua_pushnumber(t->size); | ||
629 | lua_pushnumber(t->firstfree - t->node); | ||
630 | } | ||
631 | else if (i < t->size) { | ||
632 | luaA_pushobject(&t->node[i].key); | ||
633 | luaA_pushobject(&t->node[i].val); | ||
634 | lua_pushnumber(t->node[i].next == NULL ? 0 : t->node[i].next - t->node); | ||
635 | } | ||
612 | } | 636 | } |
613 | 637 | ||
614 | 638 | ||
@@ -715,6 +739,7 @@ static const struct luaL_reg builtin_funcs[] = { | |||
715 | {"extra", extra_services}, | 739 | {"extra", extra_services}, |
716 | {"hash", hash_query}, | 740 | {"hash", hash_query}, |
717 | {"querystr", query_strings}, | 741 | {"querystr", query_strings}, |
742 | {"querytab", table_query}, | ||
718 | {"testC", testC}, | 743 | {"testC", testC}, |
719 | {"totalmem", mem_query}, | 744 | {"totalmem", mem_query}, |
720 | #endif | 745 | #endif |