GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/biff/biffmsg.c Lines: 78 133 58.6 %
Date: 2017-05-26 Branches: 34 70 48.6 %

Line Branch Exec Source
1
/*
2
  Teem: Tools to process and visualize scientific data and images             .
3
  Copyright (C) 2013, 2012, 2011, 2010, 2009  University of Chicago
4
  Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
5
  Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
6
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public License
9
  (LGPL) as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
  The terms of redistributing and/or modifying this software also
12
  include exceptions to the LGPL that facilitate static linking.
13
14
  This library is distributed in the hope that it will be useful,
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
  Lesser General Public License for more details.
18
19
  You should have received a copy of the GNU Lesser General Public License
20
  along with this library; if not, write to Free Software Foundation, Inc.,
21
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
*/
23
24
#include "biff.h"
25
#include "privateBiff.h"
26
27
/* ---- BEGIN non-NrrdIO */
28
const int
29
biffPresent = 42;
30
/* ---- END non-NrrdIO */
31
32
/*
33
** with the Nov'09 re-write of biff, this sourcefile becomes the only
34
** place where a static buffer is used for message handling; this
35
** should eventually be avoided by using things like asprintf and
36
** vasprintf which allocated the string as needed
37
*/
38
#define _HACK_STRLEN  AIR_STRLEN_HUGE
39
#define _MSG_INCR 2
40
41
biffMsg *
42
biffMsgNew(const char *key) {
43
  static const char me[]="biffMsgNew";
44
  biffMsg *msg;
45
46
56
  if (!key) {
47
    fprintf(stderr, "%s: PANIC got NULL key\n", me);
48
    return NULL; /* exit(1); */
49
  }
50
28
  msg = AIR_CALLOC(1, biffMsg);
51
28
  if (msg) {
52
    airPtrPtrUnion appu;
53
54
28
    msg->key = airStrdup(key);
55
28
    msg->err = NULL;
56
28
    msg->errNum = 0;
57
28
    appu.cp = &(msg->err);
58
28
    msg->errArr = airArrayNew(appu.v, &(msg->errNum),
59
                              sizeof(char*), _MSG_INCR);
60
28
    if (msg->errArr) {
61
28
      airArrayPointerCB(msg->errArr, NULL, airFree);
62
28
    }
63
28
  }
64

84
  if (!( msg && msg->key && msg->errArr )) {
65
    fprintf(stderr, "%s: PANIC couldn't calloc new msg\n", me);
66
    return NULL; /* exit(1); */
67
  }
68
28
  return msg;
69
28
}
70
71
biffMsg *
72
biffMsgNix(biffMsg *msg) {
73
74

75
  if (msg && msg != biffMsgNoop) {
75
25
    airFree(msg->key);
76
25
    airArrayLenSet(msg->errArr, 0); /* frees all msg->err[i] */
77
25
    airArrayNuke(msg->errArr);
78
25
    airFree(msg);
79
25
  }
80
25
  return NULL;
81
}
82
83
/*
84
** adds a given message to the given entry.  The message is processed to
85
** convert all whitespace into ' ', and to eliminate whitespace at the
86
** end of the message.
87
*/
88
void
89
biffMsgAdd(biffMsg *msg, const char *err) {
90
  static const char me[]="biffMsgAdd";
91
  unsigned int idx;
92
93
104
  if (biffMsgNoop == msg) {
94
    return;
95
  }
96
52
  if (!( msg && err )) {
97
    fprintf(stderr, "%s: PANIC got NULL msg (%p) or err (%p)\n", me,
98
            AIR_VOIDP(msg), AIR_CVOIDP(err));
99
    return; /* exit(1); */
100
  }
101
52
  idx = airArrayLenIncr(msg->errArr, 1);
102
52
  if (!msg->err) {
103
    fprintf(stderr, "%s: PANIC: couldn't add message to %s\n", me, msg->key);
104
    return; /* exit(1); */
105
  }
106
52
  if (!( msg->err[idx] = airOneLinify(airStrdup(err)) )) {
107
    fprintf(stderr, "%s: PANIC: couldn't alloc message to %s\n", me, msg->key);
108
    return; /* exit(1); */
109
  }
110
52
  return;
111
52
}
112
113
void
114
_biffMsgAddVL(biffMsg *msg, const char *errfmt, va_list args) {
115
44
  char errstr[_HACK_STRLEN];
116
117
22
  vsprintf(errstr, errfmt, args);
118
22
  biffMsgAdd(msg, errstr);
119
  return;
120
22
}
121
122
/* ---- BEGIN non-NrrdIO */
123
void
124
biffMsgAddf(biffMsg *msg, const char *errfmt, ...) {
125
  va_list args;
126
127
  va_start(args, errfmt);
128
  _biffMsgAddVL(msg, errfmt, args);
129
  va_end(args);
130
  return;
131
}
132
/* ---- END non-NrrdIO */
133
134
void
135
biffMsgClear(biffMsg *msg) {
136
137
10
  if (biffMsgNoop == msg) {
138
    return;
139
  }
140
5
  airArrayLenSet(msg->errArr, 0); /* frees all msg->err[i] */
141
  /* but msg->key stays allocated */
142
5
  return;
143
5
}
144
145
/*
146
** max length of line formatted "[<key>] <err>\n"
147
*/
148
unsigned int
149
biffMsgLineLenMax(const biffMsg *msg) {
150
  unsigned int ii, len, maxlen;
151
152
62
  if (biffMsgNoop == msg) {
153
    return 0;
154
  }
155
  maxlen = 0;
156
166
  for (ii=0; ii<msg->errNum; ii++) {
157
52
    len = AIR_UINT(strlen(msg->err[ii]) + strlen(msg->key) + strlen("[] \n"));
158
52
    maxlen = AIR_MAX(maxlen, len);
159
  }
160
31
  return maxlen;
161
31
}
162
163
/*
164
******** biffMsgMove
165
**
166
** "src" is not const because we clear it after moving things out
167
*/
168
void
169
biffMsgMove(biffMsg *dest, biffMsg *src, const char *err) {
170
  static const char me[]="biffMsgMove";
171
  unsigned int ii;
172
  char *buff;
173
174

15
  if (biffMsgNoop == dest || biffMsgNoop == src) {
175
    return;
176
  }
177
5
  if (!( dest && src )) {
178
    fprintf(stderr, "%s: PANIC got NULL msg (%p %p)\n", me,
179
            AIR_VOIDP(dest), AIR_VOIDP(src));
180
    return; /* exit(1); */
181
  }
182
  /* if src and dest are same, this degenerates to biffMsgAdd */
183

5
  if (dest == src && airStrlen(err)) {
184
    biffMsgAdd(dest, err);
185
    return;
186
  }
187
188
5
  buff = AIR_CALLOC(biffMsgLineLenMax(src)+1, char);
189
5
  if (!buff) {
190
    fprintf(stderr, "%s: PANIC: can't allocate buffer\n", me);
191
    return; /* exit(1); */
192
  }
193
26
  for (ii=0; ii<src->errNum; ii++) {
194
8
    sprintf(buff, "[%s] %s", src->key, src->err[ii]);
195
8
    biffMsgAdd(dest, buff);
196
  }
197
5
  free(buff);
198
5
  biffMsgClear(src);
199
5
  if (airStrlen(err)) {
200
4
    biffMsgAdd(dest, err);
201
4
  }
202
5
  return;
203
5
}
204
205
void
206
_biffMsgMoveVL(biffMsg *dest, biffMsg *src,
207
               const char *errfmt, va_list args) {
208
8
  char errstr[_HACK_STRLEN];
209
210
4
  vsprintf(errstr, errfmt, args);
211
4
  biffMsgMove(dest, src, errstr);
212
  return;
213
4
}
214
215
void
216
biffMsgMovef(biffMsg *dest, biffMsg *src, const char *errfmt, ...) {
217
  va_list args;
218
219
  va_start(args, errfmt);
220
  _biffMsgMoveVL(dest, src, errfmt, args);
221
  va_end(args);
222
  return;
223
}
224
225
/*
226
******** biffMsgErrNum
227
**
228
** returns number of errors in a message
229
*/
230
unsigned int
231
biffMsgErrNum(const biffMsg *msg) {
232
233
  if (biffMsgNoop == msg) {
234
    return 0;
235
  }
236
  if (!msg) {
237
    return 0;
238
  }
239
  return msg->errNum;
240
}
241
242
/*
243
******** biffMsgStrlen
244
**
245
** returns length of string (not including null termination, as usual)
246
** of the error message that will be generated by biffMsgStrSet
247
*/
248
unsigned int
249
biffMsgStrlen(const biffMsg *msg) {
250
  static const char me[]="biffMsgStrlen";
251
  unsigned int ii, len;
252
253
52
  if (biffMsgNoop == msg) {
254
    return 0;
255
  }
256
26
  if (!( msg )) {
257
    fprintf(stderr, "%s: PANIC got NULL msg %p\n", me, AIR_CVOIDP(msg));
258
    return 0; /* exit(1); */
259
  }
260
261
  len = 0;
262
140
  for (ii=0; ii<msg->errNum; ii++) {
263
44
    len += AIR_UINT(strlen(msg->key)
264
                    + strlen(msg->err[ii]) + strlen("[] \n"));
265
  }
266
26
  return len+1;
267
26
}
268
269
char *
270
biffMsgStrAlloc(const biffMsg *msg) {
271
  static const char me[]="biffMsgStrAlloc";
272
  char *ret;
273
  unsigned int len;
274
275
  if (biffMsgNoop == msg) {
276
    return NULL;
277
  }
278
  len = biffMsgStrlen(msg);
279
  ret = AIR_CALLOC(len+1, char);
280
  if (!ret) {
281
    fprintf(stderr, "%s: PANIC couldn't alloc string", me);
282
    return NULL; /* exit(1); */
283
  }
284
  return ret;
285
}
286
287
/*
288
** ret is assumed to be allocated for biffMsgStrlen()+1, or is the
289
** the return from biffMsgStrAlloc
290
*/
291
void
292
biffMsgStrSet(char *ret, const biffMsg *msg) {
293
  static const char me[]="biffMsgStrSet";
294
  char *buff;
295
  unsigned int ii;
296
297
52
  if (biffMsgNoop == msg) {
298
    return;
299
  }
300
26
  if (!ret) {
301
    fprintf(stderr, "%s: PANIC got NULL ret", me);
302
    return;
303
  }
304
26
  buff = AIR_CALLOC(biffMsgLineLenMax(msg)+1, char);
305
26
  if (!buff) {
306
    fprintf(stderr, "%s: PANIC couldn't alloc buffer", me);
307
    return; /* exit(1); */
308
  }
309
26
  strcpy(ret, "");
310
140
  for (ii=msg->errNum; ii>0; ii--) {
311
44
    sprintf(buff, "[%s] %s\n", msg->key, msg->err[ii-1]);
312
44
    strcat(ret, buff);
313
  }
314
26
  free(buff);
315
52
}
316
317
char *
318
biffMsgStrGet(const biffMsg *msg) {
319
  char *ret;
320
321
  if (biffMsgNoop == msg) {
322
    return NULL;
323
  }
324
  ret = biffMsgStrAlloc(msg);
325
  biffMsgStrSet(ret, msg);
326
  return ret;
327
}
328
329
biffMsg
330
_biffMsgNoop = {
331
  NULL,
332
  NULL,
333
  0,
334
  NULL
335
};
336
337
/*
338
******** biffMsgNoop
339
**
340
** pass this instead of a real biffMsg (allocated by biffMsgNew) as a
341
** flag to say, "don't bother, really".  This turns all the biffMsg
342
** functions into no-ops (except that var-args are still consumed
343
** where they are used)
344
*/
345
biffMsg *
346
biffMsgNoop = &_biffMsgNoop;