convert_utf8_to_ucs2: Allow partial conversion

Fixes #3638.
This commit is contained in:
Orestis Floros 2019-03-08 19:16:39 +02:00
parent 6ec7b91cff
commit bd58d67ea8
No known key found for this signature in database
GPG Key ID: E9AD9F32E401E38F
1 changed files with 20 additions and 11 deletions

View File

@ -69,32 +69,41 @@ xcb_char2b_t *convert_utf8_to_ucs2(char *input, size_t *real_strlen) {
xcb_char2b_t *buffer = smalloc(buffer_size); xcb_char2b_t *buffer = smalloc(buffer_size);
/* We need to use an additional pointer, because iconv() modifies it */ /* We need to use an additional pointer, because iconv() modifies it */
size_t output_size = buffer_size; size_t output_bytes_left = buffer_size;
xcb_char2b_t *output = buffer; xcb_char2b_t *output = buffer;
if (ucs2_conversion_descriptor == (iconv_t)-1) { if (ucs2_conversion_descriptor == (iconv_t)-1) {
/* Get a new conversion descriptor */ /* Get a new conversion descriptor. //IGNORE is a GNU suffix that makes
* iconv to silently discard characters that cannot be represented in
* the target character set. */
ucs2_conversion_descriptor = iconv_open("UCS-2BE//IGNORE", "UTF-8");
if (ucs2_conversion_descriptor == (iconv_t)-1) {
ucs2_conversion_descriptor = iconv_open("UCS-2BE", "UTF-8"); ucs2_conversion_descriptor = iconv_open("UCS-2BE", "UTF-8");
if (ucs2_conversion_descriptor == (iconv_t)-1) }
if (ucs2_conversion_descriptor == (iconv_t)-1) {
err(EXIT_FAILURE, "Error opening the conversion context"); err(EXIT_FAILURE, "Error opening the conversion context");
}
} else { } else {
/* Reset the existing conversion descriptor */ /* Reset the existing conversion descriptor */
iconv(ucs2_conversion_descriptor, NULL, NULL, NULL, NULL); iconv(ucs2_conversion_descriptor, NULL, NULL, NULL, NULL);
} }
/* Do the conversion */ /* Do the conversion */
size_t rc = iconv(ucs2_conversion_descriptor, &input, &input_size, (char **)&output, &output_size); size_t rc = iconv(ucs2_conversion_descriptor, &input, &input_size,
(char **)&output, &output_bytes_left);
if (rc == (size_t)-1) { if (rc == (size_t)-1) {
/* Conversion will only be partial. */
perror("Converting to UCS-2 failed"); perror("Converting to UCS-2 failed");
free(buffer);
if (real_strlen != NULL)
*real_strlen = 0;
return NULL;
} }
/* If no bytes where converted, this is equivalent to freeing buffer. */
buffer_size -= output_bytes_left;
buffer = srealloc(buffer, buffer_size);
/* Return the resulting string's length */ /* Return the resulting string's length */
if (real_strlen != NULL) if (real_strlen != NULL) {
*real_strlen = (buffer_size - output_size) / sizeof(xcb_char2b_t); *real_strlen = buffer_size / sizeof(xcb_char2b_t);
}
return buffer; return buffer;
} }