Cleanup: fix cppcheck warnings
[babeltrace.git] / formats / ctf / types / float.c
CommitLineData
6dc2ca62
MD
1/*
2 * Common Trace Format
3 *
4 * Floating point read/write functions.
5 *
64fa3fec
MD
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6dc2ca62 9 *
ccd7e1c8
MD
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
de0ba614 16 *
ccd7e1c8
MD
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
6dc2ca62 19 *
de0ba614 20 * Reference: ISO C99 standard 5.2.4
6dc2ca62
MD
21 */
22
d79865b9 23#include <babeltrace/ctf/types.h>
6dc2ca62 24#include <glib.h>
de0ba614 25#include <float.h> /* C99 floating point definitions */
a3dbc794 26#include <limits.h> /* C99 limits */
9b0422a0 27#include <babeltrace/endian.h>
f530d9ce 28#include <pthread.h>
6dc2ca62 29
de0ba614
MD
30/*
31 * This library is limited to binary representation of floating point values.
f72803ca
MD
32 * We use hardware support for conversion between 32 and 64-bit floating
33 * point values.
de0ba614
MD
34 */
35
6dc2ca62
MD
36/*
37 * Aliasing float/double and unsigned long is not strictly permitted by strict
f6625916 38 * aliasing, but in practice declaration prunning is well supported, and this permits
6dc2ca62
MD
39 * us to use per-word read/writes rather than per-byte.
40 */
41
42#if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
43#define HAS_TYPE_PRUNING
44#endif
45
de0ba614
MD
46#if (FLT_RADIX != 2)
47
48#error "Unsupported floating point radix"
49
6dc2ca62 50#endif
6dc2ca62
MD
51
52union doubleIEEE754 {
f72803ca
MD
53 double vd;
54 float vf;
6dc2ca62
MD
55#ifdef HAS_TYPE_PRUNING
56 unsigned long bits[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
57#else
58 unsigned char bits[sizeof(double)];
59#endif
60};
61
f530d9ce
JD
62/*
63 * This mutex protects the static temporary float and double
64 * declarations (static_float_declaration and static_double_declaration).
65 */
66static pthread_mutex_t float_mutex = PTHREAD_MUTEX_INITIALIZER;
67
f72803ca
MD
68static struct declaration_float *static_float_declaration,
69 *static_double_declaration;
d11e9c49 70
de0ba614 71struct pos_len {
08c82b90 72 size_t len;
de0ba614
MD
73};
74
f530d9ce
JD
75static void float_lock(void)
76{
77 int ret;
78
79 ret = pthread_mutex_lock(&float_mutex);
80 assert(!ret);
81}
82
83static void float_unlock(void)
84{
85 int ret;
86
87 ret = pthread_mutex_unlock(&float_mutex);
88 assert(!ret);
89}
90
c5e74408
MD
91int _ctf_float_copy(struct stream_pos *destp,
92 struct definition_float *dest_definition,
93 struct stream_pos *srcp,
94 const struct definition_float *src_definition)
6dc2ca62 95{
c5e74408
MD
96 int ret;
97
f72803ca
MD
98 /* We only support copy of same-size floats for now */
99 assert(src_definition->declaration->sign->len ==
100 dest_definition->declaration->sign->len);
101 assert(src_definition->declaration->exp->len ==
102 dest_definition->declaration->exp->len);
103 assert(src_definition->declaration->mantissa->len ==
104 dest_definition->declaration->mantissa->len);
11d43b90 105 /* Read */
d11e9c49 106 if (src_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
107 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
108 if (ret)
109 return ret;
110 ret = ctf_integer_read(srcp, &src_definition->exp->p);
111 if (ret)
112 return ret;
113 ret = ctf_integer_read(srcp, &src_definition->sign->p);
114 if (ret)
115 return ret;
de0ba614 116 } else {
c5e74408
MD
117 ret = ctf_integer_read(srcp, &src_definition->sign->p);
118 if (ret)
119 return ret;
120 ret = ctf_integer_read(srcp, &src_definition->exp->p);
121 if (ret)
122 return ret;
123 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
124 if (ret)
125 return ret;
6dc2ca62 126 }
d11e9c49
MD
127
128 dest_definition->mantissa->value._unsigned =
129 src_definition->mantissa->value._unsigned;
130 dest_definition->exp->value._signed =
131 src_definition->exp->value._signed;
132 dest_definition->sign->value._unsigned =
133 src_definition->sign->value._unsigned;
134
11d43b90 135 /* Write */
d11e9c49 136 if (dest_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
137 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
138 if (ret)
139 return ret;
140 ret = ctf_integer_write(destp, &dest_definition->exp->p);
141 if (ret)
142 return ret;
143 ret = ctf_integer_write(destp, &dest_definition->sign->p);
144 if (ret)
145 return ret;
de0ba614 146 } else {
c5e74408
MD
147 ret = ctf_integer_write(destp, &dest_definition->sign->p);
148 if (ret)
149 return ret;
150 ret = ctf_integer_write(destp, &dest_definition->exp->p);
151 if (ret)
152 return ret;
153 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
154 if (ret)
155 return ret;
6dc2ca62 156 }
c5e74408 157 return 0;
11d43b90 158}
de0ba614 159
c5e74408 160int ctf_float_read(struct stream_pos *ppos, struct definition *definition)
6dc2ca62 161{
d11e9c49
MD
162 struct definition_float *float_definition =
163 container_of(definition, struct definition_float, p);
164 const struct declaration_float *float_declaration =
165 float_definition->declaration;
166 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca
MD
167 union doubleIEEE754 u;
168 struct definition *tmpdef;
169 struct definition_float *tmpfloat;
46322b33 170 struct ctf_stream_pos destp;
aee35fcc 171 struct mmap_align mma;
c5e74408 172 int ret;
11d43b90 173
f530d9ce 174 float_lock();
f72803ca
MD
175 switch (float_declaration->mantissa->len + 1) {
176 case FLT_MANT_DIG:
177 tmpdef = static_float_declaration->p.definition_new(
178 &static_float_declaration->p,
179 NULL, 0, 0, "__tmpfloat");
180 break;
181 case DBL_MANT_DIG:
182 tmpdef = static_double_declaration->p.definition_new(
183 &static_double_declaration->p,
184 NULL, 0, 0, "__tmpfloat");
185 break;
186 default:
f530d9ce
JD
187 ret = -EINVAL;
188 goto end;
f72803ca
MD
189 }
190 tmpfloat = container_of(tmpdef, struct definition_float, p);
86b06ede 191 memset(&destp, 0, sizeof(destp));
989c73bc 192 ctf_init_pos(&destp, -1, O_RDWR);
aee35fcc
MD
193 mmap_align_set_addr(&mma, (char *) u.bits);
194 destp.base_mma = &mma;
f72803ca 195 destp.packet_size = sizeof(u) * CHAR_BIT;
d11e9c49 196 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 197 ret = _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition);
f72803ca
MD
198 switch (float_declaration->mantissa->len + 1) {
199 case FLT_MANT_DIG:
200 float_definition->value = u.vf;
201 break;
202 case DBL_MANT_DIG:
203 float_definition->value = u.vd;
204 break;
205 default:
f530d9ce
JD
206 ret = -EINVAL;
207 goto end_unref;
f72803ca 208 }
f530d9ce
JD
209
210end_unref:
d11e9c49 211 definition_unref(tmpdef);
f530d9ce
JD
212end:
213 float_unlock();
c5e74408 214 return ret;
de0ba614
MD
215}
216
c5e74408 217int ctf_float_write(struct stream_pos *ppos, struct definition *definition)
de0ba614 218{
d11e9c49
MD
219 struct definition_float *float_definition =
220 container_of(definition, struct definition_float, p);
221 const struct declaration_float *float_declaration =
222 float_definition->declaration;
223 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca
MD
224 union doubleIEEE754 u;
225 struct definition *tmpdef;
226 struct definition_float *tmpfloat;
46322b33 227 struct ctf_stream_pos srcp;
aee35fcc 228 struct mmap_align mma;
c5e74408 229 int ret;
11d43b90 230
f530d9ce 231 float_lock();
f72803ca
MD
232 switch (float_declaration->mantissa->len + 1) {
233 case FLT_MANT_DIG:
234 tmpdef = static_float_declaration->p.definition_new(
235 &static_float_declaration->p,
236 NULL, 0, 0, "__tmpfloat");
237 break;
238 case DBL_MANT_DIG:
239 tmpdef = static_double_declaration->p.definition_new(
240 &static_double_declaration->p,
241 NULL, 0, 0, "__tmpfloat");
242 break;
243 default:
f530d9ce
JD
244 ret = -EINVAL;
245 goto end;
f72803ca
MD
246 }
247 tmpfloat = container_of(tmpdef, struct definition_float, p);
8563e754 248 ctf_init_pos(&srcp, -1, O_RDONLY);
aee35fcc
MD
249 mmap_align_set_addr(&mma, (char *) u.bits);
250 srcp.base_mma = &mma;
f72803ca
MD
251 srcp.packet_size = sizeof(u) * CHAR_BIT;
252 switch (float_declaration->mantissa->len + 1) {
253 case FLT_MANT_DIG:
254 u.vf = float_definition->value;
255 break;
256 case DBL_MANT_DIG:
257 u.vd = float_definition->value;
258 break;
259 default:
f530d9ce
JD
260 ret = -EINVAL;
261 goto end_unref;
f72803ca 262 }
d11e9c49 263 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 264 ret = _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat);
f530d9ce
JD
265
266end_unref:
d11e9c49 267 definition_unref(tmpdef);
f530d9ce
JD
268end:
269 float_unlock();
c5e74408 270 return ret;
de0ba614 271}
6dc2ca62 272
d11e9c49 273void __attribute__((constructor)) ctf_float_init(void)
de0ba614 274{
f72803ca
MD
275 static_float_declaration =
276 float_declaration_new(FLT_MANT_DIG,
277 sizeof(float) * CHAR_BIT - FLT_MANT_DIG,
278 BYTE_ORDER,
279 __alignof__(float));
280 static_double_declaration =
281 float_declaration_new(DBL_MANT_DIG,
282 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
11d43b90 283 BYTE_ORDER,
f72803ca 284 __alignof__(double));
de0ba614
MD
285}
286
d11e9c49 287void __attribute__((destructor)) ctf_float_fini(void)
de0ba614 288{
f72803ca
MD
289 declaration_unref(&static_float_declaration->p);
290 declaration_unref(&static_double_declaration->p);
6dc2ca62 291}
This page took 0.040602 seconds and 4 git commands to generate.