根据mbsrtowcs实现mbsnrtowcs

时间:2011-09-23 11:37:00

标签: c++

在将libc ++移植到Windows的几乎全部工作中,我需要函数mbsnrtowcs,并认为最简单的方法是用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;
}

这里的问题是mbsrtowcs需要&nmcsrcconst char**类型,而不是,因为它是我刚刚复制了第一个nmc的字符串元素,并附加\0字符。我该如何解决这个问题?严格来说,这是编译为C ++,所以也许const_cast在这里几乎没有什么害处?我也可以访问c ++ 0X(libc ++是/需要一个c ++ 0x子集)。

编辑:Clang错误消息显示为:

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:修复错误的问题。 Matthieu,我已经改变了我的天真实现:

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 error
    if( nmcsrc == NULL )
        *src = NULL;
    delete[] local_src;
    return result;
}

我添加了一个FIXME,说正确的方法是通过mbrtowc实现它。

2 个答案:

答案 0 :(得分:4)

这里存在一个问题(与我认为的const没有关系。)

mbsrtowcs可能会将*src设置为NULL

mbsnrtowcs当然也应该这样做。

但是对你来说这会造成2个错误:

  • 由于您创建了本地别名,如果mbsrtowcs*src设置为NULL,则mbsnrtowcs
  • 的来电者不会反映出来 如果mbsnrtowcs设置为nmcsrc ,则
  • NULL内存泄漏

或许只是咬紧牙关并以mbsnrtowcs方式实施mbrtowc会更有效率吗?

如果你需要同时实现这些(我猜你这样做),你也可以通过调用mbsrtowcs来解决问题,并在mbsnrtowcs方面实施strlen一开始不失一般性(并避免复制)。

答案 1 :(得分:1)

没有问题,因为该函数需要更严格的接口。所以你可以抛出指针:

const size_t result = std::mbsrtowcs(dst, const_cast<const char **>(&nmcsrc), len, ps);

我不确定restrict;你可能还需要将它添加到转换器中(不是在GCC上) - 这是编译器相关的问题,因为C ++中没有restrict