Merge tag 'v0.21.23'

release v0.21.23
This commit is contained in:
Max Kellermann
2020-04-23 17:54:22 +02:00
20 changed files with 238 additions and 60 deletions

View File

@@ -34,12 +34,6 @@
#include <algorithm>
#endif
#ifdef _WIN32
#include "Win32.hxx"
#include <windows.h>
#endif
#include <cassert>
#include <memory>
#include <string.h>
@@ -65,27 +59,6 @@ try {
folded.SetSize(folded_length);
return UCharToUTF8({folded.begin(), folded.size()});
#elif defined(_WIN32)
const auto u = MultiByteToWideChar(CP_UTF8, src);
const int size = LCMapStringEx(LOCALE_NAME_INVARIANT,
LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
u.c_str(), -1, nullptr, 0,
nullptr, nullptr, 0);
if (size <= 0)
return AllocatedString<>::Duplicate(src);
std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]);
int result = LCMapStringEx(LOCALE_NAME_INVARIANT,
LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
u.c_str(), -1, buffer.get(), size,
nullptr, nullptr, 0);
if (result <= 0)
return AllocatedString<>::Duplicate(src);
return WideCharToMultiByte(CP_UTF8,
{buffer.get(), size_t(result - 1)});
#else
#error not implemented
#endif

View File

@@ -22,7 +22,7 @@
#include "config.h"
#if defined(HAVE_ICU) || defined(_WIN32)
#ifdef HAVE_ICU
#define HAVE_ICU_CASE_FOLD
#include <string_view>

View File

@@ -108,7 +108,7 @@ IcuCollate(std::string_view a, std::string_view b) noexcept
}
auto result = CompareStringEx(LOCALE_NAME_INVARIANT,
LINGUISTIC_IGNORECASE,
NORM_IGNORECASE,
wa.c_str(), -1,
wb.c_str(), -1,
nullptr, nullptr, 0);

View File

@@ -22,11 +22,27 @@
#include "util/StringAPI.hxx"
#include "config.h"
#ifdef _WIN32
#include "Win32.hxx"
#include <windows.h>
#endif
#ifdef HAVE_ICU_CASE_FOLD
IcuCompare::IcuCompare(std::string_view _needle) noexcept
:needle(IcuCaseFold(_needle)) {}
#elif defined(_WIN32)
IcuCompare::IcuCompare(std::string_view _needle) noexcept
:needle(nullptr)
{
try {
needle = MultiByteToWideChar(CP_UTF8, _needle);
} catch (...) {
}
}
#else
IcuCompare::IcuCompare(std::string_view _needle) noexcept
@@ -39,6 +55,22 @@ IcuCompare::operator==(const char *haystack) const noexcept
{
#ifdef HAVE_ICU_CASE_FOLD
return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str());
#elif defined(_WIN32)
if (needle.IsNull())
/* the MultiByteToWideChar() call in the constructor
has failed, so let's always fail the comparison */
return false;
try {
auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack);
return CompareStringEx(LOCALE_NAME_INVARIANT,
NORM_IGNORECASE,
w_haystack.c_str(), -1,
needle.c_str(), -1,
nullptr, nullptr, 0) == CSTR_EQUAL;
} catch (...) {
return false;
}
#else
return StringIsEqualIgnoreCase(haystack, needle.c_str());
#endif
@@ -50,6 +82,24 @@ IcuCompare::IsIn(const char *haystack) const noexcept
#ifdef HAVE_ICU_CASE_FOLD
return StringFind(IcuCaseFold(haystack).c_str(),
needle.c_str()) != nullptr;
#elif defined(_WIN32)
if (needle.IsNull())
/* the MultiByteToWideChar() call in the constructor
has failed, so let's always fail the comparison */
return false;
try {
auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack);
return FindNLSStringEx(LOCALE_NAME_INVARIANT,
FIND_FROMSTART|NORM_IGNORECASE,
w_haystack.c_str(), -1,
needle.c_str(), -1,
nullptr,
nullptr, nullptr, 0) >= 0;
} catch (...) {
/* MultiByteToWideChar() has failed */
return false;
}
#elif defined(HAVE_STRCASESTR)
return strcasestr(haystack, needle.c_str()) != nullptr;
#else

View File

@@ -25,13 +25,23 @@
#include <string_view>
#ifdef _WIN32
#include <wchar.h>
#endif
/**
* This class can compare one string ("needle") with lots of other
* strings ("haystacks") efficiently, ignoring case. With some
* configurations, it can prepare a case-folded version of the needle.
*/
class IcuCompare {
#ifdef _WIN32
/* Windows API functions work with wchar_t strings, so let's
cache the MultiByteToWideChar() result for performance */
AllocatedString<wchar_t> needle;
#else
AllocatedString<> needle;
#endif
public:
IcuCompare():needle(nullptr) {}
@@ -40,12 +50,12 @@ public:
IcuCompare(const IcuCompare &src) noexcept
:needle(src
? AllocatedString<>::Duplicate(src.needle)
? src.needle.Clone()
: nullptr) {}
IcuCompare &operator=(const IcuCompare &src) noexcept {
needle = src
? AllocatedString<>::Duplicate(src.needle)
? src.needle.Clone()
: nullptr;
return *this;
}

View File

@@ -191,7 +191,9 @@ static constexpr int
events_to_libnfs(unsigned i) noexcept
{
return ((i & SocketMonitor::READ) ? POLLIN : 0) |
((i & SocketMonitor::WRITE) ? POLLOUT : 0);
((i & SocketMonitor::WRITE) ? POLLOUT : 0) |
((i & SocketMonitor::HANGUP) ? POLLHUP : 0) |
((i & SocketMonitor::ERROR) ? POLLERR : 0);
}
NfsConnection::~NfsConnection() noexcept
@@ -450,8 +452,7 @@ NfsConnection::ScheduleSocket() noexcept
SocketMonitor::Open(_fd);
}
SocketMonitor::Schedule(libnfs_to_events(which_events)
| SocketMonitor::HANGUP);
SocketMonitor::Schedule(libnfs_to_events(which_events));
}
inline int

View File

@@ -180,7 +180,6 @@ NfsFileReader::OnNfsConnectionDisconnected(std::exception_ptr e) noexcept
inline void
NfsFileReader::OpenCallback(nfsfh *_fh) noexcept
{
assert(state == State::OPEN);
assert(connection != nullptr);
assert(_fh != nullptr);
@@ -197,27 +196,33 @@ NfsFileReader::OpenCallback(nfsfh *_fh) noexcept
}
inline void
NfsFileReader::StatCallback(const struct stat *st) noexcept
NfsFileReader::StatCallback(const struct stat *_st) noexcept
{
assert(state == State::STAT);
assert(connection != nullptr);
assert(fh != nullptr);
assert(st != nullptr);
assert(_st != nullptr);
#if defined(_WIN32) && !defined(_WIN64)
/* on 32-bit Windows, libnfs enables -D_FILE_OFFSET_BITS=64,
but MPD (Meson) doesn't - to work around this mismatch, we
cast explicitly to "struct stat64" */
const auto *st = (const struct stat64 *)_st;
#else
const auto *st = _st;
#endif
if (!S_ISREG(st->st_mode)) {
OnNfsFileError(std::make_exception_ptr(std::runtime_error("Not a regular file")));
return;
}
state = State::IDLE;
OnNfsFileOpen(st->st_size);
}
void
NfsFileReader::OnNfsCallback(unsigned status, void *data) noexcept
{
switch (state) {
switch (std::exchange(state, State::IDLE)) {
case State::INITIAL:
case State::DEFER:
case State::MOUNT:
@@ -234,7 +239,6 @@ NfsFileReader::OnNfsCallback(unsigned status, void *data) noexcept
break;
case State::READ:
state = State::IDLE;
OnNfsFileRead(data, status);
break;
}