Apollo 10.0
自动驾驶开放平台
general_message_base.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
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
18
19#include <iomanip>
20#include <string>
21#include <vector>
22
25
26namespace {
27constexpr int INT_FLOAT_PRECISION = 6;
28constexpr int DOULBE_PRECISION = 9;
29
30int CalculateStringLines(const std::string& str, int screen_width) {
31 int line_width = 0;
32 int line_count = 0;
33 for (std::size_t i = 0; i < str.size(); ++i) {
34 if (str[i] == '\n' || str[i] == '\r') {
35 ++line_count;
36 line_width = 0;
37 } else {
38 ++line_width;
39 if (line_width == screen_width) {
40 ++line_count;
41 line_width = 0;
42 }
43 }
44 }
45
46 if (line_width) {
47 ++line_count;
48 }
49
50 return line_count;
51}
52
53} // namespace
54
55int GeneralMessageBase::LineCount(const google::protobuf::Message& msg,
56 int screen_width) {
57 const google::protobuf::Reflection* reflection = msg.GetReflection();
58 const google::protobuf::Descriptor* descriptor = msg.GetDescriptor();
59 std::vector<const google::protobuf::FieldDescriptor*> fields;
60 if (descriptor->options().map_entry()) {
61 fields.push_back(descriptor->field(0));
62 fields.push_back(descriptor->field(1));
63 } else {
64 reflection->ListFields(msg, &fields);
65 }
66
67 auto fsize = fields.size();
68 int ret = 0;
69 for (decltype(fsize) i = 0; i < fsize; ++i) {
70 ret += LineCountOfField(msg, screen_width, fields[i], reflection);
71 }
72
73 return ret;
74}
75
77 const google::protobuf::Message& msg, int screen_width,
78 const google::protobuf::FieldDescriptor* field,
79 const google::protobuf::Reflection* reflection, bool is_folded) {
80 int ret = 0;
81 if (!is_folded && field->is_repeated()) {
82 int size = reflection->FieldSize(msg, field);
83 for (int i = 0; i < size; ++i) {
84 switch (field->cpp_type()) {
85 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
86 std::string scratch;
87 const std::string& value =
88 reflection->GetRepeatedStringReference(msg, field, i, &scratch);
89 ret += CalculateStringLines(value, screen_width);
90 break;
91 }
92
93 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
94 const google::protobuf::Message& child_msg =
95 reflection->GetRepeatedMessage(msg, field, i);
96 ret += LineCount(child_msg, screen_width);
97 break;
98 }
99
100 default:
101 ret += 1;
102 }
103 }
104 } else {
105 ret = 1;
106 if (!field->is_repeated()) {
107 switch (field->cpp_type()) {
108 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
109 std::string scratch;
110 const std::string& value =
111 reflection->GetStringReference(msg, field, &scratch);
112 ret += CalculateStringLines(value, screen_width);
113 break;
114 }
115
116 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
117 const google::protobuf::Message& child_msg =
118 reflection->GetMessage(msg, field);
119 ret += LineCount(child_msg, screen_width);
120 break;
121 }
122
123 default: {
124 }
125 }
126 }
127 }
128 return ret;
129}
130
132 const google::protobuf::Message& msg,
133 int* jump_lines, const Screen* s,
134 int* line_no, int indent) {
135 const google::protobuf::Reflection* reflection = msg.GetReflection();
136 const google::protobuf::Descriptor* descriptor = msg.GetDescriptor();
137 std::vector<const google::protobuf::FieldDescriptor*> fields;
138 if (descriptor->options().map_entry()) {
139 fields.push_back(descriptor->field(0));
140 fields.push_back(descriptor->field(1));
141 } else {
142 reflection->ListFields(msg, &fields);
143 }
144 for (std::size_t i = 0; i < fields.size(); ++i) {
145 if (*line_no > s->Height()) {
146 break;
147 }
148 const google::protobuf::FieldDescriptor* field = fields[i];
149 if (field->is_repeated()) {
150 if (*jump_lines) {
151 --(*jump_lines);
152 } else {
153 std::ostringstream out_str;
154 const std::string& fieldName = field->name();
155 out_str << fieldName << ": ";
156 out_str << "+[" << reflection->FieldSize(msg, field) << " items]";
157 GeneralMessage* item =
158 new GeneralMessage(baseMsg, &msg, reflection, field);
159 if (item) {
160 baseMsg->InsertRepeatedMessage(*line_no, item);
161 }
162 s->AddStr(indent, (*line_no)++, out_str.str().c_str());
163 }
164 } else {
165 PrintField(baseMsg, msg, jump_lines, s, line_no, indent, reflection,
166 field, -1);
167 }
168 }
169
170 const google::protobuf::UnknownFieldSet& unknown_fields =
171 reflection->GetUnknownFields(msg);
172 if (!unknown_fields.empty()) {
173 Screen::ColorPair c = s->Color();
176 s->AddStr(indent, (*line_no)++, "Have Unknown Fields");
178 s->SetCurrentColor(c);
179 }
180}
181
183 GeneralMessageBase* baseMsg, const google::protobuf::Message& msg,
184 int* jump_lines, const Screen* s, int* line_no, int indent,
185 const google::protobuf::Reflection* ref,
186 const google::protobuf::FieldDescriptor* field, int index) {
187 std::ostringstream out_str;
188 std::ios_base::fmtflags old_flags;
189
190 switch (field->cpp_type()) {
191#define OUTPUT_FIELD(CPPTYPE, METHOD, PRECISION) \
192 case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
193 if (*jump_lines) { \
194 --(*jump_lines); \
195 } else { \
196 const std::string& fieldName = field->name(); \
197 out_str << fieldName << ": "; \
198 if (field->is_repeated()) { \
199 out_str << "[" << index << "] "; \
200 } \
201 old_flags = out_str.flags(); \
202 out_str << std::fixed << std::setprecision(PRECISION) \
203 << (field->is_repeated() \
204 ? ref->GetRepeated##METHOD(msg, field, index) \
205 : ref->Get##METHOD(msg, field)); \
206 out_str.flags(old_flags); \
207 s->AddStr(indent, (*line_no)++, out_str.str().c_str()); \
208 } \
209 break
210
211 OUTPUT_FIELD(INT32, Int32, INT_FLOAT_PRECISION);
212 OUTPUT_FIELD(INT64, Int64, INT_FLOAT_PRECISION);
213 OUTPUT_FIELD(UINT32, UInt32, INT_FLOAT_PRECISION);
214 OUTPUT_FIELD(UINT64, UInt64, INT_FLOAT_PRECISION);
215 OUTPUT_FIELD(FLOAT, Float, INT_FLOAT_PRECISION);
216 OUTPUT_FIELD(DOUBLE, Double, DOULBE_PRECISION);
217 OUTPUT_FIELD(BOOL, Bool, INT_FLOAT_PRECISION);
218#undef OUTPUT_FIELD
219
220 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
221 std::string scratch;
222 const std::string& str =
223 field->is_repeated()
224 ? ref->GetRepeatedStringReference(msg, field, index, &scratch)
225 : ref->GetStringReference(msg, field, &scratch);
226 {
227 int line_width = 0;
228 std::size_t i = 0;
229
230 for (; i < str.size() && *jump_lines > 0; ++i) {
231 if (str[i] == '\n' || str[i] == '\r') {
232 --(*jump_lines);
233 line_width = 0;
234 } else {
235 ++line_width;
236 if (line_width == s->Width()) {
237 --(*jump_lines);
238 line_width = 0;
239 }
240 }
241 }
242
243 if (*jump_lines == 0) {
244 line_width = 0;
245 unsigned line_count = 1;
246
247 const std::string& fieldName = field->name();
248 out_str << fieldName << ": ";
249 if (field->is_repeated()) {
250 out_str << "[" << index << "] ";
251 }
252
253 for (; i < str.size(); ++i) {
254 char ch = str[i];
255 if (str[i] == '\n' || str[i] == '\r') {
256 ++line_count;
257 line_width = 0;
258 ch = '\n';
259 } else {
260 ++line_width;
261 if (line_width == s->Width()) {
262 ++line_count;
263 line_width = 0;
264 }
265 }
266 out_str << ch;
267 }
268
269 s->AddStr(indent, *line_no, out_str.str().c_str());
270 (*line_no) += line_count;
271 }
272 }
273
274 break;
275 }
276
277 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
278 if (*jump_lines) {
279 --(*jump_lines);
280 } else {
281 const std::string& fieldName = field->name();
282 out_str << fieldName << ": ";
283 if (field->is_repeated()) {
284 out_str << "[" << index << "] ";
285 }
286 int enum_value = field->is_repeated()
287 ? ref->GetRepeatedEnumValue(msg, field, index)
288 : ref->GetEnumValue(msg, field);
289 const google::protobuf::EnumValueDescriptor* enum_desc =
290 field->enum_type()->FindValueByNumber(enum_value);
291 if (enum_desc != nullptr) {
292 out_str << enum_desc->name();
293 } else {
294 out_str << enum_value;
295 }
296 s->AddStr(indent, (*line_no)++, out_str.str().c_str());
297 }
298 break;
299 }
300
301 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
302 if (!*jump_lines) {
303 const std::string& fieldName = field->name();
304 out_str << fieldName;
305 if (!field->is_map()) {
306 out_str << ": ";
307 if (field->is_repeated()) {
308 out_str << "[" << index << "] ";
309 }
310 }
311 s->AddStr(indent, (*line_no)++, out_str.str().c_str());
312 } else {
313 --(*jump_lines);
314 }
316 baseMsg,
317 field->is_repeated() ? ref->GetRepeatedMessage(msg, field, index)
318 : ref->GetMessage(msg, field),
319 jump_lines, s, line_no, indent + 2);
320 break;
321 }
322}
323
325 if (line_no < 0) {
326 return nullptr;
327 }
328 auto iter = children_map_.find(line_no);
329 if (iter == children_map_.cend()) {
330 return nullptr;
331 }
332
333 return iter->second;
334}
RenderableMessage * Child(int line_no) const override
std::map< const int, GeneralMessageBase * > children_map_
static void PrintField(GeneralMessageBase *baseMsg, const google::protobuf::Message &msg, int *jump_lines, const Screen *s, int *line_no, int indent, const google::protobuf::Reflection *ref, const google::protobuf::FieldDescriptor *field, int index)
static int LineCount(const google::protobuf::Message &msg, int screen_width)
static void PrintMessage(GeneralMessageBase *baseMsg, const google::protobuf::Message &msg, int *jump_lines, const Screen *s, int *line_no, int indent)
void InsertRepeatedMessage(int line_no, GeneralMessageBase *item)
static int LineCountOfField(const google::protobuf::Message &msg, int screen_width, const google::protobuf::FieldDescriptor *field, const google::protobuf::Reflection *reflection, bool is_folded=true)
void AddStr(int x, int y, ColorPair color, const char *str) const
Definition screen.cc:152
ColorPair Color(void) const
Definition screen.h:56
int Height(void) const
Definition screen.cc:122
int Width(void) const
Definition screen.cc:120
void SetCurrentColor(ColorPair color) const
Definition screen.cc:124
void ClearCurrentColor(void) const
Definition screen.cc:145
ColorPair
Definition screen.h:34
@ RED_BLACK
Definition screen.h:38
#define OUTPUT_FIELD(CPPTYPE, METHOD, PRECISION)