Skip to content

Commit

Permalink
[C++, C#] Avoid unnecessary validation code.
Browse files Browse the repository at this point in the history
Previously, regardless of whether the min and max values were the min
and max values for the host language representation of an SBE type, we
would generate a range check. Now, we do not generate the check unless
it is meaningful.

Also, adjust the property-based test dotnet version to bring inline with
other tests.
  • Loading branch information
ZachBray committed Jun 25, 2024
1 parent 801b5ba commit d93b337
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.ir.Encoding;
import uk.co.real_logic.sbe.ir.Ir;
import uk.co.real_logic.sbe.ir.Signal;
import uk.co.real_logic.sbe.ir.Token;
Expand Down Expand Up @@ -1489,7 +1490,8 @@ private void generateSingleValueProperty(
final Token typeToken,
final String indent)
{
final String elementTypeName = cppTypeName(typeToken.encoding().primitiveType());
final Encoding encoding = typeToken.encoding();
final String elementTypeName = cppTypeName(encoding.primitiveType());
final CharSequence typeName = typeWithFieldOptionality(
fieldToken,
elementTypeName
Expand Down Expand Up @@ -1518,13 +1520,41 @@ private void generateSingleValueProperty(
.append(indent).append(INDENT).append(fieldName).append(" = value;\n")
.append(indent).append("}\n");

generateSingleValuePropertyValidateMethod(
classBuilder,
codecClassName,
propertyName,
fieldToken,
indent,
validateMethod,
typeName,
formattedPropertyName,
elementTypeName,
encoding);
}

private static void generateSingleValuePropertyValidateMethod(
final ClassBuilder classBuilder,
final String codecClassName,
final String propertyName,
final Token fieldToken,
final String indent,
final String validateMethod,
final CharSequence typeName,
final String formattedPropertyName,
final String elementTypeName,
final Encoding encoding)
{
final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n")
.append(indent).append("static void ").append(validateMethod).append("(")
.append(typeName).append(" value)\n")
.append(indent).append("{\n");

String value = "value";

final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue());
final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue());

if (fieldToken.isOptionalEncoding())
{
validateBuilder.append(indent).append(INDENT)
Expand All @@ -1548,27 +1578,48 @@ private void generateSingleValueProperty(
.append(indent).append(INDENT)
.append("}\n");

if (mustPreventLesser || mustPreventGreater)
{
validateBuilder.append(indent).append(INDENT)
.append(elementTypeName).append(" actualValue = value.value();\n");

value = "actualValue";
}
}

if (mustPreventLesser)
{
validateBuilder.append(indent).append(INDENT)
.append(elementTypeName).append(" actualValue = value.value();\n");
.append("if (").append(value).append(" < ")
.append(codecClassName).append("::").append(formattedPropertyName).append("MinValue())\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw std::invalid_argument(\"")
.append(propertyName)
.append(": value is less than allowed minimum: \" + std::to_string(")
.append(value).append("));\n")
.append(indent).append(INDENT)
.append("}\n");
}

value = "actualValue";
if (mustPreventGreater)
{
validateBuilder.append(indent).append(INDENT)
.append("if (").append(value).append(" > ")
.append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw std::invalid_argument(\"")
.append(propertyName)
.append(": value is greater than allowed maximum: \" + std::to_string(")
.append(value).append("));\n")
.append(indent).append(INDENT)
.append("}\n");
}

validateBuilder.append(indent).append(INDENT)
.append("if (").append(value).append(" < ")
.append(codecClassName).append("::").append(formattedPropertyName).append("MinValue() || ")
.append(value).append(" > ")
.append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw std::invalid_argument(\"")
.append(propertyName)
.append(": value is out of allowed range: \" + std::to_string(")
.append(value).append("));\n")
.append(indent).append(INDENT)
.append("}\n")
.append(indent).append("}\n");
validateBuilder.append(indent).append("}\n");
}

private void generateConstPropertyMethods(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.ir.Encoding;
import uk.co.real_logic.sbe.ir.Ir;
import uk.co.real_logic.sbe.ir.Signal;
import uk.co.real_logic.sbe.ir.Token;
Expand Down Expand Up @@ -1194,7 +1195,8 @@ private void generateSingleValueProperty(
final String indent)
{
final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : "";
final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()) + nullableSuffix;
final Encoding encoding = typeToken.encoding();
final String typeName = cSharpTypeName(encoding.primitiveType()) + nullableSuffix;
final String formattedPropertyName = formatPropertyName(propertyName);
final String fieldName = "_" + toLowerFirstChar(propertyName);

Expand Down Expand Up @@ -1242,17 +1244,35 @@ private void generateSingleValueProperty(
.append("}\n");
}

final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue());
if (mustPreventLesser)
{
sb.append(indent).append(INDENT)
.append("if (value < ")
.append(codecClassName).append(".").append(formattedPropertyName).append("MinValue)\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw new ArgumentException(\"value is less than minimum allowed: \" + value);\n")
.append(indent).append(INDENT)
.append("}\n");
}

final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue());
if (mustPreventGreater)
{
sb.append(indent).append(INDENT)
.append("if (value > ")
.append(codecClassName).append(".").append(formattedPropertyName).append("MaxValue)\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw new ArgumentException(\"value is greater than maximum allowed: \" + value);\n")
.append(indent).append(INDENT)
.append("}\n");
}

sb.append(indent).append(INDENT)
.append("if (value < ")
.append(codecClassName).append(".").append(formattedPropertyName).append("MinValue || value > ")
.append(codecClassName).append(".").append(formattedPropertyName).append("MaxValue)\n")
.append(indent).append(INDENT)
.append("{\n")
.append(indent).append(INDENT).append(INDENT)
.append("throw new ArgumentException(\"value is out of allowed range: \" + value);\n")
.append(indent).append(INDENT)
.append("}\n")
.append(indent).append(INDENT)
.append("return value;\n")
.append(indent).append("}\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit d93b337

Please sign in to comment.