1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/utils/common.h" 10 #include "td/utils/SharedSlice.h" 11 #include "td/utils/Slice.h" 12 #include "td/utils/SliceBuilder.h" 13 #include "td/utils/UInt.h" 14 15 namespace td { 16 17 class TlStorerToString { 18 string result; 19 size_t shift = 0; 20 store_field_begin(const char * name)21 void store_field_begin(const char *name) { 22 result.append(shift, ' '); 23 if (name && name[0]) { 24 result += name; 25 result += " = "; 26 } 27 } 28 store_field_end()29 void store_field_end() { 30 result += '\n'; 31 } 32 store_long(int64 value)33 void store_long(int64 value) { 34 result += (PSLICE() << value).c_str(); 35 } 36 store_binary(Slice data)37 void store_binary(Slice data) { 38 static const char *hex = "0123456789ABCDEF"; 39 40 result.append("{ ", 2); 41 for (auto c : data) { 42 unsigned char byte = c; 43 result += hex[byte >> 4]; 44 result += hex[byte & 15]; 45 result += ' '; 46 } 47 result += '}'; 48 } 49 50 public: 51 TlStorerToString() = default; 52 TlStorerToString(const TlStorerToString &other) = delete; 53 TlStorerToString &operator=(const TlStorerToString &other) = delete; 54 store_field(const char * name,bool value)55 void store_field(const char *name, bool value) { 56 store_field_begin(name); 57 result += (value ? "true" : "false"); 58 store_field_end(); 59 } 60 store_field(const char * name,int32 value)61 void store_field(const char *name, int32 value) { 62 store_field(name, static_cast<int64>(value)); 63 } 64 store_field(const char * name,int64 value)65 void store_field(const char *name, int64 value) { 66 store_field_begin(name); 67 store_long(value); 68 store_field_end(); 69 } 70 store_field(const char * name,double value)71 void store_field(const char *name, double value) { 72 store_field_begin(name); 73 result += (PSLICE() << value).c_str(); 74 store_field_end(); 75 } 76 store_field(const char * name,const char * value)77 void store_field(const char *name, const char *value) { 78 store_field_begin(name); 79 result += value; 80 store_field_end(); 81 } 82 store_field(const char * name,const string & value)83 void store_field(const char *name, const string &value) { 84 store_field_begin(name); 85 result += '"'; 86 result += value; 87 result += '"'; 88 store_field_end(); 89 } 90 store_field(const char * name,const SecureString & value)91 void store_field(const char *name, const SecureString &value) { 92 store_field_begin(name); 93 result.append("<secret>"); 94 store_field_end(); 95 } 96 97 template <class T> store_field(const char * name,const T & value)98 void store_field(const char *name, const T &value) { 99 store_field_begin(name); 100 result.append(value.data(), value.size()); 101 store_field_end(); 102 } 103 store_bytes_field(const char * name,const SecureString & value)104 void store_bytes_field(const char *name, const SecureString &value) { 105 store_field_begin(name); 106 result.append("<secret>"); 107 store_field_end(); 108 } 109 110 template <class BytesT> store_bytes_field(const char * name,const BytesT & value)111 void store_bytes_field(const char *name, const BytesT &value) { 112 static const char *hex = "0123456789ABCDEF"; 113 114 store_field_begin(name); 115 result.append("bytes ["); 116 store_long(static_cast<int64>(value.size())); 117 result.append("] { "); 118 size_t len = min(static_cast<size_t>(64), value.size()); 119 for (size_t i = 0; i < len; i++) { 120 int b = value[static_cast<int>(i)] & 0xff; 121 result += hex[b >> 4]; 122 result += hex[b & 15]; 123 result += ' '; 124 } 125 if (len < value.size()) { 126 result.append("..."); 127 } 128 result += '}'; 129 store_field_end(); 130 } 131 132 template <class ObjectT> store_object_field(const char * name,const ObjectT * value)133 void store_object_field(const char *name, const ObjectT *value) { 134 if (value == nullptr) { 135 store_field(name, "null"); 136 } else { 137 value->store(*this, name); 138 } 139 } 140 store_field(const char * name,const UInt128 & value)141 void store_field(const char *name, const UInt128 &value) { 142 store_field_begin(name); 143 store_binary(as_slice(value)); 144 store_field_end(); 145 } 146 store_field(const char * name,const UInt256 & value)147 void store_field(const char *name, const UInt256 &value) { 148 store_field_begin(name); 149 store_binary(as_slice(value)); 150 store_field_end(); 151 } 152 store_vector_begin(const char * field_name,size_t vector_size)153 void store_vector_begin(const char *field_name, size_t vector_size) { 154 store_field_begin(field_name); 155 result += "vector["; 156 result += (PSLICE() << vector_size).c_str(); 157 result += "] {\n"; 158 shift += 2; 159 } 160 store_class_begin(const char * field_name,const char * class_name)161 void store_class_begin(const char *field_name, const char *class_name) { 162 store_field_begin(field_name); 163 result += class_name; 164 result += " {\n"; 165 shift += 2; 166 } 167 store_class_end()168 void store_class_end() { 169 CHECK(shift >= 2); 170 shift -= 2; 171 result.append(shift, ' '); 172 result += "}\n"; 173 } 174 move_as_string()175 string move_as_string() { 176 return std::move(result); 177 } 178 }; 179 180 } // namespace td 181