Skip to content

Commit 0463eed

Browse files
committed
[C++] Complete and tidy up string handling for fixed length array fields plus reduce copying of string while generating codecs.
1 parent c043457 commit 0463eed

File tree

1 file changed

+65
-52
lines changed

1 file changed

+65
-52
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java

Lines changed: 65 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -521,39 +521,7 @@ private void generateVarData(
521521
lengthByteOrderStr,
522522
lengthCppType);
523523

524-
new Formatter(sb).format("\n" +
525-
indent + " std::string get%1$sAsJsonEscapedString()\n" +
526-
indent + " {\n" +
527-
"%2$s" +
528-
indent + " std::ostringstream oss;\n" +
529-
indent + " std::string s = get%1$sAsString();\n\n" +
530-
indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" +
531-
indent + " {\n" +
532-
indent + " switch (*c)\n" +
533-
indent + " {\n" +
534-
indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" +
535-
indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" +
536-
indent + " case '\\b': oss << \"\\\\b\"; break;\n" +
537-
indent + " case '\\f': oss << \"\\\\f\"; break;\n" +
538-
indent + " case '\\n': oss << \"\\\\n\"; break;\n" +
539-
indent + " case '\\r': oss << \"\\\\r\"; break;\n" +
540-
indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" +
541-
indent + " default:\n" +
542-
indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" +
543-
indent + " {\n" +
544-
indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" +
545-
indent + " << std::setfill('0') << (int)(*c);\n" +
546-
indent + " }\n" +
547-
indent + " else\n" +
548-
indent + " {\n" +
549-
indent + " oss << *c;\n" +
550-
indent + " }\n" +
551-
indent + " }\n" +
552-
indent + " }\n\n" +
553-
indent + " return oss.str();\n" +
554-
indent + " }\n",
555-
propertyName,
556-
generateStringNotPresentCondition(token.version(), indent));
524+
generateJsonEscapedStringGetter(sb, token, indent, propertyName);
557525

558526
new Formatter(sb).format("\n" +
559527
indent + " #if __cplusplus >= 201703L\n" +
@@ -1524,6 +1492,8 @@ private void generateArrayProperty(
15241492
offset,
15251493
arrayLength);
15261494

1495+
generateJsonEscapedStringGetter(sb, token, indent, propertyName);
1496+
15271497
new Formatter(sb).format("\n" +
15281498
indent + " #if __cplusplus >= 201703L\n" +
15291499
indent + " std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" +
@@ -1584,6 +1554,44 @@ private void generateArrayProperty(
15841554
}
15851555
}
15861556

1557+
private void generateJsonEscapedStringGetter(
1558+
final StringBuilder sb, final Token token, final String indent, final String propertyName)
1559+
{
1560+
new Formatter(sb).format("\n" +
1561+
indent + " std::string get%1$sAsJsonEscapedString()\n" +
1562+
indent + " {\n" +
1563+
"%2$s" +
1564+
indent + " std::ostringstream oss;\n" +
1565+
indent + " std::string s = get%1$sAsString();\n\n" +
1566+
indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" +
1567+
indent + " {\n" +
1568+
indent + " switch (*c)\n" +
1569+
indent + " {\n" +
1570+
indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" +
1571+
indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" +
1572+
indent + " case '\\b': oss << \"\\\\b\"; break;\n" +
1573+
indent + " case '\\f': oss << \"\\\\f\"; break;\n" +
1574+
indent + " case '\\n': oss << \"\\\\n\"; break;\n" +
1575+
indent + " case '\\r': oss << \"\\\\r\"; break;\n" +
1576+
indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" +
1577+
indent + " default:\n" +
1578+
indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" +
1579+
indent + " {\n" +
1580+
indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" +
1581+
indent + " << std::setfill('0') << (int)(*c);\n" +
1582+
indent + " }\n" +
1583+
indent + " else\n" +
1584+
indent + " {\n" +
1585+
indent + " oss << *c;\n" +
1586+
indent + " }\n" +
1587+
indent + " }\n" +
1588+
indent + " }\n\n" +
1589+
indent + " return oss.str();\n" +
1590+
indent + " }\n",
1591+
toUpperFirstChar(propertyName),
1592+
generateStringNotPresentCondition(token.version(), indent));
1593+
}
1594+
15871595
private void generateConstPropertyMethods(
15881596
final StringBuilder sb, final String propertyName, final Token token, final String indent)
15891597
{
@@ -1657,6 +1665,18 @@ private void generateConstPropertyMethods(
16571665
toUpperFirstChar(propertyName),
16581666
propertyName,
16591667
values);
1668+
1669+
new Formatter(sb).format("\n" +
1670+
indent + " std::string get%1$sAsString() const\n" +
1671+
indent + " {\n" +
1672+
indent + " static const std::uint8_t %1$sValues[] = { %2$s };\n\n" +
1673+
indent + " return std::string((const char *)%1$sValues, %3$s);\n" +
1674+
indent + " }\n",
1675+
toUpperFirstChar(propertyName),
1676+
values,
1677+
constantValue.length);
1678+
1679+
generateJsonEscapedStringGetter(sb, token, indent, propertyName);
16601680
}
16611681

16621682
private CharSequence generateFixedFlyweightCode(final String className, final int size)
@@ -2392,7 +2412,7 @@ private CharSequence appendDisplay(
23922412
final List<Token> fields, final List<Token> groups, final List<Token> varData, final String indent)
23932413
{
23942414
final StringBuilder sb = new StringBuilder();
2395-
final boolean[] atLeastOne = {false};
2415+
final boolean[] atLeastOne = { false };
23962416

23972417
for (int i = 0, size = fields.size(); i < size;)
23982418
{
@@ -2402,17 +2422,15 @@ private CharSequence appendDisplay(
24022422
{
24032423
final Token encodingToken = fields.get(i + 1);
24042424

2405-
sb.append(
2406-
writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n");
2425+
writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent);
24072426

24082427
i += fieldToken.componentTokenCount();
24092428
}
24102429
else
24112430
{
24122431
final Token encodingToken = fields.get(i);
24132432

2414-
sb.append(
2415-
writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n");
2433+
writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent);
24162434

24172435
i += fieldToken.componentTokenCount();
24182436
}
@@ -2501,19 +2519,18 @@ private CharSequence appendDisplay(
25012519
return sb;
25022520
}
25032521

2504-
private CharSequence writeTokenDisplay(
2522+
private void writeTokenDisplay(
2523+
final StringBuilder sb,
25052524
final String fieldTokenName,
25062525
final Token typeToken,
25072526
final boolean[] atLeastOne,
25082527
final String indent)
25092528
{
25102529
if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding())
25112530
{
2512-
return "";
2531+
return;
25132532
}
25142533

2515-
final StringBuilder sb = new StringBuilder();
2516-
25172534
if (atLeastOne[0])
25182535
{
25192536
sb.append(
@@ -2534,15 +2551,12 @@ private CharSequence writeTokenDisplay(
25342551
{
25352552
if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR)
25362553
{
2554+
final String getAsStringFunction =
2555+
"writer.get" + toUpperFirstChar(fieldTokenName) + "AsJsonEscapedString().c_str()";
2556+
25372557
sb.append(
2538-
indent + "builder << '\"';\n" +
2539-
indent + "for (size_t i = 0, length = " + fieldName + "Length();\n" +
2540-
indent + " i < length && " + fieldName + "(i) > 0;\n" +
2541-
indent + " i++)\n" +
2542-
indent + "{\n" +
2543-
indent + " builder << (char)" + fieldName + "(i);\n" +
2544-
indent + "}\n" +
2545-
indent + "builder << '\"';\n");
2558+
indent + "builder << '\"' <<\n" +
2559+
indent + INDENT + getAsStringFunction + " << '\"';\n");
25462560
}
25472561
else
25482562
{
@@ -2564,7 +2578,6 @@ private CharSequence writeTokenDisplay(
25642578
}
25652579
else
25662580
{
2567-
// have to duplicate because of checkstyle :/
25682581
if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR)
25692582
{
25702583
sb.append(
@@ -2597,7 +2610,7 @@ private CharSequence writeTokenDisplay(
25972610
break;
25982611
}
25992612

2600-
return sb;
2613+
sb.append('\n');
26012614
}
26022615

26032616
private CharSequence generateChoicesDisplay(final String name, final List<Token> tokens)

0 commit comments

Comments
 (0)