summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/IOStream.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/kwsys/IOStream.cxx')
-rw-r--r--Source/kwsys/IOStream.cxx255
1 files changed, 255 insertions, 0 deletions
diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx
new file mode 100644
index 0000000..e21f87d
--- /dev/null
+++ b/Source/kwsys/IOStream.cxx
@@ -0,0 +1,255 @@
+/* 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