2023-07-19 22:54:11 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS ATL
|
|
|
|
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
|
|
|
* PURPOSE: String conversion
|
|
|
|
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ATLCONV_H__
|
|
|
|
#define __ATLCONV_H__
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "atlbase.h"
|
|
|
|
|
|
|
|
namespace ATL
|
|
|
|
{
|
|
|
|
|
|
|
|
// This class does not own the string
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CA2CAEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPCSTR m_psz;
|
|
|
|
|
|
|
|
CA2CAEX(_In_z_ LPCSTR psz) : m_psz(psz) { }
|
|
|
|
|
|
|
|
CA2CAEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage) : m_psz(psz)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(nCodePage);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CA2CAEX() noexcept { } // There is nothing to free here
|
2023-07-19 22:54:11 +00:00
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPCSTR() const noexcept { return m_psz; }
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// CA2CAEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CA2CAEX(_In_ const CA2CAEX&) noexcept = delete;
|
|
|
|
CA2CAEX& operator=(_In_ const CA2CAEX&) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// This class does not own the string
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CW2CWEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPCWSTR m_psz;
|
|
|
|
|
|
|
|
CW2CWEX(_In_z_ LPCWSTR psz) : m_psz(psz) { }
|
|
|
|
|
|
|
|
CW2CWEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage) : m_psz(psz)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(nCodePage);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CW2CWEX() noexcept { } // There is nothing to free here
|
2023-07-19 22:54:11 +00:00
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPCWSTR() const noexcept { return m_psz; }
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// CW2CWEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CW2CWEX(_In_ const CW2CWEX&) noexcept = delete;
|
|
|
|
CW2CWEX& operator=(_In_ const CW2CWEX&) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CA2AEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPSTR m_psz;
|
|
|
|
char m_szBuffer[t_nBufferLength];
|
|
|
|
|
|
|
|
CA2AEX(_In_z_ LPCSTR psz)
|
|
|
|
{
|
|
|
|
Init(psz);
|
|
|
|
}
|
|
|
|
|
|
|
|
CA2AEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(nCodePage);
|
|
|
|
Init(psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CA2AEX() noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
if (m_psz != m_szBuffer)
|
|
|
|
free(m_psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPSTR() const noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
return m_psz;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// CA2AEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CA2AEX(_In_ const CA2AEX &) noexcept = delete;
|
|
|
|
CA2AEX& operator=(_In_ const CA2AEX &) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
void Init(_In_z_ LPCSTR psz)
|
|
|
|
{
|
|
|
|
if (!psz)
|
|
|
|
{
|
|
|
|
m_psz = NULL;
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int cchMax = lstrlenA(psz) + 1;
|
|
|
|
if (cchMax <= t_nBufferLength)
|
|
|
|
{
|
|
|
|
#ifdef _STRSAFE_H_INCLUDED_
|
|
|
|
StringCchCopyA(m_szBuffer, _countof(m_szBuffer), psz);
|
|
|
|
#else
|
|
|
|
lstrcpynA(m_szBuffer, psz, _countof(m_szBuffer));
|
|
|
|
#endif
|
|
|
|
m_psz = m_szBuffer;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
m_psz = _strdup(psz);
|
|
|
|
if (!m_psz)
|
|
|
|
AtlThrow(E_OUTOFMEMORY);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CW2WEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPWSTR m_psz;
|
|
|
|
wchar_t m_szBuffer[t_nBufferLength];
|
|
|
|
|
|
|
|
CW2WEX(_In_z_ LPCWSTR psz)
|
|
|
|
{
|
|
|
|
Init(psz);
|
|
|
|
}
|
|
|
|
|
|
|
|
CW2WEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(nCodePage);
|
|
|
|
Init(psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CW2WEX() noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
if (m_psz != m_szBuffer)
|
|
|
|
free(m_psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPWSTR() const noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
return m_psz;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// CW2WEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CW2WEX(_In_ const CW2WEX&) noexcept = delete;
|
|
|
|
CW2WEX& operator=(_In_ const CW2WEX&) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
void Init(_In_z_ LPCWSTR psz)
|
|
|
|
{
|
|
|
|
if (!psz)
|
|
|
|
{
|
|
|
|
m_psz = NULL;
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int cchMax = lstrlenW(psz);
|
|
|
|
if (cchMax <= t_nBufferLength)
|
|
|
|
{
|
|
|
|
#ifdef _STRSAFE_H_INCLUDED_
|
|
|
|
StringCchCopyW(m_szBuffer, _countof(m_szBuffer), psz);
|
|
|
|
#else
|
|
|
|
lstrcpynW(m_szBuffer, psz, _countof(m_szBuffer));
|
|
|
|
#endif
|
|
|
|
m_psz = m_szBuffer;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
m_psz = _wcsdup(psz);
|
|
|
|
if (!m_psz)
|
|
|
|
AtlThrow(E_OUTOFMEMORY);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CA2WEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPWSTR m_psz;
|
|
|
|
wchar_t m_szBuffer[t_nBufferLength];
|
|
|
|
|
|
|
|
CA2WEX(_In_z_ LPCSTR psz)
|
|
|
|
{
|
|
|
|
Init(psz, CP_ACP);
|
|
|
|
}
|
|
|
|
|
|
|
|
CA2WEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
|
|
|
|
{
|
|
|
|
Init(psz, nCodePage);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CA2WEX() noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
if (m_psz != m_szBuffer)
|
|
|
|
free(m_psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPWSTR() const noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
return m_psz;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// CA2WEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CA2WEX(_In_ const CA2WEX&) noexcept = delete;
|
|
|
|
CA2WEX& operator=(_In_ const CA2WEX&) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
void Init(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
|
|
|
|
{
|
|
|
|
if (!psz)
|
|
|
|
{
|
|
|
|
m_psz = NULL;
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
int cchMax = lstrlenA(psz) + 1; // This is 3 times faster
|
|
|
|
#else
|
|
|
|
int cchMax = MultiByteToWideChar(nCodePage, 0, psz, -1, NULL, 0); // It's slow
|
|
|
|
#endif
|
|
|
|
if (cchMax <= (int)_countof(m_szBuffer))
|
|
|
|
{
|
|
|
|
// Use the static buffer
|
|
|
|
m_psz = m_szBuffer;
|
|
|
|
cchMax = _countof(m_szBuffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Allocate a new buffer
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
m_psz = (LPWSTR)malloc(cchMax * sizeof(WCHAR));
|
|
|
|
if (!m_psz)
|
|
|
|
AtlThrow(E_OUTOFMEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiByteToWideChar(nCodePage, 0, psz, -1, m_psz, cchMax);
|
|
|
|
m_psz[cchMax - 1] = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <int t_nBufferLength = 128>
|
|
|
|
class CW2AEX
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LPSTR m_psz;
|
|
|
|
char m_szBuffer[t_nBufferLength];
|
|
|
|
|
|
|
|
CW2AEX(_In_z_ LPCWSTR psz)
|
|
|
|
{
|
|
|
|
Init(psz, CP_ACP);
|
|
|
|
}
|
|
|
|
|
|
|
|
CW2AEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage)
|
|
|
|
{
|
|
|
|
Init(psz, nCodePage);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
~CW2AEX() noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
if (m_psz != m_szBuffer)
|
|
|
|
free(m_psz);
|
|
|
|
}
|
|
|
|
|
2023-10-16 06:40:17 +00:00
|
|
|
_Ret_z_ operator LPSTR() const noexcept
|
2023-07-19 22:54:11 +00:00
|
|
|
{
|
|
|
|
return m_psz;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// CW2AEX is not copyable
|
2023-10-16 06:40:17 +00:00
|
|
|
CW2AEX(_In_ const CW2AEX&) noexcept = delete;
|
|
|
|
CW2AEX& operator=(_In_ const CW2AEX&) noexcept = delete;
|
2023-07-19 22:54:11 +00:00
|
|
|
|
|
|
|
void Init(_In_z_ LPCWSTR psz, _In_ UINT nConvertCodePage)
|
|
|
|
{
|
|
|
|
if (!psz)
|
|
|
|
{
|
|
|
|
m_psz = NULL;
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: This has a failure.
|
|
|
|
int cchMax = WideCharToMultiByte(nConvertCodePage, 0, psz, -1, NULL, 0, NULL, NULL);
|
|
|
|
if (cchMax <= (int)_countof(m_szBuffer))
|
|
|
|
{
|
|
|
|
// Use the static buffer
|
|
|
|
m_psz = m_szBuffer;
|
|
|
|
cchMax = _countof(m_szBuffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Allocate a new buffer
|
|
|
|
m_szBuffer[0] = 0;
|
|
|
|
m_psz = (LPSTR)malloc(cchMax * sizeof(CHAR));
|
|
|
|
if (!m_psz)
|
|
|
|
AtlThrow(E_OUTOFMEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
WideCharToMultiByte(nConvertCodePage, 0, psz, -1, m_psz, cchMax, NULL, NULL);
|
|
|
|
m_psz[cchMax - 1] = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef CA2AEX<> CA2A;
|
|
|
|
typedef CW2AEX<> CW2A;
|
|
|
|
typedef CA2WEX<> CA2W;
|
|
|
|
typedef CW2WEX<> CW2W;
|
|
|
|
typedef CA2CAEX<> CA2CA;
|
|
|
|
typedef CW2CWEX<> CW2CW;
|
|
|
|
|
|
|
|
#ifdef UNICODE
|
|
|
|
#define CA2CTEX CA2WEX
|
|
|
|
#define CA2TEX CA2WEX
|
|
|
|
#define CT2AEX CW2AEX
|
|
|
|
#define CT2CAEX CW2AEX
|
|
|
|
#define CT2CWEX CW2CWEX
|
|
|
|
#define CT2WEX CW2WEX
|
|
|
|
#define CW2CTEX CW2CWEX
|
|
|
|
#define CW2CTEX CW2CWEX
|
|
|
|
#else
|
|
|
|
#define CA2CTEX CA2CAEX
|
|
|
|
#define CA2TEX CA2AEX
|
|
|
|
#define CT2AEX CA2AEX
|
|
|
|
#define CT2CAEX CA2CAEX
|
|
|
|
#define CT2CWEX CA2WEX
|
|
|
|
#define CT2WEX CA2WEX
|
|
|
|
#define CW2CTEX CW2AEX
|
|
|
|
#define CW2TEX CW2AEX
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace ATL
|
|
|
|
|
|
|
|
#endif // ndef __ATLCONV_H__
|