On Mon, Sep 22, 2025 at 7:48 PM Mark Michelson <[email protected]> wrote:

> 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
> >
>
>
Thank you Mark,

I went ahead and merged this into main.

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

Reply via email to