diff options
Diffstat (limited to 'intl/icu/source/io/ustream.cpp')
-rw-r--r-- | intl/icu/source/io/ustream.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/intl/icu/source/io/ustream.cpp b/intl/icu/source/io/ustream.cpp new file mode 100644 index 0000000000..fd783b3b23 --- /dev/null +++ b/intl/icu/source/io/ustream.cpp @@ -0,0 +1,170 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (C) 2001-2016, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +* FILE NAME : ustream.cpp +* +* Modification History: +* +* Date Name Description +* 06/25/2001 grhoten Move iostream from unistr.h to here +****************************************************************************** +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_CONVERSION + +#include "unicode/uobject.h" +#include "unicode/ustream.h" +#include "unicode/ucnv.h" +#include "unicode/uchar.h" +#include "unicode/utf16.h" +#include "ustr_cnv.h" +#include "cmemory.h" +#include <string.h> + +// console IO + +#define STD_NAMESPACE std:: + +#define STD_OSTREAM STD_NAMESPACE ostream +#define STD_ISTREAM STD_NAMESPACE istream + +U_NAMESPACE_BEGIN + +U_IO_API STD_OSTREAM & U_EXPORT2 +operator<<(STD_OSTREAM& stream, const UnicodeString& str) +{ + if(str.length() > 0) { + char buffer[200]; + UConverter *converter; + UErrorCode errorCode = U_ZERO_ERROR; + + // use the default converter to convert chunks of text + converter = u_getDefaultConverter(&errorCode); + if(U_SUCCESS(errorCode)) { + const char16_t *us = str.getBuffer(); + const char16_t *uLimit = us + str.length(); + char *s, *sLimit = buffer + (sizeof(buffer) - 1); + do { + errorCode = U_ZERO_ERROR; + s = buffer; + ucnv_fromUnicode(converter, &s, sLimit, &us, uLimit, 0, false, &errorCode); + *s = 0; + + // write this chunk + if(s > buffer) { + stream << buffer; + } + } while(errorCode == U_BUFFER_OVERFLOW_ERROR); + u_releaseDefaultConverter(converter); + } + } + +/* stream.flush();*/ + return stream; +} + +U_IO_API STD_ISTREAM & U_EXPORT2 +operator>>(STD_ISTREAM& stream, UnicodeString& str) +{ + // This is like ICU status checking. + if (stream.fail()) { + return stream; + } + + /* ipfx should eat whitespace when ios::skipws is set */ + char16_t uBuffer[16]; + char buffer[16]; + int32_t idx = 0; + UConverter *converter; + UErrorCode errorCode = U_ZERO_ERROR; + + // use the default converter to convert chunks of text + converter = u_getDefaultConverter(&errorCode); + if(U_SUCCESS(errorCode)) { + char16_t *us = uBuffer; + const char16_t *uLimit = uBuffer + UPRV_LENGTHOF(uBuffer); + const char *s, *sLimit; + char ch; + char16_t ch32; + UBool initialWhitespace = true; + UBool continueReading = true; + + /* We need to consume one byte at a time to see what is considered whitespace. */ + while (continueReading) { + ch = stream.get(); + if (stream.eof()) { + // The EOF is only set after the get() of an unavailable byte. + if (!initialWhitespace) { + stream.clear(stream.eofbit); + } + continueReading = false; + } + sLimit = &ch + (int)continueReading; + us = uBuffer; + s = &ch; + errorCode = U_ZERO_ERROR; + /* + Since we aren't guaranteed to see the state before this call, + this code won't work on stateful encodings like ISO-2022 or an EBCDIC stateful encoding. + We flush on the last byte to ensure that we output truncated multibyte characters. + */ + ucnv_toUnicode(converter, &us, uLimit, &s, sLimit, 0, !continueReading, &errorCode); + if(U_FAILURE(errorCode)) { + /* Something really bad happened. setstate() isn't always an available API */ + stream.clear(stream.failbit); + goto STOP_READING; + } + /* Was the character consumed? */ + if (us != uBuffer) { + /* Reminder: ibm-1390 & JISX0213 can output 2 Unicode code points */ + int32_t uBuffSize = static_cast<int32_t>(us-uBuffer); + int32_t uBuffIdx = 0; + while (uBuffIdx < uBuffSize) { + U16_NEXT(uBuffer, uBuffIdx, uBuffSize, ch32); + if (u_isWhitespace(ch32)) { + if (!initialWhitespace) { + buffer[idx++] = ch; + while (idx > 0) { + stream.putback(buffer[--idx]); + } + goto STOP_READING; + } + /* else skip intialWhitespace */ + } + else { + if (initialWhitespace) { + /* + When initialWhitespace is true, we haven't appended any + character yet. This is where we truncate the string, + to avoid modifying the string before we know if we can + actually read from the stream. + */ + str.truncate(0); + initialWhitespace = false; + } + str.append(ch32); + } + } + idx = 0; + } + else { + buffer[idx++] = ch; + } + } +STOP_READING: + u_releaseDefaultConverter(converter); + } + +/* stream.flush();*/ + return stream; +} + +U_NAMESPACE_END + +#endif |