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