aboutsummaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/CMakeLists.txt3
-rw-r--r--c/data.cpp16
-rw-r--r--c/data.h8
-rw-r--r--c/ext.cpp2
-rw-r--r--c/util.h60
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")
diff --git a/c/data.cpp b/c/data.cpp
index 4db294c..8c26138 100644
--- a/c/data.cpp
+++ b/c/data.cpp
@@ -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;
diff --git a/c/data.h b/c/data.h
index 478182d..171edaa 100644
--- a/c/data.h
+++ b/c/data.h
@@ -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();
}
diff --git a/c/ext.cpp b/c/ext.cpp
index 398804e..8e58ade 100644
--- a/c/ext.cpp
+++ b/c/ext.cpp
@@ -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
diff --git a/c/util.h b/c/util.h
index ffc6b57..f9e3057 100644
--- a/c/util.h
+++ b/c/util.h
@@ -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}; }
};