• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Shared Converter Utilities 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_CONVERTER_UTILS_H
10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CONVERTER_UTILS_H
11 
12 #include "src/__support/CPP/limits.h"
13 #include "src/stdio/printf_core/core_structs.h"
14 
15 #include <inttypes.h>
16 #include <stddef.h>
17 
18 namespace LIBC_NAMESPACE {
19 namespace printf_core {
20 
apply_length_modifier(uintmax_t num,LengthSpec length_spec)21 LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num,
22                                             LengthSpec length_spec) {
23   auto [lm, bw] = length_spec;
24   switch (lm) {
25   case LengthModifier::none:
26     return num & cpp::numeric_limits<unsigned int>::max();
27   case LengthModifier::l:
28     return num & cpp::numeric_limits<unsigned long>::max();
29   case LengthModifier::ll:
30   case LengthModifier::L:
31     return num & cpp::numeric_limits<unsigned long long>::max();
32   case LengthModifier::h:
33     return num & cpp::numeric_limits<unsigned short>::max();
34   case LengthModifier::hh:
35     return num & cpp::numeric_limits<unsigned char>::max();
36   case LengthModifier::z:
37     return num & cpp::numeric_limits<size_t>::max();
38   case LengthModifier::t:
39     // We don't have unsigned ptrdiff so uintptr_t is used, since we need an
40     // unsigned type and ptrdiff is usually the same size as a pointer.
41     static_assert(sizeof(ptrdiff_t) == sizeof(uintptr_t));
42     return num & cpp::numeric_limits<uintptr_t>::max();
43   case LengthModifier::j:
44     return num; // j is intmax, so no mask is necessary.
45   case LengthModifier::w:
46   case LengthModifier::wf: {
47     uintmax_t mask;
48     if (bw == 0) {
49       mask = 0;
50     } else if (bw < sizeof(uintmax_t) * CHAR_BIT) {
51       mask = (static_cast<uintmax_t>(1) << bw) - 1;
52     } else {
53       mask = UINTMAX_MAX;
54     }
55     return num & mask;
56   }
57   }
58   __builtin_unreachable();
59 }
60 
61 #define RET_IF_RESULT_NEGATIVE(func)                                           \
62   {                                                                            \
63     int result = (func);                                                       \
64     if (result < 0)                                                            \
65       return result;                                                           \
66   }
67 
68 // This is used to represent which direction the number should be rounded.
69 enum class RoundDirection { Up, Down, Even };
70 
71 } // namespace printf_core
72 } // namespace LIBC_NAMESPACE
73 
74 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CONVERTER_UTILS_H
75