/* Copies an UTF-16 stream from an UTF-8 string * Returns 1 if successful or -1 on error */ int libuna_utf16_stream_copy_from_utf8( uint8_t *utf16_stream, size_t utf16_stream_size, int byte_order, const libuna_utf8_character_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libuna_utf16_stream_copy_from_utf8"; size_t utf16_stream_index = 0; size_t utf8_string_index = 0; libuna_unicode_character_t unicode_character = 0; if( utf16_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 stream.", function ); return( -1 ); } if( utf16_stream_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 stream size value exceeds maximum.", function ); return( -1 ); } if( ( byte_order != LIBUNA_ENDIAN_BIG ) && ( byte_order != LIBUNA_ENDIAN_LITTLE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported byte order.", function ); return( -1 ); } if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-8 string size value exceeds maximum.", function ); return( -1 ); } if( libuna_utf16_stream_copy_byte_order_mark( utf16_stream, utf16_stream_size, &utf16_stream_index, byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED, "%s: unable to copy UTF-16 byte order mark.", function ); return( -1 ); } while( utf8_string_index < utf8_string_size ) { /* Convert the UTF-8 string bytes into a Unicode character */ if( libuna_unicode_character_copy_from_utf8( &unicode_character, utf8_string, utf8_string_size, &utf8_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from UTF-8 string.", function ); return( -1 ); } /* Convert the Unicode character into UTF-16 stream bytes */ if( libuna_unicode_character_copy_to_utf16_stream( unicode_character, utf16_stream, utf16_stream_size, &utf16_stream_index, byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED, "%s: unable to copy Unicode character to UTF-16 stream.", function ); return( -1 ); } } return( 1 ); }
/* Copies an UTF-16 stream from an UTF-16 string * Returns 1 if successful or -1 on error */ int libuna_utf16_stream_copy_from_utf16( uint8_t *utf16_stream, size_t utf16_stream_size, int byte_order, const libuna_utf16_character_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libuna_utf16_stream_copy_from_utf16"; size_t utf16_stream_index = 0; size_t utf16_string_index = 0; libuna_utf16_character_t utf16_character = 0; if( utf16_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 stream.", function ); return( -1 ); } if( utf16_stream_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 stream size value exceeds maximum.", function ); return( -1 ); } if( ( byte_order != LIBUNA_ENDIAN_BIG ) && ( byte_order != LIBUNA_ENDIAN_LITTLE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported byte order.", function ); return( -1 ); } if( utf16_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string.", function ); return( -1 ); } if( utf16_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 string size value exceeds maximum.", function ); return( -1 ); } if( libuna_utf16_stream_copy_byte_order_mark( utf16_stream, utf16_stream_size, &utf16_stream_index, byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED, "%s: unable to copy UTF-16 byte order mark.", function ); return( -1 ); } /* Assumes the UTF-16 string is santized */ while( utf16_string_index < utf16_string_size ) { if( ( utf16_stream_index + 2 ) >= utf16_stream_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: UTF-16 stream too small.", function ); return( -1 ); } utf16_character = utf16_string[ utf16_string_index++ ]; if( byte_order == LIBUNA_ENDIAN_BIG ) { utf16_stream[ utf16_stream_index + 1 ] = (uint8_t) ( utf16_character & 0xff ); utf16_character >>= 8; utf16_stream[ utf16_stream_index ] = (uint8_t) ( utf16_character & 0xff ); } else if( byte_order == LIBUNA_ENDIAN_LITTLE )
/* Tests the libuna_utf16_stream_copy_byte_order_mark function * Returns 1 if successful or 0 if not */ int una_test_utf16_stream_copy_byte_order_mark( void ) { uint8_t utf16_stream[ 16 ]; libuna_error_t *error = NULL; size_t utf16_stream_index = 0; int result = 0; /* Test regular cases */ utf16_stream_index = 0; result = libuna_utf16_stream_copy_byte_order_mark( utf16_stream, 16, &utf16_stream_index, LIBUNA_ENDIAN_BIG, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); UNA_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( una_test_utf16_stream_byte_order_mark_big_endian, utf16_stream, sizeof( uint8_t ) * 2 ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); utf16_stream_index = 0; result = libuna_utf16_stream_copy_byte_order_mark( utf16_stream, 16, &utf16_stream_index, LIBUNA_ENDIAN_LITTLE, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); UNA_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( una_test_utf16_stream_byte_order_mark_little_endian, utf16_stream, sizeof( uint8_t ) * 2 ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Test error cases */ utf16_stream_index = 0; result = libuna_utf16_stream_copy_byte_order_mark( NULL, 16, &utf16_stream_index, LIBUNA_ENDIAN_LITTLE, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); UNA_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libuna_utf16_stream_copy_byte_order_mark( utf16_stream, (size_t) SSIZE_MAX + 1, &utf16_stream_index, LIBUNA_ENDIAN_LITTLE, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); UNA_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libuna_utf16_stream_copy_byte_order_mark( utf16_stream, 16, NULL, LIBUNA_ENDIAN_LITTLE, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); UNA_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libuna_utf16_stream_copy_byte_order_mark( utf16_stream, 16, &utf16_stream_index, -1, &error ); UNA_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); UNA_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); }