]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/io/ustdio.c
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / io / ustdio.c
index 8ffd9050ea38248a7143312622b773c5b132ff70..df4c4f1c37c4441f49d09e8f81eac7843c35db24 100644 (file)
@@ -1,21 +1,21 @@
 /*
-******************************************************************************
-*
-*   Copyright (C) 1998-2004, International Business Machines
-*   Corporation and others.  All Rights Reserved.
-*
-******************************************************************************
-*
-* File ustdio.c
-*
-* Modification History:
-*
-*   Date        Name        Description
-*   11/18/98    stephen     Creation.
-*   03/12/99    stephen     Modified for new C API.
-*   07/19/99    stephen     Fixed read() and gets()
-******************************************************************************
-*/
+ ******************************************************************************
+ *
+ *   Copyright (C) 1998-2011, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ ******************************************************************************
+ *
+ * File ustdio.c
+ *
+ * Modification History:
+ *
+ *   Date        Name        Description
+ *   11/18/98    stephen     Creation.
+ *   03/12/99    stephen     Modified for new C API.
+ *   07/19/99    stephen     Fixed read() and gets()
+ ******************************************************************************
+ */
 
 #include "unicode/ustdio.h"
 #include "unicode/putil.h"
 #define DELIM_LS 0x2028
 #define DELIM_PS 0x2029
 
-/* Leave this copyright notice here! */
-static const char copyright[] = U_COPYRIGHT_STRING;
-
 /* TODO: is this correct for all codepages? Should we just use \n and let the converter handle it? */
-#ifdef WIN32
+#if U_PLATFORM_USES_ONLY_WIN32_API
 static const UChar DELIMITERS [] = { DELIM_CR, DELIM_LF, 0x0000 };
 static const uint32_t DELIMITERS_LEN = 2;
 /* TODO: Default newline writing should be detected based upon the converter being used. */
@@ -166,6 +163,10 @@ static const UChar * u_file_translit(UFILE *f, const UChar *src, int32_t *count,
         {
             f->fTranslit->buffer = (UChar*)uprv_realloc(f->fTranslit->buffer, newlen * sizeof(UChar));
         }
+        /* Check for malloc/realloc failure. */
+        if (f->fTranslit->buffer == NULL) {
+               return NULL;
+        }
         f->fTranslit->capacity = newlen;
     }
 
@@ -233,7 +234,18 @@ ufile_flush_translit(UFILE *f)
         return;
 #endif
 
-    u_file_write_flush(NULL, 0, f, TRUE);
+    u_file_write_flush(NULL, 0, f, FALSE, TRUE);
+}
+
+
+void
+ufile_flush_io(UFILE *f)
+{
+  if((!f) || (!f->fFile)) {
+    return; /* skip if no file */
+  }
+
+  u_file_write_flush(NULL, 0, f, TRUE, FALSE);
 }
 
 
@@ -283,58 +295,59 @@ u_fputc(UChar32      uc,
 
     U16_APPEND(buf, idx, sizeof(buf)/sizeof(*buf), uc, isError);
     if (isError) {
-        return EOF;
+        return U_EOF;
     }
-    return u_file_write(buf, idx, f) == idx ? uc : EOF;
+    return u_file_write(buf, idx, f) == idx ? uc : U_EOF;
 }
 
 
-U_CAPI int32_t U_EXPORT2
-u_file_write_flush(    const UChar     *chars,
-                   int32_t        count,
-                   UFILE         *f,
-                   UBool         flush)
+U_CFUNC int32_t U_EXPORT2
+u_file_write_flush(const UChar *chars,
+                   int32_t     count,
+                   UFILE       *f,
+                   UBool       flushIO,
+                   UBool       flushTranslit)
 {
     /* Set up conversion parameters */
     UErrorCode  status       = U_ZERO_ERROR;
     const UChar *mySource    = chars;
-    const UChar *sourceAlias = chars;
+    const UChar *mySourceBegin; 
     const UChar *mySourceEnd;
     char        charBuffer[UFILE_CHARBUFFER_SIZE];
     char        *myTarget   = charBuffer;
     int32_t     written      = 0;
     int32_t     numConverted = 0;
 
-    if (!f->fFile) {
-        int32_t charsLeft = f->str.fLimit - f->str.fPos;
-        if (flush && charsLeft > count) {
-            count++;
-        }
-        written = ufmt_min(count, charsLeft);
-        u_strncpy(f->str.fPos, chars, written);
-        f->str.fPos += written;
-        return written;
-    }
-
     if (count < 0) {
         count = u_strlen(chars);
     }
-    mySourceEnd     = chars + count;
 
 #if !UCONFIG_NO_TRANSLITERATION
     if((f->fTranslit) && (f->fTranslit->translit))
     {
         /* Do the transliteration */
-        mySource = u_file_translit(f, chars, &count, flush);
-        sourceAlias = mySource;
-        mySourceEnd = mySource + count;
+        mySource = u_file_translit(f, chars, &count, flushTranslit);
     }
 #endif
 
+    /* Write to a string. */
+    if (!f->fFile) {
+        int32_t charsLeft = (int32_t)(f->str.fLimit - f->str.fPos);
+        if (flushIO && charsLeft > count) {
+            count++;
+        }
+        written = ufmt_min(count, charsLeft);
+        u_strncpy(f->str.fPos, mySource, written);
+        f->str.fPos += written;
+        return written;
+    }
+
+    mySourceEnd = mySource + count;
+
     /* Perform the conversion in a loop */
     do {
+        mySourceBegin = mySource; /* beginning location for this loop */
         status     = U_ZERO_ERROR;
-        sourceAlias = mySource;
         if(f->fConverter != NULL) { /* We have a valid converter */
             ucnv_fromUnicode(f->fConverter,
                 &myTarget,
@@ -342,11 +355,17 @@ u_file_write_flush(    const UChar     *chars,
                 &mySource,
                 mySourceEnd,
                 NULL,
-                flush,
+                flushIO,
                 &status);
         } else { /*weiv: do the invariant conversion */
-            u_UCharsToChars(mySource, myTarget, count);
-            myTarget += count;
+            int32_t convertChars = (int32_t) (mySourceEnd - mySource); 
+            if (convertChars > UFILE_CHARBUFFER_SIZE) { 
+                convertChars = UFILE_CHARBUFFER_SIZE; 
+                status = U_BUFFER_OVERFLOW_ERROR; 
+            } 
+            u_UCharsToChars(mySource, myTarget, convertChars); 
+            mySource += convertChars; 
+            myTarget += convertChars; 
         }
         numConverted = (int32_t)(myTarget - charBuffer);
 
@@ -357,7 +376,7 @@ u_file_write_flush(    const UChar     *chars,
                 numConverted,
                 f->fFile);
 
-            written     += numConverted;
+            written     += (int32_t) (mySource - mySourceBegin);
         }
         myTarget     = charBuffer;
     }
@@ -372,7 +391,7 @@ u_file_write(    const UChar     *chars,
              int32_t        count,
              UFILE         *f)
 {
-    return u_file_write_flush(chars,count,f,FALSE);
+    return u_file_write_flush(chars,count,f,FALSE,FALSE);
 }
 
 
@@ -406,7 +425,7 @@ ufile_fill_uchar_buffer(UFILE *f)
 
     /* shift the buffer if it isn't empty */
     if(dataSize != 0) {
-        uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar));
+        uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar)); /* not accessing beyond memory */
     }
 
 
@@ -421,7 +440,7 @@ ufile_fill_uchar_buffer(UFILE *f)
     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);
+        bytesRead = (int32_t)(retStr ? uprv_strlen(charBuffer) : 0);
     }
     else {
         /* A normal file */
@@ -501,11 +520,11 @@ u_fgets(UChar        *s,
         alias = str->fPos;
 
         /* Find how much to copy */
-        if (dataSize < n) {
+        if (dataSize < (n - count)) {
             limit = str->fLimit;
         }
         else {
-            limit = alias + n;
+            limit = alias + (n - count);
         }
 
         if (!currDelim) {
@@ -519,6 +538,12 @@ u_fgets(UChar        *s,
                 if (CAN_HAVE_COMBINED_STRING_DELIMITER(*alias)) {
                     currDelim = *alias;
                 }
+                else {
+                    currDelim = 1;  /* This isn't a newline, but it's used to say
+                                    that we should break later. We've checked all
+                                    possible newline combinations even across buffer
+                                    boundaries. */
+                }
                 count++;
                 *(sItr++) = *(alias++);
             }
@@ -567,7 +592,7 @@ ufile_getch(UFILE *f, UChar *ch)
         *ch = *(f->str.fPos)++;
         isValidChar = TRUE;
     }
-    else if (f) {
+    else {
         /* otherwise, fill the buffer and return the next character */
         if(f->str.fPos >= f->str.fLimit) {
             ufile_fill_uchar_buffer(f);