binScanf.cpp
Go to the documentation of this file.
1 /* $Id: scanf.c,v 1.2 2002/08/09 20:56:57 pefo Exp $ */
2 
3 /*
4  * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  * must display the following acknowledgement:
16  * This product includes software developed by Opsycon AB.
17  * 4. The name of the author may not be used to endorse or promote products
18  * derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  */
33 
34 #define _CRT_SECURE_NO_WARNINGS
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <vector>
40 #include "sick_scan/binScanf.hpp"
41 
42 #define MAXLN (10 * 1024)
43 
44 #define ISSPACE " \t\n\r\f\v"
45 
46 int binIsspace(int val)
47 {
48  if (val < 0) // characters >= 80
49  {
50  val = (int)(val & 0xFF);
51  }
52  int ret = isspace(val);
53  return(ret);
54 }
55 static char *
56 _binGetbase(char *p, int *basep)
57 {
58  if (p[0] == '0') {
59  switch (p[1]) {
60  case 'x':
61  *basep = 16;
62  break;
63  case 't': case 'n':
64  *basep = 10;
65  break;
66  case 'o':
67  *basep = 8;
68  break;
69  default:
70  *basep = 10;
71  return (p);
72  }
73  return (p + 2);
74  }
75  *basep = 10;
76  return (p);
77 }
78 static int
79 _binAtob(unsigned long *vp, char *p, int base)
80 {
81  unsigned long value, v1, v2;
82  char *q, tmp[20];
83  int digit;
84 
85  if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
86  base = 16;
87  p += 2;
88  }
89 
90  if (base == 16 && (q = strchr(p, '.')) != 0) {
91  if (q - p > sizeof(tmp) - 1)
92  return (0);
93 
94  strncpy(tmp, p, q - p);
95  tmp[q - p] = '\0';
96  if (!_binAtob(&v1, tmp, 16))
97  return (0);
98 
99  q++;
100  if (strchr(q, '.'))
101  return (0);
102 
103  if (!_binAtob(&v2, q, 16))
104  return (0);
105  *vp = (v1 << 16) + v2;
106  return (1);
107  }
108 
109  value = *vp = 0;
110  for (; *p; p++) {
111  if (*p >= '0' && *p <= '9')
112  digit = *p - '0';
113  else if (*p >= 'a' && *p <= 'f')
114  digit = *p - 'a' + 10;
115  else if (*p >= 'A' && *p <= 'F')
116  digit = *p - 'A' + 10;
117  else
118  return (0);
119 
120  if (digit >= base)
121  return (0);
122  value *= base;
123  value += digit;
124  }
125  *vp = value;
126  return (1);
127 }
128 
129 /*
130 * atob(vp,p,base)
131 * converts p to binary result in vp, rtn 1 on success
132 */
133 int binAtob(unsigned long*vp, char *p, int base)
134 {
135 
136  unsigned long v;
137 
138  if (base == 0)
139  p = _binGetbase(p, &base);
140  if (_binAtob(&v, p, base)) {
141  *vp = v;
142  return (1);
143  }
144  return (0);
145 }
146 
147 
148 
149 /*
150  * scanf(fmt,va_alist)
151  */
152 int
153 binSscanf(const char *fmt, ...)
154 {
155  int count;
156  va_list ap;
157 
158  va_start(ap, fmt);
159  count = vfscanf(stdin, fmt, ap);
160  va_end(ap);
161  return (count);
162 }
163 
164 /*
165  * fscanf(fp,fmt,va_alist)
166  */
167 int
168 binFscanf(FILE *fp, const char *fmt, ...)
169 {
170  int count;
171  va_list ap;
172 
173  va_start(ap, fmt);
174  count = vfscanf(fp, fmt, ap);
175  va_end(ap);
176  return (count);
177 }
178 
179 /*
180  * sscanf(buf,fmt,va_alist)
181  */
182 int
183 binSscanf(const char *buf, const char *fmt, ...)
184 {
185  int count;
186  va_list ap;
187 
188  va_start(ap, fmt);
189  count = vsscanf(buf, fmt, ap);
190  va_end(ap);
191  return (count);
192 }
193 
194 /*
195  * vfscanf(fp,fmt,ap)
196  */
197 static int
198 binVfscanf(FILE *fp, const char *fmt, va_list ap)
199 {
200  int count;
201  char buf[MAXLN + 1];
202 
203  if (fgets(buf, MAXLN, fp) == 0)
204  return (-1);
205  count = vsscanf(buf, fmt, ap);
206  return (count);
207 }
208 
209 
220 static int
221 binVsscanf(const char *bufOrg, const char *s, va_list ap, int bufLen)
222 {
223  int count, noassign, base, lflag;
224  unsigned long width;
225  const char *tc;
226  char *t, tmp[MAXLN];
227  const char *buf;
228  const char *bufEnd;
229  buf = bufOrg;
230  bufEnd = buf + bufLen;
231 
232  count = noassign = width = lflag = base = 0;
233  // Parse Inputbuffer buf
234  while (*s && (buf < bufEnd))
235  {
236  while (binIsspace(*s)) // skipping blanks
237  s++;
238  if (*s == '%') { // maybe a format identifier
239  s++;
240  for (; *s; s++) {
241  if (strchr("dibouxycsefg%", *s)) // check allowed format identifier
242  break;
243  if (*s == '*') // length identifier
244  noassign = 1;
245  else if (*s == 'l' || *s == 'L') // long flag
246  lflag = 1;
247  else if (*s >= '1' && *s <= '9') { // length of argument
248  for (tc = s; isdigit(*s); s++);
249  strncpy(tmp, tc, s - tc);
250  tmp[s - tc] = '\0';
251  binAtob((unsigned long *)&width, tmp, 10);
252  s--;
253  }
254  }
255  if (*s == 's')
256  {
257  while (binIsspace((int)(0xFF & *buf))) // must be done to handle data >= 0x80
258  {
259  buf++;
260  }
261  if (!width)
262  width = (int)strcspn(buf, ISSPACE);
263  if (!noassign) {
264  strncpy(t = va_arg(ap, char *), buf, width);
265  t[width] = '\0';
266  }
267  buf += width;
268  }
269  else if (*s == 'c') {
270  if (!width)
271  width = 1;
272  if (!noassign) {
273  strncpy(t = va_arg(ap, char *), buf, width);
274  t[width] = '\0';
275  }
276  buf += width;
277  }
278  else if (strchr("dobxyu", *s)) {
279  while (binIsspace((int)(0xFF & *buf))) // must be done to handle data >= 0x80
280  {
281  buf++;
282  }
283  if (*s == 'd' || *s == 'u')
284  base = 10;
285  else if (*s == 'x')
286  base = 16;
287  else if (*s == 'o')
288  base = 8;
289  else if (*s == 'b')
290  base = 2;
291  else if (*s == 'y')
292  base = 1; // use as marker for binary scan
293  if (!width) {
294  if (binIsspace(*(s + 1)) || *(s + 1) == 0)
295  width = (int)strcspn(buf, ISSPACE);
296  else
297  width = (int)(strchr(buf, *(s + 1)) - buf);
298  }
299  if (base == 1) // binary data - plain copy without string function
300  {
301  memcpy(tmp, buf, width);
302  unsigned char *destAdr = va_arg(ap, unsigned char *);
303  unsigned long destVal = 0;
304  for (int i = 0; i < width; i++) // Big Endian - MSB first - convention for SOPAS-Binary
305  {
306  destVal <<= 8;
307  destVal |= (unsigned char)(0xFF & tmp[i]);
308  }
309  for (int i = 0; i < width; i++) // Big Endian - MSB first - convention for SOPAS-Binary
310  {
311  unsigned char val = (unsigned char)(0xFF & (destVal >> (i * 8)));
312  destAdr[i] = val;
313  }
314  }
315  else
316  {
317  strncpy(tmp, buf, width);
318  tmp[width] = '\0';
319  if (!noassign)
320  binAtob(va_arg(ap, unsigned long *), tmp, base);
321  }
322  buf += width;
323  }
324  if (!noassign)
325  count++;
326  width = noassign = lflag = 0;
327  s++;
328  }
329  else {
330  while (binIsspace(*buf))
331  buf++;
332  if (*s != *buf)
333  break;
334  else
335  s++, buf++;
336  }
337  }
338  return (count);
339 }
340 
341 /*
342 * scanf(fmt,va_alist)
343 */
344 int
345 binScanfVec(const std::vector<unsigned char> *vec, const char *fmt, ...)
346 {
347  if (vec->size() == 0)
348  {
349  return(0);
350  }
351  const char *buf = (const char *)(&(*vec)[0]);
352  int count;
353  int bufLen = (int)vec->size();
354  if (0 == bufLen)
355  {
356  return(0);
357  }
358  va_list ap;
359 
360  va_start(ap, fmt);
361  count = binVsscanf(buf, fmt, ap, bufLen);
362  va_end(ap);
363  return (count);
364 }
365 
366 int binScanfGuessDataLenFromMask(const char *scanfMask)
367 {
368  int retLen = 0;
369  int noassign = 0;
370  int lflag = 0;
371  char tmp[20];
372  int width;
373  if (scanfMask == NULL)
374  {
375  }
376  else
377  {
378  const char *s = scanfMask;
379  const char *tc = NULL;
380  while (*s)
381  {
382  while (binIsspace(*s))
383  {
384  s++;
385  retLen++;
386  }
387  if (*s == '%') {
388  s++;
389  for (; *s; s++) {
390  if (strchr("dibouxycsefg%", *s))
391  break;
392  if (*s == '*')
393  noassign = 1;
394  else if (*s == 'l' || *s == 'L')
395  lflag = 1;
396  else if (*s >= '1' && *s <= '9') {
397  for (tc = s; isdigit(*s); s++);
398  strncpy(tmp, tc, s - tc);
399  tmp[s - tc] = '\0';
400  sscanf(tmp,"%d", &width);
401  retLen += width;
402  }
403  }
404  }
405  else
406  {
407  s++;
408  retLen++;
409  }
410  }
411 
412  }
413  return(retLen);
414 }
int binScanfGuessDataLenFromMask(const char *scanfMask)
Definition: binScanf.cpp:366
int binIsspace(int val)
Definition: binScanf.cpp:46
int binSscanf(const char *fmt,...)
Definition: binScanf.cpp:153
int binScanfVec(const std::vector< unsigned char > *vec, const char *fmt,...)
Definition: binScanf.cpp:345
static int _binAtob(unsigned long *vp, char *p, int base)
Definition: binScanf.cpp:79
int binAtob(unsigned long *vp, char *p, int base)
Definition: binScanf.cpp:133
#define ISSPACE
Definition: binScanf.cpp:44
static char * _binGetbase(char *p, int *basep)
Definition: binScanf.cpp:56
int binFscanf(FILE *fp, const char *fmt,...)
Definition: binScanf.cpp:168
static sick_scan::SickScanCommonTcp * s
static int binVfscanf(FILE *fp, const char *fmt, va_list ap)
Definition: binScanf.cpp:198
#define MAXLN
Definition: binScanf.cpp:42
static int binVsscanf(const char *bufOrg, const char *s, va_list ap, int bufLen)
sscanf-like function In addition to standard sscanf a format identifier "y" is introduced to parse bi...
Definition: binScanf.cpp:221


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 04:55:32