1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/io/ustream.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,167 @@ 1.4 +/* 1.5 +********************************************************************** 1.6 +* Copyright (C) 2001-2011, International Business Machines 1.7 +* Corporation and others. All Rights Reserved. 1.8 +********************************************************************** 1.9 +* FILE NAME : ustream.cpp 1.10 +* 1.11 +* Modification History: 1.12 +* 1.13 +* Date Name Description 1.14 +* 06/25/2001 grhoten Move iostream from unistr.h to here 1.15 +****************************************************************************** 1.16 +*/ 1.17 + 1.18 +#include "unicode/utypes.h" 1.19 +#include "unicode/uobject.h" 1.20 +#include "unicode/ustream.h" 1.21 +#include "unicode/ucnv.h" 1.22 +#include "unicode/uchar.h" 1.23 +#include "unicode/utf16.h" 1.24 +#include "ustr_cnv.h" 1.25 +#include "cmemory.h" 1.26 +#include <string.h> 1.27 + 1.28 +// console IO 1.29 + 1.30 +#if U_IOSTREAM_SOURCE >= 199711 1.31 + 1.32 +#define STD_NAMESPACE std:: 1.33 + 1.34 +#define STD_OSTREAM STD_NAMESPACE ostream 1.35 +#define STD_ISTREAM STD_NAMESPACE istream 1.36 + 1.37 +U_NAMESPACE_BEGIN 1.38 + 1.39 +U_IO_API STD_OSTREAM & U_EXPORT2 1.40 +operator<<(STD_OSTREAM& stream, const UnicodeString& str) 1.41 +{ 1.42 + if(str.length() > 0) { 1.43 + char buffer[200]; 1.44 + UConverter *converter; 1.45 + UErrorCode errorCode = U_ZERO_ERROR; 1.46 + 1.47 + // use the default converter to convert chunks of text 1.48 + converter = u_getDefaultConverter(&errorCode); 1.49 + if(U_SUCCESS(errorCode)) { 1.50 + const UChar *us = str.getBuffer(); 1.51 + const UChar *uLimit = us + str.length(); 1.52 + char *s, *sLimit = buffer + (sizeof(buffer) - 1); 1.53 + do { 1.54 + errorCode = U_ZERO_ERROR; 1.55 + s = buffer; 1.56 + ucnv_fromUnicode(converter, &s, sLimit, &us, uLimit, 0, FALSE, &errorCode); 1.57 + *s = 0; 1.58 + 1.59 + // write this chunk 1.60 + if(s > buffer) { 1.61 + stream << buffer; 1.62 + } 1.63 + } while(errorCode == U_BUFFER_OVERFLOW_ERROR); 1.64 + u_releaseDefaultConverter(converter); 1.65 + } 1.66 + } 1.67 + 1.68 +/* stream.flush();*/ 1.69 + return stream; 1.70 +} 1.71 + 1.72 +U_IO_API STD_ISTREAM & U_EXPORT2 1.73 +operator>>(STD_ISTREAM& stream, UnicodeString& str) 1.74 +{ 1.75 + // This is like ICU status checking. 1.76 + if (stream.fail()) { 1.77 + return stream; 1.78 + } 1.79 + 1.80 + /* ipfx should eat whitespace when ios::skipws is set */ 1.81 + UChar uBuffer[16]; 1.82 + char buffer[16]; 1.83 + int32_t idx = 0; 1.84 + UConverter *converter; 1.85 + UErrorCode errorCode = U_ZERO_ERROR; 1.86 + 1.87 + // use the default converter to convert chunks of text 1.88 + converter = u_getDefaultConverter(&errorCode); 1.89 + if(U_SUCCESS(errorCode)) { 1.90 + UChar *us = uBuffer; 1.91 + const UChar *uLimit = uBuffer + sizeof(uBuffer)/sizeof(*uBuffer); 1.92 + const char *s, *sLimit; 1.93 + char ch; 1.94 + UChar ch32; 1.95 + UBool initialWhitespace = TRUE; 1.96 + UBool continueReading = TRUE; 1.97 + 1.98 + /* We need to consume one byte at a time to see what is considered whitespace. */ 1.99 + while (continueReading) { 1.100 + ch = stream.get(); 1.101 + if (stream.eof()) { 1.102 + // The EOF is only set after the get() of an unavailable byte. 1.103 + if (!initialWhitespace) { 1.104 + stream.clear(stream.eofbit); 1.105 + } 1.106 + continueReading = FALSE; 1.107 + } 1.108 + sLimit = &ch + (int)continueReading; 1.109 + us = uBuffer; 1.110 + s = &ch; 1.111 + errorCode = U_ZERO_ERROR; 1.112 + /* 1.113 + Since we aren't guaranteed to see the state before this call, 1.114 + this code won't work on stateful encodings like ISO-2022 or an EBCDIC stateful encoding. 1.115 + We flush on the last byte to ensure that we output truncated multibyte characters. 1.116 + */ 1.117 + ucnv_toUnicode(converter, &us, uLimit, &s, sLimit, 0, !continueReading, &errorCode); 1.118 + if(U_FAILURE(errorCode)) { 1.119 + /* Something really bad happened. setstate() isn't always an available API */ 1.120 + stream.clear(stream.failbit); 1.121 + goto STOP_READING; 1.122 + } 1.123 + /* Was the character consumed? */ 1.124 + if (us != uBuffer) { 1.125 + /* Reminder: ibm-1390 & JISX0213 can output 2 Unicode code points */ 1.126 + int32_t uBuffSize = us-uBuffer; 1.127 + int32_t uBuffIdx = 0; 1.128 + while (uBuffIdx < uBuffSize) { 1.129 + U16_NEXT(uBuffer, uBuffIdx, uBuffSize, ch32); 1.130 + if (u_isWhitespace(ch32)) { 1.131 + if (!initialWhitespace) { 1.132 + buffer[idx++] = ch; 1.133 + while (idx > 0) { 1.134 + stream.putback(buffer[--idx]); 1.135 + } 1.136 + goto STOP_READING; 1.137 + } 1.138 + /* else skip intialWhitespace */ 1.139 + } 1.140 + else { 1.141 + if (initialWhitespace) { 1.142 + /* 1.143 + When initialWhitespace is TRUE, we haven't appended any 1.144 + character yet. This is where we truncate the string, 1.145 + to avoid modifying the string before we know if we can 1.146 + actually read from the stream. 1.147 + */ 1.148 + str.truncate(0); 1.149 + initialWhitespace = FALSE; 1.150 + } 1.151 + str.append(ch32); 1.152 + } 1.153 + } 1.154 + idx = 0; 1.155 + } 1.156 + else { 1.157 + buffer[idx++] = ch; 1.158 + } 1.159 + } 1.160 +STOP_READING: 1.161 + u_releaseDefaultConverter(converter); 1.162 + } 1.163 + 1.164 +/* stream.flush();*/ 1.165 + return stream; 1.166 +} 1.167 + 1.168 +U_NAMESPACE_END 1.169 + 1.170 +#endif