summaryrefslogtreecommitdiff
path: root/src/scan.c
blob: 4d6b918ea56023112c3198cb4bedeff85641d45c (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
121
122
123
124
125
126
127
128
129
130
#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);
}