mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 09:12:11 +08:00
Eliminate wcs2str
Use std::string variants everywhere instead
This commit is contained in:
parent
e4b1fc9f6a
commit
db086fc5d4
@ -95,7 +95,6 @@ int get_debug_stack_frames() { return debug_stack_frames; }
|
||||
/// This is set during startup and not modified after.
|
||||
static relaxed_atomic_t<pid_t> initial_fg_process_group{-1};
|
||||
|
||||
static char *wcs2str_internal(const wchar_t *in, char *out);
|
||||
static void debug_shared(wchar_t msg_level, const wcstring &msg);
|
||||
|
||||
#if defined(OS_IS_CYGWIN) || defined(WSL)
|
||||
@ -333,33 +332,6 @@ wcstring str2wcstring(const std::string &in, size_t len) {
|
||||
return str2wcs_internal(in.data(), len);
|
||||
}
|
||||
|
||||
char *wcs2str(const wchar_t *in, size_t len) {
|
||||
if (!in) return nullptr;
|
||||
size_t desired_size = MAX_UTF8_BYTES * len + 1;
|
||||
char local_buff[512];
|
||||
if (desired_size <= sizeof local_buff / sizeof *local_buff) {
|
||||
// Convert into local buff, then use strdup() so we don't waste malloc'd space.
|
||||
char *result = wcs2str_internal(in, local_buff);
|
||||
if (result) {
|
||||
// It converted into the local buffer, so copy it.
|
||||
result = strdup(result);
|
||||
assert(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Here we probably allocate a buffer probably much larger than necessary.
|
||||
auto out = static_cast<char *>(malloc(MAX_UTF8_BYTES * len + 1));
|
||||
assert(out);
|
||||
// Instead of returning the return value of wcs2str_internal, return `out` directly.
|
||||
// This eliminates false warnings in coverity about resource leaks.
|
||||
wcs2str_internal(in, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
char *wcs2str(const wchar_t *in) { return wcs2str(in, std::wcslen(in)); }
|
||||
char *wcs2str(const wcstring &in) { return wcs2str(in.c_str(), in.length()); }
|
||||
|
||||
/// This function is distinguished from wcs2str_internal in that it allows embedded null bytes.
|
||||
std::string wcs2string(const wcstring &input) {
|
||||
std::string result;
|
||||
@ -395,47 +367,6 @@ std::string wcs2string(const wcstring &input) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Converts the wide character string \c in into it's narrow equivalent, stored in \c out. \c out
|
||||
/// must have enough space to fit the entire string.
|
||||
///
|
||||
/// This function decodes illegal character sequences in a reversible way using the private use
|
||||
/// area.
|
||||
static char *wcs2str_internal(const wchar_t *in, char *out) {
|
||||
assert(in && out && "in and out must not be null");
|
||||
size_t in_pos = 0;
|
||||
size_t out_pos = 0;
|
||||
mbstate_t state = {};
|
||||
|
||||
while (in[in_pos]) {
|
||||
if (in[in_pos] == INTERNAL_SEPARATOR) {
|
||||
// do nothing
|
||||
} else if (in[in_pos] >= ENCODE_DIRECT_BASE && in[in_pos] < ENCODE_DIRECT_BASE + 256) {
|
||||
out[out_pos++] = in[in_pos] - ENCODE_DIRECT_BASE;
|
||||
} else if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
|
||||
{
|
||||
// If `wc` contains a wide character we emit a question-mark.
|
||||
if (in[in_pos] & ~0xFF) {
|
||||
out[out_pos++] = '?';
|
||||
} else {
|
||||
out[out_pos++] = static_cast<unsigned char>(in[in_pos]);
|
||||
}
|
||||
} else {
|
||||
size_t len = std::wcrtomb(&out[out_pos], in[in_pos], &state);
|
||||
if (len == static_cast<size_t>(-1)) {
|
||||
FLOGF(char_encoding, L"Wide character U+%4X has no narrow representation",
|
||||
in[in_pos]);
|
||||
std::memset(&state, 0, sizeof(state));
|
||||
} else {
|
||||
out_pos += len;
|
||||
}
|
||||
}
|
||||
in_pos++;
|
||||
}
|
||||
out[out_pos] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Test if the character can be encoded using the current locale.
|
||||
static bool can_be_encoded(wchar_t wc) {
|
||||
char converted[MB_LEN_MAX];
|
||||
|
@ -290,8 +290,6 @@ wcstring str2wcstring(const std::string &in, size_t len);
|
||||
///
|
||||
/// This function decodes illegal character sequences in a reversible way using the private use
|
||||
/// area.
|
||||
char *wcs2str(const wchar_t *in);
|
||||
char *wcs2str(const wcstring &in);
|
||||
std::string wcs2string(const wcstring &input);
|
||||
|
||||
enum fuzzy_match_type_t {
|
||||
|
@ -324,18 +324,18 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
||||
if (vars.get(L"HOME").missing_or_empty()) {
|
||||
auto user_var = vars.get(L"USER");
|
||||
if (!user_var.missing_or_empty()) {
|
||||
char *unam_narrow = wcs2str(user_var->as_string());
|
||||
std::string unam_narrow = wcs2string(user_var->as_string());
|
||||
struct passwd userinfo;
|
||||
struct passwd *result;
|
||||
char buf[8192];
|
||||
int retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result);
|
||||
int retval = getpwnam_r(unam_narrow.c_str(), &userinfo, buf, sizeof(buf), &result);
|
||||
if (retval || !result) {
|
||||
// Maybe USER is set but it's bogus. Reset USER from the db and try again.
|
||||
setup_user(true);
|
||||
user_var = vars.get(L"USER");
|
||||
if (!user_var.missing_or_empty()) {
|
||||
unam_narrow = wcs2str(user_var->as_string());
|
||||
retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result);
|
||||
unam_narrow = wcs2string(user_var->as_string());
|
||||
retval = getpwnam_r(unam_narrow.c_str(), &userinfo, buf, sizeof(buf), &result);
|
||||
}
|
||||
}
|
||||
if (!retval && result && userinfo.pw_dir) {
|
||||
@ -346,7 +346,6 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
||||
// so it isn't necessary to warn here as well.
|
||||
vars.set_empty(L"HOME", ENV_GLOBAL | ENV_EXPORT);
|
||||
}
|
||||
free(unam_narrow);
|
||||
} else {
|
||||
// If $USER is empty as well (which we tried to set above), we can't get $HOME.
|
||||
vars.set_empty(L"HOME", ENV_GLOBAL | ENV_EXPORT);
|
||||
|
@ -537,14 +537,13 @@ autoclose_fd_t env_universal_t::open_temporary_file(const wcstring &directory, w
|
||||
int saved_errno;
|
||||
const wcstring tmp_name_template = directory + L"/fishd.tmp.XXXXXX";
|
||||
autoclose_fd_t result;
|
||||
char *narrow_str = nullptr;
|
||||
std::string narrow_str;
|
||||
for (size_t attempt = 0; attempt < 10 && !result.valid(); attempt++) {
|
||||
narrow_str = wcs2str(tmp_name_template);
|
||||
result.reset(fish_mkstemp_cloexec(narrow_str));
|
||||
narrow_str = wcs2string(tmp_name_template);
|
||||
result.reset(fish_mkstemp_cloexec(&narrow_str[0]));
|
||||
saved_errno = errno;
|
||||
}
|
||||
*out_path = str2wcstring(narrow_str);
|
||||
free(narrow_str);
|
||||
|
||||
if (!result.valid()) {
|
||||
const char *error = std::strerror(saved_errno);
|
||||
|
@ -110,12 +110,12 @@ static relaxed_atomic_t<int> s_fork_count{0};
|
||||
|
||||
auto export_vars = vars.export_arr();
|
||||
const char *const *envv = export_vars->get();
|
||||
char *actual_cmd = wcs2str(p->actual_cmd);
|
||||
std::string actual_cmd = wcs2string(p->actual_cmd);
|
||||
|
||||
// Ensure the terminal modes are what they were before we changed them.
|
||||
restore_term_mode();
|
||||
// Bounce to launch_process. This never returns.
|
||||
safe_launch_process(p, actual_cmd, argv_array.get(), envv);
|
||||
safe_launch_process(p, actual_cmd.c_str(), argv_array.get(), envv);
|
||||
}
|
||||
|
||||
// Returns whether we can use posix spawn for a given process in a given job.
|
||||
|
@ -496,42 +496,25 @@ static char *str2hex(const char *input) {
|
||||
/// Test wide/narrow conversion by creating random strings and verifying that the original string
|
||||
/// comes back through double conversion.
|
||||
static void test_convert() {
|
||||
int i;
|
||||
std::vector<char> sb{};
|
||||
|
||||
say(L"Testing wide/narrow string conversion");
|
||||
|
||||
for (i = 0; i < ESCAPE_TEST_COUNT; i++) {
|
||||
const char *o, *n;
|
||||
char c;
|
||||
|
||||
sb.clear();
|
||||
for (int i = 0; i < ESCAPE_TEST_COUNT; i++) {
|
||||
std::string orig{};
|
||||
while (random() % ESCAPE_TEST_LENGTH) {
|
||||
c = random();
|
||||
sb.push_back(c);
|
||||
}
|
||||
c = 0;
|
||||
sb.push_back(c);
|
||||
|
||||
o = &sb.at(0);
|
||||
const wcstring w = str2wcstring(o);
|
||||
n = wcs2str(w);
|
||||
|
||||
if (!o || !n) {
|
||||
err(L"Line %d - Conversion cycle of string %s produced null pointer on %s", __LINE__, o,
|
||||
L"wcs2str");
|
||||
char c = random();
|
||||
orig.push_back(c);
|
||||
}
|
||||
|
||||
if (std::strcmp(o, n)) {
|
||||
char *o2 = str2hex(o);
|
||||
char *n2 = str2hex(n);
|
||||
const wcstring w = str2wcstring(orig);
|
||||
std::string n = wcs2string(w);
|
||||
if (orig != n) {
|
||||
char *o2 = str2hex(orig.c_str());
|
||||
char *n2 = str2hex(n.c_str());
|
||||
err(L"Line %d - %d: Conversion cycle of string:\n%4d chars: %s\n"
|
||||
L"produced different string:\n%4d chars: %s",
|
||||
__LINE__, i, std::strlen(o), o2, std::strlen(n), n2);
|
||||
__LINE__, i, orig.size(), o2, n.size(), n2);
|
||||
free(o2);
|
||||
free(n2);
|
||||
}
|
||||
free((void *)n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,19 +480,15 @@ wcstring path_normalize_for_cd(const wcstring &wd, const wcstring &path) {
|
||||
}
|
||||
|
||||
wcstring wdirname(const wcstring &path) {
|
||||
char *tmp = wcs2str(path);
|
||||
char *narrow_res = dirname(tmp);
|
||||
wcstring result = format_string(L"%s", narrow_res);
|
||||
free(tmp);
|
||||
return result;
|
||||
std::string tmp = wcs2string(path);
|
||||
const char *narrow_res = dirname(&tmp[0]);
|
||||
return str2wcstring(narrow_res);
|
||||
}
|
||||
|
||||
wcstring wbasename(const wcstring &path) {
|
||||
char *tmp = wcs2str(path);
|
||||
char *narrow_res = basename(tmp);
|
||||
wcstring result = format_string(L"%s", narrow_res);
|
||||
free(tmp);
|
||||
return result;
|
||||
std::string tmp = wcs2string(path);
|
||||
char *narrow_res = basename(&tmp[0]);
|
||||
return str2wcstring(narrow_res);
|
||||
}
|
||||
|
||||
// Really init wgettext.
|
||||
|
Loading…
x
Reference in New Issue
Block a user