GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/keyvalue.c Lines: 69 130 53.1 %
Date: 2017-05-26 Branches: 35 80 43.8 %

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 "nrrd.h"
25
#include "privateNrrd.h"
26
27
/***
28
**** NONE of the nrrdKeyValue functions use biff.
29
**** They don't use them now, and they never should.
30
**** Unless I change my mind.
31
***/
32
33
/*
34
******** nrrdKeyValueSize
35
**
36
** returns the number of key/value pairs in a nrrd
37
*/
38
unsigned int
39
nrrdKeyValueSize(const Nrrd *nrrd) {
40
41
2
  if (!nrrd) {
42
    return 0;
43
  }
44
1
  return nrrd->kvpArr->len;
45
1
}
46
47
/*
48
******** nrrdKeyValueIndex
49
**
50
** given an int in [0 .. #key/value pairs - 1], sets *keyP and *valueP
51
** to put to the corresponding key and value.
52
**
53
** NOTE: whether or not *keyP and *valueP are set to pointers to memory
54
** "inside" the nrrd struct (pointers which you had better not free()!)
55
** is controlled by nrrdStateKeyValueReturnInternalPointers, which defaults
56
** to AIR_FALSE
57
*/
58
void
59
nrrdKeyValueIndex(const Nrrd *nrrd, char **keyP, char **valueP,
60
                  unsigned int ki) {
61
62
  if (!( nrrd && keyP && valueP && ki < nrrd->kvpArr->len )) {
63
    if (keyP) {
64
      *keyP = NULL;
65
    }
66
    if (valueP) {
67
      *valueP = NULL;
68
    }
69
    return;
70
  }
71
  if (nrrdStateKeyValueReturnInternalPointers) {
72
    *keyP = nrrd->kvp[0 + 2*ki];
73
    *valueP = nrrd->kvp[1 + 2*ki];
74
  } else {
75
    *keyP = airStrdup(nrrd->kvp[0 + 2*ki]);
76
    *valueP = airStrdup(nrrd->kvp[1 + 2*ki]);
77
  }
78
  return;
79
}
80
81
static unsigned int
82
_kvpIdxFind(const Nrrd *nrrd, const char *key, int *found) {
83
  unsigned int nk, ki, ret;
84
85
226
  nk = nrrd->kvpArr->len;
86
1492
  for (ki=0; ki<nk; ki++) {
87
633
    if (!strcmp(nrrd->kvp[0 + 2*ki], key)) {
88
      break;
89
    }
90
  }
91
113
  if (ki<nk) {
92
    ret = ki;
93
    *found = AIR_TRUE;
94
  } else {
95
    ret = UINT_MAX;
96
113
    *found = AIR_FALSE;
97
  }
98
113
  return ret;
99
}
100
101
void
102
nrrdKeyValueClear(Nrrd *nrrd) {
103
  unsigned int nk, ki;
104
105
4192
  if (!nrrd) {
106
    return;
107
  }
108
109
2096
  nk = nrrd->kvpArr->len;
110
4418
  for (ki=0; ki<nk; ki++) {
111
113
    nrrd->kvp[0 + 2*ki] = (char *)airFree(nrrd->kvp[0 + 2*ki]);
112
113
    nrrd->kvp[1 + 2*ki] = (char *)airFree(nrrd->kvp[1 + 2*ki]);
113
  }
114
2096
  airArrayLenSet(nrrd->kvpArr, 0);
115
116
2096
  return;
117
2096
}
118
119
int
120
nrrdKeyValueErase(Nrrd *nrrd, const char *key) {
121
  unsigned int nk, ki;
122
  int found;
123
124
  if (!( nrrd && key )) {
125
    /* got NULL pointer */
126
    return 1;
127
  }
128
  ki = _kvpIdxFind(nrrd, key, &found);
129
  if (!found) {
130
    return 0;
131
  }
132
  nrrd->kvp[0 + 2*ki] = (char *)airFree(nrrd->kvp[0 + 2*ki]);
133
  nrrd->kvp[1 + 2*ki] = (char *)airFree(nrrd->kvp[1 + 2*ki]);
134
  nk = nrrd->kvpArr->len;
135
  for (; ki<nk-1; ki++) {
136
    nrrd->kvp[0 + 2*ki] = nrrd->kvp[0 + 2*(ki+1)];
137
    nrrd->kvp[1 + 2*ki] = nrrd->kvp[1 + 2*(ki+1)];
138
  }
139
  airArrayLenIncr(nrrd->kvpArr, -1);
140
141
  return 0;
142
}
143
144
/*
145
******** nrrdKeyValueAdd
146
**
147
** This will COPY the given strings, and so does not depend on
148
** them existing past the return of this function
149
**
150
** NOTE: Despite what might be most logical, there is no effort made
151
** here to cleanup key or value, including any escaping or filtering
152
** that might be warranted for white space other than \n
153
**
154
** does NOT use BIFF
155
*/
156
int
157
nrrdKeyValueAdd(Nrrd *nrrd, const char *key, const char *value) {
158
  unsigned int ki;
159
226
  int found;
160
161
113
  if (!( nrrd && key && value )) {
162
    /* got NULL pointer */
163
    return 1;
164
  }
165
113
  if (!strlen(key)) {
166
    /* reject empty keys */
167
    return 1;
168
  }
169
113
  ki = _kvpIdxFind(nrrd, key, &found);
170
113
  if (found) {
171
    /* over-writing value for an existing key, so have to free old value */
172
    airFree(nrrd->kvp[1 + 2*ki]);
173
    nrrd->kvp[1 + 2*ki] = airStrdup(value);
174
  } else {
175
    /* adding value for a new key */
176
113
    ki = airArrayLenIncr(nrrd->kvpArr, 1);
177
113
    nrrd->kvp[0 + 2*ki] = airStrdup(key);
178
113
    nrrd->kvp[1 + 2*ki] = airStrdup(value);
179
  }
180
113
  return 0;
181
113
}
182
183
/*
184
******** nrrdKeyValueGet
185
**
186
** NOTE: whether or not *keyP and *valueP are set to pointers to memory
187
** "inside" the nrrd struct (pointers which you had better not free()!)
188
** is controlled by nrrdStateKeyValueReturnInternalPointers, which defaults
189
** to AIR_FALSE
190
**
191
** does NOT use BIFF
192
*/
193
char *
194
nrrdKeyValueGet(const Nrrd *nrrd, const char *key) {
195
  char *ret;
196
  unsigned int ki;
197
  int found;
198
199
  if (!( nrrd && key )) {
200
    /* got NULL pointer */
201
    return NULL;
202
  }
203
  ki = _kvpIdxFind(nrrd, key, &found);
204
  if (found) {
205
    if (nrrdStateKeyValueReturnInternalPointers) {
206
      ret = nrrd->kvp[1 + 2*ki];
207
    } else {
208
      ret = airStrdup(nrrd->kvp[1 + 2*ki]);
209
    }
210
  } else {
211
    ret = NULL;
212
  }
213
  return ret;
214
}
215
216
/*
217
** Does the escaping of special characters in a string that
218
** is being written either to "FILE *file" or "char *dst"
219
** (WHICH IS ASSUMED to be allocated to be big enough!)
220
** Which characters to escape should be put in string "toescape"
221
** currently supported: \n  \  "
222
** Also, converts characters in "tospace" to a space.  Being in
223
** toescape trumps being in tospace, so tospace can be harmlessly
224
** set to, say, AIR_WHITESPACE.
225
**
226
** accident of history that this function is in this file
227
*/
228
void
229
_nrrdWriteEscaped(FILE *file, char *dst, const char *str,
230
                  const char *toescape, const char *tospace) {
231
  /* static const char me[]="_nrrdWriteEscaped"; */
232
  size_t ci, gslen; /* given strlen */
233
234
28
  gslen = strlen(str);
235
257832
  for (ci=0; ci<gslen; ci++) {
236
    char cc;
237
128902
    cc = str[ci];
238
128902
    if (strchr(toescape, cc)) {
239

134565
      switch(cc) {
240
      case '\n':
241
1411
        if (file) {
242
1411
          fprintf(file, "\\n");
243
1411
        } else {
244
          strcat(dst, "\\n");
245
        }
246
        break;
247
      case '\\':
248
1429
        if (file) {
249
1429
          fprintf(file, "\\\\");
250
1429
        } else {
251
          strcat(dst, "\\\\");
252
        }
253
        break;
254
      case '"':
255
2901
        if (file) {
256
          fprintf(file, "\\\"");
257
        } else {
258
2901
          strcat(dst, "\\\"");
259
        }
260
        break;
261
      }
262
    } else {
263
123161
      if (strchr(tospace, cc)) {
264
        cc = ' ';
265
6885
      }
266
123161
      if (file) {
267
40252
        fputc(cc, file);
268
40252
      } else {
269
        size_t dsln;
270
82909
        dsln = strlen(dst);
271
82909
        dst[dsln++] = cc;
272
82909
        dst[dsln] = '\0';
273
      }
274
    }
275
  }
276
  return;
277
14
}
278
279
/*
280
** _nrrdKeyValueWrite
281
**
282
** writes a given key and value to a file, starting with the given
283
** prefix (if non-NULL), and ending with "\n"
284
*/
285
int
286
_nrrdKeyValueWrite(FILE *file, char **stringP, const char *prefix,
287
                   const char *key, const char *value) {
288
289
6
  if (!( (file || stringP) && key && value )) {
290
    return 1;
291
  }
292
3
  if (stringP) {
293
    /* 2*strlen() because at worst all characters will be escaped */
294
    *stringP = AIR_CALLOC(airStrlen(prefix) + 2*airStrlen(key)
295
                          + strlen(":=") + 2*airStrlen(value)
296
                          + strlen("\n") + 1, char);
297
    /* HEY error checking? */
298
  }
299
3
  if (prefix) {
300
    if (file) {
301
      fprintf(file, "%s", prefix);
302
    } else {
303
      strcat(*stringP, prefix);
304
    }
305
  }
306
3
  if (file) {
307
3
    _nrrdWriteEscaped(file, NULL, key, "\n\\", _NRRD_WHITESPACE_NOTAB);
308
3
    fprintf(file, ":=");
309
3
    _nrrdWriteEscaped(file, NULL, value, "\n\\", _NRRD_WHITESPACE_NOTAB);
310
3
    fprintf(file, "\n");
311
3
  } else {
312
    _nrrdWriteEscaped(NULL, *stringP, key, "\n\\", _NRRD_WHITESPACE_NOTAB);
313
    strcat(*stringP, ":=");
314
    _nrrdWriteEscaped(NULL, *stringP, value, "\n\\", _NRRD_WHITESPACE_NOTAB);
315
    strcat(*stringP, "\n");
316
  }
317
3
  return 0;
318
3
}
319
320
/*
321
******** nrrdKeyValueCopy()
322
**
323
** copies key/value pairs from one nrrd to another
324
** Existing key/value pairs in nout are blown away
325
*/
326
int
327
nrrdKeyValueCopy(Nrrd *nout, const Nrrd *nin) {
328
  char *key, *value;
329
  unsigned int ki;
330
331
246
  if (!(nout && nin)) {
332
    /* got NULL pointer */
333
    return 1;
334
  }
335
123
  if (nout == nin) {
336
    /* can't satisfy semantics of copying with nout==nin */
337
    return 2;
338
  }
339
340
123
  nrrdKeyValueClear(nout);
341
252
  for (ki=0; ki<nin->kvpArr->len; ki++) {
342
3
    key = nin->kvp[0 + 2*ki];
343
3
    value = nin->kvp[1 + 2*ki];
344
3
    if (nrrdKeyValueAdd(nout, key, value)) {
345
      return 3;
346
    }
347
  }
348
349
123
  return 0;
350
123
}