diff options
author | John Ankarström <john@ankarstrom.se> | 2022-09-02 00:09:56 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-09-02 00:09:56 +0200 |
commit | c624a89b4f1cccfefd60424a3181d76e4692fa4d (patch) | |
tree | 3449c8bcc9ad200c01fb2bed3154a68cb0c7c907 /c | |
parent | a26488497cc765890dd5dff122a1f08ca6c5ca95 (diff) | |
download | EpisodeBrowser-c624a89b4f1cccfefd60424a3181d76e4692fa4d.tar.gz |
Add UniqueOk.
Diffstat (limited to 'c')
-rw-r--r-- | c/data.cpp | 27 | ||||
-rw-r--r-- | c/layout.h | 8 | ||||
-rw-r--r-- | c/util.h | 66 |
3 files changed, 66 insertions, 35 deletions
@@ -11,16 +11,15 @@ #include "util.h" #include "win.h" -static Unique<HINTERNET, InternetCloseHandle> s_hi = - InternetOpenW(L"Episode Browser", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0); - -Unique<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* wszUrl, const char* szUrl) +UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* wszUrl, const char* szUrl) { - if (s_hi.Bad(0)) - throw Win32Error(); + static Unique<HINTERNET, InternetCloseHandle> hi = + InternetOpenW(L"Episode Browser", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0); + if (hi.Bad(0)) + throw Win32Error(); Unique<HINTERNET, InternetCloseHandle> hiUrl = InternetOpenUrlW( - s_hi.v, wszUrl, nullptr, 0, INTERNET_FLAG_NO_UI, 0); + hi.v, wszUrl, nullptr, 0, INTERNET_FLAG_NO_UI, 0); if (hiUrl.Bad(0)) throw InternetError(); @@ -81,7 +80,7 @@ bool WcharsFromXmlchars(wchar_t (&dst)[N], Unique<xmlChar*, XmlFree> utf8) * shared byte. At any given time, only a single fetch thread may be * performing work. */ -enum Signal +enum Signal : unsigned char { READY = 1<<0, /* Main -> fetch: start working! */ DONE = 1<<1, /* Fetch -> main: work is done. */ @@ -161,7 +160,7 @@ void FetchData(unsigned char* sig) * specific XPath query. This is fragile theoretically, but * unlikely to break practically. */ - Unique<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = + UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(L"https://www.detectiveconanworld.com/wiki/Anime", "https://www.detectiveconanworld.com/wiki/Anime"); @@ -251,6 +250,9 @@ void FetchScreenwriters(unsigned char* sig) const wchar_t prefix[] = L"https://www.detectiveconanworld.com"; wchar_t url[256]; Wcscpy(url, prefix); + + Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx; + Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj; for (iLast++; iLast < iMax; iLast++) { if (*sig & ABORT) return; @@ -265,13 +267,12 @@ void FetchScreenwriters(unsigned char* sig) /* Retrieve screenwriter from HTML. */ - Unique<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(url, nullptr); - Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx = xmlXPathNewContext(ctx.v->myDoc); + UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(url, nullptr); + xpathCtx = xmlXPathNewContext(ctx.v->myDoc); if (xpathCtx.Bad(0)) throw XmlError(); - Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj = - xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>( + xpathObj = xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>( "//th[contains(text(), 'Screenplay:')]/following-sibling::td"), xpathCtx.v); if (xpathObj.Bad(0)) @@ -21,13 +21,13 @@ struct Dragger protected: bool IsDown() const; bool IsDouble(const long time, const POINT& pt); - virtual bool InDragArea(int x, int y) const; + virtual bool InDragArea(int x, int y) const = 0; /* Perform drag, resizing relevant windows. */ - virtual void Drag(int x, int y) const; + virtual void Drag(int x, int y) const = 0; /* Reset dragger to automatic position. */ - virtual void Reset() const; + virtual void Reset() const = 0; /* Called after drag, when mouse button is released. */ - virtual void Done() const; + virtual void Done() const = 0; private: bool m_bActive = false; long m_time0 = 0; @@ -3,6 +3,7 @@ #include <cstring> #include <memory> +#include <stdexcept> #include <string> #include <windows.h> @@ -29,18 +30,12 @@ struct Finally }; #define FINALLY Finally _ = [=]() -template <typename T> -inline void Delete(T v) noexcept -{ - delete v; -} - /* Unique is similar to unique_ptr, but it is designed for pointers * and handles of type T, where T is not an RAII class. Further, the * managed object is assumed to be in an invalid state until checked * with Good or Bad. Upon destruction, the object, if valid, is passed * to a given destructor function F. */ -template <typename T, auto F = Delete<T>> +template <typename T, auto F> struct Unique { union { T v; }; @@ -49,10 +44,7 @@ struct Unique Unique(T v) noexcept : v(v) {} Unique& operator =(T v_) noexcept { - if (ok) { - F(v); - v.~T(); - } + Destroy(); v = v_; ok = false; return *this; @@ -63,8 +55,7 @@ struct Unique } Unique& operator =(Unique&& other) noexcept { - if (ok) - F(v); + Destroy(); v = std::move(other.v); ok = other.ok; other.ok = false; @@ -78,15 +69,54 @@ struct Unique { return !(ok = v != u); } + template <typename, auto> class UniqueOk; + template <auto E> + UniqueOk<T, F> ThrowIf(T u) noexcept + { + if (v == u) + throw E; + return std::move(*this); + } ~Unique() { + Destroy(); + } +private: + void Destroy() + { if (ok) { - F(v); + if constexpr (F) F(v); v.~T(); } } }; +/* UniqueOk contains a Unique that has already been validated. */ +template <typename T, auto F> +struct UniqueOk +{ + T v; + UniqueOk(Unique<T, F>&& u) : v(std::move(u.v)) + { + if (!u.ok) + throw std::runtime_error("cannot construct UniqueOk from non-ok Unique"); + u.ok = false; + } + UniqueOk& operator =(Unique<T, F>&& u) + { + if (!u.ok) + throw std::runtime_error("cannot construct UniqueOk from non-ok Unique"); + F(v); + v = std::move(u.v); + u.ok = false; + return *this; + } + ~UniqueOk() + { + F(v); + } +}; + /* Buf is a span-like structure of a buffer and its size. */ template <typename T> struct Buf @@ -96,10 +126,10 @@ struct Buf Buf(T* data, size_t c) noexcept : data(data), c(c) {} Buf(std::basic_string<T>& s) noexcept : data(s.data()), c(s.capacity()) {} template <size_t N> Buf(T (&data)[N]) noexcept : data(data), c(N) {} - operator T*() noexcept { return data; } - T& operator *() noexcept { return *data; } - T& operator [](size_t i) noexcept { return data[i]; } - Buf<T> operator +(size_t i) noexcept { return {data+i, c-i}; } + operator T*() const noexcept { return data; } + T& operator *() const noexcept { return *data; } + T& operator [](size_t i) const noexcept { return data[i]; } + Buf<T> operator +(size_t i) const noexcept { return {data+i, c-i}; } //T operator -(size_t i) { return {data-i, c+i}; } }; |