File Coverage

type.c
Criterion Covered Total %
statement 86 145 59.3
branch 62 132 46.9
condition n/a
subroutine n/a
pod n/a
total 148 277 53.4


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #include "ppport.h"
6              
7             #include
8             #include "define.h"
9             #include "type.h"
10             #include "proto.h"
11              
12 350           int unpack_type_nocroak(pTHX_ unsigned char *input, STRLEN len, STRLEN *pos, struct cc_type *output)
13             {
14 350 50         if (UNLIKELY(unpack_short_nocroak(aTHX_ input, len, pos, &output->type_id) != 0))
15 0           return -1;
16              
17 350 100         if (output->type_id > 0 && output->type_id < 0x20) {
    100          
18             /* Primitives. No further decoding needed */
19              
20 31 100         } else if (output->type_id == CC_TYPE_CUSTOM) {
21             char *custom_type;
22             STRLEN type_length;
23 4 50         if (UNLIKELY(unpack_string_nocroak(aTHX_ input, len, pos, &custom_type, &type_length) != 0)) {
24 0           return -3;
25             }
26 4           const char *marshal_prefix = "org.apache.cassandra.db.marshal.";
27 4 50         if (type_length > strlen(marshal_prefix) && !memcmp(marshal_prefix, custom_type, strlen(marshal_prefix))) {
    0          
28             char *marshal_type;
29             STRLEN marshal_type_length;
30              
31 0           marshal_type = custom_type + strlen(marshal_prefix);
32 0           marshal_type_length = type_length - strlen(marshal_prefix);
33 0           switch(marshal_type_length) {
34 0           case 8:
35 0 0         if (!memcmp(marshal_type, "UTF8Type", 8)) { output->type_id = CC_TYPE_VARCHAR; break; }
36 0 0         if (!memcmp(marshal_type, "UUIDType", 8)) { output->type_id = CC_TYPE_UUID; break; }
37 0 0         if (!memcmp(marshal_type, "TimeType", 8)) { output->type_id = CC_TYPE_TIME; break; }
38 0 0         if (!memcmp(marshal_type, "ByteType", 8)) { output->type_id = CC_TYPE_TINYINT; break; }
39 0 0         if (!memcmp(marshal_type, "DateType", 8)) { output->type_id = CC_TYPE_DATE; break; }
40 0 0         if (!memcmp(marshal_type, "LongType", 8)) { output->type_id = CC_TYPE_BIGINT; break; }
41 0           break;
42 0           case 9:
43 0 0         if (!memcmp(marshal_type, "AsciiType", 9)) { output->type_id = CC_TYPE_ASCII; break; }
44 0 0         if (!memcmp(marshal_type, "Int32Type", 9)) { output->type_id = CC_TYPE_INT; break; }
45 0 0         if (!memcmp(marshal_type, "BytesType", 9)) { output->type_id = CC_TYPE_BLOB; break; }
46 0 0         if (!memcmp(marshal_type, "FloatType", 9)) { output->type_id = CC_TYPE_FLOAT; break; }
47 0 0         if (!memcmp(marshal_type, "ShortType", 9)) { output->type_id = CC_TYPE_SMALLINT; break; }
48 0           break;
49 0           case 10:
50 0 0         if (!memcmp(marshal_type, "DoubleType", 10)) { output->type_id = CC_TYPE_DOUBLE; break; }
51 0           break;
52 0           case 11:
53 0 0         if (!memcmp(marshal_type, "BooleanType", 11)) { output->type_id = CC_TYPE_BOOLEAN; break; }
54 0 0         if (!memcmp(marshal_type, "DecimalType", 11)) { output->type_id = CC_TYPE_DECIMAL; break; }
55 0 0         if (!memcmp(marshal_type, "IntegerType", 11)) { output->type_id = CC_TYPE_VARINT; break; }
56 0           break;
57 0           case 12:
58 0 0         if (!memcmp(marshal_type, "TimeUUIDType", 12)) { output->type_id = CC_TYPE_TIMEUUID; break; }
59 0           break;
60 0           case 13:
61 0 0         if (!memcmp(marshal_type, "TimestampType", 13)) { output->type_id = CC_TYPE_TIMESTAMP; break; }
62 0           break;
63 0           case 14:
64 0 0         if (!memcmp(marshal_type, "SimpleDateType", 14)) { output->type_id = CC_TYPE_DATE; break; }
65 0           break;
66 0           case 15:
67 0 0         if (!memcmp(marshal_type, "InetAddressType", 15)) { output->type_id = CC_TYPE_INET; break; }
68 0           break;
69 0           case 17:
70 0 0         if (!memcmp(marshal_type, "CounterColumnType", 17)) { output->type_id = CC_TYPE_COUNTER; break; }
71 0           break;
72             }
73             }
74              
75             /* If we made it this far, it's not a type we understand. So just copy the name and we're done. */
76 4           Newxz(output->custom_name, type_length+1, char);
77 4           memcpy(output->custom_name, custom_type, type_length);
78              
79 27 100         } else if (output->type_id == CC_TYPE_LIST) {
80             struct cc_type *inner;
81 9           Newxz(inner, 1, struct cc_type);
82 9           output->inner_type = inner;
83              
84 9 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, inner) != 0)) {
85 0           return -3;
86             }
87              
88 18 100         } else if (output->type_id == CC_TYPE_MAP) {
89 9           Newxz(output->inner_type, 2, struct cc_type);
90              
91 9 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, &output->inner_type[0]) != 0)) {
92 0           return -3;
93             }
94 9 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, &output->inner_type[1]) != 0)) {
95 0           return -3;
96             }
97              
98 9 100         } else if (output->type_id == CC_TYPE_SET) {
99             struct cc_type *inner;
100 4           Newxz(inner, 1, struct cc_type);
101 4           output->inner_type = inner;
102              
103 4 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, inner) != 0)) {
104 0           return -3;
105             }
106              
107 5 100         } else if (output->type_id == CC_TYPE_UDT) {
108             char *str;
109             STRLEN str_len;
110             uint16_t field_count;
111             int i;
112              
113 2           Newxz(output->udt, 1, struct cc_udt);
114              
115 2 50         if (UNLIKELY(unpack_string_nocroak(aTHX_ input, len, pos, &str, &str_len) != 0)) {
116 0           return -3;
117             }
118 2           output->udt->keyspace = newSVpvn_utf8(str, str_len, 1);
119              
120 2 50         if (UNLIKELY(unpack_string_nocroak(aTHX_ input, len, pos, &str, &str_len) != 0)) {
121 0           return -3;
122             }
123 2           output->udt->udt_name = newSVpvn_utf8(str, str_len, 1);
124              
125 2 50         if (UNLIKELY(unpack_short_nocroak(aTHX_ input, len, pos, &field_count) != 0)) {
126 0           return -3;
127             }
128 2           output->udt->field_count = field_count;
129              
130 2 50         if (UNLIKELY(field_count > len || field_count == 0)) {
    50          
131 0           return -3;
132             }
133              
134 2           Newxz(output->udt->fields, field_count, struct cc_udt_field);
135              
136 4 100         for (i = 0; i < field_count; i++) {
137 2           struct cc_udt_field *field = &output->udt->fields[i];
138 2 50         if (UNLIKELY(unpack_string_nocroak(aTHX_ input, len, pos, &str, &str_len) != 0)) {
139 0           return -3;
140             }
141 2           field->name = newSVpvn_utf8(str, str_len, 1);
142 2 50         PERL_HASH(field->name_hash, str, str_len);
143              
144 2 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, &field->type) != 0)) {
145 0           return -3;
146             }
147             }
148              
149 3 50         } else if (output->type_id == CC_TYPE_TUPLE) {
150             uint16_t field_count;
151             int i;
152              
153 3           Newxz(output->tuple, 1, struct cc_tuple);
154              
155 3 50         if (UNLIKELY(unpack_short_nocroak(aTHX_ input, len, pos, &field_count) != 0)) {
156 0           return -3;
157             }
158 3           output->tuple->field_count = field_count;
159              
160 3 50         if (UNLIKELY(field_count > len || field_count == 0)) {
    50          
161 0           return -3;
162             }
163              
164 3           Newxz(output->tuple->fields, field_count, struct cc_type);
165              
166 9 100         for (i = 0; i < field_count; i++) {
167             struct cc_type *field;
168 6           field = &output->tuple->fields[i];
169              
170 6 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, field) != 0)) {
171 0           return -3;
172             }
173             }
174              
175             } else {
176 0           return -2;
177             }
178              
179 350           return 0;
180             }
181              
182 311           void unpack_type(pTHX_ unsigned char *input, STRLEN len, STRLEN *pos, struct cc_type *output)
183             {
184 311 50         if (UNLIKELY(unpack_type_nocroak(aTHX_ input, len, pos, output) != 0)) {
185 0           cc_type_destroy(aTHX_ output);
186 0           croak("unpack_type: invalid input. Data corrupted?");
187             }
188 311           }
189              
190 350           void cc_type_destroy(pTHX_ struct cc_type *type)
191             {
192 350 100         if (type->type_id == CC_TYPE_LIST || type->type_id == CC_TYPE_SET) {
    100          
193 13 50         if (type->inner_type != NULL) {
194 13           cc_type_destroy(aTHX_ type->inner_type);
195 13           Safefree(type->inner_type);
196 13           type->inner_type = NULL;
197             }
198              
199 337 100         } else if (type->type_id == CC_TYPE_MAP) {
200 9 50         if (type->inner_type != NULL) {
201 9           cc_type_destroy(aTHX_ &type->inner_type[0]);
202 9           cc_type_destroy(aTHX_ &type->inner_type[1]);
203 9           Safefree(type->inner_type);
204 9           type->inner_type = NULL;
205             }
206              
207 328 100         } else if (type->type_id == CC_TYPE_CUSTOM) {
208 4 50         if (type->custom_name != NULL) {
209 4           Safefree(type->custom_name);
210 4           type->custom_name = NULL;
211             }
212              
213 324 100         } else if (type->type_id == CC_TYPE_UDT) {
214 2 50         if (type->udt != NULL) {
215 2           SvREFCNT_dec(type->udt->keyspace);
216 2           SvREFCNT_dec(type->udt->udt_name);
217 2 50         if (type->udt->fields != NULL) {
218             int i;
219 4 100         for (i = 0; i < type->udt->field_count; i++) {
220 2           SvREFCNT_dec(type->udt->fields[i].name);
221 2           cc_type_destroy(aTHX_ &type->udt->fields[i].type);
222             }
223 2           Safefree(type->udt->fields);
224             }
225 2           Safefree(type->udt);
226 2           type->udt = NULL;
227             }
228              
229 322 100         } else if (type->type_id == CC_TYPE_TUPLE) {
230 3 50         if (type->tuple != NULL) {
231 3 50         if (type->tuple->fields != NULL) {
232             int i;
233 9 100         for (i = 0; i < type->tuple->field_count; i++) {
234 6           cc_type_destroy(aTHX_ &type->tuple->fields[i]);
235             }
236 3           Safefree(type->tuple->fields);
237             }
238              
239 3           Safefree(type->tuple);
240 3           type->tuple = NULL;
241             }
242             }
243 350           }