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