aboutsummaryrefslogtreecommitdiff
path: root/c/data.cpp
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-09-03 15:28:56 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-09-03 15:28:56 +0200
commit6ae7e24675cff4ff6b808c3024f45083f35ced97 (patch)
tree2a47273f325d8367db2a8669691273f02ca83eb9 /c/data.cpp
parent2cd22c671c67deaf2c1fcb659e3262bf57552557 (diff)
downloadEpisodeBrowser-6ae7e24675cff4ff6b808c3024f45083f35ced97.tar.gz
Improve error handling.
Diffstat (limited to 'c/data.cpp')
-rw-r--r--c/data.cpp42
1 files changed, 20 insertions, 22 deletions
diff --git a/c/data.cpp b/c/data.cpp
index f862a5e..a75111a 100644
--- a/c/data.cpp
+++ b/c/data.cpp
@@ -7,28 +7,31 @@
#include "data.h"
#include "episodelistview.h"
+#include "err.h"
#include "res.h"
#include "util.h"
#include "win32.h"
#include "window.h"
+using namespace std::string_literals;
+
UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* wszUrl, const char* szUrl)
{
static Unique<HINTERNET, InternetCloseHandle> hi =
InternetOpenW(L"Episode Browser", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0);
if (hi.Bad(0))
- throw Win32Error();
+ throw Err(WINDOWS, L"Internet handle could not be opened: %s");
Unique<HINTERNET, InternetCloseHandle> hiUrl = InternetOpenUrlW(
hi.v, wszUrl, nullptr, 0, INTERNET_FLAG_NO_UI, 0);
if (hiUrl.Bad(0))
- throw InternetError();
+ throw Err(WININET, L"Could not open "s + wszUrl + L": %s");
char bufX[1024];
Unique<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = htmlCreatePushParserCtxt(
nullptr, nullptr, bufX, sizeof(bufX), szUrl, XML_CHAR_ENCODING_UTF8);
if (ctx.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"HTML parser context could not be created: %s");
htmlCtxtUseOptions(ctx.v, HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING);
@@ -37,9 +40,9 @@ UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* w
char bufI[1024];
while (r = InternetReadFile(hiUrl.v, bufI, sizeof(bufI), &cbRead), cbRead) {
if (!r)
- throw InternetError();
+ throw Err(WININET, L"HTML could not be retrieved: %s");
if (!htmlParseChunk(ctx.v, bufI, cbRead, 0))
- throw XmlError();
+ throw Err(LIBXML2, L"HTML could not be parsed: %s");
}
htmlParseChunk(ctx.v, bufI, 0, 1); /* Stop parsing. */
@@ -52,7 +55,7 @@ template <size_t N>
bool WcharsFromXmlchars(wchar_t (&dst)[N], Unique<xmlChar*, XmlFree> utf8)
{
if (utf8.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"Node content could not be retrieved: %s");
/* Truncate if source is larger than destination. */
int lenUtf8 = xmlStrlen(utf8.v);
@@ -125,8 +128,7 @@ void WaitFor(Window& window, void (*f)(unsigned char*))
sig |= DONE;
} catch (...) {
sig |= DONE;
- ShowException(L"Remote data could not be fetched due to an error while %s: %s",
- L"Error", MB_ICONWARNING);
+ EBMessageBox(What(), L"Remote Data Retrieval Error");
}
};
@@ -155,8 +157,6 @@ void WaitFor(Window& window, void (*f)(unsigned char*))
void FetchData(unsigned char* sig)
{
- Act(L"fetching and parsing general episode data");
-
/* The remote data is retrieved using WinINet from the
* Detective Conan World wiki. Using libxml2's "push parser",
* the HTML is parsed piece by piece as it is retrieved. The
@@ -164,26 +164,26 @@ void FetchData(unsigned char* sig)
* specific XPath query. This is fragile theoretically, but
* unlikely to break practically. */
+ wchar_t url[_countof(s_window->cfg.prefixUrl)+46+1];
+ Swprintf(url, L"%shttps://www.detectiveconanworld.com/wiki/Anime", s_window->cfg.prefixUrl);
+
UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx =
- RemoteParserCtxt(L"https://www.detectiveconanworld.com/wiki/Anime",
- "https://www.detectiveconanworld.com/wiki/Anime");
+ RemoteParserCtxt(url, "https://www.detectiveconanworld.com/wiki/Anime");
Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx = xmlXPathNewContext(ctx.v->myDoc);
if (xpathCtx.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"XPath context could not be created: %s");
Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj = xmlXPathEvalExpression(
reinterpret_cast<const xmlChar*>("//tr[./td[1] != '' and ./td[3][@style='background:#f2fde9;']]"),
xpathCtx.v);
if (xpathObj.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"XPath object could not be created: %s");
xmlNodeSetPtr nodes = xpathObj.v->nodesetval;
if (!nodes || !nodes->nodeNr)
- throw std::runtime_error("could not find remote episode information");
-
- Act(L"inserting remote data");
+ throw Err(GENERIC, L"Data retrieval failed: No matching HTML nodes found.");
for (int i = 0; i < nodes->nodeNr; i++) {
if (*sig & ABORT)
@@ -191,7 +191,7 @@ void FetchData(unsigned char* sig)
const xmlNodePtr node = nodes->nodeTab[i];
if (xmlChildElementCount(node) != 8)
- throw std::runtime_error("unexpected remote data format");
+ throw Err(GENERIC, L"Data retrieval failed: Unexcepted number of columns in table.");
ElvDataA& e = s_window->fvElv.At(i);
DlvDataA& d = s_window->fvDlv.At(i);
@@ -226,8 +226,6 @@ void FetchData(unsigned char* sig)
void FetchScreenwriters(unsigned char* sig)
{
- Act(L"fetching and parsing screenwriter data");
-
/* Screenwriters are expensive to fetch, so we try to avoid
* fetching screenwriters for episodes that already have a
* screenwriter. Additionally, in the same session, we don't
@@ -271,13 +269,13 @@ void FetchScreenwriters(unsigned char* sig)
UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(url, nullptr);
xpathCtx = xmlXPathNewContext(ctx.v->myDoc);
if (xpathCtx.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"XPath context could not be created: %s");
xpathObj = xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>(
"//th[contains(text(), 'Screenplay:')]/following-sibling::td"),
xpathCtx.v);
if (xpathObj.Bad(0))
- throw XmlError();
+ throw Err(LIBXML2, L"XPath object could not be created: %s");
xmlNodeSetPtr nodes = xpathObj.v->nodesetval;
if (nodes && nodes->nodeNr)