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