FreeBSD uuid wrapper fixes
[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 */
6dc2ca62
MD
27#include <endian.h>
28
de0ba614
MD
29/*
30 * This library is limited to binary representation of floating point values.
f72803ca
MD
31 * We use hardware support for conversion between 32 and 64-bit floating
32 * point values.
de0ba614
MD
33 */
34
6dc2ca62
MD
35/*
36 * Aliasing float/double and unsigned long is not strictly permitted by strict
f6625916 37 * aliasing, but in practice declaration prunning is well supported, and this permits
6dc2ca62
MD
38 * us to use per-word read/writes rather than per-byte.
39 */
40
41#if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
42#define HAS_TYPE_PRUNING
43#endif
44
de0ba614
MD
45#if (FLT_RADIX != 2)
46
47#error "Unsupported floating point radix"
48
6dc2ca62 49#endif
6dc2ca62
MD
50
51union doubleIEEE754 {
f72803ca
MD
52 double vd;
53 float vf;
6dc2ca62
MD
54#ifdef HAS_TYPE_PRUNING
55 unsigned long bits[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
56#else
57 unsigned char bits[sizeof(double)];
58#endif
59};
60
f72803ca
MD
61static struct declaration_float *static_float_declaration,
62 *static_double_declaration;
d11e9c49 63
de0ba614
MD
64struct pos_len {
65 size_t sign_start, exp_start, mantissa_start, len;
66};
67
c5e74408
MD
68int _ctf_float_copy(struct stream_pos *destp,
69 struct definition_float *dest_definition,
70 struct stream_pos *srcp,
71 const struct definition_float *src_definition)
6dc2ca62 72{
c5e74408
MD
73 int ret;
74
f72803ca
MD
75 /* We only support copy of same-size floats for now */
76 assert(src_definition->declaration->sign->len ==
77 dest_definition->declaration->sign->len);
78 assert(src_definition->declaration->exp->len ==
79 dest_definition->declaration->exp->len);
80 assert(src_definition->declaration->mantissa->len ==
81 dest_definition->declaration->mantissa->len);
11d43b90 82 /* Read */
d11e9c49 83 if (src_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
84 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
85 if (ret)
86 return ret;
87 ret = ctf_integer_read(srcp, &src_definition->exp->p);
88 if (ret)
89 return ret;
90 ret = ctf_integer_read(srcp, &src_definition->sign->p);
91 if (ret)
92 return ret;
de0ba614 93 } else {
c5e74408
MD
94 ret = ctf_integer_read(srcp, &src_definition->sign->p);
95 if (ret)
96 return ret;
97 ret = ctf_integer_read(srcp, &src_definition->exp->p);
98 if (ret)
99 return ret;
100 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
101 if (ret)
102 return ret;
6dc2ca62 103 }
d11e9c49
MD
104
105 dest_definition->mantissa->value._unsigned =
106 src_definition->mantissa->value._unsigned;
107 dest_definition->exp->value._signed =
108 src_definition->exp->value._signed;
109 dest_definition->sign->value._unsigned =
110 src_definition->sign->value._unsigned;
111
11d43b90 112 /* Write */
d11e9c49 113 if (dest_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
114 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
115 if (ret)
116 return ret;
117 ret = ctf_integer_write(destp, &dest_definition->exp->p);
118 if (ret)
119 return ret;
120 ret = ctf_integer_write(destp, &dest_definition->sign->p);
121 if (ret)
122 return ret;
de0ba614 123 } else {
c5e74408
MD
124 ret = ctf_integer_write(destp, &dest_definition->sign->p);
125 if (ret)
126 return ret;
127 ret = ctf_integer_write(destp, &dest_definition->exp->p);
128 if (ret)
129 return ret;
130 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
131 if (ret)
132 return ret;
6dc2ca62 133 }
c5e74408 134 return 0;
11d43b90 135}
de0ba614 136
c5e74408 137int ctf_float_read(struct stream_pos *ppos, struct definition *definition)
6dc2ca62 138{
d11e9c49
MD
139 struct definition_float *float_definition =
140 container_of(definition, struct definition_float, p);
141 const struct declaration_float *float_declaration =
142 float_definition->declaration;
143 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca
MD
144 union doubleIEEE754 u;
145 struct definition *tmpdef;
146 struct definition_float *tmpfloat;
46322b33 147 struct ctf_stream_pos destp;
c5e74408 148 int ret;
11d43b90 149
f72803ca
MD
150 switch (float_declaration->mantissa->len + 1) {
151 case FLT_MANT_DIG:
152 tmpdef = static_float_declaration->p.definition_new(
153 &static_float_declaration->p,
154 NULL, 0, 0, "__tmpfloat");
155 break;
156 case DBL_MANT_DIG:
157 tmpdef = static_double_declaration->p.definition_new(
158 &static_double_declaration->p,
159 NULL, 0, 0, "__tmpfloat");
160 break;
161 default:
162 return -EINVAL;
163 }
164 tmpfloat = container_of(tmpdef, struct definition_float, p);
989c73bc 165 ctf_init_pos(&destp, -1, O_RDWR);
0f980a35 166 destp.base = (char *) u.bits;
f72803ca 167 destp.packet_size = sizeof(u) * CHAR_BIT;
d11e9c49 168 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 169 ret = _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition);
f72803ca
MD
170 switch (float_declaration->mantissa->len + 1) {
171 case FLT_MANT_DIG:
172 float_definition->value = u.vf;
173 break;
174 case DBL_MANT_DIG:
175 float_definition->value = u.vd;
176 break;
177 default:
178 return -EINVAL;
179 }
d11e9c49 180 definition_unref(tmpdef);
c5e74408 181 return ret;
de0ba614
MD
182}
183
c5e74408 184int ctf_float_write(struct stream_pos *ppos, struct definition *definition)
de0ba614 185{
d11e9c49
MD
186 struct definition_float *float_definition =
187 container_of(definition, struct definition_float, p);
188 const struct declaration_float *float_declaration =
189 float_definition->declaration;
190 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca
MD
191 union doubleIEEE754 u;
192 struct definition *tmpdef;
193 struct definition_float *tmpfloat;
46322b33 194 struct ctf_stream_pos srcp;
c5e74408 195 int ret;
11d43b90 196
f72803ca
MD
197 switch (float_declaration->mantissa->len + 1) {
198 case FLT_MANT_DIG:
199 tmpdef = static_float_declaration->p.definition_new(
200 &static_float_declaration->p,
201 NULL, 0, 0, "__tmpfloat");
202 break;
203 case DBL_MANT_DIG:
204 tmpdef = static_double_declaration->p.definition_new(
205 &static_double_declaration->p,
206 NULL, 0, 0, "__tmpfloat");
207 break;
208 default:
209 return -EINVAL;
210 }
211 tmpfloat = container_of(tmpdef, struct definition_float, p);
8563e754 212 ctf_init_pos(&srcp, -1, O_RDONLY);
0f980a35 213 srcp.base = (char *) u.bits;
f72803ca
MD
214 srcp.packet_size = sizeof(u) * CHAR_BIT;
215 switch (float_declaration->mantissa->len + 1) {
216 case FLT_MANT_DIG:
217 u.vf = float_definition->value;
218 break;
219 case DBL_MANT_DIG:
220 u.vd = float_definition->value;
221 break;
222 default:
223 return -EINVAL;
224 }
d11e9c49 225 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 226 ret = _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat);
d11e9c49 227 definition_unref(tmpdef);
c5e74408 228 return ret;
de0ba614 229}
6dc2ca62 230
d11e9c49 231void __attribute__((constructor)) ctf_float_init(void)
de0ba614 232{
f72803ca
MD
233 static_float_declaration =
234 float_declaration_new(FLT_MANT_DIG,
235 sizeof(float) * CHAR_BIT - FLT_MANT_DIG,
236 BYTE_ORDER,
237 __alignof__(float));
238 static_double_declaration =
239 float_declaration_new(DBL_MANT_DIG,
240 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
11d43b90 241 BYTE_ORDER,
f72803ca 242 __alignof__(double));
de0ba614
MD
243}
244
d11e9c49 245void __attribute__((destructor)) ctf_float_fini(void)
de0ba614 246{
f72803ca
MD
247 declaration_unref(&static_float_declaration->p);
248 declaration_unref(&static_double_declaration->p);
6dc2ca62 249}
This page took 0.036761 seconds and 4 git commands to generate.