1/*	$OpenBSD: _wcstod.h,v 1.4 2015/10/01 02:32:07 guenther Exp $	*/
2/* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */
3
4/*-
5 * Copyright (c)1999, 2000, 2001 Citrus Project,
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $
30 */
31
32/*
33 * function template for wcstof, wcstod and wcstold.
34 *
35 * parameters:
36 *	FUNCNAME : function name
37 *      float_type : return type
38 *      STRTOD_FUNC : conversion function
39 */
40
41float_type
42FUNCNAME(const wchar_t *nptr, wchar_t **endptr)
43{
44	const wchar_t *src;
45	size_t size;
46	const wchar_t *start;
47	const wchar_t *aftersign;
48
49	/*
50	 * check length of string and call strtod
51	 */
52	src = nptr;
53
54	/* skip space first */
55	while (iswspace(*src)) {
56		src++;
57	}
58
59	/* get length of string */
60	start = src;
61	if (*src && wcschr(L"+-", *src))
62		src++;
63	aftersign = src;
64	if (wcsncasecmp(src, L"inf", 3) == 0) {
65		src += 3;
66		if (wcsncasecmp(src, L"inity", 5) == 0)
67			src += 5;
68		goto match;
69	}
70	if (wcsncasecmp(src, L"nan", 3) == 0) {
71		src += 3;
72		if (*src == L'(') {
73			size = 1;
74			while (src[size] != L'\0' && src[size] != L')')
75				size++;
76			if (src[size] == L')')
77				src += size + 1;
78		}
79		goto match;
80	}
81	size = wcsspn(src, L"0123456789");
82	src += size;
83	if (*src == L'.') {/* XXX use localeconv */
84		src++;
85		size = wcsspn(src, L"0123456789");
86		src += size;
87	}
88	if (*src && wcschr(L"Ee", *src)) {
89		src++;
90		if (*src && wcschr(L"+-", *src))
91			src++;
92		size = wcsspn(src, L"0123456789");
93		src += size;
94	}
95match:
96	size = src - start;
97
98	/*
99	 * convert to a char-string and pass it to strtod.
100	 */
101	if (src > aftersign) {
102		mbstate_t st;
103		char *buf;
104		char *end;
105		const wchar_t *s;
106		size_t size_converted;
107		float_type result;
108		size_t bufsize;
109
110		s = start;
111		memset(&st, 0, sizeof(st));
112		bufsize = wcsnrtombs(NULL, &s, size, 0, &st);
113
114		buf = malloc(bufsize + 1);
115		if (!buf) {
116			errno = ENOMEM; /* XXX */
117			goto fail;
118		}
119
120		s = start;
121		memset(&st, 0, sizeof(st));
122		size_converted = wcsnrtombs(buf, &s, size, bufsize, &st);
123		if (size_converted != bufsize) {
124			/* XXX should not happen */
125			free(buf);
126			errno = EILSEQ;
127			goto fail;
128		}
129
130		buf[bufsize] = 0;
131		result = STRTOD_FUNC(buf, &end);
132
133		if (endptr) {
134			const char *s = buf;
135			memset(&st, 0, sizeof(st));
136			size = mbsnrtowcs(NULL, &s, end - buf, 0, &st);
137			*endptr = (wchar_t*)start + size;
138		}
139
140		free(buf);
141
142		return result;
143	}
144
145fail:
146	if (endptr)
147		*endptr = (wchar_t*)nptr;
148
149	return 0;
150}
151DEF_STRONG(FUNCNAME);
152