2001-08-30 01:58:44 +00:00
|
|
|
/*
|
|
|
|
**********************************************************************
|
|
|
|
* Copyright (C) 2001, 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"
|
2002-06-27 01:19:20 +00:00
|
|
|
#include "unicode/uobject.h"
|
2001-08-30 01:58:44 +00:00
|
|
|
#include "unicode/ustream.h"
|
|
|
|
#include "unicode/ucnv.h"
|
2002-02-25 21:46:41 +00:00
|
|
|
#include "unicode/uchar.h"
|
2001-08-30 01:58:44 +00:00
|
|
|
#include "ustr_imp.h"
|
2002-02-23 00:34:39 +00:00
|
|
|
#include <string.h>
|
2001-08-30 01:58:44 +00:00
|
|
|
|
|
|
|
// console IO
|
|
|
|
|
|
|
|
#if U_IOSTREAM_SOURCE >= 198506
|
|
|
|
|
|
|
|
#if U_IOSTREAM_SOURCE >= 199711
|
2002-02-23 00:34:39 +00:00
|
|
|
#define STD_NAMESPACE std::
|
2001-08-30 01:58:44 +00:00
|
|
|
#else
|
2002-02-23 00:34:39 +00:00
|
|
|
#define STD_NAMESPACE
|
2001-08-30 01:58:44 +00:00
|
|
|
#endif
|
|
|
|
|
2002-02-23 00:34:39 +00:00
|
|
|
#define STD_OSTREAM STD_NAMESPACE ostream
|
|
|
|
#define STD_ISTREAM STD_NAMESPACE istream
|
2001-08-30 01:58:44 +00:00
|
|
|
|
2001-08-30 03:29:14 +00:00
|
|
|
U_USTDIO_API STD_OSTREAM &
|
2002-02-23 00:34:39 +00:00
|
|
|
operator<<(STD_OSTREAM& stream, const UnicodeString& str)
|
2001-08-30 01:58:44 +00:00
|
|
|
{
|
2002-02-23 00:34:39 +00:00
|
|
|
if(str.length() > 0) {
|
2001-08-30 01:58:44 +00:00
|
|
|
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)) {
|
2002-02-23 00:34:39 +00:00
|
|
|
const UChar *us = str.getBuffer();
|
|
|
|
const UChar *uLimit = us + str.length();
|
2001-08-30 01:58:44 +00:00
|
|
|
char *s, *sLimit = buffer + sizeof(buffer);
|
|
|
|
do {
|
|
|
|
errorCode = U_ZERO_ERROR;
|
|
|
|
s = buffer;
|
|
|
|
ucnv_fromUnicode(converter, &s, sLimit, &us, uLimit, 0, FALSE, &errorCode);
|
|
|
|
|
|
|
|
// write this chunk
|
|
|
|
if(s > buffer) {
|
|
|
|
stream.write(buffer, s - buffer);
|
|
|
|
}
|
|
|
|
} while(errorCode == U_BUFFER_OVERFLOW_ERROR);
|
|
|
|
u_releaseDefaultConverter(converter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-23 00:34:39 +00:00
|
|
|
/* stream.flush();*/
|
2001-08-30 01:58:44 +00:00
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2002-02-23 00:34:39 +00:00
|
|
|
U_USTDIO_API STD_ISTREAM &
|
|
|
|
operator>>(STD_ISTREAM& stream, UnicodeString& str)
|
|
|
|
{
|
|
|
|
/* ipfx should eat whitespace when ios::skipws is set */
|
2002-02-25 21:46:41 +00:00
|
|
|
UChar uBuffer[16];
|
2002-02-26 21:23:21 +00:00
|
|
|
char buffer[16];
|
|
|
|
int32_t idx = 0;
|
2002-02-23 00:34:39 +00:00
|
|
|
UConverter *converter;
|
|
|
|
UErrorCode errorCode = U_ZERO_ERROR;
|
|
|
|
|
|
|
|
str.truncate(0);
|
|
|
|
// use the default converter to convert chunks of text
|
|
|
|
converter = u_getDefaultConverter(&errorCode);
|
|
|
|
if(U_SUCCESS(errorCode)) {
|
|
|
|
UChar *us = uBuffer;
|
|
|
|
const UChar *uLimit = uBuffer + sizeof(uBuffer)/sizeof(*uBuffer);
|
|
|
|
const char *s, *sLimit;
|
|
|
|
char ch;
|
2002-02-26 21:23:21 +00:00
|
|
|
UChar ch32;
|
2002-02-25 21:46:41 +00:00
|
|
|
UBool intialWhitespace = TRUE;
|
2002-02-23 00:34:39 +00:00
|
|
|
|
2002-02-25 21:46:41 +00:00
|
|
|
/* We need to consume one byte at a time to see what is considered whitespace. */
|
2002-02-23 00:34:39 +00:00
|
|
|
while (!stream.eof()) {
|
2002-02-25 21:46:41 +00:00
|
|
|
ch = stream.get();
|
|
|
|
sLimit = &ch + 1;
|
|
|
|
errorCode = U_ZERO_ERROR;
|
|
|
|
us = uBuffer;
|
|
|
|
s = &ch;
|
|
|
|
ucnv_toUnicode(converter, &us, uLimit, &s, sLimit, 0, FALSE, &errorCode);
|
|
|
|
if(U_FAILURE(errorCode)) {
|
|
|
|
/* Something really bad happened */
|
|
|
|
return stream;
|
2002-02-23 00:34:39 +00:00
|
|
|
}
|
2002-02-26 21:23:21 +00:00
|
|
|
/* Was the character consumed? */
|
2002-02-25 21:46:41 +00:00
|
|
|
if (us != uBuffer) {
|
2002-09-30 04:01:47 +00:00
|
|
|
U16_GET(uBuffer, 0, 0, us-uBuffer, ch32);
|
2002-02-26 21:23:21 +00:00
|
|
|
if (u_isWhitespace(ch32)) {
|
2002-02-25 21:46:41 +00:00
|
|
|
if (!intialWhitespace) {
|
2002-02-26 21:23:21 +00:00
|
|
|
buffer[idx++] = ch;
|
|
|
|
while (idx > 0) {
|
|
|
|
stream.putback(buffer[--idx]);
|
|
|
|
}
|
2002-02-25 21:46:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* else skip intialWhitespace */
|
2002-02-23 00:34:39 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-02-26 21:23:21 +00:00
|
|
|
str.append(ch32);
|
2002-02-25 21:46:41 +00:00
|
|
|
intialWhitespace = FALSE;
|
2002-02-23 00:34:39 +00:00
|
|
|
}
|
2002-02-26 21:23:21 +00:00
|
|
|
idx = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
buffer[idx++] = ch;
|
2002-02-23 00:34:39 +00:00
|
|
|
}
|
2002-02-25 21:46:41 +00:00
|
|
|
}
|
2002-02-23 00:34:39 +00:00
|
|
|
u_releaseDefaultConverter(converter);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stream.flush();*/
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-30 01:58:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
2002-06-29 00:04:16 +00:00
|
|
|
/* UnicodeStringStreamer internal API may be useful for future reference */
|
2001-08-30 01:58:44 +00:00
|
|
|
#ifndef UNISTRM_H
|
|
|
|
#define UNISTRM_H
|
|
|
|
|
|
|
|
#include "filestrm.h"
|
|
|
|
#include "umemstrm.h"
|
|
|
|
#include "unicode/unistr.h"
|
|
|
|
|
|
|
|
|
2002-06-29 00:04:16 +00:00
|
|
|
class U_COMMON_API UnicodeStringStreamer /* not : public UObject because all methods are static */ {
|
2001-08-30 01:58:44 +00:00
|
|
|
public:
|
|
|
|
static void streamIn(UnicodeString* string, FileStream* is);
|
|
|
|
static void streamOut(const UnicodeString* string, FileStream* os);
|
|
|
|
static void streamIn(UnicodeString* string, UMemoryStream* is);
|
|
|
|
static void streamOut(const UnicodeString* string, UMemoryStream* os);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//========================================
|
|
|
|
// Streaming (to be removed)
|
|
|
|
//========================================
|
|
|
|
|
|
|
|
#include "unistrm.h"
|
|
|
|
#include "filestrm.h"
|
|
|
|
|
|
|
|
|
|
|
|
inline uint8_t
|
|
|
|
uprv_hibyte(uint16_t x)
|
|
|
|
{ return (uint8_t)(x >> 8); }
|
|
|
|
|
|
|
|
inline uint8_t
|
|
|
|
uprv_lobyte(uint16_t x)
|
|
|
|
{ return (uint8_t)(x & 0xff); }
|
|
|
|
|
|
|
|
inline uint16_t
|
|
|
|
uprv_hiword(uint32_t x)
|
|
|
|
{ return (uint16_t)(x >> 16); }
|
|
|
|
|
|
|
|
inline uint16_t
|
|
|
|
uprv_loword(uint32_t x)
|
|
|
|
{ return (uint16_t)(x & 0xffff); }
|
|
|
|
|
|
|
|
inline void
|
|
|
|
writeLong(FileStream *os,
|
|
|
|
int32_t x)
|
|
|
|
{
|
|
|
|
uint16_t word = uprv_hiword((uint32_t)x);
|
|
|
|
T_FileStream_putc(os, uprv_hibyte(word));
|
|
|
|
T_FileStream_putc(os, uprv_lobyte(word));
|
|
|
|
word = uprv_loword((uint32_t)x);
|
|
|
|
T_FileStream_putc(os, uprv_hibyte(word));
|
|
|
|
T_FileStream_putc(os, uprv_lobyte(word));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int32_t
|
|
|
|
readLong(FileStream *is)
|
|
|
|
{
|
|
|
|
int32_t x = T_FileStream_getc(is);
|
|
|
|
|
|
|
|
x = (x << 8) | T_FileStream_getc(is);
|
|
|
|
x = (x << 8) | T_FileStream_getc(is);
|
|
|
|
x = (x << 8) | T_FileStream_getc(is);
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
writeUChar(FileStream *os,
|
|
|
|
UChar c)
|
|
|
|
{
|
|
|
|
T_FileStream_putc(os, uprv_hibyte(c));
|
|
|
|
T_FileStream_putc(os, uprv_lobyte(c));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline UChar
|
|
|
|
readUChar(FileStream *is)
|
|
|
|
{
|
|
|
|
UChar c = (UChar)T_FileStream_getc(is);
|
|
|
|
|
|
|
|
return (UChar)((c << 8) | T_FileStream_getc(is));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UnicodeStringStreamer::streamOut(const UnicodeString *s,
|
|
|
|
FileStream *os)
|
|
|
|
{
|
|
|
|
if(!T_FileStream_error(os)) {
|
|
|
|
writeLong(os, s->fLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
const UChar *c = s->getArrayStart();
|
|
|
|
const UChar *end = c + s->fLength;
|
|
|
|
|
|
|
|
while(c != end && ! T_FileStream_error(os)) {
|
|
|
|
writeUChar(os, *c++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UnicodeStringStreamer::streamIn(UnicodeString *s,
|
|
|
|
FileStream *is)
|
|
|
|
{
|
|
|
|
int32_t newSize;
|
|
|
|
|
|
|
|
// handle error conditions
|
|
|
|
if(T_FileStream_error(is) || T_FileStream_eof(is)) {
|
|
|
|
s->setToBogus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
newSize = readLong(is);
|
|
|
|
if((newSize < 0) || T_FileStream_error(is)
|
|
|
|
|| ((newSize > 0) && T_FileStream_eof(is))) {
|
|
|
|
s->setToBogus(); //error condition
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// clone s's array, if needed
|
|
|
|
if(!s->cloneArrayIfNeeded(newSize, newSize, FALSE)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar *c = s->getArrayStart();
|
|
|
|
UChar *end = c + newSize;
|
|
|
|
|
|
|
|
while(c < end && ! (T_FileStream_error(is) || T_FileStream_eof(is))) {
|
|
|
|
*c++ = readUChar(is);
|
|
|
|
}
|
|
|
|
|
|
|
|
// couldn't read all chars
|
|
|
|
if(c < end) {
|
|
|
|
s->setToBogus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->fLength = newSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UnicodeStringStreamer::streamOut(const UnicodeString *s,
|
|
|
|
UMemoryStream *os)
|
|
|
|
{
|
|
|
|
if(!uprv_mstrm_error(os)) {
|
|
|
|
uprv_mstrm_write(os, (uint8_t*)&s->fLength, (int32_t)sizeof(s->fLength));
|
|
|
|
}
|
|
|
|
|
|
|
|
const UChar *c = s->getArrayStart();
|
|
|
|
const UChar *end = c + s->fLength;
|
|
|
|
|
|
|
|
while(c != end && ! uprv_mstrm_error(os)) {
|
|
|
|
uprv_mstrm_write(os, (uint8_t*)c, (int32_t)sizeof(*c));
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UnicodeStringStreamer::streamIn(UnicodeString *s,
|
|
|
|
UMemoryStream *is)
|
|
|
|
{
|
|
|
|
int32_t newSize;
|
|
|
|
|
|
|
|
// handle error conditions
|
|
|
|
if(uprv_mstrm_error(is) || uprv_mstrm_eof(is)) {
|
|
|
|
s->setToBogus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
uprv_mstrm_read(is, (uint8_t *)&newSize, (int32_t)sizeof(int32_t));
|
|
|
|
if((newSize < 0) || uprv_mstrm_error(is)
|
|
|
|
|| ((newSize > 0) && uprv_mstrm_eof(is))) {
|
|
|
|
s->setToBogus(); //error condition
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// clone s's array, if needed
|
|
|
|
if(!s->cloneArrayIfNeeded(newSize, newSize, FALSE)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar *c = s->getArrayStart();
|
|
|
|
UChar *end = c + newSize;
|
|
|
|
|
|
|
|
while(c < end && ! (uprv_mstrm_error(is) || uprv_mstrm_eof(is))) {
|
|
|
|
uprv_mstrm_read(is, (uint8_t *)c, (int32_t)sizeof(*c));
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// couldn't read all chars
|
|
|
|
if(c < end) {
|
|
|
|
s->setToBogus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->fLength = newSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|