Previous: Converting Strings, Up: Restartable multibyte conversion


6.3.5 A Complete Multibyte Conversion Example

The example programs given in the last sections are only brief and do not contain all the error checking, etc. Presented here is a complete and documented example. It features the mbrtowc function but it should be easy to derive versions using the other functions.

     int
     file_mbsrtowcs (int input, int output)
     {
       /* Note the use of MB_LEN_MAX.
          MB_CUR_MAX cannot portably be used here.  */
       char buffer[BUFSIZ + MB_LEN_MAX];
       mbstate_t state;
       int filled = 0;
       int eof = 0;
     
       /* Initialize the state.  */
       memset (&state, '\0', sizeof (state));
     
       while (!eof)
         {
           ssize_t nread;
           ssize_t nwrite;
           char *inp = buffer;
           wchar_t outbuf[BUFSIZ];
           wchar_t *outp = outbuf;
     
           /* Fill up the buffer from the input file.  */
           nread = read (input, buffer + filled, BUFSIZ);
           if (nread < 0)
             {
               perror ("read");
               return 0;
             }
           /* If we reach end of file, make a note to read no more. */
           if (nread == 0)
             eof = 1;
     
           /* filled is now the number of bytes in buffer. */
           filled += nread;
     
           /* Convert those bytes to wide characters--as many as we can. */
           while (1)
             {
               size_t thislen = mbrtowc (outp, inp, filled, &state);
               /* Stop converting at invalid character;
                  this can mean we have read just the first part
                  of a valid character.  */
               if (thislen == (size_t) -1)
                 break;
               /* We want to handle embedded NUL bytes
                  but the return value is 0.  Correct this.  */
               if (thislen == 0)
                 thislen = 1;
               /* Advance past this character. */
               inp += thislen;
               filled -= thislen;
               ++outp;
             }
     
           /* Write the wide characters we just made.  */
           nwrite = write (output, outbuf,
                           (outp - outbuf) * sizeof (wchar_t));
           if (nwrite < 0)
             {
               perror ("write");
               return 0;
             }
     
           /* See if we have a real invalid character. */
           if ((eof && filled > 0) || filled >= MB_CUR_MAX)
             {
               error (0, 0, "invalid multibyte character");
               return 0;
             }
     
           /* If any characters must be carried forward,
              put them at the beginning of buffer. */
           if (filled > 0)
             memmove (inp, buffer, filled);
         }
     
       return 1;
     }