diff options
author | John Ankarström <john@ankarstrom.se> | 2022-08-29 23:33:48 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-08-29 23:33:48 +0200 |
commit | b9d7ec228b03e2978b0e1d9f21dadd56b2f405e3 (patch) | |
tree | b909da04cba0bcaada3c5fa16c474c49c684ef12 | |
parent | aabdb17f29216e03b9821fb99b57e9287ee46d6d (diff) | |
download | EpisodeBrowser-b9d7ec228b03e2978b0e1d9f21dadd56b2f405e3.tar.gz |
Small improvments.
-rw-r--r-- | c/CMakeLists.txt | 3 | ||||
-rw-r--r-- | c/data.cpp | 16 | ||||
-rw-r--r-- | c/data.h | 8 | ||||
-rw-r--r-- | c/ext.cpp | 2 | ||||
-rw-r--r-- | c/util.h | 60 |
5 files changed, 50 insertions, 39 deletions
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index b3a1671..da411b2 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -35,7 +35,8 @@ target_sources(EpisodeBrowser PRIVATE test.h util.h win.cpp - win.h) + win.h +) if (CMAKE_GENERATOR MATCHES "Visual Studio") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") @@ -24,15 +24,15 @@ struct ParsedDoc ParsedDoc(const wchar_t* wszUrl, const char* szUrl) { - if (!s_hi.Not(0)) + if (!s_hi.Bad(0)) throw Win32Error(); hiUrl = InternetOpenUrlW(s_hi.v, wszUrl, nullptr, 0, INTERNET_FLAG_NO_UI, 0); - if (!hiUrl.Not(0)) + if (!hiUrl.Bad(0)) throw InternetError(); ctxt = htmlCreatePushParserCtxt(nullptr, nullptr, bufX, sizeof(bufX), szUrl, XML_CHAR_ENCODING_UTF8); - if (!ctxt.Not(0)) + if (!ctxt.Bad(0)) throw XmlError(); htmlCtxtUseOptions(ctxt.v, HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING); @@ -57,7 +57,7 @@ template <size_t N> bool WcharsFromXmlchars(wchar_t (&dst)[N], xmlChar* utf8_) { Unique<xmlChar*, XmlFree> utf8 = utf8_; - if (!utf8.Not(0)) + if (!utf8.Bad(0)) throw XmlError(); /* Truncate if source is larger than destination. */ @@ -171,13 +171,13 @@ void FetchData(unsigned char* sig) "https://www.detectiveconanworld.com/wiki/Anime"); Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx = xmlXPathNewContext(doc); - if (!xpathCtx.Not(0)) + if (!xpathCtx.Bad(0)) throw XmlError(); Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj = xmlXPathEvalExpression( reinterpret_cast<const xmlChar*>("//tr[./td[1] != '' and ./td[3][@style='background:#f2fde9;']]"), xpathCtx.v); - if (!xpathObj.Not(0)) + if (!xpathObj.Bad(0)) throw XmlError(); xmlNodeSetPtr nodes = xpathObj.v->nodesetval; @@ -271,14 +271,14 @@ void FetchScreenwriters(unsigned char* sig) /* Retrieve screenwriter from HTML. */ ParsedDoc doc(url, nullptr); Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx = xmlXPathNewContext(doc); - if (!xpathCtx.Not(0)) + if (!xpathCtx.Bad(0)) throw XmlError(); Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj = xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>( "//th[contains(text(), 'Screenplay:')]/following-sibling::td"), xpathCtx.v); - if (!xpathObj.Not(0)) + if (!xpathObj.Bad(0)) throw XmlError(); xmlNodeSetPtr nodes = xpathObj.v->nodesetval; @@ -120,11 +120,11 @@ struct FileView { hf = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!hf.Not(INVALID_HANDLE_VALUE)) { + if (!hf.Bad(INVALID_HANDLE_VALUE)) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { hf = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!hf.Not(INVALID_HANDLE_VALUE)) + if (!hf.Bad(INVALID_HANDLE_VALUE)) throw Win32Error(); } else throw Win32Error(); @@ -134,11 +134,11 @@ struct FileView cbMap.QuadPart = c*sizeof(T); hm = CreateFileMapping(hf.v, nullptr, PAGE_READWRITE, cbMap.HighPart, cbMap.LowPart, nullptr); - if (!hm.Not(0)) + if (!hm.Bad(0)) throw Win32Error(); view = reinterpret_cast<T*>(MapViewOfFile(hm.v, FILE_MAP_ALL_ACCESS, 0, 0, 0)); - if (!view.Not(0)) + if (!view.Bad(0)) throw Win32Error(); } @@ -87,7 +87,7 @@ static bool FindMatchingFile(wchar_t (&file)[MAX_PATH], const wchar_t* const roo WIN32_FIND_DATA fdata; Unique<HANDLE, FindClose> h = FindFirstFileW(pat, &fdata); - if (!h.Not(INVALID_HANDLE_VALUE)) + if (!h.Bad(INVALID_HANDLE_VALUE)) throw Win32Error(); do @@ -19,42 +19,49 @@ _Exit(1); \ }) +/* Scope guard. */ template <typename F> struct Finally { F f; - inline Finally(F f) : f(f) {} + inline Finally(F f) noexcept : f(f) {} inline ~Finally() { f(); } }; #define FINALLY Finally _ = [=]() template <typename T> -inline void Delete(T v) +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>> struct Unique { - T v; - bool ok = true; - Unique() : ok(false) {} - Unique(T v) : v(v) {} - Unique& operator =(T v_) + union { T v; }; + bool ok = false; + Unique() noexcept {} + Unique(T v) noexcept : v(v) {} + Unique& operator =(T v_) noexcept { - if (ok) + if (ok) { F(v); + v.~T(); + } v = v_; - ok = true; + ok = false; return *this; } - Unique(Unique&& other) + Unique(Unique&& other) noexcept : v(std::move(other.v)), ok(other.ok) { - v = std::move(other.v); other.ok = false; } - Unique& operator =(Unique&& other) + Unique& operator =(Unique&& other) noexcept { if (ok) F(v); @@ -63,17 +70,20 @@ struct Unique other.ok = false; return *this; } - bool Not(T u) + bool Good(T u) noexcept { - if (v == u) - return ok = false; - else - return true; + return ok = v == u; + } + bool Bad(T u) noexcept + { + return ok = v != u; } ~Unique() { - if (ok) + if (ok) { F(v); + v.~T(); + } } }; @@ -83,13 +93,13 @@ struct Buf { T* data; size_t c; - Buf(T* data, size_t c) : data(data), c(c) {} - Buf(std::basic_string<T>& s) : data(s.data()), c(s.capacity()) {} - template <size_t N> Buf(T (&data)[N]) : data(data), c(N) {} - operator T*() { return data; } - T& operator *() { return *data; } - T& operator [](size_t i) { return data[i]; } - Buf<T> operator +(size_t i) { return {data+i, c-i}; } + 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}; } //T operator -(size_t i) { return {data-i, c+i}; } }; |