LAL  7.5.0.1-8083555
LALValue.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2016 Jolien Creighton
3 *
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 2 of the License, or
7 * (at your option) any later version.
8 *
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.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <lal/LALStdlib.h>
24 #include <lal/LALStdio.h>
25 #include <lal/LALValue.h>
26 #include "LALValue_private.h"
27 #include "config.h"
28 
29 /* warning: garbage until set */
30 LALValue * XLALValueAlloc(size_t size)
31 {
32  LALValue *v = XLALMalloc(sizeof(*v) + size);
33  if (!v)
35  v->size = size;
36  return v;
37 }
38 
39 /* warning: garbage until set */
40 LALValue * XLALValueRealloc(LALValue *value, size_t size)
41 {
42  if (value == NULL)
43  return XLALValueAlloc(size);
44  value = XLALRealloc(value, sizeof(*value) + size);
45  if (!value)
47  value->size = size;
48  return value;
49 }
50 
51 LALValue * XLALValueDuplicate(const LALValue *value)
52 {
53  size_t size = sizeof(LALValue) + value->size;
54  LALValue *copy = XLALMalloc(size);
55  if (!copy)
57  return memcpy(copy, value, size);
58 }
59 
60 LALValue * XLALValueCopy(LALValue *copy, const LALValue *orig)
61 {
62  LALTYPECODE type = XLALValueGetType(orig);
63  size_t size = XLALValueGetSize(orig);
64  const void * data = XLALValueGetDataPtr(orig);
65  return XLALValueSet(copy, data, size, type);
66 }
67 
68 LALValue * XLALValueSet(LALValue *value, const void *data, size_t size, LALTYPECODE type)
69 {
70  XLAL_CHECK_NULL(value != NULL, XLAL_EFAULT);
71 
72  /* sanity check type-size relation */
73  switch (type) {
74  case LAL_CHAR_TYPE_CODE:
75  /* variable length strings allowed */
76  break;
77  case LAL_I2_TYPE_CODE:
78  XLAL_CHECK_NULL(size == sizeof(INT2), XLAL_ETYPE, "Wrong size for type");
79  break;
80  case LAL_I4_TYPE_CODE:
81  XLAL_CHECK_NULL(size == sizeof(INT4), XLAL_ETYPE, "Wrong size for type");
82  break;
83  case LAL_I8_TYPE_CODE:
84  XLAL_CHECK_NULL(size == sizeof(INT8), XLAL_ETYPE, "Wrong size for type");
85  break;
87  /* variable length BLOBs allowed */
88  break;
89  case LAL_U2_TYPE_CODE:
90  XLAL_CHECK_NULL(size == sizeof(UINT2), XLAL_ETYPE, "Wrong size for type");
91  break;
92  case LAL_U4_TYPE_CODE:
93  XLAL_CHECK_NULL(size == sizeof(UINT4), XLAL_ETYPE, "Wrong size for type");
94  break;
95  case LAL_U8_TYPE_CODE:
96  XLAL_CHECK_NULL(size == sizeof(UINT8), XLAL_ETYPE, "Wrong size for type");
97  break;
98  case LAL_S_TYPE_CODE:
99  XLAL_CHECK_NULL(size == sizeof(REAL4), XLAL_ETYPE, "Wrong size for type");
100  break;
101  case LAL_D_TYPE_CODE:
102  XLAL_CHECK_NULL(size == sizeof(REAL8), XLAL_ETYPE, "Wrong size for type");
103  break;
104  case LAL_C_TYPE_CODE:
105  XLAL_CHECK_NULL(size == sizeof(COMPLEX8), XLAL_ETYPE, "Wrong size for type");
106  break;
107  case LAL_Z_TYPE_CODE:
108  XLAL_CHECK_NULL(size == sizeof(COMPLEX16), XLAL_ETYPE, "Wrong size for type");
109  break;
110  default:
111  XLAL_ERROR_NULL(XLAL_ETYPE, "Unsupported LALTYPECODE value 0%o", (unsigned int)type);
112  }
113 
114  /* make sure sizes are compatible */
115  XLAL_CHECK_NULL(size == value->size, XLAL_ESIZE, "Value has incompatible size");
116 
117  value->type = type;
118  memcpy(value->data, data, size);
119  return value;
120 }
121 
122 void XLALDestroyValue(LALValue *value)
123 {
124  XLALFree(value);
125  return;
126 }
127 
128 LALValue *XLALCreateValue(const void * data, size_t size, LALTYPECODE type)
129 {
130  LALValue *v = XLALValueAlloc(size);
131  if (v == NULL)
133  v = XLALValueSet(v, data, size, type);
134  if (v == NULL)
136  return v;
137 }
138 
139 LALValue *XLALCreateBLOBValue(const void * blob, size_t size)
140 {
141  LALValue *v = XLALCreateValue(blob, size, LAL_UCHAR_TYPE_CODE);
142  if (v == NULL)
144  return v;
145 }
146 
147 LALValue *XLALCreateStringValue(const char *string)
148 {
149  size_t size = strlen(string) + 1;
150  LALValue *v = XLALCreateValue(string, size, LAL_CHAR_TYPE_CODE);
151  if (v == NULL)
153  return v;
154 }
155 
156 #define DEFINE_CREATE_FUNC(TYPE, TCODE) \
157  LALValue *XLALCreate ## TYPE ## Value(TYPE value) \
158  { \
159  LALValue *v = XLALCreateValue(&value, sizeof(value), TCODE); \
160  if (v == NULL) \
161  XLAL_ERROR_NULL(XLAL_EFUNC); \
162  return v; \
163  }
164 
177 
178 #undef DEFINE_CREATE_FUNC
179 
180 LALTYPECODE XLALValueGetType(const LALValue *value)
181 {
182  return value->type;
183 }
184 
185 size_t XLALValueGetSize(const LALValue *value)
186 {
187  return value->size;
188 }
189 
190 /* warning: shallow pointer */
191 const void * XLALValueGetDataPtr(const LALValue *value)
192 {
193  return value->data;
194 }
195 
196 void * XLALValueGetData(void *data, size_t size, LALTYPECODE type, const LALValue *value)
197 {
198  if (value->size != size || value->type != type)
199  XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect value type");
200  return memcpy(data, value->data, size);
201 }
202 
203 int XLALValueEqual(const LALValue *value1, const LALValue *value2)
204 {
205  if (value1->size == value2->size && value1->type == value2->type)
206  return memcmp(value1->data, value2->data, value1->size) == 0;
207  return 0;
208 }
209 
210 void * XLALValueGetBLOB(const LALValue *value)
211 {
212  void *blob;
213  /* sanity check the type */
214  if (value->type != LAL_UCHAR_TYPE_CODE)
215  XLAL_ERROR_NULL(XLAL_ETYPE, "Value is not a BLOB");
216  blob = LALMalloc(value->size);
217  if (blob == NULL)
219  return memcpy(blob, value->data, value->size);
220 }
221 
222 /* warning: shallow pointer */
223 const char * XLALValueGetString(const LALValue *value)
224 {
225  /* sanity check the type */
226  if (value->type != LAL_CHAR_TYPE_CODE)
227  XLAL_ERROR_NULL(XLAL_ETYPE, "Value is not a string");
228  /* make sure this is a nul-terminated string */
229  if (value->size == 0 || ((const char *)(value->data))[value->size - 1] != '\0')
230  XLAL_ERROR_NULL(XLAL_ETYPE, "Value is not a string");
231  return (const char *)(value->data);
232 }
233 
234 #define DEFINE_GET_FUNC(TYPE, TCODE, FAILVAL) \
235  TYPE XLALValueGet ## TYPE (const LALValue *value) \
236  { \
237  XLAL_CHECK_VAL(FAILVAL, value->type == TCODE, XLAL_ETYPE); \
238  return *(const TYPE *)(value->data); \
239  }
240 
253 
254 #undef DEFINE_GET_FUNC
255 
256 REAL8 XLALValueGetAsREAL8(const LALValue *value)
257 {
258  const INT8 max_as_double = LAL_INT8_C(9007199254740992);
259  const UINT8 umax_as_double = LAL_INT8_C(9007199254740992);
260  INT8 i;
261  UINT8 u;
262  REAL8 result;
263  switch (value->type) {
264  case LAL_CHAR_TYPE_CODE:
265  if (value->size == 1)
266  result = *(const CHAR *)value;
267  else
268  XLAL_ERROR_REAL8(XLAL_ETYPE, "Cannot convert string to float");
269  break;
270  case LAL_I2_TYPE_CODE:
271  result = XLALValueGetINT2(value);
272  break;
273  case LAL_I4_TYPE_CODE:
274  result = XLALValueGetINT4(value);
275  break;
276  case LAL_I8_TYPE_CODE:
277  result = i = XLALValueGetINT8(value);
278  if (i > max_as_double || -i > max_as_double)
279  XLAL_PRINT_WARNING("Loss of precision");
280  break;
281  case LAL_UCHAR_TYPE_CODE:
282  if (value->size == 1)
283  result = XLALValueGetUCHAR(value);
284  else
285  XLAL_ERROR_REAL8(XLAL_ETYPE, "Cannot convert BLOB to float");
286  break;
287  case LAL_U2_TYPE_CODE:
288  result = XLALValueGetUINT2(value);
289  break;
290  case LAL_U4_TYPE_CODE:
291  result = XLALValueGetUINT4(value);
292  break;
293  case LAL_U8_TYPE_CODE:
294  result = u = XLALValueGetUINT8(value);
295  if (u > umax_as_double)
296  XLAL_PRINT_WARNING("Loss of precision");
297  break;
298  case LAL_S_TYPE_CODE:
299  result = XLALValueGetREAL4(value);
300  break;
301  case LAL_D_TYPE_CODE:
302  result = XLALValueGetREAL8(value);
303  break;
304  case LAL_C_TYPE_CODE:
305  case LAL_Z_TYPE_CODE:
306  XLAL_ERROR_REAL8(XLAL_ETYPE, "Cannot convert complex to float");
307  default:
308  XLAL_ERROR_REAL8(XLAL_ETYPE, "Unsupported LALTYPECODE value 0%o", (unsigned int)value->type);
309  }
310  return result;
311 }
312 
313 char * XLALValueAsStringAppend(char *s, const LALValue *value)
314 {
315  COMPLEX8 c;
316  COMPLEX16 z;
317  switch (value->type) {
318  case LAL_CHAR_TYPE_CODE:
319  if (value->size == 1)
320  s = XLALStringAppendFmt(s, "'%c'", *(const CHAR *)(value->data));
321  else
322  s = XLALStringAppendFmt(s, "\"%s\"", (const CHAR *)(value->data));
323  break;
324  case LAL_I2_TYPE_CODE:
325  if (value->size != sizeof(INT2))
326  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
328  break;
329  case LAL_I4_TYPE_CODE:
330  if (value->size != sizeof(INT4))
331  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
333  break;
334  case LAL_I8_TYPE_CODE:
335  if (value->size != sizeof(INT8))
336  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
338  break;
339  case LAL_UCHAR_TYPE_CODE:
340  if (value->size == sizeof(UCHAR))
341  s = XLALStringAppendFmt(s, "0x%x", XLALValueGetUCHAR(value));
342  else {
343  s = XLALStringAppendFmt(s, "b\"");
344  for (size_t i = 0; i < value->size; ++i)
345  s = XLALStringAppendFmt(s, "\\x%02x", ((const UCHAR *)(value->data))[i]);
346  s = XLALStringAppendFmt(s, "\"");
347  }
348  break;
349  case LAL_U2_TYPE_CODE:
350  if (value->size != sizeof(UINT2))
351  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
353  break;
354  case LAL_U4_TYPE_CODE:
355  if (value->size != sizeof(UINT4))
356  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
358  break;
359  case LAL_U8_TYPE_CODE:
360  if (value->size != sizeof(UINT8))
361  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
363  break;
364  case LAL_S_TYPE_CODE:
365  if (value->size != sizeof(REAL4))
366  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
367  s = XLALStringAppendFmt(s, "%.8g", XLALValueGetREAL4(value));
368  break;
369  case LAL_D_TYPE_CODE:
370  if (value->size != sizeof(REAL8))
371  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
372  s = XLALStringAppendFmt(s, "%.16g", XLALValueGetREAL8(value));
373  break;
374  case LAL_C_TYPE_CODE:
375  c = XLALValueGetCOMPLEX8(value);
376  if (value->size != sizeof(COMPLEX8))
377  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
378  s = XLALStringAppendFmt(s, "%.8g%+.8gj", crealf(c), cimagf(c));
379  break;
380  case LAL_Z_TYPE_CODE:
381  z = XLALValueGetCOMPLEX16(value);
382  if (value->size != sizeof(COMPLEX16))
383  XLAL_ERROR_NULL(XLAL_ESIZE, "Value has incorrect size for type");
384  s = XLALStringAppendFmt(s, "%.16g%+.16gj", creal(z), cimag(z));
385  break;
386  default:
387  XLAL_ERROR_NULL(XLAL_ETYPE, "Unsupported LALTYPECODE value 0%o", (unsigned int)value->type);
388  }
389  return s;
390 }
391 
392 void XLALValuePrint(const LALValue *value, int fd)
393 {
394  char *s = NULL;
395  s = XLALValueAsStringAppend(s, value);
397 #if HAVE_DPRINTF
398  dprintf(fd, "%s", s);
399 #else
400  /* hack... */
401  switch (fd) {
402  case 1:
403  fprintf(stdout, "%s", s);
404  break;
405  case 2:
406  fprintf(stderr, "%s", s);
407  break;
408  default:
409  LALFree(s);
410  XLAL_ERROR_VOID(XLAL_EIO, "Don't know what to do with file descriptor %d", fd);
411  }
412 #endif
413  LALFree(s);
414  return;
415 }
#define LALMalloc(n)
Definition: LALMalloc.h:93
#define LALFree(p)
Definition: LALMalloc.h:96
char * XLALStringAppendFmt(char *s, const char *fmt,...)
Append the formatted string 'fmt' to the string 's', which is reallocated with XLALRealloc() to the r...
Definition: LALString.c:69
LALValue * XLALValueRealloc(LALValue *value, size_t size)
Definition: LALValue.c:40
REAL8 XLALValueGetAsREAL8(const LALValue *value)
Definition: LALValue.c:256
char * XLALValueAsStringAppend(char *s, const LALValue *value)
Definition: LALValue.c:313
LALValue * XLALValueDuplicate(const LALValue *value)
Definition: LALValue.c:51
int XLALValueEqual(const LALValue *value1, const LALValue *value2)
Definition: LALValue.c:203
#define DEFINE_GET_FUNC(TYPE, TCODE, FAILVAL)
Definition: LALValue.c:234
void * XLALValueGetBLOB(const LALValue *value)
Definition: LALValue.c:210
void XLALDestroyValue(LALValue *value)
Definition: LALValue.c:122
LALValue * XLALCreateValue(const void *data, size_t size, LALTYPECODE type)
Definition: LALValue.c:128
void XLALValuePrint(const LALValue *value, int fd)
Definition: LALValue.c:392
LALValue * XLALValueCopy(LALValue *copy, const LALValue *orig)
Definition: LALValue.c:60
LALValue * XLALCreateStringValue(const char *string)
Definition: LALValue.c:147
#define DEFINE_CREATE_FUNC(TYPE, TCODE)
Definition: LALValue.c:156
size_t XLALValueGetSize(const LALValue *value)
Definition: LALValue.c:185
const void * XLALValueGetDataPtr(const LALValue *value)
Definition: LALValue.c:191
const char * XLALValueGetString(const LALValue *value)
Definition: LALValue.c:223
LALValue * XLALCreateBLOBValue(const void *blob, size_t size)
Definition: LALValue.c:139
void * XLALValueGetData(void *data, size_t size, LALTYPECODE type, const LALValue *value)
Definition: LALValue.c:196
LALValue * XLALValueAlloc(size_t size)
Definition: LALValue.c:30
LALTYPECODE XLALValueGetType(const LALValue *value)
Definition: LALValue.c:180
LALValue * XLALValueSet(LALValue *value, const void *data, size_t size, LALTYPECODE type)
Definition: LALValue.c:68
REAL8 XLALValueGetREAL8(const LALValue *value)
REAL4 XLALValueGetREAL4(const LALValue *value)
INT2 XLALValueGetINT2(const LALValue *value)
INT8 XLALValueGetINT8(const LALValue *value)
UCHAR XLALValueGetUCHAR(const LALValue *value)
COMPLEX8 XLALValueGetCOMPLEX8(const LALValue *value)
COMPLEX16 XLALValueGetCOMPLEX16(const LALValue *value)
UINT8 XLALValueGetUINT8(const LALValue *value)
INT4 XLALValueGetINT4(const LALValue *value)
UINT4 XLALValueGetUINT4(const LALValue *value)
UINT2 XLALValueGetUINT2(const LALValue *value)
#define fprintf
LALTYPECODE
Type codes: use these type codes to identify a LAL atomic data type, see Headers LAL(Atomic)Datatypes...
Definition: LALDatatypes.h:49
unsigned char UCHAR
One-byte unsigned integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint64_t UINT8
Eight-byte unsigned integer; on some platforms this is equivalent to unsigned long int instead.
double complex COMPLEX16
Double-precision floating-point complex number (16 bytes total)
#define LAL_INT8_C(c)
Macro for use in defining v as an INT8 constant.
double REAL8
Double precision real floating-point number (8 bytes).
int16_t INT2
Two-byte signed integer.
int64_t INT8
Eight-byte signed integer; on some platforms this is equivalent to long int instead.
uint16_t UINT2
Two-byte unsigned integer.
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
float complex COMPLEX8
Single-precision floating-point complex number (8 bytes total)
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
@ LAL_C_TYPE_CODE
COMPLEX8 type code (27)
Definition: LALDatatypes.h:60
@ LAL_CHAR_TYPE_CODE
CHAR type code (0)
Definition: LALDatatypes.h:50
@ LAL_U2_TYPE_CODE
UINT2 type code (33)
Definition: LALDatatypes.h:55
@ LAL_Z_TYPE_CODE
COMPLEX16 type code (28)
Definition: LALDatatypes.h:61
@ LAL_S_TYPE_CODE
REAL4 type code (18)
Definition: LALDatatypes.h:58
@ LAL_I2_TYPE_CODE
INT2 type code (1)
Definition: LALDatatypes.h:51
@ LAL_I8_TYPE_CODE
INT8 type code (3)
Definition: LALDatatypes.h:53
@ LAL_D_TYPE_CODE
REAL8 type code (19)
Definition: LALDatatypes.h:59
@ LAL_I4_TYPE_CODE
INT4 type code (2)
Definition: LALDatatypes.h:52
@ LAL_UCHAR_TYPE_CODE
UCHAR type code (32)
Definition: LALDatatypes.h:54
@ LAL_U8_TYPE_CODE
UINT8 type code (35)
Definition: LALDatatypes.h:57
@ LAL_U4_TYPE_CODE
UINT4 type code (34)
Definition: LALDatatypes.h:56
#define XLALMalloc(n)
Definition: LALMalloc.h:44
#define XLALFree(p)
Definition: LALMalloc.h:47
#define XLALRealloc(p, n)
Definition: LALMalloc.h:46
#define LAL_INT4_PRId
Definition: LALStdio.h:69
#define LAL_INT8_PRIu
Definition: LALStdio.h:84
#define LAL_INT8_PRId
Definition: LALStdio.h:81
#define LAL_INT2_PRId
Definition: LALStdio.h:57
#define LAL_INT2_PRIu
Definition: LALStdio.h:60
#define LAL_INT4_PRIu
Definition: LALStdio.h:72
#define XLAL_ERROR_VOID(...)
Macro to invoke a failure from a XLAL routine returning void.
Definition: XLALError.h:726
#define XLAL_ERROR_REAL8(...)
Macro to invoke a failure from a XLAL routine returning a REAL8.
Definition: XLALError.h:752
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define XLAL_CHECK_VOID(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns void.
Definition: XLALError.h:840
#define XLAL_REAL4_FAIL_NAN
Floating-point value of the XLAL REAL4 failure NaN.
Definition: XLALError.h:388
#define XLAL_REAL8_FAIL_NAN
Floating-point value of the XLAL REAL8 failure NaN.
Definition: XLALError.h:389
#define XLAL_PRINT_WARNING(...)
Macro that will print a warning message with a standard format.
Definition: XLALError.h:270
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_ETYPE
Wrong or unknown type.
Definition: XLALError.h:422
@ XLAL_ESIZE
Wrong size.
Definition: XLALError.h:420
@ XLAL_EIO
I/O error.
Definition: XLALError.h:406
@ XLAL_FAILURE
Failure return value (not an error number)
Definition: XLALError.h:402