Eliminate wcs2str

Use std::string variants everywhere instead
This commit is contained in:
ridiculousfish 2020-07-29 16:37:23 -07:00
parent e4b1fc9f6a
commit db086fc5d4
7 changed files with 25 additions and 119 deletions

View File

@ -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];

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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.