1 /* $NetBSD: _wcstod.h,v 1.4 2013/05/17 12:55:57 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 Tim J. Robbins 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * aINre met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * Original version ID: 29 * FreeBSD: /repoman/r/ncvs/src/lib/libc/locale/wcstod.c,v 1.4 2004/04/07 09:47:56 tjr Exp 30 * NetBSD: wcstod.c,v 1.8 2006/04/13 01:25:13 tnozaki Exp 31 */ 32 33 /* 34 * function template for wcstof, wcstod, wcstold. 35 * 36 * parameters: 37 * _FUNCNAME : function name 38 * _RETURN_TYPE : return type 39 * _STRTOD_FUNC : real conversion function 40 */ 41 #ifndef __WCSTOD_H_ 42 #define __WCSTOD_H_ 43 44 #include <locale.h> 45 #include "setlocale_local.h" 46 #define INT_NAME_(pre, middle, post) pre ## middle ## post 47 #define INT_NAME(pre, middle, post) INT_NAME_(pre, middle, post) 48 49 /* 50 * Convert a string to a double-precision number. 51 * 52 * This is the wide-character counterpart of strto{f,d,ld}(). So that 53 * we do not have to duplicate the code of strto{f,d,ld}() here, 54 * we convert the supplied wide-character string to multibyte and 55 * call strto{f,d,ld}() on the result. 56 * This assumes that the multibyte encoding is compatible with ASCII 57 * for at least the digits, radix character and letters. 58 */ 59 static _RETURN_TYPE 60 INT_NAME(_int_, _FUNCNAME, _l)(const wchar_t * __restrict nptr, 61 wchar_t ** __restrict endptr, locale_t loc) 62 { 63 const wchar_t *src, *start; 64 _RETURN_TYPE val; 65 char *buf, *end; 66 size_t bufsiz, len; 67 68 _DIAGASSERT(nptr != NULL); 69 /* endptr may be null */ 70 71 src = nptr; 72 while (iswspace_l((wint_t)*src, loc) != 0) 73 ++src; 74 if (*src == L'\0') 75 goto no_convert; 76 77 /* 78 * Convert the supplied numeric wide-char. string to multibyte. 79 * 80 * We could attempt to find the end of the numeric portion of the 81 * wide-char. string to avoid converting unneeded characters but 82 * choose not to bother; optimising the uncommon case where 83 * the input string contains a lot of text after the number 84 * duplicates a lot of strto{f,d,ld}()'s functionality and 85 * slows down the most common cases. 86 */ 87 start = src; 88 len = wcstombs_l(NULL, src, 0, loc); 89 if (len == (size_t)-1) 90 /* errno = EILSEQ */ 91 goto no_convert; 92 93 _DIAGASSERT(len > 0); 94 95 bufsiz = len; 96 buf = (void *)malloc(bufsiz + 1); 97 if (buf == NULL) 98 /* errno = ENOMEM */ 99 goto no_convert; 100 101 len = wcstombs_l(buf, src, bufsiz + 1, loc); 102 103 _DIAGASSERT(len == bufsiz); 104 _DIAGASSERT(buf[len] == '\0'); 105 106 /* Let strto{f,d,ld}() do most of the work for us. */ 107 val = _STRTOD_FUNC(buf, &end, loc); 108 if (buf == end) { 109 free(buf); 110 goto no_convert; 111 } 112 113 /* 114 * We only know where the number ended in the _multibyte_ 115 * representation of the string. If the caller wants to know 116 * where it ended, count multibyte characters to find the 117 * corresponding position in the wide-char string. 118 */ 119 if (endptr != NULL) 120 /* XXX Assume each wide char is one byte. */ 121 *endptr = __UNCONST(start + (size_t)(end - buf)); 122 123 free(buf); 124 125 return val; 126 127 no_convert: 128 if (endptr != NULL) 129 *endptr = __UNCONST(nptr); 130 return 0; 131 } 132 133 _RETURN_TYPE 134 INT_NAME(, _FUNCNAME, )(const wchar_t * __restrict nptr, 135 wchar_t ** __restrict endptr) 136 { 137 return INT_NAME(_int_, _FUNCNAME, _l)(nptr, endptr, _current_locale()); 138 } 139 140 _RETURN_TYPE 141 INT_NAME(, _FUNCNAME, _l)(const wchar_t * __restrict nptr, 142 wchar_t ** __restrict endptr, locale_t loc) 143 { 144 return INT_NAME(_int_, _FUNCNAME, _l)(nptr, endptr, loc); 145 } 146 #endif /*__WCSTOD_H_*/ 147