1 /*
2 Copyright (c) 1990 Regents of the University of California.
3 All rights reserved.
4  */
5 /*
6 FUNCTION
7 <<wcstombs>>---minimal wide char string to multibyte string converter
8 
9 INDEX
10 	wcstombs
11 
12 SYNOPSIS
13 	#include <stdlib.h>
14 	size_t wcstombs(char *restrict <[s]>, const wchar_t *restrict <[pwc]>, size_t <[n]>);
15 
16 DESCRIPTION
17 When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming
18 implementation of <<wcstombs>>.  In this case,
19 all wide-characters are expected to represent single bytes and so
20 are converted simply by casting to char.
21 
22 When _MB_CAPABLE is defined, this routine uses a state variable to
23 allow state dependent decoding.  The result is based on the locale
24 setting which may be restricted to a defined set of locales.
25 
26 RETURNS
27 This implementation of <<wcstombs>> returns <<0>> if
28 <[s]> is <<NULL>> or is the empty string;
29 it returns <<-1>> if _MB_CAPABLE and one of the
30 wide-char characters does not represent a valid multi-byte character;
31 otherwise it returns the minimum of: <<n>> or the
32 number of bytes that are transferred to <<s>>, not including the
33 nul terminator.
34 
35 If the return value is -1, the state of the <<pwc>> string is
36 indeterminate.  If the input has a length of 0, the output
37 string will be modified to contain a wchar_t nul terminator if
38 <<n>> > 0.
39 
40 PORTABILITY
41 <<wcstombs>> is required in the ANSI C standard.  However, the precise
42 effects vary with the locale.
43 
44 <<wcstombs>> requires no supporting OS subroutines.
45 */
46 
47 #include <stdlib.h>
48 #include <wchar.h>
49 #include "local.h"
50 
51 size_t
wcstombs(char * __restrict s,const wchar_t * __restrict pwcs,size_t n)52 wcstombs (char          *__restrict s,
53         const wchar_t *__restrict pwcs,
54         size_t         n)
55 {
56 #ifdef _MB_CAPABLE
57   mbstate_t state;
58   state.__count = 0;
59 
60   char *ptr = s;
61   size_t max = n;
62   char buff[8];
63   int i, bytes, num_to_copy;
64 
65   if (s == NULL)
66     {
67       size_t num_bytes = 0;
68       while (*pwcs != 0)
69 	{
70 	  bytes = __WCTOMB (buff, *pwcs++, &state);
71 	  if (bytes == -1)
72 	    return -1;
73 	  num_bytes += bytes;
74 	}
75       return num_bytes;
76     }
77   else
78     {
79       while (n > 0)
80         {
81           bytes = __WCTOMB (buff, *pwcs, &state);
82           if (bytes == -1)
83             return -1;
84           num_to_copy = (n > (size_t) bytes ? bytes : (int)n);
85           for (i = 0; i < num_to_copy; ++i)
86             *ptr++ = buff[i];
87 
88           if (*pwcs == 0x00)
89             return ptr - s - (n >= (size_t) bytes);
90           ++pwcs;
91           n -= num_to_copy;
92         }
93       return max;
94     }
95 #else /* not _MB_CAPABLE */
96   int count = 0;
97 
98   if (n != 0) {
99     do {
100       if ((*s++ = (char) *pwcs++) == 0)
101 	break;
102       count++;
103     } while (--n != 0);
104   }
105 
106   return count;
107 #endif /* not _MB_CAPABLE */
108 }
109