// Copyright (C) Microsoft Corporation. All rights reserved. /*poor man's string routines*/ #include #include #include #include "windows.h" #include "azure_macro_utils/macro_utils.h" #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/string_utils.h" IMPLEMENT_MOCKABLE_FUNCTION(, char*, vsprintf_char, const char*, format, va_list, va) { char* result; int neededSize = vsnprintf(NULL, 0, format, va); if (neededSize < 0) { LogError("failure in vsnprintf"); result = NULL; } else { result = (char*)malloc(((unsigned long long)neededSize + 1) * sizeof(char)); if (result == NULL) { LogError("failure in malloc"); /*return as is*/ } else { if (vsnprintf(result, (unsigned long long)neededSize + 1, format, va) != neededSize) { LogError("inconsistent vsnprintf behavior"); free(result); result = NULL; } } } return result; } IMPLEMENT_MOCKABLE_FUNCTION(, wchar_t*, vsprintf_wchar, const wchar_t*, format, va_list, va) { wchar_t* result; int neededSize = vswprintf(NULL, 0, format, va); if (neededSize < 0) { LogError("failure in swprintf"); result = NULL; } else { result = (wchar_t*)malloc(((unsigned long long)neededSize + 1)*sizeof(wchar_t)); if (result == NULL) { LogError("failure in malloc"); /*return as is*/ } else { if (vswprintf(result, (unsigned long long)neededSize + 1, format, va) != neededSize) { LogError("inconsistent vswprintf behavior"); free(result); result = NULL; } } } return result; } /*returns a char* that is as if printed by printf*/ /*needs to be free'd after usage*/ char* sprintf_char_function(const char* format, ...) { char* result; va_list va; va_start(va, format); result = vsprintf_char(format, va); va_end(va); return result; } wchar_t* sprintf_wchar_function(const wchar_t* format, ...) { wchar_t* result; va_list va; va_start(va, format); result = vsprintf_wchar(format, va); va_end(va); return result; } /*takes a FILETIME, returns a nice string representation of it*/ char* FILETIME_toAsciiArray(const FILETIME* fileTime) { char* result; if (fileTime == NULL) { LogError("invalid argument const FILETIME* fileTime=%p", fileTime); result = NULL; } else { FILETIME localFileTime; if (FileTimeToLocalFileTime(fileTime, &localFileTime) == 0) { LogLastError("failure in FileTimeToLocalFileTime"); result = NULL; } else { SYSTEMTIME systemTime; if (FileTimeToSystemTime(&localFileTime, &systemTime) == 0) { LogLastError("failure in FileTimeToLocalFileTime"); result = NULL; } else { char localDate[255]; if (GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, NULL, localDate, sizeof(localDate)/sizeof(localDate[0])) == 0) { LogLastError("failure in GetDateFormat"); result = NULL; } else { char localTime[255]; if (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime, NULL, localTime, sizeof(localTime)/sizeof(localTime[0])) == 0) { LogLastError("failure in GetTimeFormat"); result = NULL; } else { result = sprintf_char("%s %s", localDate, localTime); /*return as is*/ } } } } } return result; } IMPLEMENT_MOCKABLE_FUNCTION(, wchar_t*, mbs_to_wcs, const char*, source) { wchar_t *result; if (source == NULL) { LogError("invalid argument const char* source=%s", MU_P_OR_NULL(source)); result = NULL; } else { const char* sameAsSource = source; /*assuming source is a multibyte character string*/ mbstate_t state = { 0 };/*initial state!*/ size_t nwc = mbsrtowcs(NULL, &sameAsSource, 0, &state); /*note 350 from C standard seems to indicate that NULL is a valid pointer to pass here*/ if (nwc == (size_t)(-1)) { LogError("failure to get the length of the string %s in multibyte characters", strerror(errno)); result = NULL; } else { result = (wchar_t*)malloc(sizeof(wchar_t)*(nwc+1)); if (result == NULL) { LogError("failure in malloc"); /*return as is*/ } else { size_t nwc2 = mbsrtowcs(result, &sameAsSource, nwc+1, &state); if (nwc2 != nwc) { LogError("unexpected inconsistency in mbsrtowcs"); } else { /*all is fine*/ goto allOk; } free(result); result = NULL; } allOk:; } } return result; } IMPLEMENT_MOCKABLE_FUNCTION(, char*, wcs_to_mbs, const wchar_t*, source) { char *result; if (source == NULL) { LogError("invalid argument const wchar_t* source=%ls", MU_WP_OR_NULL(source)); result = NULL; } else { const wchar_t* sameAsSource = source; mbstate_t state = { 0 };/*initial state!*/ size_t nc = wcsrtombs(NULL, &sameAsSource, 0, &state); if (nc == (size_t)(-1)) { LogError("failure to get the length of the string %s in characters", strerror(errno)); result = NULL; } else { result = (char*)malloc(sizeof(char)*(nc + 1)); if (result == NULL) { LogError("failure in malloc"); /*return as is*/ } else { size_t nc2 = wcsrtombs(result, &sameAsSource, nc + 1, &state); if (nc2 != nc) { LogError("unexpected inconsistency in wcsrtombs"); } else { /*all is fine*/ goto allOk; } free(result); result = NULL; } allOk:; } } return result; }