192a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// -*- C++ -*- 2efbe4067f225856814465913bf51e87ec8f17bdbHoward Hinnant//===----------------------- support/win32/support.h ----------------------===// 392a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// 492a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// The LLVM Compiler Infrastructure 592a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// 692a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// This file is dual licensed under the MIT and the University of Illinois Open 792a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// Source Licenses. See LICENSE.TXT for details. 892a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant// 992a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant//===----------------------------------------------------------------------===// 1092a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant 119e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cstdarg> // va_start, va_end 129e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cstddef> // size_t 139e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cstdlib> // malloc 149e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cstdio> // vsprintf, vsnprintf 159e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cstring> // strcpy, wcsncpy 169e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant#include <cwchar> // mbstate_t 176cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant 189e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant// Some of these functions aren't standard or if they conform, the name does not. 199e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant 209e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnantint asprintf(char **sptr, const char *__restrict format, ...) 21efbe4067f225856814465913bf51e87ec8f17bdbHoward Hinnant{ 22efbe4067f225856814465913bf51e87ec8f17bdbHoward Hinnant va_list ap; 239e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant va_start(ap, format); 249e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant int result; 255ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant result = vasprintf(sptr, format, ap); 26efbe4067f225856814465913bf51e87ec8f17bdbHoward Hinnant va_end(ap); 278db4acad3b67808114c495fc21d4db6e7e277087Howard Hinnant return result; 28efbe4067f225856814465913bf51e87ec8f17bdbHoward Hinnant} 29a1985ebbc84c8f8536ce9e2003d43c4aa2603a56Howard Hinnant 305ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// Like sprintf, but when return value >= 0 it returns 315ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// a pointer to a malloc'd string in *sptr. 32a1985ebbc84c8f8536ce9e2003d43c4aa2603a56Howard Hinnant// If return >= 0, use free to delete *sptr. 339e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnantint vasprintf( char **sptr, const char *__restrict format, va_list ap ) 3492a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant{ 356cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant *sptr = NULL; 365ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // Query the count required. 375ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant int count = _vsnprintf( NULL, 0, format, ap ); 385ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant if (count < 0) 395ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant return count; 405ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant size_t buffer_size = static_cast<size_t>(count) + 1; 415ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant char* p = static_cast<char*>(malloc(buffer_size)); 425ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant if ( ! p ) 435ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant return -1; 445ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // If we haven't used exactly what was required, something is wrong. 455ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // Maybe bug in vsnprintf. Report the error and return. 465ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant if (_vsnprintf(p, buffer_size, format, ap) != count) { 475ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant free(p); 485ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant return -1; 4992a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant } 505ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // All good. This is returning memory to the caller not freeing it. 515ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant *sptr = p; 5292a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant return count; 5392a07003b2ce449b22709fbd9b4f1e49b3a2fd3eHoward Hinnant} 546cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant 555ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// Returns >= 0: the number of wide characters found in the 565ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// multi byte sequence src (of src_size_bytes), that fit in the buffer dst 575ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// (of max_dest_chars elements size). The count returned excludes the 585ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// null terminator. When dst is NULL, no characters are copied 595ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// and no "out" parameters are updated. 60cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant// Returns (size_t) -1: an incomplete sequence encountered. 615ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// Leaves *src pointing the next character to convert or NULL 625ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// if a null character was converted from *src. 6378b6828f1420a266e02687685bc2ab993a54eaddHoward Hinnantsize_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src, 64cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t src_size_bytes, size_t max_dest_chars, mbstate_t *__restrict ps ) 656cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant{ 66cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant const size_t terminated_sequence = static_cast<size_t>(0); 67cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant //const size_t invalid_sequence = static_cast<size_t>(-1); 68cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant const size_t incomplete_sequence = static_cast< size_t>(-2); 69cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 70cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t dest_converted = 0; 71cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t source_converted = 0; 72cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t source_remaining = src_size_bytes; 73cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t result = 0; 74cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant bool have_result = false; 75cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 76cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant while ( source_remaining ) { 77cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( dst && dest_converted >= max_dest_chars ) 78cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant break; 79cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // Converts one multi byte character. 80cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // if result > 0, it's the size in bytes of that character. 81cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // othewise if result is zero it indicates the null character has been found. 82cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // otherwise it's an error and errno may be set. 83cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t char_size = mbrtowc( dst ? dst + dest_converted : NULL, *src + source_converted, source_remaining, ps ); 84cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // Don't do anything to change errno from here on. 85cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( char_size > 0 ) { 86cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant source_remaining -= char_size; 87cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant source_converted += char_size; 88cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant ++dest_converted; 89cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant continue; 90cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 91cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant result = char_size; 92cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant have_result = true; 93cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant break; 94cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 95cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( dst ) { 96cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( have_result && result == terminated_sequence ) 97cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant *src = NULL; 98cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant else 99cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant *src += source_converted; 100cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 101cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( have_result && result != terminated_sequence && result != incomplete_sequence ) 102cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant return static_cast<size_t>(-1); 103cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 104cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant return dest_converted; 1056cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant} 106cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 107cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant// Converts max_source_chars from the wide character buffer pointer to by *src, 1085ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// into the multi byte character sequence buffer stored at dst which must be 1095ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// dst_size_bytes bytes in size. 1105ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// Returns >= 0: the number of bytes in the sequence sequence 1115ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// converted frome *src, excluding the null terminator. 112cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant// Returns size_t(-1) if an error occurs, also sets errno. 1135ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// If dst is NULL dst_size_bytes is ignored and no bytes are copied to dst 1145ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant// and no "out" parameters are updated. 11578b6828f1420a266e02687685bc2ab993a54eaddHoward Hinnantsize_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src, 116cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t max_source_chars, size_t dst_size_bytes, mbstate_t *__restrict ps ) 1176cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant{ 118cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant //const size_t invalid_sequence = static_cast<size_t>(-1); 119cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 120cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t source_converted = 0; 121cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t dest_converted = 0; 122cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t dest_remaining = dst_size_bytes; 123cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant size_t char_size = 0; 124cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant const errno_t no_error = ( errno_t) 0; 125cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant errno_t result = ( errno_t ) 0; 126cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant bool have_result = false; 127cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant bool terminator_found = false; 128cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 129cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant while ( source_converted != max_source_chars ) { 130cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( ! dest_remaining ) 131cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant break; 132cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant wchar_t c = (*src)[source_converted]; 133cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( dst ) 134cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps); 135cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant else 1369e98b34a8c03460dacab05068d900dd424e45e53Howard Hinnant result = wcrtomb_s( &char_size, NULL, 0, c, ps); 1375ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // If result is zero there is no error and char_size contains the 1385ec0ff81cecfbc317b2a53894f8bf2da6eb0e8c7Howard Hinnant // size of the multi-byte-sequence converted. 139cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant // Otherwise result indicates an errno type error. 140cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( result == no_error ) { 141cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( c == L'\0' ) { 142cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant terminator_found = true; 143cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant break; 144cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 145cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant ++source_converted; 146cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( dst ) 147cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant dest_remaining -= char_size; 148cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant dest_converted += char_size; 149cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant continue; 150cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 151cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant have_result = true; 152cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant break; 153cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 154cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( dst ) { 155cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( terminator_found ) 156cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant *src = NULL; 157cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant else 158cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant *src = *src + source_converted; 159cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 160cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant if ( have_result && result != no_error ) { 161cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant errno = result; 162cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant return static_cast<size_t>(-1); 163cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant } 164cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant 165cf31d3864e94e52790c7d2db1c85a015de4da8feHoward Hinnant return dest_converted; 1666cd05eeb35636c33a5cd951a7b5501f51611b469Howard Hinnant} 167