1112758Ssam/*-
2112758Ssam * Copyright (c) 2002, 2003 Tim J. Robbins
3112758Ssam * All rights reserved.
4112758Ssam *
5112758Ssam * Copyright (c) 2011 The FreeBSD Foundation
6112758Ssam * All rights reserved.
7112758Ssam * Portions of this software were developed by David Chisnall
8112758Ssam * under sponsorship from the FreeBSD Foundation.
9112758Ssam *
10112758Ssam * Redistribution and use in source and binary forms, with or without
11112758Ssam * modification, are permitted provided that the following conditions
12112758Ssam * are met:
13112758Ssam * 1. Redistributions of source code must retain the above copyright
14112758Ssam *    notice, this list of conditions and the following disclaimer.
15112758Ssam * 2. Redistributions in binary form must reproduce the above copyright
16112758Ssam *    notice, this list of conditions and the following disclaimer in the
17112758Ssam *    documentation and/or other materials provided with the distribution.
18112758Ssam *
19112758Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20112758Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21112758Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22112758Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23112758Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24112758Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25112758Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26112758Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27112758Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28105197Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29105197Ssam * SUCH DAMAGE.
30105197Ssam */
31105197Ssam
32105197Ssam#include <sys/cdefs.h>
33105197Ssam__FBSDID("$FreeBSD$");
34105197Ssam
35159965Sthompsa#include <stdlib.h>
36105197Ssam#include <wchar.h>
37105197Ssam#include <wctype.h>
38105197Ssam#include "xlocale_private.h"
39105197Ssam
40105197Ssam/*
41105197Ssam * See wcstod() for comments as to the logic used.
42105197Ssam */
43105197Ssamlong double
44105197Ssamwcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
45105197Ssam		locale_t locale)
46105197Ssam{
47171497Sbz	static const mbstate_t initial;
48195699Srwatson	mbstate_t mbs;
49105197Ssam	long double val;
50105197Ssam	char *buf, *end;
51105197Ssam	const wchar_t *wcp = nptr;
52105197Ssam	size_t len;
53105197Ssam	size_t spaces = 0;
54105197Ssam	FIX_LOCALE(locale);
55105197Ssam
56105197Ssam	while (iswspace_l(*wcp, locale)) {
57105197Ssam		wcp++;
58105197Ssam		spaces++;
59105197Ssam	}
60105197Ssam
61105197Ssam	wcp = nptr;
62105197Ssam	mbs = initial;
63105197Ssam	if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
64105197Ssam		if (endptr != NULL)
65105197Ssam			*endptr = (wchar_t *)nptr;
66105197Ssam		return (0.0);
67105197Ssam	}
68105197Ssam	if ((buf = malloc(len + 1)) == NULL)
69105197Ssam		return (0.0);
70105197Ssam	mbs = initial;
71105197Ssam	wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
72105197Ssam
73105197Ssam	val = strtold_l(buf, &end, locale);
74105197Ssam
75105197Ssam	if (endptr != NULL) {
76105197Ssam		/* XXX Assume each wide char is one byte. */
77105197Ssam		*endptr = (wchar_t *)nptr + (end - buf);
78105197Ssam		if (buf != end)
79105197Ssam			*endptr += spaces;
80105197Ssam	}
81105197Ssam
82105197Ssam	free(buf);
83105197Ssam
84105197Ssam	return (val);
85194062Svanhu}
86194062Svanhulong double
87194062Svanhuwcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
88194062Svanhu{
89181627Svanhu	return wcstold_l(nptr, endptr, __get_locale());
90181627Svanhu}
91181627Svanhu