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 #ifndef _REENT_ONLY
48 
49 #include <newlib.h>
50 #include <stdlib.h>
51 #include <wchar.h>
52 #include "local.h"
53 
54 size_t
wcstombs(char * __restrict s,const wchar_t * __restrict pwcs,size_t n)55 wcstombs (char          *__restrict s,
56         const wchar_t *__restrict pwcs,
57         size_t         n)
58 {
59 #ifdef _MB_CAPABLE
60   mbstate_t state;
61   state.__count = 0;
62 
63   char *ptr = s;
64   size_t max = n;
65   char buff[8];
66   int i, bytes, num_to_copy;
67 
68   if (s == NULL)
69     {
70       size_t num_bytes = 0;
71       while (*pwcs != 0)
72 	{
73 	  bytes = __WCTOMB (buff, *pwcs++, &state);
74 	  if (bytes == -1)
75 	    return -1;
76 	  num_bytes += bytes;
77 	}
78       return num_bytes;
79     }
80   else
81     {
82       while (n > 0)
83         {
84           bytes = __WCTOMB (buff, *pwcs, &state);
85           if (bytes == -1)
86             return -1;
87           num_to_copy = (n > (size_t) bytes ? bytes : (int)n);
88           for (i = 0; i < num_to_copy; ++i)
89             *ptr++ = buff[i];
90 
91           if (*pwcs == 0x00)
92             return ptr - s - (n >= (size_t) bytes);
93           ++pwcs;
94           n -= num_to_copy;
95         }
96       return max;
97     }
98 #else /* not _MB_CAPABLE */
99   int count = 0;
100 
101   if (n != 0) {
102     do {
103       if ((*s++ = (char) *pwcs++) == 0)
104 	break;
105       count++;
106     } while (--n != 0);
107   }
108 
109   return count;
110 #endif /* not _MB_CAPABLE */
111 }
112 
113 #endif /* !_REENT_ONLY */
114