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 out()38 std::string& out() { return mOut; } 39 40 void dump(std::string_view name, std::string_view value = {}) { 41 using namespace std::string_view_literals; 42 43 for (int i = mIndent; i-- > 0;) mOut += " "sv; 44 mOut += name; 45 if (!name.empty()) mOut += '='; 46 mOut += value; 47 eol(); 48 } 49 dump(std::string_view name,const std::string & value)50 void dump(std::string_view name, const std::string& value) { 51 dump(name, static_cast<const std::string_view&>(value)); 52 } 53 dump(std::string_view name,bool value)54 void dump(std::string_view name, bool value) { 55 using namespace std::string_view_literals; 56 dump(name, value ? "true"sv : "false"sv); 57 } 58 59 template <typename T> dump(std::string_view name,const std::optional<T> & opt)60 void dump(std::string_view name, const std::optional<T>& opt) { 61 if (opt) { 62 dump(name, *opt); 63 } else { 64 using namespace std::string_view_literals; 65 dump(name, "nullopt"sv); 66 } 67 } 68 69 template <typename T> dump(std::string_view name,const ftl::Optional<T> & opt)70 void dump(std::string_view name, const ftl::Optional<T>& opt) { 71 dump(name, static_cast<const std::optional<T>&>(opt)); 72 } 73 74 template <typename T, typename... Ts> dump(std::string_view name,const T & value,const Ts &...rest)75 void dump(std::string_view name, const T& value, const Ts&... rest) { 76 std::string string; 77 78 constexpr bool kIsTuple = sizeof...(Ts) > 0; 79 if constexpr (kIsTuple) { 80 string += '{'; 81 } 82 83 using std::to_string; 84 string += to_string(value); 85 86 if constexpr (kIsTuple) { 87 string += ((", " + to_string(rest)) + ...); 88 string += '}'; 89 } 90 91 dump(name, string); 92 } 93 94 struct Indent { IndentIndent95 explicit Indent(Dumper& dumper) : dumper(dumper) { dumper.mIndent++; } ~IndentIndent96 ~Indent() { dumper.mIndent--; } 97 98 Dumper& dumper; 99 }; 100 101 struct Section { SectionSection102 Section(Dumper& dumper, std::string_view heading) : dumper(dumper) { 103 dumper.dump({}, heading); 104 indent.emplace(dumper); 105 } 106 ~SectionSection107 ~Section() { 108 indent.reset(); 109 dumper.eol(); 110 } 111 112 Dumper& dumper; 113 std::optional<Indent> indent; 114 }; 115 116 private: 117 std::string& mOut; 118 int mIndent = 0; 119 }; 120 121 } // namespace android::utils 122