Consistently print errors in factory functions

This commit is contained in:
vittorioromeo 2024-06-10 17:11:43 +02:00 committed by Vittorio Romeo
parent 52fb26c6cd
commit a303cee386
9 changed files with 106 additions and 28 deletions

View File

@ -235,7 +235,8 @@ private:
/// \brief Try opening the music file from an optional input sound file /// \brief Try opening the music file from an optional input sound file
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] static std::optional<Music> tryOpenFromFile(std::optional<InputSoundFile>&& optFile); [[nodiscard]] static std::optional<Music> tryOpenFromInputSoundFile(std::optional<InputSoundFile>&& optFile,
const char* errorContext);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Initialize the internal state after loading a new music /// \brief Initialize the internal state after loading a new music

View File

@ -56,6 +56,8 @@ public:
/// ///
/// \param address IP address or network name /// \param address IP address or network name
/// ///
/// \return Address if provided argument was valid, otherwise `std::nullopt`
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] static std::optional<IpAddress> resolve(std::string_view address); [[nodiscard]] static std::optional<IpAddress> resolve(std::string_view address);
@ -128,7 +130,7 @@ public:
/// Unlike getPublicAddress, this function is fast and may be /// Unlike getPublicAddress, this function is fast and may be
/// used safely anywhere. /// used safely anywhere.
/// ///
/// \return Local IP address of the computer /// \return Local IP address of the computer on success, `std::nullopt` otherwise
/// ///
/// \see getPublicAddress /// \see getPublicAddress
/// ///
@ -152,7 +154,7 @@ public:
/// ///
/// \param timeout Maximum time to wait /// \param timeout Maximum time to wait
/// ///
/// \return Public IP address of the computer /// \return Public IP address of the computer on success, `std::nullopt` otherwise
/// ///
/// \see getLocalAddress /// \see getLocalAddress
/// ///

View File

@ -34,6 +34,7 @@
#include <SFML/System/InputStream.hpp> #include <SFML/System/InputStream.hpp>
#include <SFML/System/MemoryInputStream.hpp> #include <SFML/System/MemoryInputStream.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <SFML/System/Utils.hpp>
#include <ostream> #include <ostream>
#include <utility> #include <utility>
@ -71,19 +72,32 @@ std::optional<InputSoundFile> InputSoundFile::openFromFile(const std::filesystem
// Find a suitable reader for the file type // Find a suitable reader for the file type
auto reader = SoundFileFactory::createReaderFromFilename(filename); auto reader = SoundFileFactory::createReaderFromFilename(filename);
if (!reader) if (!reader)
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
// Wrap the file into a stream // Wrap the file into a stream
auto file = std::make_unique<FileInputStream>(); auto file = std::make_unique<FileInputStream>();
// Open it // Open it
if (!file->open(filename)) if (!file->open(filename))
{
err() << "Failed to open input sound file from file (couldn't open file input stream)\n"
<< formatDebugPathInfo(filename) << std::endl;
return std::nullopt; return std::nullopt;
}
// Pass the stream to the reader // Pass the stream to the reader
auto info = reader->open(*file); auto info = reader->open(*file);
if (!info) if (!info)
{
err() << "Failed to open input sound file from file (reader open failure)\n"
<< formatDebugPathInfo(filename) << std::endl;
return std::nullopt; return std::nullopt;
}
return InputSoundFile(std::move(reader), std::move(file), info->sampleCount, info->sampleRate, std::move(info->channelMap)); return InputSoundFile(std::move(reader), std::move(file), info->sampleCount, info->sampleRate, std::move(info->channelMap));
} }
@ -95,7 +109,10 @@ std::optional<InputSoundFile> InputSoundFile::openFromMemory(const void* data, s
// Find a suitable reader for the file type // Find a suitable reader for the file type
auto reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes); auto reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes);
if (!reader) if (!reader)
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
// Wrap the memory file into a stream // Wrap the memory file into a stream
auto memory = std::make_unique<MemoryInputStream>(data, sizeInBytes); auto memory = std::make_unique<MemoryInputStream>(data, sizeInBytes);
@ -103,7 +120,10 @@ std::optional<InputSoundFile> InputSoundFile::openFromMemory(const void* data, s
// Pass the stream to the reader // Pass the stream to the reader
auto info = reader->open(*memory); auto info = reader->open(*memory);
if (!info) if (!info)
{
err() << "Failed to open input sound file from memory (reader open failure)" << std::endl;
return std::nullopt; return std::nullopt;
}
return InputSoundFile(std::move(reader), std::move(memory), info->sampleCount, info->sampleRate, std::move(info->channelMap)); return InputSoundFile(std::move(reader), std::move(memory), info->sampleCount, info->sampleRate, std::move(info->channelMap));
} }
@ -115,7 +135,10 @@ std::optional<InputSoundFile> InputSoundFile::openFromStream(InputStream& stream
// Find a suitable reader for the file type // Find a suitable reader for the file type
auto reader = SoundFileFactory::createReaderFromStream(stream); auto reader = SoundFileFactory::createReaderFromStream(stream);
if (!reader) if (!reader)
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
// Don't forget to reset the stream to its beginning before re-opening it // Don't forget to reset the stream to its beginning before re-opening it
if (stream.seek(0) != 0) if (stream.seek(0) != 0)
@ -127,7 +150,10 @@ std::optional<InputSoundFile> InputSoundFile::openFromStream(InputStream& stream
// Pass the stream to the reader // Pass the stream to the reader
auto info = reader->open(stream); auto info = reader->open(stream);
if (!info) if (!info)
{
err() << "Failed to open input sound file from stream (reader open failure)" << std::endl;
return std::nullopt; return std::nullopt;
}
return InputSoundFile(std::move(reader), {&stream, false}, info->sampleCount, info->sampleRate, std::move(info->channelMap)); return InputSoundFile(std::move(reader), {&stream, false}, info->sampleCount, info->sampleRate, std::move(info->channelMap));
} }

View File

@ -79,10 +79,13 @@ Music& Music::operator=(Music&&) noexcept = default;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Music> Music::tryOpenFromFile(std::optional<InputSoundFile>&& optFile) std::optional<Music> Music::tryOpenFromInputSoundFile(std::optional<InputSoundFile>&& optFile, const char* errorContext)
{ {
if (!optFile.has_value()) if (!optFile.has_value())
{
err() << "Failed to open music from " << errorContext << std::endl;
return std::nullopt; return std::nullopt;
}
// TODO: apply RVO here via passkey idiom // TODO: apply RVO here via passkey idiom
return Music(std::move(*optFile)); return Music(std::move(*optFile));
@ -92,21 +95,21 @@ std::optional<Music> Music::tryOpenFromFile(std::optional<InputSoundFile>&& optF
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Music> Music::openFromFile(const std::filesystem::path& filename) std::optional<Music> Music::openFromFile(const std::filesystem::path& filename)
{ {
return tryOpenFromFile(InputSoundFile::openFromFile(filename)); return tryOpenFromInputSoundFile(InputSoundFile::openFromFile(filename), "file");
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Music> Music::openFromMemory(const void* data, std::size_t sizeInBytes) std::optional<Music> Music::openFromMemory(const void* data, std::size_t sizeInBytes)
{ {
return tryOpenFromFile(InputSoundFile::openFromMemory(data, sizeInBytes)); return tryOpenFromInputSoundFile(InputSoundFile::openFromMemory(data, sizeInBytes), "memory");
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Music> Music::openFromStream(InputStream& stream) std::optional<Music> Music::openFromStream(InputStream& stream)
{ {
return tryOpenFromFile(InputSoundFile::openFromStream(stream)); return tryOpenFromInputSoundFile(InputSoundFile::openFromStream(stream), "stream");
} }

View File

@ -29,6 +29,8 @@
#include <SFML/Audio/SoundFileFactory.hpp> #include <SFML/Audio/SoundFileFactory.hpp>
#include <SFML/Audio/SoundFileWriter.hpp> #include <SFML/Audio/SoundFileWriter.hpp>
#include <SFML/System/Err.hpp>
#include <cassert> #include <cassert>
@ -44,11 +46,15 @@ std::optional<OutputSoundFile> OutputSoundFile::openFromFile(
// Find a suitable writer for the file type // Find a suitable writer for the file type
auto writer = SoundFileFactory::createWriterFromFilename(filename); auto writer = SoundFileFactory::createWriterFromFilename(filename);
if (!writer) if (!writer)
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
// Pass the stream to the reader // Pass the stream to the reader
if (!writer->open(filename, sampleRate, channelCount, channelMap)) if (!writer->open(filename, sampleRate, channelCount, channelMap))
{ {
err() << "Failed to open output sound file from file (writer open failure)" << std::endl;
return std::nullopt; return std::nullopt;
} }

View File

@ -72,7 +72,8 @@ std::optional<SoundBuffer> SoundBuffer::loadFromFile(const std::filesystem::path
{ {
if (auto file = InputSoundFile::openFromFile(filename)) if (auto file = InputSoundFile::openFromFile(filename))
return initialize(*file); return initialize(*file);
else
err() << "Failed to open sound buffer from file" << std::endl;
return std::nullopt; return std::nullopt;
} }
@ -82,7 +83,8 @@ std::optional<SoundBuffer> SoundBuffer::loadFromMemory(const void* data, std::si
{ {
if (auto file = InputSoundFile::openFromMemory(data, sizeInBytes)) if (auto file = InputSoundFile::openFromMemory(data, sizeInBytes))
return initialize(*file); return initialize(*file);
else
err() << "Failed to open sound buffer from memory" << std::endl;
return std::nullopt; return std::nullopt;
} }
@ -92,7 +94,8 @@ std::optional<SoundBuffer> SoundBuffer::loadFromStream(InputStream& stream)
{ {
if (auto file = InputSoundFile::openFromStream(stream)) if (auto file = InputSoundFile::openFromStream(stream))
return initialize(*file); return initialize(*file);
else
err() << "Failed to open sound buffer from stream" << std::endl;
return std::nullopt; return std::nullopt;
} }
@ -223,7 +226,11 @@ std::optional<SoundBuffer> SoundBuffer::initialize(InputSoundFile& file)
// Update the internal buffer with the new samples // Update the internal buffer with the new samples
SoundBuffer soundBuffer(std::move(samples)); SoundBuffer soundBuffer(std::move(samples));
if (!soundBuffer.update(file.getChannelCount(), file.getSampleRate(), file.getChannelMap())) if (!soundBuffer.update(file.getChannelCount(), file.getSampleRate(), file.getChannelMap()))
{
err() << "Failed to initialize sound buffer (internal update failure)" << std::endl;
return std::nullopt; return std::nullopt;
}
return soundBuffer; return soundBuffer;
} }
else else

View File

@ -266,30 +266,33 @@ std::optional<Texture> Texture::create(const Vector2u& size, bool sRgb)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Texture> Texture::loadFromFile(const std::filesystem::path& filename, bool sRgb, const IntRect& area) std::optional<Texture> Texture::loadFromFile(const std::filesystem::path& filename, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromFile(filename); if (const auto image = sf::Image::loadFromFile(filename))
if (!image)
return std::nullopt;
return loadFromImage(*image, sRgb, area); return loadFromImage(*image, sRgb, area);
err() << "Failed to load texture from file" << std::endl;
return std::nullopt;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Texture> Texture::loadFromMemory(const void* data, std::size_t size, bool sRgb, const IntRect& area) std::optional<Texture> Texture::loadFromMemory(const void* data, std::size_t size, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromMemory(data, size); if (const auto image = sf::Image::loadFromMemory(data, size))
if (!image)
return std::nullopt;
return loadFromImage(*image, sRgb, area); return loadFromImage(*image, sRgb, area);
err() << "Failed to load texture from memory" << std::endl;
return std::nullopt;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<Texture> Texture::loadFromStream(InputStream& stream, bool sRgb, const IntRect& area) std::optional<Texture> Texture::loadFromStream(InputStream& stream, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromStream(stream); if (const auto image = sf::Image::loadFromStream(stream))
if (!image)
return std::nullopt;
return loadFromImage(*image, sRgb, area); return loadFromImage(*image, sRgb, area);
err() << "Failed to load texture from stream" << std::endl;
return std::nullopt;
} }
@ -307,11 +310,11 @@ std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, con
if (auto texture = sf::Texture::create(image.getSize(), sRgb)) if (auto texture = sf::Texture::create(image.getSize(), sRgb))
{ {
texture->update(image); texture->update(image);
return texture; return texture;
} }
else else
{ {
// Error message generated in called function.
return std::nullopt; return std::nullopt;
} }
} }
@ -354,6 +357,7 @@ std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, con
} }
else else
{ {
// Error message generated in called function.
return std::nullopt; return std::nullopt;
} }
} }

View File

@ -29,6 +29,8 @@
#include <SFML/Network/IpAddress.hpp> #include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/SocketImpl.hpp> #include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <istream> #include <istream>
#include <ostream> #include <ostream>
@ -49,7 +51,10 @@ std::optional<IpAddress> IpAddress::resolve(std::string_view address)
using namespace std::string_view_literals; using namespace std::string_view_literals;
if (address.empty()) if (address.empty())
{
// Not generating en error message here as resolution failure is a valid outcome.
return std::nullopt; return std::nullopt;
}
if (address == "255.255.255.255"sv) if (address == "255.255.255.255"sv)
{ {
@ -81,6 +86,7 @@ std::optional<IpAddress> IpAddress::resolve(std::string_view address)
return IpAddress(ntohl(ip)); return IpAddress(ntohl(ip));
} }
// Not generating en error message here as resolution failure is a valid outcome.
return std::nullopt; return std::nullopt;
} }
@ -125,13 +131,18 @@ std::optional<IpAddress> IpAddress::getLocalAddress()
// Create the socket // Create the socket
const SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0); const SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == priv::SocketImpl::invalidSocket()) if (sock == priv::SocketImpl::invalidSocket())
{
err() << "Failed to retrieve local address (invalid socket)" << std::endl;
return std::nullopt; return std::nullopt;
}
// Connect the socket to localhost on any port // Connect the socket to localhost on any port
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9); sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1) if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{ {
priv::SocketImpl::close(sock); priv::SocketImpl::close(sock);
err() << "Failed to retrieve local address (socket connection failure)" << std::endl;
return std::nullopt; return std::nullopt;
} }
@ -140,6 +151,8 @@ std::optional<IpAddress> IpAddress::getLocalAddress()
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1) if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{ {
priv::SocketImpl::close(sock); priv::SocketImpl::close(sock);
err() << "Failed to retrieve local address (socket local address retrieval failure)" << std::endl;
return std::nullopt; return std::nullopt;
} }
@ -163,10 +176,15 @@ std::optional<IpAddress> IpAddress::getPublicAddress(Time timeout)
Http server("www.sfml-dev.org"); Http server("www.sfml-dev.org");
const Http::Request request("/ip-provider.php", Http::Request::Method::Get); const Http::Request request("/ip-provider.php", Http::Request::Method::Get);
const Http::Response page = server.sendRequest(request, timeout); const Http::Response page = server.sendRequest(request, timeout);
if (page.getStatus() == Http::Response::Status::Ok)
const Http::Response::Status status = page.getStatus();
if (status == Http::Response::Status::Ok)
return IpAddress::resolve(page.getBody()); return IpAddress::resolve(page.getBody());
// Something failed: return an invalid address err() << "Failed to retrieve public address from external IP resolution server (HTTP response status "
<< static_cast<int>(status) << ")" << std::endl;
return std::nullopt; return std::nullopt;
} }

View File

@ -28,9 +28,11 @@
#include <SFML/Window/Cursor.hpp> #include <SFML/Window/Cursor.hpp>
#include <SFML/Window/CursorImpl.hpp> #include <SFML/Window/CursorImpl.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <memory> #include <memory>
#include <ostream>
namespace sf namespace sf
{ {
@ -57,11 +59,17 @@ Cursor& Cursor::operator=(Cursor&&) noexcept = default;
std::optional<Cursor> Cursor::loadFromPixels(const std::uint8_t* pixels, Vector2u size, Vector2u hotspot) std::optional<Cursor> Cursor::loadFromPixels(const std::uint8_t* pixels, Vector2u size, Vector2u hotspot)
{ {
if ((pixels == nullptr) || (size.x == 0) || (size.y == 0)) if ((pixels == nullptr) || (size.x == 0) || (size.y == 0))
{
err() << "Failed to load cursor from pixels (invalid arguments)" << std::endl;
return std::nullopt; return std::nullopt;
}
Cursor cursor; Cursor cursor;
if (!cursor.m_impl->loadFromPixels(pixels, size, hotspot)) if (!cursor.m_impl->loadFromPixels(pixels, size, hotspot))
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
return cursor; return cursor;
} }
@ -72,7 +80,10 @@ std::optional<Cursor> Cursor::loadFromSystem(Type type)
{ {
Cursor cursor; Cursor cursor;
if (!cursor.m_impl->loadFromSystem(type)) if (!cursor.m_impl->loadFromSystem(type))
{
// Error message generated in called function.
return std::nullopt; return std::nullopt;
}
return cursor; return cursor;
} }