#include <cstdarg> // va_start, va_end
#include <cstddef> // size_t
#include <cstdlib> // malloc
#include <cstdio> // vsprintf, vsnprintf
#include <cstring> // strcpy, wcsncpy
#include <cwchar> // mbstate_t
int asprintf(char **sptr, const char *__restrict format, ...)
{
va_list ap;
va_start(ap, format);
int result;
result = vasprintf(sptr, format, ap);
va_end(ap);
return result;
}
int 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;
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;
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;
}