| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ |
| #include "kwsysPrivate.h" |
| #include KWSYS_HEADER(Configure.hxx) |
| |
| // Include the streams library. |
| #include <iostream> |
| #include KWSYS_HEADER(IOStream.hxx) |
| |
| // Work-around CMake dependency scanning limitation. This must |
| // duplicate the above list of headers. |
| #if 0 |
| #include "Configure.hxx.in" |
| #include "IOStream.hxx.in" |
| #endif |
| |
| // Implement the rest of this file only if it is needed. |
| #if KWSYS_IOS_NEED_OPERATORS_LL |
| |
| #include <stdio.h> // sscanf, sprintf |
| #include <string.h> // memchr |
| |
| #if defined(_MAX_INT_DIG) |
| #define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG |
| #else |
| #define KWSYS_IOS_INT64_MAX_DIG 32 |
| #endif |
| |
| namespace KWSYS_NAMESPACE { |
| |
| // Scan an input stream for an integer value. |
| static int IOStreamScanStream(std::istream& is, char* buffer) |
| { |
| // Prepare to write to buffer. |
| char* out = buffer; |
| char* end = buffer + KWSYS_IOS_INT64_MAX_DIG - 1; |
| |
| // Look for leading sign. |
| if (is.peek() == '+') { |
| *out++ = '+'; |
| is.ignore(); |
| } else if (is.peek() == '-') { |
| *out++ = '-'; |
| is.ignore(); |
| } |
| |
| // Determine the base. If not specified in the stream, try to |
| // detect it from the input. A leading 0x means hex, and a leading |
| // 0 alone means octal. |
| int base = 0; |
| int flags = is.flags() & std::ios_base::basefield; |
| if (flags == std::ios_base::oct) { |
| base = 8; |
| } else if (flags == std::ios_base::dec) { |
| base = 10; |
| } else if (flags == std::ios_base::hex) { |
| base = 16; |
| } |
| bool foundDigit = false; |
| bool foundNonZero = false; |
| if (is.peek() == '0') { |
| foundDigit = true; |
| is.ignore(); |
| if ((is.peek() == 'x' || is.peek() == 'X') && (base == 0 || base == 16)) { |
| base = 16; |
| foundDigit = false; |
| is.ignore(); |
| } else if (base == 0) { |
| base = 8; |
| } |
| } |
| |
| // Determine the range of digits allowed for this number. |
| const char* digits = "0123456789abcdefABCDEF"; |
| int maxDigitIndex = 10; |
| if (base == 8) { |
| maxDigitIndex = 8; |
| } else if (base == 16) { |
| maxDigitIndex = 10 + 6 + 6; |
| } |
| |
| // Scan until an invalid digit is found. |
| for (; is.peek() != EOF; is.ignore()) { |
| if (memchr(digits, *out = (char)is.peek(), maxDigitIndex) != 0) { |
| if ((foundNonZero || *out != '0') && out < end) { |
| ++out; |
| foundNonZero = true; |
| } |
| foundDigit = true; |
| } else { |
| break; |
| } |
| } |
| |
| // Correct the buffer contents for degenerate cases. |
| if (foundDigit && !foundNonZero) { |
| *out++ = '0'; |
| } else if (!foundDigit) { |
| out = buffer; |
| } |
| |
| // Terminate the string in the buffer. |
| *out = '\0'; |
| |
| return base; |
| } |
| |
| // Read an integer value from an input stream. |
| template <class T> |
| std::istream& IOStreamScanTemplate(std::istream& is, T& value, char type) |
| { |
| int state = std::ios_base::goodbit; |
| |
| // Skip leading whitespace. |
| std::istream::sentry okay(is); |
| |
| if (okay) { |
| try { |
| // Copy the string to a buffer and construct the format string. |
| char buffer[KWSYS_IOS_INT64_MAX_DIG]; |
| #if defined(_MSC_VER) |
| char format[] = "%I64_"; |
| const int typeIndex = 4; |
| #else |
| char format[] = "%ll_"; |
| const int typeIndex = 3; |
| #endif |
| switch (IOStreamScanStream(is, buffer)) { |
| case 8: |
| format[typeIndex] = 'o'; |
| break; |
| case 0: // Default to decimal if not told otherwise. |
| case 10: |
| format[typeIndex] = type; |
| break; |
| case 16: |
| format[typeIndex] = 'x'; |
| break; |
| }; |
| |
| // Use sscanf to parse the number from the buffer. |
| T result; |
| int success = (sscanf(buffer, format, &result) == 1) ? 1 : 0; |
| |
| // Set flags for resulting state. |
| if (is.peek() == EOF) { |
| state |= std::ios_base::eofbit; |
| } |
| if (!success) { |
| state |= std::ios_base::failbit; |
| } else { |
| value = result; |
| } |
| } catch (...) { |
| state |= std::ios_base::badbit; |
| } |
| } |
| |
| is.setstate(std::ios_base::iostate(state)); |
| return is; |
| } |
| |
| // Print an integer value to an output stream. |
| template <class T> |
| std::ostream& IOStreamPrintTemplate(std::ostream& os, T value, char type) |
| { |
| std::ostream::sentry okay(os); |
| if (okay) { |
| try { |
| // Construct the format string. |
| char format[8]; |
| char* f = format; |
| *f++ = '%'; |
| if (os.flags() & std::ios_base::showpos) { |
| *f++ = '+'; |
| } |
| if (os.flags() & std::ios_base::showbase) { |
| *f++ = '#'; |
| } |
| #if defined(_MSC_VER) |
| *f++ = 'I'; |
| *f++ = '6'; |
| *f++ = '4'; |
| #else |
| *f++ = 'l'; |
| *f++ = 'l'; |
| #endif |
| long bflags = os.flags() & std::ios_base::basefield; |
| if (bflags == std::ios_base::oct) { |
| *f++ = 'o'; |
| } else if (bflags != std::ios_base::hex) { |
| *f++ = type; |
| } else if (os.flags() & std::ios_base::uppercase) { |
| *f++ = 'X'; |
| } else { |
| *f++ = 'x'; |
| } |
| *f = '\0'; |
| |
| // Use sprintf to print to a buffer and then write the |
| // buffer to the stream. |
| char buffer[2 * KWSYS_IOS_INT64_MAX_DIG]; |
| sprintf(buffer, format, value); |
| os << buffer; |
| } catch (...) { |
| os.clear(os.rdstate() | std::ios_base::badbit); |
| } |
| } |
| return os; |
| } |
| |
| #if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG |
| // Implement input stream operator for IOStreamSLL. |
| std::istream& IOStreamScan(std::istream& is, IOStreamSLL& value) |
| { |
| return IOStreamScanTemplate(is, value, 'd'); |
| } |
| |
| // Implement input stream operator for IOStreamULL. |
| std::istream& IOStreamScan(std::istream& is, IOStreamULL& value) |
| { |
| return IOStreamScanTemplate(is, value, 'u'); |
| } |
| #endif |
| |
| #if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG |
| // Implement output stream operator for IOStreamSLL. |
| std::ostream& IOStreamPrint(std::ostream& os, IOStreamSLL value) |
| { |
| return IOStreamPrintTemplate(os, value, 'd'); |
| } |
| |
| // Implement output stream operator for IOStreamULL. |
| std::ostream& IOStreamPrint(std::ostream& os, IOStreamULL value) |
| { |
| return IOStreamPrintTemplate(os, value, 'u'); |
| } |
| #endif |
| |
| } // namespace KWSYS_NAMESPACE |
| |
| #else |
| |
| namespace KWSYS_NAMESPACE { |
| |
| // Create one public symbol in this object file to avoid warnings from |
| // archivers. |
| void IOStreamSymbolToAvoidWarning(); |
| void IOStreamSymbolToAvoidWarning() |
| { |
| } |
| |
| } // namespace KWSYS_NAMESPACE |
| |
| #endif // KWSYS_IOS_NEED_OPERATORS_LL |