/* $NetBSD: _wcstod.h,v 1.1 2006/04/15 12:17:23 tnozaki Exp $ */ | |
/*- | |
* Copyright (c) 2002 Tim J. Robbins | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
* | |
* Original version ID: | |
* FreeBSD: /repoman/r/ncvs/src/lib/libc/locale/wcstod.c,v 1.4 2004/04/07 09:47:56 tjr Exp | |
* NetBSD: wcstod.c,v 1.8 2006/04/13 01:25:13 tnozaki Exp | |
*/ | |
/* | |
* function template for wcstof, wcstod, wcstold. | |
* | |
* parameters: | |
* _FUNCNAME : function name | |
* _RETURN_TYPE : return type | |
* _STRTOD_FUNC : real conversion function | |
*/ | |
#ifndef __WCSTOD_H_ | |
#define __WCSTOD_H_ | |
/* | |
* Convert a string to a double-precision number. | |
* | |
* This is the wide-character counterpart of strto{f,d,ld}(). So that | |
* we do not have to duplicate the code of strto{f,d,ld}() here, | |
* we convert the supplied wide character string to multibyte and | |
* call strto{f,d,ld}() on the result. | |
* This assumes that the multibyte encoding is compatible with ASCII | |
* for at least the digits, radix character and letters. | |
*/ | |
_RETURN_TYPE | |
_FUNCNAME(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) | |
{ | |
const wchar_t *src, *start; | |
_RETURN_TYPE val; | |
char *buf, *end; | |
size_t bufsiz, len; | |
_DIAGASSERT(nptr != NULL); | |
/* endptr may be null */ | |
src = nptr; | |
while (iswspace((wint_t)*src) != 0) | |
++src; | |
if (*src == L'\0') | |
goto no_convert; | |
/* | |
* Convert the supplied numeric wide char. string to multibyte. | |
* | |
* We could attempt to find the end of the numeric portion of the | |
* wide char. string to avoid converting unneeded characters but | |
* choose not to bother; optimising the uncommon case where | |
* the input string contains a lot of text after the number | |
* duplicates a lot of strto{f,d,ld}()'s functionality and | |
* slows down the most common cases. | |
*/ | |
start = src; | |
len = wcstombs(NULL, src, 0); | |
if (len == (size_t)-1) | |
/* errno = EILSEQ */ | |
goto no_convert; | |
_DIAGASSERT(len > 0); | |
bufsiz = len; | |
buf = (void *)malloc(bufsiz + 1); | |
if (buf == NULL) | |
/* errno = ENOMEM */ | |
goto no_convert; | |
len = wcstombs(buf, src, bufsiz + 1); | |
_DIAGASSERT(len == bufsiz); | |
_DIAGASSERT(buf[len] == '\0'); | |
/* Let strto{f,d,ld}() do most of the work for us. */ | |
val = _STRTOD_FUNC(buf, &end); | |
if (buf == end) { | |
free(buf); | |
goto no_convert; | |
} | |
/* | |
* We only know where the number ended in the _multibyte_ | |
* representation of the string. If the caller wants to know | |
* where it ended, count multibyte characters to find the | |
* corresponding position in the wide char string. | |
*/ | |
if (endptr != NULL) | |
/* XXX Assume each wide char is one byte. */ | |
*endptr = __UNCONST(start + (size_t)(end - buf)); | |
free(buf); | |
return val; | |
no_convert: | |
if (endptr != NULL) | |
*endptr = __UNCONST(nptr); | |
return 0.0; | |
} | |
#endif /*__WCSTOD_H_*/ |