根据mbsrtowcs实现mbsnrtowcs

Implementing mbsnrtowcs in terms of mbsrtowcs

本文关键字:mbsnrtowcs 实现 mbsrtowcs 根据      更新时间:2023-10-16

在将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] = '';
    const size_t result = mbsrtowcs( dst, &nmcsrc, len, ps );
    delete[] nmcsrc;
    return result;
}

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

编辑:Clang错误信息为:

M:DevelopmentSourcelibc++srcsupportwin32support.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/includewchar.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;
                 ^

编辑2:修复什么是错误的Re. 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] = '';
    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实现它。

这里有一个问题(我认为与const无关)。

mbsrtowcs可能设置*srcNULL

当然,

mbsnrtowcs也应该这样做。

但是对于你这里,它会导致两个错误:

  • 因为你创建了一个本地别名,如果mbsrtowcs设置*srcNULL,它不会反映在mbsnrtowcs的调用者
  • 如果nmcsrc设置为NULL,则mbsnrtowcs有内存泄漏

也许仅仅咬紧牙关,根据mbrtowc实现mbsnrtowcs会更有效?

如果你需要实现这两个(我猜你是这样做的),你也可以扭转这个问题,在mbsnrtowcs方面实现mbsrtowcs,只需在开始时调用strlen,而不会失去通用性(并避免复制)。

没有问题,因为该函数期望使用更具限制性的接口。所以你可以直接转换指针:

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

我不确定restrict;您可能还需要将其添加到强制转换中(尽管不是在GCC上)-这是与编译器相关的问题,因为c++中没有restrict