/** * Format a class name for the generated code. * * @param value to be formatted. * @return the string formatted as a class name. */ public static String formatClassName(final String value) { return Generators.toUpperFirstChar(value); }
/** * Generate SBE encoding and decoding stubs for a target language. * * @param ir for the parsed specification. * @param outputDirName directory into which code will be generated. * @param targetLanguage for the generated code. * @throws Exception if an error occurs while generating the code. */ public static void generate(final Ir ir, final String outputDirName, final String targetLanguage) throws Exception { final TargetCodeGenerator targetCodeGenerator = TargetCodeGeneratorLoader.get(targetLanguage); final CodeGenerator codeGenerator = targetCodeGenerator.newInstance(ir, outputDirName); codeGenerator.generate(); } }
GroupTreeNode( final Optional<GroupTreeNode> parent, final String originalName, final String contextualName, final PrimitiveType numInGroupType, final PrimitiveType blockLengthType, final int blockLength, final List<Token> fields, final List<VarDataSummary> varData) { this.parent = parent; this.originalName = originalName; this.contextualName = contextualName; this.numInGroupType = numInGroupType; this.blockLengthType = blockLengthType; this.blockLength = blockLength; this.rawFields = fields; this.simpleNamedFields = NamedToken.gatherNamedNonConstantFieldTokens(fields); this.varData = varData; parent.ifPresent((p) -> p.addChild(this)); }
Generators.forEachField( tokens, (fieldToken, typeToken) -> final String propertyName = formatPropertyName(fieldToken.name()); final String typeName = decoderName(formatClassName(typeToken.name())); generateFieldIdMethod(sb, fieldToken, indent); generateFieldSinceVersionMethod(sb, fieldToken, indent); generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); generateFieldMetaAttributeMethod(sb, fieldToken, indent); sb.append(generatePrimitiveDecoder(false, propertyName, fieldToken, typeToken, indent)); break; sb.append(generateEnumDecoder(false, fieldToken, propertyName, typeToken, indent)); break; sb.append(generateBitSetProperty( false, DECODER, propertyName, fieldToken, typeToken, indent, typeName)); break; sb.append(generateCompositeProperty( false, DECODER, propertyName, fieldToken, typeToken, indent, typeName)); break;
Generators.forEachField( tokens, (fieldToken, typeToken) -> final String propertyName = formatPropertyName(fieldToken.name()); final String typeName = formatClassName(encoderName(typeToken.name())); generateFieldIdMethod(sb, fieldToken, indent); generateFieldSinceVersionMethod(sb, fieldToken, indent); generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); generateFieldMetaAttributeMethod(sb, fieldToken, indent); sb.append(generatePrimitiveEncoder(containingClassName, propertyName, typeToken, indent)); break; sb.append(generateEnumEncoder(containingClassName, propertyName, typeToken, indent)); break; sb.append(generateBitSetProperty( false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); break; sb.append(generateCompositeProperty( false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); break;
generateFieldIdMethod(sb, token, indent); generateFieldSinceVersionMethod(sb, token, indent); generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); generateFieldMetaAttributeMethod(sb, token, indent); final String propertyName = Generators.toUpperFirstChar(token.name()); final Token lengthToken = tokens.get(i + 2); final int sizeOfLengthField = lengthToken.encodedLength(); final Encoding lengthEncoding = lengthToken.encoding(); final PrimitiveType lengthType = lengthEncoding.primitiveType(); final String byteOrderStr = byteOrderString(lengthEncoding); indent + " return %d;\n" + indent + " }\n", Generators.toLowerFirstChar(propertyName), sizeOfLengthField)); indent + " return (int)%s;\n" + indent + " }\n", Generators.toLowerFirstChar(propertyName), generateArrayFieldNotPresentCondition(token.version(), indent), generateGet(lengthType, "limit", byteOrderStr))); generateDataDecodeMethods( sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent);
final String indent) generateVarDataTypedDecoder( sb, token, generateVarDataTypedDecoder( sb, token, generateVarDataWrapDecoder(sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, indent); indent + " return value;\n" + indent + " }\n", formatPropertyName(propertyName), generateStringNotPresentCondition(token.version(), indent), sizeOfLengthField, generateGet(lengthType, "limit", byteOrderStr), characterEncoding)); indent + " }\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, generateGet(lengthType, "limit", byteOrderStr), byteOrderStr));
enum CodecType { DECODER, ENCODER }
private void generateGroups(final StringBuilder sb, final List<Token> tokens, final String indent) { for (int i = 0, size = tokens.size(); i < size; i++) { final Token groupToken = tokens.get(i); if (groupToken.signal() != Signal.BEGIN_GROUP) { throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } final String groupName = groupToken.name(); final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, i); final String cppTypeForNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); generateGroupClassHeader(sb, groupName, tokens, i, indent + INDENT); ++i; final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); i += groupHeaderTokenCount; final List<Token> fields = new ArrayList<>(); i = collectFields(tokens, i, fields); sb.append(generateFields(formatClassName(groupName), fields, indent + INDENT)); final List<Token> groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); generateGroups(sb, groups, indent + INDENT); final List<Token> varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); sb.append(generateVarData(formatClassName(groupName), varData, indent + INDENT)); sb.append(indent).append(" };\n"); sb.append(generateGroupProperty(groupName, groupToken, cppTypeForNumInGroup, indent)); } }
final Token typeToken = namedToken.typeToken(); if (typeToken.isConstantEncoding()) final String propertyName = formatMethodName(namedToken.name()); indent(appendable).append("pub ").append(propertyName).append(":"); final String rustPrimitiveType = RustUtil.rustTypeName(typeToken.encoding().primitiveType()); final String rustFieldType = getRustTypeForPrimitivePossiblyArray(typeToken, rustPrimitiveType); appendable.append(rustFieldType); break; case BEGIN_SET: case BEGIN_COMPOSITE: appendable.append(formatTypeName(typeToken.applicableTypeName())); break;
private void generateVarData( final StringBuilder sb, final String typeName, final List<Token> tokens) { for (int i = 0, size = tokens.size(); i < size;) { final Token token = tokens.get(i); if (token.signal() != Signal.BEGIN_VAR_DATA) { throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); } final String propertyName = toUpperFirstChar(token.name()); final Token lengthToken = Generators.findFirst("length", tokens, i); final int lengthOfLengthField = lengthToken.encodedLength(); final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); generateFieldMetaAttributeMethod(sb, typeName, propertyName, token); generateVarDataDescriptors(sb, token, typeName, propertyName, characterEncoding, lengthOfLengthField); i += token.componentTokenCount(); } }
@Test public void happyPathRustGeneratorThatThrowsNoExceptions() throws IOException { final File newFolder = temporaryFolder.newFolder(); final CodeGenerator codeGenerator = new Rust().newInstance(minimalDummyIr(), newFolder.toString()); assertNotNull(codeGenerator); codeGenerator.generate(); newFolder.setWritable(true, false); }
public static List<NamedToken> gatherNamedNonConstantFieldTokens(final List<Token> fields) { final List<NamedToken> namedTokens = new ArrayList<>(); forEachField(fields, (f, t) -> { if (!f.isConstantEncoding()) { namedTokens.add(new NamedToken(f.name(), t)); } }); return namedTokens; } }
private static String toLowerUnderscoreFromCamel(final String value) { if (value.isEmpty()) { return value; } final String s = toLowerFirstChar(value); // include some extra space for separators final StringBuilder out = new StringBuilder(s.length() + 4); int i = 0; int j = -1; while ((j = indexInUpperAlphaRange(s, ++j)) != -1) { final String word = s.substring(i, j).toLowerCase(); out.append(word); if (!word.endsWith("_")) { out.append("_"); } i = j; } return (i == 0) ? s.toLowerCase() : out.append(s.substring(i).toLowerCase()).toString(); }
/** * Do a case insensitive lookup of a target language for code generation. * * @param name of the target language to lookup. * @return the {@link TargetCodeGenerator} for the given language name. */ public static TargetCodeGenerator get(final String name) { for (final TargetCodeGeneratorLoader target : values()) { if (target.name().equalsIgnoreCase(name)) { return target; } } try { return (TargetCodeGenerator)Class.forName(name).getConstructor().newInstance(); } catch (final Exception ex) { throw new IllegalArgumentException("No code generator for name: " + name, ex); } } }
public static SplitCompositeTokens splitInnerTokens(final List<Token> tokens) { final List<Token> constantTokens = new ArrayList<>(); final List<NamedToken> namedNonConstantTokens = new ArrayList<>(); for (int i = 1, end = tokens.size() - 1; i < end; ) { final Token encodingToken = tokens.get(i); if (encodingToken.isConstantEncoding()) { constantTokens.add(encodingToken); } else { namedNonConstantTokens.add(new NamedToken(encodingToken.name(), encodingToken)); } i += encodingToken.componentTokenCount(); } return new SplitCompositeTokens(constantTokens, namedNonConstantTokens); } }
@Test public void shouldLoadAndInstatiateNonStandardTargetLanguage() throws Exception { final Ir ir = mock(Ir.class); final String outputDir = "."; SbeTool.generate(ir, outputDir, "uk.co.real_logic.sbe.TestTargetLanguage"); verify(TestTargetLanguage.SINGLETON).generate(); assertThat(ir, is(TestTargetLanguage.ir)); assertThat(outputDir, is(TestTargetLanguage.outputDir)); } }
/** * Format a property name for generated code. * <p> * If the formatted property name is a keyword then {@link SbeTool#KEYWORD_APPEND_TOKEN} is appended if set. * * @param value to be formatted. * @return the string formatted as a property name. * @throws IllegalStateException if a keyword and {@link SbeTool#KEYWORD_APPEND_TOKEN} is not set. */ public static String formatPropertyName(final String value) { String formattedValue = Generators.toLowerFirstChar(value); if (ValidationUtil.isJavaKeyword(formattedValue)) { final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); if (null == keywordAppendToken) { throw new IllegalStateException( "Invalid property name='" + formattedValue + "' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN); } formattedValue += keywordAppendToken; } return formattedValue; }
static String formatTypeName(final String value) { return toUpperFirstChar(value); }
static void get(final Object object, final String fieldName, final Appendable arg) throws Exception { final String methodName = "get" + Generators.toUpperFirstChar(fieldName); object.getClass().getMethod(methodName, Appendable.class).invoke(object, arg); }