Browse Source

Merge pull request #2184 from svaarala/add-pull-api

Add duk_pull() public API call
pull/2187/head
Sami Vaarala 5 years ago
committed by GitHub
parent
commit
bad57cb2ec
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      RELEASES.rst
  2. 36
      src-input/duk_api_stack.c
  3. 1
      src-input/duktape.h.in
  4. 4
      tests/api/test-all-public-symbols.c
  5. 120
      tests/api/test-insert.c
  6. 190
      tests/api/test-pull.c
  7. 1
      website/api/duk_insert.yaml
  8. 26
      website/api/duk_pull.yaml

2
RELEASES.rst

@ -3550,6 +3550,8 @@ Planned
proposal-global; enable the binding by default; update proposal-global; enable the binding by default; update
polyfills/global.js (GH-2160) polyfills/global.js (GH-2160)
* Add duk_pull() API call (GH-2184)
* Add experimental duk_cbor_encode() and duk_cbor_decode() API calls (GH-2163) * Add experimental duk_cbor_encode() and duk_cbor_decode() API calls (GH-2163)
* Move CBOR extra into an actual Duktape built-in, enabled by default (GH-2163) * Move CBOR extra into an actual Duktape built-in, enabled by default (GH-2163)

36
src-input/duk_api_stack.c

@ -1172,7 +1172,7 @@ DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
* => [ ... | q | p | x | x ] * => [ ... | q | p | x | x ]
*/ */
nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */ nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu", DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
(long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes)); (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
@ -1208,6 +1208,40 @@ DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_id
} }
} }
DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
duk_tval *p;
duk_tval *q;
duk_tval tv_tmp;
duk_size_t nbytes;
DUK_ASSERT_API_ENTRY(thr);
/* nbytes
* <--------->
* [ ... | x | x | p | y | y | q ]
* => [ ... | x | x | y | y | q | p ]
*/
p = duk_require_tval(thr, from_idx);
DUK_ASSERT(p != NULL);
q = duk_require_tval(thr, -1);
DUK_ASSERT(q != NULL);
DUK_ASSERT(q >= p);
nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
(long) from_idx, (void *) p, (void *) q, (unsigned long) nbytes));
/* No net refcount changes. No need to special case nbytes == 0
* (p == q).
*/
DUK_TVAL_SET_TVAL(&tv_tmp, p);
duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
DUK_TVAL_SET_TVAL(q, &tv_tmp);
}
DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) { DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
duk_tval *tv1; duk_tval *tv1;
duk_tval *tv2; duk_tval *tv2;

1
src-input/duktape.h.in

@ -524,6 +524,7 @@ DUK_EXTERNAL_DECL void duk_swap_top(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_idx); DUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_idx);
DUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx); DUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx);
DUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_idx); DUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_idx);
DUK_EXTERNAL_DECL void duk_pull(duk_context *ctx, duk_idx_t from_idx);
DUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_idx); DUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_idx);
DUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx); DUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx);
DUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t idx); DUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t idx);

4
tests/api/test-all-public-symbols.c

@ -23,8 +23,7 @@ static duk_ret_t test_func(duk_context *ctx, void *udata) {
return 0; return 0;
} }
/* Up-to-date for Duktape 1.3.0, alphabetical order: /* $ cd website/api; ls *.yaml
* $ cd website/api; ls *.yaml
*/ */
(void) duk_alloc_raw(ctx, 0); (void) duk_alloc_raw(ctx, 0);
@ -223,6 +222,7 @@ static duk_ret_t test_func(duk_context *ctx, void *udata) {
(void) duk_pop_3(ctx); (void) duk_pop_3(ctx);
(void) duk_pop_n(ctx, 0); (void) duk_pop_n(ctx, 0);
(void) duk_pop(ctx); (void) duk_pop(ctx);
(void) duk_pull(ctx, 0);
(void) duk_push_array(ctx); (void) duk_push_array(ctx);
(void) duk_push_bare_object(ctx); (void) duk_push_bare_object(ctx);
(void) duk_push_boolean(ctx, 0); (void) duk_push_boolean(ctx, 0);

120
tests/api/test-insert.c

@ -4,19 +4,90 @@
1: foo 1: foo
2: 234 2: 234
3: 345 3: 345
final top: 4
==> rc=0, result='undefined' ==> rc=0, result='undefined'
*** test_2 (duk_safe_call) *** test_2 (duk_safe_call)
insert at 3 ok insert at 3 ok
0: 123
1: 234
2: 345
3: foo
insert at -1 ok insert at -1 ok
0: 123
1: 234
2: 345
3: foo
==> rc=1, result='RangeError: invalid stack index 4' ==> rc=1, result='RangeError: invalid stack index 4'
*** test_3 (duk_safe_call) *** test_3 (duk_safe_call)
insert at 0 ok insert at 0 ok
0: foo
1: 123
2: 234
3: 345
insert at -4 ok insert at -4 ok
0: 345
1: foo
2: 123
3: 234
==> rc=1, result='RangeError: invalid stack index -5' ==> rc=1, result='RangeError: invalid stack index -5'
*** test_4 (duk_safe_call) *** test_4 (duk_safe_call)
==> rc=1, result='RangeError: invalid stack index -2147483648' ==> rc=1, result='RangeError: invalid stack index -2147483648'
*** test_5 (duk_safe_call)
0: val-0
1: val-1
2: val-2
3: val-3
4: val-4
5: val-5
6: val-6
7: val-7
8: val-8
9: val-9
0: val-9
1: val-0
2: val-1
3: val-2
4: val-3
5: val-4
6: val-5
7: val-6
8: val-7
9: val-8
0: val-9
1: val-0
2: val-1
3: val-8
4: val-2
5: val-3
6: val-4
7: val-5
8: val-6
9: val-7
0: val-9
1: val-0
2: val-1
3: val-8
4: val-2
5: val-3
6: val-7
7: val-4
8: val-5
9: val-6
final top: 10
==> rc=0, result='undefined'
*** test_6 (duk_safe_call)
==> rc=1, result='RangeError: invalid stack index 0'
===*/ ===*/
static void dump_stack(duk_context *ctx) {
duk_idx_t i, n;
n = duk_get_top(ctx);
for (i = 0; i < n; i++) {
printf("%ld: %s\n", (long) i, duk_to_string(ctx, i));
}
}
static void prep(duk_context *ctx) { static void prep(duk_context *ctx) {
duk_set_top(ctx, 0); duk_set_top(ctx, 0);
duk_push_int(ctx, 123); duk_push_int(ctx, 123);
@ -26,17 +97,14 @@ static void prep(duk_context *ctx) {
} }
static duk_ret_t test_1(duk_context *ctx, void *udata) { static duk_ret_t test_1(duk_context *ctx, void *udata) {
duk_idx_t i, n;
(void) udata; (void) udata;
prep(ctx); prep(ctx);
duk_insert(ctx, -3); /* -> [ 123 "foo" 234 345 ] */ duk_insert(ctx, -3); /* -> [ 123 "foo" 234 345 ] */
n = duk_get_top(ctx); dump_stack(ctx);
for (i = 0; i < n; i++) {
printf("%ld: %s\n", (long) i, duk_to_string(ctx, i)); printf("final top: %ld\n", (long) duk_get_top(ctx));
}
return 0; return 0;
} }
@ -46,10 +114,13 @@ static duk_ret_t test_2(duk_context *ctx, void *udata) {
prep(ctx); prep(ctx);
duk_insert(ctx, 3); /* -> [ 123 234 345 "foo" ] (legal, keep top) */ duk_insert(ctx, 3); /* -> [ 123 234 345 "foo" ] (legal, keep top) */
printf("insert at 3 ok\n"); printf("insert at 3 ok\n");
dump_stack(ctx);
duk_insert(ctx, -1); /* -> [ 123 234 345 "foo" ] (legal, keep top) */ duk_insert(ctx, -1); /* -> [ 123 234 345 "foo" ] (legal, keep top) */
printf("insert at -1 ok\n"); printf("insert at -1 ok\n");
dump_stack(ctx);
duk_insert(ctx, 4); /* (illegal: index too high) */ duk_insert(ctx, 4); /* (illegal: index too high) */
printf("insert at 4 ok\n"); printf("insert at 4 ok\n");
dump_stack(ctx);
return 0; return 0;
} }
@ -59,10 +130,13 @@ static duk_ret_t test_3(duk_context *ctx, void *udata) {
prep(ctx); prep(ctx);
duk_insert(ctx, 0); /* -> [ "foo" 123 234 345 ] (legal) */ duk_insert(ctx, 0); /* -> [ "foo" 123 234 345 ] (legal) */
printf("insert at 0 ok\n"); printf("insert at 0 ok\n");
dump_stack(ctx);
duk_insert(ctx, -4); /* -> [ 345 "foo" 123 234 ] (legal) */ duk_insert(ctx, -4); /* -> [ 345 "foo" 123 234 ] (legal) */
printf("insert at -4 ok\n"); printf("insert at -4 ok\n");
dump_stack(ctx);
duk_insert(ctx, -5); /* (illegal: index too low) */ duk_insert(ctx, -5); /* (illegal: index too low) */
printf("insert at -5 ok\n"); printf("insert at -5 ok\n");
dump_stack(ctx);
return 0; return 0;
} }
@ -72,6 +146,38 @@ static duk_ret_t test_4(duk_context *ctx, void *udata) {
prep(ctx); prep(ctx);
duk_insert(ctx, DUK_INVALID_INDEX); /* (illegal: invalid index) */ duk_insert(ctx, DUK_INVALID_INDEX); /* (illegal: invalid index) */
printf("insert at DUK_INVALID_INDEX ok\n"); printf("insert at DUK_INVALID_INDEX ok\n");
dump_stack(ctx);
return 0;
}
static duk_ret_t test_5(duk_context *ctx, void *udata) {
duk_idx_t i;
(void) udata;
for (i = 0; i < 10; i++) {
duk_push_sprintf(ctx, "val-%d", (int) i);
}
dump_stack(ctx);
duk_insert(ctx, 0);
dump_stack(ctx);
duk_insert(ctx, 3);
dump_stack(ctx);
duk_insert(ctx, -4);
dump_stack(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_6(duk_context *ctx, void *udata) {
(void) udata;
duk_set_top(ctx, 0);
duk_insert(ctx, 0);
printf("insert on empty stack\n");
dump_stack(ctx);
return 0; return 0;
} }
@ -80,4 +186,6 @@ void test(duk_context *ctx) {
TEST_SAFE_CALL(test_2); TEST_SAFE_CALL(test_2);
TEST_SAFE_CALL(test_3); TEST_SAFE_CALL(test_3);
TEST_SAFE_CALL(test_4); TEST_SAFE_CALL(test_4);
TEST_SAFE_CALL(test_5);
TEST_SAFE_CALL(test_6);
} }

190
tests/api/test-pull.c

@ -0,0 +1,190 @@
/*===
*** test_1 (duk_safe_call)
0: 123
1: 345
2: foo
3: 234
final top: 4
==> rc=0, result='undefined'
*** test_2 (duk_safe_call)
pull at 3 ok
0: 123
1: 234
2: 345
3: foo
pull at -1 ok
0: 123
1: 234
2: 345
3: foo
==> rc=1, result='RangeError: invalid stack index 4'
*** test_3 (duk_safe_call)
pull at 0 ok
0: 234
1: 345
2: foo
3: 123
pull at -4 ok
0: 345
1: foo
2: 123
3: 234
==> rc=1, result='RangeError: invalid stack index -5'
*** test_4 (duk_safe_call)
==> rc=1, result='RangeError: invalid stack index -2147483648'
*** test_5 (duk_safe_call)
0: val-0
1: val-1
2: val-2
3: val-3
4: val-4
5: val-5
6: val-6
7: val-7
8: val-8
9: val-9
0: val-1
1: val-2
2: val-3
3: val-4
4: val-5
5: val-6
6: val-7
7: val-8
8: val-9
9: val-0
0: val-1
1: val-2
2: val-3
3: val-5
4: val-6
5: val-7
6: val-8
7: val-9
8: val-0
9: val-4
0: val-1
1: val-2
2: val-3
3: val-5
4: val-6
5: val-7
6: val-9
7: val-0
8: val-4
9: val-8
final top: 10
==> rc=0, result='undefined'
*** test_6 (duk_safe_call)
==> rc=1, result='RangeError: invalid stack index 0'
===*/
static void prep(duk_context *ctx) {
duk_set_top(ctx, 0);
duk_push_int(ctx, 123);
duk_push_int(ctx, 234);
duk_push_int(ctx, 345); /* -> [ 123 234 345 ] */
duk_push_string(ctx, "foo"); /* -> [ 123 234 345 "foo" ] */
}
static void dump_stack(duk_context *ctx) {
duk_idx_t i, n;
n = duk_get_top(ctx);
for (i = 0; i < n; i++) {
printf("%ld: %s\n", (long) i, duk_to_string(ctx, i));
}
}
static duk_ret_t test_1(duk_context *ctx, void *udata) {
(void) udata;
prep(ctx);
duk_pull(ctx, -3); /* -> [ 123 345 "foo" 234 ] */
dump_stack(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_2(duk_context *ctx, void *udata) {
(void) udata;
prep(ctx);
duk_pull(ctx, 3); /* -> [ 123 234 345 "foo" ] (legal, keep top) */
printf("pull at 3 ok\n");
dump_stack(ctx);
duk_pull(ctx, -1); /* -> [ 123 234 345 "foo" ] (legal, keep top) */
printf("pull at -1 ok\n");
dump_stack(ctx);
duk_pull(ctx, 4); /* (illegal: index too high) */
printf("pull at 4 ok\n");
dump_stack(ctx);
return 0;
}
static duk_ret_t test_3(duk_context *ctx, void *udata) {
(void) udata;
prep(ctx);
duk_pull(ctx, 0); /* -> [ 234 345 "foo" 123 ] (legal) */
printf("pull at 0 ok\n");
dump_stack(ctx);
duk_pull(ctx, -4); /* -> [ 345 "foo" 123 234 ] (legal) */
printf("pull at -4 ok\n");
dump_stack(ctx);
duk_pull(ctx, -5); /* (illegal: index too low) */
printf("pull at -5 ok\n");
dump_stack(ctx);
return 0;
}
static duk_ret_t test_4(duk_context *ctx, void *udata) {
(void) udata;
prep(ctx);
duk_pull(ctx, DUK_INVALID_INDEX); /* (illegal: invalid index) */
printf("pull at DUK_INVALID_INDEX ok\n");
dump_stack(ctx);
return 0;
}
static duk_ret_t test_5(duk_context *ctx, void *udata) {
duk_idx_t i;
(void) udata;
for (i = 0; i < 10; i++) {
duk_push_sprintf(ctx, "val-%d", (int) i);
}
dump_stack(ctx);
duk_pull(ctx, 0);
dump_stack(ctx);
duk_pull(ctx, 3);
dump_stack(ctx);
duk_pull(ctx, -4);
dump_stack(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_6(duk_context *ctx, void *udata) {
(void) udata;
duk_set_top(ctx, 0);
duk_pull(ctx, 0);
printf("pull on empty stack\n");
dump_stack(ctx);
return 0;
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_1);
TEST_SAFE_CALL(test_2);
TEST_SAFE_CALL(test_3);
TEST_SAFE_CALL(test_4);
TEST_SAFE_CALL(test_5);
TEST_SAFE_CALL(test_6);
}

1
website/api/duk_insert.yaml

@ -28,6 +28,7 @@ tags:
- stack - stack
seealso: seealso:
- duk_pull
- duk_replace - duk_replace
introduced: 1.0.0 introduced: 1.0.0

26
website/api/duk_pull.yaml

@ -0,0 +1,26 @@
name: duk_pull
proto: |
void duk_pull(duk_context *ctx, duk_idx_t from_idx);
stack: |
[ ... val! ... ] -> [ ... val! ]
summary: |
<p>Remove value at <code>from_idx</code> and push it on the value stack top.</p>
If <code>from_idx</code> is an invalid index, throws an error.</p>
example: |
duk_push_int(ctx, 123);
duk_push_int(ctx, 234);
duk_push_int(ctx, 345); /* -> [ 123 234 345 ] */
duk_pull(ctx, -2); /* [ 123 234 345 ] -> [ 123 345 234 ] */
tags:
- stack
seealso:
- duk_insert
- duk_remove
introduced: 2.5.0
Loading…
Cancel
Save