诸暨麻将添加redis
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

422 řádky
14 KiB

  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/datapiece.h>
  31. #include <google/protobuf/struct.pb.h>
  32. #include <google/protobuf/type.pb.h>
  33. #include <google/protobuf/descriptor.h>
  34. #include <google/protobuf/util/internal/utility.h>
  35. #include <google/protobuf/stubs/strutil.h>
  36. #include <google/protobuf/stubs/mathlimits.h>
  37. #include <google/protobuf/stubs/mathutil.h>
  38. namespace google {
  39. namespace protobuf {
  40. namespace util {
  41. namespace converter {
  42. using util::Status;
  43. using util::StatusOr;
  44. using util::error::Code;
  45. namespace {
  46. inline Status InvalidArgument(StringPiece value_str) {
  47. return Status(util::error::INVALID_ARGUMENT, value_str);
  48. }
  49. template <typename To, typename From>
  50. StatusOr<To> ValidateNumberConversion(To after, From before) {
  51. if (after == before &&
  52. MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
  53. return after;
  54. } else {
  55. return InvalidArgument(std::is_integral<From>::value
  56. ? ValueAsString(before)
  57. : std::is_same<From, double>::value
  58. ? DoubleAsString(before)
  59. : FloatAsString(before));
  60. }
  61. }
  62. // For general conversion between
  63. // int32, int64, uint32, uint64, double and float
  64. // except conversion between double and float.
  65. template <typename To, typename From>
  66. StatusOr<To> NumberConvertAndCheck(From before) {
  67. if (std::is_same<From, To>::value) return before;
  68. To after = static_cast<To>(before);
  69. return ValidateNumberConversion(after, before);
  70. }
  71. // For conversion to integer types (int32, int64, uint32, uint64) from floating
  72. // point types (double, float) only.
  73. template <typename To, typename From>
  74. StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
  75. if (std::is_same<From, To>::value) return before;
  76. To after = static_cast<To>(before);
  77. return ValidateNumberConversion(after, before);
  78. }
  79. // For conversion between double and float only.
  80. StatusOr<double> FloatToDouble(float before) {
  81. // Casting float to double should just work as double has more precision
  82. // than float.
  83. return static_cast<double>(before);
  84. }
  85. StatusOr<float> DoubleToFloat(double before) {
  86. if (MathLimits<double>::IsNaN(before)) {
  87. return std::numeric_limits<float>::quiet_NaN();
  88. } else if (!MathLimits<double>::IsFinite(before)) {
  89. // Converting a double +inf/-inf to float should just work.
  90. return static_cast<float>(before);
  91. } else if (before > std::numeric_limits<float>::max() ||
  92. before < -std::numeric_limits<float>::max()) {
  93. // Double value outside of the range of float.
  94. return InvalidArgument(DoubleAsString(before));
  95. } else {
  96. return static_cast<float>(before);
  97. }
  98. }
  99. } // namespace
  100. StatusOr<int32> DataPiece::ToInt32() const {
  101. if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);
  102. if (type_ == TYPE_DOUBLE)
  103. return FloatingPointToIntConvertAndCheck<int32, double>(double_);
  104. if (type_ == TYPE_FLOAT)
  105. return FloatingPointToIntConvertAndCheck<int32, float>(float_);
  106. return GenericConvert<int32>();
  107. }
  108. StatusOr<uint32> DataPiece::ToUint32() const {
  109. if (type_ == TYPE_STRING)
  110. return StringToNumber<uint32>(safe_strtou32);
  111. if (type_ == TYPE_DOUBLE)
  112. return FloatingPointToIntConvertAndCheck<uint32, double>(double_);
  113. if (type_ == TYPE_FLOAT)
  114. return FloatingPointToIntConvertAndCheck<uint32, float>(float_);
  115. return GenericConvert<uint32>();
  116. }
  117. StatusOr<int64> DataPiece::ToInt64() const {
  118. if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);
  119. if (type_ == TYPE_DOUBLE)
  120. return FloatingPointToIntConvertAndCheck<int64, double>(double_);
  121. if (type_ == TYPE_FLOAT)
  122. return FloatingPointToIntConvertAndCheck<int64, float>(float_);
  123. return GenericConvert<int64>();
  124. }
  125. StatusOr<uint64> DataPiece::ToUint64() const {
  126. if (type_ == TYPE_STRING)
  127. return StringToNumber<uint64>(safe_strtou64);
  128. if (type_ == TYPE_DOUBLE)
  129. return FloatingPointToIntConvertAndCheck<uint64, double>(double_);
  130. if (type_ == TYPE_FLOAT)
  131. return FloatingPointToIntConvertAndCheck<uint64, float>(float_);
  132. return GenericConvert<uint64>();
  133. }
  134. StatusOr<double> DataPiece::ToDouble() const {
  135. if (type_ == TYPE_FLOAT) {
  136. return FloatToDouble(float_);
  137. }
  138. if (type_ == TYPE_STRING) {
  139. if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
  140. if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
  141. if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
  142. StatusOr<double> value = StringToNumber<double>(safe_strtod);
  143. if (value.ok() && !MathLimits<double>::IsFinite(value.ValueOrDie())) {
  144. // safe_strtod converts out-of-range values to +inf/-inf, but we want
  145. // to report them as errors.
  146. return InvalidArgument(StrCat("\"", str_, "\""));
  147. } else {
  148. return value;
  149. }
  150. }
  151. return GenericConvert<double>();
  152. }
  153. StatusOr<float> DataPiece::ToFloat() const {
  154. if (type_ == TYPE_DOUBLE) {
  155. return DoubleToFloat(double_);
  156. }
  157. if (type_ == TYPE_STRING) {
  158. if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
  159. if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity();
  160. if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN();
  161. // SafeStrToFloat() is used instead of safe_strtof() because the later
  162. // does not fail on inputs like SimpleDtoa(DBL_MAX).
  163. return StringToNumber<float>(SafeStrToFloat);
  164. }
  165. return GenericConvert<float>();
  166. }
  167. StatusOr<bool> DataPiece::ToBool() const {
  168. switch (type_) {
  169. case TYPE_BOOL:
  170. return bool_;
  171. case TYPE_STRING:
  172. return StringToNumber<bool>(safe_strtob);
  173. default:
  174. return InvalidArgument(
  175. ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
  176. }
  177. }
  178. StatusOr<std::string> DataPiece::ToString() const {
  179. switch (type_) {
  180. case TYPE_STRING:
  181. return std::string(str_);
  182. case TYPE_BYTES: {
  183. std::string base64;
  184. Base64Escape(str_, &base64);
  185. return base64;
  186. }
  187. default:
  188. return InvalidArgument(
  189. ValueAsStringOrDefault("Cannot convert to string."));
  190. }
  191. }
  192. std::string DataPiece::ValueAsStringOrDefault(
  193. StringPiece default_string) const {
  194. switch (type_) {
  195. case TYPE_INT32:
  196. return StrCat(i32_);
  197. case TYPE_INT64:
  198. return StrCat(i64_);
  199. case TYPE_UINT32:
  200. return StrCat(u32_);
  201. case TYPE_UINT64:
  202. return StrCat(u64_);
  203. case TYPE_DOUBLE:
  204. return DoubleAsString(double_);
  205. case TYPE_FLOAT:
  206. return FloatAsString(float_);
  207. case TYPE_BOOL:
  208. return SimpleBtoa(bool_);
  209. case TYPE_STRING:
  210. return StrCat("\"", str_.ToString(), "\"");
  211. case TYPE_BYTES: {
  212. std::string base64;
  213. WebSafeBase64Escape(str_, &base64);
  214. return StrCat("\"", base64, "\"");
  215. }
  216. case TYPE_NULL:
  217. return "null";
  218. default:
  219. return std::string(default_string);
  220. }
  221. }
  222. StatusOr<std::string> DataPiece::ToBytes() const {
  223. if (type_ == TYPE_BYTES) return str_.ToString();
  224. if (type_ == TYPE_STRING) {
  225. std::string decoded;
  226. if (!DecodeBase64(str_, &decoded)) {
  227. return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
  228. }
  229. return decoded;
  230. } else {
  231. return InvalidArgument(ValueAsStringOrDefault(
  232. "Wrong type. Only String or Bytes can be converted to Bytes."));
  233. }
  234. }
  235. StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
  236. bool use_lower_camel_for_enums,
  237. bool case_insensitive_enum_parsing,
  238. bool ignore_unknown_enum_values,
  239. bool* is_unknown_enum_value) const {
  240. if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
  241. if (type_ == TYPE_STRING) {
  242. // First try the given value as a name.
  243. std::string enum_name = std::string(str_);
  244. const google::protobuf::EnumValue* value =
  245. FindEnumValueByNameOrNull(enum_type, enum_name);
  246. if (value != nullptr) return value->number();
  247. // Check if int version of enum is sent as string.
  248. StatusOr<int32> int_value = ToInt32();
  249. if (int_value.ok()) {
  250. if (const google::protobuf::EnumValue* enum_value =
  251. FindEnumValueByNumberOrNull(enum_type, int_value.ValueOrDie())) {
  252. return enum_value->number();
  253. }
  254. }
  255. // Next try a normalized name.
  256. bool should_normalize_enum =
  257. case_insensitive_enum_parsing || use_lower_camel_for_enums;
  258. if (should_normalize_enum) {
  259. for (std::string::iterator it = enum_name.begin(); it != enum_name.end();
  260. ++it) {
  261. *it = *it == '-' ? '_' : ascii_toupper(*it);
  262. }
  263. value = FindEnumValueByNameOrNull(enum_type, enum_name);
  264. if (value != nullptr) return value->number();
  265. }
  266. // If use_lower_camel_for_enums is true try with enum name without
  267. // underscore. This will also accept camel case names as the enum_name has
  268. // been normalized before.
  269. if (use_lower_camel_for_enums) {
  270. value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name);
  271. if (value != nullptr) return value->number();
  272. }
  273. // If ignore_unknown_enum_values is true an unknown enum value is ignored.
  274. if (ignore_unknown_enum_values) {
  275. *is_unknown_enum_value = true;
  276. return enum_type->enumvalue(0).number();
  277. }
  278. } else {
  279. // We don't need to check whether the value is actually declared in the
  280. // enum because we preserve unknown enum values as well.
  281. return ToInt32();
  282. }
  283. return InvalidArgument(
  284. ValueAsStringOrDefault("Cannot find enum with given value."));
  285. }
  286. template <typename To>
  287. StatusOr<To> DataPiece::GenericConvert() const {
  288. switch (type_) {
  289. case TYPE_INT32:
  290. return NumberConvertAndCheck<To, int32>(i32_);
  291. case TYPE_INT64:
  292. return NumberConvertAndCheck<To, int64>(i64_);
  293. case TYPE_UINT32:
  294. return NumberConvertAndCheck<To, uint32>(u32_);
  295. case TYPE_UINT64:
  296. return NumberConvertAndCheck<To, uint64>(u64_);
  297. case TYPE_DOUBLE:
  298. return NumberConvertAndCheck<To, double>(double_);
  299. case TYPE_FLOAT:
  300. return NumberConvertAndCheck<To, float>(float_);
  301. default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
  302. return InvalidArgument(ValueAsStringOrDefault(
  303. "Wrong type. Bool, Enum, String and Cord not supported in "
  304. "GenericConvert."));
  305. }
  306. }
  307. template <typename To>
  308. StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
  309. To*)) const {
  310. if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
  311. return InvalidArgument(StrCat("\"", str_, "\""));
  312. }
  313. To result;
  314. if (func(str_, &result)) return result;
  315. return InvalidArgument(StrCat("\"", string(str_), "\""));
  316. }
  317. bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const {
  318. // Try web-safe decode first, if it fails, try the non-web-safe decode.
  319. if (WebSafeBase64Unescape(src, dest)) {
  320. if (use_strict_base64_decoding_) {
  321. // In strict mode, check if the escaped version gives us the same value as
  322. // unescaped.
  323. std::string encoded;
  324. // WebSafeBase64Escape does no padding by default.
  325. WebSafeBase64Escape(*dest, &encoded);
  326. // Remove trailing padding '=' characters before comparison.
  327. StringPiece src_no_padding = StringPiece(src).substr(
  328. 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
  329. : src.length());
  330. return encoded == src_no_padding;
  331. }
  332. return true;
  333. }
  334. if (Base64Unescape(src, dest)) {
  335. if (use_strict_base64_decoding_) {
  336. std::string encoded;
  337. Base64Escape(
  338. reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
  339. &encoded, false);
  340. StringPiece src_no_padding = StringPiece(src).substr(
  341. 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
  342. : src.length());
  343. return encoded == src_no_padding;
  344. }
  345. return true;
  346. }
  347. return false;
  348. }
  349. void DataPiece::InternalCopy(const DataPiece& other) {
  350. type_ = other.type_;
  351. use_strict_base64_decoding_ = other.use_strict_base64_decoding_;
  352. switch (type_) {
  353. case TYPE_INT32:
  354. case TYPE_INT64:
  355. case TYPE_UINT32:
  356. case TYPE_UINT64:
  357. case TYPE_DOUBLE:
  358. case TYPE_FLOAT:
  359. case TYPE_BOOL:
  360. case TYPE_ENUM:
  361. case TYPE_NULL:
  362. case TYPE_BYTES:
  363. case TYPE_STRING: {
  364. str_ = other.str_;
  365. break;
  366. }
  367. }
  368. }
  369. } // namespace converter
  370. } // namespace util
  371. } // namespace protobuf
  372. } // namespace google