1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <inttypes.h> 30 #include <stdlib.h> 31 #include <wchar.h> 32 33 #include "UniquePtr.h" 34 35 namespace { 36 constexpr size_t MBS_FAILURE = static_cast<size_t>(-1); 37 } 38 39 template <typename T> 40 static T wcstox(T (*func)(const char*, char**, int), const wchar_t* wcs, 41 wchar_t** wcs_end, int base) { 42 mbstate_t mbstate; 43 memset(&mbstate, 0, sizeof(mbstate)); 44 45 if (wcs_end != nullptr) { 46 *wcs_end = const_cast<wchar_t*>(wcs); 47 } 48 49 const size_t max_mb_len = wcslen(wcs) * 4 + 1; 50 UniquePtr<char[]> mbs(new char[max_mb_len]); 51 const wchar_t* s = wcs; 52 if (wcsrtombs(mbs.get(), &s, max_mb_len, &mbstate) == MBS_FAILURE) { 53 return static_cast<T>(0); 54 } 55 56 char* mbs_end; 57 T value = func(mbs.get(), &mbs_end, base); 58 if (wcs_end == nullptr) { 59 // If the user passed nullptr for the end pointer, we don't need to compute 60 // it and can return early. 61 return value; 62 } 63 64 // strto* can set ERANGE or EINVAL. Preserve the value of errno in case any of 65 // the things we're about to do to comput the end pointer don't clobber it. 66 int preserved_errno = errno; 67 68 // wcs_end needs to point to the character after the one converted. We don't 69 // know how many wide characters were converted, but we can figure that out by 70 // converting the multibyte string between mbs and mbs_end back to a wide 71 // character string. 72 size_t converted_len = mbs_end - mbs.get(); 73 UniquePtr<char[]> converted_mbs(new char[converted_len + 1]); 74 strncpy(converted_mbs.get(), mbs.get(), converted_len); 75 converted_mbs[converted_len] = '\0'; 76 77 const char* mbsp = converted_mbs.get(); 78 size_t converted_wlen = mbsrtowcs(nullptr, &mbsp, 0, &mbstate); 79 if (converted_wlen == MBS_FAILURE) { 80 // This should be impossible. 81 abort(); 82 } 83 84 *wcs_end = const_cast<wchar_t*>(wcs) + converted_wlen; 85 errno = preserved_errno; 86 return value; 87 } 88 89 static float strtof_wrapper(const char* s, char** p, int) { 90 return strtof(s, p); 91 } 92 93 float wcstof(const wchar_t* s, wchar_t** p) { 94 return wcstox(strtof_wrapper, s, p, 0); 95 } 96 97 static double strtod_wrapper(const char* s, char** p, int) { 98 return strtod(s, p); 99 } 100 101 double wcstod(const wchar_t *restrict s, wchar_t **restrict p) { 102 return wcstox(strtod_wrapper, s, p, 0); 103 } 104 105 long wcstol(const wchar_t *restrict s, wchar_t **restrict p, int base) { 106 return wcstox(strtol, s, p, base); 107 } 108 109 unsigned long wcstoul(const wchar_t *restrict s, wchar_t **restrict p, int base) { 110 return wcstox(strtoul, s, p, base); 111 } 112 113 long long wcstoll(const wchar_t *restrict s, wchar_t **restrict p, int base) { 114 return wcstox(strtoll, s, p, base); 115 } 116 117 unsigned long long wcstoull(const wchar_t *restrict s, wchar_t **restrict p, int base) { 118 return wcstox(strtoull, s, p, base); 119 } 120 121 intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict p, int base) { 122 return wcstox(strtoimax, s, p, base); 123 } 124 125 uintmax_t wcstoumax(const wchar_t *restrict s, wchar_t **restrict p, int base) { 126 return wcstox(strtoumax, s, p, base); 127 } 128