Newer
Older
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Brad King
committed
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
Brad King
committed
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.
============================================================================*/
Brad King
committed
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Configure.hxx)
// Include the streams library.
#include <iostream>
Brad King
committed
#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)
Brad King
committed
{
// 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; }
Brad King
committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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)
Brad King
committed
{
int state = std::ios_base::goodbit;
Brad King
committed
// Skip leading whitespace.
std::istream::sentry okay(is);
Brad King
committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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; }
Brad King
committed
else { value = result; }
} catch(...) { state |= std::ios_base::badbit; }
Brad King
committed
}
is.setstate(std::ios_base::iostate(state));
Brad King
committed
return is;
}
// Print an integer value to an output stream.
template <class T>
std::ostream&
IOStreamPrintTemplate(std::ostream& os, T value, char type)
Brad King
committed
{
std::ostream::sentry okay(os);
Brad King
committed
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++ = '#'; }
Brad King
committed
# 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'; }
Brad King
committed
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); }
Brad King
committed
}
return os;
}
# if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
// Implement input stream operator for IOStreamSLL.
std::istream& IOStreamScan(std::istream& is, IOStreamSLL& value)
Brad King
committed
{
return IOStreamScanTemplate(is, value, 'd');
}
// Implement input stream operator for IOStreamULL.
std::istream& IOStreamScan(std::istream& is, IOStreamULL& value)
Brad King
committed
{
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)
Brad King
committed
{
return IOStreamPrintTemplate(os, value, 'd');
}
// Implement output stream operator for IOStreamULL.
std::ostream& IOStreamPrint(std::ostream& os, IOStreamULL value)
Brad King
committed
{
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()
{
}
} // namespace KWSYS_NAMESPACE
Brad King
committed
#endif // KWSYS_IOS_NEED_OPERATORS_LL