summaryrefslogtreecommitdiff
path: root/scan.c
blob: da3d8ade51b5c7c46b3c542bf7e8dd9831a6ef4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "scan.h"

/**
	@file scan.c
	@author djb
	@source qmail, ucspi-tcp
	@brief scanning/conversion of strings to different variable types
*/

static long int fromhex(unsigned char c) 
{
  if (c>='0' && c<='9')
    return c-'0';
  else if (c>='A' && c<='F')
    return c-'A'+10;
  else if (c>='a' && c<='f')
    return c-'a'+10;
  return -1;
}

unsigned int scan_0x(register const char *s,register unsigned int *u)
{
  register unsigned int pos = 0;
  register unsigned long result = 0;
  register long int c;

  while ((c = fromhex((unsigned char) (s[pos]))) >= 0) {
    result = (result << 4) + c;
    ++pos;
  }
  *u = result;
  return pos;
}

unsigned int scan_8long(register const char *s,register unsigned long *u)
{
  register unsigned int pos = 0;
  register unsigned long result = 0;
  register unsigned long c;

  while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 8) {
    result = result * 8 + c;
    ++pos; 
  }
  *u = result;
  return pos;
}

unsigned int scan_uint(register const char *s,register unsigned int *u)
{
  register unsigned int pos; 
  unsigned long result;

  pos = scan_ulong(s,&result);
  *u = result; 
  return pos;
}

unsigned int scan_plusminus(register const char *s,register int *sign)
{
  if (*s == '+') { *sign = 1; return 1; }
  if (*s == '-') { *sign = -1; return 1; }
  *sign = 1; return 0;
}

unsigned int scan_long(register const char *s,register long *i)
{
  int sign; 
  unsigned long u; 
  register unsigned int len;

  len = scan_plusminus(s,&sign); s += len;
  len += scan_ulong(s,&u);
  if (sign < 0) *i = -u; else *i = u;
  return len;
}


unsigned int scan_ulong(register const char *s,register unsigned long *u)
{
  register unsigned int pos = 0;
  register unsigned long result = 0;
  register unsigned long c;

  while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
    result = result * 10 + c;
    ++pos; 
  }
  *u = result;
  return pos;
}

unsigned int scan_xlong(const char *s,unsigned long *u)
{
  register const char *t = s;
  register int l = 0;
  register unsigned char c;

  while ((c = fromhex(*t)) < 16) {
    l = (l<<4)+c;
    ++t;
  }
  *u=l;
  return t-s;
}

unsigned int scan_xint(const char *s,unsigned int *i)
{
  register const char *t = s;
  register unsigned int l = 0;
  register unsigned char c;

  while ((l >> (sizeof(l)*8 - 4)) == 0 
      && (c = (unsigned char)fromhex((unsigned char)*t))<16) {
    l= (l << 4) + c;
    ++t;
  }
  *i = l;
  return (unsigned int)(t-s);
}