# Changeset View

Changeset View

# Standalone View

Standalone View

# src/lib/eina/eina_convert.c

1 | /* EINA - EFL data type library | 1 | /* EINA - EFL data type library | ||
---|---|---|---|---|---|

2 | * Copyright (C) 2008 Cedric BAIL, Vincent Torri | 2 | * Copyright (C) 2008 Cedric BAIL, Vincent Torri | ||

3 | * | 3 | * | ||

4 | * This library is free software; you can redistribute it and/or | 4 | * This library is free software; you can redistribute it and/or | ||

5 | * modify it under the terms of the GNU Lesser General Public | 5 | * modify it under the terms of the GNU Lesser General Public | ||

6 | * License as published by the Free Software Foundation; either | 6 | * License as published by the Free Software Foundation; either | ||

7 | * version 2.1 of the License, or (at your option) any later version. | 7 | * version 2.1 of the License, or (at your option) any later version. | ||

8 | * | 8 | * | ||

9 | * This library is distributed in the hope that it will be useful, | 9 | * This library is distributed in the hope that it will be useful, | ||

10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||

11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||

12 | * Lesser General Public License for more details. | 12 | * Lesser General Public License for more details. | ||

13 | * | 13 | * | ||

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 | ||

20 | # include "config.h" | 24 | # include "config.h" | ||

21 | #endif | 25 | #endif | ||

22 | 26 | | |||

23 | #include <math.h> | 27 | #include <math.h> | ||

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> | ||

30 | #endif | 36 | #endif | ||

31 | 37 | | |||

32 | #include "eina_config.h" | 38 | #include "eina_config.h" | ||

33 | #include "eina_private.h" | 39 | #include "eina_private.h" | ||

34 | #include "eina_log.h" | 40 | #include "eina_log.h" | ||

▲ Show 20 Lines • Show All 413 Lines • ▼ Show 20 Line(s) | 442 | { | |||

448 | if (e > 0) | 454 | if (e > 0) | ||

449 | *fp = m << e; | 455 | *fp = m << e; | ||

450 | else | 456 | else | ||

451 | *fp = m >> -e; | 457 | *fp = m >> -e; | ||

452 | 458 | | |||

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 | ||||

raster: any reason to not just use tolower() ? | |||||

Not Done Replyi test only what i want. I can use tolower if you want, not a problem for me. vtorri: i test only what i want. I can use tolower if you want, not a problem for me. | |||||

Not Done ReplyI'd prefer to see zmike: I'd prefer to see `tolower` (or at least `eina_str_tolower`) here unless there's a functional… | |||||

Done Replyok, i'll use tolower() vtorri: ok, i'll use tolower() | |||||

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 | */ | ||||

456 | EAPI double | 474 | EAPI double | ||

457 | eina_convert_strtod_c(const char *nptr, char **endptr) | 475 | eina_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 | /** | ||

467 | * @} | 667 | * @} | ||

468 | */ | 668 | */ |

any reason to not just use tolower() ?