Multibyte Conversion Example (The GNU C Library)

#### 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;
    }