|  | /*============================================================================ | 
|  | KWSys - Kitware System Library | 
|  | Copyright 2000-2009 Kitware, Inc., Insight Software Consortium | 
|  |  | 
|  | Distributed under the OSI-approved BSD License (the "License"); | 
|  | see accompanying file Copyright.txt for details. | 
|  |  | 
|  | This software is distributed WITHOUT ANY WARRANTY; without even the | 
|  | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | See the License for more information. | 
|  | ============================================================================*/ | 
|  | #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 |