103b716c4STim J. Robbins /*- 203b716c4STim J. Robbins * Copyright (c) 2002 Tim J. Robbins 303b716c4STim J. Robbins * All rights reserved. 403b716c4STim J. Robbins * 503b716c4STim J. Robbins * Redistribution and use in source and binary forms, with or without 603b716c4STim J. Robbins * modification, are permitted provided that the following conditions 703b716c4STim J. Robbins * are met: 803b716c4STim J. Robbins * 1. Redistributions of source code must retain the above copyright 903b716c4STim J. Robbins * notice, this list of conditions and the following disclaimer. 1003b716c4STim J. Robbins * 2. Redistributions in binary form must reproduce the above copyright 1103b716c4STim J. Robbins * notice, this list of conditions and the following disclaimer in the 1203b716c4STim J. Robbins * documentation and/or other materials provided with the distribution. 1303b716c4STim J. Robbins * 1403b716c4STim J. Robbins * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1503b716c4STim J. Robbins * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1603b716c4STim J. Robbins * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1703b716c4STim J. Robbins * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1803b716c4STim J. Robbins * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1903b716c4STim J. Robbins * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2003b716c4STim J. Robbins * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2103b716c4STim J. Robbins * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2203b716c4STim J. Robbins * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2303b716c4STim J. Robbins * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2403b716c4STim J. Robbins * SUCH DAMAGE. 2503b716c4STim J. Robbins */ 2603b716c4STim J. Robbins 2703b716c4STim J. Robbins #include <sys/cdefs.h> 2803b716c4STim J. Robbins __FBSDID("$FreeBSD$"); 2903b716c4STim J. Robbins 3003b716c4STim J. Robbins #include <stdlib.h> 3103b716c4STim J. Robbins #include <wchar.h> 3203b716c4STim J. Robbins #include <wctype.h> 3303b716c4STim J. Robbins 3403b716c4STim J. Robbins /* 3503b716c4STim J. Robbins * Convert a string to a double-precision number. 3603b716c4STim J. Robbins * 3703b716c4STim J. Robbins * This is the wide-character counterpart of strtod(). So that we do not 3803b716c4STim J. Robbins * have to duplicate the code of strtod() here, we convert the supplied 3903b716c4STim J. Robbins * wide character string to multibyte and call strtod() on the result. 4003b716c4STim J. Robbins * This assumes that the multibyte encoding is compatible with ASCII 4103b716c4STim J. Robbins * for at least the digits, radix character and letters. 4203b716c4STim J. Robbins */ 4303b716c4STim J. Robbins double 4403b716c4STim J. Robbins wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) 4503b716c4STim J. Robbins { 4603b716c4STim J. Robbins double val; 471e8742e9STim J. Robbins char *buf, *end; 4803b716c4STim J. Robbins const wchar_t *wcp; 491e8742e9STim J. Robbins size_t len; 5003b716c4STim J. Robbins 5103b716c4STim J. Robbins while (iswspace(*nptr)) 5203b716c4STim J. Robbins nptr++; 5303b716c4STim J. Robbins 5403b716c4STim J. Robbins /* 5503b716c4STim J. Robbins * Convert the supplied numeric wide char. string to multibyte. 5603b716c4STim J. Robbins * 5703b716c4STim J. Robbins * We could attempt to find the end of the numeric portion of the 5803b716c4STim J. Robbins * wide char. string to avoid converting unneeded characters but 5903b716c4STim J. Robbins * choose not to bother; optimising the uncommon case where 6003b716c4STim J. Robbins * the input string contains a lot of text after the number 6103b716c4STim J. Robbins * duplicates a lot of strtod()'s functionality and slows down the 6203b716c4STim J. Robbins * most common cases. 631e8742e9STim J. Robbins * 641e8742e9STim J. Robbins * We pass NULL as the state pointer to wcrtomb() because we don't 651e8742e9STim J. Robbins * support state-dependent encodings and don't want to waste time 661e8742e9STim J. Robbins * creating a zeroed mbstate_t that will not be used. 6703b716c4STim J. Robbins */ 6803b716c4STim J. Robbins wcp = nptr; 691e8742e9STim J. Robbins if ((len = wcsrtombs(NULL, &wcp, 0, NULL)) == (size_t)-1) { 7003b716c4STim J. Robbins if (endptr != NULL) 7103b716c4STim J. Robbins *endptr = (wchar_t *)nptr; 7203b716c4STim J. Robbins return (0.0); 7303b716c4STim J. Robbins } 7403b716c4STim J. Robbins if ((buf = malloc(len + 1)) == NULL) 7503b716c4STim J. Robbins return (0.0); 761e8742e9STim J. Robbins wcsrtombs(buf, &wcp, len + 1, NULL); 7703b716c4STim J. Robbins 7803b716c4STim J. Robbins /* Let strtod() do most of the work for us. */ 7903b716c4STim J. Robbins val = strtod(buf, &end); 8003b716c4STim J. Robbins 8103b716c4STim J. Robbins /* 8203b716c4STim J. Robbins * We only know where the number ended in the _multibyte_ 8303b716c4STim J. Robbins * representation of the string. If the caller wants to know 8403b716c4STim J. Robbins * where it ended, count multibyte characters to find the 8503b716c4STim J. Robbins * corresponding position in the wide char string. 8603b716c4STim J. Robbins */ 871e8742e9STim J. Robbins if (endptr != NULL) 881e8742e9STim J. Robbins /* XXX Assume each wide char is one byte. */ 8903b716c4STim J. Robbins *endptr = (wchar_t *)nptr + (end - buf); 9003b716c4STim J. Robbins 9103b716c4STim J. Robbins free(buf); 9203b716c4STim J. Robbins 9303b716c4STim J. Robbins return (val); 9403b716c4STim J. Robbins } 95