diff --git a/src/wutil.cpp b/src/wutil.cpp index bbbbe497b..9aa76102b 100644 --- a/src/wutil.cpp +++ b/src/wutil.cpp @@ -625,6 +625,37 @@ long long fish_wcstoll(const wchar_t *str, const wchar_t **endptr, int base) { return result; } +/// An enhanced version of wcstoull(). +/// +/// This is needed because BSD and GNU implementations differ in several ways that make it really +/// annoying to use them in a portable fashion. +/// +/// The caller doesn't have to zero errno. Sets errno to -1 if the int ends with something other +/// than a digit. Leading whitespace is ignored (per the base wcstoll implementation). Trailing +/// whitespace is also ignored. +unsigned long long fish_wcstoull(const wchar_t *str, const wchar_t **endptr, int base) { + while (iswspace(*str)) ++str; // skip leading whitespace + if (!*str) { // this is because some implementations don't handle this sensibly + errno = EINVAL; + if (endptr) *endptr = str; + return 0; + } + + errno = 0; + wchar_t *_endptr; + unsigned long long result = wcstoull(str, &_endptr, base); + while (iswspace(*_endptr)) ++_endptr; // skip trailing whitespace + if (!errno && *_endptr) { + if (_endptr == str) { + errno = EINVAL; + } else { + errno = -1; + } + } + if (endptr) *endptr = _endptr; + return result; +} + file_id_t file_id_t::file_id_from_stat(const struct stat *buf) { assert(buf != NULL); diff --git a/src/wutil.h b/src/wutil.h index a529de9ce..2bd8ed80a 100644 --- a/src/wutil.h +++ b/src/wutil.h @@ -120,6 +120,7 @@ int fish_wcswidth(const wcstring &str); int fish_wcstoi(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); long fish_wcstol(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); long long fish_wcstoll(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); +unsigned long long fish_wcstoull(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); /// Class for representing a file's inode. We use this to detect and avoid symlink loops, among /// other things. While an inode / dev pair is sufficient to distinguish co-existing files, Linux