From c6099fb59d5619fe650bbeda5dfdf50848389028 Mon Sep 17 00:00:00 2001 From: George Rhoten Date: Fri, 13 Aug 2004 17:05:00 +0000 Subject: [PATCH] ICU-3720 Make it possible to read from stdin. Can't easily automate this test case X-SVN-Rev: 16153 --- icu4c/source/io/ufile.c | 23 +++++++++++---------- icu4c/source/io/ufile.h | 2 ++ icu4c/source/io/ustdio.c | 32 +++++++++++++++++++++--------- icu4c/source/test/iotest/filetst.c | 27 ++++++++++++++++++++++++- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/icu4c/source/io/ufile.c b/icu4c/source/io/ufile.c index bcd9f09156d..19e95f68a96 100644 --- a/icu4c/source/io/ufile.c +++ b/icu4c/source/io/ufile.c @@ -27,6 +27,10 @@ #include "cstring.h" #include "cmemory.h" +#ifdef WIN32 +/* Windows likes to rename Unix-like functions */ +#define fileno _fileno +#endif U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ u_finit(FILE *f, @@ -40,21 +44,18 @@ u_finit(FILE *f, } uprv_memset(result, 0, sizeof(UFILE)); + result->fFileno = fileno(f); #ifdef WIN32 - { - int filenum = _fileno(f); - if (0 <= filenum && filenum <= 2) { - /* stdin, stdout and stderr need to be special cased for Windows 98 */ - result->fFile = &_iob[_fileno(f)]; - } - else { - result->fFile = f; - } + if (0 <= result->fFileno && result->fFileno <= 2) { + /* stdin, stdout and stderr need to be special cased for Windows 98 */ + result->fFile = &_iob[_fileno(f)]; } -#else - result->fFile = f; + else #endif + { + result->fFile = f; + } result->str.fBuffer = result->fUCBuffer; result->str.fPos = result->fUCBuffer; diff --git a/icu4c/source/io/ufile.h b/icu4c/source/io/ufile.h index 0794144f82f..8be6d7314a4 100644 --- a/icu4c/source/io/ufile.h +++ b/icu4c/source/io/ufile.h @@ -68,6 +68,8 @@ struct UFILE { UChar fUCBuffer[UFILE_UCHARBUFFER_SIZE];/* buffer used for toUnicode */ UBool fOwnFile; /* TRUE if fFile should be closed */ + + int32_t fFileno; /* File number. Useful to determine if it's stdin. */ }; /** diff --git a/icu4c/source/io/ustdio.c b/icu4c/source/io/ustdio.c index dbb6560a00a..28e12719dc5 100644 --- a/icu4c/source/io/ustdio.c +++ b/icu4c/source/io/ustdio.c @@ -20,6 +20,7 @@ #include "unicode/ustdio.h" #include "unicode/putil.h" #include "cmemory.h" +#include "cstring.h" #include "ufile.h" #include "ufmt_cmn.h" #include "unicode/ucnv.h" @@ -396,13 +397,16 @@ ufile_fill_uchar_buffer(UFILE *f) return; } - /* shift the buffer if it isn't empty */ str = &f->str; dataSize = (int32_t)(str->fLimit - str->fPos); + if (f->fFileno == 0 && dataSize > 0) { + /* Don't read from stdin too many times. There is still some data. */ + return; + } + + /* shift the buffer if it isn't empty */ if(dataSize != 0) { - memmove(f->fUCBuffer, - str->fPos, - dataSize * sizeof(UChar)); + uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar)); } @@ -414,10 +418,18 @@ ufile_fill_uchar_buffer(UFILE *f) maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1); /* Read in the data to convert */ - bytesRead = (int32_t)fread(charBuffer, - sizeof(char), - ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), - f->fFile); + if (f->fFileno == 0) { + /* Special case. Read from stdin one line at a time. */ + char *retStr = fgets(charBuffer, ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile); + bytesRead = (retStr ? uprv_strlen(charBuffer) : 0); + } + else { + /* A normal file */ + bytesRead = (int32_t)fread(charBuffer, + sizeof(char), + ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), + f->fFile); + } /* Set up conversion parameters */ status = U_ZERO_ERROR; @@ -555,7 +567,9 @@ ufile_getch(UFILE *f, UChar *ch) } else if (f) { /* otherwise, fill the buffer and return the next character */ - ufile_fill_uchar_buffer(f); + if(f->str.fPos >= f->str.fLimit) { + ufile_fill_uchar_buffer(f); + } if(f->str.fPos < f->str.fLimit) { *ch = *(f->str.fPos)++; isValidChar = TRUE; diff --git a/icu4c/source/test/iotest/filetst.c b/icu4c/source/test/iotest/filetst.c index 9316d9e41ec..1e7963f9745 100644 --- a/icu4c/source/test/iotest/filetst.c +++ b/icu4c/source/test/iotest/filetst.c @@ -23,8 +23,8 @@ const char STANDARD_TEST_FILE[] = "iotest-c.txt"; -static void TestFileFromICU(UFILE *myFile) { #if !UCONFIG_NO_FORMATTING +static void TestFileFromICU(UFILE *myFile) { int32_t n[1]; float myFloat = -1234.0; int32_t newValuePtr[1]; @@ -317,6 +317,30 @@ static void TestFile(void) { TestFileFromICU(u_finit(standardFile, NULL, NULL)); fclose(standardFile); */ +} +#endif + +static void StdinBuffering(void) { +#if 0 + UChar buff[255]; + int32_t num = 0; + UFILE *uStdIn = NULL; + UFILE *uStdOut = NULL; + uStdIn = u_finit(stdin, NULL, NULL); + uStdOut = u_finit(stdout, NULL, NULL); + if (uStdIn == NULL) + return; + + buff[0] = 0x40; + buff[1] = 0; + u_fgets(buff, sizeof(buff)/sizeof(buff[0]), uStdIn); + u_fprintf(uStdOut, "%S\n", buff); + u_fscanf(uStdIn, "%d", &num); + u_fprintf(uStdOut, "%d\n", num); + u_fscanf(uStdIn, "%d", &num); + u_fprintf(uStdOut, "%d\n", num); +#else + log_verbose("Test disabled because it requires user interaction"); #endif } @@ -1415,6 +1439,7 @@ addFileTest(TestNode** root) { #if !UCONFIG_NO_FORMATTING addTest(root, &TestFile, "file/TestFile"); #endif + addTest(root, &StdinBuffering, "file/StdinBuffering"); addTest(root, &TestfgetsBuffers, "file/TestfgetsBuffers"); addTest(root, &TestfgetsLineCount, "file/TestfgetsLineCount"); addTest(root, &TestfgetsNewLineHandling, "file/TestfgetsNewLineHandling");