| 545 | } |
| 546 | |
| 547 | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( |
| 548 | const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, |
| 549 | utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, |
| 550 | utf8proc_custom_func custom_func, void *custom_data |
| 551 | ) { |
| 552 | /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */ |
| 553 | utf8proc_ssize_t wpos = 0; |
| 554 | if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE)) |
| 555 | return UTF8PROC_ERROR_INVALIDOPTS; |
| 556 | if ((options & UTF8PROC_STRIPMARK) && |
| 557 | !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE)) |
| 558 | return UTF8PROC_ERROR_INVALIDOPTS; |
| 559 | { |
| 560 | utf8proc_int32_t uc; |
| 561 | utf8proc_ssize_t rpos = 0; |
| 562 | utf8proc_ssize_t decomp_result; |
| 563 | int boundclass = UTF8PROC_BOUNDCLASS_START; |
| 564 | while (1) { |
| 565 | if (options & UTF8PROC_NULLTERM) { |
| 566 | rpos += utf8proc_iterate(str + rpos, -1, &uc); |
| 567 | /* checking of return value is not necessary, |
| 568 | as 'uc' is < 0 in case of error */ |
| 569 | if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; |
| 570 | if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW; |
| 571 | if (uc == 0) break; |
| 572 | } else { |
| 573 | if (rpos >= strlen) break; |
| 574 | rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc); |
| 575 | if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; |
| 576 | } |
| 577 | if (custom_func != NULL) { |
| 578 | uc = custom_func(uc, custom_data); /* user-specified custom mapping */ |
| 579 | } |
| 580 | decomp_result = utf8proc_decompose_char( |
| 581 | uc, buffer ? buffer+wpos : buffer, (bufsize > wpos) ? (bufsize - wpos) : 0, options, |
| 582 | &boundclass |
| 583 | ); |
| 584 | if (decomp_result < 0) return decomp_result; |
| 585 | wpos += decomp_result; |
| 586 | /* prohibiting integer overflows due to too long strings: */ |
| 587 | if (wpos < 0 || |
| 588 | wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2)) |
| 589 | return UTF8PROC_ERROR_OVERFLOW; |
| 590 | } |
| 591 | } |
| 592 | if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) { |
| 593 | utf8proc_ssize_t pos = 0; |
| 594 | while (pos < wpos-1) { |
| 595 | utf8proc_int32_t uc1, uc2; |
| 596 | const utf8proc_property_t *property1, *property2; |
| 597 | uc1 = buffer[pos]; |
| 598 | if (uc1 < 0) { |
| 599 | /* skip grapheme break */ |
| 600 | pos++; |
| 601 | continue; |
| 602 | } |
| 603 | uc2 = buffer[pos+1]; |
| 604 | if (uc2 < 0) { |
no test coverage detected