@@ -138,6 +138,7 @@ public void generate() throws IOException
138
138
generateGroups (sb , groups , BASE_INDENT );
139
139
generateVarData (sb , className , varData , BASE_INDENT );
140
140
generateDisplay (sb , msgToken .name (), fields , groups , varData , BASE_INDENT + INDENT );
141
+ sb .append (generateMessageLength (fields , groups , varData , BASE_INDENT + INDENT ));
141
142
sb .append ("};\n " );
142
143
sb .append (CppUtil .closingBraces (ir .namespaces ().length )).append ("#endif\n " );
143
144
out .append (sb );
@@ -178,6 +179,7 @@ private void generateGroups(final StringBuilder sb, final List<Token> tokens, fi
178
179
generateVarData (sb , formatClassName (groupName ), varData , indent + INDENT );
179
180
180
181
sb .append (generateGroupDisplay (groupName , fields , groups , varData , indent + INDENT + INDENT ));
182
+ sb .append (generateMessageLength (fields , groups , varData , indent + INDENT + INDENT ));
181
183
182
184
sb .append (indent ).append (" };\n " );
183
185
generateGroupProperty (sb , groupName , groupToken , cppTypeForNumInGroup , indent );
@@ -1067,6 +1069,7 @@ private static CharSequence generateFileHeader(
1067
1069
"#include <stdexcept>\n " +
1068
1070
"#include <sstream>\n " +
1069
1071
"#include <string>\n " +
1072
+ "#include <vector>\n " +
1070
1073
"\n " +
1071
1074
1072
1075
"#if defined(WIN32) || defined(_WIN32)\n " +
@@ -2765,4 +2768,263 @@ private CharSequence generateEnumDisplay(final List<Token> tokens, final Token e
2765
2768
2766
2769
return sb ;
2767
2770
}
2771
+
2772
+ private Object [] generateMessageLengthArgs (
2773
+ final List <Token > fields ,
2774
+ final List <Token > groups ,
2775
+ final List <Token > varData ,
2776
+ final String indent ,
2777
+ final boolean withName )
2778
+ {
2779
+ final StringBuilder sb = new StringBuilder ();
2780
+ int count = 0 ;
2781
+
2782
+ for (int i = 0 , size = groups .size (); i < size ; i ++)
2783
+ {
2784
+ final Token groupToken = groups .get (i );
2785
+ if (groupToken .signal () != Signal .BEGIN_GROUP )
2786
+ {
2787
+ throw new IllegalStateException ("tokens must begin with BEGIN_GROUP: token=" + groupToken );
2788
+ }
2789
+
2790
+ final int endSignal = findEndSignal (groups , i , Signal .END_GROUP , groupToken .name ());
2791
+
2792
+ if (count > 0 )
2793
+ {
2794
+ sb .append (",\n " + indent );
2795
+ }
2796
+
2797
+ final List <Token > thisGroup = groups .subList (i , endSignal + 1 );
2798
+
2799
+ if (isMessageConstLength (thisGroup ))
2800
+ {
2801
+ sb .append ("std::size_t" );
2802
+ if (withName )
2803
+ {
2804
+ sb .append (" " + groupToken .name () + "Length = 0" );
2805
+ }
2806
+ }
2807
+ else
2808
+ {
2809
+ sb .append ("const std::vector<std::tuple<" );
2810
+ sb .append (generateMessageLengthArgs (thisGroup , indent + INDENT , false )[0 ]);
2811
+ sb .append (">>&" );
2812
+
2813
+ if (withName )
2814
+ {
2815
+ sb .append (" " + groupToken .name () + "ItemLengths = {}" );
2816
+ }
2817
+ }
2818
+
2819
+ count += 1 ;
2820
+
2821
+ i = endSignal ;
2822
+ }
2823
+
2824
+ for (int i = 0 , size = varData .size (); i < size ;)
2825
+ {
2826
+ final Token varDataToken = varData .get (i );
2827
+ if (varDataToken .signal () != Signal .BEGIN_VAR_DATA )
2828
+ {
2829
+ throw new IllegalStateException ("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken );
2830
+ }
2831
+
2832
+ if (count > 0 )
2833
+ {
2834
+ sb .append (",\n " + indent );
2835
+ }
2836
+
2837
+ sb .append ("std::size_t" );
2838
+ if (withName )
2839
+ {
2840
+ sb .append (" " + varDataToken .name () + "Length = 0" );
2841
+ }
2842
+
2843
+ count += 1 ;
2844
+
2845
+ i += varDataToken .componentTokenCount ();
2846
+ }
2847
+
2848
+ CharSequence result = sb ;
2849
+ if (count > 1 )
2850
+ {
2851
+ result = "\n " + indent + result ;
2852
+ }
2853
+
2854
+ return new Object []{result , count };
2855
+ }
2856
+
2857
+ private Object [] generateMessageLengthArgs (
2858
+ final List <Token > tokens ,
2859
+ final String indent ,
2860
+ final boolean withName )
2861
+ {
2862
+ int i = 0 ;
2863
+
2864
+ final Token groupToken = tokens .get (i );
2865
+ if (groupToken .signal () != Signal .BEGIN_GROUP )
2866
+ {
2867
+ throw new IllegalStateException ("tokens must begin with BEGIN_GROUP: token=" + groupToken );
2868
+ }
2869
+
2870
+ ++i ;
2871
+ final int groupHeaderTokenCount = tokens .get (i ).componentTokenCount ();
2872
+ i += groupHeaderTokenCount ;
2873
+
2874
+ final List <Token > fields = new ArrayList <>();
2875
+ i = collectFields (tokens , i , fields );
2876
+
2877
+ final List <Token > groups = new ArrayList <>();
2878
+ i = collectGroups (tokens , i , groups );
2879
+
2880
+ final List <Token > varData = new ArrayList <>();
2881
+ i = collectVarData (tokens , i , varData );
2882
+
2883
+ return generateMessageLengthArgs (fields , groups , varData , indent , withName );
2884
+ }
2885
+
2886
+ private boolean isMessageConstLength (final List <Token > tokens )
2887
+ {
2888
+ final Integer count = (Integer )generateMessageLengthArgs (tokens , "" , false )[1 ];
2889
+
2890
+ return (count == 0 );
2891
+ }
2892
+
2893
+ private CharSequence generateMessageLengthCallPre17Helper (final List <Token > tokens )
2894
+ {
2895
+ final StringBuilder sb = new StringBuilder ();
2896
+
2897
+ final Integer count = (Integer )generateMessageLengthArgs (tokens , "" , false )[1 ];
2898
+
2899
+ for (int i = 0 ; i < count ; i ++)
2900
+ {
2901
+ if (i > 0 )
2902
+ {
2903
+ sb .append (", " );
2904
+ }
2905
+ new Formatter (sb ).format ("std::get<%1$d>(e)" , i );
2906
+ }
2907
+
2908
+ return sb ;
2909
+ }
2910
+
2911
+ private CharSequence generateMessageLength (
2912
+ final List <Token > fields ,
2913
+ final List <Token > groups ,
2914
+ final List <Token > varData ,
2915
+ final String indent )
2916
+ {
2917
+ final StringBuilder sbEncode = new StringBuilder ();
2918
+
2919
+ for (int i = 0 , size = groups .size (); i < size ; i ++)
2920
+ {
2921
+ final Token groupToken = groups .get (i );
2922
+
2923
+ if (groupToken .signal () != Signal .BEGIN_GROUP )
2924
+ {
2925
+ throw new IllegalStateException ("tokens must begin with BEGIN_GROUP: token=" + groupToken );
2926
+ }
2927
+
2928
+ final int endSignal = findEndSignal (groups , i , Signal .END_GROUP , groupToken .name ());
2929
+ final List <Token > thisGroup = groups .subList (i , endSignal + 1 );
2930
+
2931
+ final Token numInGroupToken = Generators .findFirst ("numInGroup" , groups , i );
2932
+ final long minCount = numInGroupToken .encoding ().applicableMinValue ().longValue ();
2933
+ final long maxCount = numInGroupToken .encoding ().applicableMaxValue ().longValue ();
2934
+
2935
+ final String countName = groupToken .name () +
2936
+ (isMessageConstLength (thisGroup ) ? "Length" : "ItemLengths.size()" );
2937
+
2938
+ final String minCheck = minCount > 0 ? countName + " < " + minCount + " || " : "" ;
2939
+ final String maxCheck = countName + " > " + maxCount ;
2940
+
2941
+ new Formatter (sbEncode ).format ("\n " +
2942
+ indent + " length += %1$s::sbeHeaderSize();\n " ,
2943
+ formatClassName (groupToken .name ()));
2944
+
2945
+ if (isMessageConstLength (thisGroup ))
2946
+ {
2947
+ new Formatter (sbEncode ).format (
2948
+ indent + " if (%3$s%4$s)\n " +
2949
+ indent + " {\n " +
2950
+ indent + " throw std::runtime_error(\" %5$s outside of allowed range [E110]\" );\n " +
2951
+ indent + " }\n " +
2952
+ indent + " length += %1$sLength * %2$s::sbeBlockLength();\n " ,
2953
+ groupToken .name (),
2954
+ formatClassName (groupToken .name ()),
2955
+ minCheck ,
2956
+ maxCheck ,
2957
+ countName );
2958
+ }
2959
+ else
2960
+ {
2961
+ new Formatter (sbEncode ).format (
2962
+ indent + " if (%3$s%4$s)\n " +
2963
+ indent + " {\n " +
2964
+ indent + " throw std::runtime_error(\" %5$s outside of allowed range [E110]\" );\n " +
2965
+ indent + " }\n " +
2966
+ indent + " for (const auto& e: %1$sItemLengths)\n " +
2967
+ indent + " {\n " +
2968
+ indent + " #if __cpluplus >= 201703L\n " +
2969
+ indent + " length += std::apply(%2$s::computeLength, e);\n " +
2970
+ indent + " #else\n " +
2971
+ indent + " length += %2$s::computeLength(%6$s);\n " +
2972
+ indent + " #endif\n " +
2973
+ indent + " }\n " ,
2974
+ groupToken .name (),
2975
+ formatClassName (groupToken .name ()),
2976
+ minCheck ,
2977
+ maxCheck ,
2978
+ countName ,
2979
+ generateMessageLengthCallPre17Helper (thisGroup ));
2980
+ }
2981
+
2982
+ i = endSignal ;
2983
+ }
2984
+
2985
+ for (int i = 0 , size = varData .size (); i < size ;)
2986
+ {
2987
+ final Token varDataToken = varData .get (i );
2988
+
2989
+ if (varDataToken .signal () != Signal .BEGIN_VAR_DATA )
2990
+ {
2991
+ throw new IllegalStateException ("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken );
2992
+ }
2993
+
2994
+ final Token lengthToken = Generators .findFirst ("length" , varData , i );
2995
+
2996
+ new Formatter (sbEncode ).format ("\n " +
2997
+ indent + " length += %1$sHeaderLength();\n " +
2998
+ indent + " if (%1$sLength > %2$d)\n " +
2999
+ indent + " {\n " +
3000
+ indent + " throw std::runtime_error(\" %1$sLength too long for length type [E109]\" );\n " +
3001
+ indent + " }\n " +
3002
+ indent + " length += %1$sLength;\n " ,
3003
+ varDataToken .name (),
3004
+ lengthToken .encoding ().applicableMaxValue ().longValue ());
3005
+
3006
+ i += varDataToken .componentTokenCount ();
3007
+ }
3008
+
3009
+ final StringBuilder sb = new StringBuilder ();
3010
+
3011
+ new Formatter (sb ).format ("\n " +
3012
+ indent + "SBE_NODISCARD static SBE_CONSTEXPR_14 size_t computeLength(%1$s)\n " +
3013
+ indent + "{\n " +
3014
+ "#if defined(__GNUG__) && !defined(__clang__)\n " +
3015
+ "#pragma GCC diagnostic push\n " +
3016
+ "#pragma GCC diagnostic ignored \" -Wtype-limits\" \n " +
3017
+ "#endif\n " +
3018
+ indent + " size_t length = sbeBlockLength();\n \n " +
3019
+ "%2$s" +
3020
+ indent + " return length;\n " +
3021
+ "#if defined(__GNUG__) && !defined(__clang__)\n " +
3022
+ "#pragma GCC diagnostic pop\n " +
3023
+ "#endif\n " +
3024
+ indent + "}\n " ,
3025
+ generateMessageLengthArgs (fields , groups , varData , indent + INDENT , true )[0 ],
3026
+ sbEncode .toString ());
3027
+
3028
+ return sb ;
3029
+ }
2768
3030
}
0 commit comments