/* 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 #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 // sscanf, sprintf #include // 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 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 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