1 |
#include <stdio.h> |
2 |
#include <assert.h> |
3 |
#include <ctype.h> |
4 |
#include <errno.h> |
5 |
#include <string.h> |
6 |
#include <stdlib.h> |
7 |
#include <stdarg.h> |
8 |
|
9 |
#include "memcached.h" |
10 |
|
11 |
bool safe_strtoull(const char *str, uint64_t *out) { |
12 |
assert(out != NULL); |
13 |
errno = 0; |
14 |
*out = 0; |
15 |
char *endptr; |
16 |
unsigned long long ull = strtoull(str, &endptr, 10); |
17 |
if (errno == ERANGE) |
18 |
return false; |
19 |
if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { |
20 |
if ((long long) ull < 0) { |
21 |
/* only check for negative signs in the uncommon case when |
22 |
* the unsigned number is so big that it's negative as a |
23 |
* signed number. */ |
24 |
if (strchr(str, '-') != NULL) { |
25 |
return false; |
26 |
} |
27 |
} |
28 |
*out = ull; |
29 |
return true; |
30 |
} |
31 |
return false; |
32 |
} |
33 |
|
34 |
bool safe_strtoll(const char *str, int64_t *out) { |
35 |
assert(out != NULL); |
36 |
errno = 0; |
37 |
*out = 0; |
38 |
char *endptr; |
39 |
long long ll = strtoll(str, &endptr, 10); |
40 |
if (errno == ERANGE) |
41 |
return false; |
42 |
if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { |
43 |
*out = ll; |
44 |
return true; |
45 |
} |
46 |
return false; |
47 |
} |
48 |
|
49 |
bool safe_strtoul(const char *str, uint32_t *out) { |
50 |
char *endptr = NULL; |
51 |
unsigned long l = 0; |
52 |
assert(out); |
53 |
assert(str); |
54 |
*out = 0; |
55 |
errno = 0; |
56 |
|
57 |
l = strtoul(str, &endptr, 10); |
58 |
if (errno == ERANGE) { |
59 |
return false; |
60 |
} |
61 |
|
62 |
if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { |
63 |
if ((long) l < 0) { |
64 |
/* only check for negative signs in the uncommon case when |
65 |
* the unsigned number is so big that it's negative as a |
66 |
* signed number. */ |
67 |
if (strchr(str, '-') != NULL) { |
68 |
return false; |
69 |
} |
70 |
} |
71 |
*out = l; |
72 |
return true; |
73 |
} |
74 |
|
75 |
return false; |
76 |
} |
77 |
|
78 |
bool safe_strtol(const char *str, int32_t *out) { |
79 |
assert(out != NULL); |
80 |
errno = 0; |
81 |
*out = 0; |
82 |
char *endptr; |
83 |
long l = strtol(str, &endptr, 10); |
84 |
if (errno == ERANGE) |
85 |
return false; |
86 |
if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { |
87 |
*out = l; |
88 |
return true; |
89 |
} |
90 |
return false; |
91 |
} |
92 |
|
93 |
void vperror(const char *fmt, ...) { |
94 |
int old_errno = errno; |
95 |
char buf[1024]; |
96 |
va_list ap; |
97 |
|
98 |
va_start(ap, fmt); |
99 |
if (vsnprintf(buf, sizeof(buf), fmt, ap) == -1) { |
100 |
buf[sizeof(buf) - 1] = '\0'; |
101 |
} |
102 |
va_end(ap); |
103 |
|
104 |
errno = old_errno; |
105 |
|
106 |
perror(buf); |
107 |
} |
108 |
|
109 |
#ifndef HAVE_HTONLL |
110 |
static uint64_t mc_swap64(uint64_t in) { |
111 |
#ifdef ENDIAN_LITTLE |
112 |
/* Little endian, flip the bytes around until someone makes a faster/better |
113 |
* way to do this. */ |
114 |
int64_t rv = 0; |
115 |
int i = 0; |
116 |
for(i = 0; i<8; i++) { |
117 |
rv = (rv << 8) | (in & 0xff); |
118 |
in >>= 8; |
119 |
} |
120 |
return rv; |
121 |
#else |
122 |
/* big-endian machines don't need byte swapping */ |
123 |
return in; |
124 |
#endif |
125 |
} |
126 |
|
127 |
uint64_t ntohll(uint64_t val) { |
128 |
return mc_swap64(val); |
129 |
} |
130 |
|
131 |
uint64_t htonll(uint64_t val) { |
132 |
return mc_swap64(val); |
133 |
} |
134 |
#endif |
135 |
|