xref: /illumos-gate/usr/src/lib/libc/port/locale/mbftowc.c (revision 5aec55eb)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
14  */
15 
16 #include "lint.h"
17 #include <stdlib.h>
18 #include <string.h>
19 #include <wchar.h>
20 
21 /*
22  * This function is apparently referenced by parts of ON.  It is
23  * not intended for public API usage -- and it is not documented.
24  *
25  * The usage appears to be to consume bytes until a character is
26  * gathered, using a supplied function.   It reads exactly one
27  * character and returns the number of bytes in the multibyte string
28  * that were consumed.
29  *
30  * The string "s" is storage for the multibyte string, the
31  * wc will receive the interpreted character, the peek function
32  * obtains the next character (as an int so we can get EOF),
33  * and errorc is stuffed with the character that is responsible
34  * for a parse error, if any.
35  */
36 
37 int
_mbftowc(char * s,wchar_t * wc,int (* peek)(void),int * errorc)38 _mbftowc(char *s, wchar_t *wc, int (*peek)(void), int *errorc)
39 {
40 	int		c;
41 	mbstate_t	mbs;
42 	char		*start = s;
43 	size_t		cons = 0;
44 
45 	for (;;) {
46 		c = peek();
47 		if (c < 0) {
48 			/* No bytes returned? */
49 			return (s - start);
50 		}
51 
52 		*s = (char)c;
53 		s++;
54 
55 		(void) memset(&mbs, 0, sizeof (mbs));
56 		cons = mbrtowc(wc, start, s - start, &mbs);
57 		if ((int)cons >= 0) {
58 			/* fully translated character */
59 			return (cons);
60 		}
61 		if (cons == (size_t)-2) {
62 			/* incomplete, recycle */
63 			continue;
64 		}
65 
66 		/*
67 		 * Parse error, don't consider the first character part
68 		 * of the error.
69 		 */
70 		s--;
71 		cons = (s - start);
72 		*errorc = c >= 0 ?  c : 0;
73 		break;
74 	}
75 
76 	return (cons);
77 }
78