Previous: String Values, Up: Values


2.1.3 Runtime Typed Values

When a value's type is only known at runtime, it is often represented as a union value, defined in data/value.h. union value has two members: a double named `f' to store a numeric value and an array of char named `s' to a store a string value. A union value does not identify the type or width of the data it contains. Code that works with union valuess must therefore have external knowledge of its content, often through the type and width of a struct variable (see Variables).

The array of char in union value has only a small, fixed capacity of MAX_SHORT_STRING bytes. A value that fits within this capacity is called a short string. Any wider string value, which must be represented by more than one union value, is called a long string.

— Macro: int MAX_SHORT_STRING

Maximum width of a short string value, never less than 8 bytes. It is wider than 8 bytes on systems where double is either larger than 8 bytes or has stricter alignment than 8 bytes.

— Macro: int MIN_LONG_STRING

Minimum width of a long string value, that is, MAX_SHORT_STRING + 1.

Long string variables are slightly harder to work with than short string values, because they cannot be conveniently and efficiently allocated as block scope variables or structure members. The PSPP language exposes this inconvenience to the user: there are many circumstances in PSPP syntax where short strings are allowed but not long strings. Short string variables, for example, may have user-missing values, but long string variables may not (see Missing Observations).

PSPP provides a few functions for working with union values. The most useful are described below. To use these functions, recall that a numeric value has a width of 0.

— Function: size_t value_cnt_from_width (int width)

Returns the number of consecutive union values that must be allocated to store a value of the given width. For a numeric or short string value, the return value is 1; for long string variables, it is greater than 1.

— Function: void value_copy (union value *dst, const union value *src, int width)

Copies a value of the given width from the union value array starting at src to the one starting at dst. The two arrays must not overlap.

— Function: void value_set_missing (union value *value, int width)

Sets value to SYSMIS if it is numeric or to all spaces if it is alphanumeric, according to width. value must point to the start of a union value array of the given width.

— Function: bool value_is_resizable (const union value *value, int old_width, int new_width)

Determines whether value may be resized from old_width to new_width. Resizing is possible if the following criteria are met. First, old_width and new_width must be both numeric or both string widths. Second, if new_width is a short string width and less than old_width, resizing is allowed only if bytes new_width through old_width in value contain only spaces.

These rules are part of those used by mv_is_resizable and val_labs_can_set_width.

— Function: void value_resize (union value *value, int old_width, int new_width)

Resizes value from old_width to new_width, which must be allowed by the rules stated above. This has an effect only if new_width is greater than old_width, in which case the bytes newly added to value are cleared to spaces.