diff options
author | Brad King <brad.king@kitware.com> | 2006-08-27 17:17:23 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2006-08-27 17:17:23 (GMT) |
commit | c500078dccbc0a82e33eaac1ca1b55ede1332860 (patch) | |
tree | e19ac1300dc5f35cc4a8827af159c8da9fba7f27 /Source | |
parent | 2b602ea738f4ed99b67085f3f035f8eb2f43de88 (diff) | |
download | CMake-c500078dccbc0a82e33eaac1ca1b55ede1332860.zip CMake-c500078dccbc0a82e33eaac1ca1b55ede1332860.tar.gz CMake-c500078dccbc0a82e33eaac1ca1b55ede1332860.tar.bz2 |
ENH: Adding KWSys component IOStream to provide help with broken C++ stream libraries.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/kwsys/CMakeLists.txt | 26 | ||||
-rw-r--r-- | Source/kwsys/IOStream.cxx | 270 | ||||
-rw-r--r-- | Source/kwsys/IOStream.hxx.in | 148 | ||||
-rw-r--r-- | Source/kwsys/kwsysPlatformCxxTests.cxx | 44 |
4 files changed, 486 insertions, 2 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index b4bd93c..921e0d3 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -127,6 +127,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_CommandLineArguments 1) SET(KWSYS_USE_FundamentalType 1) SET(KWSYS_USE_Terminal 1) + SET(KWSYS_USE_IOStream 1) ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) #----------------------------------------------------------------------------- @@ -144,6 +145,7 @@ ENDIF(KWSYS_STANDALONE) # Include helper macros. INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformCxxTests.cmake) +INCLUDE(CheckTypeSize) # Do full dependency headers. INCLUDE_REGULAR_EXPRESSION("^.*$") @@ -393,7 +395,6 @@ ENDIF(UNIX) IF(KWSYS_USE_FundamentalType) # Determine type sizes. - INCLUDE(CheckTypeSize) CHECK_TYPE_SIZE("char" KWSYS_SIZEOF_CHAR) CHECK_TYPE_SIZE("short" KWSYS_SIZEOF_SHORT) CHECK_TYPE_SIZE("int" KWSYS_SIZEOF_INT) @@ -447,6 +448,24 @@ IF(KWSYS_USE_FundamentalType) "Checking whether char is signed" DIRECT) ENDIF(KWSYS_USE_FundamentalType) +IF(KWSYS_USE_IOStream) + # Determine whether iostreams support long long. + CHECK_TYPE_SIZE("long long" KWSYS_SIZEOF_LONG_LONG) + IF(KWSYS_SIZEOF_LONG_LONG) + SET(KWSYS_PLATFORM_CXX_TEST_DEFINES + -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI} + -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD}) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG + "Checking if istream supports long long" DIRECT) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM_LONG_LONG + "Checking if ostream supports long long" DIRECT) + SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) + ELSE(KWSYS_SIZEOF_LONG_LONG) + SET(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0) + SET(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0) + ENDIF(KWSYS_SIZEOF_LONG_LONG) +ENDIF(KWSYS_USE_IOStream) + IF(KWSYS_NAMESPACE MATCHES "^kwsys$") SET(KWSYS_NAME_IS_KWSYS 1) ELSE(KWSYS_NAMESPACE MATCHES "^kwsys$") @@ -560,7 +579,10 @@ IF(KWSYS_USE_Glob) ENDIF(KWSYS_USE_Glob) # Add selected C++ classes. -SET(cppclasses Directory DynamicLoader Glob RegularExpression SystemTools CommandLineArguments Registry) +SET(cppclasses + Directory DynamicLoader Glob RegularExpression SystemTools + CommandLineArguments Registry IOStream + ) FOREACH(cpp ${cppclasses}) IF(KWSYS_USE_${cpp}) SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${cpp}) diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx new file mode 100644 index 0000000..2e1a379 --- /dev/null +++ b/Source/kwsys/IOStream.cxx @@ -0,0 +1,270 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Configure.hxx) + +// Configure the implementation for the current streams library. +#if !KWSYS_IOS_USE_ANSI +# define ios_base ios +# if defined(__HP_aCC) +# define protected public +# include <iostream.h> // Hack access to some private stream methods. +# undef protected +# endif +#endif + +// Include the streams library. +#include KWSYS_HEADER(ios/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 "kwsys_ios_iostream.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(kwsys_ios::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() & kwsys_ios::ios_base::basefield; + if(flags == kwsys_ios::ios_base::oct) { base = 8; } + else if(flags == kwsys_ios::ios_base::dec) { base = 10; } + else if(flags == kwsys_ios::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> +kwsys_ios::istream& +IOStreamScanTemplate(kwsys_ios::istream& is, T& value, char type) +{ + int state = kwsys_ios::ios_base::goodbit; + + // Skip leading whitespace. +# if KWSYS_IOS_USE_ANSI + kwsys_ios::istream::sentry okay(is); +# else + is.eatwhite(); + kwsys_ios::istream& okay = is; +# endif + + if(okay) + { +# if KWSYS_IOS_USE_ANSI + try { +# endif + // 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 |= kwsys_ios::ios_base::eofbit; } + if(!success) { state |= kwsys_ios::ios_base::failbit; } + else { value = result; } +# if KWSYS_IOS_USE_ANSI + } catch(...) { state |= kwsys_ios::ios_base::badbit; } +# endif + } + +# if KWSYS_IOS_USE_ANSI + is.setstate(kwsys_ios::ios_base::iostate(state)); +# else + is.clear(state); +# endif + return is; +} + +// Print an integer value to an output stream. +template <class T> +kwsys_ios::ostream& +IOStreamPrintTemplate(kwsys_ios::ostream& os, T value, char type) +{ +# if KWSYS_IOS_USE_ANSI + kwsys_ios::ostream::sentry okay(os); +# else + kwsys_ios::ostream& okay = os; +# endif + if(okay) + { +# if KWSYS_IOS_USE_ANSI + try { +# endif + // Construct the format string. + char format[8]; + char* f = format; + *f++ = '%'; + if(os.flags() & kwsys_ios::ios_base::showpos) { *f++ = '+'; } + if(os.flags() & kwsys_ios::ios_base::showbase) { *f++ = '#'; } +# if defined(_MSC_VER) + *f++ = 'I'; *f++ = '6'; *f++ = '4'; +# else + *f++ = 'l'; *f++ = 'l'; +# endif + long bflags = os.flags() & kwsys_ios::ios_base::basefield; + if(bflags == kwsys_ios::ios_base::oct) { *f++ = 'o'; } + else if(bflags != kwsys_ios::ios_base::hex) { *f++ = type; } + else if(os.flags() & kwsys_ios::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; +# if KWSYS_IOS_USE_ANSI + } catch(...) { os.clear(os.rdstate() | kwsys_ios::ios_base::badbit); } +# endif + } + return os; +} + +# if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG +// Implement input stream operator for IOStreamSLL. +kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamSLL& value) +{ + return IOStreamScanTemplate(is, value, 'd'); +} + +// Implement input stream operator for IOStreamULL. +kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamULL& value) +{ + return IOStreamScanTemplate(is, value, 'u'); +} +# endif + +# if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG +// Implement output stream operator for IOStreamSLL. +kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamSLL value) +{ + return IOStreamPrintTemplate(os, value, 'd'); +} + +// Implement output stream operator for IOStreamULL. +kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamULL value) +{ + return IOStreamPrintTemplate(os, value, 'u'); +} +# endif + +} // namespace KWSYS_NAMESPACE + +#endif // KWSYS_IOS_NEED_OPERATORS_LL diff --git a/Source/kwsys/IOStream.hxx.in b/Source/kwsys/IOStream.hxx.in new file mode 100644 index 0000000..5b08689 --- /dev/null +++ b/Source/kwsys/IOStream.hxx.in @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_IOStream_hxx +#define @KWSYS_NAMESPACE@_IOStream_hxx + +#include <@KWSYS_NAMESPACE@/ios/iosfwd> + +/* Define these macros temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +# define kwsys_ios @KWSYS_NAMESPACE@_ios +#endif + +/* Whether istream supports long long. */ +#define @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_IOS_HAS_ISTREAM_LONG_LONG@ + +/* Whether ostream supports long long. */ +#define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@ + +/* Size of type long long and 0 if not available. */ +#define @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@ + +/* Determine whether we need to define the streaming operators for + long long or __int64. */ +#if @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG +# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \ + !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG +# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1 + namespace @KWSYS_NAMESPACE@ + { + typedef long long IOStreamSLL; + typedef unsigned long long IOStreamULL; + } +# endif +#elif defined(_MSC_VER) && _MSC_VER < 1300 +# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1 + namespace @KWSYS_NAMESPACE@ + { + typedef __int64 IOStreamSLL; + typedef unsigned __int64 IOStreamULL; + } +#endif +#if !defined(@KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL) +# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 0 +#endif + +#if @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL +# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG + +/* Input stream operator implementation functions. */ +namespace @KWSYS_NAMESPACE@ +{ +kwsysEXPORT kwsys_ios::istream& IOStreamScan(kwsys_ios::istream&, + IOStreamSLL&); +kwsysEXPORT kwsys_ios::istream& IOStreamScan(kwsys_ios::istream&, + IOStreamULL&); +} + +/* Provide input stream operator for long long. */ +# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_LONG_LONG) && \ + !defined(KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED) +# define KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED +# define @KWSYS_NAMESPACE@_IOS_ISTREAM_LONG_LONG_DEFINED +inline kwsys_ios::istream& +operator>>(kwsys_ios::istream& is, @KWSYS_NAMESPACE@::IOStreamSLL& value) +{ + return @KWSYS_NAMESPACE@::IOStreamScan(is, value); +} +# endif + +/* Provide input stream operator for unsigned long long. */ +# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_UNSIGNED_LONG_LONG) && \ + !defined(KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED) +# define KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED +# define @KWSYS_NAMESPACE@_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED +inline kwsys_ios::istream& +operator>>(kwsys_ios::istream& is, @KWSYS_NAMESPACE@::IOStreamULL& value) +{ + return @KWSYS_NAMESPACE@::IOStreamScan(is, value); +} +# endif +# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG */ + +# if !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG + +/* Output stream operator implementation functions. */ +namespace @KWSYS_NAMESPACE@ +{ +kwsysEXPORT kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream&, + IOStreamSLL); +kwsysEXPORT kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream&, + IOStreamULL); +} + +/* Provide output stream operator for long long. */ +# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_LONG_LONG) && \ + !defined(KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED) +# define KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED +# define @KWSYS_NAMESPACE@_IOS_OSTREAM_LONG_LONG_DEFINED +inline kwsys_ios::ostream& +operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamSLL value) +{ + return @KWSYS_NAMESPACE@::IOStreamPrint(os, value); +} +# endif + +/* Provide output stream operator for unsigned long long. */ +# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_UNSIGNED_LONG_LONG) && \ + !defined(KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED) +# define KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED +# define @KWSYS_NAMESPACE@_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED +inline kwsys_ios::ostream& +operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value) +{ + return @KWSYS_NAMESPACE@::IOStreamPrint(os, value); +} +# endif +# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG */ +#endif /* @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL */ + +/* Undefine temporary macros. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsysEXPORT +# undef kwsys_ios +#endif + +/* If building a C++ file in kwsys itself, give the source file + access to the macros without a configured namespace. */ +#if defined(KWSYS_NAMESPACE) +# define KWSYS_IOS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG +# define KWSYS_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG +# define KWSYS_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG +# define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL +#endif + +#endif + diff --git a/Source/kwsys/kwsysPlatformCxxTests.cxx b/Source/kwsys/kwsysPlatformCxxTests.cxx index 989bf1b..ccc46fe 100644 --- a/Source/kwsys/kwsysPlatformCxxTests.cxx +++ b/Source/kwsys/kwsysPlatformCxxTests.cxx @@ -7,6 +7,26 @@ # endif #endif +// Setup for tests that use iostreams. +#if defined(KWSYS_IOS_USE_ANSI) && defined(KWSYS_IOS_HAVE_STD) +# if defined(_MSC_VER) +# pragma warning (push,1) +# endif +# if KWSYS_IOS_USE_ANSI +# include <iostream> +# else +# include <iostream.h> +# endif +# if defined(_MSC_VER) +# pragma warning (pop) +# endif +# if KWSYS_IOS_HAVE_STD +# define kwsys_ios std +# else +# define kwsys_ios +# endif +#endif + #ifdef TEST_KWSYS_STL_HAVE_STD #include <list> void f(std::list<int>*) {} @@ -266,6 +286,30 @@ int main() } #endif +#ifdef TEST_KWSYS_IOS_HAS_ISTREAM_LONG_LONG +int test_istream(kwsys_ios::istream& is, long long& x) +{ + return (is >> x)? 1:0; +} +int main() +{ + long long x = 0; + return test_istream(kwsys_ios::cin, x); +} +#endif + +#ifdef TEST_KWSYS_IOS_HAS_OSTREAM_LONG_LONG +int test_ostream(kwsys_ios::ostream& os, long long x) +{ + return (os << x)? 1:0; +} +int main() +{ + long long x = 0; + return test_ostream(kwsys_ios::cout, x); +} +#endif + #ifdef TEST_KWSYS_CHAR_IS_SIGNED /* Return 0 for char signed and 1 for char unsigned. */ int main() |