void check(rope *rope, char *expected) { _rope_check(rope); test(rope_byte_count(rope) == strlen(expected)); uint8_t *cstr = rope_createcstr(rope, NULL); test(strcmp((char *)cstr, expected) == 0); free(cstr); }
static void test_random_edits() { // This string should always have the same content as the rope. _string *str = str_create(); rope *r = rope_new(); const size_t max_stringsize = 1000; uint8_t strbuffer[max_stringsize + 1]; for (int i = 0; i < 1000; i++) { // First, some sanity checks. check(r, (char *)str->mem); rope *r2 = rope_copy(r); check(r2, (char *)str->mem); rope_free(r2); // printf("String contains '%s'\n", str->mem); test(rope_byte_count(r) == str->len); size_t len = strlen_utf8(str->mem); test(rope_char_count(r) == len); test(str_num_chars(str) == len); if (len == 0 || rand_float() < 0.5f) { // Insert. //uint8_t *text = random_ascii_string(11); random_unicode_string(strbuffer, 1 + random() % max_stringsize); size_t pos = random() % (len + 1); // printf("inserting %s at %zd\n", strbuffer, pos); rope_insert(r, pos, strbuffer); str_insert(str, pos, strbuffer); } else { // Delete size_t pos = random() % len; size_t dellen = random() % 10; dellen = MIN(len - pos, dellen); // printf("deleting %zd chars at %zd\n", dellen, pos); //deletedText = str[pos...pos + length] //test.strictEqual deletedText, r.substring pos, length rope_del(r, pos, dellen); str_del(str, pos, dellen); } } rope_free(r); str_destroy(str); }
// Copies the rope's contents into a utf8 encoded C string. Also copies a trailing '\0' character. // Returns the number of bytes written, which is rope_byte_count(r) + 1. size_t rope_write_cstr(rope *r, uint8_t *dest) { size_t num_bytes = rope_byte_count(r); dest[num_bytes] = '\0'; if (num_bytes) { uint8_t *p = dest; for (rope_node* restrict n = &r->head; n != NULL; n = n->nexts[0].node) { memcpy(p, n->str, n->num_bytes); p += n->num_bytes; } assert(p == &dest[num_bytes]); } return num_bytes + 1; }
// Create a new C string which contains the rope. The string will contain // the rope encoded as utf-8. uint8_t *rope_createcstr(rope *r, size_t *len) { size_t numbytes = rope_byte_count(r); uint8_t *bytes = (uint8_t *)r->alloc(numbytes + 1); // Room for a zero. bytes[numbytes] = '\0'; if (numbytes == 0) { return bytes; } uint8_t *p = bytes; for (rope_node *n = r->heads[0].node; n != NULL; n = n->nexts[0].node) { memcpy(p, n->str, n->num_bytes); p += n->num_bytes; } assert(p == &bytes[numbytes]); if (len) { *len = numbytes; } return bytes; }
// Create a new C string which contains the rope. The string will contain // the rope encoded as utf8. uint8_t *rope_create_cstr(rope *r) { uint8_t *bytes = (uint8_t *)r->alloc(rope_byte_count(r) + 1); // Room for a zero. rope_write_cstr(r, bytes); return bytes; }