Trims characters present in the trim text from both ends of the base text
| 457 | |
| 458 | // Trims characters present in the trim text from both ends of the base text |
| 459 | FORCE_INLINE |
| 460 | const char* btrim_utf8_utf8(gdv_int64 context, const char* basetext, |
| 461 | gdv_int32 basetext_len, const char* trimtext, |
| 462 | gdv_int32 trimtext_len, int32_t* out_len) { |
| 463 | if (basetext_len == 0) { |
| 464 | *out_len = 0; |
| 465 | return ""; |
| 466 | } else if (trimtext_len == 0) { |
| 467 | *out_len = basetext_len; |
| 468 | return basetext; |
| 469 | } |
| 470 | |
| 471 | gdv_int32 start_ptr, end_ptr, char_len, byte_cnt = 1; |
| 472 | // scan the base text from left to right and increment the start and decrement the |
| 473 | // end pointers till there are characters which are not present in the trim text |
| 474 | for (start_ptr = 0; start_ptr < basetext_len; start_ptr += char_len) { |
| 475 | char_len = utf8_char_length(basetext[start_ptr]); |
| 476 | if (char_len == 0 || start_ptr + char_len > basetext_len) { |
| 477 | // invalid byte or incomplete glyph |
| 478 | set_error_for_invalid_utf(context, basetext[start_ptr]); |
| 479 | *out_len = 0; |
| 480 | return ""; |
| 481 | } |
| 482 | if (!is_substr_utf8_utf8(trimtext, trimtext_len, basetext + start_ptr, char_len)) { |
| 483 | break; |
| 484 | } |
| 485 | } |
| 486 | for (end_ptr = basetext_len - 1; end_ptr >= start_ptr; --end_ptr) { |
| 487 | char_len = utf8_char_length(basetext[end_ptr]); |
| 488 | if (char_len == 0) { // trailing byte in multibyte character |
| 489 | ++byte_cnt; |
| 490 | continue; |
| 491 | } |
| 492 | // this is the first byte of a character, hence check if char_len = char_cnt |
| 493 | if (byte_cnt != char_len) { // invalid byte or incomplete glyph |
| 494 | set_error_for_invalid_utf(context, basetext[end_ptr]); |
| 495 | *out_len = 0; |
| 496 | return ""; |
| 497 | } |
| 498 | byte_cnt = 1; // reset the counter*/ |
| 499 | if (!is_substr_utf8_utf8(trimtext, trimtext_len, basetext + end_ptr, char_len)) { |
| 500 | break; |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | // when all characters are trimmed, start_ptr has been incremented to basetext_len and |
| 505 | // end_ptr still points to basetext_len - 1, hence we need to handle this case |
| 506 | if (start_ptr > end_ptr) { |
| 507 | *out_len = 0; |
| 508 | return ""; |
| 509 | } |
| 510 | |
| 511 | end_ptr += utf8_char_length(basetext[end_ptr]); // point to the next character |
| 512 | *out_len = end_ptr - start_ptr; |
| 513 | return basetext + start_ptr; |
| 514 | } |
| 515 | |
| 516 | FORCE_INLINE |