diff options
author | Max Kellermann <max@duempel.org> | 2016-02-06 08:45:19 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2016-02-07 12:58:20 +0100 |
commit | 6c5bc9b4a391c081a7856ef60bc7c0332d21c32e (patch) | |
tree | 1eca15770c342b4e4d03b89f851ecbc7882ecccc | |
parent | cd2f65aafca3263478d11673e5a14bc6d30fcdfa (diff) |
lib/expat: use C++ exceptions instead of class Error
-rw-r--r-- | src/db/plugins/upnp/ContentDirectoryService.cxx | 50 | ||||
-rw-r--r-- | src/db/plugins/upnp/Directory.cxx | 6 | ||||
-rw-r--r-- | src/db/plugins/upnp/Directory.hxx | 5 | ||||
-rw-r--r-- | src/db/plugins/upnp/UpnpDatabasePlugin.cxx | 124 | ||||
-rw-r--r-- | src/lib/expat/ExpatParser.cxx | 19 | ||||
-rw-r--r-- | src/lib/expat/ExpatParser.hxx | 19 | ||||
-rw-r--r-- | src/lib/upnp/ContentDirectoryService.hxx | 26 | ||||
-rw-r--r-- | src/lib/upnp/Device.cxx | 12 | ||||
-rw-r--r-- | src/lib/upnp/Device.hxx | 5 | ||||
-rw-r--r-- | src/lib/upnp/Discovery.cxx | 11 | ||||
-rw-r--r-- | src/lib/upnp/Discovery.hxx | 5 |
11 files changed, 108 insertions, 174 deletions
diff --git a/src/db/plugins/upnp/ContentDirectoryService.cxx b/src/db/plugins/upnp/ContentDirectoryService.cxx index 98f705212..0a5ec5fd8 100644 --- a/src/db/plugins/upnp/ContentDirectoryService.cxx +++ b/src/db/plugins/upnp/ContentDirectoryService.cxx @@ -32,22 +32,22 @@ #include <stdio.h> -static bool -ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response, Error &error) +static void +ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response) { const char *p = ixmlwrap::getFirstElementValue(response, "Result"); if (p == nullptr) p = ""; - return dirbuf.parse(p, error); + dirbuf.Parse(p); } -inline bool +inline void ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl, const char *objectId, unsigned offset, unsigned count, UPnPDirContent &dirbuf, - unsigned &didreadp, unsigned &totalp, - Error &error) const + unsigned &didreadp, + unsigned &totalp) const { // Create request char ofbuf[100], cntbuf[100]; @@ -85,35 +85,32 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl, if (value != nullptr) totalp = ParseUnsigned(value); - return ReadResultTag(dirbuf, response, error); + ReadResultTag(dirbuf, response); } -bool +UPnPDirContent ContentDirectoryService::readDir(UpnpClient_Handle handle, - const char *objectId, - UPnPDirContent &dirbuf, - Error &error) const + const char *objectId) const { + UPnPDirContent dirbuf; unsigned offset = 0, total = -1, count; do { - if (!readDirSlice(handle, objectId, offset, m_rdreqcnt, dirbuf, - count, total, error)) - return false; + readDirSlice(handle, objectId, offset, m_rdreqcnt, dirbuf, + count, total); offset += count; } while (count > 0 && offset < total); - return true; + return dirbuf; } -bool +UPnPDirContent ContentDirectoryService::search(UpnpClient_Handle hdl, const char *objectId, - const char *ss, - UPnPDirContent &dirbuf, - Error &error) const + const char *ss) const { + UPnPDirContent dirbuf; unsigned offset = 0, total = -1, count; do { @@ -155,18 +152,15 @@ ContentDirectoryService::search(UpnpClient_Handle hdl, if (value != nullptr) total = ParseUnsigned(value); - if (!ReadResultTag(dirbuf, response.get(), error)) - return false; + ReadResultTag(dirbuf, response.get()); } while (count > 0 && offset < total); - return true; + return dirbuf; } -bool +UPnPDirContent ContentDirectoryService::getMetadata(UpnpClient_Handle hdl, - const char *objectId, - UPnPDirContent &dirbuf, - Error &error) const + const char *objectId) const { // Create request UniqueIxmlDocument request(MakeActionHelper("Browse", m_serviceType.c_str(), @@ -188,5 +182,7 @@ ContentDirectoryService::getMetadata(UpnpClient_Handle hdl, UpnpGetErrorMessage(code)); UniqueIxmlDocument response(_response); - return ReadResultTag(dirbuf, response.get(), error); + UPnPDirContent dirbuf; + ReadResultTag(dirbuf, response.get()); + return dirbuf; } diff --git a/src/db/plugins/upnp/Directory.cxx b/src/db/plugins/upnp/Directory.cxx index e7f92432a..ecf346c6d 100644 --- a/src/db/plugins/upnp/Directory.cxx +++ b/src/db/plugins/upnp/Directory.cxx @@ -236,9 +236,9 @@ protected: } }; -bool -UPnPDirContent::parse(const char *input, Error &error) +void +UPnPDirContent::Parse(const char *input) { UPnPDirParser parser(*this); - return parser.Parse(input, strlen(input), true, error); + parser.Parse(input, strlen(input), true); } diff --git a/src/db/plugins/upnp/Directory.hxx b/src/db/plugins/upnp/Directory.hxx index 639f2bcbe..6c00747c2 100644 --- a/src/db/plugins/upnp/Directory.hxx +++ b/src/db/plugins/upnp/Directory.hxx @@ -36,6 +36,9 @@ class UPnPDirContent { public: std::vector<UPnPDirObject> objects; + UPnPDirContent() = default; + UPnPDirContent(UPnPDirContent &&) = default; + ~UPnPDirContent(); gcc_pure @@ -60,7 +63,7 @@ public: * actually global, nothing really bad will happen if you mix * up... */ - bool parse(const char *didltext, Error &error); + void Parse(const char *didltext); }; #endif /* _UPNPDIRCONTENT_H_X_INCLUDED_ */ diff --git a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx index bca25efaa..462d523d2 100644 --- a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx +++ b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx @@ -127,32 +127,26 @@ private: VisitSong visit_song, Error &error) const; - bool SearchSongs(const ContentDirectoryService &server, - const char *objid, - const DatabaseSelection &selection, - UPnPDirContent& dirbuf, - Error &error) const; + UPnPDirContent SearchSongs(const ContentDirectoryService &server, + const char *objid, + const DatabaseSelection &selection) const; - bool Namei(const ContentDirectoryService &server, - const std::list<std::string> &vpath, - UPnPDirObject &dirent, - Error &error) const; + UPnPDirObject Namei(const ContentDirectoryService &server, + const std::list<std::string> &vpath) const; /** * Take server and objid, return metadata. */ - bool ReadNode(const ContentDirectoryService &server, - const char *objid, UPnPDirObject& dirent, - Error &error) const; + UPnPDirObject ReadNode(const ContentDirectoryService &server, + const char *objid) const; /** * Get the path for an object Id. This works much like pwd, * except easier cause our inodes have a parent id. Not used * any more actually (see comments in SearchSongs). */ - bool BuildPath(const ContentDirectoryService &server, - const UPnPDirObject& dirent, std::string &idpath, - Error &error) const; + std::string BuildPath(const ContentDirectoryService &server, + const UPnPDirObject& dirent) const; }; Database * @@ -214,7 +208,7 @@ UpnpDatabase::ReturnSong(const LightSong *_song) const // Get song info by path. We can receive either the id path, or the titles // one const LightSong * -UpnpDatabase::GetSong(const char *uri, Error &error) const +UpnpDatabase::GetSong(const char *uri, gcc_unused Error &error) const { auto vpath = stringToTokens(uri, "/", true); if (vpath.size() < 2) @@ -227,12 +221,9 @@ UpnpDatabase::GetSong(const char *uri, Error &error) const UPnPDirObject dirent; if (vpath.front() != rootid) { - if (!Namei(server, vpath, dirent, error)) - return nullptr; + dirent = Namei(server, vpath); } else { - if (!ReadNode(server, vpath.back().c_str(), dirent, - error)) - return nullptr; + dirent = ReadNode(server, vpath.back().c_str()); } return new UpnpSong(std::move(dirent), uri); @@ -262,20 +253,18 @@ dquote(std::string &out, const char *in) // Run an UPnP search, according to MPD parameters. Return results as // UPnP items -bool +UPnPDirContent UpnpDatabase::SearchSongs(const ContentDirectoryService &server, const char *objid, - const DatabaseSelection &selection, - UPnPDirContent &dirbuf, - Error &error) const + const DatabaseSelection &selection) const { const SongFilter *filter = selection.filter; if (selection.filter == nullptr) - return true; + return UPnPDirContent(); const auto searchcaps = server.getSearchCapabilities(handle); if (searchcaps.empty()) - return true; + return UPnPDirContent(); std::string cond; for (const auto &item : filter->GetItems()) { @@ -338,9 +327,7 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server, } } - return server.search(handle, - objid, cond.c_str(), dirbuf, - error); + return server.search(handle, objid, cond.c_str()); } static bool @@ -381,13 +368,10 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server, VisitSong visit_song, Error &error) const { - UPnPDirContent dirbuf; if (!visit_song) return true; - if (!SearchSongs(server, objid, selection, dirbuf, error)) - return false; - for (auto &dirent : dirbuf.objects) { + for (auto &dirent : SearchSongs(server, objid, selection).objects) { if (dirent.type != UPnPDirObject::Type::ITEM || dirent.item_class != UPnPDirObject::ItemClass::MUSIC) continue; @@ -419,34 +403,25 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server, return true; } -bool +UPnPDirObject UpnpDatabase::ReadNode(const ContentDirectoryService &server, - const char *objid, UPnPDirObject &dirent, - Error &error) const + const char *objid) const { - UPnPDirContent dirbuf; - if (!server.getMetadata(handle, objid, dirbuf, error)) - return false; - + auto dirbuf = server.getMetadata(handle, objid); if (dirbuf.objects.size() != 1) throw std::runtime_error("Bad resource"); - dirent = std::move(dirbuf.objects.front()); - return true; + return std::move(dirbuf.objects.front()); } -bool +std::string UpnpDatabase::BuildPath(const ContentDirectoryService &server, - const UPnPDirObject& idirent, - std::string &path, - Error &error) const + const UPnPDirObject& idirent) const { const char *pid = idirent.id.c_str(); - path.clear(); - UPnPDirObject dirent; + std::string path; while (strcmp(pid, rootid) != 0) { - if (!ReadNode(server, pid, dirent, error)) - return false; + auto dirent = ReadNode(server, pid); pid = dirent.parent_id.c_str(); if (path.empty()) @@ -456,33 +431,24 @@ UpnpDatabase::BuildPath(const ContentDirectoryService &server, path.c_str()); } - path = PathTraitsUTF8::Build(server.getFriendlyName(), + return PathTraitsUTF8::Build(server.getFriendlyName(), path.c_str()); - return true; } // Take server and internal title pathname and return objid and metadata. -bool +UPnPDirObject UpnpDatabase::Namei(const ContentDirectoryService &server, - const std::list<std::string> &vpath, - UPnPDirObject &odirent, - Error &error) const + const std::list<std::string> &vpath) const { - if (vpath.empty()) { + if (vpath.empty()) // looking for root info - if (!ReadNode(server, rootid, odirent, error)) - return false; - - return true; - } + return ReadNode(server, rootid); std::string objid(rootid); // Walk the path elements, read each directory and try to find the next one for (auto i = vpath.begin(), last = std::prev(vpath.end());; ++i) { - UPnPDirContent dirbuf; - if (!server.readDir(handle, objid.c_str(), dirbuf, error)) - return false; + auto dirbuf = server.readDir(handle, objid.c_str()); // Look for the name in the sub-container list UPnPDirObject *child = dirbuf.FindObject(i->c_str()); @@ -490,10 +456,8 @@ UpnpDatabase::Namei(const ContentDirectoryService &server, throw DatabaseError(DatabaseErrorCode::NOT_FOUND, "No such object"); - if (i == last) { - odirent = std::move(*child); - return true; - } + if (i == last) + return std::move(*child); if (child->type != UPnPDirObject::Type::CONTAINER) throw DatabaseError(DatabaseErrorCode::NOT_FOUND, @@ -597,10 +561,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server, } if (visit_song) { - UPnPDirObject dirent; - if (!ReadNode(server, vpath.back().c_str(), dirent, - error)) - return false; + auto dirent = ReadNode(server, vpath.back().c_str()); if (dirent.type != UPnPDirObject::Type::ITEM || dirent.item_class != UPnPDirObject::ItemClass::MUSIC) @@ -618,9 +579,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server, } // Translate the target path into an object id and the associated metadata. - UPnPDirObject tdirent; - if (!Namei(server, vpath, tdirent, error)) - return false; + const auto tdirent = Namei(server, vpath); /* If recursive is set, this is a search... No use sending it if the filter is empty. In this case, we implement limited @@ -644,12 +603,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server, /* Target was a a container. Visit it. We could read slices and loop here, but it's not useful as mpd will only return data to the client when we're done anyway. */ - UPnPDirContent dirbuf; - if (!server.readDir(handle, tdirent.id.c_str(), dirbuf, - error)) - return false; - - for (auto &dirent : dirbuf.objects) { + for (const auto &dirent : server.readDir(handle, tdirent.id.c_str()).objects) { const std::string uri = PathTraitsUTF8::Build(base_uri, dirent.name.c_str()); if (!VisitObject(dirent, uri.c_str(), @@ -712,9 +666,7 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection, std::set<std::string> values; for (auto& server : discovery->GetDirectories()) { - UPnPDirContent dirbuf; - if (!SearchSongs(server, rootid, selection, dirbuf, error)) - return false; + const auto dirbuf = SearchSongs(server, rootid, selection); for (const auto &dirent : dirbuf.objects) { if (dirent.type != UPnPDirObject::Type::ITEM || diff --git a/src/lib/expat/ExpatParser.cxx b/src/lib/expat/ExpatParser.cxx index 7d9f1d587..dfe1b763e 100644 --- a/src/lib/expat/ExpatParser.cxx +++ b/src/lib/expat/ExpatParser.cxx @@ -36,16 +36,11 @@ ExpatParser::SetError(Error &error) XML_ErrorString(code)); } -bool -ExpatParser::Parse(const char *data, size_t length, bool is_final, - Error &error) +void +ExpatParser::Parse(const char *data, size_t length, bool is_final) { - bool success = XML_Parse(parser, data, length, - is_final) == XML_STATUS_OK; - if (!success) - SetError(error); - - return success; + if (XML_Parse(parser, data, length, is_final) != XML_STATUS_OK) + throw ExpatError(parser); } bool @@ -59,14 +54,14 @@ ExpatParser::Parse(InputStream &is, Error &error) if (nbytes == 0) break; - if (!Parse(buffer, nbytes, false, error)) - return false; + Parse(buffer, nbytes, false); } if (error.IsDefined()) return false; - return Parse("", 0, true, error); + Parse("", 0, true); + return true; } const char * diff --git a/src/lib/expat/ExpatParser.hxx b/src/lib/expat/ExpatParser.hxx index 5f2626dda..f62a2f64a 100644 --- a/src/lib/expat/ExpatParser.hxx +++ b/src/lib/expat/ExpatParser.hxx @@ -25,9 +25,20 @@ #include <expat.h> +#include <stdexcept> + class InputStream; class Error; +class ExpatError final : public std::runtime_error { +public: + ExpatError(XML_Error code) + :std::runtime_error(XML_ErrorString(code)) {} + + ExpatError(XML_Parser parser) + :ExpatError(XML_GetErrorCode(parser)) {} +}; + class ExpatParser final { const XML_Parser parser; @@ -53,8 +64,7 @@ public: XML_SetCharacterDataHandler(parser, charhndl); } - bool Parse(const char *data, size_t length, bool is_final, - Error &error); + void Parse(const char *data, size_t length, bool is_final); bool Parse(InputStream &is, Error &error); @@ -83,9 +93,8 @@ public: parser.SetCharacterDataHandler(CharacterData); } - bool Parse(const char *data, size_t length, bool is_final, - Error &error) { - return parser.Parse(data, length, is_final, error); + void Parse(const char *data, size_t length, bool is_final) { + parser.Parse(data, length, is_final); } bool Parse(InputStream &is, Error &error) { diff --git a/src/lib/upnp/ContentDirectoryService.hxx b/src/lib/upnp/ContentDirectoryService.hxx index cbce65696..5541cc282 100644 --- a/src/lib/upnp/ContentDirectoryService.hxx +++ b/src/lib/upnp/ContentDirectoryService.hxx @@ -76,17 +76,14 @@ public: /** Read a container's children list into dirbuf. * * @param objectId the UPnP object Id for the container. Root has Id "0" - * @param[out] dirbuf stores the entries we read. */ - bool readDir(UpnpClient_Handle handle, - const char *objectId, UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent readDir(UpnpClient_Handle handle, + const char *objectId) const; - bool readDirSlice(UpnpClient_Handle handle, + void readDirSlice(UpnpClient_Handle handle, const char *objectId, unsigned offset, unsigned count, UPnPDirContent& dirbuf, - unsigned &didread, unsigned &total, - Error &error) const; + unsigned &didread, unsigned &total) const; /** Search the content directory service. * @@ -96,22 +93,17 @@ public: * @param searchstring an UPnP searchcriteria string. Check the * UPnP document: UPnP-av-ContentDirectory-v1-Service-20020625.pdf * section 2.5.5. Maybe we'll provide an easier way some day... - * @param[out] dirbuf stores the entries we read. */ - bool search(UpnpClient_Handle handle, - const char *objectId, const char *searchstring, - UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent search(UpnpClient_Handle handle, + const char *objectId, + const char *searchstring) const; /** Read metadata for a given node. * * @param objectId the UPnP object Id. Root has Id "0" - * @param[out] dirbuf stores the entries we read. At most one entry will be - * returned. */ - bool getMetadata(UpnpClient_Handle handle, - const char *objectId, UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent getMetadata(UpnpClient_Handle handle, + const char *objectId) const; /** Retrieve search capabilities * diff --git a/src/lib/upnp/Device.cxx b/src/lib/upnp/Device.cxx index 402a39166..85829f9fe 100644 --- a/src/lib/upnp/Device.cxx +++ b/src/lib/upnp/Device.cxx @@ -21,7 +21,6 @@ #include "Device.hxx" #include "Util.hxx" #include "lib/expat/ExpatParser.hxx" -#include "util/Error.hxx" #include <stdlib.h> @@ -100,15 +99,12 @@ protected: } }; -bool -UPnPDevice::Parse(const std::string &url, const char *description, - Error &error) +void +UPnPDevice::Parse(const std::string &url, const char *description) { { UPnPDeviceParser mparser(*this); - if (!mparser.Parse(description, strlen(description), - true, error)) - return false; + mparser.Parse(description, strlen(description), true); } if (URLBase.empty()) { @@ -129,6 +125,4 @@ UPnPDevice::Parse(const std::string &url, const char *description, } } } - - return true; } diff --git a/src/lib/upnp/Device.hxx b/src/lib/upnp/Device.hxx index cdb065434..1144aaf93 100644 --- a/src/lib/upnp/Device.hxx +++ b/src/lib/upnp/Device.hxx @@ -23,8 +23,6 @@ #include <vector> #include <string> -class Error; - /** * UPnP Description phase: interpreting the device description which we * downloaded from the URL obtained by the discovery phase. @@ -81,8 +79,7 @@ public: * @param url where the description came from * @param description the xml device description */ - bool Parse(const std::string &url, const char *description, - Error &error); + void Parse(const std::string &url, const char *description); }; #endif /* _UPNPDEV_HXX_INCLUDED_ */ diff --git a/src/lib/upnp/Discovery.cxx b/src/lib/upnp/Discovery.cxx index 009ca89ad..56c823f06 100644 --- a/src/lib/upnp/Discovery.cxx +++ b/src/lib/upnp/Discovery.cxx @@ -135,13 +135,10 @@ UPnPDeviceDirectory::Explore() ContentDirectoryDescriptor d(std::move(tsk->device_id), MonotonicClockS(), tsk->expires); - { - Error error2; - bool success = d.Parse(tsk->url, buf, error2); - if (!success) { - LogError(error2); - continue; - } + try { + d.Parse(tsk->url, buf); + } catch (const std::exception &e) { + LogError(e); } LockAdd(std::move(d)); diff --git a/src/lib/upnp/Discovery.hxx b/src/lib/upnp/Discovery.hxx index 4ee08dd55..82cd26d9b 100644 --- a/src/lib/upnp/Discovery.hxx +++ b/src/lib/upnp/Discovery.hxx @@ -87,9 +87,8 @@ class UPnPDeviceDirectory final : UpnpCallback { unsigned last, int exp) :id(std::move(_id)), expires(last + exp + 20) {} - bool Parse(const std::string &url, const char *description, - Error &_error) { - return device.Parse(url, description, _error); + void Parse(const std::string &url, const char *description) { + device.Parse(url, description); } }; |