1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <string> 20 #include <string_view> 21 22 #include <ftl/optional.h> 23 24 namespace android::utils { 25 26 // Dumps variables by appending their name and value to the output string. A variable is formatted 27 // as "name=value". If the name or value is empty, the format is "value" or "name=", respectively. 28 // A value of user-defined type T is stringified via `std::string to_string(const T&)`, which must 29 // be defined in the same namespace as T per the rules of ADL (argument-dependent lookup). 30 // 31 // TODO(b/249828573): Consolidate with <compositionengine/impl/DumpHelpers.h> 32 class Dumper { 33 public: Dumper(std::string & out)34 explicit Dumper(std::string& out) : mOut(out) {} 35 eol()36 void eol() { mOut += '\n'; } 37 38 void dump(std::string_view name, std::string_view value = {}) { 39 using namespace std::string_view_literals; 40 41 for (int i = mIndent; i-- > 0;) mOut += " "sv; 42 mOut += name; 43 if (!name.empty()) mOut += '='; 44 mOut += value; 45 eol(); 46 } 47 dump(std::string_view name,const std::string & value)48 void dump(std::string_view name, const std::string& value) { 49 dump(name, static_cast<const std::string_view&>(value)); 50 } 51 dump(std::string_view name,bool value)52 void dump(std::string_view name, bool value) { 53 using namespace std::string_view_literals; 54 dump(name, value ? "true"sv : "false"sv); 55 } 56 57 template <typename T> dump(std::string_view name,const std::optional<T> & opt)58 void dump(std::string_view name, const std::optional<T>& opt) { 59 if (opt) { 60 dump(name, *opt); 61 } else { 62 using namespace std::string_view_literals; 63 dump(name, "nullopt"sv); 64 } 65 } 66 67 template <typename T> dump(std::string_view name,const ftl::Optional<T> & opt)68 void dump(std::string_view name, const ftl::Optional<T>& opt) { 69 dump(name, static_cast<const std::optional<T>&>(opt)); 70 } 71 72 template <typename T, typename... Ts> dump(std::string_view name,const T & value,const Ts &...rest)73 void dump(std::string_view name, const T& value, const Ts&... rest) { 74 std::string string; 75 76 constexpr bool kIsTuple = sizeof...(Ts) > 0; 77 if constexpr (kIsTuple) { 78 string += '{'; 79 } 80 81 using std::to_string; 82 string += to_string(value); 83 84 if constexpr (kIsTuple) { 85 string += ((", " + to_string(rest)) + ...); 86 string += '}'; 87 } 88 89 dump(name, string); 90 } 91 92 struct Indent { IndentIndent93 explicit Indent(Dumper& dumper) : dumper(dumper) { dumper.mIndent++; } ~IndentIndent94 ~Indent() { dumper.mIndent--; } 95 96 Dumper& dumper; 97 }; 98 99 struct Section { SectionSection100 Section(Dumper& dumper, std::string_view heading) : dumper(dumper) { 101 dumper.dump({}, heading); 102 indent.emplace(dumper); 103 } 104 ~SectionSection105 ~Section() { 106 indent.reset(); 107 dumper.eol(); 108 } 109 110 Dumper& dumper; 111 std::optional<Indent> indent; 112 }; 113 114 private: 115 std::string& mOut; 116 int mIndent = 0; 117 }; 118 119 } // namespace android::utils 120