xscanf.cpp
上传用户:hmc_gdtv
上传日期:2013-08-04
资源大小:798k
文件大小:6k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001,2002,2003 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    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. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: xscanf.cpp,v 1.4.2.1 2003/04/12 22:52:34 mike Exp $
  29.  * 
  30.  */
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include "xscanf.h"
  35. #define MAXARGS   8
  36. static int    Integer(const wchar_t **str,const wchar_t *end,int *val,
  37.       int *argv,int argc)
  38. {
  39.   const wchar_t   *p=*str;
  40.   int   iv=0;
  41.   int   sign=0;
  42.   bool   range=true;
  43.   if (argc>1 && argv[0]>=argv[1])
  44.     range=false;
  45.   if (*p==L'-') {
  46.     ++p;
  47.     sign=1;
  48.   } else if (*p==L'+')
  49.     ++p;
  50.   *str=p;
  51.   while (p<end && iswdigit(*p))
  52.     iv=iv*10+*p++-L'0';
  53.   if (p==*str) {
  54.     if (argc>2 && p<end && *p==L'*') {
  55.       *val=argv[2];
  56.       *str=p+1;
  57.       return 0;
  58.     }
  59.     return -1;
  60.   }
  61.   if (sign)
  62.     iv=-iv;
  63.   if (range && argc>0 && iv<argv[0])
  64.     iv=argv[0];
  65.   if (range && argc>1 && iv>=argv[1])
  66.     iv=argv[1];
  67.   *val=iv;
  68.   *str=p;
  69.   return 0;
  70. }
  71. static int    String(const wchar_t **str,const wchar_t *end,void *dstr,
  72.      bool alloc,int delim,int *argv,int argc)
  73. {
  74.   const wchar_t   *p=*str;
  75.   // find end of string
  76.   if (delim==L' ') {
  77.     while (p<end && !iswspace(*p))
  78.       ++p;
  79.   } else {
  80.     while (p<end && *p!=delim)
  81.       ++p;
  82.   }
  83.   int     length=p-*str;
  84.   wchar_t   *dest=(wchar_t*)dstr;
  85.   // allocate storage if needed
  86.   if (alloc) {
  87.     dest=new wchar_t[length+1];
  88.     *(wchar_t**)dstr=dest;
  89.   }
  90.   // copy chars
  91.   memcpy(dest,*str,length*sizeof(wchar_t));
  92.   dest[length]=L'';
  93.   *str+=length;
  94.   return 0;
  95. }
  96. int Scan::vxscanf(const wchar_t *str,int len,const wchar_t *format,
  97. int *chars,int *fields,va_list args)
  98. {
  99.   const wchar_t   *startstr=str;
  100.   const wchar_t   *endstr=str+len;
  101.   int   fieldnum=0;
  102.   int   error=0;
  103.   int   fmt_args[MAXARGS];
  104.   int   num_fmt_args,cur_fmt_arg,seen_arg_char,arg_sign;
  105.   wchar_t   fmt_char;
  106.   while (*format && str<endstr)
  107.     switch (*format) {
  108.     case L' ': // skip 0..inf whitespace chars
  109.       while (str < endstr && iswspace(*str))
  110. ++str;
  111.       ++format;
  112.       break;
  113.     case L'%': // format spec
  114.       // extract args from format(!), can be negative
  115.       ++format;
  116.       num_fmt_args=seen_arg_char=arg_sign=cur_fmt_arg=0;
  117.       while (*format)
  118. switch (*format) {
  119. case L'+':
  120.   ++format;
  121.   break;
  122. case L'-':
  123.   ++format;
  124.   arg_sign=1;
  125.   break;
  126. case L',': // end of arg
  127.   if (seen_arg_char && num_fmt_args<MAXARGS)
  128.       fmt_args[num_fmt_args++]=arg_sign ? -cur_fmt_arg : cur_fmt_arg;
  129.   seen_arg_char=arg_sign=cur_fmt_arg=0;
  130.   ++format;
  131.   break;
  132. case L'0': case L'1': case L'2': case L'3': case L'4':
  133. case L'5': case L'6': case L'7': case L'8': case L'9':
  134.   cur_fmt_arg=cur_fmt_arg*10+*format++-L'0';
  135.   seen_arg_char=1;
  136.   break;
  137. default: // end of format spec
  138.   if (seen_arg_char && num_fmt_args<MAXARGS)
  139.       fmt_args[num_fmt_args++]=arg_sign ? -cur_fmt_arg : cur_fmt_arg;
  140.   fmt_char=*format++;
  141.   goto done_fmt;
  142. }
  143.       return -1; // invalid format string
  144. done_fmt:
  145.       // handle format specs now
  146.       switch (fmt_char) {
  147.       case L's': // whitespace delimited string
  148. if (String(&str,endstr,va_arg(args,wchar_t*),false,L' ',fmt_args,num_fmt_args)<0)
  149.   goto format_error;
  150. ++fieldnum;
  151. break;
  152.       case L'S': // whitespace delimited string, allocate storage
  153. if (String(&str,endstr,va_arg(args,wchar_t**),true,L' ',fmt_args,num_fmt_args)<0)
  154.   goto format_error;
  155. ++fieldnum;
  156. break;
  157.       case L'd': // (signed) integer
  158. if (Integer(&str,endstr,va_arg(args,int*),fmt_args,num_fmt_args)<0)
  159.   goto format_error;
  160. ++fieldnum;
  161. break;
  162.       case L'c': // a single character
  163. *va_arg(args,wchar_t*)=*str++;
  164. ++fieldnum;
  165. break;
  166.       case L't': // a delimited string
  167. if (String(&str,endstr,va_arg(args,wchar_t*),false,*format,fmt_args,num_fmt_args)<0)
  168.   goto format_error;
  169. ++fieldnum;
  170. break;
  171.       case L'T': // the same, but allocate storage
  172. if (String(&str,endstr,va_arg(args,wchar_t**),true,*format,fmt_args,num_fmt_args)<0)
  173.   goto format_error;
  174. ++fieldnum;
  175. break;
  176.       default: // invalid format char
  177. return -1;
  178.       }
  179.       break;
  180.     default: // match the character as is
  181.       if (*format!=*str) {
  182. error=NOMATCH;
  183. goto out;
  184.       }
  185.       ++str;
  186.       ++format;
  187.       break;
  188.     }
  189. out:
  190.   if (chars)
  191.     *chars=str-startstr;
  192.   if (fields)
  193.     *fields=fieldnum;
  194.   return error;
  195. format_error:
  196.   error=FORMAT;
  197.   goto out;
  198. }
  199. int Scan::xscanf(const wchar_t *str,int len,const wchar_t *format,
  200.        int *chars,int *fields,...)
  201. {
  202.   va_list   ap;
  203.   va_start(ap,fields);
  204.   int ret=vxscanf(str,len,format,chars,fields,ap);
  205.   va_end(ap);
  206.   return ret;
  207. }