Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc

Issue 2590803003: Revert "third_party/protobuf: Update to HEAD (83d681ee2c)" (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698