home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / extra / ustdio / ustdio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-07  |  8.2 KB  |  339 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright International Business Machines Corporation, 1998           *
  6. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  7. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  8. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  9. *                                                                             *
  10. *******************************************************************************
  11. *
  12. * File ustdio.c
  13. *
  14. * Modification History:
  15. *
  16. *   Date        Name        Description
  17. *   11/18/98    stephen     Creation.
  18. *   03/12/99    stephen     Modified for new C API.
  19. *   07/19/99    stephen     Fixed read() and gets()
  20. *******************************************************************************
  21. */
  22.  
  23. #include "ustdio.h"
  24. #include "ufile.h"
  25. #include "ufmt_cmn.h"
  26. #include "ucnv.h"
  27. #include "ustring.h"
  28.  
  29. #include <string.h>
  30.  
  31. static const UChar DELIMITERS [] = { 0x000A, 0x0000 };
  32.  
  33. #define DELIM_CR 0x000D
  34. #define DELIM_LF 0x000A
  35.  
  36. #define IS_STRING_DELIMITER(s)    (bool_t)(    (s) == DELIM_CR || \
  37.                         (s) == DELIM_LF    )
  38.  
  39.  
  40. /* Input/output */
  41.  
  42. int32_t
  43. u_fputs(const UChar    *s,
  44.     UFILE        *f)
  45. {
  46.   int32_t count = u_file_write(s, u_strlen(s), f);
  47.   count += u_file_write(DELIMITERS, u_strlen(DELIMITERS), f);
  48.   return count;
  49. }
  50.  
  51. int32_t
  52. u_fputc(UChar        uc,
  53.     UFILE        *f)
  54. {
  55.   return u_file_write(&uc, 1, f) == 1 ? uc : EOF;
  56. }
  57.  
  58. int32_t
  59. u_file_write(    const UChar     *chars, 
  60.         int32_t        count, 
  61.         UFILE         *f)
  62. {
  63.   /* Set up conversion parameters */
  64.   UErrorCode         status        = U_ZERO_ERROR;
  65.   const UChar        *mySource       = chars;
  66.   const UChar        *sourceAlias       = chars;
  67.   const UChar        *mySourceEnd     = chars + count;
  68.   char            *myTarget     = f->fCharBuffer;
  69.   int32_t        bufferSize    = UFILE_CHARBUFFER_SIZE;
  70.   int32_t        written        = 0;
  71.  
  72.   /* Perform the conversion in a loop */
  73.   do {
  74.     status     = U_ZERO_ERROR;
  75.     sourceAlias = mySource;
  76.     
  77.     ucnv_fromUnicode(f->fConverter,
  78.              &myTarget, 
  79.              f->fCharBuffer + bufferSize,
  80.              &mySource,
  81.              mySourceEnd,
  82.              NULL,
  83.              TRUE,
  84.              &status);
  85.  
  86.     /* write the converted bytes */
  87.     fwrite(f->fCharBuffer, 
  88.        sizeof(char), 
  89.        myTarget - f->fCharBuffer, 
  90.        f->fFile);
  91.     
  92.     written     += (myTarget - f->fCharBuffer);
  93.     myTarget     = f->fCharBuffer;
  94.   }
  95.   while(status == U_INDEX_OUTOFBOUNDS_ERROR); 
  96.  
  97.   /* return # of chars written */
  98.   return written;
  99. }
  100.  
  101. /* private function used for buffering input */
  102. void
  103. ufile_fill_uchar_buffer(UFILE *f)
  104. {
  105.   UErrorCode         status;
  106.   const char        *mySource;
  107.   const char        *mySourceEnd;
  108.   UChar            *myTarget;
  109.   int32_t        bufferSize;
  110.   int32_t        maxCPBytes;
  111.   int32_t        bytesRead;
  112.   int32_t        availLength;
  113.   int32_t        dataSize;
  114.  
  115.  
  116.   /* shift the buffer if it isn't empty */
  117.   dataSize = f->fUCLimit - f->fUCPos;
  118.   if(dataSize != 0) {
  119.     memmove(f->fUCBuffer, 
  120.         f->fUCPos, 
  121.         dataSize * sizeof(UChar));
  122.   }
  123.   
  124.   /* record how much buffer space is available */
  125.   availLength = UFILE_UCHARBUFFER_SIZE - dataSize;
  126.   
  127.   /* Determine the # of codepage bytes needed to fill our UChar buffer */
  128.   maxCPBytes = availLength * ucnv_getMaxCharSize(f->fConverter);
  129.   
  130.   /* Read in the data to convert */
  131.   bytesRead = fread(f->fCharBuffer, 
  132.             sizeof(char), 
  133.             ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), 
  134.             f->fFile);
  135.   
  136.   /* Set up conversion parameters */
  137.   status    = U_ZERO_ERROR;
  138.   mySource       = f->fCharBuffer;
  139.   mySourceEnd     = f->fCharBuffer + bytesRead;
  140.   myTarget     = f->fUCBuffer + dataSize;
  141.   bufferSize    = UFILE_UCHARBUFFER_SIZE;
  142.  
  143.   /* Perform the conversion */
  144.   ucnv_toUnicode(f->fConverter,
  145.          &myTarget, 
  146.          f->fUCBuffer + bufferSize,
  147.          &mySource,
  148.          mySourceEnd,
  149.          NULL,
  150.          TRUE,
  151.          &status);
  152.   
  153.   /* update the pointers into our array */
  154.   f->fUCPos    = f->fUCBuffer;
  155.   f->fUCLimit     = myTarget;
  156. }
  157.  
  158. UChar*
  159. u_fgets(UFILE        *f,
  160.     int32_t        n,
  161.     UChar        *s)
  162. {
  163.   int32_t dataSize;
  164.   int32_t read;
  165.   int32_t count;
  166.   UChar *alias;
  167.  
  168.     
  169.   /* fill the buffer */
  170.   ufile_fill_uchar_buffer(f);
  171.  
  172.   /* subtract 1 from n to compensate for the terminator */
  173.   --n;
  174.  
  175.   /* determine the amount of data in the buffer */
  176.   dataSize = f->fUCLimit - f->fUCPos;
  177.  
  178.   /* if the buffer contains more data than requested, operate on the buffer */
  179.   if(dataSize > n) {
  180.  
  181.     /* find the first occurrence of a delimiter character */
  182.     alias = f->fUCPos;
  183.     count = 0;
  184.     while( ! IS_STRING_DELIMITER(*alias) && count < n) {
  185.       ++count;
  186.       *alias++;
  187.     }
  188.  
  189.     /* copy the characters into the target*/
  190.     memcpy(s, f->fUCPos, count * sizeof(UChar));
  191.  
  192.     /* add the terminator */
  193.     s[count] = 0x0000;
  194.  
  195.     /* update the current buffer position */
  196.     f->fUCPos += count;
  197.  
  198.     /* refill the buffer */
  199.     ufile_fill_uchar_buffer(f);
  200.     
  201.     /* skip over any remaining delimiters */
  202.     while(IS_STRING_DELIMITER(*(f->fUCPos)) && f->fUCPos < f->fUCLimit)
  203.       *(f->fUCPos)++;
  204.     
  205.     /* return s */
  206.     return s;
  207.   }
  208.  
  209.   /* otherwise, iteratively fill the buffer and copy */
  210.   read = 0;
  211.   do {
  212.         
  213.     /* determine the amount of data in the buffer */
  214.     dataSize = f->fUCLimit - f->fUCPos;
  215.  
  216.     /* find the first occurrence of a delimiter character, if present */
  217.     alias = f->fUCPos;
  218.     count = 0;
  219.     while( ! IS_STRING_DELIMITER(*alias) && alias < f->fUCLimit && count < n) {
  220.       ++count;
  221.       *alias++;
  222.     }
  223.     
  224.     /* copy the current data in the buffer */
  225.     memcpy(s + read, f->fUCPos, count * sizeof(UChar));
  226.     
  227.     /* update number of items read */
  228.     read += count;
  229.  
  230.     /* update the current buffer position */
  231.     f->fUCPos += count;
  232.  
  233.     /* if we found a delimiter */
  234.     if(alias < f->fUCLimit) {
  235.  
  236.       /* refill the buffer */
  237.       ufile_fill_uchar_buffer(f);
  238.       
  239.       /* skip over any remaining delimiters */
  240.       while(IS_STRING_DELIMITER(*(f->fUCPos)) && f->fUCPos < f->fUCLimit)
  241.     *(f->fUCPos)++;
  242.       
  243.       /* break out */
  244.       break;
  245.     }
  246.  
  247.     /* refill the buffer */
  248.     ufile_fill_uchar_buffer(f);
  249.  
  250.   } while(dataSize != 0 && read < n);
  251.  
  252.   /* if 0 characters were read, return 0 */
  253.   if(read == 0)
  254.     return 0;
  255.  
  256.   /* add the terminator and return s */
  257.   s[read] = 0x0000;
  258.   return s;
  259. }
  260.  
  261. UChar
  262. u_fgetc(UFILE        *f)
  263. {
  264.   /* if we have an available character in the buffer, return it */
  265.   if(f->fUCPos < f->fUCLimit)
  266.     return *(f->fUCPos)++;
  267.   /* otherwise, fill the buffer and return the next character */
  268.   else {
  269.     ufile_fill_uchar_buffer(f);
  270.     if(f->fUCPos < f->fUCLimit)
  271.       return *(f->fUCPos)++;
  272.     else
  273.       return 0xFFFF;
  274.   }
  275. }
  276.  
  277. UChar
  278. u_fungetc(UChar        c,
  279.       UFILE        *f)
  280. {
  281.   /* if we're at the beginning of the buffer, sorry! */
  282.   if(f->fUCPos == f->fUCBuffer)
  283.     return 0xFFFF;
  284.   /* otherwise, put the character back */
  285.   else {
  286.     *--(f->fUCPos) = c;
  287.     return c;
  288.   }
  289. }
  290.  
  291. int32_t
  292. u_file_read(    UChar        *chars, 
  293.         int32_t        count, 
  294.         UFILE         *f)
  295. {
  296.   int32_t dataSize;
  297.   int32_t read;
  298.  
  299.   /* fill the buffer */
  300.   ufile_fill_uchar_buffer(f);
  301.  
  302.   /* determine the amount of data in the buffer */
  303.   dataSize = f->fUCLimit - f->fUCPos;
  304.  
  305.   /* if the buffer contains the amount requested, just copy */
  306.   if(dataSize > count) {
  307.     memcpy(chars, f->fUCPos, count * sizeof(UChar));
  308.  
  309.     /* update the current buffer position */
  310.     f->fUCPos += count;
  311.  
  312.     /* return # of chars read */
  313.     return count;
  314.   }
  315.  
  316.   /* otherwise, iteratively fill the buffer and copy */
  317.   read = 0;
  318.   do {
  319.     
  320.     /* determine the amount of data in the buffer */
  321.     dataSize = f->fUCLimit - f->fUCPos;
  322.  
  323.     /* copy the current data in the buffer */
  324.     memcpy(chars + read, f->fUCPos, dataSize * sizeof(UChar));
  325.     
  326.     /* update number of items read */
  327.     read += dataSize;
  328.  
  329.     /* update the current buffer position */
  330.     f->fUCPos += dataSize;
  331.  
  332.     /* refill the buffer */
  333.     ufile_fill_uchar_buffer(f);
  334.  
  335.   } while(dataSize != 0 && read < count);
  336.   
  337.   return read;
  338. }
  339.