IOStream.cxx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*============================================================================
  2. KWSys - Kitware System Library
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(Configure.hxx)
  12. // Configure the implementation for the current streams library.
  13. #if !KWSYS_IOS_USE_ANSI
  14. # define ios_base ios
  15. # if defined(__HP_aCC)
  16. # define protected public
  17. # include <iostream.h> // Hack access to some private stream methods.
  18. # undef protected
  19. # endif
  20. #endif
  21. // Include the streams library.
  22. #include KWSYS_HEADER(ios/iostream)
  23. #include KWSYS_HEADER(IOStream.hxx)
  24. // Work-around CMake dependency scanning limitation. This must
  25. // duplicate the above list of headers.
  26. #if 0
  27. # include "Configure.hxx.in"
  28. # include "kwsys_ios_iostream.hxx.in"
  29. # include "IOStream.hxx.in"
  30. #endif
  31. // Implement the rest of this file only if it is needed.
  32. #if KWSYS_IOS_NEED_OPERATORS_LL
  33. # include <stdio.h> // sscanf, sprintf
  34. # include <string.h> // memchr
  35. # if defined(_MAX_INT_DIG)
  36. # define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG
  37. # else
  38. # define KWSYS_IOS_INT64_MAX_DIG 32
  39. # endif
  40. namespace KWSYS_NAMESPACE
  41. {
  42. // Scan an input stream for an integer value.
  43. static int IOStreamScanStream(kwsys_ios::istream& is, char* buffer)
  44. {
  45. // Prepare to write to buffer.
  46. char* out = buffer;
  47. char* end = buffer + KWSYS_IOS_INT64_MAX_DIG - 1;
  48. // Look for leading sign.
  49. if(is.peek() == '+') { *out++ = '+'; is.ignore(); }
  50. else if(is.peek() == '-') { *out++ = '-'; is.ignore(); }
  51. // Determine the base. If not specified in the stream, try to
  52. // detect it from the input. A leading 0x means hex, and a leading
  53. // 0 alone means octal.
  54. int base = 0;
  55. int flags = is.flags() & kwsys_ios::ios_base::basefield;
  56. if(flags == kwsys_ios::ios_base::oct) { base = 8; }
  57. else if(flags == kwsys_ios::ios_base::dec) { base = 10; }
  58. else if(flags == kwsys_ios::ios_base::hex) { base = 16; }
  59. bool foundDigit = false;
  60. bool foundNonZero = false;
  61. if(is.peek() == '0')
  62. {
  63. foundDigit = true;
  64. is.ignore();
  65. if((is.peek() == 'x' || is.peek() == 'X') && (base == 0 || base == 16))
  66. {
  67. base = 16;
  68. foundDigit = false;
  69. is.ignore();
  70. }
  71. else if (base == 0)
  72. {
  73. base = 8;
  74. }
  75. }
  76. // Determine the range of digits allowed for this number.
  77. const char* digits = "0123456789abcdefABCDEF";
  78. int maxDigitIndex = 10;
  79. if(base == 8)
  80. {
  81. maxDigitIndex = 8;
  82. }
  83. else if(base == 16)
  84. {
  85. maxDigitIndex = 10+6+6;
  86. }
  87. // Scan until an invalid digit is found.
  88. for(;is.peek() != EOF; is.ignore())
  89. {
  90. if(memchr(digits, *out = (char)is.peek(), maxDigitIndex) != 0)
  91. {
  92. if((foundNonZero || *out != '0') && out < end)
  93. {
  94. ++out;
  95. foundNonZero = true;
  96. }
  97. foundDigit = true;
  98. }
  99. else
  100. {
  101. break;
  102. }
  103. }
  104. // Correct the buffer contents for degenerate cases.
  105. if(foundDigit && !foundNonZero)
  106. {
  107. *out++ = '0';
  108. }
  109. else if (!foundDigit)
  110. {
  111. out = buffer;
  112. }
  113. // Terminate the string in the buffer.
  114. *out = '\0';
  115. return base;
  116. }
  117. // Read an integer value from an input stream.
  118. template <class T>
  119. kwsys_ios::istream&
  120. IOStreamScanTemplate(kwsys_ios::istream& is, T& value, char type)
  121. {
  122. int state = kwsys_ios::ios_base::goodbit;
  123. // Skip leading whitespace.
  124. # if KWSYS_IOS_USE_ANSI
  125. kwsys_ios::istream::sentry okay(is);
  126. # else
  127. is.eatwhite();
  128. kwsys_ios::istream& okay = is;
  129. # endif
  130. if(okay)
  131. {
  132. # if KWSYS_IOS_USE_ANSI
  133. try {
  134. # endif
  135. // Copy the string to a buffer and construct the format string.
  136. char buffer[KWSYS_IOS_INT64_MAX_DIG];
  137. # if defined(_MSC_VER)
  138. char format[] = "%I64_";
  139. const int typeIndex = 4;
  140. # else
  141. char format[] = "%ll_";
  142. const int typeIndex = 3;
  143. # endif
  144. switch(IOStreamScanStream(is, buffer))
  145. {
  146. case 8: format[typeIndex] = 'o'; break;
  147. case 0: // Default to decimal if not told otherwise.
  148. case 10: format[typeIndex] = type; break;
  149. case 16: format[typeIndex] = 'x'; break;
  150. };
  151. // Use sscanf to parse the number from the buffer.
  152. T result;
  153. int success = (sscanf(buffer, format, &result) == 1)?1:0;
  154. // Set flags for resulting state.
  155. if(is.peek() == EOF) { state |= kwsys_ios::ios_base::eofbit; }
  156. if(!success) { state |= kwsys_ios::ios_base::failbit; }
  157. else { value = result; }
  158. # if KWSYS_IOS_USE_ANSI
  159. } catch(...) { state |= kwsys_ios::ios_base::badbit; }
  160. # endif
  161. }
  162. # if KWSYS_IOS_USE_ANSI
  163. is.setstate(kwsys_ios::ios_base::iostate(state));
  164. # else
  165. is.clear(state);
  166. # endif
  167. return is;
  168. }
  169. // Print an integer value to an output stream.
  170. template <class T>
  171. kwsys_ios::ostream&
  172. IOStreamPrintTemplate(kwsys_ios::ostream& os, T value, char type)
  173. {
  174. # if KWSYS_IOS_USE_ANSI
  175. kwsys_ios::ostream::sentry okay(os);
  176. # else
  177. kwsys_ios::ostream& okay = os;
  178. # endif
  179. if(okay)
  180. {
  181. # if KWSYS_IOS_USE_ANSI
  182. try {
  183. # endif
  184. // Construct the format string.
  185. char format[8];
  186. char* f = format;
  187. *f++ = '%';
  188. if(os.flags() & kwsys_ios::ios_base::showpos) { *f++ = '+'; }
  189. if(os.flags() & kwsys_ios::ios_base::showbase) { *f++ = '#'; }
  190. # if defined(_MSC_VER)
  191. *f++ = 'I'; *f++ = '6'; *f++ = '4';
  192. # else
  193. *f++ = 'l'; *f++ = 'l';
  194. # endif
  195. long bflags = os.flags() & kwsys_ios::ios_base::basefield;
  196. if(bflags == kwsys_ios::ios_base::oct) { *f++ = 'o'; }
  197. else if(bflags != kwsys_ios::ios_base::hex) { *f++ = type; }
  198. else if(os.flags() & kwsys_ios::ios_base::uppercase) { *f++ = 'X'; }
  199. else { *f++ = 'x'; }
  200. *f = '\0';
  201. // Use sprintf to print to a buffer and then write the
  202. // buffer to the stream.
  203. char buffer[2*KWSYS_IOS_INT64_MAX_DIG];
  204. sprintf(buffer, format, value);
  205. os << buffer;
  206. # if KWSYS_IOS_USE_ANSI
  207. } catch(...) { os.clear(os.rdstate() | kwsys_ios::ios_base::badbit); }
  208. # endif
  209. }
  210. return os;
  211. }
  212. # if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
  213. // Implement input stream operator for IOStreamSLL.
  214. kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamSLL& value)
  215. {
  216. return IOStreamScanTemplate(is, value, 'd');
  217. }
  218. // Implement input stream operator for IOStreamULL.
  219. kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamULL& value)
  220. {
  221. return IOStreamScanTemplate(is, value, 'u');
  222. }
  223. # endif
  224. # if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG
  225. // Implement output stream operator for IOStreamSLL.
  226. kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamSLL value)
  227. {
  228. return IOStreamPrintTemplate(os, value, 'd');
  229. }
  230. // Implement output stream operator for IOStreamULL.
  231. kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamULL value)
  232. {
  233. return IOStreamPrintTemplate(os, value, 'u');
  234. }
  235. # endif
  236. } // namespace KWSYS_NAMESPACE
  237. #else
  238. namespace KWSYS_NAMESPACE
  239. {
  240. // Create one public symbol in this object file to avoid warnings from
  241. // archivers.
  242. void IOStreamSymbolToAvoidWarning();
  243. void IOStreamSymbolToAvoidWarning()
  244. {
  245. }
  246. } // namespace KWSYS_NAMESPACE
  247. #endif // KWSYS_IOS_NEED_OPERATORS_LL