Reactos
at master 369 lines 10 kB view raw
1// 2// _ctype.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Functions for converting integers to strings. 7// 8#include <corecrt_internal.h> 9#include <corecrt_internal_securecrt.h> 10#include <limits.h> 11#include <stdlib.h> 12 13#pragma warning(disable:__WARNING_NOT_SATISFIED) // 28020 Prefast thinks that 18446744073709551615 < 1. 14#pragma warning(disable:__WARNING_RANGE_PRECONDITION_VIOLATION) // 26060 Prefast thinks that 18446744073709551615 < 1. 15 16//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 17// 18// Common Conversion Implementation 19// 20//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21namespace 22{ 23 template <typename T> struct make_signed; 24 template <> struct make_signed<unsigned long> { typedef long type; }; 25 template <> struct make_signed<unsigned __int64> { typedef __int64 type; }; 26} 27 28 29 30template <typename UnsignedInteger, typename Character> 31_Success_(return == 0) 32static errno_t __cdecl common_xtox( 33 UnsignedInteger const original_value, 34 _Out_writes_z_(buffer_count) Character* const buffer, 35 _When_(is_negative == true, _In_range_(>=, 2)) _In_range_(>=, 1) 36 size_t const buffer_count, 37 unsigned const radix, 38 bool const is_negative 39 ) throw() 40{ 41// OACR isn't able to track that p stays within the bounds of [buffer, buffer + buffer_count) so manually verified and disabled warning 42#pragma warning(push) 43#pragma warning(disable:26014) 44 Character* p = buffer; // pointer to traverse the string 45 size_t length = 0; // current length of string 46 47 UnsignedInteger remaining_value = original_value;; 48 49 if (is_negative) 50 { 51 *p++ = '-'; 52 ++length; 53 54 remaining_value = static_cast<UnsignedInteger>( 55 -static_cast<typename make_signed<UnsignedInteger>::type>(remaining_value) 56 ); 57 } 58 59 Character* first_digit = p; 60 61 do 62 { 63 unsigned const digit = static_cast<unsigned>(remaining_value % radix); 64 remaining_value /= radix; 65 66 // Convert to ASCII and store: 67 if (digit > 9) 68 { 69 *p++ = static_cast<Character>(digit - 10 + 'a'); 70 } 71 else 72 { 73 *p++ = static_cast<Character>(digit + '0'); 74 } 75 76 ++length; 77 } 78 while (remaining_value > 0 && length < buffer_count); 79 80 if (length >= buffer_count) 81 { 82 buffer[0] = '\0'; 83 _VALIDATE_RETURN_ERRCODE(length < buffer_count, ERANGE); 84 } 85 86 // We now have the digits of the number in the buffer, but in reverse order. 87 // Reverse the order, but first terminate the string: 88 *p-- = '\0'; 89 90 do 91 { 92 Character const t = *p; 93 *p = *first_digit; 94 *first_digit = t; 95 --p; 96 ++first_digit; 97 } 98 while (first_digit < p); 99 100 return 0; 101#pragma warning(pop) 102} 103 104template <typename UnsignedInteger, typename Character> 105_Success_(return == 0) 106static errno_t __cdecl common_xtox_s( 107 UnsignedInteger const value, 108 _Out_writes_z_(buffer_count) Character* const buffer, 109 size_t const buffer_count, 110 unsigned const radix, 111 bool const is_negative 112 ) throw() 113{ 114 _VALIDATE_RETURN_ERRCODE(buffer != nullptr, EINVAL); 115 _VALIDATE_RETURN_ERRCODE(buffer_count > 0, EINVAL); 116 _RESET_STRING(buffer, buffer_count); 117 _VALIDATE_RETURN_ERRCODE(buffer_count > static_cast<size_t>(is_negative ? 2 : 1), ERANGE); 118 _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL); 119 120 return common_xtox(value, buffer, buffer_count, radix, is_negative); 121} 122 123 124 125//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 126// 127// 32-bit Integers => Narrow Strings 128// 129//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 130extern "C" errno_t __cdecl _itoa_s( 131 int const value, 132 char* const buffer, 133 size_t const buffer_count, 134 int const radix 135 ) 136{ 137 bool const is_negative = radix == 10 && value < 0; 138 return common_xtox_s(static_cast<unsigned long>(value), buffer, buffer_count, radix, is_negative); 139} 140 141extern "C" errno_t __cdecl _ltoa_s( 142 long const value, 143 char* const buffer, 144 size_t const buffer_count, 145 int const radix 146 ) 147{ 148 bool const is_negative = radix == 10 && value < 0; 149 return common_xtox_s(static_cast<unsigned long>(value), buffer, buffer_count, radix, is_negative); 150} 151 152extern "C" errno_t __cdecl _ultoa_s( 153 unsigned long const value, 154 char* const buffer, 155 size_t const buffer_count, 156 int const radix 157 ) 158{ 159 return common_xtox_s(value, buffer, buffer_count, radix, false); 160} 161 162 163 164extern "C" char* __cdecl _itoa( 165 int const value, 166 char* const buffer, 167 int const radix 168 ) 169{ 170 bool const is_negative = radix == 10 && value < 0; 171 common_xtox(static_cast<unsigned long>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 172 return buffer; 173} 174 175extern "C" char* __cdecl _ltoa( 176 long const value, 177 char* const buffer, 178 int const radix 179 ) 180{ 181 bool const is_negative = radix == 10 && value < 0; 182 common_xtox(static_cast<unsigned long>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 183 return buffer; 184} 185 186extern "C" char* __cdecl _ultoa( 187 unsigned long const value, 188 char* const buffer, 189 int const radix 190 ) 191{ 192 common_xtox(value, buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, false); 193 return buffer; 194} 195 196 197 198//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 199// 200// 64-bit Integers => Narrow Strings 201// 202//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 203extern "C" errno_t __cdecl _i64toa_s( 204 __int64 const value, 205 char* const buffer, 206 size_t const buffer_count, 207 int const radix 208 ) 209{ 210 bool const is_negative = radix == 10 && value < 0; 211 return common_xtox_s(static_cast<unsigned __int64>(value), buffer, buffer_count, radix, is_negative); 212} 213 214extern "C" errno_t __cdecl _ui64toa_s( 215 unsigned __int64 const value, 216 char* const buffer, 217 size_t const buffer_count, 218 int const radix 219 ) 220{ 221 return common_xtox_s(value, buffer, buffer_count, radix, false); 222} 223 224 225 226extern "C" char* __cdecl _i64toa( 227 __int64 const value, 228 char* const buffer, 229 int const radix 230 ) 231{ 232 bool const is_negative = radix == 10 && value < 0; 233 common_xtox(static_cast<unsigned __int64>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 234 return buffer; 235} 236 237extern "C" char* __cdecl _ui64toa( 238 unsigned __int64 const value, 239 char* const buffer, 240 int const radix 241 ) 242{ 243 common_xtox(value, buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, false); 244 return buffer; 245} 246 247 248 249//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 250// 251// 32-bit Integers => Wide Strings 252// 253//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 254extern "C" errno_t __cdecl _itow_s( 255 int const value, 256 wchar_t* const buffer, 257 size_t const buffer_count, 258 int const radix 259 ) 260{ 261 bool const is_negative = radix == 10 && value < 0; 262 return common_xtox_s(static_cast<unsigned long>(value), buffer, buffer_count, radix, is_negative); 263} 264 265extern "C" errno_t __cdecl _ltow_s( 266 long const value, 267 wchar_t* const buffer, 268 size_t const buffer_count, 269 int const radix 270 ) 271{ 272 bool const is_negative = radix == 10 && value < 0; 273 return common_xtox_s(static_cast<unsigned long>(value), buffer, buffer_count, radix, is_negative); 274} 275 276extern "C" errno_t __cdecl _ultow_s( 277 unsigned long const value, 278 wchar_t* const buffer, 279 size_t const buffer_count, 280 int const radix 281 ) 282{ 283 return common_xtox_s(value, buffer, buffer_count, radix, false); 284} 285 286 287 288extern "C" wchar_t* __cdecl _itow( 289 int const value, 290 wchar_t* const buffer, 291 int const radix 292 ) 293{ 294 bool const is_negative = radix == 10 && value < 0; 295 common_xtox(static_cast<unsigned long>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 296 return buffer; 297} 298 299extern "C" wchar_t* __cdecl _ltow( 300 long const value, 301 wchar_t* const buffer, 302 int const radix 303 ) 304{ 305 bool const is_negative = radix == 10 && value < 0; 306 common_xtox(static_cast<unsigned long>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 307 return buffer; 308} 309 310extern "C" wchar_t* __cdecl _ultow( 311 unsigned long const value, 312 wchar_t* const buffer, 313 int const radix 314 ) 315{ 316 common_xtox(value, buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, false); 317 return buffer; 318} 319 320 321 322//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 323// 324// 64-bit Integers => Wide Strings 325// 326//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 327extern "C" errno_t __cdecl _i64tow_s( 328 __int64 const value, 329 wchar_t* const buffer, 330 size_t const buffer_count, 331 int const radix 332 ) 333{ 334 bool const is_negative = radix == 10 && value < 0; 335 return common_xtox_s(static_cast<unsigned __int64>(value), buffer, buffer_count, radix, is_negative); 336} 337 338extern "C" errno_t __cdecl _ui64tow_s( 339 unsigned __int64 const value, 340 wchar_t* const buffer, 341 size_t const buffer_count, 342 int const radix 343 ) 344{ 345 return common_xtox_s(value, buffer, buffer_count, radix, false); 346} 347 348 349 350extern "C" wchar_t* __cdecl _i64tow( 351 __int64 const value, 352 wchar_t* const buffer, 353 int const radix 354 ) 355{ 356 bool const is_negative = radix == 10 && value < 0; 357 common_xtox(static_cast<unsigned __int64>(value), buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, is_negative); 358 return buffer; 359} 360 361extern "C" wchar_t* __cdecl _ui64tow( 362 unsigned __int64 const value, 363 wchar_t* const buffer, 364 int const radix 365 ) 366{ 367 common_xtox(value, buffer, _CRT_UNBOUNDED_BUFFER_SIZE, radix, false); 368 return buffer; 369}