summaryrefslogtreecommitdiff
path: root/src/scan.c
blob: 3b65130921013883e71bca766a38159bdde412c5 (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
  @ref    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(const char *s, unsigned int *u)
{
  unsigned int pos = 0;
  unsigned long result = 0;
  long int c;

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

unsigned int scan_8long(const char *s, unsigned long *u)
{
  unsigned int pos = 0;
  unsigned long result = 0;
  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(const char *s, unsigned int *u)
{
  unsigned int pos;
  unsigned long result;

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

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

unsigned int scan_long(const char *s, long *i)
{
  int sign;
  unsigned long u;
  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(const char *s, unsigned long *u)
{
  unsigned int pos = 0;
  unsigned long result = 0;
  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)
{
  const char *t = s;
  int l = 0;
  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)
{
  const char *t = s;
  unsigned int l = 0;
  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);
}