1 /* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */ 2 3 /*- 4 * Copyright (c)1999, 2000, 2001 Citrus Project, 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 * are 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 * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $ 29 */ 30 31 #include <sys/cdefs.h> 32 #include <assert.h> 33 #include <errno.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <wchar.h> 37 #include <wctype.h> 38 39 #define _L(x) __CONCAT(L,x) 40 #define _LC(x) __CONCAT(L,x) 41 42 double 43 wcstod(const wchar_t *nptr, wchar_t **endptr) 44 { 45 const wchar_t *src; 46 size_t size; 47 const wchar_t *start; 48 49 _DIAGASSERT(nptr); 50 51 /* 52 * we do only check length of string 53 * and give it over strtod. 54 */ 55 src = nptr; 56 57 /* skip space first */ 58 while (iswspace(*src)) { 59 src++; 60 } 61 62 /* get length of string */ 63 start = src; 64 if (wcschr(_L("+-"), *src)) 65 src++; 66 size = wcsspn(src, _L("0123456789")); 67 src += size; 68 if (*src == _LC('.')) {/* XXX use localeconv */ 69 src++; 70 size = wcsspn(src, _L("0123456789")); 71 src += size; 72 } 73 if (wcschr(_L("Ee"), *src)) { 74 src++; 75 if (wcschr(_L("+-"), *src)) 76 src++; 77 size = wcsspn(src, _L("0123456789")); 78 src += size; 79 } 80 size = src - start; 81 82 /* 83 * convert to a char-string and pass it to strtod. 84 * 85 * since all chars used to represent a double-constant 86 * are in the portable character set, we can assume 87 * that they are 1-byte chars. 88 */ 89 if (size) 90 { 91 mbstate_t st; 92 char *buf; 93 char *end; 94 const wchar_t *s; 95 size_t size_converted; 96 double result; 97 98 buf = malloc(size + 1); 99 if (!buf) { 100 /* error */ 101 errno = ENOMEM; /* XXX */ 102 return 0; 103 } 104 105 s = start; 106 memset(&st, 0, sizeof(st)); 107 size_converted = wcsrtombs(buf, &s, size, &st); 108 if (size != size_converted) { 109 /* XXX should not happen */ 110 free(buf); 111 errno = EILSEQ; 112 return 0; 113 } 114 115 buf[size] = 0; 116 result = strtod(buf, &end); 117 118 free(buf); 119 120 if (endptr) 121 /* LINTED bad interface */ 122 *endptr = (wchar_t*)start + (end - buf); 123 124 return result; 125 } 126 127 if (endptr) 128 /* LINTED bad interface */ 129 *endptr = (wchar_t*)start; 130 131 return 0; 132 } 133