private CharSequence appendDisplay(
        final List<Token> fields, final List<Token> groups, final List<Token> varData, final String indent)
    {
        final StringBuilder sb = new StringBuilder();
        final boolean[] atLeastOne = { false };

        for (int i = 0, size = fields.size(); i < size;)
        {
            final Token fieldToken = fields.get(i);
            final Token encodingToken = fields.get(fieldToken.signal() == Signal.BEGIN_FIELD ? i + 1 : i);

            writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent);
            i += fieldToken.componentTokenCount();
        }

        for (int i = 0, size = groups.size(); i < size; i++)
        {
            final Token groupToken = groups.get(i);
            if (groupToken.signal() != Signal.BEGIN_GROUP)
            {
                throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken);
            }

            if (atLeastOne[0])
            {
                sb.append(indent).append("builder << \", \";\n");
            }
            atLeastOne[0] = true;

            new Formatter(sb).format(
                indent + "{\n" +
                indent + "    bool atLeastOne = false;\n" +
                indent + "    builder << R\"(\"%3$s\": [)\";\n" +
                indent + "    writer.%2$s().forEach(\n" +
                indent + "        [&](%1$s &%2$s)\n" +
                indent + "        {\n" +
                indent + "            if (atLeastOne)\n" +
                indent + "            {\n" +
                indent + "                builder << \", \";\n" +
                indent + "            }\n" +
                indent + "            atLeastOne = true;\n" +
                indent + "            builder << %2$s;\n" +
                indent + "        });\n" +
                indent + "    builder << ']';\n" +
                indent + "}\n\n",
                formatClassName(groupToken.name()),
                formatPropertyName(groupToken.name()),
                groupToken.name());

            i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name());
        }

        for (int i = 0, size = varData.size(); i < size;)
        {
            final Token varDataToken = varData.get(i);
            if (varDataToken.signal() != Signal.BEGIN_VAR_DATA)
            {
                throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken);
            }

            if (atLeastOne[0])
            {
                sb.append(indent).append("builder << \", \";\n");
            }
            atLeastOne[0] = true;

            final String characterEncoding = varData.get(i + 3).encoding().characterEncoding();
            sb.append(indent).append("builder << R\"(\"").append(varDataToken.name()).append("\": )\";\n");

            if (null == characterEncoding)
            {
                final String skipFunction = "writer.skip" + toUpperFirstChar(varDataToken.name()) + "()";

                sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT).append(skipFunction)
                    .append(" << \" bytes of raw data\\\"\";\n");
            }
            else
            {
                final String getAsStringFunction =
                    "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsJsonEscapedString().c_str()";

                sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT)
                    .append(getAsStringFunction).append(" << '\"';\n\n");
            }

            i += varDataToken.componentTokenCount();
        }

        return sb;
    }
\n");
        sb.append("     * The states in which a encoder/decoder/codec can live.\n");
        sb.append("     *\n");
        sb.append("     * <p>The state machine diagram below, encoded in the dot language, describes\n");
        sb.append("     * the valid state transitions according to the order in which fields may be\n");
        sb.append("     * accessed safely. Tools such as PlantUML and Graphviz can render it.\n");
        sb.append("     *\n");
        sb.append("     * <pre>{@code\n");
        fieldPrecedenceModel.generateGraph(sb, "     *   ");
        sb.append("     * }</pre>\n");
        sb.append("
sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java