@@ -290,41 +290,59 @@ UTF_CONVERT_DEFINITION(16, 32, be, le, , );
290
290
const bool assume_valid = cnc_mcstate_is_assuming_valid (state); \
291
291
if (!assume_valid) { /* if we can't assume it's valid, we must check validating before \
292
292
copying... */ \
293
+ const from_char_t * input = (const from_char_t *)input_bytes; \
293
294
simdutf::result valid_utf = ztd::endian::native == ztd::endian::big \
294
- ? simdutf::validate_utf##N##BIG_SUFFIX##_with_errors ( \
295
- (const from_char_t *)input_bytes, input_size) \
296
- : simdutf::validate_utf##N##LIL_SUFFIX##_with_errors ( \
297
- (const from_char_t *)input_bytes, input_size); \
295
+ ? simdutf::validate_utf##N##BIG_SUFFIX##_with_errors (input, input_size) \
296
+ : simdutf::validate_utf##N##LIL_SUFFIX##_with_errors (input, input_size); \
298
297
/* perform a partial copy of the data, if needed */ \
299
- size_t output_bytes_size = valid_utf.count * sizeof (from_char_t ); \
298
+ const size_t initial_output_bytes_size = valid_utf.count * sizeof (from_char_t ); \
299
+ size_t output_bytes_size = initial_output_bytes_size; \
300
+ size_t available_output_bytes_size = initial_output_bytes_size; \
301
+ if (!is_unbounded_write) { \
302
+ available_output_bytes_size = p_output_bytes_size[0 ]; \
303
+ output_bytes_size \
304
+ = (std::min)(output_bytes_size, available_output_bytes_size); \
305
+ p_output_bytes_size[0 ] -= output_bytes_size; \
306
+ } \
300
307
if (!is_counting_only) { \
301
- if (!is_unbounded_write) { \
302
- output_bytes_size = (std::min)(output_bytes_size, *p_output_bytes_size); \
303
- p_output_bytes_size[0 ] -= output_bytes_size; \
304
- } \
305
308
std::memcpy (p_output_bytes[0 ], input_bytes, output_bytes_size); \
306
309
p_output_bytes[0 ] += output_bytes_size; \
307
310
} \
308
311
p_input_bytes_size[0 ] -= output_bytes_size; \
309
312
p_input_bytes[0 ] += output_bytes_size; \
310
313
if (valid_utf.error != simdutf::error_code::SUCCESS) { \
311
- return valid_utf.error == simdutf::error_code::TOO_SHORT \
312
- ? cnc_mcerr_incomplete_input \
313
- : cnc_mcerr_invalid_sequence; \
314
- } \
315
- else { \
316
- return cnc_mcerr_ok; \
314
+ if constexpr (N == 32 ) { \
315
+ return cnc_mcerr_invalid_sequence; \
316
+ } \
317
+ else if constexpr (N == 16 ) { \
318
+ return valid_utf.error == simdutf::error_code::SURROGATE \
319
+ && (input_size % 2 != 0 ) \
320
+ ? cnc_mcerr_incomplete_input \
321
+ : cnc_mcerr_invalid_sequence; \
322
+ } \
323
+ else { \
324
+ return valid_utf.error == simdutf::error_code::TOO_SHORT \
325
+ ? cnc_mcerr_incomplete_input \
326
+ : cnc_mcerr_invalid_sequence; \
327
+ } \
317
328
} \
329
+ return initial_output_bytes_size > available_output_bytes_size \
330
+ ? cnc_mcerr_insufficient_output \
331
+ : cnc_mcerr_ok; \
318
332
} \
319
- size_t output_bytes_size = input_bytes_size; \
320
- if (!is_unbounded_write) { \
321
- p_output_bytes_size[0 ] -= input_bytes_size; \
322
- } \
323
- if (!is_counting_only) { /* just memcpy the whole damn thing, then */ \
324
- std::memcpy (p_output_bytes[0 ], input_bytes, output_bytes_size); \
325
- p_output_bytes[0 ] += output_bytes_size; \
333
+ else { \
334
+ const size_t output_bytes_size = input_bytes_size; \
335
+ if (!is_unbounded_write) { \
336
+ p_output_bytes_size[0 ] -= input_bytes_size; \
337
+ } \
338
+ if (!is_counting_only) { /* just memcpy the whole damn thing, then */ \
339
+ std::memcpy (p_output_bytes[0 ], input_bytes, output_bytes_size); \
340
+ p_output_bytes[0 ] += output_bytes_size; \
341
+ } \
342
+ p_input_bytes_size[0 ] -= output_bytes_size; \
343
+ p_input_bytes[0 ] += output_bytes_size; \
344
+ return cnc_mcerr_ok; \
326
345
} \
327
- return cnc_mcerr_ok; \
328
346
} \
329
347
static_assert (true , " " )
330
348
0 commit comments