Browse Source

ShaderTools: port away from std::pair.

Here the benefit is especially clear -- as Containers::Pair is trivially
copyable with trivial types, all growable arrays can make use of
std::realloc() while with the STL variant a silly constructor, copy
constructor, destructor had to be used.

Additionally, we no longer need to take explicit care of libc++ and MSVC
STL where returning a std::pair<bool, Containers::String> as

    return {{}, Containers::String{..., <deleter>}};

would caused an unnecessary copy instead of a move, losing the custom
deleter in the process. Yay!

There's a <Corrade/Containers/PairStl.h> include for backwards
compatibility purposes, but obviously it would only work for the return
type of validate*() and cases where an initializer list was passed to a
list-of-pairs-taking functions, and not a concretely typed ArrayView.
Those functions were though mostly the linker API which isn't
implemented by any plugin yet, so it shouldn't be *that* breaking to
users. Neverteless, I'm trying to do this breaking change rather sooner
than later to prevent pain further down the road when the Vulkan APIs
and SPIR-V pipeline gets widely used.
pull/557/head
Vladimír Vondruš 4 years ago
parent
commit
7f4500d9e0
  1. 14
      doc/snippets/MagnumShaderTools.cpp
  2. 85
      src/Magnum/ShaderTools/AbstractConverter.cpp
  3. 45
      src/Magnum/ShaderTools/AbstractConverter.h
  4. 215
      src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp
  5. 17
      src/Magnum/ShaderTools/shaderconverter.cpp
  6. 24
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp
  7. 6
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.h
  8. 49
      src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp

14
doc/snippets/MagnumShaderTools.cpp

@ -27,6 +27,7 @@
#include <unordered_map> #include <unordered_map>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop when file callbacks are <string>-free */ #include <Corrade/Containers/StringStl.h> /** @todo drop when file callbacks are <string>-free */
#include <Corrade/Utility/Macros.h> /* CORRADE_LINE_STRING */ #include <Corrade/Utility/Macros.h> /* CORRADE_LINE_STRING */
@ -47,14 +48,13 @@ PluginManager::Manager<ShaderTools::AbstractConverter> manager;
Containers::Pointer<ShaderTools::AbstractConverter> converter = Containers::Pointer<ShaderTools::AbstractConverter> converter =
manager.loadAndInstantiate("AnyShaderConverter"); manager.loadAndInstantiate("AnyShaderConverter");
bool valid; Containers::Pair<bool, Containers::String> validMessage;
Containers::String message; if(converter) validMessage =
if(converter) std::tie(valid, message) =
converter->validateFile(ShaderTools::Stage::Unspecified, "file.spv"); converter->validateFile(ShaderTools::Stage::Unspecified, "file.spv");
if(!converter || !valid) if(!converter || !validMessage.first())
Error{} << "Validation failed:" << message; Error{} << "Validation failed:" << validMessage.second();
else if(!message.isEmpty()) else if(!validMessage.second().isEmpty())
Warning{} << "Validation succeeded with warnings:" << message; Warning{} << "Validation succeeded with warnings:" << validMessage.second();
else else
Debug{} << "Validation passed"; Debug{} << "Validation passed";
/* [AbstractConverter-usage-validation] */ /* [AbstractConverter-usage-validation] */

85
src/Magnum/ShaderTools/AbstractConverter.cpp

@ -29,6 +29,7 @@
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.hpp> #include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once file callbacks are <string>-free */ #include <Corrade/Containers/StringStl.h> /** @todo remove once file callbacks are <string>-free */
#include <Corrade/PluginManager/Manager.hpp> #include <Corrade/PluginManager/Manager.hpp>
@ -151,17 +152,17 @@ void AbstractConverter::setOutputFormat(const Format format) {
return setOutputFormat(format, {}); return setOutputFormat(format, {});
} }
void AbstractConverter::setDefinitions(const Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) { void AbstractConverter::setDefinitions(const Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
CORRADE_ASSERT(features() & ConverterFeature::Preprocess, CORRADE_ASSERT(features() & ConverterFeature::Preprocess,
"ShaderTools::AbstractConverter::setDefinitions(): feature not supported", ); "ShaderTools::AbstractConverter::setDefinitions(): feature not supported", );
doSetDefinitions(definitions); doSetDefinitions(definitions);
} }
void AbstractConverter::setDefinitions(std::initializer_list<std::pair<Containers::StringView, Containers::StringView>> definitions) { void AbstractConverter::setDefinitions(std::initializer_list<Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
return setDefinitions(Containers::arrayView(definitions)); return setDefinitions(Containers::arrayView(definitions));
} }
void AbstractConverter::doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>>) { void AbstractConverter::doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDefinitions(): feature advertised but not implemented", ); CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDefinitions(): feature advertised but not implemented", );
} }
@ -185,30 +186,30 @@ void AbstractConverter::doSetDebugInfoLevel(Containers::StringView) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDebugInfoLevel(): feature advertised but not implemented", ); CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDebugInfoLevel(): feature advertised but not implemented", );
} }
std::pair<bool, Containers::String> AbstractConverter::validateData(const Stage stage, const Containers::ArrayView<const void> data) { Containers::Pair<bool, Containers::String> AbstractConverter::validateData(const Stage stage, const Containers::ArrayView<const void> data) {
CORRADE_ASSERT(features() & ConverterFeature::ValidateData, CORRADE_ASSERT(features() & ConverterFeature::ValidateData,
"ShaderTools::AbstractConverter::validateData(): feature not supported", {}); "ShaderTools::AbstractConverter::validateData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
"ShaderTools::AbstractConverter::validateData(): PreprocessOnly is not allowed in combination with validation", {}); "ShaderTools::AbstractConverter::validateData(): PreprocessOnly is not allowed in combination with validation", {});
/* Cast to a non-void type for more convenience */ /* Cast to a non-void type for more convenience */
std::pair<bool, Containers::String> out = doValidateData(stage, Containers::arrayCast<const char>(data)); Containers::Pair<bool, Containers::String> out = doValidateData(stage, Containers::arrayCast<const char>(data));
CORRADE_ASSERT(out.second.isSmall() || !out.second.deleter(), CORRADE_ASSERT(out.second().isSmall() || !out.second().deleter(),
"ShaderTools::AbstractConverter::validateData(): implementation is not allowed to use a custom String deleter", {}); "ShaderTools::AbstractConverter::validateData(): implementation is not allowed to use a custom String deleter", {});
return out; return out;
} }
std::pair<bool, Containers::String> AbstractConverter::doValidateData(Stage, Containers::ArrayView<const char>) { Containers::Pair<bool, Containers::String> AbstractConverter::doValidateData(Stage, Containers::ArrayView<const char>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::validateData(): feature advertised but not implemented", {}); CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::validateData(): feature advertised but not implemented", {});
} }
std::pair<bool, Containers::String> AbstractConverter::validateFile(const Stage stage, const Containers::StringView filename) { Containers::Pair<bool, Containers::String> AbstractConverter::validateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_ASSERT(features() & (ConverterFeature::ValidateFile|ConverterFeature::ValidateData), CORRADE_ASSERT(features() & (ConverterFeature::ValidateFile|ConverterFeature::ValidateData),
"ShaderTools::AbstractConverter::validateFile(): feature not supported", {}); "ShaderTools::AbstractConverter::validateFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
"ShaderTools::AbstractConverter::validateFile(): PreprocessOnly is not allowed in combination with validation", {}); "ShaderTools::AbstractConverter::validateFile(): PreprocessOnly is not allowed in combination with validation", {});
std::pair<bool, Containers::String> out; Containers::Pair<bool, Containers::String> out;
/* If input file callbacks are not set or the converter supports handling /* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */ them directly, call into the implementation */
@ -240,12 +241,12 @@ std::pair<bool, Containers::String> AbstractConverter::validateFile(const Stage
/* Shouldn't get here, the assert is fired already in setFileCallback() */ /* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
CORRADE_ASSERT(out.second.isSmall() || !out.second.deleter(), CORRADE_ASSERT(out.second().isSmall() || !out.second().deleter(),
"ShaderTools::AbstractConverter::validateFile(): implementation is not allowed to use a custom String deleter", {}); "ShaderTools::AbstractConverter::validateFile(): implementation is not allowed to use a custom String deleter", {});
return out; return out;
} }
std::pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stage stage, const Containers::StringView filename) { Containers::Pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_ASSERT(features() >= ConverterFeature::ValidateData, "ShaderTools::AbstractConverter::validateFile(): feature advertised but not implemented", {}); CORRADE_ASSERT(features() >= ConverterFeature::ValidateData, "ShaderTools::AbstractConverter::validateFile(): feature advertised but not implemented", {});
/* If callbacks are set, use them. This is the same implementation as in /* If callbacks are set, use them. This is the same implementation as in
@ -256,7 +257,7 @@ std::pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stag
Error{} << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename; Error{} << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename;
return {}; return {};
} }
std::pair<bool, Containers::String> out = doValidateData(stage, *data); Containers::Pair<bool, Containers::String> out = doValidateData(stage, *data);
_inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData); _inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
return out; return out;
@ -465,7 +466,7 @@ Containers::Optional<Containers::Array<char>>
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
AbstractConverter::linkDataToData(const Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data) { AbstractConverter::linkDataToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData, CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToData(): feature not supported", {}); "ShaderTools::AbstractConverter::linkDataToData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -474,7 +475,7 @@ AbstractConverter::linkDataToData(const Containers::ArrayView<const std::pair<St
"ShaderTools::AbstractConverter::linkDataToData(): no data passed", {}); "ShaderTools::AbstractConverter::linkDataToData(): no data passed", {});
/* Cast to a non-void type for more convenience */ /* Cast to a non-void type for more convenience */
Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data)); Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const Containers::Pair<Stage, Containers::ArrayView<const char>>>(data));
CORRADE_ASSERT(!out || !out->deleter(), CORRADE_ASSERT(!out || !out->deleter(),
"ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter", {}); "ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter", {});
@ -491,15 +492,15 @@ Containers::Optional<Containers::Array<char>>
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
AbstractConverter::linkDataToData(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data) { AbstractConverter::linkDataToData(const std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data) {
return linkDataToData(Containers::arrayView(data)); return linkDataToData(Containers::arrayView(data));
} }
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) { Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented", {}); CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented", {});
} }
bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) { bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData, CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToFile(): feature not supported", {}); "ShaderTools::AbstractConverter::linkDataToFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -510,7 +511,7 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pa
/** @todo this needs expansion once output callbacks are supported as well */ /** @todo this needs expansion once output callbacks are supported as well */
/* Cast to a non-void type for more convenience */ /* Cast to a non-void type for more convenience */
const Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data)); const Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const Containers::Pair<Stage, Containers::ArrayView<const char>>>(data));
if(!out) return false; if(!out) return false;
if(!Utility::Path::write(filename, *out)) { if(!Utility::Path::write(filename, *out)) {
@ -521,22 +522,22 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pa
return true; return true;
} }
bool AbstractConverter::linkDataToFile(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) { bool AbstractConverter::linkDataToFile(const std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) {
return linkDataToFile(Containers::arrayView(data), filename); return linkDataToFile(Containers::arrayView(data), filename);
} }
Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) { Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()}; Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()};
/* First load all files. Remember how many of these succeeded so we can /* First load all files. Remember how many of these succeeded so we can
close them again after */ close them again after */
std::size_t i; std::size_t i;
for(i = 0; i != filenames.size(); ++i) { for(i = 0; i != filenames.size(); ++i) {
const Containers::Optional<Containers::ArrayView<const char>> contents = _inputFileCallback(filenames[i].second, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData); const Containers::Optional<Containers::ArrayView<const char>> contents = _inputFileCallback(filenames[i].second(), InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!contents) break; if(!contents) break;
data[i].first = filenames[i].first; data[i].first() = filenames[i].first();
data[i].second = *contents; data[i].second() = *contents;
} }
/* If all input files loaded successfully, process */ /* If all input files loaded successfully, process */
@ -545,13 +546,13 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataU
/* Close again all input files that loaded successfully */ /* Close again all input files that loaded successfully */
for(std::size_t ii = 0; ii != i; ++ii) for(std::size_t ii = 0; ii != i; ++ii)
_inputFileCallback(filenames[ii].second, InputFileCallbackPolicy::Close, _inputFileCallbackUserData); _inputFileCallback(filenames[ii].second(), InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
/* Now that we have cleaned up correctly, it's time print the error message /* Now that we have cleaned up correctly, it's time print the error message
if something didn't go well. IN this case doLinkDataToData() was not if something didn't go well. IN this case doLinkDataToData() was not
called at all. */ called at all. */
if(i != filenames.size()) { if(i != filenames.size()) {
Error{} << prefix << "cannot open file" << filenames[i].second; Error{} << prefix << "cannot open file" << filenames[i].second();
return {}; return {};
} }
@ -560,7 +561,7 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataU
return out; return out;
} }
bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) { bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
CORRADE_ASSERT(features() & (ConverterFeature::LinkFile|ConverterFeature::LinkData), CORRADE_ASSERT(features() & (ConverterFeature::LinkFile|ConverterFeature::LinkData),
"ShaderTools::AbstractConverter::linkFilesToFile(): feature not supported", {}); "ShaderTools::AbstractConverter::linkFilesToFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -603,11 +604,11 @@ bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const std::p
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
bool AbstractConverter::linkFilesToFile(const std::initializer_list<std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) { bool AbstractConverter::linkFilesToFile(const std::initializer_list<Containers::Pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
return linkFilesToFile(Containers::arrayView(from), to); return linkFilesToFile(Containers::arrayView(from), to);
} }
bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) { bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData, "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented", {}); CORRADE_ASSERT(features() >= ConverterFeature::LinkData, "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented", {});
/** @todo this needs expansion once output callbacks are supported as well */ /** @todo this needs expansion once output callbacks are supported as well */
@ -622,9 +623,9 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std:
} else { } else {
Containers::Array<Containers::Array<char>> fileData{from.size()}; Containers::Array<Containers::Array<char>> fileData{from.size()};
for(std::size_t i = 0; i != from.size(); ++i) { for(std::size_t i = 0; i != from.size(); ++i) {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(from[i].second); Containers::Optional<Containers::Array<char>> data = Utility::Path::read(from[i].second());
if(!data) { if(!data) {
Error() << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot open file" << from[i].second; Error() << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot open file" << from[i].second();
return {}; return {};
} }
@ -633,10 +634,10 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std:
/** @todo merge the allocations once we have an ArrayTuple (actually, /** @todo merge the allocations once we have an ArrayTuple (actually,
ideally it would merge also the nested allocations, how?) */ ideally it would merge also the nested allocations, how?) */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, from.size()}; Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, from.size()};
for(std::size_t i = 0; i != from.size(); ++i) { for(std::size_t i = 0; i != from.size(); ++i) {
data[i].first = from[i].first; data[i].first() = from[i].first();
data[i].second = fileData[i]; data[i].second() = fileData[i];
} }
out = doLinkDataToData(data); out = doLinkDataToData(data);
@ -657,7 +658,7 @@ Containers::Optional<Containers::Array<char>>
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
AbstractConverter::linkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) { AbstractConverter::linkFilesToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData, CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkFilesToData(): feature not supported", {}); "ShaderTools::AbstractConverter::linkFilesToData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -705,11 +706,11 @@ Containers::Optional<Containers::Array<char>>
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
AbstractConverter::linkFilesToData(const std::initializer_list<std::pair<Stage, Containers::StringView>> filenames) { AbstractConverter::linkFilesToData(const std::initializer_list<Containers::Pair<Stage, Containers::StringView>> filenames) {
return linkFilesToData(Containers::arrayView(filenames)); return linkFilesToData(Containers::arrayView(filenames));
} }
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) { Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
/* If callbacks are set, use them. This is the same implementation as in /* If callbacks are set, use them. This is the same implementation as in
linkFilesToFile(), see the comment there for details. */ linkFilesToFile(), see the comment there for details. */
if(_inputFileCallback) { if(_inputFileCallback) {
@ -719,9 +720,9 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToDa
} else { } else {
Containers::Array<Containers::Array<char>> fileData{filenames.size()}; Containers::Array<Containers::Array<char>> fileData{filenames.size()};
for(std::size_t i = 0; i != filenames.size(); ++i) { for(std::size_t i = 0; i != filenames.size(); ++i) {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filenames[i].second); Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filenames[i].second());
if(!data) { if(!data) {
Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << filenames[i].second; Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << filenames[i].second();
return {}; return {};
} }
@ -729,10 +730,10 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToDa
} }
/** @todo merge the allocations once we have an ArrayTuple */ /** @todo merge the allocations once we have an ArrayTuple */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()}; Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()};
for(std::size_t i = 0; i != filenames.size(); ++i) { for(std::size_t i = 0; i != filenames.size(); ++i) {
data[i].first = filenames[i].first; data[i].first() = filenames[i].first();
data[i].second = fileData[i]; data[i].second() = fileData[i];
} }
return doLinkDataToData(data); return doLinkDataToData(data);

45
src/Magnum/ShaderTools/AbstractConverter.h

@ -41,6 +41,13 @@
/* For *ToData() APIs that used to return just an Array before */ /* For *ToData() APIs that used to return just an Array before */
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
/* For validate*() that used to return a std::pair. Similar case is with
setDefinitions(), there a hope is that a std::initializer_list was used and
thus the type change won't break much code; lastly the link APIs that used
std::pair heavily are not implemented by any plugin yet so changing them
should be still fine. */
#include <Corrade/Containers/PairStl.h>
#include "Magnum/ShaderTools/Stage.h" #include "Magnum/ShaderTools/Stage.h"
#endif #endif
@ -720,10 +727,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* in @ref magnum-shaderconverter "magnum-shaderconverter". * in @ref magnum-shaderconverter "magnum-shaderconverter".
* @see @ref ConverterFlag::PreprocessOnly * @see @ref ConverterFlag::PreprocessOnly
*/ */
void setDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions); void setDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/** @overload */ /** @overload */
void setDefinitions(std::initializer_list<std::pair<Containers::StringView, Containers::StringView>> definitions); void setDefinitions(std::initializer_list<Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/** /**
* @brief Set optimization level * @brief Set optimization level
@ -778,7 +785,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* *
* @see @ref features(), @ref validateFile() * @see @ref features(), @ref validateFile()
*/ */
std::pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data); Containers::Pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data);
/** /**
* @brief Validate a shader * @brief Validate a shader
@ -799,7 +806,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @ref magnum-shaderconverter "magnum-shaderconverter". * @ref magnum-shaderconverter "magnum-shaderconverter".
* @see @ref features(), @ref validateData() * @see @ref features(), @ref validateData()
*/ */
std::pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename); Containers::Pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename);
/** /**
* @brief Convert shader data to a data * @brief Convert shader data to a data
@ -874,7 +881,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
linkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data); linkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data);
/** @overload */ /** @overload */
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) #if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT)
@ -882,7 +889,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
linkDataToData(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data); linkDataToData(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data);
/** /**
* @brief Link shader data together to a file * @brief Link shader data together to a file
@ -895,10 +902,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @see @ref features(), @ref linkFilesToFile(), * @see @ref features(), @ref linkFilesToFile(),
* @ref linkFilesToData(), @ref linkDataToData() * @ref linkFilesToData(), @ref linkDataToData()
*/ */
bool linkDataToFile(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename); bool linkDataToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
/** @overload */ /** @overload */
bool linkDataToFile(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename); bool linkDataToFile(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
/** /**
* @brief Link shader files together to a file * @brief Link shader files together to a file
@ -914,10 +921,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @see @ref features(), @ref linkFilesToData(), @ref linkDataToFile(), * @see @ref features(), @ref linkFilesToData(), @ref linkDataToFile(),
* @ref linkDataToData() * @ref linkDataToData()
*/ */
bool linkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to); bool linkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/** @overload */ /** @overload */
bool linkFilesToFile(std::initializer_list<std::pair<Stage, Containers::StringView>> from, Containers::StringView to); bool linkFilesToFile(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/** /**
* @brief Link shader files together to a data * @brief Link shader files together to a data
@ -935,7 +942,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
linkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames); linkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames);
/** @overload */ /** @overload */
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) #if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT)
@ -943,7 +950,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else #else
Implementation::OptionalButAlsoArray<char> Implementation::OptionalButAlsoArray<char>
#endif #endif
linkFilesToData(std::initializer_list<std::pair<Stage, Containers::StringView>> filenames); linkFilesToData(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> filenames);
protected: protected:
/** /**
@ -961,7 +968,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* is not supported --- instead, file is loaded though the callback and * is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doValidateData(). * data passed through to @ref doValidateData().
*/ */
virtual std::pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename); virtual Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename);
/** /**
* @brief Implementation for @ref convertFileToFile() * @brief Implementation for @ref convertFileToFile()
@ -1012,7 +1019,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* is not supported --- instead, file is loaded though the callback and * is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doLinkDataToData(). * data passed through to @ref doLinkDataToData().
*/ */
virtual bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to); virtual bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/** /**
* @brief Implementation for @ref linkFilesToData() * @brief Implementation for @ref linkFilesToData()
@ -1029,7 +1036,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* is not supported --- instead, file is loaded though the callback and * is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doConvertDataToData(). * data passed through to @ref doConvertDataToData().
*/ */
virtual Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames); virtual Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames);
private: private:
/** /**
@ -1100,7 +1107,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* Has to be implemented if @ref ConverterFeature::Preprocess is * Has to be implemented if @ref ConverterFeature::Preprocess is
* supported. This function isn't expected to fail. * supported. This function isn't expected to fail.
*/ */
virtual void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions); virtual void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/** /**
* @brief Implementation for @ref setOptimizationLevel() * @brief Implementation for @ref setOptimizationLevel()
@ -1136,7 +1143,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* order to accept any type, this function gets it cast to * order to accept any type, this function gets it cast to
* @cpp char @ce for more convenience. * @cpp char @ce for more convenience.
*/ */
virtual std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data); virtual Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data);
/* Used by convertFileToFile(), doConvertFileToFile(), /* Used by convertFileToFile(), doConvertFileToFile(),
convertFileToData() and doConvertFileToData() */ convertFileToData() and doConvertFileToData() */
@ -1154,7 +1161,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
/* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData() /* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData()
and doLinkFilesToData() */ and doLinkFilesToData() */
MAGNUM_SHADERTOOLS_LOCAL Containers::Optional<Containers::Array<char>> linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames); MAGNUM_SHADERTOOLS_LOCAL Containers::Optional<Containers::Array<char>> linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames);
/** /**
* @brief Implementation for @ref linkDataToData() * @brief Implementation for @ref linkDataToData()
@ -1164,7 +1171,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* order to accept any type, this function gets it cast to * order to accept any type, this function gets it cast to
* @cpp char @ce for more convenience. * @cpp char @ce for more convenience.
*/ */
virtual Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data); virtual Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data);
ConverterFlags _flags; ConverterFlags _flags;

215
src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp

@ -26,6 +26,7 @@
#include <sstream> #include <sstream>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once Debug is stream-free */ #include <Corrade/Containers/StringStl.h> /** @todo remove once Debug is stream-free */
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
@ -504,7 +505,7 @@ void AbstractConverterTest::setDefinitions() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) override { void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) override {
howManyIsThere = definitions.size(); howManyIsThere = definitions.size();
} }
@ -679,14 +680,14 @@ void AbstractConverterTest::validateData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override { Containers::Pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
return {data.size() == 5*4 && stage == Stage::MeshTask, "Yes, this is valid"}; return {data.size() == 5*4 && stage == Stage::MeshTask, "Yes, this is valid"};
} }
} converter; } converter;
std::pair<bool, Containers::String> out = converter.validateData(Stage::MeshTask, Containers::arrayView<UnsignedInt>({0x07230203, 99, 0xcafebabeu, 50, 0})); Containers::Pair<bool, Containers::String> out = converter.validateData(Stage::MeshTask, Containers::arrayView<UnsignedInt>({0x07230203, 99, 0xcafebabeu, 50, 0}));
CORRADE_VERIFY(out.first); CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second, "Yes, this is valid"); CORRADE_COMPARE(out.second(), "Yes, this is valid");
} }
void AbstractConverterTest::validateDataNotSupported() { void AbstractConverterTest::validateDataNotSupported() {
@ -759,15 +760,8 @@ void AbstractConverterTest::validateDataCustomStringDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(Stage, const Containers::ArrayView<const char>) override { Containers::Pair<bool, Containers::String> doValidateData(Stage, const Containers::ArrayView<const char>) override {
/* libc++ and MSVC STL is STUPID and doing return {{}, Containers::String{"", 0, [](char*, std::size_t){}}};
`return {{}, Containers::String{...}};`
will do a COPY, even though not needed. That then of course
discards the custom deleter and makes the test fail. Oh C++, do
I really have to reimplement even std::pair, FFS?! */
std::pair<bool, Containers::String> out;
out.second = Containers::String{"", 0, [](char*, std::size_t){}};
return out;
} }
} converter; } converter;
@ -785,14 +779,14 @@ void AbstractConverterTest::validateFile() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(const Stage stage, const Containers::StringView filename) override { Containers::Pair<bool, Containers::String> doValidateFile(const Stage stage, const Containers::StringView filename) override {
return {stage == Stage::Vertex && filename.size() == 8, "Yes, this is valid"}; return {stage == Stage::Vertex && filename.size() == 8, "Yes, this is valid"};
} }
} converter; } converter;
std::pair<bool, Containers::String> out = converter.validateFile(Stage::Vertex, "file.spv"); Containers::Pair<bool, Containers::String> out = converter.validateFile(Stage::Vertex, "file.spv");
CORRADE_VERIFY(out.first); CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second, "Yes, this is valid"); CORRADE_COMPARE(out.second(), "Yes, this is valid");
} }
void AbstractConverterTest::validateFileAsData() { void AbstractConverterTest::validateFileAsData() {
@ -803,14 +797,14 @@ void AbstractConverterTest::validateFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override { Containers::Pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
return {stage == Stage::Compute && data.size() == 5, "Yes, this is valid"}; return {stage == Stage::Compute && data.size() == 5, "Yes, this is valid"};
} }
} converter; } converter;
std::pair<bool, Containers::String> out = converter.validateFile(Stage::Compute, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")); Containers::Pair<bool, Containers::String> out = converter.validateFile(Stage::Compute, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat"));
CORRADE_VERIFY(out.first); CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second, "Yes, this is valid"); CORRADE_COMPARE(out.second(), "Yes, this is valid");
} }
void AbstractConverterTest::validateFileAsDataNotFound() { void AbstractConverterTest::validateFileAsDataNotFound() {
@ -821,7 +815,7 @@ void AbstractConverterTest::validateFileAsDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override { Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
@ -829,9 +823,9 @@ void AbstractConverterTest::validateFileAsDataNotFound() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
std::pair<bool, Containers::String> out2 = converter.validateFile({}, "nonexistent.bin"); Containers::Pair<bool, Containers::String> out2 = converter.validateFile({}, "nonexistent.bin");
CORRADE_VERIFY(!out2.first); CORRADE_VERIFY(!out2.first());
CORRADE_COMPARE(out2.second, ""); CORRADE_COMPARE(out2.second(), "");
/* There's an error message from Path::read() before */ /* There's an error message from Path::read() before */
CORRADE_COMPARE_AS(out.str(), CORRADE_COMPARE_AS(out.str(),
"\nShaderTools::AbstractConverter::validateFile(): cannot open file nonexistent.bin\n", "\nShaderTools::AbstractConverter::validateFile(): cannot open file nonexistent.bin\n",
@ -908,15 +902,8 @@ void AbstractConverterTest::validateFileCustomStringDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, Containers::StringView) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage, Containers::StringView) override {
/* libc++ and MSVC STL is STUPID and doing return {{}, Containers::String{"", 0, [](char*, std::size_t){}}};
`return {{}, Containers::String{...}};`
will do a COPY, even though not needed. That then of course
discards the custom deleter and makes the test fail. Oh C++, do
I really have to reimplement even std::pair, FFS?! */
std::pair<bool, Containers::String> out;
out.second = Containers::String{"", 0, [](char*, std::size_t){}};
return out;
} }
} converter; } converter;
@ -1412,11 +1399,11 @@ void AbstractConverterTest::linkDataToData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -1467,7 +1454,7 @@ void AbstractConverterTest::linkDataToDataNotImplemented() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToData({std::pair<Stage, Containers::ArrayView<const void>>{}}); converter.linkDataToData({Containers::Pair<Stage, Containers::ArrayView<const void>>{}});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n");
} }
@ -1522,7 +1509,7 @@ void AbstractConverterTest::linkDataToDataCustomDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}}; return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}};
} }
} converter; } converter;
@ -1530,7 +1517,7 @@ void AbstractConverterTest::linkDataToDataCustomDeleter() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToData({std::pair<Stage, Containers::ArrayView<const void>>{}}); converter.linkDataToData({Containers::Pair<Stage, Containers::ArrayView<const void>>{}});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter\n");
} }
@ -1542,11 +1529,11 @@ void AbstractConverterTest::linkDataToFileThroughData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -1572,7 +1559,7 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return {}; return {};
} }
} converter; } converter;
@ -1587,7 +1574,7 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, filename)); CORRADE_VERIFY(!converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename)); CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_COMPARE(out.str(), ""); CORRADE_COMPARE(out.str(), "");
} }
@ -1600,7 +1587,7 @@ void AbstractConverterTest::linkDataToFileThroughDataNotWritable() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1}; return Containers::Array<char>{1};
} }
} converter; } converter;
@ -1608,7 +1595,7 @@ void AbstractConverterTest::linkDataToFileThroughDataNotWritable() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, "/some/path/that/does/not/exist")); CORRADE_VERIFY(!converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, "/some/path/that/does/not/exist"));
CORRADE_COMPARE_AS(out.str(), CORRADE_COMPARE_AS(out.str(),
"ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file /some/path/that/does/not/exist\n", "ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file /some/path/that/does/not/exist\n",
TestSuite::Compare::StringHasSuffix); TestSuite::Compare::StringHasSuffix);
@ -1649,7 +1636,7 @@ void AbstractConverterTest::linkDataToFileNotImplemented() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, "file.dat"); converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, "file.dat");
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n");
} }
@ -1700,15 +1687,15 @@ void AbstractConverterTest::linkFilesToFile() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
CORRADE_COMPARE(from.size(), 2); CORRADE_COMPARE(from.size(), 2);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second); Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second());
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second); Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second());
CORRADE_VERIFY(first); CORRADE_VERIFY(first);
CORRADE_VERIFY(second); CORRADE_VERIFY(second);
return Utility::Path::write(to, Containers::array({ return Utility::Path::write(to, Containers::array({
from[0].first == Stage::Vertex ? (*first)[0] : ' ', from[0].first() == Stage::Vertex ? (*first)[0] : ' ',
from[1].first == Stage::Fragment ? (*second)[0] : ' ' from[1].first() == Stage::Fragment ? (*second)[0] : ' '
})); }));
} }
} converter; } converter;
@ -1736,11 +1723,11 @@ void AbstractConverterTest::linkFilesToFileThroughData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -1766,7 +1753,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
@ -1792,7 +1779,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return {}; return {};
} }
} converter; } converter;
@ -1821,7 +1808,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataNotWritable() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1}; return Containers::Array<char>{1};
} }
} converter; } converter;
@ -1871,7 +1858,7 @@ void AbstractConverterTest::linkFilesToFileNotImplemented() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */ /* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkFilesToFile({std::pair<Stage, Containers::StringView>{}}, {}); converter.linkFilesToFile({Containers::Pair<Stage, Containers::StringView>{}}, {});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented\n");
} }
@ -1922,15 +1909,15 @@ void AbstractConverterTest::linkFilesToData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
CORRADE_COMPARE(from.size(), 2); CORRADE_COMPARE(from.size(), 2);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second); Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second());
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second); Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second());
CORRADE_VERIFY(first); CORRADE_VERIFY(first);
CORRADE_VERIFY(second); CORRADE_VERIFY(second);
return Containers::array({ return Containers::array({
from[0].first == Stage::Vertex ? (*first)[0] : ' ', from[0].first() == Stage::Vertex ? (*first)[0] : ' ',
from[1].first == Stage::Fragment ? (*second)[0] : ' ' from[1].first() == Stage::Fragment ? (*second)[0] : ' '
}); });
} }
} converter; } converter;
@ -1954,11 +1941,11 @@ void AbstractConverterTest::linkFilesToDataAsData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -1982,7 +1969,7 @@ void AbstractConverterTest::linkFilesToDataAsDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
@ -2092,7 +2079,7 @@ void AbstractConverterTest::linkFilesToDataCustomDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}}; return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}};
} }
} converter; } converter;
@ -2255,11 +2242,11 @@ void AbstractConverterTest::setInputFileCallbackValidateFileDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView filename) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView filename) override {
return {filename == "file.dat" && inputFileCallback() && inputFileCallbackUserData(), "it's what it is!"}; return {filename == "file.dat" && inputFileCallback() && inputFileCallbackUserData(), "it's what it is!"};
} }
std::pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override { Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
CORRADE_VERIFY(!"this should not be reached"); CORRADE_VERIFY(!"this should not be reached");
return {}; return {};
} }
@ -2271,7 +2258,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileDirectly() {
return Containers::Optional<Containers::ArrayView<const char>>{}; return Containers::Optional<Containers::ArrayView<const char>>{};
}, &a); }, &a);
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(true, "it's what it is!")); CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(true, Containers::String{"it's what it is!"}));
} }
void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplementation() { void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplementation() {
@ -2282,7 +2269,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
validateFileCalled = true; validateFileCalled = true;
if(filename != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData()) if(filename != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData())
@ -2291,7 +2278,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
return AbstractConverter::doValidateFile(stage, filename); return AbstractConverter::doValidateFile(stage, filename);
} }
std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override { Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
return {stage == Stage::RayCallable && data.size() == 1 && data[0] == '\xb0', "yep!!"}; return {stage == Stage::RayCallable && data.size() == 1 && data[0] == '\xb0', "yep!!"};
} }
@ -2319,7 +2306,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
return {}; return {};
}, state); }, state);
CORRADE_COMPARE(converter.validateFile(Stage::RayCallable, "file.dat"), std::make_pair(true, "yep!!")); CORRADE_COMPARE(converter.validateFile(Stage::RayCallable, "file.dat"), Containers::pair(true, Containers::String{"yep!!"}));
CORRADE_VERIFY(converter.validateFileCalled); CORRADE_VERIFY(converter.validateFileCalled);
CORRADE_VERIFY(state.loaded); CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed); CORRADE_VERIFY(state.closed);
@ -2333,7 +2320,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
validateFileCalled = true; validateFileCalled = true;
return AbstractConverter::doValidateFile(stage, filename); return AbstractConverter::doValidateFile(stage, filename);
} }
@ -2348,7 +2335,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(false, "")); CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(false, Containers::String{}));
CORRADE_VERIFY(converter.validateFileCalled); CORRADE_VERIFY(converter.validateFileCalled);
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n");
} }
@ -2361,12 +2348,12 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override { Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
return {stage == Stage::Fragment && data.size() == 1 && data[0] == '\xb0', "yep!!"}; return {stage == Stage::Fragment && data.size() == 1 && data[0] == '\xb0', "yep!!"};
} }
} converter; } converter;
@ -2392,7 +2379,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsData() {
return {}; return {};
}, state); }, state);
CORRADE_COMPARE(converter.validateFile(Stage::Fragment, "file.dat"), std::make_pair(true, "yep!!")); CORRADE_COMPARE(converter.validateFile(Stage::Fragment, "file.dat"), Containers::pair(true, Containers::String{"yep!!"}));
CORRADE_VERIFY(state.loaded); CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed); CORRADE_VERIFY(state.closed);
} }
@ -2405,7 +2392,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override { Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
@ -2418,7 +2405,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsDataFailed() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(false, "")); CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n");
} }
@ -2863,8 +2850,8 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
return from.size() == 2 && from[0].first == Stage::Vertex && from[0].second == "another.dat" && from[1].first == Stage::Fragment && from[1].second == "file.dat" && to == "file.out" && inputFileCallback() && inputFileCallbackUserData(); return from.size() == 2 && from[0].first() == Stage::Vertex && from[0].second() == "another.dat" && from[1].first() == Stage::Fragment && from[1].second() == "file.dat" && to == "file.out" && inputFileCallback() && inputFileCallbackUserData();
} }
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override { Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
@ -2893,20 +2880,20 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
linkFilesToFileCalled = true; linkFilesToFileCalled = true;
if(from.size() != 2 || from[0].first != Stage::Vertex || from[0].second != "another.dat" || from[1].first != Stage::Fragment || from[1].second != "file.dat" || !to.hasSuffix("file.out") || !inputFileCallback() || !inputFileCallbackUserData()) if(from.size() != 2 || from[0].first() != Stage::Vertex || from[0].second() != "another.dat" || from[1].first() != Stage::Fragment || from[1].second() != "file.dat" || !to.hasSuffix("file.out") || !inputFileCallback() || !inputFileCallbackUserData())
return {}; return {};
return AbstractConverter::doLinkFilesToFile(from, to); return AbstractConverter::doLinkFilesToFile(from, to);
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
@ -2963,12 +2950,12 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
linkFilesToFileCalled = true; linkFilesToFileCalled = true;
return AbstractConverter::doLinkFilesToFile(from, to); return AbstractConverter::doLinkFilesToFile(from, to);
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be called"); CORRADE_VERIFY(!"this shouldn't be called");
return {}; return {};
} }
@ -3022,16 +3009,16 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -3085,7 +3072,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
@ -3132,12 +3119,12 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsDataNotWritable
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override { bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1}; return Containers::Array<char>{1};
} }
} converter; } converter;
@ -3190,13 +3177,13 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
if(from.size() == 2 && from[0].first == Stage::Vertex && from[0].second == "another.dat" && from[1].first == Stage::Fragment && from[1].second == "file.dat" && inputFileCallback() && inputFileCallbackUserData()) if(from.size() == 2 && from[0].first() == Stage::Vertex && from[0].second() == "another.dat" && from[1].first() == Stage::Fragment && from[1].second() == "file.dat" && inputFileCallback() && inputFileCallbackUserData())
return Containers::array({'y', 'e', 'p'}); return Containers::array({'y', 'e', 'p'});
return {}; return {};
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this should not be reached"); CORRADE_VERIFY(!"this should not be reached");
return {}; return {};
} }
@ -3226,20 +3213,20 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
linkFilesToDataCalled = true; linkFilesToDataCalled = true;
if(from.size() != 2 || from[0].first != Stage::Vertex || from[0].second != "another.dat" || from[1].first != Stage::Fragment || from[1].second != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData()) if(from.size() != 2 || from[0].first() != Stage::Vertex || from[0].second() != "another.dat" || from[1].first() != Stage::Fragment || from[1].second() != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData())
return {}; return {};
return AbstractConverter::doLinkFilesToData(from); return AbstractConverter::doLinkFilesToData(from);
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
@ -3294,7 +3281,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
linkFilesToDataCalled = true; linkFilesToDataCalled = true;
return AbstractConverter::doLinkFilesToData(from); return AbstractConverter::doLinkFilesToData(from);
} }
@ -3348,16 +3335,16 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataAsData() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override { Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2); CORRADE_COMPARE(data.size(), 2);
return Containers::array({ return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ', data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' ' data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
}); });
} }
} converter; } converter;
@ -3409,7 +3396,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {} void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {} void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override { Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
CORRADE_VERIFY(!"this shouldn't be reached"); CORRADE_VERIFY(!"this shouldn't be reached");
return {}; return {};
} }

17
src/Magnum/ShaderTools/shaderconverter.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/GrowableArray.h> #include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/Arguments.h> #include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
@ -421,7 +422,7 @@ see documentation of a particular converter for more information.)")
/* Options and flags applied just for the first converter; setting up /* Options and flags applied just for the first converter; setting up
file list for linking */ file list for linking */
Containers::Array<std::pair<ShaderTools::Stage, Containers::StringView>> linkInputs; Containers::Array<Containers::Pair<ShaderTools::Stage, Containers::StringView>> linkInputs;
if(i == 0) { if(i == 0) {
if((args.isSet("preprocess-only") || args.arrayValueCount("define") || args.arrayValueCount("undefine"))) { if((args.isSet("preprocess-only") || args.arrayValueCount("define") || args.arrayValueCount("undefine"))) {
if(!(converter->features() >= ShaderTools::ConverterFeature::Preprocess)) { if(!(converter->features() >= ShaderTools::ConverterFeature::Preprocess)) {
@ -432,7 +433,7 @@ see documentation of a particular converter for more information.)")
if(args.isSet("preprocess-only")) if(args.isSet("preprocess-only"))
flags |= ShaderTools::ConverterFlag::PreprocessOnly; flags |= ShaderTools::ConverterFlag::PreprocessOnly;
Containers::Array<std::pair<Containers::StringView, Containers::StringView>> definitions; Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>> definitions;
arrayReserve(definitions, args.arrayValueCount("define") + args.arrayValueCount("undefine")); arrayReserve(definitions, args.arrayValueCount("define") + args.arrayValueCount("undefine"));
for(std::size_t j = 0; j != args.arrayValueCount("define"); ++j) { for(std::size_t j = 0; j != args.arrayValueCount("define"); ++j) {
const Containers::Array3<Containers::StringView> define = const Containers::Array3<Containers::StringView> define =
@ -516,18 +517,18 @@ see documentation of a particular converter for more information.)")
return 13; return 13;
} }
std::pair<bool, Containers::String> out = converter->validateFile(ShaderTools::Stage::Unspecified, args.arrayValue<Containers::StringView>("input", 0)); Containers::Pair<bool, Containers::String> out = converter->validateFile(ShaderTools::Stage::Unspecified, args.arrayValue<Containers::StringView>("input", 0));
if(!out.first) { if(!out.first()) {
if(args.isSet("verbose")) if(args.isSet("verbose"))
Error{} << "Validation failed:"; Error{} << "Validation failed:";
if(!out.second.isEmpty()) Error{} << out.second; if(!out.second().isEmpty()) Error{} << out.second();
} else if(!out.second.isEmpty()) { } else if(!out.second().isEmpty()) {
if(args.isSet("verbose")) if(args.isSet("verbose"))
Warning{} << "Validation succeeded with warnings:"; Warning{} << "Validation succeeded with warnings:";
if(!out.second.isEmpty()) Warning{} << out.second; if(!out.second().isEmpty()) Warning{} << out.second();
} else if(args.isSet("verbose")) } else if(args.isSet("verbose"))
Debug{} << "Validation passed"; Debug{} << "Validation passed";
return out.first ? 0 : 14; return out.first() ? 0 : 14;
} }
/** @todo ability to specify the stage (need a configurationvalue parser for this) */ /** @todo ability to specify the stage (need a configurationvalue parser for this) */

24
src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp

@ -44,8 +44,8 @@ struct AnyConverter::State {
Format inputFormat, outputFormat; Format inputFormat, outputFormat;
Containers::String inputVersion, outputVersion; Containers::String inputVersion, outputVersion;
Containers::Array<std::pair<Containers::String, Containers::String>> definitions; Containers::Array<Containers::Pair<Containers::String, Containers::String>> definitions;
Containers::Array<std::pair<Containers::StringView, Containers::StringView>> definitionViews; Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>> definitionViews;
Containers::String debugInfoLevel, optimizationLevel; Containers::String debugInfoLevel, optimizationLevel;
}; };
@ -70,23 +70,23 @@ void AnyConverter::doSetOutputFormat(Format format, Containers::StringView versi
_state->outputVersion = Containers::String::nullTerminatedGlobalView(version); _state->outputVersion = Containers::String::nullTerminatedGlobalView(version);
} }
void AnyConverter::doSetDefinitions(const Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) { void AnyConverter::doSetDefinitions(const Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
/* We have to make a local copy, unfortunately, and then a view on that /* We have to make a local copy, unfortunately, and then a view on that
local copy */ local copy */
_state->definitions = Containers::Array<std::pair<Containers::String, Containers::String>>{definitions.size()}; _state->definitions = Containers::Array<Containers::Pair<Containers::String, Containers::String>>{definitions.size()};
_state->definitionViews = Containers::Array<std::pair<Containers::StringView, Containers::StringView>>{definitions.size()}; _state->definitionViews = Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>>{definitions.size()};
for(std::size_t i = 0; i != definitions.size(); ++i) { for(std::size_t i = 0; i != definitions.size(); ++i) {
/* Avoid a copy if the input is a global string literal */ /* Avoid a copy if the input is a global string literal */
_state->definitions[i] = { _state->definitions[i] = {
Containers::String::nullTerminatedGlobalView(definitions[i].first), Containers::String::nullTerminatedGlobalView(definitions[i].first()),
Containers::String::nullTerminatedGlobalView(definitions[i].second) Containers::String::nullTerminatedGlobalView(definitions[i].second())
}; };
/* Preserve the distinction between empty defines ("") and undefines /* Preserve the distinction between empty defines ("") and undefines
(nullptr or default constructor) */ (nullptr or default constructor) */
_state->definitionViews[i] = { _state->definitionViews[i] = {
_state->definitions[i].first, _state->definitions[i].first(),
definitions[i].second.data() ? definitions[i].second().data() ?
Containers::StringView{_state->definitions[i].second} : Containers::StringView{_state->definitions[i].second()} :
Containers::StringView{} Containers::StringView{}
}; };
} }
@ -175,7 +175,7 @@ Format formatForExtension(const char* prefix, const Containers::StringView filen
} }
std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) { Containers::Pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager()); CORRADE_INTERNAL_ASSERT(manager());
/* Prefer the explicitly set input format. If not set, fall back to /* Prefer the explicitly set input format. If not set, fall back to
@ -235,7 +235,7 @@ std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage sta
return converter->validateFile(stage, filename); return converter->validateFile(stage, filename);
} }
std::pair<bool, Containers::String> AnyConverter::doValidateData(const Stage stage, const Containers::ArrayView<const char> data) { Containers::Pair<bool, Containers::String> AnyConverter::doValidateData(const Stage stage, const Containers::ArrayView<const char> data) {
CORRADE_INTERNAL_ASSERT(manager()); CORRADE_INTERNAL_ASSERT(manager());
/* Decide on a plugin name based on the format */ /* Decide on a plugin name based on the format */

6
src/MagnumPlugins/AnyShaderConverter/AnyConverter.h

@ -155,12 +155,12 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter {
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetInputFormat(Format, Containers::StringView version) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetInputFormat(Format, Containers::StringView version) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOutputFormat(Format, Containers::StringView version) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOutputFormat(Format, Containers::StringView version) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDebugInfoLevel(Containers::StringView level) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDebugInfoLevel(Containers::StringView level) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOptimizationLevel(Containers::StringView level) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOptimizationLevel(Containers::StringView level) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename) override; MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override; MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override; MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView filename) override; MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView filename) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertDataToData(Magnum::ShaderTools::Stage stage, Containers::ArrayView<const char> data) override; MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertDataToData(Magnum::ShaderTools::Stage stage, Containers::ArrayView<const char> data) override;

49
src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp

@ -26,6 +26,7 @@
#include <sstream> #include <sstream>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> #include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
@ -264,7 +265,7 @@ void AnyConverterTest::validateFile() {
/* Make it print a warning so we know it's doing something */ /* Make it print a warning so we know it's doing something */
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename))); Containers::pair(true, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
} }
void AnyConverterTest::validateFilePluginLoadFailed() { void AnyConverterTest::validateFilePluginLoadFailed() {
@ -273,7 +274,7 @@ void AnyConverterTest::validateFilePluginLoadFailed() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "file.glsl"), CORRADE_COMPARE(converter->validateFile({}, "file.glsl"),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n" "PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n"
@ -291,7 +292,7 @@ void AnyConverterTest::validateFileUnknown() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "dead.cg"), CORRADE_COMPARE(converter->validateFile({}, "dead.cg"),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateFile(): cannot determine the format of dead.cg\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateFile(): cannot determine the format of dead.cg\n");
} }
@ -317,7 +318,7 @@ void AnyConverterTest::validateFilePreprocessNotSupported() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")), CORRADE_COMPARE(converter->validateFile({}, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): SpirvToolsShaderConverter does not support preprocessing\n"); "ShaderTools::AnyConverter::validateFile(): SpirvToolsShaderConverter does not support preprocessing\n");
} }
@ -342,7 +343,7 @@ void AnyConverterTest::validateFilePropagateFlags() {
std::ostringstream out; std::ostringstream out;
Debug redirectDebug{&out}; Debug redirectDebug{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(false, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename))); Containers::pair(false, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): using GlslShaderConverter (provided by GlslangShaderConverter)\n"); "ShaderTools::AnyConverter::validateFile(): using GlslShaderConverter (provided by GlslangShaderConverter)\n");
} }
@ -366,7 +367,7 @@ void AnyConverterTest::validateFilePropagateInputVersion() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n"); "ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n");
} }
@ -390,7 +391,7 @@ void AnyConverterTest::validateFilePropagateOutputVersion() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n"); "ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n");
} }
@ -417,7 +418,7 @@ void AnyConverterTest::validateFilePropagatePreprocess() {
}); });
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, Utility::format("WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved", filename))); Containers::pair(true, Utility::format("WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
} }
void AnyConverterTest::validateFilePropagateConfiguration() { void AnyConverterTest::validateFilePropagateConfiguration() {
@ -435,13 +436,13 @@ void AnyConverterTest::validateFilePropagateConfiguration() {
{ {
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(false, Utility::format("ERROR: {}:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated.", filename))); Containers::pair(false, Utility::format("ERROR: {}:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated.", filename)));
} { } {
converter->configuration().setValue("permissive", true); converter->configuration().setValue("permissive", true);
/* Lol stupid thing, apparently it has two differently worded messages /* Lol stupid thing, apparently it has two differently worded messages
for the same thing? Dumpster fire. */ for the same thing? Dumpster fire. */
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, "WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version")); Containers::pair(true, Containers::String{"WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version"}));
} }
} }
@ -462,7 +463,7 @@ void AnyConverterTest::validateFilePropagateConfigurationUnknown() {
std::ostringstream out; std::ostringstream out;
Warning redirectWarning{&out}; Warning redirectWarning{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")), CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(true, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): option noSuchOption not recognized by GlslangShaderConverter\n"); "ShaderTools::AnyConverter::validateFile(): option noSuchOption not recognized by GlslangShaderConverter\n");
} }
@ -484,7 +485,7 @@ void AnyConverterTest::validateData() {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")); Containers::Optional<Containers::Array<char>> data = Utility::Path::read(Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"));
CORRADE_VERIFY(data); CORRADE_VERIFY(data);
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved")); Containers::pair(true, Containers::String{"WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"}));
} }
void AnyConverterTest::validateDataPluginLoadFailed() { void AnyConverterTest::validateDataPluginLoadFailed() {
@ -495,7 +496,7 @@ void AnyConverterTest::validateDataPluginLoadFailed() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, {}), CORRADE_COMPARE(converter->validateData({}, {}),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n" "PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n"
@ -513,7 +514,7 @@ void AnyConverterTest::validateDataNoFormatSet() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, "dead.cg"), CORRADE_COMPARE(converter->validateData({}, "dead.cg"),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateData(): no input format specified\n"); CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateData(): no input format specified\n");
} }
@ -544,7 +545,7 @@ void AnyConverterTest::validateDataPreprocessNotSupported() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, *data), CORRADE_COMPARE(converter->validateData({}, *data),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): SpirvToolsShaderConverter does not support preprocessing\n"); "ShaderTools::AnyConverter::validateData(): SpirvToolsShaderConverter does not support preprocessing\n");
} }
@ -572,7 +573,7 @@ void AnyConverterTest::validateDataPropagateFlags() {
std::ostringstream out; std::ostringstream out;
Debug redirectDebug{&out}; Debug redirectDebug{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved")); Containers::pair(false, Containers::String{"WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): using GlslShaderConverter (provided by GlslangShaderConverter)\n"); "ShaderTools::AnyConverter::validateData(): using GlslShaderConverter (provided by GlslangShaderConverter)\n");
} }
@ -601,7 +602,7 @@ void AnyConverterTest::validateDataPropagateInputVersion() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n"); "ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n");
} }
@ -630,7 +631,7 @@ void AnyConverterTest::validateDataPropagateOutputVersion() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n"); "ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n");
} }
@ -660,7 +661,7 @@ void AnyConverterTest::validateDataPropagatePreprocess() {
CORRADE_VERIFY(data); CORRADE_VERIFY(data);
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, "WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved")); Containers::pair(true, Containers::String{"WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved"}));
} }
void AnyConverterTest::validateDataPropagateConfiguration() { void AnyConverterTest::validateDataPropagateConfiguration() {
@ -680,13 +681,13 @@ void AnyConverterTest::validateDataPropagateConfiguration() {
{ {
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "ERROR: 0:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated.")); Containers::pair(false, Containers::String{"ERROR: 0:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated."}));
} { } {
converter->configuration().setValue("permissive", true); converter->configuration().setValue("permissive", true);
/* Lol stupid thing, apparently it has two differently worded messages /* Lol stupid thing, apparently it has two differently worded messages
for the same thing? Dumpster fire. */ for the same thing? Dumpster fire. */
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, Utility::format("WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version"))); Containers::pair(true, Utility::format("WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version")));
} }
} }
@ -711,7 +712,7 @@ void AnyConverterTest::validateDataPropagateConfigurationUnknown() {
std::ostringstream out; std::ostringstream out;
Warning redirectWarning{&out}; Warning redirectWarning{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data), CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, "")); Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): option noSuchOption not recognized by GlslangShaderConverter\n"); "ShaderTools::AnyConverter::validateData(): option noSuchOption not recognized by GlslangShaderConverter\n");
} }
@ -1856,7 +1857,7 @@ void AnyConverterTest::detectValidate() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, data.filename), CORRADE_COMPARE(converter->validateFile({}, data.filename),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString( CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n" "PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
@ -1877,7 +1878,7 @@ void AnyConverterTest::detectValidateExplicitFormat() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "file.spv"), CORRADE_COMPARE(converter->validateFile({}, "file.spv"),
std::make_pair(false, "")); Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin HlslShaderConverter is not static and was not found in nonexistent\n" "PluginManager::Manager::load(): plugin HlslShaderConverter is not static and was not found in nonexistent\n"

Loading…
Cancel
Save