utility.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <google/protobuf/util/internal/utility.h>
  31. #include <google/protobuf/stubs/callback.h>
  32. #include <google/protobuf/stubs/common.h>
  33. #include <google/protobuf/stubs/logging.h>
  34. #include <google/protobuf/wrappers.pb.h>
  35. #include <google/protobuf/descriptor.pb.h>
  36. #include <google/protobuf/descriptor.h>
  37. #include <google/protobuf/util/internal/constants.h>
  38. #include <google/protobuf/stubs/strutil.h>
  39. #include <google/protobuf/stubs/map_util.h>
  40. #include <google/protobuf/stubs/mathlimits.h>
  41. #include <algorithm>
  42. namespace google {
  43. namespace protobuf {
  44. namespace util {
  45. namespace converter {
  46. namespace {
  47. const StringPiece SkipWhiteSpace(StringPiece str) {
  48. StringPiece::size_type i;
  49. for (i = 0; i < str.size() && isspace(str[i]); ++i) {
  50. }
  51. GOOGLE_DCHECK(i == str.size() || !isspace(str[i]));
  52. return str.substr(i);
  53. }
  54. } // namespace
  55. bool GetBoolOptionOrDefault(
  56. const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
  57. const string& option_name, bool default_value) {
  58. const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
  59. if (opt == NULL) {
  60. return default_value;
  61. }
  62. return GetBoolFromAny(opt->value());
  63. }
  64. int64 GetInt64OptionOrDefault(
  65. const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
  66. const string& option_name, int64 default_value) {
  67. const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
  68. if (opt == NULL) {
  69. return default_value;
  70. }
  71. return GetInt64FromAny(opt->value());
  72. }
  73. double GetDoubleOptionOrDefault(
  74. const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
  75. const string& option_name, double default_value) {
  76. const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
  77. if (opt == NULL) {
  78. return default_value;
  79. }
  80. return GetDoubleFromAny(opt->value());
  81. }
  82. string GetStringOptionOrDefault(
  83. const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
  84. const string& option_name, const string& default_value) {
  85. const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
  86. if (opt == NULL) {
  87. return default_value;
  88. }
  89. return GetStringFromAny(opt->value());
  90. }
  91. template <typename T>
  92. void ParseFromAny(const string& data, T* result) {
  93. result->ParseFromString(data);
  94. }
  95. // Returns a boolean value contained in Any type.
  96. // TODO(skarvaje): Add type checking & error messages here.
  97. bool GetBoolFromAny(const google::protobuf::Any& any) {
  98. google::protobuf::BoolValue b;
  99. ParseFromAny(any.value(), &b);
  100. return b.value();
  101. }
  102. int64 GetInt64FromAny(const google::protobuf::Any& any) {
  103. google::protobuf::Int64Value i;
  104. ParseFromAny(any.value(), &i);
  105. return i.value();
  106. }
  107. double GetDoubleFromAny(const google::protobuf::Any& any) {
  108. google::protobuf::DoubleValue i;
  109. ParseFromAny(any.value(), &i);
  110. return i.value();
  111. }
  112. string GetStringFromAny(const google::protobuf::Any& any) {
  113. google::protobuf::StringValue s;
  114. ParseFromAny(any.value(), &s);
  115. return s.value();
  116. }
  117. const StringPiece GetTypeWithoutUrl(StringPiece type_url) {
  118. if (type_url.size() > kTypeUrlSize && type_url[kTypeUrlSize] == '/') {
  119. return type_url.substr(kTypeUrlSize + 1);
  120. } else {
  121. size_t idx = type_url.rfind('/');
  122. return type_url.substr(idx + 1);
  123. }
  124. }
  125. const string GetFullTypeWithUrl(StringPiece simple_type) {
  126. return StrCat(kTypeServiceBaseUrl, "/", simple_type);
  127. }
  128. const google::protobuf::Option* FindOptionOrNull(
  129. const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
  130. const string& option_name) {
  131. for (int i = 0; i < options.size(); ++i) {
  132. const google::protobuf::Option& opt = options.Get(i);
  133. if (opt.name() == option_name) {
  134. return &opt;
  135. }
  136. }
  137. return NULL;
  138. }
  139. const google::protobuf::Field* FindFieldInTypeOrNull(
  140. const google::protobuf::Type* type, StringPiece field_name) {
  141. if (type != NULL) {
  142. for (int i = 0; i < type->fields_size(); ++i) {
  143. const google::protobuf::Field& field = type->fields(i);
  144. if (field.name() == field_name) {
  145. return &field;
  146. }
  147. }
  148. }
  149. return NULL;
  150. }
  151. const google::protobuf::Field* FindJsonFieldInTypeOrNull(
  152. const google::protobuf::Type* type, StringPiece json_name) {
  153. if (type != NULL) {
  154. for (int i = 0; i < type->fields_size(); ++i) {
  155. const google::protobuf::Field& field = type->fields(i);
  156. if (field.json_name() == json_name) {
  157. return &field;
  158. }
  159. }
  160. }
  161. return NULL;
  162. }
  163. const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
  164. const google::protobuf::Type* type, int32 number) {
  165. if (type != NULL) {
  166. for (int i = 0; i < type->fields_size(); ++i) {
  167. const google::protobuf::Field& field = type->fields(i);
  168. if (field.number() == number) {
  169. return &field;
  170. }
  171. }
  172. }
  173. return NULL;
  174. }
  175. const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
  176. const google::protobuf::Enum* enum_type, StringPiece enum_name) {
  177. if (enum_type != NULL) {
  178. for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
  179. const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
  180. if (enum_value.name() == enum_name) {
  181. return &enum_value;
  182. }
  183. }
  184. }
  185. return NULL;
  186. }
  187. const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
  188. const google::protobuf::Enum* enum_type, int32 value) {
  189. if (enum_type != NULL) {
  190. for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
  191. const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
  192. if (enum_value.number() == value) {
  193. return &enum_value;
  194. }
  195. }
  196. }
  197. return NULL;
  198. }
  199. const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull(
  200. const google::protobuf::Enum* enum_type, StringPiece enum_name) {
  201. if (enum_type != NULL) {
  202. for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
  203. const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
  204. string enum_name_without_underscore = enum_value.name();
  205. // Remove underscore from the name.
  206. enum_name_without_underscore.erase(
  207. std::remove(enum_name_without_underscore.begin(),
  208. enum_name_without_underscore.end(), '_'),
  209. enum_name_without_underscore.end());
  210. // Make the name uppercase.
  211. for (string::iterator it = enum_name_without_underscore.begin();
  212. it != enum_name_without_underscore.end(); ++it) {
  213. *it = ascii_toupper(*it);
  214. }
  215. if (enum_name_without_underscore == enum_name) {
  216. return &enum_value;
  217. }
  218. }
  219. }
  220. return NULL;
  221. }
  222. string ToCamelCase(const StringPiece input) {
  223. bool capitalize_next = false;
  224. bool was_cap = true;
  225. bool is_cap = false;
  226. bool first_word = true;
  227. string result;
  228. result.reserve(input.size());
  229. for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
  230. is_cap = ascii_isupper(input[i]);
  231. if (input[i] == '_') {
  232. capitalize_next = true;
  233. if (!result.empty()) first_word = false;
  234. continue;
  235. } else if (first_word) {
  236. // Consider when the current character B is capitalized,
  237. // first word ends when:
  238. // 1) following a lowercase: "...aB..."
  239. // 2) followed by a lowercase: "...ABc..."
  240. if (!result.empty() && is_cap &&
  241. (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
  242. first_word = false;
  243. result.push_back(input[i]);
  244. } else {
  245. result.push_back(ascii_tolower(input[i]));
  246. continue;
  247. }
  248. } else if (capitalize_next) {
  249. capitalize_next = false;
  250. if (ascii_islower(input[i])) {
  251. result.push_back(ascii_toupper(input[i]));
  252. continue;
  253. } else {
  254. result.push_back(input[i]);
  255. continue;
  256. }
  257. } else {
  258. result.push_back(ascii_tolower(input[i]));
  259. }
  260. }
  261. return result;
  262. }
  263. string ToSnakeCase(StringPiece input) {
  264. bool was_not_underscore = false; // Initialize to false for case 1 (below)
  265. bool was_not_cap = false;
  266. string result;
  267. result.reserve(input.size() << 1);
  268. for (size_t i = 0; i < input.size(); ++i) {
  269. if (ascii_isupper(input[i])) {
  270. // Consider when the current character B is capitalized:
  271. // 1) At beginning of input: "B..." => "b..."
  272. // (e.g. "Biscuit" => "biscuit")
  273. // 2) Following a lowercase: "...aB..." => "...a_b..."
  274. // (e.g. "gBike" => "g_bike")
  275. // 3) At the end of input: "...AB" => "...ab"
  276. // (e.g. "GoogleLAB" => "google_lab")
  277. // 4) Followed by a lowercase: "...ABc..." => "...a_bc..."
  278. // (e.g. "GBike" => "g_bike")
  279. if (was_not_underscore && // case 1 out
  280. (was_not_cap || // case 2 in, case 3 out
  281. (i + 1 < input.size() && // case 3 out
  282. ascii_islower(input[i + 1])))) { // case 4 in
  283. // We add an underscore for case 2 and case 4.
  284. result.push_back('_');
  285. }
  286. result.push_back(ascii_tolower(input[i]));
  287. was_not_underscore = true;
  288. was_not_cap = false;
  289. } else {
  290. result.push_back(input[i]);
  291. was_not_underscore = input[i] != '_';
  292. was_not_cap = true;
  293. }
  294. }
  295. return result;
  296. }
  297. set<string>* well_known_types_ = NULL;
  298. GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_);
  299. const char* well_known_types_name_array_[] = {
  300. "google.protobuf.Timestamp", "google.protobuf.Duration",
  301. "google.protobuf.DoubleValue", "google.protobuf.FloatValue",
  302. "google.protobuf.Int64Value", "google.protobuf.UInt64Value",
  303. "google.protobuf.Int32Value", "google.protobuf.UInt32Value",
  304. "google.protobuf.BoolValue", "google.protobuf.StringValue",
  305. "google.protobuf.BytesValue", "google.protobuf.FieldMask"};
  306. void DeleteWellKnownTypes() { delete well_known_types_; }
  307. void InitWellKnownTypes() {
  308. well_known_types_ = new set<string>;
  309. for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
  310. well_known_types_->insert(well_known_types_name_array_[i]);
  311. }
  312. google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes);
  313. }
  314. bool IsWellKnownType(const string& type_name) {
  315. InitWellKnownTypes();
  316. return ContainsKey(*well_known_types_, type_name);
  317. }
  318. bool IsValidBoolString(const string& bool_string) {
  319. return bool_string == "true" || bool_string == "false" ||
  320. bool_string == "1" || bool_string == "0";
  321. }
  322. bool IsMap(const google::protobuf::Field& field,
  323. const google::protobuf::Type& type) {
  324. return (
  325. field.cardinality() ==
  326. google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
  327. (GetBoolOptionOrDefault(
  328. type.options(), "google.protobuf.MessageOptions.map_entry", false) ||
  329. GetBoolOptionOrDefault(type.options(), "proto2.MessageOptions.map_entry",
  330. false)));
  331. }
  332. bool IsMessageSetWireFormat(const google::protobuf::Type& type) {
  333. return (
  334. GetBoolOptionOrDefault(
  335. type.options(),
  336. "google.protobuf.MessageOptions.message_set_wire_format", false) ||
  337. GetBoolOptionOrDefault(type.options(),
  338. "proto2.MessageOptions.message_set_wire_format",
  339. false));
  340. }
  341. string DoubleAsString(double value) {
  342. if (MathLimits<double>::IsPosInf(value)) return "Infinity";
  343. if (MathLimits<double>::IsNegInf(value)) return "-Infinity";
  344. if (MathLimits<double>::IsNaN(value)) return "NaN";
  345. return SimpleDtoa(value);
  346. }
  347. string FloatAsString(float value) {
  348. if (MathLimits<float>::IsFinite(value)) return SimpleFtoa(value);
  349. return DoubleAsString(value);
  350. }
  351. bool SafeStrToFloat(StringPiece str, float* value) {
  352. double double_value;
  353. if (!safe_strtod(str, &double_value)) {
  354. return false;
  355. }
  356. if (MathLimits<double>::IsInf(double_value) ||
  357. MathLimits<double>::IsNaN(double_value))
  358. return false;
  359. // Fail if the value is not representable in float.
  360. if (double_value > std::numeric_limits<float>::max() ||
  361. double_value < -std::numeric_limits<float>::max()) {
  362. return false;
  363. }
  364. *value = static_cast<float>(double_value);
  365. return true;
  366. }
  367. } // namespace converter
  368. } // namespace util
  369. } // namespace protobuf
  370. } // namespace google