| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <cstdarg> |
| | #include <cstddef> |
| | #include <cstdlib> |
| | #include <cstdio> |
| | #include <cstring> |
| | #include <cwchar> |
| |
|
| |
|
| | |
| | |
| | |
| | int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap ) |
| | { |
| | *sptr = NULL; |
| | |
| | int count = _vsnprintf( NULL, 0, format, ap ); |
| | if (count < 0) |
| | return count; |
| | size_t buffer_size = static_cast<size_t>(count) + 1; |
| | char* p = static_cast<char*>(malloc(buffer_size)); |
| | if ( ! p ) |
| | return -1; |
| | |
| | |
| | if (_vsnprintf(p, buffer_size, format, ap) != count) { |
| | free(p); |
| | return -1; |
| | } |
| | |
| | *sptr = p; |
| | return count; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src, |
| | size_t src_size_bytes, size_t max_dest_chars, mbstate_t *__restrict ps ) |
| | { |
| | const size_t terminated_sequence = static_cast<size_t>(0); |
| | |
| | const size_t incomplete_sequence = static_cast< size_t>(-2); |
| |
|
| | size_t dest_converted = 0; |
| | size_t source_converted = 0; |
| | size_t source_remaining = src_size_bytes; |
| | size_t result = 0; |
| | bool have_result = false; |
| |
|
| | |
| | |
| | if (!dst) |
| | max_dest_chars = static_cast<size_t>(-1); |
| |
|
| | while ( source_remaining ) { |
| | if ( dst && dest_converted >= max_dest_chars ) |
| | break; |
| | |
| | |
| | |
| | |
| | size_t char_size = mbrtowc( dst ? dst + dest_converted : NULL, *src + source_converted, source_remaining, ps ); |
| | |
| | if ( char_size > 0 ) { |
| | source_remaining -= char_size; |
| | source_converted += char_size; |
| | ++dest_converted; |
| | continue; |
| | } |
| | result = char_size; |
| | have_result = true; |
| | break; |
| | } |
| | if ( dst ) { |
| | if ( have_result && result == terminated_sequence ) |
| | *src = NULL; |
| | else |
| | *src += source_converted; |
| | } |
| | if ( have_result && result != terminated_sequence && result != incomplete_sequence ) |
| | return static_cast<size_t>(-1); |
| |
|
| | return dest_converted; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src, |
| | size_t max_source_chars, size_t dst_size_bytes, mbstate_t *__restrict ps ) |
| | { |
| | |
| |
|
| | size_t source_converted = 0; |
| | size_t dest_converted = 0; |
| | size_t dest_remaining = dst_size_bytes; |
| | size_t char_size = 0; |
| | const errno_t no_error = ( errno_t) 0; |
| | errno_t result = ( errno_t ) 0; |
| | bool have_result = false; |
| | bool terminator_found = false; |
| |
|
| | |
| | |
| | if (!dst) |
| | dest_remaining = static_cast<size_t>(-1); |
| |
|
| | while ( source_converted != max_source_chars ) { |
| | if ( ! dest_remaining ) |
| | break; |
| | wchar_t c = (*src)[source_converted]; |
| | if ( dst ) |
| | result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps); |
| | else |
| | result = wcrtomb_s( &char_size, NULL, 0, c, ps); |
| | |
| | |
| | |
| | if ( result == no_error ) { |
| | if ( c == L'\0' ) { |
| | terminator_found = true; |
| | break; |
| | } |
| | ++source_converted; |
| | if ( dst ) |
| | dest_remaining -= char_size; |
| | dest_converted += char_size; |
| | continue; |
| | } |
| | have_result = true; |
| | break; |
| | } |
| | if ( dst ) { |
| | if ( terminator_found ) |
| | *src = NULL; |
| | else |
| | *src = *src + source_converted; |
| | } |
| | if ( have_result && result != no_error ) { |
| | errno = result; |
| | return static_cast<size_t>(-1); |
| | } |
| |
|
| | return dest_converted; |
| | } |
| |
|