16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************** 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 2001-2011, International Business Machines 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Corporation and others. All Rights Reserved. 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************** 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* FILE NAME : ustream.cpp 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Modification History: 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Date Name Description 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 06/25/2001 grhoten Move iostream from unistr.h to here 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org****************************************************************************** 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/ 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h" 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uobject.h" 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustream.h" 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ucnv.h" 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uchar.h" 206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h" 216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ustr_cnv.h" 226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h" 236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <string.h> 246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// console IO 266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_IOSTREAM_SOURCE >= 199711 286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define STD_NAMESPACE std:: 306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define STD_OSTREAM STD_NAMESPACE ostream 326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define STD_ISTREAM STD_NAMESPACE istream 336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN 356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_IO_API STD_OSTREAM & U_EXPORT2 376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgoperator<<(STD_OSTREAM& stream, const UnicodeString& str) 386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(str.length() > 0) { 406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char buffer[200]; 416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UConverter *converter; 426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UErrorCode errorCode = U_ZERO_ERROR; 436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // use the default converter to convert chunks of text 456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org converter = u_getDefaultConverter(&errorCode); 466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(U_SUCCESS(errorCode)) { 476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const UChar *us = str.getBuffer(); 486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const UChar *uLimit = us + str.length(); 496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char *s, *sLimit = buffer + (sizeof(buffer) - 1); 506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org do { 516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org errorCode = U_ZERO_ERROR; 526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org s = buffer; 536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ucnv_fromUnicode(converter, &s, sLimit, &us, uLimit, 0, FALSE, &errorCode); 546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *s = 0; 556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // write this chunk 576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(s > buffer) { 586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org stream << buffer; 596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } while(errorCode == U_BUFFER_OVERFLOW_ERROR); 616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org u_releaseDefaultConverter(converter); 626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* stream.flush();*/ 666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return stream; 676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_IO_API STD_ISTREAM & U_EXPORT2 706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgoperator>>(STD_ISTREAM& stream, UnicodeString& str) 716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // This is like ICU status checking. 736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (stream.fail()) { 746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return stream; 756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* ipfx should eat whitespace when ios::skipws is set */ 786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UChar uBuffer[16]; 796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char buffer[16]; 806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t idx = 0; 816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UConverter *converter; 826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UErrorCode errorCode = U_ZERO_ERROR; 836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // use the default converter to convert chunks of text 856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org converter = u_getDefaultConverter(&errorCode); 866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(U_SUCCESS(errorCode)) { 876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UChar *us = uBuffer; 886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const UChar *uLimit = uBuffer + sizeof(uBuffer)/sizeof(*uBuffer); 896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const char *s, *sLimit; 906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char ch; 916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UChar ch32; 926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UBool initialWhitespace = TRUE; 936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UBool continueReading = TRUE; 946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* We need to consume one byte at a time to see what is considered whitespace. */ 966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org while (continueReading) { 976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ch = stream.get(); 986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (stream.eof()) { 996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // The EOF is only set after the get() of an unavailable byte. 1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (!initialWhitespace) { 1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org stream.clear(stream.eofbit); 1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org continueReading = FALSE; 1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org sLimit = &ch + (int)continueReading; 1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org us = uBuffer; 1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org s = &ch; 1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org errorCode = U_ZERO_ERROR; 1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* 1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Since we aren't guaranteed to see the state before this call, 1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org this code won't work on stateful encodings like ISO-2022 or an EBCDIC stateful encoding. 1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org We flush on the last byte to ensure that we output truncated multibyte characters. 1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ucnv_toUnicode(converter, &us, uLimit, &s, sLimit, 0, !continueReading, &errorCode); 1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(U_FAILURE(errorCode)) { 1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* Something really bad happened. setstate() isn't always an available API */ 1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org stream.clear(stream.failbit); 1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org goto STOP_READING; 1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* Was the character consumed? */ 1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (us != uBuffer) { 1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* Reminder: ibm-1390 & JISX0213 can output 2 Unicode code points */ 1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t uBuffSize = us-uBuffer; 1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t uBuffIdx = 0; 1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org while (uBuffIdx < uBuffSize) { 1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org U16_NEXT(uBuffer, uBuffIdx, uBuffSize, ch32); 1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (u_isWhitespace(ch32)) { 1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (!initialWhitespace) { 1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer[idx++] = ch; 1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org while (idx > 0) { 1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org stream.putback(buffer[--idx]); 1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org goto STOP_READING; 1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* else skip intialWhitespace */ 1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org else { 1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (initialWhitespace) { 1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* 1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org When initialWhitespace is TRUE, we haven't appended any 1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org character yet. This is where we truncate the string, 1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org to avoid modifying the string before we know if we can 1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org actually read from the stream. 1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org str.truncate(0); 1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org initialWhitespace = FALSE; 1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org str.append(ch32); 1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org idx = 0; 1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org else { 1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer[idx++] = ch; 1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgSTOP_READING: 1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org u_releaseDefaultConverter(converter); 1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* stream.flush();*/ 1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return stream; 1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END 1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 168