Multibyte Conversion Example - The GNU C Library

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 (buffer, inp, filled);
             }

           return 1;
         }