binScanf.cpp
Go to the documentation of this file.
00001 /* $Id: scanf.c,v 1.2 2002/08/09 20:56:57 pefo Exp $ */
00002 
00003 /*
00004  * Copyright (c) 2000-2002 Opsycon AB  (www.opsycon.se)
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by Opsycon AB.
00017  * 4. The name of the author may not be used to endorse or promote products
00018  *    derived from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00021  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00024  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00025  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00026  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00027  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00029  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  */
00033 
00034 #define _CRT_SECURE_NO_WARNINGS
00035 #include <stdio.h>
00036 #include <stdarg.h>
00037 #include <string.h>
00038 #include <ctype.h>
00039 #include <vector>
00040 #include "sick_scan/binScanf.hpp"
00041 
00042 #define MAXLN (10 * 1024)
00043 
00044 #define ISSPACE " \t\n\r\f\v"
00045 
00046 int binIsspace(int val)
00047 {
00048         if (val < 0) // characters >= 80
00049         {
00050                 val = (int)(val & 0xFF);
00051         }
00052         int ret = isspace(val);
00053         return(ret);
00054 }
00055 static char *
00056 _binGetbase(char *p, int *basep)
00057 {
00058         if (p[0] == '0') {
00059                 switch (p[1]) {
00060                 case 'x':
00061                         *basep = 16;
00062                         break;
00063                 case 't': case 'n':
00064                         *basep = 10;
00065                         break;
00066                 case 'o':
00067                         *basep = 8;
00068                         break;
00069                 default:
00070                         *basep = 10;
00071                         return (p);
00072                 }
00073                 return (p + 2);
00074         }
00075         *basep = 10;
00076         return (p);
00077 }
00078 static int
00079 _binAtob(unsigned long *vp, char *p, int base)
00080 {
00081         unsigned long value, v1, v2;
00082         char *q, tmp[20];
00083         int digit;
00084 
00085         if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
00086                 base = 16;
00087                 p += 2;
00088         }
00089 
00090         if (base == 16 && (q = strchr(p, '.')) != 0) {
00091                 if (q - p > sizeof(tmp) - 1)
00092                         return (0);
00093 
00094                 strncpy(tmp, p, q - p);
00095                 tmp[q - p] = '\0';
00096                 if (!_binAtob(&v1, tmp, 16))
00097                         return (0);
00098 
00099                 q++;
00100                 if (strchr(q, '.'))
00101                         return (0);
00102 
00103                 if (!_binAtob(&v2, q, 16))
00104                         return (0);
00105                 *vp = (v1 << 16) + v2;
00106                 return (1);
00107         }
00108 
00109         value = *vp = 0;
00110         for (; *p; p++) {
00111                 if (*p >= '0' && *p <= '9')
00112                         digit = *p - '0';
00113                 else if (*p >= 'a' && *p <= 'f')
00114                         digit = *p - 'a' + 10;
00115                 else if (*p >= 'A' && *p <= 'F')
00116                         digit = *p - 'A' + 10;
00117                 else
00118                         return (0);
00119 
00120                 if (digit >= base)
00121                         return (0);
00122                 value *= base;
00123                 value += digit;
00124         }
00125         *vp = value;
00126         return (1);
00127 }
00128 
00129 /*
00130 *  atob(vp,p,base)
00131 *      converts p to binary result in vp, rtn 1 on success
00132 */
00133 int binAtob(unsigned long*vp, char *p, int base)
00134 {
00135 
00136         unsigned long  v;
00137 
00138         if (base == 0)
00139                 p = _binGetbase(p, &base);
00140         if (_binAtob(&v, p, base)) {
00141                 *vp = v;
00142                 return (1);
00143         }
00144         return (0);
00145 }
00146 
00147 
00148 
00149 /*
00150  *  scanf(fmt,va_alist)
00151  */
00152 int
00153 binSscanf(const char *fmt, ...)
00154 {
00155         int            count;
00156         va_list ap;
00157 
00158         va_start(ap, fmt);
00159         count = vfscanf(stdin, fmt, ap);
00160         va_end(ap);
00161         return (count);
00162 }
00163 
00164 /*
00165  *  fscanf(fp,fmt,va_alist)
00166  */
00167 int
00168 binFscanf(FILE *fp, const char *fmt, ...)
00169 {
00170         int             count;
00171         va_list ap;
00172 
00173         va_start(ap, fmt);
00174         count = vfscanf(fp, fmt, ap);
00175         va_end(ap);
00176         return (count);
00177 }
00178 
00179 /*
00180  *  sscanf(buf,fmt,va_alist)
00181  */
00182 int
00183 binSscanf(const char *buf, const char *fmt, ...)
00184 {
00185         int             count;
00186         va_list ap;
00187 
00188         va_start(ap, fmt);
00189         count = vsscanf(buf, fmt, ap);
00190         va_end(ap);
00191         return (count);
00192 }
00193 
00194 /*
00195  *  vfscanf(fp,fmt,ap)
00196  */
00197 static int
00198 binVfscanf(FILE *fp, const char *fmt, va_list ap)
00199 {
00200         int             count;
00201         char            buf[MAXLN + 1];
00202 
00203         if (fgets(buf, MAXLN, fp) == 0)
00204                 return (-1);
00205         count = vsscanf(buf, fmt, ap);
00206         return (count);
00207 }
00208 
00209 
00220 static int
00221 binVsscanf(const char *bufOrg, const char *s, va_list ap, int bufLen)
00222 {
00223         int             count, noassign, base, lflag;
00224         unsigned long   width;
00225   const char     *tc;
00226         char           *t, tmp[MAXLN];
00227         const char *buf;
00228         const char *bufEnd;
00229         buf = bufOrg;
00230         bufEnd = buf + bufLen;
00231 
00232         count = noassign = width = lflag = base = 0;
00233         // Parse Inputbuffer buf
00234         while (*s && (buf < bufEnd))
00235         {
00236                 while (binIsspace(*s)) // skipping blanks
00237                         s++;
00238                 if (*s == '%') { // maybe a format identifier
00239                         s++;
00240                         for (; *s; s++) {
00241                                 if (strchr("dibouxycsefg%", *s)) // check allowed format identifier
00242                                         break;
00243                                 if (*s == '*')  // length identifier
00244                                         noassign = 1;
00245                                 else if (*s == 'l' || *s == 'L') // long flag
00246                                         lflag = 1;
00247                                 else if (*s >= '1' && *s <= '9') {  // length of argument
00248                                         for (tc = s; isdigit(*s); s++);
00249                                         strncpy(tmp, tc, s - tc);
00250                                         tmp[s - tc] = '\0';
00251                                         binAtob((unsigned long *)&width, tmp, 10);
00252                                         s--;
00253                                 }
00254                         }
00255                         if (*s == 's') 
00256                         {
00257                                 while (binIsspace((int)(0xFF & *buf)))   // must be done to handle data >= 0x80
00258                                 {
00259                                         buf++;
00260                                 }
00261                                 if (!width)
00262                                         width = (int)strcspn(buf, ISSPACE);
00263                                 if (!noassign) {
00264                                         strncpy(t = va_arg(ap, char *), buf, width);
00265                                         t[width] = '\0';
00266                                 }
00267                                 buf += width;
00268                         }
00269                         else if (*s == 'c') {
00270                                 if (!width)
00271                                         width = 1;
00272                                 if (!noassign) {
00273                                         strncpy(t = va_arg(ap, char *), buf, width);
00274                                         t[width] = '\0';
00275                                 }
00276                                 buf += width;
00277                         }
00278                         else if (strchr("dobxyu", *s)) {
00279                                 while (binIsspace((int)(0xFF & *buf)))   // must be done to handle data >= 0x80
00280                                 {
00281                                         buf++;
00282                                 }
00283                                 if (*s == 'd' || *s == 'u')
00284                                         base = 10;
00285                                 else if (*s == 'x')
00286                                         base = 16;
00287                                 else if (*s == 'o')
00288                                         base = 8;
00289                                 else if (*s == 'b')
00290                                         base = 2;
00291                                 else if (*s == 'y')
00292                                         base = 1; // use as marker for binary scan
00293                                 if (!width) {
00294                                         if (binIsspace(*(s + 1)) || *(s + 1) == 0)
00295                                                 width = (int)strcspn(buf, ISSPACE);
00296                                         else
00297                                                 width = (int)(strchr(buf, *(s + 1)) - buf);
00298                                 }
00299                                 if (base == 1)  // binary data - plain copy without string function
00300                                 {
00301                                         memcpy(tmp, buf, width);
00302                                         unsigned char *destAdr = va_arg(ap, unsigned char *);
00303                                         unsigned long destVal = 0;
00304                                         for (int i = 0; i < width; i++)  // Big Endian - MSB first - convention for SOPAS-Binary
00305                                         {
00306                                                 destVal <<= 8;
00307                                                 destVal |= (unsigned char)(0xFF & tmp[i]);
00308                                         }
00309           for (int i = 0; i < width; i++)  // Big Endian - MSB first - convention for SOPAS-Binary
00310           {
00311             unsigned char val = (unsigned char)(0xFF & (destVal >> (i * 8)));
00312             destAdr[i] = val;
00313           }
00314                                 }
00315                                 else
00316                                 {
00317                                         strncpy(tmp, buf, width);
00318                                         tmp[width] = '\0';
00319                                         if (!noassign)
00320                                                 binAtob(va_arg(ap, unsigned long *), tmp, base);
00321                                 }
00322                                 buf += width;
00323                         }
00324                         if (!noassign)
00325                                 count++;
00326                         width = noassign = lflag = 0;
00327                         s++;
00328                 }
00329                 else {
00330                         while (binIsspace(*buf))
00331                                 buf++;
00332                         if (*s != *buf)
00333                                 break;
00334                         else
00335                                 s++, buf++;
00336                 }
00337         }
00338         return (count);
00339 }
00340 
00341 /*
00342 *  scanf(fmt,va_alist)
00343 */
00344 int
00345 binScanfVec(const std::vector<unsigned char> *vec, const char *fmt, ...)
00346 {
00347         if (vec->size() == 0)
00348         {
00349                 return(0);
00350         }
00351         const char *buf = (const char *)(&(*vec)[0]);
00352         int             count;
00353         int bufLen = (int)vec->size();
00354         if (0 == bufLen)
00355         {
00356                 return(0);
00357         }
00358         va_list ap;
00359 
00360         va_start(ap, fmt);
00361         count = binVsscanf(buf, fmt, ap, bufLen);
00362         va_end(ap);
00363         return (count);
00364 }
00365 
00366 int binScanfGuessDataLenFromMask(const char *scanfMask)
00367 {
00368         int retLen = 0;
00369         int noassign = 0;
00370         int lflag = 0;
00371         char tmp[20];
00372         int width;
00373         if (scanfMask == NULL)
00374         {
00375         }
00376         else
00377         {
00378                 const char *s = scanfMask;
00379                 const char *tc = NULL;
00380                 while (*s)
00381                 {
00382                         while (binIsspace(*s))
00383                         {
00384                                 s++;
00385                                 retLen++;
00386                         }
00387                         if (*s == '%') {
00388                                 s++;
00389                                 for (; *s; s++) {
00390                                         if (strchr("dibouxycsefg%", *s))
00391                                                 break;
00392                                         if (*s == '*')
00393                                                 noassign = 1;
00394                                         else if (*s == 'l' || *s == 'L')
00395                                                 lflag = 1;
00396                                         else if (*s >= '1' && *s <= '9') {
00397                                                 for (tc = s; isdigit(*s); s++);
00398                                                 strncpy(tmp, tc, s - tc);
00399                                                 tmp[s - tc] = '\0';
00400                                                 sscanf(tmp,"%d", &width);
00401                                                 retLen += width;
00402                                         }
00403                                 }
00404                         }
00405                         else
00406                         {
00407                                 s++;
00408                                 retLen++;
00409                         }
00410                 }
00411 
00412         }
00413         return(retLen);
00414 }


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