@@ -2249,6 +2249,7 @@ typedef struct JsonStack {
22492249 size_t n_elements , n_elements_allocated ;
22502250 unsigned line_before ;
22512251 unsigned column_before ;
2252+ size_t n_suppress ; /* When building: if > 0, suppress this many subsequent elements. If == (size_t) -1, suppress all subsequent elements */
22522253} JsonStack ;
22532254
22542255static void json_stack_release (JsonStack * s ) {
@@ -2656,6 +2657,8 @@ int json_buildv(JsonVariant **ret, va_list ap) {
26562657
26572658 for (;;) {
26582659 _cleanup_ (json_variant_unrefp ) JsonVariant * add = NULL ;
2660+ size_t n_subtract = 0 ; /* how much to subtract from current->n_suppress, i.e. how many elements would
2661+ * have been added to the current variant */
26592662 JsonStack * current ;
26602663 int command ;
26612664
@@ -2679,9 +2682,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
26792682
26802683 p = va_arg (ap , const char * );
26812684
2682- r = json_variant_new_string (& add , p );
2683- if (r < 0 )
2684- goto finish ;
2685+ if (current -> n_suppress == 0 ) {
2686+ r = json_variant_new_string (& add , p );
2687+ if (r < 0 )
2688+ goto finish ;
2689+ }
2690+
2691+ n_subtract = 1 ;
26852692
26862693 if (current -> expect == EXPECT_TOPLEVEL )
26872694 current -> expect = EXPECT_END ;
@@ -2703,9 +2710,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
27032710
27042711 j = va_arg (ap , intmax_t );
27052712
2706- r = json_variant_new_integer (& add , j );
2707- if (r < 0 )
2708- goto finish ;
2713+ if (current -> n_suppress == 0 ) {
2714+ r = json_variant_new_integer (& add , j );
2715+ if (r < 0 )
2716+ goto finish ;
2717+ }
2718+
2719+ n_subtract = 1 ;
27092720
27102721 if (current -> expect == EXPECT_TOPLEVEL )
27112722 current -> expect = EXPECT_END ;
@@ -2727,9 +2738,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
27272738
27282739 j = va_arg (ap , uintmax_t );
27292740
2730- r = json_variant_new_unsigned (& add , j );
2731- if (r < 0 )
2732- goto finish ;
2741+ if (current -> n_suppress == 0 ) {
2742+ r = json_variant_new_unsigned (& add , j );
2743+ if (r < 0 )
2744+ goto finish ;
2745+ }
2746+
2747+ n_subtract = 1 ;
27332748
27342749 if (current -> expect == EXPECT_TOPLEVEL )
27352750 current -> expect = EXPECT_END ;
@@ -2751,9 +2766,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
27512766
27522767 d = va_arg (ap , long double );
27532768
2754- r = json_variant_new_real (& add , d );
2755- if (r < 0 )
2756- goto finish ;
2769+ if (current -> n_suppress == 0 ) {
2770+ r = json_variant_new_real (& add , d );
2771+ if (r < 0 )
2772+ goto finish ;
2773+ }
2774+
2775+ n_subtract = 1 ;
27572776
27582777 if (current -> expect == EXPECT_TOPLEVEL )
27592778 current -> expect = EXPECT_END ;
@@ -2775,9 +2794,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
27752794
27762795 b = va_arg (ap , int );
27772796
2778- r = json_variant_new_boolean (& add , b );
2779- if (r < 0 )
2780- goto finish ;
2797+ if (current -> n_suppress == 0 ) {
2798+ r = json_variant_new_boolean (& add , b );
2799+ if (r < 0 )
2800+ goto finish ;
2801+ }
2802+
2803+ n_subtract = 1 ;
27812804
27822805 if (current -> expect == EXPECT_TOPLEVEL )
27832806 current -> expect = EXPECT_END ;
@@ -2796,9 +2819,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
27962819 goto finish ;
27972820 }
27982821
2799- r = json_variant_new_null (& add );
2800- if (r < 0 )
2801- goto finish ;
2822+ if (current -> n_suppress == 0 ) {
2823+ r = json_variant_new_null (& add );
2824+ if (r < 0 )
2825+ goto finish ;
2826+ }
2827+
2828+ n_subtract = 1 ;
28022829
28032830 if (current -> expect == EXPECT_TOPLEVEL )
28042831 current -> expect = EXPECT_END ;
@@ -2816,12 +2843,16 @@ int json_buildv(JsonVariant **ret, va_list ap) {
28162843 goto finish ;
28172844 }
28182845
2846+ /* Note that we don't care for current->n_suppress here, after all the variant is already
2847+ * allocated anyway... */
28192848 add = va_arg (ap , JsonVariant * );
28202849 if (!add )
28212850 add = JSON_VARIANT_MAGIC_NULL ;
28222851 else
28232852 json_variant_ref (add );
28242853
2854+ n_subtract = 1 ;
2855+
28252856 if (current -> expect == EXPECT_TOPLEVEL )
28262857 current -> expect = EXPECT_END ;
28272858 else if (current -> expect == EXPECT_OBJECT_VALUE )
@@ -2841,13 +2872,17 @@ int json_buildv(JsonVariant **ret, va_list ap) {
28412872
28422873 l = va_arg (ap , const char * );
28432874
2844- if (!l )
2845- add = JSON_VARIANT_MAGIC_NULL ;
2846- else {
2875+ if (l ) {
2876+ /* Note that we don't care for current->n_suppress here, we should generate parsing
2877+ * errors even in suppressed object properties */
2878+
28472879 r = json_parse (l , & add , NULL , NULL );
28482880 if (r < 0 )
28492881 goto finish ;
2850- }
2882+ } else
2883+ add = JSON_VARIANT_MAGIC_NULL ;
2884+
2885+ n_subtract = 1 ;
28512886
28522887 if (current -> expect == EXPECT_TOPLEVEL )
28532888 current -> expect = EXPECT_END ;
@@ -2881,6 +2916,10 @@ int json_buildv(JsonVariant **ret, va_list ap) {
28812916
28822917 stack [n_stack ++ ] = (JsonStack ) {
28832918 .expect = EXPECT_ARRAY_ELEMENT ,
2919+ .n_suppress = current -> n_suppress != 0 ? (size_t ) -1 : 0 , /* if we shall suppress the
2920+ * new array, then we should
2921+ * also suppress all array
2922+ * members */
28842923 };
28852924
28862925 break ;
@@ -2893,9 +2932,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
28932932
28942933 assert (n_stack > 1 );
28952934
2896- r = json_variant_new_array (& add , current -> elements , current -> n_elements );
2897- if (r < 0 )
2898- goto finish ;
2935+ if (current -> n_suppress == 0 ) {
2936+ r = json_variant_new_array (& add , current -> elements , current -> n_elements );
2937+ if (r < 0 )
2938+ goto finish ;
2939+ }
2940+
2941+ n_subtract = 1 ;
28992942
29002943 json_stack_release (current );
29012944 n_stack -- , current -- ;
@@ -2912,9 +2955,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
29122955
29132956 l = va_arg (ap , char * * );
29142957
2915- r = json_variant_new_array_strv (& add , l );
2916- if (r < 0 )
2917- goto finish ;
2958+ if (current -> n_suppress == 0 ) {
2959+ r = json_variant_new_array_strv (& add , l );
2960+ if (r < 0 )
2961+ goto finish ;
2962+ }
2963+
2964+ n_subtract = 1 ;
29182965
29192966 if (current -> expect == EXPECT_TOPLEVEL )
29202967 current -> expect = EXPECT_END ;
@@ -2948,6 +2995,10 @@ int json_buildv(JsonVariant **ret, va_list ap) {
29482995
29492996 stack [n_stack ++ ] = (JsonStack ) {
29502997 .expect = EXPECT_OBJECT_KEY ,
2998+ .n_suppress = current -> n_suppress != 0 ? (size_t ) -1 : 0 , /* if we shall suppress the
2999+ * new object, then we should
3000+ * also suppress all object
3001+ * members */
29513002 };
29523003
29533004 break ;
@@ -2961,9 +3012,13 @@ int json_buildv(JsonVariant **ret, va_list ap) {
29613012
29623013 assert (n_stack > 1 );
29633014
2964- r = json_variant_new_object (& add , current -> elements , current -> n_elements );
2965- if (r < 0 )
2966- goto finish ;
3015+ if (current -> n_suppress == 0 ) {
3016+ r = json_variant_new_object (& add , current -> elements , current -> n_elements );
3017+ if (r < 0 )
3018+ goto finish ;
3019+ }
3020+
3021+ n_subtract = 1 ;
29673022
29683023 json_stack_release (current );
29693024 n_stack -- , current -- ;
@@ -2980,22 +3035,64 @@ int json_buildv(JsonVariant **ret, va_list ap) {
29803035
29813036 n = va_arg (ap , const char * );
29823037
2983- r = json_variant_new_string (& add , n );
2984- if (r < 0 )
3038+ if (current -> n_suppress == 0 ) {
3039+ r = json_variant_new_string (& add , n );
3040+ if (r < 0 )
3041+ goto finish ;
3042+ }
3043+
3044+ n_subtract = 1 ;
3045+
3046+ current -> expect = EXPECT_OBJECT_VALUE ;
3047+ break ;
3048+ }
3049+
3050+ case _JSON_BUILD_PAIR_CONDITION : {
3051+ const char * n ;
3052+ bool b ;
3053+
3054+ if (current -> expect != EXPECT_OBJECT_KEY ) {
3055+ r = - EINVAL ;
29853056 goto finish ;
3057+ }
3058+
3059+ b = va_arg (ap , int );
3060+ n = va_arg (ap , const char * );
3061+
3062+ if (b && current -> n_suppress == 0 ) {
3063+ r = json_variant_new_string (& add , n );
3064+ if (r < 0 )
3065+ goto finish ;
3066+ }
3067+
3068+ n_subtract = 1 ; /* we generated one item */
3069+
3070+ if (!b && current -> n_suppress != (size_t ) -1 )
3071+ current -> n_suppress += 2 ; /* Suppress this one and the next item */
29863072
29873073 current -> expect = EXPECT_OBJECT_VALUE ;
29883074 break ;
29893075 }}
29903076
2991- if (add ) {
3077+ /* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */
3078+ if (add && current -> n_suppress == 0 ) {
29923079 if (!GREEDY_REALLOC (current -> elements , current -> n_elements_allocated , current -> n_elements + 1 )) {
29933080 r = - ENOMEM ;
29943081 goto finish ;
29953082 }
29963083
29973084 current -> elements [current -> n_elements ++ ] = TAKE_PTR (add );
29983085 }
3086+
3087+ /* If we are supposed to suppress items, let's subtract how many items where generated from that
3088+ * counter. Except if the counter is (size_t) -1, i.e. we shall suppress an infinite number of elements
3089+ * on this stack level */
3090+ if (current -> n_suppress != (size_t ) -1 ) {
3091+ if (current -> n_suppress <= n_subtract ) /* Saturated */
3092+ current -> n_suppress = 0 ;
3093+ else
3094+ current -> n_suppress -= n_subtract ;
3095+ }
29993096 }
30003097
30013098done :
0 commit comments