BRL-CAD
scan.c
Go to the documentation of this file.
1 /* S C A N . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
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  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <stdarg.h>
24 #include <string.h>
25 
26 #include "bu/log.h"
27 #include "bu/malloc.h"
28 #include "bu/str.h"
29 
30 
31 int
32 bu_scan_fastf_t(int *c, const char *src, const char *delim, int n, ...)
33 {
34  va_list ap;
35  int offset = 0;
36  int current_n = 0, part_n = 0;
37  int len, delim_len;
38  int i;
39  char *delim_fmt;
40 
41  if (UNLIKELY(!delim || n <= 0)) {
42  return 0;
43  }
44 
45  va_start(ap, n);
46 
47  /* TODO: we should just simply skip all occurrences of delim chars
48  * after reading a fastf_t, avoid dynamic memory allocation and
49  * avoid scanf/sscanf (we don't need to scan the delimiter, just
50  * skip chars in a loop until none are found.
51  */
52 
53  delim_len = strlen(delim);
54  /* + 3 here to make room for the two characters '%' and 'n' as
55  * well as the terminating '\0'
56  */
57  delim_fmt = (char *)bu_malloc(delim_len + 3, "bu_scan_fastf_t");
58  bu_strlcpy(delim_fmt, delim, delim_len + 1);
59  bu_strlcat(delim_fmt, "%n", delim_len + 3);
60 
61  for (i = 0; i < n; i++) {
62  /* Read in the next fastf_t */
63  double scan = 0;
64  fastf_t *arg;
65 
66  if (src)
67  part_n = sscanf(src + offset, "%lf%n", &scan, &len);
68  else
69  part_n = scanf("%lf%n", &scan, &len);
70 
71  current_n += part_n;
72  offset += len;
73  if (part_n != 1) {
74  break;
75  }
76 
77  arg = va_arg(ap, fastf_t *);
78  if (arg) {
79  *arg = scan;
80  }
81  /* Don't scan an extra delimiter at the end of the string */
82  if (i == n - 1) {
83  break;
84  }
85 
86  /* Make sure that a delimiter is present */
87  if (src)
88  part_n = sscanf(src + offset, delim_fmt, &len);
89  else
90  part_n = scanf(delim_fmt, &len);
91 
92  offset += len;
93 
94  /* as delim_fmt should only have a %n and that doesn't get
95  * counted in the scanf return, make sure the return is 0 as
96  * no values should be scanned.
97  */
98  if (part_n != 0 || len != delim_len) {
99  break;
100  }
101  }
102 
103  va_end(ap);
104  bu_free(delim_fmt, "bu_scan_fastf_t");
105 
106  if (c) {
107  *c = offset;
108  }
109  return current_n;
110 }
111 /*
112  * Local Variables:
113  * tab-width: 8
114  * mode: C
115  * indent-tabs-mode: t
116  * c-file-style: "stroustrup"
117  * End:
118  * ex: shiftwidth=4 tabstop=8
119  */
Header file for the BRL-CAD common definitions.
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
int bu_scan_fastf_t(int *c, const char *src, const char *delim, int n,...)
Definition: scan.c:32
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
double fastf_t
Definition: defines.h:300
#define bu_strlcat(dst, src, size)
Definition: str.h:50
#define UNLIKELY(expression)
Definition: common.h:282