39#include "denigma/io/random_access_reader.h"
119 [[nodiscard]] std::span<const Diagnostic>
diagnostics() const noexcept {
return m_diagnostics; }
122 [[nodiscard]]
bool hasError() const noexcept {
return m_hasError; }
125 explicit operator bool() const noexcept {
return !
hasError(); }
133 m_hasError = m_hasError || diagnostic.
severity == MessageSeverity::Error;
134 m_diagnostics.push_back(std::move(diagnostic));
138 std::vector<Diagnostic> m_diagnostics;
166 [[nodiscard]] std::span<const ConversionOutput>
outputs() const noexcept {
return m_outputs; }
172 explicit operator bool() const noexcept {
return static_cast<bool>(m_result); }
176 std::vector<ConversionOutput> m_outputs;
182template <
typename OptionsT>
188 if (
const auto* options =
dynamic_cast<const OptionsT*
>(request.
options)) {
191 assert(
false &&
"incompatible conversion options");
192 throw std::invalid_argument(std::string(converterName) +
" received incompatible conversion options.");
228using MultiOutputCallback = std::function<void(std::string_view suggestedName, std::span<const std::byte> data)>;
270 void add(std::unique_ptr<IConverter> converter)
273 throw std::invalid_argument(
"converter cannot be null");
275 m_converters.emplace_back(std::move(converter));
279 void add(std::unique_ptr<IMultiOutputConverter> converter)
282 throw std::invalid_argument(
"converter cannot be null");
284 m_multiOutputConverters.emplace_back(std::move(converter));
288 void add(std::unique_ptr<IReaderConverter> converter)
291 throw std::invalid_argument(
"converter cannot be null");
293 m_readerConverters.emplace_back(std::move(converter));
297 void add(std::unique_ptr<IReaderMultiOutputConverter> converter)
300 throw std::invalid_argument(
"converter cannot be null");
302 m_readerMultiOutputConverters.emplace_back(std::move(converter));
308 for (
const auto& converter : m_converters) {
309 if (converter->sourceFormat() == sourceFormat && converter->targetFormat() == targetFormat) {
310 return converter.get();
319 for (
const auto& converter : m_multiOutputConverters) {
320 if (converter->sourceFormat() == sourceFormat && converter->targetFormat() == targetFormat) {
321 return converter.get();
330 for (
const auto& converter : m_readerConverters) {
331 if (converter->sourceFormat() == sourceFormat && converter->targetFormat() == targetFormat) {
332 return converter.get();
341 for (
const auto& converter : m_readerMultiOutputConverters) {
342 if (converter->sourceFormat() == sourceFormat && converter->targetFormat() == targetFormat) {
343 return converter.get();
354 if (
const auto* converter =
find(sourceFormat, targetFormat)) {
355 return collectSingleOutput(*converter, input, request);
357 if (
const auto* converter =
findMultiOutput(sourceFormat, targetFormat)) {
358 return collectMultipleOutputs(*converter, input, request);
360 return unsupportedConversion();
368 if (
const auto* converter =
findReader(sourceFormat, targetFormat)) {
369 return collectSingleOutput(*converter, input, request);
372 return collectMultipleOutputs(*converter, input, request);
374 return unsupportedConversion();
378 template <
typename Converter,
typename Input>
379 static ConversionArtifact collectSingleOutput(
const Converter& converter,
const Input& input,
const ConversionRequest& request)
381 std::ostringstream output;
382 auto result = converter.convert(input, output, request);
383 auto text = output.str();
384 std::vector<std::byte> data(text.size());
386 std::memcpy(data.data(), text.data(), text.size());
388 std::vector<ConversionOutput> outputs;
389 outputs.push_back({{}, std::move(data)});
390 return {std::move(result), std::move(outputs)};
393 template <
typename Converter,
typename Input>
394 static ConversionArtifact collectMultipleOutputs(
const Converter& converter,
const Input& input,
const ConversionRequest& request)
396 std::vector<ConversionOutput> outputs;
397 auto result = converter.convert(
399 [&outputs](std::string_view suggestedName, std::span<const std::byte> data) {
400 outputs.push_back({std::string(suggestedName), {data.begin(), data.end()}});
403 return {std::move(result), std::move(outputs)};
406 static ConversionArtifact unsupportedConversion()
408 ConversionResult result;
409 result.addDiagnostic(MessageSeverity::Error,
"No converter is registered for the requested formats.");
410 return {std::move(result), {}};
413 std::vector<std::unique_ptr<IConverter>> m_converters;
414 std::vector<std::unique_ptr<IMultiOutputConverter>> m_multiOutputConverters;
415 std::vector<std::unique_ptr<IReaderConverter>> m_readerConverters;
416 std::vector<std::unique_ptr<IReaderMultiOutputConverter>> m_readerMultiOutputConverters;
Owned documents and result metadata from one conversion.
Definition conversion.h:155
const ConversionResult & result() const noexcept
Returns converter result metadata.
Definition conversion.h:163
bool hasError() const noexcept
Returns true when the conversion result contains an error diagnostic.
Definition conversion.h:169
ConversionArtifact(ConversionResult result, std::vector< ConversionOutput > outputs)
Creates an artifact from converter result metadata and generated documents.
Definition conversion.h:158
std::span< const ConversionOutput > outputs() const noexcept
Returns the generated documents in converter emission order.
Definition conversion.h:166
Result metadata returned after a conversion completes.
Definition conversion.h:116
void addDiagnostic(MessageSeverity severity, std::string message)
Adds a diagnostic and updates the error state if needed.
Definition conversion.h:128
bool hasError() const noexcept
Returns true when at least one diagnostic has severity Error.
Definition conversion.h:122
void addDiagnostic(Diagnostic diagnostic)
Adds a diagnostic and updates the error state if needed.
Definition conversion.h:131
std::span< const Diagnostic > diagnostics() const noexcept
Returns the diagnostics collected during conversion.
Definition conversion.h:119
Lightweight registry for locating converters by source and target format.
Definition conversion.h:267
void add(std::unique_ptr< IReaderMultiOutputConverter > converter)
Adds a reader-backed multi-output converter to the registry.
Definition conversion.h:297
const IReaderConverter * findReader(FormatId sourceFormat, FormatId targetFormat) const
Returns the first registered reader-backed converter matching the requested formats,...
Definition conversion.h:328
ConversionArtifact convert(FormatId sourceFormat, FormatId targetFormat, std::span< const std::byte > input, const ConversionRequest &request={}) const
Converts an in-memory input with the registered adapter for the requested formats.
Definition conversion.h:351
const IReaderMultiOutputConverter * findReaderMultiOutput(FormatId sourceFormat, FormatId targetFormat) const
Returns the first registered reader-backed multi-output converter matching the requested formats,...
Definition conversion.h:339
const IMultiOutputConverter * findMultiOutput(FormatId sourceFormat, FormatId targetFormat) const
Returns the first registered multi-output converter matching the requested formats,...
Definition conversion.h:317
const IConverter * find(FormatId sourceFormat, FormatId targetFormat) const
Returns the first registered converter matching the requested formats, or nullptr.
Definition conversion.h:306
ConversionArtifact convert(FormatId sourceFormat, FormatId targetFormat, const IRandomAccessReader &input, const ConversionRequest &request={}) const
Converts a random-access input with the registered adapter for the requested formats.
Definition conversion.h:365
void add(std::unique_ptr< IMultiOutputConverter > converter)
Adds a multi-output converter to the registry.
Definition conversion.h:279
void add(std::unique_ptr< IConverter > converter)
Adds a converter to the registry.
Definition conversion.h:270
void add(std::unique_ptr< IReaderConverter > converter)
Adds a reader-backed converter to the registry.
Definition conversion.h:288
Public interface implemented by each conversion adapter.
Definition conversion.h:198
virtual ~IConverter()=default
virtual destructor
virtual FormatId sourceFormat() const =0
Returns the source format accepted by this converter.
virtual FormatId targetFormat() const =0
Returns the target format produced by this converter.
virtual ConversionResult convert(std::span< const std::byte > input, std::ostream &output, const ConversionRequest &request={}) const =0
Converts the input memory buffer and writes the converted output to the provided stream.
Public interface implemented by adapters that may produce multiple output documents.
Definition conversion.h:233
virtual FormatId targetFormat() const =0
Returns the target format produced by this converter.
virtual ConversionResult convert(std::span< const std::byte > input, const MultiOutputCallback &outputCallback, const ConversionRequest &request={}) const =0
Converts the input memory buffer and invokes outputCallback once for each generated output.
virtual FormatId sourceFormat() const =0
Returns the source format accepted by this converter.
virtual ~IMultiOutputConverter()=default
virtual destructor
Base class for adapter-specific option structs.
Definition conversion.h:100
virtual ~IOptions()=default
Virtual destructor.
Random-access byte reader used for container formats such as MUSX.
Definition random_access_reader.h:32
Public interface implemented by adapters whose input is a random-access container.
Definition conversion.h:214
virtual ConversionResult convert(const IRandomAccessReader &input, std::ostream &output, const ConversionRequest &request={}) const =0
Converts the input reader and writes the converted output to the provided stream.
virtual ~IReaderConverter()=default
virtual destructor
virtual FormatId targetFormat() const =0
Returns the target format produced by this converter.
virtual FormatId sourceFormat() const =0
Returns the source format accepted by this converter.
Public interface implemented by reader-backed adapters that may produce multiple output documents.
Definition conversion.h:250
virtual ConversionResult convert(const IRandomAccessReader &input, const MultiOutputCallback &outputCallback, const ConversionRequest &request={}) const =0
Converts the input reader and invokes outputCallback once for each generated output.
virtual ~IReaderMultiOutputConverter()=default
virtual destructor
virtual FormatId sourceFormat() const =0
Returns the source format accepted by this converter.
virtual FormatId targetFormat() const =0
Returns the target format produced by this converter.
Collects typed conversion gaps for inspection or later serialization.
Definition gaps.h:102
Core public API for the Denigma conversion libraries.
Definition articulations.h:33
FormatId
Stable identifiers for converter input and output formats.
Definition conversion.h:51
@ MssXml
MuseScore style sheet XML.
@ EnigmaXml
Finale Enigma XML.
@ Svg
Scalable Vector Graphics XML.
@ MnxJson
MNX JSON as produced by mnxdom.
@ Musx
Finale MUSX archive.
@ MusicXml
MusicXML score-partwise XML.
MessageSeverity
Severity for log messages and diagnostics emitted by converters.
Definition conversion.h:62
OptionsT optionsFromRequest(const ConversionRequest &request, std::string_view converterName)
Returns typed options from an erased request, or default options when none were supplied.
Definition conversion.h:183
std::function< void(std::string_view suggestedName, std::span< const std::byte > data)> MultiOutputCallback
Callback used by converters that may emit zero, one, or many output buffers.
Definition conversion.h:228
Options common to all public converter adapters.
Definition conversion.h:80
std::function< void(MessageSeverity severity, std::string_view message)> logCallback
Optional callback that receives converter log messages. Defaults to no-op.
Definition conversion.h:94
classify::GapCollector * gapCollector
Optional non-owning destination for typed conversion gaps. Null disables gap collection.
Definition conversion.h:92
bool validate
Enables converter-specific output validation when supported.
Definition conversion.h:84
bool allFontsAvailable
Every source font will be available in the environment that reads the converted output.
Definition conversion.h:90
std::string sourceName
Caller-supplied source name used for diagnostics and metadata.
Definition conversion.h:82
bool verbose
Enables verbose logging when supported by the caller.
Definition conversion.h:86
bool quiet
Suppresses info/verbose logging when true.
Definition conversion.h:88
One document produced by a conversion.
Definition conversion.h:145
std::string suggestedName
Suggested output filename. Empty when the converter does not supply one.
Definition conversion.h:147
std::vector< std::byte > data
Owned output bytes.
Definition conversion.h:149
Type-erased request used by registry-based converter calls.
Definition conversion.h:108
const IOptions * options
Adapter-specific options. Must remain valid for the duration of the conversion call.
Definition conversion.h:110
A non-fatal message emitted by a converter.
Definition conversion.h:72
std::string message
Human-readable diagnostic text.
Definition conversion.h:74
MessageSeverity severity
Message severity.
Definition conversion.h:73