skywind3000 / PyStand

:rocket: Python Standalone Deploy Environment !!
MIT License
736 stars 81 forks source link

refactor Ansi2Unicode #32

Closed myd7349 closed 1 year ago

myd7349 commented 1 year ago

修改的动机:

原来的实现里:

int size = wcslen(wide.c_str());

会触发一个告警信息。于是我就想消除它。我考虑了:

int size = (int)wcslen(wide.c_str());

但又想,这里要不要 +1 以保留 \0 呢?(虽然,后面通过 .c_str() 总是能确保得到一个以 \0 结尾的字符串。)

int size = wcslen(wide.c_str()) + 1;
wide.resize(size);

纠结之下,便决定重构一下。

修改后的版本,也能够减少不必要的内存分配。

以:

Ansi2Unicode("runtime");

为例,修改前,计算得的 require 为 26,修改后的为 8。

参考:

skywind3000 commented 1 year ago

想起个事情来,你刚好把 wide 的长度设置成需要的长度,但是 MultiByteToWideChar 是 C API,它会不会手贱在最后多写个 0 ? 这样就越界了。老写法的意思就是不管它多不多写,都能处理。

myd7349 commented 1 year ago

想起个事情来,你刚好把 wide 的长度设置成需要的长度,但是 MultiByteToWideChar 是 C API,它会不会手贱在最后多写个 0 ? 这样就越界了。老写法的意思就是不管它多不多写,都能处理。

这种写法不会导致越界。文档是这么说的:

[in] cbMultiByte

Size, in bytes, of the string indicated by the lpMultiByteStr parameter. Alternatively, this parameter can be set to -1 if the string is null-terminated. Note that, if cbMultiByte is 0, the function fails.

If this parameter is -1, the function processes the entire input string, including the terminating null character. Therefore, the resulting Unicode string has a terminating null character, and the length returned by the function includes this character.

If this parameter is set to a positive integer, the function processes exactly the specified number of bytes. If the provided size does not include a terminating null character, the resulting Unicode string is not null-terminated, and the returned length does not include this character.

因为我在第一趟计算所需空间的时候给这个参数传的是 -1,所以它的返回结果包含了终末 \0 所需的空间。

skywind3000 commented 1 year ago

那么你 wide 的长度就包括了一个 \u0000 的字符了?这样 std::wstring 按照长度进行其他计算时会不会出错呢?

myd7349 commented 1 year ago

那么你 wide 的长度就包括了一个 \u0000 的字符了?这样 std::wstring 按照长度进行其他计算时会不会出错呢?

这个确实是我过度设计了。之前想着其返回的结果直接就调 .c_str() 了,所以加个 \0 就省事儿了。

考虑到 Ansi2Unicode 的通用性的话,确实不应该加这个 \0。已提交一个新的 PR:https://github.com/skywind3000/PyStand/pull/33