diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 4118130c4d..0e5d8438ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.generation.CodeGenerator; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.java.JavaUtil; import uk.co.real_logic.sbe.ir.*; import org.agrona.Verify; @@ -244,29 +245,31 @@ private void generateCharacterEncodingRangeCheck( if (null != characterEncoding) { - switch (token.encoding().characterEncoding()) + if (JavaUtil.isAsciiEncoding(characterEncoding)) { - case "ASCII": - imports.peek().add("fmt"); - sb.append(String.format( - "\tfor idx, ch := range %1$s {\n" + - "\t\tif ch > 127 {\n" + - "\t\t\treturn fmt.Errorf(\"%1$s[%%d]=%%d" + - " failed ASCII validation\", idx, ch)\n" + - "\t\t}\n" + - "\t}\n", - varName)); - break; - - case "UTF-8": - imports.peek().add("errors"); - imports.peek().add("unicode/utf8"); - sb.append(String.format( - "\tif !utf8.Valid(%1$s[:]) {\n" + - "\t\treturn errors.New(\"%1$s failed UTF-8 validation\")\n" + - "\t}\n", - varName)); - break; + imports.peek().add("fmt"); + sb.append(String.format( + "\tfor idx, ch := range %1$s {\n" + + "\t\tif ch > 127 {\n" + + "\t\t\treturn fmt.Errorf(\"%1$s[%%d]=%%d" + + " failed ASCII validation\", idx, ch)\n" + + "\t\t}\n" + + "\t}\n", + varName)); + } + else if (JavaUtil.isUtf8Encoding(characterEncoding)) + { + imports.peek().add("errors"); + imports.peek().add("unicode/utf8"); + sb.append(String.format( + "\tif !utf8.Valid(%1$s[:]) {\n" + + "\t\treturn errors.New(\"%1$s failed UTF-8 validation\")\n" + + "\t}\n", + varName)); + } + else + { + throw new IllegalArgumentException("Unsupported encoding: " + characterEncoding); } } } @@ -1836,7 +1839,7 @@ private void generateCompositePropertyElements( final String containingTypeName, final List tokens) { - for (int i = 0; i < tokens.size();) + for (int i = 0; i < tokens.size(); ) { final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index e2d96b4927..4272a8f436 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -921,25 +921,16 @@ private void generateDataDecodeMethods( indent + " }\n\n" + indent + " final byte[] tmp = new byte[dataLength];\n" + indent + " buffer.getBytes(limit + headerLength, tmp, 0, dataLength);\n\n" + - indent + " final String value;\n" + - indent + " try\n" + - indent + " {\n" + - indent + " value = new String(tmp, \"%6$s\");\n" + - indent + " }\n" + - indent + " catch (final java.io.UnsupportedEncodingException ex)\n" + - indent + " {\n" + - indent + " throw new RuntimeException(ex);\n" + - indent + " }\n\n" + - indent + " return value;\n" + + indent + " return new String(tmp, %6$s);\n" + indent + " }\n", formatPropertyName(propertyName), generateStringNotPresentCondition(token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), - characterEncoding); + charset(characterEncoding)); - if (characterEncoding.contains("ASCII")) + if (isAsciiEncoding(characterEncoding)) { new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable appendable)\n" + @@ -1050,7 +1041,7 @@ private void generateCharArrayEncodeMethods( { final PrimitiveType lengthPutType = PrimitiveType.UINT32 == lengthType ? PrimitiveType.INT32 : lengthType; - if (characterEncoding.contains("ASCII")) + if (isAsciiEncoding(characterEncoding)) { new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + @@ -1099,16 +1090,8 @@ private void generateCharArrayEncodeMethods( new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + indent + " {\n" + - indent + " final byte[] bytes;\n" + - indent + " try\n" + - indent + " {\n" + - indent + " bytes = null == value || value.isEmpty() ?" + - " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(\"%3$s\");\n" + - indent + " }\n" + - indent + " catch (final java.io.UnsupportedEncodingException ex)\n" + - indent + " {\n" + - indent + " throw new RuntimeException(ex);\n" + - indent + " }\n\n" + + indent + " final byte[] bytes = (null == value || value.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(%3$s);\n\n" + indent + " final int length = bytes.length;\n" + indent + " if (length > %4$d)\n" + indent + " {\n" + @@ -1123,7 +1106,7 @@ private void generateCharArrayEncodeMethods( indent + " }\n", className, formatPropertyName(propertyName), - characterEncoding, + charset(characterEncoding), maxLengthValue, sizeOfLengthField, generatePut(lengthPutType, "limit", "length", byteOrderStr)); @@ -2042,7 +2025,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( fieldLength, charset(encoding.characterEncoding())); - if (encoding.characterEncoding().contains("ASCII")) + if (isAsciiEncoding(encoding.characterEncoding())) { new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable value)\n" + @@ -2240,7 +2223,7 @@ private void generateCharArrayEncodeMethods( fieldLength, offset); - if (encoding.characterEncoding().contains("ASCII")) + if (isAsciiEncoding(encoding.characterEncoding())) { new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String src)\n" + @@ -2274,15 +2257,10 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"CharSequence too large for copy: byte length=\" + srcLength);\n" + indent + " }\n\n" + - indent + " for (int i = 0; i < srcLength; ++i)\n" + - indent + " {\n" + - indent + " final char charValue = src.charAt(i);\n" + - indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + - indent + " buffer.putByte(offset + %4$d + i, byteValue);\n" + - indent + " }\n\n" + - indent + " for (int i = srcLength; i < length; ++i)\n" + + indent + " buffer.putStringWithoutLengthAscii(offset + %4$d, src);\n\n" + + indent + " for (int start = srcLength; start < length; ++start)\n" + indent + " {\n" + - indent + " buffer.putByte(offset + %4$d + i, (byte)0);\n" + + indent + " buffer.putByte(offset + %4$d + start, (byte)0);\n" + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2297,7 +2275,8 @@ private void generateCharArrayEncodeMethods( indent + " public %s %s(final String src)\n" + indent + " {\n" + indent + " final int length = %d;\n" + - indent + " final byte[] bytes = null == src ? new byte[0] : src.getBytes(%s);\n" + + indent + " final byte[] bytes = (null == src || src.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : src.getBytes(%s);\n" + indent + " if (bytes.length > length)\n" + indent + " {\n" + indent + " throw new IndexOutOfBoundsException(" + @@ -2387,7 +2366,7 @@ private static void generateCharacterEncodingMethod( sb.append("\n") .append(indent).append(" public static String ").append(propName).append("CharacterEncoding()\n") .append(indent).append(" {\n") - .append(indent).append(" return \"").append(characterEncoding).append("\";\n") + .append(indent).append(" return ").append(charsetName(characterEncoding)).append(";\n") .append(indent).append(" }\n"); } } @@ -3537,7 +3516,7 @@ private void appendDecoderDisplay( } else { - if (characterEncoding.contains("ASCII") || characterEncoding.contains("ascii")) + if (isAsciiEncoding(characterEncoding)) { append(sb, indent, "builder.append('\\'');"); append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 839923d2e1..f6969c111e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -18,20 +18,19 @@ import org.agrona.Strings; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.ValidationUtil; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.ir.Token; -import uk.co.real_logic.sbe.ValidationUtil; import java.io.IOException; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; -import static java.lang.reflect.Modifier.STATIC; - /** * Utilities for mapping between {@link uk.co.real_logic.sbe.ir.Ir} and the Java language. */ @@ -96,7 +95,7 @@ public String toString() /** * Indexes known charset aliases to the name of the instance in {@link StandardCharsets}. */ - private static final Map STD_CHARSETS = new HashMap<>(); + static final HashMap STD_CHARSETS = new HashMap<>(); static { @@ -104,11 +103,25 @@ public String toString() { for (final Field field : StandardCharsets.class.getDeclaredFields()) { - if (Charset.class.isAssignableFrom(field.getType()) && ((field.getModifiers() & STATIC) == STATIC)) + if (Charset.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers()) && + Modifier.isPublic(field.getModifiers())) { final Charset charset = (Charset)field.get(null); - STD_CHARSETS.put(charset.name(), field.getName()); - charset.aliases().forEach((alias) -> STD_CHARSETS.put(alias, field.getName())); + final String name = field.getName(); + String oldName = STD_CHARSETS.put(charset.name(), name); + if (null != oldName) + { + throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + name); + } + for (final String alias : charset.aliases()) + { + oldName = STD_CHARSETS.put(alias, name); + if (null != oldName) + { + throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + + alias); + } + } } } } @@ -207,10 +220,52 @@ public static String charset(final String encoding) } else { - return "java.nio.charset.Charset.forName(\"" + encoding + "\")"; + final String canonicalName = Charset.isSupported(encoding) ? Charset.forName(encoding).name() : encoding; + return "java.nio.charset.Charset.forName(\"" + canonicalName + "\")"; } } + /** + * Code to fetch the name of the {@link Charset} given the encoding. + * + * @param encoding as a string name (eg. UTF-8). + * @return the code to fetch the associated Charset name. + */ + public static String charsetName(final String encoding) + { + final String charsetName = STD_CHARSETS.get(encoding); + if (charsetName != null) + { + return "java.nio.charset.StandardCharsets." + charsetName + ".name()"; + } + else + { + return "\"" + (Charset.isSupported(encoding) ? Charset.forName(encoding).name() : encoding) + "\""; + } + } + + /** + * Checks if the given encoding represents an ASCII charset. + * + * @param encoding as a string name (e.g. ASCII). + * @return {@code true} if the encoding denotes an ASCII charset. + */ + public static boolean isAsciiEncoding(final String encoding) + { + return "US_ASCII".equals(STD_CHARSETS.get(encoding)); + } + + /** + * Checks if the given encoding represents a UTF-8 charset. + * + * @param encoding as a string name (e.g. unicode-1-1-utf-8). + * @return {@code true} if the encoding denotes a UTF-8 charset. + */ + public static boolean isUtf8Encoding(final String encoding) + { + return "UTF_8".equals(STD_CHARSETS.get(encoding)); + } + /** * Generate a literal value to be used in code generation. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 8cfdbd888d..b3abad386c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.java.JavaUtil; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; @@ -304,20 +305,15 @@ static void generateEncoderVarData( final String varDataType; final String toBytesFn; - switch (characterEncoding) + if (JavaUtil.isUtf8Encoding(characterEncoding)) { - case "UTF-8": - { - varDataType = "&str"; - toBytesFn = ".as_bytes()"; - break; - } - default: - { - varDataType = "&[u8]"; - toBytesFn = ""; - break; - } + varDataType = "&str"; + toBytesFn = ".as_bytes()"; + } + else + { + varDataType = "&[u8]"; + toBytesFn = ""; } // function to write slice ... todo - handle character encoding ? @@ -681,23 +677,20 @@ private static void generatePrimitiveConstantDecoder( indent(sb, level, "/// characterEncoding: '%s'\n", characterEncoding); indent(sb, level, "#[inline]\n"); - switch (characterEncoding) + if (JavaUtil.isAsciiEncoding(characterEncoding)) { - case "US-ASCII": - { - indent(sb, level, "pub fn %s(&self) -> &'static [u8] {\n", - formatFunctionName(name)); - indent(sb, level + 1, "b\"%s\"\n", rawConstValue); - break; - } - case "UTF-8": - { - indent(sb, level, "pub fn %s(&self) -> &'static str {\n", formatFunctionName(name)); - indent(sb, level + 1, "\"%s\"\n", rawConstValue); - break; - } - default: - throw new RuntimeException("Unable to handle " + characterEncoding); + indent(sb, level, "pub fn %s(&self) -> &'static [u8] {\n", + formatFunctionName(name)); + indent(sb, level + 1, "b\"%s\"\n", rawConstValue); + } + else if (JavaUtil.isUtf8Encoding(characterEncoding)) + { + indent(sb, level, "pub fn %s(&self) -> &'static str {\n", formatFunctionName(name)); + indent(sb, level + 1, "\"%s\"\n", rawConstValue); + } + else + { + throw new IllegalArgumentException("Unsupported encoding: " + characterEncoding); } indent(sb, level, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 1fc4a81cdd..d958498953 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -299,7 +299,7 @@ public static int packageNameSinceVersion() public static String packageNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) @@ -382,17 +382,7 @@ public String packageName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int namespaceNameId() @@ -407,7 +397,7 @@ public static int namespaceNameSinceVersion() public static String namespaceNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) @@ -490,17 +480,7 @@ public String namespaceName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int semanticVersionId() @@ -515,7 +495,7 @@ public static int semanticVersionSinceVersion() public static String semanticVersionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) @@ -598,17 +578,7 @@ public String semanticVersion() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public String toString() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 3fca868e13..4bcc266652 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -267,7 +267,7 @@ public static int packageNameId() public static String packageNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) @@ -319,15 +319,7 @@ public FrameCodecEncoder putPackageName(final byte[] src, final int srcOffset, f public FrameCodecEncoder packageName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -351,7 +343,7 @@ public static int namespaceNameId() public static String namespaceNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) @@ -403,15 +395,7 @@ public FrameCodecEncoder putNamespaceName(final byte[] src, final int srcOffset, public FrameCodecEncoder namespaceName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -435,7 +419,7 @@ public static int semanticVersionId() public static String semanticVersionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) @@ -487,15 +471,7 @@ public FrameCodecEncoder putSemanticVersion(final byte[] src, final int srcOffse public FrameCodecEncoder semanticVersion(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 674a2cd566..cfac525b67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -616,7 +616,7 @@ public static int nameSinceVersion() public static String nameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nameMetaAttribute(final MetaAttribute metaAttribute) @@ -699,17 +699,7 @@ public String name() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int constValueId() @@ -724,7 +714,7 @@ public static int constValueSinceVersion() public static String constValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String constValueMetaAttribute(final MetaAttribute metaAttribute) @@ -807,17 +797,7 @@ public String constValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int minValueId() @@ -832,7 +812,7 @@ public static int minValueSinceVersion() public static String minValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String minValueMetaAttribute(final MetaAttribute metaAttribute) @@ -915,17 +895,7 @@ public String minValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int maxValueId() @@ -940,7 +910,7 @@ public static int maxValueSinceVersion() public static String maxValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) @@ -1023,17 +993,7 @@ public String maxValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int nullValueId() @@ -1048,7 +1008,7 @@ public static int nullValueSinceVersion() public static String nullValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) @@ -1131,17 +1091,7 @@ public String nullValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int characterEncodingId() @@ -1156,7 +1106,7 @@ public static int characterEncodingSinceVersion() public static String characterEncodingCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) @@ -1239,17 +1189,7 @@ public String characterEncoding() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int epochId() @@ -1264,7 +1204,7 @@ public static int epochSinceVersion() public static String epochCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String epochMetaAttribute(final MetaAttribute metaAttribute) @@ -1347,17 +1287,7 @@ public String epoch() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int timeUnitId() @@ -1372,7 +1302,7 @@ public static int timeUnitSinceVersion() public static String timeUnitCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) @@ -1455,17 +1385,7 @@ public String timeUnit() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int semanticTypeId() @@ -1480,7 +1400,7 @@ public static int semanticTypeSinceVersion() public static String semanticTypeCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) @@ -1563,17 +1483,7 @@ public String semanticType() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int descriptionId() @@ -1588,7 +1498,7 @@ public static int descriptionSinceVersion() public static String descriptionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) @@ -1671,17 +1581,7 @@ public String description() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int referencedNameId() @@ -1696,7 +1596,7 @@ public static int referencedNameSinceVersion() public static String referencedNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) @@ -1779,17 +1679,7 @@ public String referencedName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public String toString() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 1790f6f10b..1f429e09b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -567,7 +567,7 @@ public static int nameId() public static String nameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nameMetaAttribute(final MetaAttribute metaAttribute) @@ -619,15 +619,7 @@ public TokenCodecEncoder putName(final byte[] src, final int srcOffset, final in public TokenCodecEncoder name(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -651,7 +643,7 @@ public static int constValueId() public static String constValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String constValueMetaAttribute(final MetaAttribute metaAttribute) @@ -703,15 +695,7 @@ public TokenCodecEncoder putConstValue(final byte[] src, final int srcOffset, fi public TokenCodecEncoder constValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -735,7 +719,7 @@ public static int minValueId() public static String minValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String minValueMetaAttribute(final MetaAttribute metaAttribute) @@ -787,15 +771,7 @@ public TokenCodecEncoder putMinValue(final byte[] src, final int srcOffset, fina public TokenCodecEncoder minValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -819,7 +795,7 @@ public static int maxValueId() public static String maxValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) @@ -871,15 +847,7 @@ public TokenCodecEncoder putMaxValue(final byte[] src, final int srcOffset, fina public TokenCodecEncoder maxValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -903,7 +871,7 @@ public static int nullValueId() public static String nullValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) @@ -955,15 +923,7 @@ public TokenCodecEncoder putNullValue(final byte[] src, final int srcOffset, fin public TokenCodecEncoder nullValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -987,7 +947,7 @@ public static int characterEncodingId() public static String characterEncodingCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) @@ -1039,15 +999,7 @@ public TokenCodecEncoder putCharacterEncoding(final byte[] src, final int srcOff public TokenCodecEncoder characterEncoding(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1071,7 +1023,7 @@ public static int epochId() public static String epochCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String epochMetaAttribute(final MetaAttribute metaAttribute) @@ -1123,15 +1075,7 @@ public TokenCodecEncoder putEpoch(final byte[] src, final int srcOffset, final i public TokenCodecEncoder epoch(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1155,7 +1099,7 @@ public static int timeUnitId() public static String timeUnitCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) @@ -1207,15 +1151,7 @@ public TokenCodecEncoder putTimeUnit(final byte[] src, final int srcOffset, fina public TokenCodecEncoder timeUnit(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1239,7 +1175,7 @@ public static int semanticTypeId() public static String semanticTypeCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) @@ -1291,15 +1227,7 @@ public TokenCodecEncoder putSemanticType(final byte[] src, final int srcOffset, public TokenCodecEncoder semanticType(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1323,7 +1251,7 @@ public static int descriptionId() public static String descriptionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) @@ -1375,15 +1303,7 @@ public TokenCodecEncoder putDescription(final byte[] src, final int srcOffset, f public TokenCodecEncoder description(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1407,7 +1327,7 @@ public static int referencedNameId() public static String referencedNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) @@ -1459,15 +1379,7 @@ public TokenCodecEncoder putReferencedName(final byte[] src, final int srcOffset public TokenCodecEncoder referencedName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 4c76c27184..f8b6728851 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -94,12 +94,12 @@ public EncodedDataType(final Node node, final String givenName, final String ref if (PrimitiveType.CHAR == primitiveType) { - characterEncoding = getAttributeValue(node, "characterEncoding", "US-ASCII").trim().toUpperCase(); + characterEncoding = getAttributeValue(node, "characterEncoding", "US-ASCII").trim(); } else { final String characterEncoding = getAttributeValueOrNull(node, "characterEncoding"); - this.characterEncoding = characterEncoding == null ? null : characterEncoding.trim().toUpperCase(); + this.characterEncoding = characterEncoding == null ? null : characterEncoding.trim(); } if (presence() == CONSTANT) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java new file mode 100644 index 0000000000..80125fdcf8 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -0,0 +1,195 @@ +/* + * Copyright 2013-2021 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.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.ByteArrayInputStream; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringContains.containsString; +import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class CharacterEncodingTest +{ + private static final String XML_SCHEMA; + + static + { + final StringBuilder buffer = + new StringBuilder("\n") + .append("\n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n"); + + int i = 0; + for (final String alias : STD_CHARSETS.keySet()) + { + buffer.append(" \n"); + buffer.append(" \n") + .append(" \n") + .append(" \n") + .append(" \n"); + i++; + } + buffer.append(" \n"); + buffer.append(" \n") + .append(" \n") + .append(" \n \n"); + buffer.append(" \n"); + buffer.append(" \n"); + + buffer.append(" \n") + .append(" \n"); + i = 0; + for (int j = 0, size = STD_CHARSETS.size(); j < size; j++) + { + buffer.append(" \n"); + i++; + } + buffer.append(""); + buffer.append(""); + buffer.append(""); + + for (int j = 0, size = STD_CHARSETS.size(); j < size; j++) + { + buffer.append(" \n"); + i++; + } + buffer.append(""); + + buffer.append(" \n") + .append(""); + XML_SCHEMA = buffer.toString(); + } + + @Test + public void shouldUseStandardCharsetsForWellKnowEncodings() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = + parse(new ByteArrayInputStream(XML_SCHEMA.getBytes(UTF_8)), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final JavaGenerator generator = new JavaGenerator( + ir, MutableDirectBuffer.class.getName(), DirectBuffer.class.getName(), false, false, false, outputManager); + + generator.generate(); + final Map sources = outputManager.getSources(); + final String encoderSources = sources.get("code.generation.test.EncodingTestEncoder").toString(); + final String decoderSources = sources.get("code.generation.test.EncodingTestDecoder").toString(); + + verifyCharacterEncodingMethods(encoderSources); + verifyCharacterEncodingMethods(decoderSources); + + assertThat(encoderSources, not(containsString("java.io.UnsupportedEncodingException"))); + assertThat(encoderSources, not(containsString("new byte[0]"))); + for (final String charset : STD_CHARSETS.values()) + { + if (!"US_ASCII".equals(charset)) + { + assertThat( + encoderSources, containsString("getBytes(java.nio.charset.StandardCharsets." + charset + ")")); + } + } + assertThat(encoderSources, containsString("getBytes(java.nio.charset.Charset.forName(\"custom-encoding\"))")); + assertThat(encoderSources, containsString("getBytes(java.nio.charset.Charset.forName(\"ISO-8859-2\"))")); + assertThat(encoderSources, allOf(not(containsString("\"cp912\"")), not(containsString("\"CP912\"")))); + final int encodeFromStringStartIndex = encoderSources.indexOf("f_std_alias(final String src)"); + final int encodeFromStringEndIndex = encoderSources.indexOf("return this", encodeFromStringStartIndex); + assertThat( + encoderSources.substring(encodeFromStringStartIndex, encodeFromStringEndIndex), + containsString("final byte[] bytes = (null == src || src.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY :" + + " src.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);")); + assertThat(decoderSources, not(containsString("java.io.UnsupportedEncodingException"))); + assertThat(decoderSources, not(containsString("new byte[0]"))); + for (final String charset : STD_CHARSETS.values()) + { + assertThat(decoderSources, containsString("end, java.nio.charset.StandardCharsets." + charset + ")")); + } + assertThat(decoderSources, containsString("end, java.nio.charset.Charset.forName(\"custom-encoding\"))")); + assertThat(decoderSources, containsString("end, java.nio.charset.Charset.forName(\"ISO-8859-2\"))")); + assertThat(decoderSources, allOf(not(containsString("\"cp912\"")), not(containsString("\"CP912\"")))); + } + + private void verifyCharacterEncodingMethods(final String code) + { + int i = 0; + for (final String charset : STD_CHARSETS.values()) + { + assertContainsCharacterEncodingMethod( + "f_" + (i++), "java.nio.charset.StandardCharsets." + charset + ".name()", code); + } + assertContainsCharacterEncodingMethod("f_custom", "\"custom-encoding\"", code); + assertContainsCharacterEncodingMethod( + "f_std_alias", "java.nio.charset.StandardCharsets.ISO_8859_1.name()", code); + assertContainsCharacterEncodingMethod("f_non_std_alias", "\"ISO-8859-2\"", code); + } + + private static void assertContainsCharacterEncodingMethod( + final String fieldName, final String expectedEncoding, final String sources) + { + final String expectedOne = + " public static String " + fieldName + "CharacterEncoding()\n" + + " {\n return " + expectedEncoding + ";\n }"; + assertThat(sources, containsString(expectedOne)); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 4e31d104be..a73173bb16 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -414,6 +414,49 @@ public void shouldReturnCorrectNullValueWhenSpecified() throws Exception is(parse(nullVal, PrimitiveType.INT8))); } + @Test + public void shouldReturnCharacterEncodingWhenSpecified() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat((((EncodedDataType)map.get("testTypeCharacterEncoding")).characterEncoding()), is("cp912")); + } + + @Test + public void shouldReturnCharacterEncodingWhenSpecifiedNonCharType() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat( + (((EncodedDataType)map.get("testTypeCharacterEncodingNonChar")).characterEncoding()), is("windows-1251")); + } + + @Test + public void shouldReturnUsAsciiWhenCharacterEncodingNotSpecifiedForTypeChar() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat( + (((EncodedDataType)map.get("testCharDefaultCharacterEncoding")).characterEncoding()), is("US-ASCII")); + } + private static Map parseTestXmlWithMap(final String xPathExpr, final String xml) throws ParserConfigurationException, XPathExpressionException, IOException, SAXException {