intl/icu/source/io/ustream.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 **********************************************************************
michael@0 3 * Copyright (C) 2001-2011, International Business Machines
michael@0 4 * Corporation and others. All Rights Reserved.
michael@0 5 **********************************************************************
michael@0 6 * FILE NAME : ustream.cpp
michael@0 7 *
michael@0 8 * Modification History:
michael@0 9 *
michael@0 10 * Date Name Description
michael@0 11 * 06/25/2001 grhoten Move iostream from unistr.h to here
michael@0 12 ******************************************************************************
michael@0 13 */
michael@0 14
michael@0 15 #include "unicode/utypes.h"
michael@0 16 #include "unicode/uobject.h"
michael@0 17 #include "unicode/ustream.h"
michael@0 18 #include "unicode/ucnv.h"
michael@0 19 #include "unicode/uchar.h"
michael@0 20 #include "unicode/utf16.h"
michael@0 21 #include "ustr_cnv.h"
michael@0 22 #include "cmemory.h"
michael@0 23 #include <string.h>
michael@0 24
michael@0 25 // console IO
michael@0 26
michael@0 27 #if U_IOSTREAM_SOURCE >= 199711
michael@0 28
michael@0 29 #define STD_NAMESPACE std::
michael@0 30
michael@0 31 #define STD_OSTREAM STD_NAMESPACE ostream
michael@0 32 #define STD_ISTREAM STD_NAMESPACE istream
michael@0 33
michael@0 34 U_NAMESPACE_BEGIN
michael@0 35
michael@0 36 U_IO_API STD_OSTREAM & U_EXPORT2
michael@0 37 operator<<(STD_OSTREAM& stream, const UnicodeString& str)
michael@0 38 {
michael@0 39 if(str.length() > 0) {
michael@0 40 char buffer[200];
michael@0 41 UConverter *converter;
michael@0 42 UErrorCode errorCode = U_ZERO_ERROR;
michael@0 43
michael@0 44 // use the default converter to convert chunks of text
michael@0 45 converter = u_getDefaultConverter(&errorCode);
michael@0 46 if(U_SUCCESS(errorCode)) {
michael@0 47 const UChar *us = str.getBuffer();
michael@0 48 const UChar *uLimit = us + str.length();
michael@0 49 char *s, *sLimit = buffer + (sizeof(buffer) - 1);
michael@0 50 do {
michael@0 51 errorCode = U_ZERO_ERROR;
michael@0 52 s = buffer;
michael@0 53 ucnv_fromUnicode(converter, &s, sLimit, &us, uLimit, 0, FALSE, &errorCode);
michael@0 54 *s = 0;
michael@0 55
michael@0 56 // write this chunk
michael@0 57 if(s > buffer) {
michael@0 58 stream << buffer;
michael@0 59 }
michael@0 60 } while(errorCode == U_BUFFER_OVERFLOW_ERROR);
michael@0 61 u_releaseDefaultConverter(converter);
michael@0 62 }
michael@0 63 }
michael@0 64
michael@0 65 /* stream.flush();*/
michael@0 66 return stream;
michael@0 67 }
michael@0 68
michael@0 69 U_IO_API STD_ISTREAM & U_EXPORT2
michael@0 70 operator>>(STD_ISTREAM& stream, UnicodeString& str)
michael@0 71 {
michael@0 72 // This is like ICU status checking.
michael@0 73 if (stream.fail()) {
michael@0 74 return stream;
michael@0 75 }
michael@0 76
michael@0 77 /* ipfx should eat whitespace when ios::skipws is set */
michael@0 78 UChar uBuffer[16];
michael@0 79 char buffer[16];
michael@0 80 int32_t idx = 0;
michael@0 81 UConverter *converter;
michael@0 82 UErrorCode errorCode = U_ZERO_ERROR;
michael@0 83
michael@0 84 // use the default converter to convert chunks of text
michael@0 85 converter = u_getDefaultConverter(&errorCode);
michael@0 86 if(U_SUCCESS(errorCode)) {
michael@0 87 UChar *us = uBuffer;
michael@0 88 const UChar *uLimit = uBuffer + sizeof(uBuffer)/sizeof(*uBuffer);
michael@0 89 const char *s, *sLimit;
michael@0 90 char ch;
michael@0 91 UChar ch32;
michael@0 92 UBool initialWhitespace = TRUE;
michael@0 93 UBool continueReading = TRUE;
michael@0 94
michael@0 95 /* We need to consume one byte at a time to see what is considered whitespace. */
michael@0 96 while (continueReading) {
michael@0 97 ch = stream.get();
michael@0 98 if (stream.eof()) {
michael@0 99 // The EOF is only set after the get() of an unavailable byte.
michael@0 100 if (!initialWhitespace) {
michael@0 101 stream.clear(stream.eofbit);
michael@0 102 }
michael@0 103 continueReading = FALSE;
michael@0 104 }
michael@0 105 sLimit = &ch + (int)continueReading;
michael@0 106 us = uBuffer;
michael@0 107 s = &ch;
michael@0 108 errorCode = U_ZERO_ERROR;
michael@0 109 /*
michael@0 110 Since we aren't guaranteed to see the state before this call,
michael@0 111 this code won't work on stateful encodings like ISO-2022 or an EBCDIC stateful encoding.
michael@0 112 We flush on the last byte to ensure that we output truncated multibyte characters.
michael@0 113 */
michael@0 114 ucnv_toUnicode(converter, &us, uLimit, &s, sLimit, 0, !continueReading, &errorCode);
michael@0 115 if(U_FAILURE(errorCode)) {
michael@0 116 /* Something really bad happened. setstate() isn't always an available API */
michael@0 117 stream.clear(stream.failbit);
michael@0 118 goto STOP_READING;
michael@0 119 }
michael@0 120 /* Was the character consumed? */
michael@0 121 if (us != uBuffer) {
michael@0 122 /* Reminder: ibm-1390 & JISX0213 can output 2 Unicode code points */
michael@0 123 int32_t uBuffSize = us-uBuffer;
michael@0 124 int32_t uBuffIdx = 0;
michael@0 125 while (uBuffIdx < uBuffSize) {
michael@0 126 U16_NEXT(uBuffer, uBuffIdx, uBuffSize, ch32);
michael@0 127 if (u_isWhitespace(ch32)) {
michael@0 128 if (!initialWhitespace) {
michael@0 129 buffer[idx++] = ch;
michael@0 130 while (idx > 0) {
michael@0 131 stream.putback(buffer[--idx]);
michael@0 132 }
michael@0 133 goto STOP_READING;
michael@0 134 }
michael@0 135 /* else skip intialWhitespace */
michael@0 136 }
michael@0 137 else {
michael@0 138 if (initialWhitespace) {
michael@0 139 /*
michael@0 140 When initialWhitespace is TRUE, we haven't appended any
michael@0 141 character yet. This is where we truncate the string,
michael@0 142 to avoid modifying the string before we know if we can
michael@0 143 actually read from the stream.
michael@0 144 */
michael@0 145 str.truncate(0);
michael@0 146 initialWhitespace = FALSE;
michael@0 147 }
michael@0 148 str.append(ch32);
michael@0 149 }
michael@0 150 }
michael@0 151 idx = 0;
michael@0 152 }
michael@0 153 else {
michael@0 154 buffer[idx++] = ch;
michael@0 155 }
michael@0 156 }
michael@0 157 STOP_READING:
michael@0 158 u_releaseDefaultConverter(converter);
michael@0 159 }
michael@0 160
michael@0 161 /* stream.flush();*/
michael@0 162 return stream;
michael@0 163 }
michael@0 164
michael@0 165 U_NAMESPACE_END
michael@0 166
michael@0 167 #endif

mercurial