Changes to make converting beteween UTF8 and UTF16

This commit is contained in:
Aaron 2015-08-14 10:51:25 -07:00
parent 72ea5abd0b
commit 1a796b5924
2 changed files with 26 additions and 40 deletions

View file

@ -7,10 +7,7 @@
#include <locale.h>
#include <unistd.h>
#include <string>
#include <unicode/utypes.h>
#include <unicode/ucnv.h>
#include <unicode/ustring.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>
#include "getcomputername.h"
//! @brief GetComputerName retrieves the name of the host associated with
@ -51,12 +48,12 @@
//! - ERROR_NO_ASSOCIATION: standard input didn't refer to a terminal
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code
//!
//! @retval 1 If the function succeeds, the return value is a nonzero
//! @retval TRUE If the function succeeds, the return value is a nonzero
//! value, and the variable pointed to by lpnSize contains the number
//! of TCHARs copied to the buffer specified by lpBuffer, including
//! the terminating null character.
//!
//! @retval 0 If the function fails, the return value is zero. To get
//! @retval FALSE If the function fails, the return value is zero. To get
//! extended error information, call GetLastError.
//!
//! [MSDN documentation]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx
@ -64,28 +61,27 @@
//! [LPTSTR]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#LPTSTR
BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize)
{
const std::string utf8 = "UTF-8";
errno = 0;
// Check parameters
if (!lpBuffer || !lpnSize)
{
errno = ERROR_INVALID_PARAMETER;
return 0;
return FALSE;
}
// Select locale from environment
setlocale(LC_ALL, "");
// Check that locale is UTF-8
if (nl_langinfo(CODESET) != utf8)
if (nl_langinfo(CODESET) != std::string("UTF-8"))
{
errno = ERROR_BAD_ENVIRONMENT;
return 0;
return FALSE;
}
// Get computername from system in a thread-safe manner
std::string computername(HOST_NAME_MAX, '\0');
int err = gethostname(&computername[0], computername.size());
std::string computername(HOST_NAME_MAX, 0);
int err = gethostname(&computername[0], computername.length());
// Map errno to Win32 Error Codes
if (err != 0)
{
@ -114,18 +110,13 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize)
default:
errno = ERROR_INVALID_FUNCTION;
}
return 0;
return FALSE;
}
// Convert to char* to WCHAR_T* (UTF-8 to UTF-16 LE w/o BOM)
std::basic_string<char16_t> computername16(HOST_NAME_MAX + 1, 0);
icu::UnicodeString computername8(computername.c_str(), "UTF-8");
int32_t targetSize = computername8.extract(0, computername8.length(),
reinterpret_cast<char*>(&computername16[0]),
(computername16.size()-1)*sizeof(char16_t),
"UTF-16LE");
// Number of characters including null
computername16.resize(targetSize/sizeof(char16_t)+1);
// Convert to UnicodeString
auto computername16 = icu::UnicodeString::fromUTF8(computername.c_str());
// Terminate string with null
computername16.append('\0');
// Size in WCHARs including null
const DWORD size = computername16.length();
@ -137,13 +128,14 @@ BOOL GetComputerNameW(WCHAR_T* lpBuffer, LPDWORD lpnSize)
// Set lpnSize if buffer is too small to inform user
// of necessary size
*lpnSize= size;
return 0;
return FALSE;
}
// Copy bytes from string to buffer
memcpy(lpBuffer, &computername16[0], size*sizeof(char16_t));
// Extract string as UTF-16LE to buffer
computername16.extract(0, size, reinterpret_cast<char*>(lpBuffer), "UTF-16LE");
*lpnSize = size;
return 1;
return TRUE;
}

View file

@ -6,10 +6,7 @@
#include <vector>
#include <unistd.h>
#include <gtest/gtest.h>
#include <unicode/utypes.h>
#include <unicode/ucnv.h>
#include <unicode/ustring.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>
#include "getcomputername.h"
//! Test fixture for GetComputerNameTest
@ -35,7 +32,7 @@ protected:
{
lpnSize = size;
// allocate a DWORD buffer to receive computername
lpBuffer.assign(lpnSize, '\0');
lpBuffer.assign(lpnSize, 0);
result = GetComputerNameW(&lpBuffer[0], &lpnSize);
}
@ -49,18 +46,15 @@ protected:
//! Sets lpnSize to number of WCHARs including null.
ASSERT_EQ(expectedSize, lpnSize);
// setup for conversion from UTF-16LE
// Read lpBuffer into UnicodeString (without null)
const char* begin = reinterpret_cast<char*>(&lpBuffer[0]);
// multiply to get number of bytes
icu::UnicodeString usercomputer16(begin, lpnSize*sizeof(char16_t), "UTF-16LE");
// username16 length includes null and is number of characters
ASSERT_EQ(expectedSize, usercomputer16.length());
icu::UnicodeString computername16(begin, (lpnSize-1)*sizeof(UChar), "UTF-16LE");
ASSERT_EQ(expectedComputerName.length(), computername16.length());
// Convert to UTF-8 for comparison
std::string computername;
computername16.toUTF8String(computername);
// convert (minus null) to UTF-8 for comparison
std::string computername(lpnSize-1, 0);
ASSERT_EQ(expectedComputerName.length(), computername.length());
usercomputer16.extract(0, computername.length(),
reinterpret_cast<char*>(&computername[0]), "UTF-8");
//! Returned computername(after conversion) is what was expected.
EXPECT_EQ(expectedComputerName, computername);