ICU-3720 Make it possible to read from stdin.
Can't easily automate this test case
X-SVN-Rev: 16153
diff --git a/icu4c/source/io/ufile.c b/icu4c/source/io/ufile.c
index bcd9f09..19e95f6 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 @@
}
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 0794144..8be6d73 100644
--- a/icu4c/source/io/ufile.h
+++ b/icu4c/source/io/ufile.h
@@ -68,6 +68,8 @@
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 dbb6560..28e1271 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 @@
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 @@
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 @@
}
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 9316d9e..1e7963f 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 @@
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 @@
#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");