php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
conv.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7#include <math.h>
8#include <float.h>
9
10#include "lexbor/core/conv.h"
11#include "lexbor/core/dtoa.h"
12#include "lexbor/core/strtod.h"
13
14
15size_t
17{
18 return lexbor_dtoa(num, buf, len);
19}
20
21size_t
23{
24 return lexbor_conv_int64_to_data((int64_t) num, buf, len);
25}
26
27size_t
29{
30 int64_t tmp;
31 size_t have_minus, i, length;
32
33 static const lxb_char_t *digits = (const lxb_char_t *) "0123456789";
34
35 if (num != 0) {
36 tmp = num;
37 length = 0;
38 have_minus = 0;
39
40 if (num < 0) {
41 length = 1;
42 num = -num;
43 have_minus = 1;
44 }
45
46 while (tmp != 0) {
47 length += 1;
48 tmp /= 10;
49 }
50
51 /* length += (size_t) floor(log10(labs((long) num))) + 1; */
52 }
53 else {
54 if (len > 0) {
55 buf[0] = '0';
56 return 1;
57 }
58
59 return 0;
60 }
61
62 if (len < length) {
63 i = (length + have_minus) - len;
64
65 while (i != have_minus) {
66 i -= 1;
67 num /= 10;
68 }
69
70 length = len;
71 }
72
73 if (have_minus) {
74 buf[0] = '-';
75 }
76
77 i = length;
78 buf[length] = '\0';
79
80 while (i != have_minus) {
81 i -= 1;
82 buf[i] = digits[ num % 10 ];
83 num /= 10;
84 }
85
86 return length;
87}
88
89double
91{
92 int exponent, exp, insignf;
93 lxb_char_t c, *pos;
94 bool minus, ex_minus;
95 double num;
96 const lxb_char_t *e, *p, *last, *end;
97 lxb_char_t data[128];
98
99 end = *start + len;
100
101 exponent = 0;
102 insignf = 0;
103
104 pos = data;
105 last = data + sizeof(data);
106
107 minus = false;
108
109 switch (**start) {
110 case '-':
111 minus = true;
112 /* fall through */
113 case '+':
114 (*start)++;
115 /* fall through */
116 default:
117 break;
118 }
119
120 for (p = *start; p < end; p++) {
121 /* Values less than '0' become >= 208. */
122 c = *p - '0';
123
124 if (c > 9) {
125 break;
126 }
127
128 if (pos < last) {
129 *pos++ = *p;
130 }
131 else {
132 insignf++;
133 }
134 }
135
136 /* Do not emit a '.', but adjust the exponent instead. */
137 if (p < end && *p == '.') {
138
139 for (p++; p < end; p++) {
140 /* Values less than '0' become >= 208. */
141 c = *p - '0';
142
143 if (c > 9) {
144 break;
145 }
146
147 if (pos < last) {
148 *pos++ = *p;
149 exponent--;
150 }
151 else {
152 /* Ignore insignificant digits in the fractional part. */
153 }
154 }
155 }
156
157 e = p + 1;
158
159 if (e < end && (*p == 'e' || *p == 'E')) {
160 ex_minus = 0;
161
162 if (e + 1 < end) {
163 if (*e == '-') {
164 e++;
165 ex_minus = 1;
166 }
167 else if (*e == '+') {
168 e++;
169 }
170 }
171
172 /* Values less than '0' become >= 208. */
173 c = *e - '0';
174
175 if (c <= 9) {
176 exp = c;
177
178 for (p = e + 1; p < end; p++) {
179 /* Values less than '0' become >= 208. */
180 c = *p - '0';
181
182 if (c > 9) {
183 break;
184 }
185
186 exp = exp * 10 + c;
187 }
188
189 exponent += ex_minus ? -exp : exp;
190 }
191 }
192
193 *start = p;
194
195 exponent += insignf;
196
197 num = lexbor_strtod_internal(data, pos - data, exponent);
198
199 if (minus) {
200 num = -num;
201 }
202
203 return num;
204}
205
206unsigned long
208{
209 const lxb_char_t *p = *data;
210 const lxb_char_t *end = p + length;
211 unsigned long last_number = 0, number = 0;
212
213 for (; p < end; p++) {
214 if (*p < '0' || *p > '9') {
215 goto done;
216 }
217
218 number = (*p - '0') + number * 10;
219
220 if (last_number > number) {
221 *data = p - 1;
222 return last_number;
223 }
224
225 last_number = number;
226 }
227
228done:
229
230 *data = p;
231
232 return number;
233}
234
235long
237{
238 bool minus;
239 const lxb_char_t *p;
240 const lxb_char_t *end;
241 unsigned long n = 0, number = 0;
242
243 minus = false;
244 p = *data;
245 end = p + length;
246
247 switch (*p) {
248 case '-':
249 minus = true;
250 /* fall through */
251 case '+':
252 p++;
253 /* fall through */
254 default:
255 break;
256 }
257
258 for (; p < end; p++) {
259 if (*p < '0' || *p > '9') {
260 break;
261 }
262
263 n = (*p - '0') + number * 10;
264
265 if (n > LONG_MAX) {
266 p -= 1;
267 break;
268 }
269
270 number = n;
271 }
272
273 *data = p;
274
275 return (minus) ? -number : number;
276}
277
278unsigned
280{
281 const lxb_char_t *p = *data;
282 const lxb_char_t *end = p + length;
283 unsigned last_number = 0, number = 0;
284
285 for (; p < end; p++) {
286 if (*p < '0' || *p > '9') {
287 goto done;
288 }
289
290 number = (*p - '0') + number * 10;
291
292 if (last_number > number) {
293 *data = p - 1;
294 return last_number;
295 }
296
297 last_number = number;
298 }
299
300done:
301
302 *data = p;
303
304 return number;
305}
306
307size_t
308lexbor_conv_dec_to_hex(uint32_t number, lxb_char_t *out, size_t length)
309{
310 lxb_char_t c;
311 size_t len;
312 uint32_t tmp;
313
314 static const lxb_char_t map_str[] = "0123456789abcdef";
315
316 if(number != 0) {
317 tmp = number;
318 len = 0;
319
320 while (tmp != 0) {
321 len += 1;
322 tmp /= 16;
323 }
324
325 /* len = (size_t) floor(log10(labs((long) number))) + 1; */
326 }
327 else {
328 if (length > 0) {
329 out[0] = '0';
330 return 1;
331 }
332
333 return 0;
334 }
335
336 length = len - 1;
337
338 while (number != 0) {
339 c = number % 16;
340 number = number / 16;
341
342 out[ length-- ] = map_str[c];
343 }
344
345 return len;
346}
size_t len
Definition apprentice.c:174
exp(float $num)
size_t lexbor_conv_int64_to_data(int64_t num, lxb_char_t *buf, size_t len)
Definition conv.c:28
long lexbor_conv_data_to_long(const lxb_char_t **data, size_t length)
Definition conv.c:236
unsigned lexbor_conv_data_to_uint(const lxb_char_t **data, size_t length)
Definition conv.c:279
size_t lexbor_conv_dec_to_hex(uint32_t number, lxb_char_t *out, size_t length)
Definition conv.c:308
size_t lexbor_conv_long_to_data(long num, lxb_char_t *buf, size_t len)
Definition conv.c:22
double lexbor_conv_data_to_double(const lxb_char_t **start, size_t len)
Definition conv.c:90
size_t lexbor_conv_float_to_data(double num, lxb_char_t *buf, size_t len)
Definition conv.c:16
unsigned long lexbor_conv_data_to_ulong(const lxb_char_t **data, size_t length)
Definition conv.c:207
size_t lexbor_dtoa(double value, lxb_char_t *begin, size_t len)
Definition dtoa.c:368
zend_long n
Definition ffi.c:4979
buf start
Definition ffi.c:4687
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
unsigned const char * end
Definition php_ffi.h:51
unsigned const char * pos
Definition php_ffi.h:52
zend_constant * data
p
Definition session.c:1105
double lexbor_strtod_internal(const lxb_char_t *start, size_t length, int exp)
Definition strtod.c:264
unsigned char lxb_char_t
Definition types.h:27
int last
#define LONG_MAX
out($f, $s)