static void stack_tests(void) { PH_STRING_DECLARE_STACK(stack1, 10); PH_STRING_DECLARE_GROW(stack2, 10, mt_misc); // Expect this to succeed; we silently truncate is(ph_string_append_cstr(&stack1, "12345678901"), PH_OK); // Ensure length is good is(10, ph_string_len(&stack1)); is(ph_string_append_cstr(&stack2, "12345678901234567890"), PH_OK); is(20, ph_string_len(&stack2)); ph_string_delref(&stack2); }
static void error_set(ph_var_err_t *error, const lex_t *lex, const char *msg, ...) { va_list ap; char msg_text[PH_VAR_ERROR_TEXT_LENGTH]; char msg_with_context[PH_VAR_ERROR_TEXT_LENGTH]; int line = -1, col = -1; size_t pos = 0; const char *result = msg_text; uint32_t len; // Don't change it if it is already set if (!error || error->text[0]) { return; } va_start(ap, msg); ph_vsnprintf(msg_text, sizeof(msg_text), msg, ap); va_end(ap); line = lex->stream.line; col = lex->stream.column; pos = lex->stream.position; len = ph_string_len(&lex->saved_text); // If the first byte is NUL, just pretend it has no length, // otherwise we end up with weird error messages if (len && lex->saved_text.buf[0] == 0) { len = 0; } if (len) { if (len <= 20) { ph_snprintf(msg_with_context, sizeof(msg_with_context), "%s near '`Ps%p'", msg_text, (void*)&lex->saved_text); result = msg_with_context; } } else { if (lex->stream.state == STREAM_STATE_ERROR) { /* No context for UTF-8 decoding errors */ result = msg_text; } else { ph_snprintf(msg_with_context, sizeof(msg_with_context), "%s near end of file", msg_text); result = msg_with_context; } } error->line = line; error->column = col; error->position = pos; ph_snprintf(error->text, sizeof(error->text), "%s", result); }
static void lex_unget_unsave(lex_t *lex, int c) { if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) { uint32_t len; len = ph_string_len(&lex->saved_text); assert(len > 0 && lex->saved_text.buf[len-1] == c); lex->saved_text.len--; stream_unget(&lex->stream, c); } }
int main(int argc, char **argv) { ph_string_t *str, *str2; ph_unused_parameter(argc); ph_unused_parameter(argv); ph_library_init(); plan_tests(102); mt_misc = ph_memtype_register(&mt_def); stack_tests(); // Tests reallocation str = ph_string_make_empty(mt_misc, 16); is(ph_string_append_cstr(str, "1234567890"), PH_OK); is(10, ph_string_len(str)); is(ph_string_append_cstr(str, "1234567890"), PH_OK); is(20, ph_string_len(str)); is(memcmp(str->buf, "12345678901234567890", 20), 0); ph_string_delref(str); // Tests reallocation and string formatting str = ph_string_make_empty(mt_misc, 4); is(ph_string_printf(str, "Hello %s", "world"), 11); is(ph_string_len(str), 11); str2 = ph_string_make_empty(mt_misc, 10); is(ph_string_printf(str2, "copy `Ps%p", (void*)str), 16); diag(":%.*s:", str2->len, str2->buf); is(ph_string_len(str2), 16); is(memcmp(str2->buf, "copy Hello world", 16), 0); ph_string_delref(str2); str2 = ph_string_make_empty(mt_misc, 10); is(ph_string_printf(str2, "copy `Ps%d%p", 5, (void*)str), 10); is(memcmp(str2->buf, "copy Hello", 10), 0); ok(!ph_string_equal(str, str2), "not same"); ph_string_delref(str2); str2 = ph_string_make_empty(mt_misc, 10); ph_string_append_buf(str2, str->buf, str->len); ok(ph_string_equal(str, str2), "same"); is(ph_string_compare(str, str2), 0); ph_string_delref(str); ph_string_delref(str2); str = ph_string_make_cstr(mt_misc, "abc"); str2 = ph_string_make_cstr(mt_misc, "bbc"); ok(ph_string_compare(str, str2) < 0, "abc < bbc"); ok(ph_string_compare(str2, str) > 0, "abc < bbc"); ph_string_delref(str2); str2 = ph_string_make_cstr(mt_misc, "abca"); ok(ph_string_compare(str, str2) < 0, "abc < abca"); ok(ph_string_compare(str2, str) > 0, "abc < abca"); ph_string_delref(str2); str2 = ph_string_make_cstr(mt_misc, "ab"); ok(ph_string_compare(str, str2) > 0, "abc > ab"); ok(ph_string_compare(str2, str) < 0, "abc > ab"); ph_string_delref(str2); ph_string_delref(str); str = ph_string_make_printf(mt_misc, 16, "Hello %d", 42); ok(ph_string_equal_cstr(str, "Hello 42"), "same"); ph_string_delref(str); utf16_tests(); string_stream_tests(); return exit_status(); }