diff --git a/crlib/files.h b/crlib/files.h index 37bf680..3cde96b 100644 --- a/crlib/files.h +++ b/crlib/files.h @@ -374,4 +374,121 @@ class MemFile final : public NonCopyable { } }; +namespace detail { + struct FileEnumeratorEntry : public NonCopyable { + FileEnumeratorEntry () = default; + ~FileEnumeratorEntry () = default; + +#if defined (CR_WINDOWS) + bool next {}; + String path {}; + HANDLE handle {}; + WIN32_FIND_DATAA data {}; +#else + String path {}; + String mask {}; + DIR *dir {}; + dirent *entry {}; +#endif + }; +} + +// file enumerator +class FileEnumerator : public NonCopyable { +private: + UniquePtr entries_; + +public: + FileEnumerator (StringRef mask) : entries_ (cr::makeUnique ()) { + start (mask); + } + + ~FileEnumerator () { + close (); + } + +public: + void start (StringRef mask) { + auto lastSeperatorPos = mask.findLastOf (kPathSeparator); + Twin pam {}; + + if (lastSeperatorPos != StringRef::InvalidIndex) { + pam = { + mask.substr (0, lastSeperatorPos), + mask.substr (1 + lastSeperatorPos) + }; + } + else { + pam = { ".", mask }; + } + entries_->path = pam.first; + +#if defined (CR_WINDOWS) + entries_->handle = FindFirstFileA (mask.chars (), &entries_->data); + entries_->next = entries_->handle != INVALID_HANDLE_VALUE; +#else + entries_->dir = opendir (entries_->path.chars ()); + entries_->mask = pam.second; + + if (entries_->dir != nullptr) { + next (); + } +#endif + } + + void close () { +#if defined (CR_WINDOWS) + if (entries_->handle != INVALID_HANDLE_VALUE) { + FindClose (entries_->handle); + + entries_->handle = INVALID_HANDLE_VALUE; + entries_->next = false; + } +#else + if (entries_->dir != nullptr) { + closedir (entries_->dir); + entries_->dir = nullptr; + } +#endif + } + + bool next () { +#if defined (CR_WINDOWS) + entries_->next = !!FindNextFileA (entries_->handle, &entries_->data); + return entries_->next; +#else + while ((entries_->entry = readdir (entries_->dir)) != nullptr) { + if (!fnmatch (entries_->mask.chars (), entries_->entry->d_name, FNM_CASEFOLD | FNM_NOESCAPE | FNM_PERIOD)) { + return true; + } + } + return false; +#endif + } + + bool stillValid () const { +#if defined (CR_WINDOWS) + return entries_->next; +#else + return entries_->dir != nullptr && entries_->entry != nullptr; +#endif + } + + String getMatch () const { + StringRef match {}; + +#if defined (CR_WINDOWS) + match = entries_->data.cFileName; +#else + match = entries_->entry->d_name; +#endif + return String::join ({ entries_->path, match }, kPathSeparator); + } + +public: + operator bool () const { + return stillValid (); + } +}; + CR_NAMESPACE_END diff --git a/crlib/http.h b/crlib/http.h index 8d54ec7..01f4db3 100644 --- a/crlib/http.h +++ b/crlib/http.h @@ -315,7 +315,7 @@ class HttpClient final : public Singleton { size_t responseCodeStart = response.find ("HTTP/1.1"); if (responseCodeStart != String::InvalidIndex) { - String respCode = response.substr (responseCodeStart + 9, 3); + String respCode = response.substr (responseCodeStart + cr::bufsize ("HTTP 1/1 "), 3); respCode.trim (); return static_cast (respCode.int_ ()); @@ -456,6 +456,7 @@ class HttpClient final : public Singleton { // send the main request if (socket->send (request.chars (), static_cast (request.length ())) < 1) { statusCode_ = HttpClientResult::SocketError; + return false; } @@ -485,7 +486,6 @@ class HttpClient final : public Singleton { return false; } statusCode_ = parseResponseHeader (socket.get (), buffer.data ()); - return statusCode_ == HttpClientResult::Ok; } diff --git a/crlib/platform.h b/crlib/platform.h index 3e413a8..5db6719 100644 --- a/crlib/platform.h +++ b/crlib/platform.h @@ -212,6 +212,8 @@ constexpr auto kPathSeparator = "/"; constexpr auto kLibrarySuffix = ".so"; #endif # include +# include +# include # include # include #endif @@ -378,7 +380,7 @@ struct Platform : public Singleton { #endif } - // anologue of memset + // analogue of memset template void bzero (U *ptr, size_t len) noexcept { memset (reinterpret_cast (ptr), 0, len); } @@ -413,6 +415,17 @@ struct Platform : public Singleton { return result; } + const char *tmpfname () { +#if defined (CR_CXX_MSVC) + static char name[L_tmpnam_s]; + tmpnam_s (name); + + return name; +#else + return tmpnam (nullptr); +#endif + } + int32_t hardwareConcurrency () { #if defined (CR_WINDOWS) SYSTEM_INFO sysinfo;