Implementing mbsnrtowcs in terms of mbsrtowcs
In an almost complete effort to port libc++ to Windows, I need the function mbsnrtowcs
, and thought that the easiest way would be to implement it in terms of mbsrtowcs
:
size_t mbsnrtowcs( wchar_t *__restrict__ dst, const char **__restrict__ src,
size_t nmc, size_t len, mbstate_t *__restrict__ ps )
{
char* nmcsrc = new char[nmc+1];
strncpy( nmcsrc, *src, nmc );
nmcsrc[nmc] = '\0';
const size_t result = mbsrtowcs( dst, &nmcsrc, len, ps );
delete[] nmcsrc;
return result;
}
The problem here is that mbsrtowcs
needs &nmcsrc
to be of type const char**
, which is isn't, because it is a string I just copied the first nmc
elements into, and appended a \0
character to. How can I work around this? Strictly speaking, this is compiled as C++, so perhaps a const_cast
would do little harm here? I also have access to c++0X (libc++ is/requires a subset c++0x).
Edit: the Clang error message reads:
M:\Development\Source\libc++\src\support\win32\support.cpp:37:27: error: no matching function for call to 'mbsrtowcs'
const size_t result = mbsrtowcs( dst, &nmcsrc, len, ps );
^~~~~~~~~
M:/Development/mingw64/bin/../lib/clang/3.0/../../../x86_64-w64-mingw32/include\wchar.h:732:18: note: candidate function not viable: no known conversion from 'char **' to 'const char **restrict' for 2nd argument;
size_t __cdecl mbsrtowcs(wchar_t * __restrict__ _Dest,const char ** __restrict__ _PSrc,size_t _Count,mbstate_t * __restrict__ _State) __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
^
EDIT2: To fix what was wrong Re. Matthieu, I have changed my naive implementation like so:
size_t mbsnrtowcs( wchar_t *__restrict__ dst, const char **__restrict__ src,
size_t nmc, size_t len, mbstate_t *__restrict__ ps )
{
char* local_src = new char[nmc+1];
char* nmcsrc = local_src;
strncpy( nmcsrc, *src, nmc );
nmcsrc[nmc] = '\0';
const size_t result = mbsrtowcs( dst, const_cast<const char **>(&nmcsrc), len, ps );
// propagate erro开发者_如何转开发r
if( nmcsrc == NULL )
*src = NULL;
delete[] local_src;
return result;
}
And I have added a FIXME saying that the proper way to do this would be implementing it via mbrtowc.
There is an issue here (not really related to the const
I think).
mbsrtowcs
might set *src
to NULL
.
mbsnrtowcs
is supposed to do the same, of course.
However for you here it causes a 2 bugs:
- Because you created a local alias, if
mbsrtowcs
set*src
toNULL
it is not reflected for the caller ofmbsnrtowcs
mbsnrtowcs
has a memory leak ifnmcsrc
is set toNULL
Perhaps that simply biting the bullet and implementing mbsnrtowcs
in terms of mbrtowc
would be more efficient ?
If you need to implement both (as I guess you do), you could also reverse the problem on its head and implement mbsrtowcs
in terms of mbsnrtowcs
simply by calling strlen
at the beginning without loss of generality (and avoid the copy).
There's no problem, since the function expects a more restrictive interface. So you can just cast the pointer:
const size_t result = std::mbsrtowcs(dst, const_cast<const char **>(&nmcsrc), len, ps);
I'm not sure about restrict
; you may need to add that to the cast as well (not on GCC, though) - that's a compiler-dependent matter, though, as there is no restrict
in C++.
精彩评论