xref: /aosp_15_r20/art/cmdline/detail/cmdline_parser_detail.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_CMDLINE_DETAIL_CMDLINE_PARSER_DETAIL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_CMDLINE_DETAIL_CMDLINE_PARSER_DETAIL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <sstream>
21*795d594fSAndroid Build Coastguard Worker #include <string>
22*795d594fSAndroid Build Coastguard Worker #include <vector>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker namespace art {
25*795d594fSAndroid Build Coastguard Worker // Implementation details for some template querying. Don't look inside if you hate templates.
26*795d594fSAndroid Build Coastguard Worker namespace detail {
27*795d594fSAndroid Build Coastguard Worker template <typename T>
28*795d594fSAndroid Build Coastguard Worker typename std::remove_reference<T>::type& FakeReference();
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker // SupportsInsertionOperator<T, TStream>::value will evaluate to a boolean,
31*795d594fSAndroid Build Coastguard Worker // whose value is true if the TStream class supports the << operator against T,
32*795d594fSAndroid Build Coastguard Worker // and false otherwise.
33*795d594fSAndroid Build Coastguard Worker template <typename T2, typename TStream2 = std::ostream>
34*795d594fSAndroid Build Coastguard Worker struct SupportsInsertionOperator {
35*795d594fSAndroid Build Coastguard Worker  private:
36*795d594fSAndroid Build Coastguard Worker   template <typename TStream, typename T>
37*795d594fSAndroid Build Coastguard Worker   static std::true_type InsertionOperatorTest(TStream& os, const T& value,
38*795d594fSAndroid Build Coastguard Worker                                               std::remove_reference<decltype(os << value)>* = 0);  // NOLINT [whitespace/operators] [3]
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker   template <typename TStream, typename ... T>
41*795d594fSAndroid Build Coastguard Worker   static std::false_type InsertionOperatorTest(TStream& os, const T& ... args);
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker  public:
44*795d594fSAndroid Build Coastguard Worker   static constexpr bool value =
45*795d594fSAndroid Build Coastguard Worker       decltype(InsertionOperatorTest(FakeReference<TStream2>(), std::declval<T2>()))::value;
46*795d594fSAndroid Build Coastguard Worker };
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker template <typename TLeft, typename TRight = TLeft, bool IsFloatingPoint = false>
49*795d594fSAndroid Build Coastguard Worker struct SupportsEqualityOperatorImpl;
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker template <typename TLeft, typename TRight>
52*795d594fSAndroid Build Coastguard Worker struct SupportsEqualityOperatorImpl<TLeft, TRight, false> {
53*795d594fSAndroid Build Coastguard Worker  private:
54*795d594fSAndroid Build Coastguard Worker   template <typename TL, typename TR>
55*795d594fSAndroid Build Coastguard Worker   static std::true_type EqualityOperatorTest(const TL& left, const TR& right,
56*795d594fSAndroid Build Coastguard Worker                                              std::remove_reference<decltype(left == right)>* = 0);  // NOLINT [whitespace/operators] [3]
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker   template <typename TL, typename ... T>
59*795d594fSAndroid Build Coastguard Worker   static std::false_type EqualityOperatorTest(const TL& left, const T& ... args);
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker  public:
62*795d594fSAndroid Build Coastguard Worker   static constexpr bool value =
63*795d594fSAndroid Build Coastguard Worker       decltype(EqualityOperatorTest(std::declval<TLeft>(), std::declval<TRight>()))::value;
64*795d594fSAndroid Build Coastguard Worker };
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker // Partial specialization when TLeft/TRight are both floating points.
67*795d594fSAndroid Build Coastguard Worker // This is a work-around because decltype(floatvar1 == floatvar2)
68*795d594fSAndroid Build Coastguard Worker // will not compile with clang:
69*795d594fSAndroid Build Coastguard Worker // error: comparing floating point with == or != is unsafe [-Werror,-Wfloat-equal]
70*795d594fSAndroid Build Coastguard Worker template <typename TLeft, typename TRight>
71*795d594fSAndroid Build Coastguard Worker struct SupportsEqualityOperatorImpl<TLeft, TRight, true> {
72*795d594fSAndroid Build Coastguard Worker   static constexpr bool value = true;
73*795d594fSAndroid Build Coastguard Worker };
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker // SupportsEqualityOperatorImpl<T1, T2>::value will evaluate to a boolean,
76*795d594fSAndroid Build Coastguard Worker // whose value is true if T1 can be compared against T2 with ==,
77*795d594fSAndroid Build Coastguard Worker // and false otherwise.
78*795d594fSAndroid Build Coastguard Worker template <typename TLeft, typename TRight = TLeft>
79*795d594fSAndroid Build Coastguard Worker struct SupportsEqualityOperator :  // NOLINT [whitespace/labels] [4]
80*795d594fSAndroid Build Coastguard Worker     SupportsEqualityOperatorImpl<TLeft, TRight,
81*795d594fSAndroid Build Coastguard Worker                                  std::is_floating_point<TLeft>::value
82*795d594fSAndroid Build Coastguard Worker                                  && std::is_floating_point<TRight>::value> {
83*795d594fSAndroid Build Coastguard Worker };
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker // Convert any kind of type to an std::string, even if there's no
86*795d594fSAndroid Build Coastguard Worker // serialization support for it. Unknown types get converted to an
87*795d594fSAndroid Build Coastguard Worker // an arbitrary value.
88*795d594fSAndroid Build Coastguard Worker //
89*795d594fSAndroid Build Coastguard Worker // Meant for printing user-visible errors or unit test failures only.
90*795d594fSAndroid Build Coastguard Worker template <typename T>
91*795d594fSAndroid Build Coastguard Worker std::string ToStringAny(const T& value,
92*795d594fSAndroid Build Coastguard Worker                         typename std::enable_if<
93*795d594fSAndroid Build Coastguard Worker                             SupportsInsertionOperator<T>::value>::type* = nullptr) {
94*795d594fSAndroid Build Coastguard Worker   std::stringstream stream;
95*795d594fSAndroid Build Coastguard Worker   stream << value;
96*795d594fSAndroid Build Coastguard Worker   return stream.str();
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker template <typename T>
100*795d594fSAndroid Build Coastguard Worker std::string ToStringAny(const std::vector<T> value,
101*795d594fSAndroid Build Coastguard Worker                         typename std::enable_if<
102*795d594fSAndroid Build Coastguard Worker                             SupportsInsertionOperator<T>::value>::type* = nullptr) {
103*795d594fSAndroid Build Coastguard Worker   std::stringstream stream;
104*795d594fSAndroid Build Coastguard Worker   stream << "vector{";
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < value.size(); ++i) {
107*795d594fSAndroid Build Coastguard Worker     stream << ToStringAny(value[i]);
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     if (i != value.size() - 1) {
110*795d594fSAndroid Build Coastguard Worker       stream << ',';
111*795d594fSAndroid Build Coastguard Worker     }
112*795d594fSAndroid Build Coastguard Worker   }
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   stream << "}";
115*795d594fSAndroid Build Coastguard Worker   return stream.str();
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker template <typename T>
119*795d594fSAndroid Build Coastguard Worker std::string ToStringAny(const T&,
120*795d594fSAndroid Build Coastguard Worker                         typename std::enable_if<
121*795d594fSAndroid Build Coastguard Worker                             !SupportsInsertionOperator<T>::value>::type* = nullptr
122*795d594fSAndroid Build Coastguard Worker ) {
123*795d594fSAndroid Build Coastguard Worker   return std::string("(unknown type [no operator<< implemented] for )");
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker }  // namespace detail  // NOLINT [readability/namespace] [5]
126*795d594fSAndroid Build Coastguard Worker }  // namespace art
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker #endif  // ART_CMDLINE_DETAIL_CMDLINE_PARSER_DETAIL_H_
129