OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 const google::protobuf::Type& type, int number); | 78 const google::protobuf::Type& type, int number); |
79 | 79 |
80 // Returns true if the field is packable. | 80 // Returns true if the field is packable. |
81 bool IsPackable(const google::protobuf::Field& field); | 81 bool IsPackable(const google::protobuf::Field& field); |
82 | 82 |
83 // Finds an enum value with the given number. NULL if none found. | 83 // Finds an enum value with the given number. NULL if none found. |
84 const google::protobuf::EnumValue* FindEnumValueByNumber( | 84 const google::protobuf::EnumValue* FindEnumValueByNumber( |
85 const google::protobuf::Enum& tech_enum, int number); | 85 const google::protobuf::Enum& tech_enum, int number); |
86 | 86 |
87 // Utility function to format nanos. | 87 // Utility function to format nanos. |
88 const string FormatNanos(uint32 nanos, bool with_trailing_zeros); | 88 const string FormatNanos(uint32 nanos); |
89 | 89 |
90 StatusOr<string> MapKeyDefaultValueAsString( | 90 StatusOr<string> MapKeyDefaultValueAsString( |
91 const google::protobuf::Field& field) { | 91 const google::protobuf::Field& field) { |
92 switch (field.kind()) { | 92 switch (field.kind()) { |
93 case google::protobuf::Field_Kind_TYPE_BOOL: | 93 case google::protobuf::Field_Kind_TYPE_BOOL: |
94 return string("false"); | 94 return string("false"); |
95 case google::protobuf::Field_Kind_TYPE_INT32: | 95 case google::protobuf::Field_Kind_TYPE_INT32: |
96 case google::protobuf::Field_Kind_TYPE_INT64: | 96 case google::protobuf::Field_Kind_TYPE_INT64: |
97 case google::protobuf::Field_Kind_TYPE_UINT32: | 97 case google::protobuf::Field_Kind_TYPE_UINT32: |
98 case google::protobuf::Field_Kind_TYPE_UINT64: | 98 case google::protobuf::Field_Kind_TYPE_UINT64: |
(...skipping 15 matching lines...) Expand all Loading... |
114 | 114 |
115 ProtoStreamObjectSource::ProtoStreamObjectSource( | 115 ProtoStreamObjectSource::ProtoStreamObjectSource( |
116 google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, | 116 google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, |
117 const google::protobuf::Type& type) | 117 const google::protobuf::Type& type) |
118 : stream_(stream), | 118 : stream_(stream), |
119 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), | 119 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
120 own_typeinfo_(true), | 120 own_typeinfo_(true), |
121 type_(type), | 121 type_(type), |
122 use_lower_camel_for_enums_(false), | 122 use_lower_camel_for_enums_(false), |
123 recursion_depth_(0), | 123 recursion_depth_(0), |
124 max_recursion_depth_(kDefaultMaxRecursionDepth), | 124 max_recursion_depth_(kDefaultMaxRecursionDepth) { |
125 render_unknown_fields_(false), | |
126 add_trailing_zeros_for_timestamp_and_duration_(false) { | |
127 GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; | 125 GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; |
128 } | 126 } |
129 | 127 |
130 ProtoStreamObjectSource::ProtoStreamObjectSource( | 128 ProtoStreamObjectSource::ProtoStreamObjectSource( |
131 google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo, | 129 google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo, |
132 const google::protobuf::Type& type) | 130 const google::protobuf::Type& type) |
133 : stream_(stream), | 131 : stream_(stream), |
134 typeinfo_(typeinfo), | 132 typeinfo_(typeinfo), |
135 own_typeinfo_(false), | 133 own_typeinfo_(false), |
136 type_(type), | 134 type_(type), |
137 use_lower_camel_for_enums_(false), | 135 use_lower_camel_for_enums_(false), |
138 recursion_depth_(0), | 136 recursion_depth_(0), |
139 max_recursion_depth_(kDefaultMaxRecursionDepth), | 137 max_recursion_depth_(kDefaultMaxRecursionDepth) { |
140 render_unknown_fields_(false), | |
141 add_trailing_zeros_for_timestamp_and_duration_(false) { | |
142 GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; | 138 GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; |
143 } | 139 } |
144 | 140 |
145 ProtoStreamObjectSource::~ProtoStreamObjectSource() { | 141 ProtoStreamObjectSource::~ProtoStreamObjectSource() { |
146 if (own_typeinfo_) { | 142 if (own_typeinfo_) { |
147 delete typeinfo_; | 143 delete typeinfo_; |
148 } | 144 } |
149 } | 145 } |
150 | 146 |
151 Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, | 147 Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, |
(...skipping 29 matching lines...) Expand all Loading... |
181 | 177 |
182 const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); | 178 const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); |
183 if (type_renderer != NULL) { | 179 if (type_renderer != NULL) { |
184 return (*type_renderer)(this, type, name, ow); | 180 return (*type_renderer)(this, type, name, ow); |
185 } | 181 } |
186 | 182 |
187 const google::protobuf::Field* field = NULL; | 183 const google::protobuf::Field* field = NULL; |
188 string field_name; | 184 string field_name; |
189 // last_tag set to dummy value that is different from tag. | 185 // last_tag set to dummy value that is different from tag. |
190 uint32 tag = stream_->ReadTag(), last_tag = tag + 1; | 186 uint32 tag = stream_->ReadTag(), last_tag = tag + 1; |
191 google::protobuf::UnknownFieldSet unknown_fields; | |
192 | 187 |
193 if (include_start_and_end) { | 188 if (include_start_and_end) { |
194 ow->StartObject(name); | 189 ow->StartObject(name); |
195 } | 190 } |
196 while (tag != end_tag) { | 191 while (tag != end_tag) { |
197 if (tag != last_tag) { // Update field only if tag is changed. | 192 if (tag != last_tag) { // Update field only if tag is changed. |
198 last_tag = tag; | 193 last_tag = tag; |
199 field = FindAndVerifyField(type, tag); | 194 field = FindAndVerifyField(type, tag); |
200 if (field != NULL) { | 195 if (field != NULL) { |
201 field_name = field->json_name(); | 196 field_name = field->json_name(); |
202 } | 197 } |
203 } | 198 } |
204 if (field == NULL) { | 199 if (field == NULL) { |
205 // If we didn't find a field, skip this unknown tag. | 200 // If we didn't find a field, skip this unknown tag. |
206 // TODO(wpoon): Check return boolean value. | 201 // TODO(wpoon): Check return boolean value. |
207 WireFormat::SkipField(stream_, tag, | 202 WireFormat::SkipField(stream_, tag, NULL); |
208 render_unknown_fields_ ? &unknown_fields : NULL); | |
209 tag = stream_->ReadTag(); | 203 tag = stream_->ReadTag(); |
210 continue; | 204 continue; |
211 } | 205 } |
212 | 206 |
213 if (field->cardinality() == | 207 if (field->cardinality() == |
214 google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { | 208 google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { |
215 bool check_maps = true; | 209 bool check_maps = true; |
216 | 210 |
217 if (check_maps && IsMap(*field)) { | 211 if (check_maps && IsMap(*field)) { |
218 ow->StartObject(field_name); | 212 ow->StartObject(field_name); |
219 ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); | 213 ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); |
220 ow->EndObject(); | 214 ow->EndObject(); |
221 } else { | 215 } else { |
222 ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); | 216 ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); |
223 } | 217 } |
224 } else { | 218 } else { |
225 // Render the field. | 219 // Render the field. |
226 RETURN_IF_ERROR(RenderField(field, field_name, ow)); | 220 RETURN_IF_ERROR(RenderField(field, field_name, ow)); |
227 tag = stream_->ReadTag(); | 221 tag = stream_->ReadTag(); |
228 } | 222 } |
229 } | 223 } |
230 | |
231 | |
232 if (include_start_and_end) { | 224 if (include_start_and_end) { |
233 ow->EndObject(); | 225 ow->EndObject(); |
234 } | 226 } |
235 return Status::OK; | 227 return Status::OK; |
236 } | 228 } |
237 | 229 |
238 StatusOr<uint32> ProtoStreamObjectSource::RenderList( | 230 StatusOr<uint32> ProtoStreamObjectSource::RenderList( |
239 const google::protobuf::Field* field, StringPiece name, uint32 list_tag, | 231 const google::protobuf::Field* field, StringPiece name, uint32 list_tag, |
240 ObjectWriter* ow) const { | 232 ObjectWriter* ow) const { |
241 uint32 tag_to_return = 0; | 233 uint32 tag_to_return = 0; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 if (map_key.empty()) { | 275 if (map_key.empty()) { |
284 // An absent map key is treated as the default. | 276 // An absent map key is treated as the default. |
285 const google::protobuf::Field* key_field = | 277 const google::protobuf::Field* key_field = |
286 FindFieldByNumber(*field_type, 1); | 278 FindFieldByNumber(*field_type, 1); |
287 if (key_field == NULL) { | 279 if (key_field == NULL) { |
288 // The Type info for this map entry is incorrect. It should always | 280 // The Type info for this map entry is incorrect. It should always |
289 // have a field named "key" and with field number 1. | 281 // have a field named "key" and with field number 1. |
290 return Status(util::error::INTERNAL, "Invalid map entry."); | 282 return Status(util::error::INTERNAL, "Invalid map entry."); |
291 } | 283 } |
292 ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field)); | 284 ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field)); |
293 // Key is empty, force it to render as empty (for string values). | |
294 ow->empty_name_ok_for_next_key(); | |
295 } | 285 } |
296 RETURN_IF_ERROR(RenderField(field, map_key, ow)); | 286 RETURN_IF_ERROR(RenderField(field, map_key, ow)); |
297 } else { | 287 } else { |
298 // The Type info for this map entry is incorrect. It should contain | 288 // The Type info for this map entry is incorrect. It should contain |
299 // exactly two fields with field number 1 and 2. | 289 // exactly two fields with field number 1 and 2. |
300 return Status(util::error::INTERNAL, "Invalid map entry."); | 290 return Status(util::error::INTERNAL, "Invalid map entry."); |
301 } | 291 } |
302 } | 292 } |
303 stream_->PopLimit(old_limit); | 293 stream_->PopLimit(old_limit); |
304 } while ((tag_to_return = stream_->ReadTag()) == list_tag); | 294 } while ((tag_to_return = stream_->ReadTag()) == list_tag); |
305 return tag_to_return; | 295 return tag_to_return; |
306 } | 296 } |
307 | 297 |
308 Status ProtoStreamObjectSource::RenderPacked( | 298 Status ProtoStreamObjectSource::RenderPacked( |
309 const google::protobuf::Field* field, ObjectWriter* ow) const { | 299 const google::protobuf::Field* field, ObjectWriter* ow) const { |
310 uint32 length; | 300 uint32 length; |
311 stream_->ReadVarint32(&length); | 301 stream_->ReadVarint32(&length); |
312 int old_limit = stream_->PushLimit(length); | 302 int old_limit = stream_->PushLimit(length); |
313 while (stream_->BytesUntilLimit() > 0) { | 303 while (stream_->BytesUntilLimit() > 0) { |
314 RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); | 304 RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); |
315 } | 305 } |
316 stream_->PopLimit(old_limit); | 306 stream_->PopLimit(old_limit); |
317 return Status::OK; | 307 return Status::OK; |
318 } | 308 } |
319 | 309 |
320 Status ProtoStreamObjectSource::RenderTimestamp( | 310 Status ProtoStreamObjectSource::RenderTimestamp( |
321 const ProtoStreamObjectSource* os, const google::protobuf::Type& type, | 311 const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
322 StringPiece field_name, ObjectWriter* ow) { | 312 StringPiece field_name, ObjectWriter* ow) { |
323 std::pair<int64, int32> p = os->ReadSecondsAndNanos(type); | 313 pair<int64, int32> p = os->ReadSecondsAndNanos(type); |
324 int64 seconds = p.first; | 314 int64 seconds = p.first; |
325 int32 nanos = p.second; | 315 int32 nanos = p.second; |
326 if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { | 316 if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { |
327 return Status( | 317 return Status( |
328 util::error::INTERNAL, | 318 util::error::INTERNAL, |
329 StrCat("Timestamp seconds exceeds limit for field: ", field_name)); | 319 StrCat("Timestamp seconds exceeds limit for field: ", field_name)); |
330 } | 320 } |
331 | 321 |
332 if (nanos < 0 || nanos >= kNanosPerSecond) { | 322 if (nanos < 0 || nanos >= kNanosPerSecond) { |
333 return Status( | 323 return Status( |
334 util::error::INTERNAL, | 324 util::error::INTERNAL, |
335 StrCat("Timestamp nanos exceeds limit for field: ", field_name)); | 325 StrCat("Timestamp nanos exceeds limit for field: ", field_name)); |
336 } | 326 } |
337 | 327 |
338 ow->RenderString(field_name, | 328 ow->RenderString(field_name, |
339 ::google::protobuf::internal::FormatTime(seconds, nanos)); | 329 ::google::protobuf::internal::FormatTime(seconds, nanos)); |
340 | 330 |
341 return Status::OK; | 331 return Status::OK; |
342 } | 332 } |
343 | 333 |
344 Status ProtoStreamObjectSource::RenderDuration( | 334 Status ProtoStreamObjectSource::RenderDuration( |
345 const ProtoStreamObjectSource* os, const google::protobuf::Type& type, | 335 const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
346 StringPiece field_name, ObjectWriter* ow) { | 336 StringPiece field_name, ObjectWriter* ow) { |
347 std::pair<int64, int32> p = os->ReadSecondsAndNanos(type); | 337 pair<int64, int32> p = os->ReadSecondsAndNanos(type); |
348 int64 seconds = p.first; | 338 int64 seconds = p.first; |
349 int32 nanos = p.second; | 339 int32 nanos = p.second; |
350 if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { | 340 if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { |
351 return Status( | 341 return Status( |
352 util::error::INTERNAL, | 342 util::error::INTERNAL, |
353 StrCat("Duration seconds exceeds limit for field: ", field_name)); | 343 StrCat("Duration seconds exceeds limit for field: ", field_name)); |
354 } | 344 } |
355 | 345 |
356 if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { | 346 if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { |
357 return Status( | 347 return Status( |
358 util::error::INTERNAL, | 348 util::error::INTERNAL, |
359 StrCat("Duration nanos exceeds limit for field: ", field_name)); | 349 StrCat("Duration nanos exceeds limit for field: ", field_name)); |
360 } | 350 } |
361 | 351 |
362 string sign = ""; | 352 string sign = ""; |
363 if (seconds < 0) { | 353 if (seconds < 0) { |
364 if (nanos > 0) { | 354 if (nanos > 0) { |
365 return Status(util::error::INTERNAL, | 355 return Status(util::error::INTERNAL, |
366 StrCat("Duration nanos is non-negative, but seconds is " | 356 StrCat("Duration nanos is non-negative, but seconds is " |
367 "negative for field: ", | 357 "negative for field: ", |
368 field_name)); | 358 field_name)); |
369 } | 359 } |
370 sign = "-"; | 360 sign = "-"; |
371 seconds = -seconds; | 361 seconds = -seconds; |
372 nanos = -nanos; | 362 nanos = -nanos; |
373 } else if (seconds == 0 && nanos < 0) { | 363 } else if (seconds == 0 && nanos < 0) { |
374 sign = "-"; | 364 sign = "-"; |
375 nanos = -nanos; | 365 nanos = -nanos; |
376 } | 366 } |
377 string formatted_duration = StringPrintf( | 367 string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds, |
378 "%s%lld%ss", sign.c_str(), seconds, | 368 FormatNanos(nanos).c_str()); |
379 FormatNanos(nanos, os->add_trailing_zeros_for_timestamp_and_duration_) | |
380 .c_str()); | |
381 ow->RenderString(field_name, formatted_duration); | 369 ow->RenderString(field_name, formatted_duration); |
382 return Status::OK; | 370 return Status::OK; |
383 } | 371 } |
384 | 372 |
385 Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, | 373 Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, |
386 const google::protobuf::Type& type, | 374 const google::protobuf::Type& type, |
387 StringPiece field_name, | 375 StringPiece field_name, |
388 ObjectWriter* ow) { | 376 ObjectWriter* ow) { |
389 uint32 tag = os->stream_->ReadTag(); | 377 uint32 tag = os->stream_->ReadTag(); |
390 uint64 buffer64 = 0; // default value of Double wrapper value | 378 uint64 buffer64 = 0; // default value of Double wrapper value |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 if (field->type_url() == kStructNullValueTypeUrl) { | 844 if (field->type_url() == kStructNullValueTypeUrl) { |
857 ow->RenderNull(field_name); | 845 ow->RenderNull(field_name); |
858 break; | 846 break; |
859 } | 847 } |
860 | 848 |
861 // Get the nested enum type for this field. | 849 // Get the nested enum type for this field. |
862 // TODO(skarvaje): Avoid string manipulation. Find ways to speed this | 850 // TODO(skarvaje): Avoid string manipulation. Find ways to speed this |
863 // up. | 851 // up. |
864 const google::protobuf::Enum* en = | 852 const google::protobuf::Enum* en = |
865 typeinfo_->GetEnumByTypeUrl(field->type_url()); | 853 typeinfo_->GetEnumByTypeUrl(field->type_url()); |
866 // Lookup the name of the enum, and render that. Unknown enum values | 854 // Lookup the name of the enum, and render that. Skips unknown enums. |
867 // are printed as integers. | |
868 if (en != NULL) { | 855 if (en != NULL) { |
869 const google::protobuf::EnumValue* enum_value = | 856 const google::protobuf::EnumValue* enum_value = |
870 FindEnumValueByNumber(*en, buffer32); | 857 FindEnumValueByNumber(*en, buffer32); |
871 if (enum_value != NULL) { | 858 if (enum_value != NULL) { |
872 if (use_lower_camel_for_enums_) | 859 if (use_lower_camel_for_enums_) |
873 ow->RenderString(field_name, ToCamelCase(enum_value->name())); | 860 ow->RenderString(field_name, ToCamelCase(enum_value->name())); |
874 else | 861 else |
875 ow->RenderString(field_name, enum_value->name()); | 862 ow->RenderString(field_name, enum_value->name()); |
876 } else { | |
877 ow->RenderInt32(field_name, buffer32); | |
878 } | 863 } |
879 } else { | 864 } else { |
880 ow->RenderInt32(field_name, buffer32); | 865 GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url(); |
881 } | 866 } |
882 break; | 867 break; |
883 } | 868 } |
884 case google::protobuf::Field_Kind_TYPE_STRING: { | 869 case google::protobuf::Field_Kind_TYPE_STRING: { |
885 stream_->ReadVarint32(&buffer32); // string size. | 870 stream_->ReadVarint32(&buffer32); // string size. |
886 stream_->ReadString(&strbuffer, buffer32); | 871 stream_->ReadString(&strbuffer, buffer32); |
887 ow->RenderString(field_name, strbuffer); | 872 ow->RenderString(field_name, strbuffer); |
888 break; | 873 break; |
889 } | 874 } |
890 case google::protobuf::Field_Kind_TYPE_BYTES: { | 875 case google::protobuf::Field_Kind_TYPE_BYTES: { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 // Field is a map if it is a repeated message and it has an option "map_type". | 1006 // Field is a map if it is a repeated message and it has an option "map_type". |
1022 // TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. | 1007 // TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. |
1023 bool ProtoStreamObjectSource::IsMap( | 1008 bool ProtoStreamObjectSource::IsMap( |
1024 const google::protobuf::Field& field) const { | 1009 const google::protobuf::Field& field) const { |
1025 const google::protobuf::Type* field_type = | 1010 const google::protobuf::Type* field_type = |
1026 typeinfo_->GetTypeByTypeUrl(field.type_url()); | 1011 typeinfo_->GetTypeByTypeUrl(field.type_url()); |
1027 | 1012 |
1028 // TODO(xiaofeng): Unify option names. | 1013 // TODO(xiaofeng): Unify option names. |
1029 return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && | 1014 return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && |
1030 (GetBoolOptionOrDefault(field_type->options(), | 1015 (GetBoolOptionOrDefault(field_type->options(), |
1031 "google.protobuf.MessageOptions.map_entry", | 1016 "google.protobuf.MessageOptions.map_entry", fal
se) || |
1032 false) || | 1017 GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); |
1033 GetBoolOptionOrDefault(field_type->options(), "map_entry", false) || | |
1034 GetBoolOptionOrDefault(field_type->options(), | |
1035 "proto2.MessageOptions.map_entry", false)); | |
1036 } | 1018 } |
1037 | 1019 |
1038 std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( | 1020 std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( |
1039 const google::protobuf::Type& type) const { | 1021 const google::protobuf::Type& type) const { |
1040 uint64 seconds = 0; | 1022 uint64 seconds = 0; |
1041 uint32 nanos = 0; | 1023 uint32 nanos = 0; |
1042 uint32 tag = 0; | 1024 uint32 tag = 0; |
1043 int64 signed_seconds = 0; | 1025 int64 signed_seconds = 0; |
1044 int32 signed_nanos = 0; | 1026 int32 signed_nanos = 0; |
1045 | 1027 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); | 1085 const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); |
1104 if (ev.number() == number) { | 1086 if (ev.number() == number) { |
1105 return &ev; | 1087 return &ev; |
1106 } | 1088 } |
1107 } | 1089 } |
1108 return NULL; | 1090 return NULL; |
1109 } | 1091 } |
1110 | 1092 |
1111 // TODO(skarvaje): Look into optimizing this by not doing computation on | 1093 // TODO(skarvaje): Look into optimizing this by not doing computation on |
1112 // double. | 1094 // double. |
1113 const string FormatNanos(uint32 nanos, bool with_trailing_zeros) { | 1095 const string FormatNanos(uint32 nanos) { |
1114 if (nanos == 0) { | |
1115 return with_trailing_zeros ? ".000" : ""; | |
1116 } | |
1117 | |
1118 const char* format = | 1096 const char* format = |
1119 (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; | 1097 (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; |
1120 string formatted = | 1098 string formatted = |
1121 StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond); | 1099 StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond); |
1122 // remove the leading 0 before decimal. | 1100 // remove the leading 0 before decimal. |
1123 return formatted.substr(1); | 1101 return formatted.substr(1); |
1124 } | 1102 } |
1125 } // namespace | 1103 } // namespace |
1126 | 1104 |
1127 } // namespace converter | 1105 } // namespace converter |
1128 } // namespace util | 1106 } // namespace util |
1129 } // namespace protobuf | 1107 } // namespace protobuf |
1130 } // namespace google | 1108 } // namespace google |
1131 | |
OLD | NEW |