caseproto_unref (sc->proto);
}
+/* Returns true if VAR already has a field in SC,
+ false otherwise. */
+bool
+subcase_contains_var (const struct subcase *sc, const struct variable *var)
+{
+ return subcase_contains (sc, var_get_case_index (var));
+}
+
+/* Returns true if CASE_INDEX already has a field in SC,
+ false otherwise. */
+bool
+subcase_contains (const struct subcase *sc, int case_index)
+{
+ size_t i;
+
+ for (i = 0; i < sc->n_fields; i++)
+ if (sc->fields[i].case_index == case_index)
+ return true;
+
+ return false;
+}
/* Add a field for VAR to SC, with DIRECTION as the sort order.
Returns true if successful, false if VAR already has a field
subcase_add_var (struct subcase *sc, const struct variable *var,
enum subcase_direction direction)
{
- return subcase_add (sc, var_get_case_index (var),
- var_get_width (var), direction);
+ if (!subcase_contains_var (sc, var))
+ {
+ subcase_add_var_always (sc, var, direction);
+ return true;
+ }
+ else
+ return false;
}
/* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the sort order.
in SC. */
bool
subcase_add (struct subcase *sc, int case_index, int width,
- enum subcase_direction direction)
+ enum subcase_direction direction)
{
- struct subcase_field *field;
- size_t i;
+ if (!subcase_contains (sc, case_index))
+ {
+ subcase_add_always (sc, case_index, width, direction);
+ return true;
+ }
+ else
+ return false;
+}
- for (i = 0; i < sc->n_fields; i++)
- if (sc->fields[i].case_index == case_index)
- return false;
+/* Add a field for VAR to SC, with DIRECTION as the sort order,
+ regardless of whether VAR already has a field in SC. */
+void
+subcase_add_var_always (struct subcase *sc, const struct variable *var,
+ enum subcase_direction direction)
+{
+ return subcase_add_always (sc, var_get_case_index (var),
+ var_get_width (var), direction);
+}
+
+/* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the
+ sort order, regardless of whether CASE_INDEX already has a
+ field in SC. */
+void
+subcase_add_always (struct subcase *sc, int case_index, int width,
+ enum subcase_direction direction)
+{
+ struct subcase_field *field;
sc->fields = xnrealloc (sc->fields, sc->n_fields + 1, sizeof *sc->fields);
field = &sc->fields[sc->n_fields++];
field->width = width;
field->direction = direction;
invalidate_proto (sc);
- return true;
+}
+
+/* Adds a field to SC for each column in PROTO, so that SC
+ contains all of the columns in PROTO in the same order as a
+ case conforming to PROTO. The fields are added with
+ ascending direction. */
+void
+subcase_add_proto_always (struct subcase *sc, const struct caseproto *proto)
+{
+ size_t n = caseproto_get_n_widths (proto);
+ size_t i;
+
+ sc->fields = xnrealloc (sc->fields, sc->n_fields + n, sizeof *sc->fields);
+ for (i = 0; i < n; i++)
+ {
+ struct subcase_field *field = &sc->fields[sc->n_fields++];
+ field->case_index = i;
+ field->width = caseproto_get_width (proto, i);
+ field->direction = SC_ASCEND;
+ }
+ invalidate_proto (sc);
}
/* Obtains a caseproto for a case described by SC. The caller
void subcase_clear (struct subcase *);
void subcase_destroy (struct subcase *);
-bool subcase_add (struct subcase *sc, int index, int width,
- enum subcase_direction direction);
+bool subcase_contains (const struct subcase *, int case_index);
+bool subcase_contains_var (const struct subcase *, const struct variable *);
+bool subcase_add (struct subcase *, int case_index, int width,
+ enum subcase_direction direction);
bool subcase_add_var (struct subcase *, const struct variable *,
enum subcase_direction);
+void subcase_add_always (struct subcase *sc, int case_index, int width,
+ enum subcase_direction direction);
+void subcase_add_var_always (struct subcase *, const struct variable *,
+ enum subcase_direction);
+void subcase_add_proto_always (struct subcase *, const struct caseproto *);
+
const struct caseproto *subcase_get_proto (const struct subcase *);
static inline bool subcase_is_empty (const struct subcase *);
static inline size_t subcase_get_n_fields (const struct subcase *);
+static inline size_t subcase_get_case_index (const struct subcase *,
+ size_t idx);
static inline enum subcase_direction subcase_get_direction (
const struct subcase *, size_t idx);
bool subcase_equal_xx (const struct subcase *,
const union value *a, const union value *b);
+static inline size_t
+subcase_get_case_index (const struct subcase *sc, size_t idx)
+{
+ return sc->fields[idx].case_index;
+}
+
static inline enum subcase_direction
subcase_get_direction (const struct subcase *sc, size_t idx)
{