@@ -302,6 +302,11 @@ private static void generateGroupClassHeader(
302302 indent + " *m_positionPtr = sbeCheckPosition(position);\n " +
303303 indent + " }\n \n " +
304304
305+ indent + " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n " +
306+ indent + " {\n " +
307+ indent + " return ::sbeEscapeJsonString(s);\n " +
308+ indent + " }\n \n " +
309+
305310 indent + " SBE_NODISCARD inline std::uint64_t count() const SBE_NOEXCEPT\n " +
306311 indent + " {\n " +
307312 indent + " return m_count;\n " +
@@ -1010,7 +1015,9 @@ private static CharSequence generateFileHeader(
10101015 "#include <cstring>\n " +
10111016 "#include <limits>\n " +
10121017 "#include <stdexcept>\n \n " +
1013- "#include <ostream>\n \n " +
1018+ "#include <ostream>\n " +
1019+ "#include <sstream>\n " +
1020+ "#include <iomanip>\n \n " +
10141021
10151022 "#if defined(WIN32) || defined(_WIN32)\n " +
10161023 "# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)\n " +
@@ -1053,10 +1060,12 @@ private static CharSequence generateFileHeader(
10531060 "#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()\n " +
10541061 "#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()\n " +
10551062 "#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()\n " +
1056- "#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()\n " ,
1063+ "#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()\n \n " ,
10571064 String .join ("_" , namespaces ).toUpperCase (),
10581065 className .toUpperCase ()));
10591066
1067+ sb .append (generateEscapeFunction ());
1068+
10601069 if (typesToInclude != null && typesToInclude .size () != 0 )
10611070 {
10621071 sb .append ("\n " );
@@ -1073,12 +1082,35 @@ private static CharSequence generateFileHeader(
10731082 return sb ;
10741083 }
10751084
1085+ private static CharSequence generateEscapeFunction ()
1086+ {
1087+ return
1088+ "#ifndef _SBE_JSON_ESCAPE_FUNC_H_\n " +
1089+ "#define _SBE_JSON_ESCAPE_FUNC_H_\n " +
1090+ "static inline std::string sbeEscapeJsonString(const std::string &s)\n " +
1091+ "{\n " +
1092+ " std::ostringstream oss;\n \n " +
1093+ " for (auto c = s.cbegin(); c != s.cend(); c++)\n " +
1094+ " {\n " +
1095+ " if (*c == '\" ' || *c == '\\ \\ ' || ('\\ x00' <= *c && *c <= '\\ x1f'))\n " +
1096+ " {\n " +
1097+ " oss << \" \\ \\ u\" " + " << std::hex << std::setw(4) << std::setfill('0') << (int)*c;\n " +
1098+ " }\n " +
1099+ " else\n " +
1100+ " {\n " +
1101+ " oss << *c;\n " +
1102+ " }\n " +
1103+ " }\n \n " +
1104+ " return oss.str();\n " +
1105+ "}\n " +
1106+ "#endif\n \n " ;
1107+ }
1108+
10761109 private static CharSequence generateClassDeclaration (final String className )
10771110 {
1078- return String .format (
1079- "class %s\n " +
1080- "{\n " ,
1081- className );
1111+ return
1112+ "class " + className + "\n " +
1113+ "{\n " ;
10821114 }
10831115
10841116 private static CharSequence generateEnumDeclaration (final String name )
@@ -1903,6 +1935,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final
19031935 " m_position = sbeCheckPosition(position);\n " +
19041936 " }\n \n " +
19051937
1938+ " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n " +
1939+ " {\n " +
1940+ " return ::sbeEscapeJsonString(s);\n " +
1941+ " }\n \n " +
1942+
19061943 " SBE_NODISCARD std::uint64_t encodedLength() const SBE_NOEXCEPT\n " +
19071944 " {\n " +
19081945 " return sbePosition() - m_offset;\n " +
@@ -2320,7 +2357,7 @@ private CharSequence generateDisplay(
23202357 indent + " builder << writer.sbeTemplateId();\n " +
23212358 indent + " builder << \" , \" ;\n \n " +
23222359 "%2$s" +
2323- indent + " builder << '}';\n " +
2360+ indent + " builder << '}';\n \n " +
23242361 indent + " return builder;\n " +
23252362 indent + "}\n " ,
23262363 formatClassName (name ),
@@ -2341,7 +2378,7 @@ private CharSequence generateGroupDisplay(
23412378 indent + "{\n " +
23422379 indent + " builder << '{';\n " +
23432380 "%2$s" +
2344- indent + " builder << '}';\n " +
2381+ indent + " builder << '}';\n \n " +
23452382 indent + " return builder;\n " +
23462383 indent + "}\n " ,
23472384 formatClassName (name ),
@@ -2360,7 +2397,7 @@ private CharSequence generateCompositeDisplay(
23602397 indent + "{\n " +
23612398 indent + " builder << '{';\n " +
23622399 "%2$s" +
2363- indent + " builder << '}';\n " +
2400+ indent + " builder << '}';\n \n " +
23642401 indent + " return builder;\n " +
23652402 indent + "}\n \n " ,
23662403 formatClassName (name ),
@@ -2453,20 +2490,25 @@ private CharSequence appendDisplay(
24532490 atLeastOne [0 ] = true ;
24542491
24552492 final String characterEncoding = varData .get (i + 3 ).encoding ().characterEncoding ();
2456- final String getAsStringFunction = "get" + toUpperFirstChar (varDataToken .name ()) + "AsString().c_str()" ;
24572493 sb .append (indent + "builder << R\" (\" " + varDataToken .name () + "\" : )\" ;\n " );
24582494
24592495 if (null == characterEncoding )
24602496 {
2497+ final String getAsStringFunction =
2498+ "writer.get" + toUpperFirstChar (varDataToken .name ()) + "AsString().c_str()" ;
2499+
24612500 sb .append (
24622501 indent + "builder << '\" ' <<\n " +
2463- indent + INDENT + "writer." + getAsStringFunction + " << '\" ';\n \n " );
2502+ indent + INDENT + getAsStringFunction + " << '\" ';\n \n " );
24642503 }
24652504 else
24662505 {
2506+ final String getAsStringFunction =
2507+ "writer.sbeEscapeJson(writer.get" + toUpperFirstChar (varDataToken .name ()) + "AsString()).c_str()" ;
2508+
24672509 sb .append (
24682510 indent + "builder << '\" ' <<\n " +
2469- indent + INDENT + "writer." + getAsStringFunction + " << '\" ';\n \n " );
2511+ indent + INDENT + getAsStringFunction + " << '\" ';\n \n " );
24702512 }
24712513
24722514 i += varDataToken .componentTokenCount ();
@@ -2510,8 +2552,8 @@ private CharSequence writeTokenDisplay(
25102552 {
25112553 sb .append (
25122554 indent + "builder << '\" ';\n " +
2513- indent + "for (size_t i = 0;\n " +
2514- indent + " i < " + fieldName + "Length() && " + fieldName + "(i) > 0;\n " +
2555+ indent + "for (size_t i = 0, length = " + fieldName + "Length() ;\n " +
2556+ indent + " i < length && " + fieldName + "(i) > 0;\n " +
25152557 indent + " i++)\n " +
25162558 indent + "{\n " +
25172559 indent + " builder << (char)" + fieldName + "(i);\n " +
@@ -2524,7 +2566,7 @@ private CharSequence writeTokenDisplay(
25242566 indent + "builder << '[';\n " +
25252567 indent + "if (" + fieldName + "Length() > 0)\n " +
25262568 indent + "{\n " +
2527- indent + " for (size_t i = 0; i < " + fieldName + "Length(); i++)\n " +
2569+ indent + " for (size_t i = 0, length = " + fieldName + "Length(); i < length ; i++)\n " +
25282570 indent + " {\n " +
25292571 indent + " if (i)\n " +
25302572 indent + " {\n " +
0 commit comments