| 650 | }; |
| 651 | |
| 652 | void Input::file_init() |
| 653 | { |
| 654 | // attempt to determine the file size with fstat() |
| 655 | #if !defined(HAVE_CONFIG_H) || defined(HAVE_FSTAT) |
| 656 | #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) |
| 657 | struct _stat st; |
| 658 | if (_fstat(_fileno(file_), &st) == 0 && ((st.st_mode & S_IFMT) == S_IFREG) && st.st_size <= 4294967295LL) |
| 659 | #else |
| 660 | struct stat st; |
| 661 | if (::fstat(::fileno(file_), &st) == 0 && S_ISREG(st.st_mode) && st.st_size <= 4294967295LL) |
| 662 | #endif |
| 663 | size_ = static_cast<size_t>(st.st_size); |
| 664 | #endif |
| 665 | // assume plain (ASCII, binary or UTF-8 without BOM) content by default |
| 666 | utfx_ = file_encoding::plain; |
| 667 | // check first UTF BOM byte using a blocking read |
| 668 | if (file_read(utf8_, 1)) |
| 669 | { |
| 670 | ulen_ = 1; |
| 671 | if (utf8_[0] == '\0' || utf8_[0] == '\xef' || utf8_[0] == '\xfe' || utf8_[0] == '\xff') |
| 672 | { |
| 673 | // check second UTF BOM byte using a blocking read |
| 674 | if (file_read(utf8_ + 1, 1)) |
| 675 | { |
| 676 | ulen_ = 2; |
| 677 | if (utf8_[0] == '\0' && utf8_[1] == '\0') // UTF-32 big endian BOM 0000XXXX? |
| 678 | { |
| 679 | // check third UTF BOM byte using a blocking read |
| 680 | if (file_read(utf8_ + 2, 2)) |
| 681 | { |
| 682 | ulen_ = 4; |
| 683 | if (utf8_[2] == '\xfe' && utf8_[3] == '\xff') // UTF-32 big endian BOM 0000FEFF? |
| 684 | { |
| 685 | size_ = 0; |
| 686 | ulen_ = 0; |
| 687 | utfx_ = file_encoding::utf32be; |
| 688 | } |
| 689 | } |
| 690 | } |
| 691 | else if (utf8_[0] == '\xfe' && utf8_[1] == '\xff') // UTF-16 big endian BOM FEFF? |
| 692 | { |
| 693 | size_ = 0; |
| 694 | ulen_ = 0; |
| 695 | utfx_ = file_encoding::utf16be; |
| 696 | } |
| 697 | else if (utf8_[0] == '\xff' && utf8_[1] == '\xfe') // UTF-16 or UTF-32 little endian BOM FFFEXXXX? |
| 698 | { |
| 699 | // check third UTF BOM byte using a blocking read |
| 700 | if (file_read(utf8_ + 2, 2)) |
| 701 | { |
| 702 | size_ = 0; |
| 703 | if (utf8_[2] == '\0' && utf8_[3] == '\0') // UTF-32 little endian BOM FFFE0000? |
| 704 | { |
| 705 | ulen_ = 0; |
| 706 | utfx_ = file_encoding::utf32le; |
| 707 | } |
| 708 | else |
| 709 | { |