1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2007, 2009, 2010, 2011 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/>. */
25 #include "libpspp/compiler.h"
26 #include "libpspp/str.h"
27 #include "data/caseproto.h"
31 /* A count of cases or the index of a case within a collection of
33 #define CASENUMBER_MAX LONG_MAX
34 typedef long int casenumber
;
36 /* Reference-counted case implementation.
38 A newly created case has a single owner (the code that created
39 it), represented by an initial reference count of 1. Other
40 code that receives the case may keep a virtual copy of it by
41 calling case_ref, which increments the case's reference count.
42 When this is done, the case becomes shared between its
43 original owner and each piece of code that incremented the
46 A shared case (one whose reference count is greater than 1)
47 must not be modified, because this would make the case change
48 in the view of every reference count holder, not just the one
49 that intended to change the case. Because the purpose of
50 keeping the reference count is to make a virtual copy of the
51 case, this is undesirable behavior. The case_unshare function
52 provides a solution, by making a new, unshared copy of a
56 struct caseproto
*proto
; /* Case prototype. */
57 size_t ref_cnt
; /* Reference count. */
58 union value values
[1]; /* Values. */
61 struct ccase
*case_create (const struct caseproto
*) MALLOC_LIKE
;
62 struct ccase
*case_try_create (const struct caseproto
*) MALLOC_LIKE
;
63 struct ccase
*case_clone (const struct ccase
*) MALLOC_LIKE
;
65 static inline struct ccase
*case_unshare (struct ccase
*) WARN_UNUSED_RESULT
;
66 struct ccase
*case_ref (const struct ccase
*) WARN_UNUSED_RESULT
;
67 static inline void case_unref (struct ccase
*);
68 static inline bool case_is_shared (const struct ccase
*);
70 static inline size_t case_get_n_values (const struct ccase
*);
71 static inline const struct caseproto
*case_get_proto (const struct ccase
*);
73 size_t case_get_cost (const struct caseproto
*);
75 struct ccase
*case_resize (struct ccase
*, const struct caseproto
*)
77 struct ccase
*case_unshare_and_resize (struct ccase
*,
78 const struct caseproto
*)
81 void case_set_missing (struct ccase
*);
83 void case_copy (struct ccase
*dst
, size_t dst_idx
,
84 const struct ccase
*src
, size_t src_idx
,
86 void case_copy_out (const struct ccase
*,
87 size_t start_idx
, union value
*, size_t n_values
);
88 void case_copy_in (struct ccase
*,
89 size_t start_idx
, const union value
*, size_t n_values
);
91 const union value
*case_data (const struct ccase
*, const struct variable
*);
92 const union value
*case_data_idx (const struct ccase
*, size_t idx
);
93 union value
*case_data_rw (struct ccase
*, const struct variable
*);
94 union value
*case_data_rw_idx (struct ccase
*, size_t idx
);
96 double case_num (const struct ccase
*, const struct variable
*);
97 double case_num_idx (const struct ccase
*, size_t idx
);
98 double *case_num_rw (struct ccase
*, const struct variable
*);
99 double *case_num_rw_idx (struct ccase
*, size_t idx
);
101 const uint8_t *case_str (const struct ccase
*, const struct variable
*);
102 const uint8_t *case_str_idx (const struct ccase
*, size_t idx
);
103 struct substring
case_ss (const struct ccase
*, const struct variable
*);
104 struct substring
case_ss_idx (const struct ccase
*, size_t width
, size_t idx
);
105 uint8_t *case_str_rw (struct ccase
*, const struct variable
*);
106 uint8_t *case_str_rw_idx (struct ccase
*, size_t idx
);
108 int case_compare (const struct ccase
*, const struct ccase
*,
109 const struct variable
*const *, size_t n_vars
);
110 int case_compare_2dict (const struct ccase
*, const struct ccase
*,
111 const struct variable
*const *,
112 const struct variable
*const *,
115 const union value
*case_data_all (const struct ccase
*);
116 union value
*case_data_all_rw (struct ccase
*);
118 struct ccase
*case_unshare__ (struct ccase
*);
119 void case_unref__ (struct ccase
*);
121 /* If C is a shared case, that is, if it has a reference count
122 greater than 1, makes a new unshared copy and returns it,
123 decrementing C's reference count. If C is not shared (its
124 reference count is 1), returns C.
126 This function should be used before attempting to modify any
127 of the data in a case that might be shared, e.g.:
128 c = case_unshare (c); // Make sure that C is not shared.
129 *case_num_rw (c, myvar) = 1; // Modify data in C.
131 static inline struct ccase
*
132 case_unshare (struct ccase
*c
)
134 if (case_is_shared (c
))
135 c
= case_unshare__ (c
);
139 /* Decrements case C's reference count. Frees C if its
140 reference count drops to 0.
142 If C is a null pointer, this function has no effect. */
144 case_unref (struct ccase
*c
)
146 if (c
!= NULL
&& --c
->ref_cnt
== 0)
150 /* Returns true if case C is shared. A case that is shared
151 cannot be modified directly. Instead, an unshared copy must
152 first be made with case_unshare(). */
154 case_is_shared (const struct ccase
*c
)
156 return c
->ref_cnt
> 1;
159 /* Returns the number of union values in C. */
161 case_get_n_values (const struct ccase
*c
)
163 return caseproto_get_n_widths (c
->proto
);
166 /* Returns the prototype that describes the format of case C.
167 The caller must not unref the returned prototype. */
168 static inline const struct caseproto
*
169 case_get_proto (const struct ccase
*c
)
174 #endif /* data/case.h */