From 94671533998b554cf16190424ea19c7c51c9f5b8 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 Aug 2013 13:45:10 +0300 Subject: [PATCH] api doc and test for duk_substring --- api-testcases/test-substring.c | 124 +++++++++++++++++++++++++++++++++ website/api/duk_substring.txt | 34 +++++++++ 2 files changed, 158 insertions(+) create mode 100644 api-testcases/test-substring.c create mode 100644 website/api/duk_substring.txt diff --git a/api-testcases/test-substring.c b/api-testcases/test-substring.c new file mode 100644 index 00000000..271c473e --- /dev/null +++ b/api-testcases/test-substring.c @@ -0,0 +1,124 @@ +/*=== +*** test_1 +blen=5, clen=3, str="o\xe1\x88\xb4a" +blen=6, clen=4, str="o\xe1\x88\xb4ar" +blen=0, clen=0, str="" +blen=0, clen=0, str="" +final top: 1 +rc=0, result=undefined +*** test_2 +rc=1, result=TypeError: incorrect type, expected tag 5 +*** test_3 +rc=1, result=Error: invalid index: -2 +*** test_4 +rc=1, result=Error: invalid index: -2147483648 +===*/ + +void dump_string(duk_context *ctx) { + const char *buf; + size_t i, len; + + buf = duk_get_lstring(ctx, -1, &len); + printf("blen=%d, clen=%d, str=\"", (int) len, (int) duk_get_length(ctx, -1)); + for (i = 0; i < len; i++) { + char c = buf[i]; + if (c >= 0x20 && c <= 0x7e) { + printf("%c", c); + } else { + printf("\\x%02x", ((int) c) & 0xff); + } + } + printf("\"\n"); + + duk_pop(ctx); +} + +int test_1(duk_context *ctx) { + /* + * Test with a string containing non-ASCII to ensure indices are + * treated correctly as char indices. + * + * >>> u'foo\u1234ar'.encode('utf-8').encode('hex') + * '666f6fe188b46172' + */ + const char *teststr = "666f6fe188b46172"; + + duk_set_top(ctx, 0); + + duk_push_string(ctx, (const char *) teststr); + duk_hex_decode(ctx, -1); + duk_to_string(ctx, -1); + + /* basic case */ + duk_dup_top(ctx); + duk_substring(ctx, -1, 2, 5); + dump_string(ctx); + + /* end is clamped */ + duk_dup_top(ctx); + duk_substring(ctx, -1, 2, 8); + dump_string(ctx); + + /* start and end are clamped */ + duk_dup_top(ctx); + duk_substring(ctx, -1, 10, 20); + dump_string(ctx); + + /* start > end */ + duk_dup_top(ctx); + duk_substring(ctx, -1, 4, 2); + dump_string(ctx); + + printf("final top: %d\n", duk_get_top(ctx)); + return 0; +} + +/* non-string -> error */ +int test_2(duk_context *ctx) { + duk_set_top(ctx, 0); + + duk_push_int(ctx, 123456); + duk_substring(ctx, -1, 2, 4); + + printf("final top: %d\n", duk_get_top(ctx)); + return 0; +} + +/* invalid index */ +int test_3(duk_context *ctx) { + duk_set_top(ctx, 0); + + duk_push_string(ctx, "foobar"); + duk_substring(ctx, -2, 2, 4); + + printf("final top: %d\n", duk_get_top(ctx)); + return 0; +} + +/* invalid index */ +int test_4(duk_context *ctx) { + duk_set_top(ctx, 0); + + duk_push_string(ctx, "foobar"); + duk_substring(ctx, DUK_INVALID_INDEX, 2, 4); + + printf("final top: %d\n", duk_get_top(ctx)); + return 0; +} + +#define TEST(func) do { \ + printf("*** %s\n", #func); \ + rc = duk_safe_call(ctx, (func), 0, 1, DUK_INVALID_INDEX); \ + printf("rc=%d, result=%s\n", rc, duk_to_string(ctx, -1)); \ + duk_pop(ctx); \ + } while (0) + +void test(duk_context *ctx) { + int rc; + + TEST(test_1); + TEST(test_2); + TEST(test_3); + TEST(test_4); /* FIXME: exposes value of DUK_INVALID_INDEX */ +} + diff --git a/website/api/duk_substring.txt b/website/api/duk_substring.txt new file mode 100644 index 00000000..54f2c723 --- /dev/null +++ b/website/api/duk_substring.txt @@ -0,0 +1,34 @@ +=proto +void duk_substring(duk_context *ctx, int index, size_t start_offset, size_t end_offset); + +=stack +[ ... str! ... ] -> [ ... substr! ... ] + +=summary +

Replace a string at index with a substring [start_offset, +end_offset[ of the string itself. If the value at index is +not a string or the index is invalid, throws an error.

+ +

The substring operation works with characters, not bytes, and the offsets +are character offsets. The semantics of this call are similar to +String.prototype.substring (start, end). +Offset values are clamped to string length (there is no need to clamp negative +values because size_t is unsigned) and if start offset is larger than +end offset, the result is an empty string.

+ +
+To get a byte-oriented substring, use +duk_get_lstring() to get a string data +pointer and length, and +duk_push_lstring() to push a slice of +bytes. +
+ +=example +/* String at index -3 is 'foobar'. Substring [2,5[ is "oba". */ + +duk_substring(ctx, -3, 2, 5); +printf("substring: %s\n", duk_get_string(ctx, -3)); + +=fixme +Return const char *?