Browse Source

Move Trade::ImporterFileCallbackPolicy to InputFileCallbackPolicy.

It'll get used outside of the root namespace and since the callbacks tend
to be quite complex, it would be silly to require users to implement one
callback for Trade, one for Text and one for Audio, for example.
audio-import
Vladimír Vondruš 7 years ago
parent
commit
e3fc0d037c
  1. 3
      doc/changelog.dox
  2. 9
      doc/snippets/MagnumTrade.cpp
  3. 2
      src/Magnum/CMakeLists.txt
  4. 46
      src/Magnum/FileCallback.cpp
  5. 92
      src/Magnum/FileCallback.h
  6. 2
      src/Magnum/Magnum.h
  7. 1
      src/Magnum/Test/CMakeLists.txt
  8. 52
      src/Magnum/Test/FileCallbackTest.cpp
  9. 27
      src/Magnum/Trade/AbstractImporter.cpp
  10. 89
      src/Magnum/Trade/AbstractImporter.h
  11. 50
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  12. 10
      src/Magnum/Trade/Trade.h
  13. 6
      src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp

3
doc/changelog.dox

@ -198,6 +198,9 @@ See also:
@subsection changelog-latest-deprecated Deprecated APIs
- @cpp Trade::ImporterFileCallbackPolicy @ce is deprecated as it was moved
to @ref InputFileCallbackPolicy in the root namespace to be shared with
APIs outside of the @ref Trade namespace
- @cpp DebugTools::ForceRendererOptions::scale() @ce is deprecated in favor
of @ref DebugTools::ForceRendererOptions::size(), as that's more consistent
with the documentation and the corresponding setter.

9
doc/snippets/MagnumTrade.cpp

@ -27,6 +27,7 @@
#include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Directory.h>
#include "Magnum/FileCallback.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Animation/Player.h"
#include "Magnum/MeshTools/Transform.h"
@ -72,13 +73,13 @@ struct Data {
} data;
importer->setFileCallback([](const std::string& filename,
Trade::ImporterFileCallbackPolicy policy, Data& data)
InputFileCallbackPolicy policy, Data& data)
-> Containers::Optional<Containers::ArrayView<const char>>
{
auto found = data.files.find(filename);
/* Discard the memory mapping, if not needed anymore */
if(policy == Trade::ImporterFileCallbackPolicy::Close) {
if(policy == InputFileCallbackPolicy::Close) {
if(found != data.files.end()) data.files.erase(found);
return {};
}
@ -114,7 +115,7 @@ static_cast<void>(shininess);
Containers::Pointer<Trade::AbstractImporter> importer;
/* [AbstractImporter-setFileCallback] */
importer->setFileCallback([](const std::string& filename,
Trade::ImporterFileCallbackPolicy, void*) {
InputFileCallbackPolicy, void*) {
Utility::Resource rs("data");
return Containers::optional(rs.getRaw(filename));
});
@ -129,7 +130,7 @@ struct Data {
} data;
importer->setFileCallback([](const std::string& filename,
Trade::ImporterFileCallbackPolicy, Data& data)
InputFileCallbackPolicy, Data& data)
-> Containers::Optional<Containers::ArrayView<const char>>
{
auto found = data.files.find(filename);

2
src/Magnum/CMakeLists.txt

@ -28,6 +28,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
# Files shared between main library and unit test library
set(Magnum_SRCS
FileCallback.cpp
Mesh.cpp
PixelStorage.cpp
Resource.cpp
@ -46,6 +47,7 @@ set(Magnum_HEADERS
AbstractResourceLoader.h
Array.h
DimensionTraits.h
FileCallback.h
Image.h
ImageView.h
Magnum.h

46
src/Magnum/FileCallback.cpp

@ -0,0 +1,46 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "FileCallback.h"
#include <Corrade/Utility/Debug.h>
namespace Magnum {
Debug& operator<<(Debug& debug, const InputFileCallbackPolicy value) {
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case InputFileCallbackPolicy::v: return debug << "InputFileCallbackPolicy::" #v;
_c(LoadTemporary)
_c(LoadPernament)
_c(Close)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "InputFileCallbackPolicy(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
}

92
src/Magnum/FileCallback.h

@ -0,0 +1,92 @@
#ifndef Magnum_FileCallback_h
#define Magnum_FileCallback_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Enum @ref Magnum::InputFileCallbackPolicy
*/
#include "Magnum/Magnum.h"
#include "Magnum/visibility.h"
namespace Magnum {
/**
@brief Input file callback policy
@see @ref Trade::AbstractImporter::setFileCallback(),
@ref Trade-AbstractImporter-usage-callbacks
*/
enum class InputFileCallbackPolicy: UnsignedByte {
/**
* The requested file is used only during a call of given function and the
* memory view is not referenced anymore once the function exits.
*
* This can be the case for example when importing image data using
* @ref Trade::AbstractImporter::image2D() --- imported data are copied
* into the returned @ref Trade::ImageData2D object and the original file
* is not needed anymore. Note, however, that this might not be the case
* for all importers --- see documentation of a particular plugin for
* concrete info.
*/
LoadTemporary,
/**
* The requested file may be used for loading most or all data in the next
* steps, so the importer expects the memory view to be valid for as long
* as data import functions are called on it, but at most until the
* data importer is destroyed, its @ref Trade::AbstractImporter::close() "close()"
* function is called or another file is opened.
*
* This can be the case for example when importing mesh data using
* @ref Trade::AbstractImporter::mesh3D() --- all vertex data might be
* combined in a single binary file and each mesh occupies only a portion
* of it. Note, however, that this might not be the case for all importers
* --- see documentation of a particular plugin for concrete info.
*/
LoadPernament,
/**
* A file that has been previously loaded by this callback can be closed
* now (and its memory freed). This is just a hint, it's not *required* for
* the callback to close it. This policy is also only ever called with a
* file that was previously opened with the same callback, so it's possible
* to completely ignore it and just return the cached value.
*
* This can be the case for example when an importer is done parsing a text
* file into an internal representation and the original data are no longer
* needed (and, for example, other files need to be loaded and they could
* repurpose the unused memory).
*/
Close
};
/** @debugoperatorenum{InputFileCallbackPolicy} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, InputFileCallbackPolicy value);
}
#endif

2
src/Magnum/Magnum.h

@ -697,6 +697,8 @@ template<class T> class Array1D;
template<class T> class Array2D;
template<class T> class Array3D;
enum class InputFileCallbackPolicy: UnsignedByte;
template<UnsignedInt> class Image;
typedef Image<1> Image1D;
typedef Image<2> Image2D;

1
src/Magnum/Test/CMakeLists.txt

@ -24,6 +24,7 @@
#
corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum)
corrade_add_test(FileCallbackTest FileCallbackTest.cpp LIBRARIES Magnum)
corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum)

52
src/Magnum/Test/FileCallbackTest.cpp

@ -0,0 +1,52 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/FileCallback.h"
namespace Magnum { namespace Test { namespace {
struct FileCallbackTest: TestSuite::Tester {
explicit FileCallbackTest();
void debugInputFileCallbackPolicy();
};
FileCallbackTest::FileCallbackTest() {
addTests({&FileCallbackTest::debugInputFileCallbackPolicy});
}
void FileCallbackTest::debugInputFileCallbackPolicy() {
std::ostringstream out;
Debug{&out} << InputFileCallbackPolicy::Close << InputFileCallbackPolicy(0xf0);
CORRADE_COMPARE(out.str(), "InputFileCallbackPolicy::Close InputFileCallbackPolicy(0xf0)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Test::FileCallbackTest)

27
src/Magnum/Trade/AbstractImporter.cpp

@ -31,6 +31,7 @@
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Directory.h>
#include "Magnum/FileCallback.h"
#include "Magnum/Trade/AbstractMaterialData.h"
#include "Magnum/Trade/AnimationData.h"
#include "Magnum/Trade/CameraData.h"
@ -73,7 +74,7 @@ AbstractImporter::AbstractImporter(PluginManager::Manager<AbstractImporter>& man
AbstractImporter::AbstractImporter(PluginManager::AbstractManager& manager, const std::string& plugin): PluginManager::AbstractManagingPlugin<AbstractImporter>{manager, plugin} {}
void AbstractImporter::setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, ImporterFileCallbackPolicy, void*), void* const userData) {
void AbstractImporter::setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* const userData) {
CORRADE_ASSERT(!isOpened(), "Trade::AbstractImporter::setFileCallback(): can't be set while a file is opened", );
CORRADE_ASSERT(features() & (Feature::FileCallback|Feature::OpenData), "Trade::AbstractImporter::setFileCallback(): importer supports neither loading from data nor via callbacks, callbacks can't be used", );
@ -82,7 +83,7 @@ void AbstractImporter::setFileCallback(Containers::Optional<Containers::ArrayVie
doSetFileCallback(callback, userData);
}
void AbstractImporter::doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, void*), void*) {}
void AbstractImporter::doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*), void*) {}
bool AbstractImporter::openData(Containers::ArrayView<const char> data) {
CORRADE_ASSERT(features() & Feature::OpenData,
@ -135,13 +136,13 @@ bool AbstractImporter::openFile(const std::string& filename) {
file loading to the default implementation (callback used in the
base doOpenFile() implementation, because this branch is never
taken in that case) */
const Containers::Optional<Containers::ArrayView<const char>> data = _fileCallback(filename, ImporterFileCallbackPolicy::LoadTemporary, _fileCallbackUserData);
const Containers::Optional<Containers::ArrayView<const char>> data = _fileCallback(filename, InputFileCallbackPolicy::LoadTemporary, _fileCallbackUserData);
if(!data) {
Error() << "Trade::AbstractImporter::openFile(): cannot open file" << filename;
return isOpened();
}
doOpenData(*data);
_fileCallback(filename, ImporterFileCallbackPolicy::Close, _fileCallbackUserData);
_fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData);
/* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
@ -155,13 +156,13 @@ void AbstractImporter::doOpenFile(const std::string& filename) {
/* If callbacks are set, use them. This is the same implementation as in
openFile(), see the comment there for details. */
if(_fileCallback) {
const Containers::Optional<Containers::ArrayView<const char>> data = _fileCallback(filename, ImporterFileCallbackPolicy::LoadTemporary, _fileCallbackUserData);
const Containers::Optional<Containers::ArrayView<const char>> data = _fileCallback(filename, InputFileCallbackPolicy::LoadTemporary, _fileCallbackUserData);
if(!data) {
Error() << "Trade::AbstractImporter::openFile(): cannot open file" << filename;
return;
}
doOpenData(*data);
_fileCallback(filename, ImporterFileCallbackPolicy::Close, _fileCallbackUserData);
_fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData);
/* Otherwise open the file directly */
} else {
@ -632,18 +633,4 @@ Debug& operator<<(Debug& debug, const AbstractImporter::Features value) {
AbstractImporter::Feature::FileCallback});
}
Debug& operator<<(Debug& debug, const ImporterFileCallbackPolicy value) {
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case ImporterFileCallbackPolicy::v: return debug << "Trade::ImporterFileCallbackPolicy::" #v;
_c(LoadTemporary)
_c(LoadPernament)
_c(Close)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "Trade::ImporterFileCallbackPolicy(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
}}

89
src/Magnum/Trade/AbstractImporter.h

@ -38,59 +38,18 @@
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Containers/PointerStl.h>
#include "Magnum/FileCallback.h"
#endif
namespace Magnum { namespace Trade {
/**
@brief Importer file loading callback policy
@see @ref AbstractImporter::setFileCallback(),
@ref Trade-AbstractImporter-usage-callbacks
*/
enum class ImporterFileCallbackPolicy: UnsignedByte {
/**
* The requested file is used only during a call of given function and the
* memory view is not referenced anymore once the function exits.
*
* This can be the case for example when importing image data using
* @ref AbstractImporter::image2D() --- imported data are copied into the
* returned @ref ImageData2D object and the original file is not needed
* anymore. Note, however, that this might not be the case for all
* importers --- see documentation of a particular plugin for concrete
* info.
*/
LoadTemporary,
/**
* The requested file may be used for loading most or all data in the next
* steps, so the importer expects the memory view to be valid for as long
* as data import functions are called on it, but at most until the
* importer is destroyed, @ref AbstractImporter::close() is called or
* another file is opened.
*
* This can be the case for example when importing mesh data using
* @ref AbstractImporter::mesh3D() --- all vertex data might be combined in
* a single binary file and each mesh occupies only a portion of it. Note,
* however, that this might not be the case for all importers --- see
* documentation of a particular plugin for concrete info.
*/
LoadPernament,
/**
* A file that has been previously loaded by this callback can be closed
* now (and its memory freed). This is just a hint, it's not *required* for
* the callback to close it. This policy is also only ever called with a
* file that was previously opened with the same callback, so it's possible
* to completely ignore it and just return the cached value.
*
* This can be the case for example when an importer is done parsing a text
* file into an internal representation and the original data are no longer
* needed (and, for example, other files need to be loaded and they could
* repurpose the unused memory).
#ifdef MAGNUM_BUILD_DEPRECATED
/** @brief @copybrief InputFileCallbackPolicy
* @deprecated Use @ref InputFileCallbackPolicy instead.
*/
Close
};
typedef CORRADE_DEPRECATED("use InputFileCallbackPolicy instead") InputFileCallbackPolicy ImporterFileCallbackPolicy;
#endif
/**
@brief Base for importer plugins
@ -109,7 +68,7 @@ like this, completely with all error handling:
See @ref plugins for more information about general plugin usage and
`*Importer` classes in the @ref Trade namespace for available importer plugins.
@subsection Trade-AbstractImporter-usage-callbacks Loading data from memory
@subsection Trade-AbstractImporter-usage-callbacks Loading data from memory, using file callbacks
Besides loading data directly from the filesystem using @ref openFile() like
shown above, it's possible to use @ref openData() to import data from memory.
@ -120,7 +79,7 @@ Complex scene files often reference other files such as images and in that case
you may want to intercept those references and load them in a custom way as
well. For importers that advertise support for this with @ref Feature::FileCallback
this is done by specifying a file loading callback using @ref setFileCallback().
The callback gets a filename, @ref ImporterFileCallbackPolicy and an user
The callback gets a filename, @ref InputFileCallbackPolicy and an user
pointer as parameters; returns a non-owning view on the loaded data or a
@ref Corrade::Containers::NullOpt "Containers::NullOpt" to indicate the file
loading failed. For example, loading a scene from memory-mapped files could
@ -311,7 +270,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*
* @see @ref Trade-AbstractImporter-usage-callbacks
*/
auto fileCallback() const -> Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, void*) { return _fileCallback; }
auto fileCallback() const -> Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) { return _fileCallback; }
/**
* @brief File opening callback user data
@ -328,7 +287,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* callback. Besides that, all external files referenced by the
* top-level file will be loaded through the callback function as well,
* usually on demand. The callback function gets a filename,
* @ref ImporterFileCallbackPolicy and the @p userData pointer as input
* @ref InputFileCallbackPolicy and the @p userData pointer as input
* and returns a non-owning view on the loaded data as output or a
* @ref Corrade::Containers::NullOpt if loading failed --- because
* empty files might also be valid in some circumstances, @cpp nullptr @ce
@ -338,11 +297,11 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* supports at least @ref Feature::OpenData, a file opened through
* @ref openFile() will be internally loaded through the provided
* callback and then passed to @ref openData(). First the file is
* loaded with @ref ImporterFileCallbackPolicy::LoadTemporary passed to
* loaded with @ref InputFileCallbackPolicy::LoadTemporary passed to
* the callback, then the returned memory view is passed to
* @ref openData() (sidestepping the potential @ref openFile()
* implementation of that particular importer) and after that the
* callback is called again with @ref ImporterFileCallbackPolicy::Close
* callback is called again with @ref InputFileCallbackPolicy::Close
* because the semantics of @ref openData() don't require the data to
* be alive after. In case you need a different behavior, use
* @ref openData() directly.
@ -355,9 +314,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* It's expected that this function is called *before* a file is
* opened. It's also expected that the loaded data are kept in scope
* for as long as the importer needs them, based on the value of
* @ref ImporterFileCallbackPolicy. Documentation of particular
* importers provides more information about the expected callback
* behavior.
* @ref InputFileCallbackPolicy. Documentation of particular importers
* provides more information about the expected callback behavior.
*
* Following is an example of setting up a file loading callback for
* fetching compiled-in resources from @ref Corrade::Utility::Resource.
@ -368,7 +326,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*
* @see @ref Trade-AbstractImporter-usage-callbacks
*/
void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, ImporterFileCallbackPolicy, void*), void* userData = nullptr);
void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData = nullptr);
/**
* @brief Set file opening callback
@ -382,7 +340,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @see @ref Trade-AbstractImporter-usage-callbacks
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, ImporterFileCallbackPolicy, T&), T& userData);
template<class T> void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, T&), T& userData);
#else
/* Otherwise the user would be forced to use the + operator to convert
a lambda to a function pointer and (besides being weird and
@ -852,7 +810,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* and user data pointer are available through @ref fileCallback() and
* @ref fileCallbackUserData().
*/
virtual void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, ImporterFileCallbackPolicy, void*), void* userData);
virtual void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData);
/** @brief Implementation for @ref isOpened() */
virtual bool doIsOpened() const = 0;
@ -1189,7 +1147,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
virtual const void* doImporterState() const;
private:
Containers::Optional<Containers::ArrayView<const char>>(*_fileCallback)(const std::string&, ImporterFileCallbackPolicy, void*){};
Containers::Optional<Containers::ArrayView<const char>>(*_fileCallback)(const std::string&, InputFileCallbackPolicy, void*){};
void* _fileCallbackUserData{};
/* Used by the templated version only */
@ -1203,13 +1161,13 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
template<class Callback, class T> void AbstractImporter::setFileCallback(Callback callback, T& userData) {
/* Don't try to wrap a null function pointer. Need to cast first because
MSVC (even 2017) can't apply ! to a lambda. Ugh. */
const auto callbackPtr = static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, T&)>(callback);
const auto callbackPtr = static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(callback);
if(!callbackPtr) return setFileCallback(nullptr);
_fileCallbackTemplate = { reinterpret_cast<void(*)()>(callbackPtr), &userData };
setFileCallback([](const std::string& filename, const ImporterFileCallbackPolicy flags, void* const userData) {
setFileCallback([](const std::string& filename, const InputFileCallbackPolicy flags, void* const userData) {
auto& s = *reinterpret_cast<FileCallbackTemplate*>(userData);
return reinterpret_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast<T*>(s.userData));
return reinterpret_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast<T*>(s.userData));
}, &_fileCallbackTemplate);
}
#endif
@ -1222,9 +1180,6 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, AbstractImporter::Feature va
/** @debugoperatorclassenum{AbstractImporter,AbstractImporter::Features} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, AbstractImporter::Features value);
/** @debugoperatorenum{ImporterFileCallbackPolicy} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ImporterFileCallbackPolicy value);
}}
#endif

50
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -29,6 +29,7 @@
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/Directory.h>
#include "Magnum/FileCallback.h"
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/AnimationData.h"
#include "Magnum/Trade/CameraData.h"
@ -240,7 +241,6 @@ class AbstractImporterTest: public TestSuite::Tester {
void debugFeature();
void debugFeatures();
void debugFileCallbackPolicy();
};
AbstractImporterTest::AbstractImporterTest() {
@ -433,8 +433,7 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::importerStateNoFile,
&AbstractImporterTest::debugFeature,
&AbstractImporterTest::debugFeatures,
&AbstractImporterTest::debugFileCallbackPolicy});
&AbstractImporterTest::debugFeatures});
}
void AbstractImporterTest::construct() {
@ -593,14 +592,14 @@ void AbstractImporterTest::setFileCallback() {
Features doFeatures() const override { return Feature::OpenData|Feature::FileCallback; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, void*), void* userData) override {
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*), void* userData) override {
*static_cast<int*>(userData) = 1337;
}
};
int a = 0;
Importer importer;
auto lambda = [](const std::string&, ImporterFileCallbackPolicy, void*) {
auto lambda = [](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
};
importer.setFileCallback(lambda, &a);
@ -614,7 +613,7 @@ void AbstractImporterTest::setFileCallbackTemplate() {
Features doFeatures() const override { return Feature::OpenData|Feature::FileCallback; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, void*), void*) override {
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*), void*) override {
called = true;
}
@ -622,7 +621,7 @@ void AbstractImporterTest::setFileCallbackTemplate() {
};
int a = 0;
auto lambda = [](const std::string&, ImporterFileCallbackPolicy, int&) {
auto lambda = [](const std::string&, InputFileCallbackPolicy, int&) {
return Containers::Optional<Containers::ArrayView<const char>>{};
};
Importer importer;
@ -632,7 +631,7 @@ void AbstractImporterTest::setFileCallbackTemplate() {
CORRADE_VERIFY(importer.called);
/* The data pointers should be wrapped, thus not the same */
CORRADE_VERIFY(reinterpret_cast<void(*)()>(importer.fileCallback()) != reinterpret_cast<void(*)()>(static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, int&)>(lambda)));
CORRADE_VERIFY(reinterpret_cast<void(*)()>(importer.fileCallback()) != reinterpret_cast<void(*)()>(static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, int&)>(lambda)));
CORRADE_VERIFY(importer.fileCallbackUserData() != &a);
}
@ -641,7 +640,7 @@ void AbstractImporterTest::setFileCallbackTemplateNull() {
Features doFeatures() const override { return Feature::OpenData|Feature::FileCallback; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, ImporterFileCallbackPolicy, void*), void* userData) override {
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData) override {
called = !callback && !userData;
}
@ -650,7 +649,7 @@ void AbstractImporterTest::setFileCallbackTemplateNull() {
int a = 0;
Importer importer;
importer.setFileCallback(static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, ImporterFileCallbackPolicy, int&)>(nullptr), a);
importer.setFileCallback(static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, int&)>(nullptr), a);
CORRADE_VERIFY(!importer.fileCallback());
CORRADE_VERIFY(!importer.fileCallbackUserData());
CORRADE_VERIFY(importer.called);
@ -667,7 +666,7 @@ void AbstractImporterTest::setFileCallbackFileOpened() {
Error redirectError{&out};
Importer importer;
importer.setFileCallback([](const std::string&, ImporterFileCallbackPolicy, void*) {
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
});
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::setFileCallback(): can't be set while a file is opened\n");
@ -681,7 +680,7 @@ void AbstractImporterTest::setFileCallbackNotImplemented() {
};
int a;
auto lambda = [](const std::string&, ImporterFileCallbackPolicy, void*) {
auto lambda = [](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
};
Importer importer;
@ -703,7 +702,7 @@ void AbstractImporterTest::setFileCallbackNotSupported() {
int a;
Importer importer;
importer.setFileCallback([](const std::string&, ImporterFileCallbackPolicy, void*) {
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
}, &a);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::setFileCallback(): importer supports neither loading from data nor via callbacks, callbacks can't be used\n");
@ -731,7 +730,7 @@ void AbstractImporterTest::setFileCallbackOpenFileDirectly() {
bool calledNotSureWhy = false;
Importer importer;
importer.setFileCallback([](const std::string&, ImporterFileCallbackPolicy, bool& calledNotSureWhy) -> Containers::Optional<Containers::ArrayView<const char>> {
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, bool& calledNotSureWhy) -> Containers::Optional<Containers::ArrayView<const char>> {
calledNotSureWhy = true;
return {};
}, calledNotSureWhy);
@ -767,13 +766,13 @@ void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementation() {
bool calledNotSureWhy = false;
} state;
Importer importer;
importer.setFileCallback([](const std::string& filename, ImporterFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == ImporterFileCallbackPolicy::LoadTemporary) {
importer.setFileCallback([](const std::string& filename, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::arrayView(&state.data, 1);
}
if(filename == "file.dat" && policy == ImporterFileCallbackPolicy::Close) {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
@ -804,7 +803,7 @@ void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationFaile
};
Importer importer;
importer.setFileCallback([](const std::string&, ImporterFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
return {};
});
@ -841,13 +840,13 @@ void AbstractImporterTest::setFileCallbackOpenFileAsData() {
bool calledNotSureWhy = false;
} state;
Importer importer;
importer.setFileCallback([](const std::string& filename, ImporterFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == ImporterFileCallbackPolicy::LoadTemporary) {
importer.setFileCallback([](const std::string& filename, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::arrayView(&state.data, 1);
}
if(filename == "file.dat" && policy == ImporterFileCallbackPolicy::Close) {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
@ -877,7 +876,7 @@ void AbstractImporterTest::setFileCallbackOpenFileAsDataFailed() {
};
Importer importer;
importer.setFileCallback([](const std::string&, ImporterFileCallbackPolicy, void*) {
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
});
@ -3271,13 +3270,6 @@ void AbstractImporterTest::debugFeatures() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::Feature::OpenData|Trade::AbstractImporter::Feature::OpenState Trade::AbstractImporter::Features{}\n");
}
void AbstractImporterTest::debugFileCallbackPolicy() {
std::ostringstream out;
Debug{&out} << ImporterFileCallbackPolicy::Close << ImporterFileCallbackPolicy(0xf0);
CORRADE_COMPARE(out.str(), "Trade::ImporterFileCallbackPolicy::Close Trade::ImporterFileCallbackPolicy(0xf0)\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::Trade::Test::AbstractImporterTest)

10
src/Magnum/Trade/Trade.h

@ -31,14 +31,20 @@
#include "Magnum/Types.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include "Magnum/Magnum.h"
#endif
namespace Magnum { namespace Trade {
#ifndef DOXYGEN_GENERATING_OUTPUT
class AbstractImageConverter;
enum class ImporterFileCallbackPolicy: UnsignedByte;
class AbstractImporter;
#ifdef MAGNUM_BUILD_DEPRECATED
typedef CORRADE_DEPRECATED("use InputFileCallbackPolicy instead") InputFileCallbackPolicy ImporterFileCallbackPolicy;
#endif
enum class MaterialType: UnsignedByte;
enum class MaterialAlphaMode: UnsignedByte;
class AbstractMaterialData;

6
src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp

@ -51,7 +51,7 @@ struct AnyImageImporterTest: TestSuite::Tester {
PluginManager::Manager<AbstractImporter> _manager{"nonexistent"};
};
Containers::Optional<Containers::ArrayView<const char>> fileCallback(const std::string& filename, Trade::ImporterFileCallbackPolicy, Containers::Array<char>& storage) {
Containers::Optional<Containers::ArrayView<const char>> fileCallback(const std::string& filename, InputFileCallbackPolicy, Containers::Array<char>& storage) {
storage = Utility::Directory::read(filename);
return Containers::ArrayView<const char>{storage};
}
@ -59,7 +59,7 @@ Containers::Optional<Containers::ArrayView<const char>> fileCallback(const std::
constexpr struct {
const char* name;
const char* filename;
Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, Trade::ImporterFileCallbackPolicy, Containers::Array<char>&);
Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, Containers::Array<char>&);
} LoadData[]{
{"TGA", TGA_FILE, nullptr},
{"TGA data", TGA_FILE, fileCallback}
@ -68,7 +68,7 @@ constexpr struct {
constexpr struct {
const char* name;
const char* filename;
Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, Trade::ImporterFileCallbackPolicy, Containers::Array<char>&);
Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, Containers::Array<char>&);
const char* plugin;
} DetectData[]{
{"PNG", "rgb.png", nullptr, "PngImporter"},

Loading…
Cancel
Save