From 6ae7e24675cff4ff6b808c3024f45083f35ced97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sat, 3 Sep 2022 15:28:56 +0200 Subject: Improve error handling. --- c/data.cpp | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'c/data.cpp') 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 RemoteParserCtxt(const wchar_t* wszUrl, const char* szUrl) { static Unique 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 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 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 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 bool WcharsFromXmlchars(wchar_t (&dst)[N], Unique 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 ctx = - RemoteParserCtxt(L"https://www.detectiveconanworld.com/wiki/Anime", - "https://www.detectiveconanworld.com/wiki/Anime"); + RemoteParserCtxt(url, "https://www.detectiveconanworld.com/wiki/Anime"); Unique xpathCtx = xmlXPathNewContext(ctx.v->myDoc); if (xpathCtx.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"XPath context could not be created: %s"); Unique xpathObj = xmlXPathEvalExpression( reinterpret_cast("//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 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( "//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) -- cgit v1.2.3