Go to the previous, next section.

Character-by-Character Conversion Example

Here is an example that reads multibyte character text from descriptor input and writes the corresponding wide characters to descriptor output. We need to convert characters one by one for this example because mbstowcs is unable to continue past a null character, and cannot cope with an apparently invalid partial character by reading more input.

int
file_mbstowcs (int input, int output)
{
  char buffer[BUFSIZ + MB_LEN_MAX];
  int filled = 0;
  int eof = 0;

  while (!eof)
    {
      int nread;
      int 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)
        {
          int thislen = mbtowc (outp, inp, filled);
          /* Stop converting at invalid character;
             this can mean we have read just the first part
             of a valid character.  */
          if (thislen == -1)
            break;
          /* Treat null character like any other,
             but also reset shift state. */
          if (thislen == 0) {
            thislen = 1;
            mbtowc (NULL, NULL, 0);
          }
          /* 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 ("invalid multibyte character");
          return 0;
        }

      /* If any characters must be carried forward,
         put them at the beginning of buffer. */
      if (filled > 0)
        memcpy (inp, buffer, filled);
      }
    }

  return 1;
}

Go to the previous, next section.