1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 #ifndef DATA_CASEPROTO_H
18 #define DATA_CASEPROTO_H 1
24 #include <data/value.h>
25 #include <libpspp/cast.h>
26 #include <libpspp/compiler.h>
30 A case prototype specifies the number and type of the values
31 in a case. It is essentially an array of integers, where the
32 array index is an index into a case and each element
33 represents the width of a value in a case. Valid widths are:
35 * 0, indicating a numeric value.
37 * A positive integer between 1 and 32767, indicating the
38 size in bytes of a string value.
40 * -1, indicating that the value at this index in the case
41 is not used at all. (This is rarely useful.)
43 Case prototypes are reference counted. A newly created case
44 prototype has a single owner (the code that created it),
45 represented by an initial reference count of 1. Other code
46 that receives the case prototype may keep a virtual copy of it
47 by calling caseproto_ref, which increments the case
48 prototype's reference count. When this is done, the case
49 prototype becomes shared between its original owner and each
50 piece of code that incremented the reference count.
52 Functions that modifying case prototypes automatically unshare
53 them as necessary. All of these functions potentially move
54 the caseproto around in memory even when the case prototype is
55 not shared. Thus it is very important that every caller of a
56 function that modifies a case prototype thereafter uses the returned
57 caseproto instead of the one passed in as an argument.
59 Only the case prototype code should refer to caseproto members
60 directly. Other code should use the provided helper
64 size_t ref_cnt; /* Reference count. */
66 /* Tracking of long string widths. Lazily maintained: when
67 'long_strings' is null and 'n_long_strings' is nonzero,
68 the former must be regenerated. */
69 size_t *long_strings; /* Array of indexes of long string widths. */
70 size_t n_long_strings; /* Number of long string widths. */
73 size_t n_widths; /* Number of widths. */
74 size_t allocated_widths; /* Space allocated for 'widths' array. */
75 short int widths[1]; /* Width of each case value. */
80 /* Creation and destruction. */
81 struct caseproto *caseproto_create (void) MALLOC_LIKE;
82 static inline struct caseproto *caseproto_ref (const struct caseproto *);
83 struct caseproto *caseproto_ref_pool (const struct caseproto *, struct pool *);
84 static inline void caseproto_unref (struct caseproto *);
86 /* Inspecting stored widths. */
87 static inline int caseproto_get_width (const struct caseproto *, size_t idx);
88 static inline size_t caseproto_get_n_widths (const struct caseproto *);
90 /* Adding and removing widths. */
91 struct caseproto *caseproto_reserve (struct caseproto *, size_t n_widths)
93 struct caseproto *caseproto_add_width (struct caseproto *, int width)
95 struct caseproto *caseproto_set_width (struct caseproto *,
96 size_t idx, int width)
98 struct caseproto *caseproto_insert_width (struct caseproto *,
99 size_t before, int width)
101 struct caseproto *caseproto_remove_widths (struct caseproto *,
102 size_t idx, size_t cnt)
104 struct caseproto *caseproto_move_widths (struct caseproto *,
105 size_t old_start, size_t new_start,
109 /* Working with "union value" arrays. */
110 bool caseproto_needs_init_values (const struct caseproto *);
111 void caseproto_init_values (const struct caseproto *, union value[]);
112 bool caseproto_try_init_values (const struct caseproto *, union value[]);
113 void caseproto_reinit_values (const struct caseproto *old,
114 const struct caseproto *new, union value[]);
115 void caseproto_destroy_values (const struct caseproto *, union value[]);
117 void caseproto_copy (const struct caseproto *, size_t idx, size_t count,
118 union value *dst, const union value *src);
120 /* Inspecting the cache of long string widths.
122 (These functions are useful for allocating cases, which
123 requires allocating a block memory for each long string value
125 static inline size_t caseproto_get_n_long_strings (const struct caseproto *);
126 static inline size_t caseproto_get_long_string_idx (const struct caseproto *,
129 /* For use in assertions. */
130 bool caseproto_range_is_valid (const struct caseproto *,
131 size_t ofs, size_t count);
132 bool caseproto_is_conformable (const struct caseproto *a,
133 const struct caseproto *b);
134 bool caseproto_equal (const struct caseproto *a, size_t a_start,
135 const struct caseproto *b, size_t b_start,
138 /* Creation and destruction. */
140 void caseproto_free__ (struct caseproto *);
142 /* Increments case prototype PROTO's reference count and returns
143 PROTO. Afterward, PROTO is shared among its reference count
145 static inline struct caseproto *
146 caseproto_ref (const struct caseproto *proto_)
148 struct caseproto *proto = CONST_CAST (struct caseproto *, proto_);
153 /* Decrements case prototype PROTO's reference count. Frees
154 PROTO if its reference count drops to 0.
156 If PROTO is a null pointer, this function has no effect. */
158 caseproto_unref (struct caseproto *proto)
160 if (proto != NULL && !--proto->ref_cnt)
161 caseproto_free__ (proto);
164 /* Inspecting stored widths. */
166 /* Returns case prototype PROTO's width with the given IDX. IDX
167 must be less than caseproto_get_n_widths(PROTO). */
169 caseproto_get_width (const struct caseproto *proto, size_t idx)
171 assert (idx < proto->n_widths);
172 return proto->widths[idx];
175 /* Returns the number of widths in case prototype PROTO. */
177 caseproto_get_n_widths (const struct caseproto *proto)
179 return proto->n_widths;
182 /* Inspecting the cache of long string widths. */
184 void caseproto_refresh_long_string_cache__ (const struct caseproto *);
186 /* Returns the number of long string widths in PROTO; that is,
187 the number of widths in PROTO that are greater than to
190 caseproto_get_n_long_strings (const struct caseproto *proto)
192 return proto->n_long_strings;
195 /* Given long string width IDX1, returns a value IDX2 for which
196 caseproto_get_width(PROTO, IDX2) will return a value greater
197 than MAX_SHORT_STRING. IDX1 must be less than
198 caseproto_get_n_long_strings(PROTO), and IDX2 will be less
199 than caseproto_get_n_widths(PROTO). */
201 caseproto_get_long_string_idx (const struct caseproto *proto, size_t idx1)
203 if (proto->long_strings == NULL)
204 caseproto_refresh_long_string_cache__ (proto);
206 assert (idx1 < proto->n_long_strings);
207 return proto->long_strings[idx1];
210 #endif /* data/caseproto.h */