11#include "moar.h"
22#include "ryu/ryu.h"
3+ #include "zmij/zmij.c"
34
45#if defined(_MSC_VER )
56#define strtoll _strtoi64
@@ -224,40 +225,40 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
224225 }
225226 }
226227
227- char buf [64 ];
228- /* What we get back is 0E0, 1E0 , 3.14E0, 1E2 , ... Infinity.
228+ char buf [25 ];
229+ /* What we get back is 0e+00, 1e+00 , 3.14e+00, 1e+02 , ... Infinity.
229230 * What we'd like is the classic "fixed decimal" representation for
230- * small values, and the exponent as a lower case 'e' . So we do some
231+ * small values. So we do some
231232 * massaging, and handle infinity above. We could leave NaN to fall
232233 * through here, but if so it would hit our "something went wrong" code,
233234 * which somewhat downplays the absolute "this path means a bug". So I think
234235 * that it's still clearer handling it above. */
235- const int orig_len = d2s_buffered_n (n , buf );
236236 const char * first = buf ;
237+ const char * end = zmij_dtoa (n , buf );
238+ const int orig_len = end - first ;
237239
238240 /* Take any leading minus away. We put it back at the end. */
239- int len = orig_len ;
241+ int len = end - first ;
240242 if (* first == '-' ) {
241243 ++ first ;
242244 -- len ;
243245 }
244246
245- if (len < 3 || !(first [1 ] == '.' || first [1 ] == 'E ' )) {
247+ if (len < 3 || !(first [1 ] == '.' || first [1 ] == 'e ' )) {
246248 /* Well, this shouldn't be possible. */
247249 }
248250 else {
249- const char * end = first + len ;
250251 const char * E = NULL ;
251- if (end [-2 ] == 'E ' ) {
252+ if (end [-2 ] == 'e ' ) {
252253 E = end - 2 ;
253254 }
254- else if (end [-3 ] == 'E ' ) {
255+ else if (end [-3 ] == 'e ' ) {
255256 E = end - 3 ;
256257 }
257- else if (len >= 4 && end [-4 ] == 'E ' ) {
258+ else if (len >= 4 && end [-4 ] == 'e ' ) {
258259 E = end - 4 ;
259260 }
260- else if (len > 4 && end [-5 ] == 'E ' ) {
261+ else if (len > 4 && end [-5 ] == 'e ' ) {
261262 E = end - 5 ;
262263 }
263264
@@ -270,24 +271,10 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
270271 if (E ) {
271272 MVMGrapheme8 * blob ;
272273 size_t e_len = end - (E + 1 );
273- if (e_len == 2 && E [1 ] == '-' ) {
274- /* 1E-1 etc to 1E-9 etc */
275- if (E [2 ] > '4' ) {
276- /* 1E-5 etc to 1E-9 etc. Need to add a zero. */
277- len = orig_len + 1 ;
278- blob = MVM_malloc (len );
279- /* Using buf here, not first, means that we copy any '-'
280- * too. */
281- size_t new_e = E - buf ;
282- memcpy (blob , buf , new_e );
283- blob [new_e ] = 'e' ;
284- blob [new_e + 1 ] = '-' ;
285- blob [new_e + 2 ] = '0' ;
286- blob [new_e + 3 ] = E [2 ];
287- }
288- else {
274+ /* 1e-01 etc to 1e-04 etc */
275+ if (e_len == 3 && E [1 ] == '-' && E [2 ] == '0' && E [3 ] <= '4' ) {
289276 /* Convert to fixed format, value < 1 */
290- unsigned int zeros = E [2 ] - '0' - 1 ;
277+ unsigned int zeros = E [3 ] - '0' - 1 ;
291278 size_t dec_len ;
292279 if (E == first + 1 ) {
293280 /* No trailing decimals */
@@ -326,75 +313,60 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
326313 memcpy (pos , first + 2 , dec_len );
327314 }
328315 }
329- }
330- else if (e_len == 1 || (e_len == 2 && E [1 ] == '1' && E [2 ] < '5' )) {
331- /* 1E0 etc to 1E14 etc.
332- * Convert to fixed format, possibly needing padding,
333- * possibly with trailing decimals, possibly neither. */
334- unsigned int exp = e_len == 1 ? E [1 ] - '0' : 10 + E [2 ] - '0' ;
335- size_t dec_len ;
336- if (E == first + 1 ) {
337- /* No trailing decimals */
338- dec_len = 0 ;
339- }
340- else {
341- dec_len = E - (first + 2 );
342- }
343- size_t padding = exp > dec_len ? exp - dec_len : 0 ;
344- size_t before_dp = exp > dec_len ? dec_len : exp ;
345- int has_dp = dec_len > exp ;
346-
347- len = 1 + padding + dec_len + has_dp ;
348-
349- MVMGrapheme8 * pos ;
350- if (first == buf ) {
351- blob = MVM_malloc (len );
352- pos = blob ;
353- } else {
354- ++ len ;
355- blob = MVM_malloc (len );
356- pos = blob ;
357- * pos ++ = '-' ;
358- }
316+ /* 1e+00 etc to 1e+14 etc. */
317+ else if (e_len == 3 && (E [2 ] == '0' || (E [2 ] == '1' && E [3 ] < '5' ))) {
318+ /* Convert to fixed format, possibly needing padding,
319+ * possibly with trailing decimals, possibly neither. */
320+ unsigned int exp = (10 * (E [2 ] - '0' )) + (E [3 ] - '0' );
321+ size_t dec_len ;
322+ if (E == first + 1 ) {
323+ /* No trailing decimals */
324+ dec_len = 0 ;
325+ }
326+ else {
327+ dec_len = E - (first + 2 );
328+ }
329+ size_t padding = exp > dec_len ? exp - dec_len : 0 ;
330+ size_t before_dp = exp > dec_len ? dec_len : exp ;
331+ int has_dp = dec_len > exp ;
359332
360- * pos ++ = * first ;
333+ len = 1 + padding + dec_len + has_dp ;
361334
362- if (before_dp ) {
363- memcpy (pos , first + 2 , before_dp );
364- pos += before_dp ;
365- }
335+ MVMGrapheme8 * pos ;
336+ if (first == buf ) {
337+ blob = MVM_malloc (len );
338+ pos = blob ;
339+ } else {
340+ ++ len ;
341+ blob = MVM_malloc (len );
342+ pos = blob ;
343+ * pos ++ = '-' ;
344+ }
366345
367- if (has_dp ) {
368- /* In this case, we never need to pad with zeros. */
369- * pos ++ = '.' ;
370- memcpy (pos , first + 2 + before_dp , dec_len - exp );
371- }
372- else {
373- /* In this case, we might need to pad with zeros. */
374- while (padding ) {
375- * pos ++ = '0' ;
376- -- padding ;
346+ * pos ++ = * first ;
347+
348+ if (before_dp ) {
349+ memcpy (pos , first + 2 , before_dp );
350+ pos += before_dp ;
351+ }
352+
353+ if (has_dp ) {
354+ /* In this case, we never need to pad with zeros. */
355+ * pos ++ = '.' ;
356+ memcpy (pos , first + 2 + before_dp , dec_len - exp );
357+ }
358+ else {
359+ /* In this case, we might need to pad with zeros. */
360+ while (padding ) {
361+ * pos ++ = '0' ;
362+ -- padding ;
363+ }
377364 }
378- }
379- }
380- else if (E [1 ] == '-' ) {
381- /* Stays in scientific notation, but need to change to 'e'. */
382- len = orig_len ;
383- blob = MVM_malloc (len );
384- size_t new_e = E - buf ;
385- memcpy (blob , buf , new_e );
386- blob [new_e ] = 'e' ;
387- memcpy (blob + new_e + 1 , E + 1 , e_len );
388365 } else {
389- /* Stays in scientific notation, but need to change to 'e'
390- * and add a + */
391- len = orig_len + 1 ;
366+ /* Stays in scientific notation. */
367+ len = orig_len ;
392368 blob = MVM_malloc (len );
393- size_t new_e = E - buf ;
394- memcpy (blob , buf , new_e );
395- blob [new_e ] = 'e' ;
396- blob [new_e + 1 ] = '+' ;
397- memcpy (blob + new_e + 2 , E + 1 , e_len );
369+ memcpy (blob , buf , len );
398370 }
399371 return MVM_string_ascii_from_buf_nocheck (tc , blob , len );
400372 }
0 commit comments