Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

ustdio.c

00001 /*
00002 *******************************************************************************
00003 *
00004 *   Copyright (C) 1998-1999, International Business Machines
00005 *   Corporation and others.  All Rights Reserved.
00006 *
00007 *******************************************************************************
00008 *
00009 * File ustdio.c
00010 *
00011 * Modification History:
00012 *
00013 *   Date        Name        Description
00014 *   11/18/98    stephen     Creation.
00015 *   03/12/99    stephen     Modified for new C API.
00016 *   07/19/99    stephen     Fixed read() and gets()
00017 *******************************************************************************
00018 */
00019 
00020 #include "unicode/ustdio.h"
00021 #include "ufile.h"
00022 #include "ufmt_cmn.h"
00023 #include "unicode/ucnv.h"
00024 #include "unicode/ustring.h"
00025 
00026 #include <string.h>
00027 
00028 static const UChar DELIMITERS [] = { 0x000A, 0x0000 };
00029 
00030 #define DELIM_CR 0x000D
00031 #define DELIM_LF 0x000A
00032 
00033 #define IS_STRING_DELIMITER(s)    (UBool)(    (s) == DELIM_CR || \
00034                         (s) == DELIM_LF    )
00035 
00036 
00037 /* Input/output */
00038 
00039 int32_t
00040 u_fputs(const UChar    *s,
00041     UFILE        *f)
00042 {
00043   int32_t count = u_file_write(s, u_strlen(s), f);
00044   count += u_file_write(DELIMITERS, u_strlen(DELIMITERS), f);
00045   return count;
00046 }
00047 
00048 int32_t
00049 u_fputc(UChar        uc,
00050     UFILE        *f)
00051 {
00052   return u_file_write(&uc, 1, f) == 1 ? uc : EOF;
00053 }
00054 
00055 int32_t
00056 u_file_write(    const UChar     *chars, 
00057         int32_t        count, 
00058         UFILE         *f)
00059 {
00060   /* Set up conversion parameters */
00061   UErrorCode         status        = U_ZERO_ERROR;
00062   const UChar        *mySource       = chars;
00063   const UChar        *sourceAlias       = chars;
00064   const UChar        *mySourceEnd     = chars + count;
00065   char            *myTarget     = f->fCharBuffer;
00066   int32_t        bufferSize    = UFILE_CHARBUFFER_SIZE;
00067   int32_t        written        = 0;
00068  
00069   /* Perform the conversion in a loop */
00070   do {
00071     status     = U_ZERO_ERROR;
00072     sourceAlias = mySource;
00073     if(f->fConverter != NULL) { /* We have a valid converter */
00074         ucnv_fromUnicode(f->fConverter,
00075                  &myTarget, 
00076                  f->fCharBuffer + bufferSize,
00077                  &mySource,
00078                  mySourceEnd,
00079                  NULL,
00080                  TRUE,
00081                  &status);
00082       } else { /*weiv: do the invariant conversion */
00083           u_UCharsToChars(mySource, myTarget, count);
00084           myTarget += count;
00085       }
00086 
00087     /* write the converted bytes */
00088     fwrite(f->fCharBuffer, 
00089        sizeof(char), 
00090        myTarget - f->fCharBuffer, 
00091        f->fFile);
00092     
00093     written     += (myTarget - f->fCharBuffer);
00094     myTarget     = f->fCharBuffer;
00095   }
00096   while(status == U_BUFFER_OVERFLOW_ERROR); 
00097 
00098   /* return # of chars written */
00099   return written;
00100 }
00101 
00102 /* private function used for buffering input */
00103 void
00104 ufile_fill_uchar_buffer(UFILE *f)
00105 {
00106   UErrorCode         status;
00107   const char        *mySource;
00108   const char        *mySourceEnd;
00109   UChar            *myTarget;
00110   int32_t        bufferSize;
00111   int32_t        maxCPBytes;
00112   int32_t        bytesRead;
00113   int32_t        availLength;
00114   int32_t        dataSize;
00115 
00116 
00117   /* shift the buffer if it isn't empty */
00118   dataSize = f->fUCLimit - f->fUCPos;
00119   if(dataSize != 0) {
00120     memmove(f->fUCBuffer, 
00121         f->fUCPos, 
00122         dataSize * sizeof(UChar));
00123   }
00124   
00125 
00126   /* record how much buffer space is available */
00127   availLength = UFILE_UCHARBUFFER_SIZE - dataSize;
00128   
00129   /* Determine the # of codepage bytes needed to fill our UChar buffer */
00130   /* weiv: if converter is NULL, we use invariant converter with charwidth = 1)*/
00131   maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1);
00132 
00133   /* Read in the data to convert */
00134   bytesRead = fread(f->fCharBuffer, 
00135             sizeof(char), 
00136             ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), 
00137             f->fFile);
00138 
00139   /* Set up conversion parameters */
00140   status    = U_ZERO_ERROR;
00141   mySource       = f->fCharBuffer;
00142   mySourceEnd     = f->fCharBuffer + bytesRead;
00143   myTarget     = f->fUCBuffer + dataSize;
00144   bufferSize    = UFILE_UCHARBUFFER_SIZE;
00145 
00146   if(f->fConverter != NULL) { /* We have a valid converter */
00147       /* Perform the conversion */
00148       ucnv_toUnicode(f->fConverter,
00149              &myTarget, 
00150              f->fUCBuffer + bufferSize,
00151              &mySource,
00152              mySourceEnd,
00153              NULL,
00154              (UBool)(feof(f->fFile) != 0),
00155              &status);
00156 
00157   } else { /*weiv: do the invariant conversion */
00158       u_charsToUChars(mySource, myTarget, bytesRead);
00159       myTarget += bytesRead;
00160   }
00161   
00162   /* update the pointers into our array */
00163   f->fUCPos    = f->fUCBuffer;
00164   f->fUCLimit     = myTarget;
00165 }
00166 
00167 UChar*
00168 u_fgets(UFILE        *f,
00169     int32_t        n,
00170     UChar        *s)
00171 {
00172   int32_t dataSize;
00173   int32_t read;
00174   int32_t count;
00175   UChar *alias;
00176 
00177     
00178   /* fill the buffer */
00179   ufile_fill_uchar_buffer(f);
00180 
00181   /* subtract 1 from n to compensate for the terminator */
00182   --n;
00183 
00184   /* determine the amount of data in the buffer */
00185   dataSize = f->fUCLimit - f->fUCPos;
00186 
00187   /* if the buffer contains more data than requested, operate on the buffer */
00188   if(dataSize > n) {
00189 
00190     /* find the first occurrence of a delimiter character */
00191     alias = f->fUCPos;
00192     count = 0;
00193     while( ! IS_STRING_DELIMITER(*alias) && count < n) {
00194       ++count;
00195       alias++;
00196     }
00197 
00198     /* copy the characters into the target*/
00199     memcpy(s, f->fUCPos, count * sizeof(UChar));
00200 
00201     /* add the terminator */
00202     s[count] = 0x0000;
00203 
00204     /* update the current buffer position */
00205     f->fUCPos += count;
00206 
00207     /* refill the buffer */
00208     ufile_fill_uchar_buffer(f);
00209     
00210     /* skip over any remaining delimiters */
00211     while(IS_STRING_DELIMITER(*(f->fUCPos)) && f->fUCPos < f->fUCLimit)
00212       (f->fUCPos)++;
00213     
00214     /* return s */
00215     return s;
00216   }
00217 
00218   /* otherwise, iteratively fill the buffer and copy */
00219   read = 0;
00220   do {
00221         
00222     /* determine the amount of data in the buffer */
00223     dataSize = f->fUCLimit - f->fUCPos;
00224 
00225     /* find the first occurrence of a delimiter character, if present */
00226     alias = f->fUCPos;
00227     count = 0;
00228     while( ! IS_STRING_DELIMITER(*alias) && alias < f->fUCLimit && count < n) {
00229       ++count;
00230       alias++;
00231     }
00232     
00233     /* copy the current data in the buffer */
00234     memcpy(s + read, f->fUCPos, count * sizeof(UChar));
00235     
00236     /* update number of items read */
00237     read += count;
00238 
00239     /* update the current buffer position */
00240     f->fUCPos += count;
00241 
00242     /* if we found a delimiter */
00243     if(alias < f->fUCLimit) {
00244 
00245       /* refill the buffer */
00246       ufile_fill_uchar_buffer(f);
00247 
00248       /* skip over any remaining delimiters */
00249       while(IS_STRING_DELIMITER(*(f->fUCPos)) && f->fUCPos < f->fUCLimit)
00250         (f->fUCPos)++;
00251 
00252       /* break out */
00253       break;
00254     }
00255 
00256     /* refill the buffer */
00257     ufile_fill_uchar_buffer(f);
00258 
00259   } while(dataSize != 0 && read < n);
00260 
00261   /* if 0 characters were read, return 0 */
00262   if(read == 0)
00263     return 0;
00264 
00265   /* add the terminator and return s */
00266   s[read] = 0x0000;
00267   return s;
00268 }
00269 
00270 UChar
00271 u_fgetc(UFILE        *f)
00272 {
00273   /* if we have an available character in the buffer, return it */
00274   if(f->fUCPos < f->fUCLimit)
00275     return *(f->fUCPos)++;
00276   /* otherwise, fill the buffer and return the next character */
00277   else {
00278     ufile_fill_uchar_buffer(f);
00279     if(f->fUCPos < f->fUCLimit)
00280       return *(f->fUCPos)++;
00281     else
00282       return 0xFFFF;
00283   }
00284 }
00285 
00286 /* u_unescapeAt() callback to return a UChar from a UFILE */
00287 static UChar _charAt(int32_t offset, void *context) {
00288     return ((UFILE*) context)->fUCPos[offset];
00289 }
00290 
00291 /* Read a UChar from a UFILE and process escape sequences */
00292 UChar32
00293 u_fgetcx(UFILE        *f) {
00294     int32_t length;
00295     int32_t offset;
00296     UChar32 c32;
00297     UChar c16;
00298     
00299     /* Fill the buffer if it is empty */
00300     if (f->fUCPos >= f->fUCLimit) {
00301         ufile_fill_uchar_buffer(f);        
00302     }
00303 
00304     /* Get the next character in the buffer */
00305     if (f->fUCPos < f->fUCLimit) {
00306         c16 = *(f->fUCPos)++;
00307     } else {
00308         c16 = U_EOF;
00309     }
00310 
00311     /* If it isn't a backslash, return it */
00312     if (c16 != 0x005C /*'\\'*/) {
00313         return c16;
00314     }
00315 
00316     /* Determine the amount of data in the buffer */
00317     length = f->fUCLimit - f->fUCPos;
00318 
00319     /* The longest escape sequence is \Uhhhhhhhh; make sure
00320        we have at least that many characters */
00321     if (length < 10) {
00322         /* fill the buffer */
00323         ufile_fill_uchar_buffer(f);
00324         length = f->fUCLimit - f->fUCPos;
00325     }
00326     
00327     /* Process the escape */
00328     offset = 0;
00329     c32 = u_unescapeAt(_charAt, &offset, length, (void*)f);
00330 
00331     /* Update the current buffer position */
00332     f->fUCPos += offset;
00333 
00334     return c32;
00335 }
00336 
00337 UChar
00338 u_fungetc(UChar        c,
00339       UFILE        *f)
00340 {
00341   /* if we're at the beginning of the buffer, sorry! */
00342   if(f->fUCPos == f->fUCBuffer)
00343     return 0xFFFF;
00344   /* otherwise, put the character back */
00345   else {
00346     *--(f->fUCPos) = c;
00347     return c;
00348   }
00349 }
00350 
00351 int32_t
00352 u_file_read(    UChar        *chars, 
00353         int32_t        count, 
00354         UFILE         *f)
00355 {
00356   int32_t dataSize;
00357   int32_t read;
00358 
00359   /* fill the buffer */
00360   ufile_fill_uchar_buffer(f);
00361 
00362   /* determine the amount of data in the buffer */
00363   dataSize = f->fUCLimit - f->fUCPos;
00364 
00365   /* if the buffer contains the amount requested, just copy */
00366   if(dataSize > count) {
00367     memcpy(chars, f->fUCPos, count * sizeof(UChar));
00368 
00369     /* update the current buffer position */
00370     f->fUCPos += count;
00371 
00372     /* return # of chars read */
00373     return count;
00374   }
00375 
00376   /* otherwise, iteratively fill the buffer and copy */
00377   read = 0;
00378   do {
00379     
00380     /* determine the amount of data in the buffer */
00381     dataSize = f->fUCLimit - f->fUCPos;
00382 
00383     /* copy the current data in the buffer */
00384     memcpy(chars + read, f->fUCPos, dataSize * sizeof(UChar));
00385     
00386     /* update number of items read */
00387     read += dataSize;
00388 
00389     /* update the current buffer position */
00390     f->fUCPos += dataSize;
00391 
00392     /* refill the buffer */
00393     ufile_fill_uchar_buffer(f);
00394 
00395   } while(dataSize != 0 && read < count);
00396   
00397   return read;
00398 }

Generated at Tue Dec 5 10:48:12 2000 for ICU by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000