Hi Ales. This looks good to me.

Acked-by: Mark Michelson <[email protected]>

On Mon, Sep 22, 2025 at 6:13 AM Ales Musil via dev
<[email protected]> wrote:
>
> The vector has the same functionality as the x2nrealloc
> for insert. Use vector instead which slightly simplifies
> the final code.
>
> Signed-off-by: Ales Musil <[email protected]>
> ---
>  controller/lflow.c |  40 ++++----
>  include/ovn/expr.h |   3 +-
>  lib/actions.c      |  30 +++---
>  lib/expr.c         | 233 ++++++++++++++++++++++-----------------------
>  4 files changed, 156 insertions(+), 150 deletions(-)
>
> diff --git a/controller/lflow.c b/controller/lflow.c
> index 11ec33faf..197adaae9 100644
> --- a/controller/lflow.c
> +++ b/controller/lflow.c
> @@ -447,21 +447,24 @@ consider_lflow_for_added_as_ips__(
>      struct expr_constant_set *new_fake_as = NULL;
>      struct in6_addr dummy_ip;
>      bool has_dummy_ip = false;
> -    ovs_assert(as_diff_added->n_values);
> +    ovs_assert(vector_len(&as_diff_added->values));
>
>      /* When there is only 1 element, we append a dummy address and create a
>       * fake address set with 2 elements, so that the lflow parsing would
>       * generate exactly the same format of flows as it would when parsing 
> with
>       * the original address set. */
> -    if (as_diff_added->n_values == 1) {
> +    if (vector_len(&as_diff_added->values) == 1) {
>          new_fake_as = xzalloc(sizeof *new_fake_as);
> -        new_fake_as->values = xzalloc(sizeof *new_fake_as->values * 2);
> -        new_fake_as->n_values = 2;
> -        new_fake_as->values[0] = new_fake_as->values[1] =
> -            as_diff_added->values[0];
> +        new_fake_as->values =
> +            VECTOR_CAPACITY_INITIALIZER(struct expr_constant, 2);
> +        struct expr_constant c =
> +            vector_get(&as_diff_added->values, 0, struct expr_constant);
> +        vector_push(&new_fake_as->values, &c);
>          /* Make a dummy ip that is different from the real one. */
> -        new_fake_as->values[1].value.u8_val++;
> -        dummy_ip = new_fake_as->values[1].value.ipv6;
> +        c.value.u8_val++;
> +        dummy_ip = c.value.ipv6;
> +        vector_push(&new_fake_as->values, &c);
> +
>          has_dummy_ip = true;
>          fake_as = new_fake_as;
>      }
> @@ -528,13 +531,14 @@ consider_lflow_for_added_as_ips__(
>       * the generated matches can't be mapped from the items in the
>       * as_diff_added. So we need to fall back to reprocessing the lflow.
>       */
> -    if (hmap_count(&matches) != as_ref_count * as_diff_added->n_values) {
> +    size_t n_values = vector_len(&as_diff_added->values);
> +    if (hmap_count(&matches) != as_ref_count * n_values) {
>          VLOG_DBG("lflow "UUID_FMT", addrset %s: Generated flows count "
>                   "(%"PRIuSIZE") " "doesn't match added addresses count "
>                   "(%"PRIuSIZE") and ref_count (%"PRIuSIZE"). "
>                   "Need reprocessing.",
>                   UUID_ARGS(&lflow->header_.uuid), as_name,
> -                 hmap_count(&matches), as_diff_added->n_values, 
> as_ref_count);
> +                 hmap_count(&matches), n_values, as_ref_count);
>          handled = false;
>          goto done;
>      }
> @@ -610,19 +614,21 @@ as_update_can_be_handled(const char *as_name, struct 
> addr_set_diff *as_diff,
>      struct expr_constant_set *as = shash_find_data(l_ctx_in->addr_sets,
>                                                     as_name);
>      ovs_assert(as);
> -    size_t n_added = as_diff->added ? as_diff->added->n_values : 0;
> -    size_t n_deleted = as_diff->deleted ? as_diff->deleted->n_values : 0;
> -    size_t old_as_size = as->n_values + n_deleted - n_added;
> +    size_t n_values = vector_len(&as->values);
> +    size_t n_added = as_diff->added ? vector_len(&as_diff->added->values) : 
> 0;
> +    size_t n_deleted =
> +        as_diff->deleted ? vector_len(&as_diff->deleted->values) : 0;
> +    size_t old_as_size = n_values + n_deleted - n_added;
>
>      /* If the change may impact n_conj, i.e. the template of the flows would
>       * change, we must reprocess the lflow. */
> -    if (old_as_size <= 1 || as->n_values <= 1) {
> +    if (old_as_size <= 1 || n_values <= 1) {
>          return false;
>      }
>
>      /* If the size of the diff is too big, reprocessing may be more
>       * efficient than incrementally processing the diffs.  */
> -    if ((n_added + n_deleted) >= as->n_values) {
> +    if ((n_added + n_deleted) >= n_values) {
>          return false;
>      }
>
> @@ -719,8 +725,8 @@ lflow_handle_addr_set_update(const char *as_name,
>
>          if (as_diff->deleted) {
>              struct addrset_info as_info;
> -            for (size_t i = 0; i < as_diff->deleted->n_values; i++) {
> -                struct expr_constant *c = &as_diff->deleted->values[i];
> +            const struct expr_constant *c;
> +            VECTOR_FOR_EACH_PTR (&as_diff->deleted->values, c) {
>                  if (!as_info_from_expr_const(as_name, c, &as_info)) {
>                      continue;
>                  }
> diff --git a/include/ovn/expr.h b/include/ovn/expr.h
> index 9621a2c09..ae5ab1aab 100644
> --- a/include/ovn/expr.h
> +++ b/include/ovn/expr.h
> @@ -537,8 +537,7 @@ void expr_constant_destroy(const struct expr_constant *,
>
>  /* A collection of "union expr_constant"s of the same type. */
>  struct expr_constant_set {
> -    struct expr_constant *values; /* Constants. */
> -    size_t n_values;              /* Number of constants. */
> +    struct vector values;         /* Constants. */
>      enum expr_constant_type type; /* Type of the constants. */
>      bool in_curlies;              /* Whether the constants were in {}. */
>  };
> diff --git a/lib/actions.c b/lib/actions.c
> index ba25fbc76..f0758752f 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -2109,7 +2109,7 @@ encode_event_empty_lb_backends_opts(struct ofpbuf 
> *ofpacts,
>          /* All empty_lb_backends fields are of type 'str' */
>          ovs_assert(!strcmp(o->option->type, "str"));
>
> -        const struct expr_constant *c = o->value.values;
> +        const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
>          size_t size = strlen(c->string);
>          struct controller_event_opt_header hdr =
>              (struct controller_event_opt_header) {
> @@ -2585,11 +2585,11 @@ validate_empty_lb_backends(struct action_context *ctx,
>  {
>      for (size_t i = 0; i < n_options; i++) {
>          const struct ovnact_gen_option *o = &options[i];
> -        const struct expr_constant *c = o->value.values;
> +        const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
>          struct sockaddr_storage ss;
>          struct uuid uuid;
>
> -        if (o->value.n_values > 1 || !c->string) {
> +        if (vector_len(&o->value.values) > 1 || !c->string) {
>              lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
>                          o->option->name);
>              return;
> @@ -2889,8 +2889,8 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option 
> *o,
>      uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
>      opt_header[0] = o->option->code;
>
> -    const struct expr_constant *c = o->value.values;
> -    size_t n_values = o->value.n_values;
> +    const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
> +    size_t n_values = vector_len(&o->value.values);
>      if (!strcmp(o->option->type, "bool") ||
>          !strcmp(o->option->type, "uint8")) {
>          opt_header[1] = 1;
> @@ -3055,8 +3055,8 @@ encode_put_dhcpv6_option(const struct ovnact_gen_option 
> *o,
>                           struct ofpbuf *ofpacts)
>  {
>      struct dhcpv6_opt_header *opt = ofpbuf_put_uninit(ofpacts, sizeof *opt);
> -    const struct expr_constant *c = o->value.values;
> -    size_t n_values = o->value.n_values;
> +    const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
> +    size_t n_values = vector_len(&o->value.values);
>      size_t size;
>
>      opt->code = htons(o->option->code);
> @@ -3103,7 +3103,9 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts 
> *pdo,
>       * (skipping offerip the second time around). */
>      const struct ovnact_gen_option *offerip_opt = find_opt(
>          pdo->options, pdo->n_options, 0);
> -    ovs_be32 offerip = offerip_opt->value.values[0].value.ipv4;
> +    const struct expr_constant *c =
> +        vector_get_ptr(&offerip_opt->value.values, 0);
> +    ovs_be32 offerip = c->value.ipv4;
>      ofpbuf_put(ofpacts, &offerip, sizeof offerip);
>
>      /* Encode bootfile_name opt (67) */
> @@ -3111,7 +3113,7 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts 
> *pdo,
>          find_opt(pdo->options, pdo->n_options, DHCP_OPT_BOOTFILE_CODE);
>      if (boot_opt) {
>          uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
> -        const struct expr_constant *c = boot_opt->value.values;
> +        c = vector_get_ptr(&boot_opt->value.values, 0);
>          opt_header[0] = boot_opt->option->code;
>          opt_header[1] = strlen(c->string);
>          ofpbuf_put(ofpacts, c->string, opt_header[1]);
> @@ -3121,7 +3123,7 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts 
> *pdo,
>          find_opt(pdo->options, pdo->n_options, DHCP_OPT_BOOTFILE_ALT_CODE);
>      if (boot_alt_opt) {
>          uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
> -        const struct expr_constant *c = boot_alt_opt->value.values;
> +        c = vector_get_ptr(&boot_alt_opt->value.values, 0);
>          opt_header[0] = boot_alt_opt->option->code;
>          opt_header[1] = strlen(c->string);
>          ofpbuf_put(ofpacts, c->string, opt_header[1]);
> @@ -3131,7 +3133,7 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts 
> *pdo,
>          pdo->options, pdo->n_options, DHCP_OPT_NEXT_SERVER_CODE);
>      if (next_server_opt) {
>          uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
> -        const struct expr_constant *c = next_server_opt->value.values;
> +        c = vector_get_ptr(&next_server_opt->value.values, 0);
>          opt_header[0] = next_server_opt->option->code;
>          opt_header[1] = sizeof(ovs_be32);
>          ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
> @@ -3344,8 +3346,8 @@ parse_put_nd_ra_opts(struct action_context *ctx, const 
> struct expr_field *dst,
>      /* Let's validate the options. */
>      for (size_t i = 0; i < po->n_options; i++) {
>          const struct ovnact_gen_option *o = &po->options[i];
> -        const struct expr_constant *c = o->value.values;
> -        if (o->value.n_values > 1) {
> +        const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
> +        if (vector_len(&o->value.values) > 1) {
>              lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
>                          o->option->name);
>              return;
> @@ -3527,7 +3529,7 @@ static void
>  encode_put_nd_ra_option(const struct ovnact_gen_option *o,
>                          struct ofpbuf *ofpacts, ptrdiff_t ra_offset)
>  {
> -    const struct expr_constant *c = o->value.values;
> +    const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
>
>      switch (o->option->code) {
>      case ND_RA_FLAG_ADDR_MODE:
> diff --git a/lib/expr.c b/lib/expr.c
> index 937fecb75..e01cd028f 100644
> --- a/lib/expr.c
> +++ b/lib/expr.c
> @@ -585,8 +585,9 @@ type_check(struct expr_context *ctx, const struct 
> expr_field *f,
>      }
>
>      if (f->symbol->width) {
> -        for (size_t i = 0; i < cs->n_values; i++) {
> -            int w = expr_constant_width(&cs->values[i]);
> +        const struct expr_constant *c;
> +        VECTOR_FOR_EACH_PTR (&cs->values, c) {
> +            int w = expr_constant_width(c);
>              if (w > f->symbol->width) {
>                  lexer_error(ctx->lexer,
>                              "%d-bit constant is not compatible with %d-bit "
> @@ -624,12 +625,13 @@ make_cmp(struct expr_context *ctx,
>                          f->symbol->name);
>              goto exit;
>          }
> -        if (!cs->n_values) {
> +        if (!vector_len(&cs->values)) {
>              lexer_error(ctx->lexer, "Only == and != operators may be used "
>                          "to compare a field against an empty value set.");
>              goto exit;
>          }
> -        if (cs->values[0].masked) {
> +        const struct expr_constant *c = vector_get_ptr(&cs->values, 0);
> +        if (c->masked) {
>              lexer_error(ctx->lexer, "Only == and != operators may be used "
>                          "with masked constants.  Consider using subfields "
>                          "instead (e.g. eth.src[0..15] > 0x1111 in place of "
> @@ -641,9 +643,9 @@ make_cmp(struct expr_context *ctx,
>      if (f->symbol->level == EXPR_L_NOMINAL) {
>          if (f->symbol->predicate) {
>              ovs_assert(f->symbol->width > 0);
> -            for (size_t i = 0; i < cs->n_values; i++) {
> -                const union mf_subvalue *value = &cs->values[i].value;
> -                bool positive = (value->integer & htonll(1)) != 0;
> +            const struct expr_constant *c;
> +            VECTOR_FOR_EACH_PTR (&cs->values, c) {
> +                bool positive = (c->value.integer & htonll(1)) != 0;
>                  positive ^= r == EXPR_R_NE;
>                  positive ^= ctx->not;
>                  if (!positive) {
> @@ -664,14 +666,15 @@ make_cmp(struct expr_context *ctx,
>          }
>      }
>
> -    if (!cs->n_values) {
> +    if (!vector_len(&cs->values)) {
>          e = expr_create_boolean(r == EXPR_R_NE);
>          goto exit;
>      }
> -    e = make_cmp__(f, r, &cs->values[0]);
> -    for (size_t i = 1; i < cs->n_values; i++) {
> +    e = make_cmp__(f, r, vector_get_ptr(&cs->values, 0));
> +    const struct expr_constant *values = vector_get_array(&cs->values);
> +    for (size_t i = 1; i < vector_len(&cs->values); i++) {
>          e = expr_combine(r == EXPR_R_EQ ? EXPR_T_OR : EXPR_T_AND,
> -                         e, make_cmp__(f, r, &cs->values[i]));
> +                         e, make_cmp__(f, r, &values[i]));
>      }
>
>  exit:
> @@ -767,7 +770,7 @@ assign_constant_set_type(struct expr_context *ctx,
>                           struct expr_constant_set *cs,
>                           enum expr_constant_type type)
>  {
> -    if (!cs->n_values || cs->type == type) {
> +    if (!vector_len(&cs->values) || cs->type == type) {
>          cs->type = type;
>          return true;
>      } else {
> @@ -778,8 +781,7 @@ assign_constant_set_type(struct expr_context *ctx,
>  }
>
>  static bool
> -parse_addr_sets(struct expr_context *ctx, struct expr_constant_set *cs,
> -                size_t *allocated_values)
> +parse_addr_sets(struct expr_context *ctx, struct expr_constant_set *cs)
>  {
>      if (ctx->addr_sets_ref) {
>          size_t *ref_count = shash_find_data(ctx->addr_sets_ref,
> @@ -806,23 +808,19 @@ parse_addr_sets(struct expr_context *ctx, struct 
> expr_constant_set *cs,
>      }
>
>      struct expr_constant_set *addr_sets = node->data;
> -    size_t n_values = cs->n_values + addr_sets->n_values;
> -    if (n_values >= *allocated_values) {
> -        cs->values = xrealloc(cs->values, n_values * sizeof *cs->values);
> -        *allocated_values = n_values;
> -    }
> -    for (size_t i = 0; i < addr_sets->n_values; i++) {
> -        struct expr_constant *c = &cs->values[cs->n_values++];
> -        *c = addr_sets->values[i];
> -        c->as_name = node->name;
> +    vector_reserve(&cs->values, vector_len(&addr_sets->values));
> +
> +    struct expr_constant c;
> +    VECTOR_FOR_EACH (&addr_sets->values, c) {
> +        c.as_name = node->name;
> +        vector_push(&cs->values, &c);
>      }
>
>      return true;
>  }
>
>  static bool
> -parse_port_group(struct expr_context *ctx, struct expr_constant_set *cs,
> -                 size_t *allocated_values)
> +parse_port_group(struct expr_context *ctx, struct expr_constant_set *cs)
>  {
>      struct ds sb_name = DS_EMPTY_INITIALIZER;
>
> @@ -847,29 +845,22 @@ parse_port_group(struct expr_context *ctx, struct 
> expr_constant_set *cs,
>          return false;
>      }
>
> -    size_t n_values = cs->n_values + port_group->n_values;
> -    if (n_values >= *allocated_values) {
> -        cs->values = xrealloc(cs->values, n_values * sizeof *cs->values);
> -        *allocated_values = n_values;
> -    }
> -    for (size_t i = 0; i < port_group->n_values; i++) {
> -        struct expr_constant *c = &cs->values[cs->n_values++];
> -        c->string = xstrdup(port_group->values[i].string);
> -        c->as_name = NULL;
> +
> +    vector_reserve(&cs->values, vector_len(&port_group->values));
> +
> +    struct expr_constant c;
> +    VECTOR_FOR_EACH (&port_group->values, c) {
> +        c.string = xstrdup(c.string);
> +        c.as_name = NULL;
> +        vector_push(&cs->values, &c);
>      }
>
>      return true;
>  }
>
>  static bool
> -parse_constant(struct expr_context *ctx, struct expr_constant_set *cs,
> -               size_t *allocated_values)
> +parse_constant(struct expr_context *ctx, struct expr_constant_set *cs)
>  {
> -    if (cs->n_values >= *allocated_values) {
> -        cs->values = x2nrealloc(cs->values, allocated_values,
> -                                sizeof *cs->values);
> -    }
> -
>      if (ctx->lexer->token.type == LEX_T_TEMPLATE) {
>          lexer_error(ctx->lexer, "Unexpanded template.");
>          return false;
> @@ -877,9 +868,11 @@ parse_constant(struct expr_context *ctx, struct 
> expr_constant_set *cs,
>          if (!assign_constant_set_type(ctx, cs, EXPR_C_STRING)) {
>              return false;
>          }
> -        struct expr_constant *c = &cs->values[cs->n_values++];
> -        c->string = xstrdup(ctx->lexer->token.s);
> -        c->as_name = NULL;
> +
> +        struct expr_constant c = (struct expr_constant) {
> +            .string = xstrdup(ctx->lexer->token.s),
> +        };
> +        vector_push(&cs->values, &c);
>          lexer_get(ctx->lexer);
>          return true;
>      } else if (ctx->lexer->token.type == LEX_T_INTEGER ||
> @@ -888,24 +881,26 @@ parse_constant(struct expr_context *ctx, struct 
> expr_constant_set *cs,
>              return false;
>          }
>
> -        struct expr_constant *c = &cs->values[cs->n_values++];
> -        c->value = ctx->lexer->token.value;
> -        c->format = ctx->lexer->token.format;
> -        c->masked = ctx->lexer->token.type == LEX_T_MASKED_INTEGER;
> -        if (c->masked) {
> -            c->mask = ctx->lexer->token.mask;
> +        bool masked = ctx->lexer->token.type == LEX_T_MASKED_INTEGER;
> +        struct expr_constant c = (struct expr_constant) {
> +            .value = ctx->lexer->token.value,
> +            .format = ctx->lexer->token.format,
> +            .masked = masked,
> +        };
> +        if (masked) {
> +            c.mask = ctx->lexer->token.mask;
>          }
> -        c->as_name = NULL;
> +        vector_push(&cs->values, &c);
>          lexer_get(ctx->lexer);
>          return true;
>      } else if (ctx->lexer->token.type == LEX_T_MACRO) {
> -        if (!parse_addr_sets(ctx, cs, allocated_values)) {
> +        if (!parse_addr_sets(ctx, cs)) {
>              return false;
>          }
>          lexer_get(ctx->lexer);
>          return true;
>      } else if (ctx->lexer->token.type == LEX_T_PORT_GROUP) {
> -        if (!parse_port_group(ctx, cs, allocated_values)) {
> +        if (!parse_port_group(ctx, cs)) {
>              return false;
>          }
>          lexer_get(ctx->lexer);
> @@ -923,22 +918,23 @@ parse_constant(struct expr_context *ctx, struct 
> expr_constant_set *cs,
>  static bool
>  parse_constant_set(struct expr_context *ctx, struct expr_constant_set *cs)
>  {
> -    size_t allocated_values = 0;
>      bool ok;
>
> -    memset(cs, 0, sizeof *cs);
> +    *cs = (struct expr_constant_set) {
> +        .values = VECTOR_EMPTY_INITIALIZER(struct expr_constant),
> +    };
>      if (lexer_match(ctx->lexer, LEX_T_LCURLY)) {
>          ok = true;
>          cs->in_curlies = true;
>          do {
> -            if (!parse_constant(ctx, cs, &allocated_values)) {
> +            if (!parse_constant(ctx, cs)) {
>                  ok = false;
>                  break;
>              }
>              lexer_match(ctx->lexer, LEX_T_COMMA);
>          } while (!lexer_match(ctx->lexer, LEX_T_RCURLY));
>      } else {
> -        ok = parse_constant(ctx, cs, &allocated_values);
> +        ok = parse_constant(ctx, cs);
>      }
>      if (!ok) {
>          expr_constant_set_destroy(cs);
> @@ -964,13 +960,13 @@ expr_constant_parse(struct lexer *lexer, const struct 
> expr_field *f,
>          .lexer = lexer,
>      };
>
> -    struct expr_constant_set cs;
> -    memset(&cs, 0, sizeof cs);
> -    size_t allocated_values = 0;
> -    if (parse_constant(&ctx, &cs, &allocated_values)
> +    struct expr_constant_set cs = (struct expr_constant_set) {
> +        .values = VECTOR_EMPTY_INITIALIZER(struct expr_constant),
> +    };
> +    if (parse_constant(&ctx, &cs)
>          && type_check(&ctx, f, &cs)) {
> -        *c = cs.values[0];
> -        cs.n_values = 0;
> +        *c = vector_get(&cs.values, 0, struct expr_constant);
> +        vector_clear(&cs.values);
>      }
>      expr_constant_set_destroy(&cs);
>
> @@ -1031,19 +1027,18 @@ expr_constant_set_parse(struct lexer *lexer, struct 
> expr_constant_set *cs)
>  void
>  expr_constant_set_format(const struct expr_constant_set *cs, struct ds *s)
>  {
> -    bool curlies = cs->in_curlies || cs->n_values != 1;
> +    bool curlies = cs->in_curlies || vector_len(&cs->values) != 1;
>      if (curlies) {
>          ds_put_char(s, '{');
>      }
>
> -    for (const struct expr_constant *c = cs->values;
> -         c < &cs->values[cs->n_values]; c++) {
> -        if (c != cs->values) {
> -            ds_put_cstr(s, ", ");
> -        }
> -
> +    const struct expr_constant *c;
> +    VECTOR_FOR_EACH_PTR (&cs->values, c) {
>          expr_constant_format(c, cs->type, s);
> +        ds_put_cstr(s, ", ");
>      }
> +    ds_chomp(s, ' ');
> +    ds_chomp(s, ',');
>
>      if (curlies) {
>          ds_put_char(s, '}');
> @@ -1055,11 +1050,12 @@ expr_constant_set_destroy(struct expr_constant_set 
> *cs)
>  {
>      if (cs) {
>          if (cs->type == EXPR_C_STRING) {
> -            for (size_t i = 0; i < cs->n_values; i++) {
> -                free(cs->values[i].string);
> +            const struct expr_constant *c;
> +            VECTOR_FOR_EACH_PTR (&cs->values, c) {
> +                free(c->string);
>              }
>          }
> -        free(cs->values);
> +        vector_destroy(&cs->values);
>      }
>  }
>
> @@ -1092,8 +1088,7 @@ expr_constant_set_create_integers(const char *const 
> *values, size_t n_values)
>  {
>      struct expr_constant_set *cs = xzalloc(sizeof *cs);
>      cs->in_curlies = true;
> -    cs->n_values = 0;
> -    cs->values = xmalloc(n_values * sizeof *cs->values);
> +    cs->values = VECTOR_CAPACITY_INITIALIZER(struct expr_constant, n_values);
>      cs->type = EXPR_C_INTEGER;
>      for (size_t i = 0; i < n_values; i++) {
>          /* Use the lexer to convert each constant set into the proper
> @@ -1106,40 +1101,41 @@ expr_constant_set_create_integers(const char *const 
> *values, size_t n_values)
>              VLOG_WARN("Invalid constant set entry: '%s', token type: %d",
>                        values[i], lex.token.type);
>          } else {
> -            struct expr_constant *c = &cs->values[cs->n_values++];
> -            c->value = lex.token.value;
> -            c->format = lex.token.format;
> -            c->masked = lex.token.type == LEX_T_MASKED_INTEGER;
> -            if (c->masked) {
> -                c->mask = lex.token.mask;
> +            bool masked = lex.token.type == LEX_T_MASKED_INTEGER;
> +            struct expr_constant c = (struct expr_constant) {
> +                .value = lex.token.value,
> +                .format = lex.token.format,
> +                .masked = masked,
> +            };
> +            if (masked) {
> +                c.mask = lex.token.mask;
>              }
> +            vector_push(&cs->values, &c);
>          }
>          lexer_destroy(&lex);
>      }
>
>      /* Sort the result, so that it is efficient to generate diffs in the
>       * function expr_constant_set_diff */
> -    qsort(cs->values, cs->n_values, sizeof *cs->values,
> -          compare_expr_constant_integer_cb);
> +    vector_qsort(&cs->values, compare_expr_constant_integer_cb);
>
>      return cs;
>  }
>
>  static void
>  expr_constant_set_add_value(struct expr_constant_set **p_cs,
> -                            struct expr_constant *c, size_t *allocated)
> +                            const struct expr_constant *c)
>  {
>      struct expr_constant_set *cs = *p_cs;
>      if (!cs) {
>          cs = xzalloc(sizeof *cs);
> +        *cs = (struct expr_constant_set) {
> +        .values = VECTOR_CAPACITY_INITIALIZER(struct expr_constant, 1),
> +        };
>          *p_cs = cs;
>      }
>
> -    if (cs->n_values >= *allocated) {
> -        cs->values = x2nrealloc(cs->values, allocated,
> -                                sizeof *cs->values);
> -    }
> -    cs->values[cs->n_values++] = *c;
> +    vector_push(&cs->values, c);
>  }
>
>  /* Find the differences between old and new. Both old and new must be integer
> @@ -1159,33 +1155,33 @@ expr_constant_set_integers_diff(struct 
> expr_constant_set *old,
>      struct expr_constant_set *diff_added = NULL;
>      struct expr_constant_set *diff_deleted = NULL;
>
> -    size_t oi, ni, added_n_allocated, deleted_n_allocated;
> -    added_n_allocated = deleted_n_allocated = 0;
> +    size_t oi, ni;
> +
> +    const struct expr_constant *old_c = vector_get_array(&old->values);
> +    size_t old_n_values = vector_len(&old->values);
>
> -    for (oi = ni = 0; oi < old->n_values && ni < new->n_values;) {
> -        int d = compare_expr_constant_integer_cb(&old->values[oi],
> -                                                 &new->values[ni]);
> +    const struct expr_constant *new_c = vector_get_array(&new->values);
> +    size_t new_n_values = vector_len(&new->values);
> +
> +    for (oi = ni = 0; oi < old_n_values && ni < new_n_values;) {
> +        int d = compare_expr_constant_integer_cb(&old_c[oi], &new_c[ni]);
>          if (d < 0) {
> -            expr_constant_set_add_value(&diff_deleted, &old->values[oi],
> -                                        &deleted_n_allocated);
> +            expr_constant_set_add_value(&diff_deleted, &old_c[oi]);
>              oi++;
>          } else if (d > 0) {
> -            expr_constant_set_add_value(&diff_added, &new->values[ni],
> -                                        &added_n_allocated);
> +            expr_constant_set_add_value(&diff_added, &new_c[ni]);
>              ni++;
>          } else {
>              oi++; ni++;
>          }
>      }
>
> -    for (; oi < old->n_values; oi++) {
> -        expr_constant_set_add_value(&diff_deleted, &old->values[oi],
> -                                    &deleted_n_allocated);
> +    for (; oi < old_n_values; oi++) {
> +        expr_constant_set_add_value(&diff_deleted, &old_c[oi]);
>      }
>
> -    for (; ni < new->n_values; ni++) {
> -        expr_constant_set_add_value(&diff_added, &new->values[ni],
> -                                    &added_n_allocated);
> +    for (; ni < new_n_values; ni++) {
> +        expr_constant_set_add_value(&diff_added, &new_c[ni]);
>      }
>
>      *p_diff_added = diff_added;
> @@ -1228,8 +1224,7 @@ expr_const_sets_add_strings(struct shash *const_sets, 
> const char *name,
>  {
>      struct expr_constant_set *cs = xzalloc(sizeof *cs);
>      cs->in_curlies = true;
> -    cs->n_values = 0;
> -    cs->values = xmalloc(n_values * sizeof *cs->values);
> +    cs->values = VECTOR_CAPACITY_INITIALIZER(struct expr_constant, n_values);
>      cs->type = EXPR_C_STRING;
>      for (size_t i = 0; i < n_values; i++) {
>          if (filter && !sset_find(filter, values[i])) {
> @@ -1238,8 +1233,10 @@ expr_const_sets_add_strings(struct shash *const_sets, 
> const char *name,
>                          values[i], name);
>              continue;
>          }
> -        struct expr_constant *c = &cs->values[cs->n_values++];
> -        c->string = xstrdup(values[i]);
> +        struct expr_constant c = (struct expr_constant) {
> +            .string =  xstrdup(values[i]),
> +        };
> +        vector_push(&cs->values, &c);
>      }
>
>      expr_const_sets_add(const_sets, name, cs);
> @@ -1351,14 +1348,15 @@ expr_parse_primary(struct expr_context *ctx, bool 
> *atomic)
>
>              *atomic = true;
>
> -            struct expr_constant *cst = xzalloc(sizeof *cst);
> -            cst->format = LEX_F_HEXADECIMAL;
> -            cst->masked = false;
> +            struct expr_constant cst = (struct expr_constant) {
> +                .format = LEX_F_HEXADECIMAL,
> +                .masked = false,
> +            };
>
> +            c.values = VECTOR_CAPACITY_INITIALIZER(struct expr_constant, 1);
>              c.type = EXPR_C_INTEGER;
> -            c.values = cst;
> -            c.n_values = 1;
>              c.in_curlies = false;
> +            vector_push(&c.values, &cst);
>              return make_cmp(ctx, &f, EXPR_R_NE, &c);
>          } else if (parse_relop(ctx, &r) && parse_constant_set(ctx, &c)) {
>              return make_cmp(ctx, &f, r, &c);
> @@ -1371,13 +1369,14 @@ expr_parse_primary(struct expr_context *ctx, bool 
> *atomic)
>              return NULL;
>          }
>
> +        struct expr_constant *c = vector_get_ptr(&c1.values, 0);
>          if (!expr_relop_from_token(ctx->lexer->token.type, NULL)
> -            && c1.n_values == 1
> +            && vector_len(&c1.values) == 1
>              && c1.type == EXPR_C_INTEGER
> -            && c1.values[0].format == LEX_F_DECIMAL
> -            && !c1.values[0].masked
> +            && c->format == LEX_F_DECIMAL
> +            && !c->masked
>              && !c1.in_curlies) {
> -            uint64_t x = ntohll(c1.values[0].value.integer);
> +            uint64_t x = ntohll(c->value.integer);
>              if (x <= 1) {
>                  *atomic = true;
>                  expr_constant_set_destroy(&c1);
> --
> 2.51.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to