From 33e08c8d94246a95c7320d14a8fbf9da51e72148 Mon Sep 17 00:00:00 2001 From: lapointexavier Date: Tue, 4 Mar 2025 22:43:50 -0600 Subject: [PATCH] [cpp] Provides a file extension option for codegen --- .../sbe/generation/cpp/CppGenerator.java | 12 ++++- .../cpp/NamespaceOutputManager.java | 20 +++++++- .../sbe/generation/cpp/WithFileExtension.java | 37 ++++++++++++++ .../sbe/generation/cpp/CppGeneratorTest.java | 48 +++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/WithFileExtension.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 566545df2f..9a8304ba1d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -55,6 +55,7 @@ public class CppGenerator implements CodeGenerator private static final String INDENT = " "; private static final String TWO_INDENT = INDENT + INDENT; private static final String THREE_INDENT = TWO_INDENT + INDENT; + private static final String DEFAULT_FILE_EXTENSION = ".h"; private final Ir ir; private final OutputManager outputManager; @@ -109,6 +110,15 @@ public CppGenerator( this.outputManager = outputManager; } + private String getFileExtension() + { + if (outputManager instanceof WithFileExtension) + { + return ((WithFileExtension)outputManager).getFileExtension(); + } + return DEFAULT_FILE_EXTENSION; + } + /** * Generate the composites for dealing with the message header. * @@ -1818,7 +1828,7 @@ private CharSequence generateFileHeader( sb.append("\n"); for (final String incName : typesToInclude) { - sb.append("#include \"").append(toUpperFirstChar(incName)).append(".h\"\n"); + sb.append("#include \"").append(toUpperFirstChar(incName)).append(getFileExtension()).append("\"\n"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 71f993dc97..d4ca3e1dbd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -28,8 +28,9 @@ * {@link OutputManager} for managing the creation of C++11 source files as the target of code generation. * The character encoding for the {@link java.io.Writer} is UTF-8. */ -public class NamespaceOutputManager implements OutputManager +public class NamespaceOutputManager implements OutputManager, WithFileExtension { + private String fileExt; private final File outputDir; /** @@ -51,6 +52,9 @@ public NamespaceOutputManager(final String baseDirName, final String namespaceNa { throw new IllegalStateException("Unable to create directory: " + packageDirName); } + + // Defaults to .h to maintain backward compatibility + fileExt = System.getProperty("sbe.cpp.file.extension", ".h"); } /** @@ -65,7 +69,19 @@ public NamespaceOutputManager(final String baseDirName, final String namespaceNa */ public Writer createOutput(final String name) throws IOException { - final File targetFile = new File(outputDir, name + ".h"); + final File targetFile = new File(outputDir, name + fileExt); return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); } + + @Override + public void withFileExtension(final String fileExtension) + { + this.fileExt = fileExtension; + } + + @Override + public String getFileExtension() + { + return this.fileExt; + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/WithFileExtension.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/WithFileExtension.java new file mode 100644 index 0000000000..8355d6121f --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/WithFileExtension.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.cpp; + +/** + * Abstraction to provide file extension configuration and retrieval. + */ +public interface WithFileExtension +{ + + /** + * Sets the file extension. + * + * @param fileExtension A valid file extension (e.g. ".hpp") + */ + void withFileExtension(String fileExtension); + + /** + * Gets a file extension. + * + * @return the configured file extension. + */ + String getFileExtension(); +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 6d4990df3b..a95db38cef 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.generation.cpp; +import org.agrona.generation.OutputManager; import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; @@ -24,11 +25,14 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.IOException; import java.io.InputStream; +import java.io.Writer; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -140,4 +144,48 @@ void shouldUseConstexprWhenDefiningPrecedenceChecksLookupTables() throws Excepti assertThat(source, containsString("static constexpr const char *STATE_TRANSITIONS_LOOKUP[] =")); } } + + @Test + void shouldAllowFileExtensionConfiguration() throws Exception + { + class OutputManagerWithExt extends StringWriterOutputManager implements WithFileExtension { + private String fileExtension; + + @Override + public String getFileExtension() { + return fileExtension; + } + + @Override + public void withFileExtension(String fileExtension) { + this.fileExtension = fileExtension; + } + + } + + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final OutputManagerWithExt outputManager = new OutputManagerWithExt(); + outputManager.setPackageName(ir.applicableNamespace()); + outputManager.withFileExtension(".hpp"); + + assertEquals(outputManager.getFileExtension(), ".hpp"); + + final CppGenerator generator = new CppGenerator( + ir, + false, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context().shouldGeneratePrecedenceChecks(true)), + false, + outputManager); + generator.generate(); + + final String source = outputManager.getSource("code.generation.test.Car").toString(); + assertThat(source, containsString("#include \"MessageHeader.hpp\"")); + assertThat(source,containsString("#include \"BoostType.hpp\"")); + } + } }