summaryrefslogtreecommitdiff
path: root/src/lib/eina
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2019-02-28 13:21:56 +0100
committerStefan Schmidt <s.schmidt@samsung.com>2019-02-28 14:36:42 +0100
commit8a7cb97e02bf0448946d4a2ddd355d394e9d8804 (patch)
treed73e0520391a1546841f09a8aa2f912adcb93ad8 /src/lib/eina
parent5861aad1853a2f6ba929bc4597996ca7782a3631 (diff)
Eina: implement strtod in C locale and remove linkl against msvcr100.
Summary: This fixes compilation on Windows More precisely edje_cc could not compile emotion edc files, so it was a runtime problem because of msvcr100 link. Add more tests than before Test Plan: compilation Reviewers: raster Subscribers: zmike, stefan_schmidt, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7926
Diffstat (limited to 'src/lib/eina')
-rw-r--r--src/lib/eina/eina_convert.c210
-rw-r--r--src/lib/eina/eina_main.c19
2 files changed, 205 insertions, 24 deletions
diff --git a/src/lib/eina/eina_convert.c b/src/lib/eina/eina_convert.c
index 152ef5be4a..bd2d3c2479 100644
--- a/src/lib/eina/eina_convert.c
+++ b/src/lib/eina/eina_convert.c
@@ -14,6 +14,10 @@
14 * You should have received a copy of the GNU Lesser General Public 14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; 15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>. 16 * if not, see <http://www.gnu.org/licenses/>.
17 *
18 * The code of eina_convert_strtod_c() is based on code published
19 * under the public domain license, which can be found here:
20 * https://gist.github.com/mattn/1890186
17 */ 21 */
18 22
19#ifdef HAVE_CONFIG_H 23#ifdef HAVE_CONFIG_H
@@ -24,6 +28,8 @@
24#include <stdlib.h> 28#include <stdlib.h>
25#include <string.h> 29#include <string.h>
26#include <stdio.h> 30#include <stdio.h>
31#include <errno.h>
32#include <ctype.h>
27 33
28#ifdef _WIN32 34#ifdef _WIN32
29# include <Evil.h> 35# include <Evil.h>
@@ -453,14 +459,208 @@ eina_convert_atofp(const char *src, int length, Eina_F32p32 *fp)
453 return EINA_TRUE; 459 return EINA_TRUE;
454} 460}
455 461
462/*
463 * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtod-strtod-l-wcstod-wcstod-l?view=vs-2017
464 *
465 * src should be one of the following form :
466 *
467 * [whitespace] [sign] {digits [radix digits] | radix digits} [{e | E} [sign] digits]
468 * [whitespace] [sign] {INF | INFINITY}
469 * [whitespace] [sign] NAN [sequence]
470 *
471 * No hexadecimal form supported
472 * no sequence supported after NAN
473 */
456EAPI double 474EAPI double
457eina_convert_strtod_c(const char *nptr, char **endptr) 475eina_convert_strtod_c(const char *nptr, char **endptr)
458{ 476{
459#ifdef _WIN32 477 const char *iter;
460 return _strtod_l(nptr, endptr, _eina_c_locale_get()); 478 const char *a;
461#else 479 double val;
462 return strtod_l(nptr, endptr, _eina_c_locale_get()); 480 unsigned long long integer_part;
463#endif 481 int minus;
482
483 EINA_SAFETY_ON_NULL_RETURN_VAL(nptr, 0.0);
484
485 a = iter = nptr;
486
487 /* ignore leading whitespaces */
488 while (isspace(*iter))
489 iter++;
490
491 /* signed or not */
492 minus = 1;
493 if (*iter == '-')
494 {
495 minus = -1;
496 iter++;
497 }
498 else if (*iter == '+')
499 iter++;
500
501 if (tolower(*iter) == 'i')
502 {
503 if ((tolower(*(iter + 1)) == 'n') &&
504 (tolower(*(iter + 2)) == 'f'))
505 iter += 3;
506 else
507 goto on_error;
508 if (tolower(*(iter + 3)) == 'i')
509 {
510 if ((tolower(*(iter + 4)) == 'n') &&
511 (tolower(*(iter + 5)) == 'i') &&
512 (tolower(*(iter + 6)) == 't') &&
513 (tolower(*(iter + 7)) == 'y'))
514 iter += 5;
515 else
516 goto on_error;
517 }
518 if (endptr)
519 *endptr = (char *)iter;
520 return (minus == -1) ? -INFINITY : INFINITY;
521 }
522
523 if (tolower(*iter) == 'n')
524 {
525 if ((tolower(*(iter + 1)) == 'a') &&
526 (tolower(*(iter + 2)) == 'n'))
527 iter += 3;
528 else
529 goto on_error;
530 if (endptr)
531 *endptr = (char *)iter;
532 return (minus == -1) ? -NAN : NAN;
533 }
534
535 integer_part = 0;
536
537 /* (optional) integer part before dot */
538 if (isdigit(*iter))
539 {
540 for (; isdigit(*iter); iter++)
541 integer_part = integer_part * 10ULL + (unsigned long long)(*iter - '0');
542 a = iter;
543 }
544 else if (*iter != '.')
545 {
546 val = 0.0;
547 goto on_success;
548 }
549
550 val = (double)integer_part;
551
552 /* (optional) decimal part after dot */
553 if (*iter == '.')
554 {
555 unsigned long long decimal_part;
556 unsigned long long pow10;
557 int count;
558
559 iter++;
560
561 decimal_part = 0;
562 count = 0;
563 pow10 = 1;
564
565 if (isdigit(*iter))
566 {
567 for (; isdigit(*iter); iter++, count++)
568 {
569 if (count < 19)
570 {
571 decimal_part = decimal_part * 10ULL + + (unsigned long long)(*iter - '0');
572 pow10 *= 10ULL;
573 }
574 }
575 }
576 val += (double)decimal_part / (double)pow10;
577 a = iter;
578 }
579
580 /* (optional) exponent */
581 if ((*iter == 'e') || (*iter == 'E'))
582 {
583 double scale = 1.0;
584 unsigned int expo_part;
585 int minus_e;
586
587 iter++;
588
589 /* signed or not */
590 minus_e = 1;
591 if (*iter == '-')
592 {
593 minus_e = -1;
594 iter++;
595 }
596 else if (*iter == '+')
597 iter++;
598
599 /* exponential part */
600 expo_part = 0;
601 if (isdigit(*iter))
602 {
603 while (*iter == 0)
604 iter++;
605
606 for (; isdigit(*iter); iter++)
607 {
608 expo_part = expo_part * 10U + (unsigned int)(*iter - '0');
609 }
610 }
611 else if (!isdigit(*(a - 1)))
612 {
613 a = nptr;
614 goto on_success;
615 }
616 else if (*iter == 0)
617 goto on_success;
618
619 if ((val == 2.2250738585072011) && ((minus_e * (int)expo_part) == -308))
620 {
621 val *= 1.0e-308;
622 a = iter;
623 errno = ERANGE;
624 goto on_success;
625 }
626
627 if ((val == 2.2250738585072012) && ((minus_e * (int)expo_part) <= -308))
628 {
629 val *= 1.0e-308;
630 a = iter;
631 goto on_success;
632 }
633
634 a = iter;
635
636 while (expo_part >= 8U)
637 {
638 scale *= 1E8;
639 expo_part -= 8U;
640 }
641 while (expo_part > 0U)
642 {
643 scale *= 10.0;
644 expo_part--;
645 }
646
647 val = (minus_e == -1) ? (val / scale) : (val * scale);
648 }
649 else if ((iter > nptr) && !isdigit(*(iter - 1)))
650 {
651 a = nptr;
652 goto on_success;
653 }
654
655 on_success:
656 if (endptr)
657 *endptr = (char *)a;
658 return minus * val;
659
660 on_error:
661 if (endptr)
662 *endptr = (char *)nptr;
663 return 0.0;
464} 664}
465 665
466/** 666/**
diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c
index 535e4e7611..024d1e3eaa 100644
--- a/src/lib/eina/eina_main.c
+++ b/src/lib/eina/eina_main.c
@@ -85,7 +85,6 @@ static int _eina_main_count = 0;
85static int _eina_main_thread_count = 0; 85static int _eina_main_thread_count = 0;
86#endif 86#endif
87static int _eina_log_dom = -1; 87static int _eina_log_dom = -1;
88static locale_t _eina_c_locale;
89 88
90#ifdef ERR 89#ifdef ERR
91#undef ERR 90#undef ERR
@@ -286,12 +285,6 @@ eina_init(void)
286 if (EINA_LIKELY(_eina_main_count > 0)) 285 if (EINA_LIKELY(_eina_main_count > 0))
287 return ++_eina_main_count; 286 return ++_eina_main_count;
288 287
289#ifdef _WIN32
290 _eina_c_locale = _create_locale(LC_ALL, "C");
291#else
292 _eina_c_locale = newlocale(LC_ALL_MASK, "C", NULL);
293#endif
294
295 srand(time(NULL)); 288 srand(time(NULL));
296 while (eina_seed == 0) 289 while (eina_seed == 0)
297 eina_seed = rand(); 290 eina_seed = rand();
@@ -355,12 +348,6 @@ eina_init(void)
355 return 1; 348 return 1;
356} 349}
357 350
358locale_t
359_eina_c_locale_get(void)
360{
361 return _eina_c_locale;
362}
363
364EAPI int 351EAPI int
365eina_shutdown(void) 352eina_shutdown(void)
366{ 353{
@@ -372,12 +359,6 @@ eina_shutdown(void)
372 _eina_main_count--; 359 _eina_main_count--;
373 if (EINA_UNLIKELY(_eina_main_count == 0)) 360 if (EINA_UNLIKELY(_eina_main_count == 0))
374 { 361 {
375#ifdef _WIN32
376 _free_locale(_eina_c_locale);
377#else
378 freelocale(_eina_c_locale);
379#endif
380
381 eina_log_timing(_eina_log_dom, 362 eina_log_timing(_eina_log_dom,
382 EINA_LOG_STATE_START, 363 EINA_LOG_STATE_START,
383 EINA_LOG_STATE_SHUTDOWN); 364 EINA_LOG_STATE_SHUTDOWN);