1 //===-- Inf or Nan Converter for printf -------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_INF_NAN_CONVERTER_H 10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_INF_NAN_CONVERTER_H 11 12 #include "src/__support/FPUtil/FPBits.h" 13 #include "src/__support/ctype_utils.h" 14 #include "src/__support/macros/config.h" 15 #include "src/stdio/printf_core/converter_utils.h" 16 #include "src/stdio/printf_core/core_structs.h" 17 #include "src/stdio/printf_core/writer.h" 18 19 #include <inttypes.h> 20 #include <stddef.h> 21 22 namespace LIBC_NAMESPACE_DECL { 23 namespace printf_core { 24 25 using StorageType = fputil::FPBits<long double>::StorageType; 26 27 LIBC_INLINE int convert_inf_nan(Writer *writer, const FormatSection &to_conv) { 28 // All of the letters will be defined relative to variable a, which will be 29 // the appropriate case based on the case of the conversion. 30 bool is_negative; 31 StorageType mantissa; 32 if (to_conv.length_modifier == LengthModifier::L) { 33 fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw; 34 fputil::FPBits<long double> float_bits(float_raw); 35 is_negative = float_bits.is_neg(); 36 mantissa = float_bits.get_mantissa(); 37 } else { 38 fputil::FPBits<double>::StorageType float_raw = 39 static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw); 40 fputil::FPBits<double> float_bits(float_raw); 41 is_negative = float_bits.is_neg(); 42 mantissa = float_bits.get_mantissa(); 43 } 44 45 char sign_char = 0; 46 47 if (is_negative) 48 sign_char = '-'; 49 else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN) 50 sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX 51 else if ((to_conv.flags & FormatFlags::SPACE_PREFIX) == 52 FormatFlags::SPACE_PREFIX) 53 sign_char = ' '; 54 55 // Both "inf" and "nan" are the same number of characters, being 3. 56 int padding = to_conv.min_width - (sign_char > 0 ? 1 : 0) - 3; 57 58 // The right justified pattern is (spaces), (sign), inf/nan 59 // The left justified pattern is (sign), inf/nan, (spaces) 60 61 if (padding > 0 && ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) != 62 FormatFlags::LEFT_JUSTIFIED)) 63 RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); 64 65 if (sign_char) 66 RET_IF_RESULT_NEGATIVE(writer->write(sign_char)); 67 if (mantissa == 0) { // inf 68 RET_IF_RESULT_NEGATIVE( 69 writer->write(internal::islower(to_conv.conv_name) ? "inf" : "INF")); 70 } else { // nan 71 RET_IF_RESULT_NEGATIVE( 72 writer->write(internal::islower(to_conv.conv_name) ? "nan" : "NAN")); 73 } 74 75 if (padding > 0 && ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == 76 FormatFlags::LEFT_JUSTIFIED)) 77 RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); 78 79 return WRITE_OK; 80 } 81 82 } // namespace printf_core 83 } // namespace LIBC_NAMESPACE_DECL 84 85 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_INF_NAN_CONVERTER_H 86