ICU-2256 Make u_fgets more compatible with fgets, and improve surrogate support.

X-SVN-Rev: 13392
This commit is contained in:
George Rhoten 2003-10-10 20:55:24 +00:00
parent 42281a6605
commit f13e8abf93
3 changed files with 104 additions and 120 deletions

View File

@ -76,14 +76,11 @@
* u_fsettransliterator does not support U_READ side of transliteration.
* The format specifier should limit the size of a format or honor it in
order to prevent buffer overruns. (e.g. %256.256d).
* u_fgets is different from stdio. The UChar and UFile arguments are swapped.
* u_fread and u_fwrite don't exist. They're needed for reading and writing
data structures without any conversion.
* u_file_read and u_file_write are used for writing strings. u_fgets and
u_fputs or u_fread and u_fwrite should be used to do this.
* u_fgetcx isn't really needed anymore because the transliterator is a
part of the file API. It allows multiple kinds of escape sequences
to be unescaped.
* u_fgetcx may not be needed anymore. Maybe u_fgetc should return a UChar32.
* We should consider using a UnicodeSet for scanset.
* scanset has a buffer overflow and underflow bug for both string and file
APIs.
@ -210,8 +207,8 @@ u_fgetlocale(UFILE *file);
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fsetlocale(const char *locale,
UFILE *file);
u_fsetlocale(const char *locale,
UFILE *file);
#endif
@ -240,8 +237,8 @@ u_fgetcodepage(UFILE *file);
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fsetcodepage(const char *codepage,
UFILE *file);
u_fsetcodepage(const char *codepage,
UFILE *file);
/**
@ -263,9 +260,9 @@ U_CAPI UConverter* U_EXPORT2 u_fgetConverter(UFILE *f);
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fprintf( UFILE *f,
const char *patternSpecification,
... );
u_fprintf(UFILE *f,
const char *patternSpecification,
... );
/**
* Write formatted data to a UFILE.
@ -280,9 +277,9 @@ u_fprintf( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_vfprintf( UFILE *f,
const char *patternSpecification,
va_list ap);
u_vfprintf(UFILE *f,
const char *patternSpecification,
va_list ap);
/**
* Write formatted data to a UFILE.
@ -293,9 +290,9 @@ u_vfprintf( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fprintf_u( UFILE *f,
const UChar *patternSpecification,
... );
u_fprintf_u(UFILE *f,
const UChar *patternSpecification,
... );
/**
* Write formatted data to a UFILE.
@ -310,9 +307,9 @@ u_fprintf_u( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_vfprintf_u( UFILE *f,
const UChar *patternSpecification,
va_list ap);
u_vfprintf_u(UFILE *f,
const UChar *patternSpecification,
va_list ap);
/**
* Write a Unicode to a UFILE. The null (U+0000) terminated UChar*
@ -324,8 +321,8 @@ u_vfprintf_u( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fputs(const UChar *s,
UFILE *f);
u_fputs(const UChar *s,
UFILE *f);
/**
* Write a UChar to a UFILE.
@ -335,8 +332,8 @@ u_fputs(const UChar *s,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fputc(UChar uc,
UFILE *f);
u_fputc(UChar uc,
UFILE *f);
/**
* Write Unicode to a UFILE.
@ -349,9 +346,9 @@ u_fputc(UChar uc,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_file_write(const UChar *chars,
int32_t count,
UFILE *f);
u_file_write(const UChar *chars,
int32_t count,
UFILE *f);
/* Input functions */
@ -366,9 +363,9 @@ u_file_write(const UChar *chars,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fscanf( UFILE *f,
const char *patternSpecification,
... );
u_fscanf(UFILE *f,
const char *patternSpecification,
... );
/**
* Read formatted data from a UFILE.
@ -384,9 +381,9 @@ u_fscanf( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_vfscanf( UFILE *f,
const char *patternSpecification,
va_list ap);
u_vfscanf(UFILE *f,
const char *patternSpecification,
va_list ap);
/**
* Read formatted data from a UFILE.
@ -398,9 +395,9 @@ u_vfscanf( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_fscanf_u( UFILE *f,
const UChar *patternSpecification,
... );
u_fscanf_u(UFILE *f,
const UChar *patternSpecification,
... );
/**
* Read formatted data from a UFILE.
@ -416,9 +413,9 @@ u_fscanf_u( UFILE *f,
* @draft
*/
U_CAPI int32_t U_EXPORT2
u_vfscanf_u( UFILE *f,
const UChar *patternSpecification,
va_list ap);
u_vfscanf_u(UFILE *f,
const UChar *patternSpecification,
va_list ap);
/**
* Read one line of text into a UChar* string from a UFILE. The newline
@ -433,9 +430,9 @@ u_vfscanf_u( UFILE *f,
* @draft
*/
U_CAPI UChar* U_EXPORT2
u_fgets(UFILE *f,
int32_t n,
UChar *s);
u_fgets(UChar *s,
int32_t n,
UFILE *f);
/**
* Read a UChar from a UFILE.
@ -444,24 +441,20 @@ u_fgets(UFILE *f,
* @draft
*/
U_CAPI UChar U_EXPORT2
u_fgetc(UFILE *f);
u_fgetc(UFILE *f);
/**
* Read a UChar from a UFILE and process escape sequences. If the
* next character is not a backslash, this is the same as calling
* u_fgetc(). If it is, then additional characters comprising the
* escape sequence will be read from the UFILE, parsed, and the
* resultant UChar returned. Ill-formed escape sequences return
* U+FFFFFFFF.
* Read a UChar32 from a UFILE.
*
* @param f The UFILE from which to read.
* @return The UChar value read, or U+FFFF if no character was
* available, or U+FFFFFFFF if an ill-formed escape sequence was
* @return The UChar32 value read, or U_EOF if no character was
* available, or U+FFFFFFFF if an ill-formed character was
* encountered.
* @see u_unescape()
* @draft
*/
U_CAPI UChar32 U_EXPORT2
u_fgetcx(UFILE *f);
u_fgetcx(UFILE *f);
/**
* Unget a UChar from a UFILE.
@ -469,11 +462,11 @@ u_fgetcx(UFILE *f);
* to <TT>u_fgetc</TT>, the results are undefined.
* @param c The UChar to put back on the stream.
* @param f The UFILE to receive <TT>c</TT>.
* @return The UChar value put back if successful, U+FFFF otherwise.
* @return The UChar32 value put back if successful, U_EOF otherwise.
* @draft
*/
U_CAPI UChar U_EXPORT2
u_fungetc(UChar c,
U_CAPI UChar32 U_EXPORT2
u_fungetc(UChar32 c,
UFILE *f);
/**
@ -788,4 +781,3 @@ u_vsscanf_u(const UChar *buffer,
#endif

View File

@ -435,9 +435,9 @@ ufile_fill_uchar_buffer(UFILE *f)
}
U_CAPI UChar* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_fgets(UFILE *f,
int32_t n,
UChar *s)
u_fgets(UChar *s,
int32_t n,
UFILE *f)
{
int32_t dataSize;
int32_t count;
@ -536,78 +536,70 @@ u_fgetc(UFILE *f)
/* otherwise, fill the buffer and return the next character */
else {
ufile_fill_uchar_buffer(f);
if(f->fUCPos < f->fUCLimit)
if(f->fUCPos < f->fUCLimit) {
return *(f->fUCPos)++;
else
return 0xFFFF;
}
else {
return U_EOF;
}
}
}
/* u_unescapeAt() callback to return a UChar from a UFILE */
static UChar U_CALLCONV
_charAt(int32_t offset, void *context) {
return ((UFILE*) context)->fUCPos[offset];
}
/* Read a UChar from a UFILE and process escape sequences */
U_CAPI UChar32 U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_fgetcx(UFILE *f)
{
int32_t length;
int32_t offset;
UChar32 c32;
UChar c16;
/* Fill the buffer if it is empty */
if (f->fUCPos >= f->fUCLimit) {
if (f->fUCPos + 1 >= f->fUCLimit) {
ufile_fill_uchar_buffer(f);
}
/* Get the next character in the buffer */
if (f->fUCPos < f->fUCLimit) {
c16 = *(f->fUCPos)++;
} else {
c16 = U_EOF;
c32 = *(f->fUCPos)++;
}
else {
c32 = U_EOF;
}
/* If it isn't a backslash, return it */
if (c16 != 0x005C /*'\\'*/) {
return c16;
if (U_IS_LEAD(c32)) {
if (f->fUCPos < f->fUCLimit) {
UChar c16 = *(f->fUCPos)++;
c32 = U16_GET_SUPPLEMENTARY(c32, c16);
}
else {
c32 = U_EOF;
}
}
/* Determine the amount of data in the buffer */
length = (int32_t)(f->fUCLimit - f->fUCPos);
/* The longest escape sequence is \Uhhhhhhhh; make sure
we have at least that many characters */
if (length < 10) {
/* fill the buffer */
ufile_fill_uchar_buffer(f);
length = (int32_t)(f->fUCLimit - f->fUCPos);
}
/* Process the escape */
offset = 0;
c32 = u_unescapeAt(_charAt, &offset, length, (void*)f);
/* Update the current buffer position */
f->fUCPos += offset;
return c32;
}
U_CAPI UChar U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_fungetc(UChar c,
U_CAPI UChar32 U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_fungetc(UChar32 ch,
UFILE *f)
{
/* if we're at the beginning of the buffer, sorry! */
if(f->fUCPos == f->fUCBuffer)
return 0xFFFF;
/* otherwise, put the character back */
else {
*--(f->fUCPos) = c;
return c;
if (f->fUCPos == f->fUCBuffer
|| (U_IS_LEAD(ch) && (f->fUCPos - 1) == f->fUCBuffer))
{
ch = U_EOF;
}
else {
/* otherwise, put the character back */
/* TODO: Maybe we shouldn't be writing to the buffer and just verify the contents */
if (U_IS_LEAD(ch)) {
/* Remember, put them back on in the reverse order. */
*--(f->fUCPos) = U16_TRAIL(ch);
*--(f->fUCPos) = U16_LEAD(ch);
}
else {
*--(f->fUCPos) = (UChar)ch;
}
}
return ch;
}
U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */

View File

@ -218,13 +218,13 @@ static void TestFileFromICU(UFILE *myFile) {
log_err("%%V Got: %f, Expected: %f\n", *newDoubleValuePtr, myFloat);
}
u_fgets(myFile, 4, myUString);
u_fgets(myUString, 4, myFile);
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
if (myString == NULL || strcmp(myString, "\t\n") != 0) {
log_err("u_fgets got \"%s\"\n", myString);
}
if (u_fgets(myFile, sizeof(myUString)/sizeof(*myUString), myUString) != myUString) {
if (u_fgets(myUString, sizeof(myUString)/sizeof(*myUString), myFile) != myUString) {
log_err("u_fgets did not return myUString\n");
}
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
@ -232,7 +232,7 @@ static void TestFileFromICU(UFILE *myFile) {
log_err("u_fgets got \"%s\"\n", myString);
}
if (u_fgets(myFile, sizeof(myUString)/sizeof(*myUString), myUString) != myUString) {
if (u_fgets(myUString, sizeof(myUString)/sizeof(*myUString), myFile) != myUString) {
log_err("u_fgets did not return myUString\n");
}
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
@ -240,7 +240,7 @@ static void TestFileFromICU(UFILE *myFile) {
log_err("u_fgets got \"%s\"\n", myString);
}
if (u_fgets(myFile, sizeof(myUString)/sizeof(*myUString), myUString) != myUString) {
if (u_fgets(myUString, sizeof(myUString)/sizeof(*myUString), myFile) != myUString) {
log_err("u_fgets did not return myUString\n");
}
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
@ -248,11 +248,11 @@ static void TestFileFromICU(UFILE *myFile) {
log_err("u_fgets got \"%s\"\n", myString);
}
if (u_fgets(myFile, 0, myUString) != NULL) {
if (u_fgets(myUString, 0, myFile) != NULL) {
log_err("u_fgets got \"%s\" and it should have returned NULL\n", myString);
}
if (u_fgets(myFile, 1, myUString) != myUString) {
if (u_fgets(myUString, 1, myFile) != myUString) {
log_err("u_fgets did not return myUString\n");
}
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
@ -260,7 +260,7 @@ static void TestFileFromICU(UFILE *myFile) {
log_err("u_fgets got \"%s\"\n", myString);
}
if (u_fgets(myFile, 2, myUString) != myUString) {
if (u_fgets(myUString, 2, myFile) != myUString) {
log_err("u_fgets did not return myUString\n");
}
u_austrncpy(myString, myUString, sizeof(myUString)/sizeof(*myUString));
@ -377,7 +377,7 @@ static void TestfgetsBuffers() {
if (u_fgetc(myFile) != 0xFF41) {
log_err("The second character is wrong\n");
}
if (u_fgets(myFile, sizeof(buffer)/sizeof(buffer[0]), buffer) != buffer) {
if (u_fgets(buffer, sizeof(buffer)/sizeof(buffer[0]), myFile) != buffer) {
log_err("Didn't get the buffer back\n");
return;
}
@ -423,7 +423,7 @@ static void TestfgetsBuffers() {
if (u_fgetc(myFile) != 0xFF41) {
log_err("The second character is wrong\n");
}
if (u_fgets(myFile, sizeof(buffer)/sizeof(buffer[0]), buffer) != buffer) {
if (u_fgets(buffer, sizeof(buffer)/sizeof(buffer[0]), myFile) != buffer) {
log_err("Didn't get the buffer back\n");
return;
}
@ -456,7 +456,7 @@ static void TestfgetsBuffers() {
u_memset(buffer, 0xDEAD, sizeof(buffer)/sizeof(buffer[0]));
myFile = u_fopen(STANDARD_TEST_FILE, "r", NULL, "UTF-8");
if (u_fgets(myFile, 2, buffer) != buffer) {
if (u_fgets(buffer, 2, myFile) != buffer) {
log_err("Didn't get the buffer back\n");
return;
}
@ -502,7 +502,7 @@ static void TestfgetsLineCount() {
for (;;) {
u_memset(buffer, 0xDEAD, sizeof(buffer)/sizeof(buffer[0]));
char *returnedCharBuffer = fgets(charBuffer, sizeof(charBuffer)/sizeof(charBuffer[0]), stdFile);
UChar *returnedUCharBuffer = u_fgets(myFile, sizeof(buffer)/sizeof(buffer[0]), buffer);
UChar *returnedUCharBuffer = u_fgets(buffer, sizeof(buffer)/sizeof(buffer[0]), myFile);
if (!returnedCharBuffer && !returnedUCharBuffer) {
/* Both returned NULL. stop. */
@ -575,7 +575,7 @@ static void TestfgetsNewLineHandling() {
for (lineIdx = 0; lineIdx < (int32_t)(sizeof(testUStr)/sizeof(testUStr[0])); lineIdx++) {
u_memset(buffer, 0xDEAD, sizeof(buffer)/sizeof(buffer[0]));
UChar *returnedUCharBuffer = u_fgets(myFile, sizeof(buffer)/sizeof(buffer[0]), buffer);
UChar *returnedUCharBuffer = u_fgets(buffer, sizeof(buffer)/sizeof(buffer[0]), myFile);
if (!returnedUCharBuffer) {
/* Returned NULL. stop. */
@ -591,7 +591,7 @@ static void TestfgetsNewLineHandling() {
if (lineIdx != (int32_t)(sizeof(testUStr)/sizeof(testUStr[0]))) {
log_err("u_fgets read too much\n");
}
if (u_fgets(myFile, sizeof(buffer)/sizeof(buffer[0]), buffer) != NULL) {
if (u_fgets(buffer, sizeof(buffer)/sizeof(buffer[0]), myFile) != NULL) {
log_err("u_file_write wrote too much\n");
}
u_fclose(myFile);
@ -739,7 +739,7 @@ static void TestFilePrintCompatibility() {
uNumPrinted = u_fprintf(myFile, uFormat, uValue);\
u_fclose(myFile);\
myFile = u_fopen(STANDARD_TEST_FILE, "r", "en_US_POSIX", NULL);\
u_fgets(myFile, sizeof(uBuffer)/sizeof(*uBuffer), uBuffer);\
u_fgets(uBuffer, sizeof(uBuffer)/sizeof(*uBuffer), myFile);\
u_fclose(myFile);\
u_austrncpy(compBuffer, uBuffer, sizeof(uBuffer)/sizeof(*uBuffer));\
cNumPrinted = sprintf(buffer, cFormat, cValue);\
@ -762,7 +762,7 @@ static void TestFilePrintCompatibility() {
uNumPrinted = u_fprintf(myFile, format, precision, value);\
u_fclose(myFile);\
myFile = u_fopen(STANDARD_TEST_FILE, "r", "en_US_POSIX", NULL);\
u_fgets(myFile, sizeof(uBuffer)/sizeof(*uBuffer), uBuffer);\
u_fgets(uBuffer, sizeof(uBuffer)/sizeof(*uBuffer), myFile);\
u_fclose(myFile);\
u_austrncpy(compBuffer, uBuffer, sizeof(uBuffer)/sizeof(*uBuffer));\
cNumPrinted = sprintf(buffer, format, precision, value);\
@ -900,7 +900,7 @@ static void TestFprintfFormat() {
uNumPrinted = u_fprintf(myFile, "%d % d %d", -1234, 1234, 1234);
u_fclose(myFile);
myFile = u_fopen(STANDARD_TEST_FILE, "r", "en_US_POSIX", NULL);
u_fgets(myFile, sizeof(uBuffer)/sizeof(*uBuffer), uBuffer);
u_fgets(uBuffer, sizeof(uBuffer)/sizeof(*uBuffer), myFile);
u_fclose(myFile);
u_austrncpy(compBuffer, uBuffer, sizeof(uBuffer)/sizeof(*uBuffer));
cNumPrinted = sprintf(buffer, "%d % d %d", -1234, 1234, 1234);