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