string_cast.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Tencent is pleased to support the open source community by making Mars available.
  2. // Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  3. // Licensed under the MIT License (the "License"); you may not use this file except in
  4. // compliance with the License. You may obtain a copy of the License at
  5. // http://opensource.org/licenses/MIT
  6. // Unless required by applicable law or agreed to in writing, software distributed under the License is
  7. // distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  8. // either express or implied. See the License for the specific language governing permissions and
  9. // limitations under the License.
  10. /*
  11. Author : yerungui
  12. Created on : 2016-04-14
  13. */
  14. #ifndef STRING_CAST_H_
  15. #define STRING_CAST_H_
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <stdint.h>
  19. #ifndef _WIN32
  20. #define __STDC_FORMAT_MACROS
  21. #include <strings.h>
  22. #else
  23. #include "projdef.h"
  24. #endif
  25. #include <inttypes.h>
  26. #include <string.h>
  27. #include <limits>
  28. #include <string>
  29. #include "strutil.h"
  30. template<typename T>
  31. char* string_cast_itoa(const T& value, char* result, uint8_t base = 10, bool upper_case=true) {
  32. if(!(2<=base && base <= 36)) {
  33. strcpy(result, "itoa err");
  34. return result;
  35. }
  36. char* ptr_right = result, *ptr_left = result;
  37. T tmp_value = value;
  38. const char* num_mapping;
  39. if (upper_case)
  40. num_mapping = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  41. else
  42. num_mapping = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz";
  43. do {
  44. T quotient = tmp_value/base;
  45. *(ptr_right++) = num_mapping[35 + tmp_value - quotient*base];
  46. tmp_value = quotient;
  47. } while (tmp_value);
  48. #ifdef __GNUC__
  49. #pragma GCC diagnostic push
  50. #pragma GCC diagnostic ignored "-Wtype-limits"
  51. #endif
  52. if (value < 0) *(ptr_right++) = '-';
  53. #ifdef __GNUC__
  54. #pragma GCC diagnostic pop
  55. #endif
  56. *(ptr_right--) = '\0';
  57. while(ptr_left < ptr_right) {
  58. char tmp_char = *ptr_right;
  59. *(ptr_right--)= *ptr_left;
  60. *(ptr_left++) = tmp_char;
  61. }
  62. return result;
  63. }
  64. #define string_cast_hex(value) string_cast(value, 16)
  65. #define string_cast_oct(value) string_cast(value, 8)
  66. class string_cast {
  67. public:
  68. string_cast(char _value):value_(NULL) { value_cache_[0] = _value; value_cache_[1] = '\0'; value_ = value_cache_;}
  69. string_cast(int _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  70. string_cast(long _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  71. string_cast(long long _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  72. string_cast(unsigned int _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  73. string_cast(unsigned long _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  74. string_cast(unsigned long long _value, uint8_t base=10):value_(NULL) { string_cast_itoa(_value, value_cache_, base); value_ = value_cache_;}
  75. string_cast(float _value):value_(NULL) { snprintf(value_cache_, sizeof(value_cache_), "%E", _value); value_ = value_cache_; }
  76. string_cast(double _value):value_(NULL) { snprintf(value_cache_, sizeof(value_cache_), "%E", _value); value_ = value_cache_; }
  77. string_cast(long double _value):value_(NULL) { snprintf(value_cache_, sizeof(value_cache_), "%LE", _value); value_ = value_cache_;}
  78. string_cast(bool _value):value_(NULL) { if (_value) value_ = "true"; else value_ = "false"; value_cache_[0] = '\0';}
  79. string_cast(const void* _value):value_(NULL) { value_cache_[0] = '0'; value_cache_[1] = 'x'; string_cast_itoa((uintptr_t)_value, value_cache_+2, 16); value_ = value_cache_;}
  80. string_cast(const char* _value):value_(NULL) { value_ = (const char*)_value; value_cache_[0] = '\0';}
  81. string_cast(const std::string& _value):value_(NULL) { value_ = _value.c_str(); value_cache_[0] = '\0';}
  82. const char* str() const { return value_;}
  83. operator const char* () const { return value_;}
  84. private:
  85. string_cast(const string_cast&);
  86. string_cast& operator=(const string_cast&);
  87. private:
  88. const char* value_;
  89. char value_cache_[65];
  90. };
  91. namespace detail {
  92. template <typename T, int base=0>
  93. class __signed_number_cast {
  94. public:
  95. __signed_number_cast(const char* _str):value_(0), vaild_(false) {
  96. if (_str == NULL)
  97. return;
  98. char *end = NULL;
  99. vaild_ = true;
  100. value_ = strtoimax(_str, &end, base);
  101. if (_str == end) {
  102. vaild_ = false;
  103. return;
  104. }
  105. if (value_ <( std::numeric_limits<T>::min)()) {
  106. value_ =( std::numeric_limits<T>::min)();
  107. vaild_ = false;
  108. return;
  109. }
  110. if ((std::numeric_limits<T>::max)() < value_) {
  111. value_ = (std::numeric_limits<T>::max)();
  112. vaild_ = false;
  113. return;
  114. }
  115. }
  116. operator T () const { return static_cast<T>(value_); }
  117. bool valid() const { return vaild_;}
  118. private:
  119. intmax_t value_;
  120. bool vaild_;
  121. };
  122. template <typename T, int base=0>
  123. class __unsigned_number_cast {
  124. public:
  125. __unsigned_number_cast(const char* _str):value_(0), vaild_(false) {
  126. if (_str == NULL)
  127. return;
  128. char *end = NULL;
  129. vaild_ = true;
  130. value_ = strtoumax(_str, &end, base);
  131. if (_str == end) {
  132. vaild_ = false;
  133. return;
  134. }
  135. if (value_ <( std::numeric_limits<T>::min)()) {
  136. value_ =( std::numeric_limits<T>::min)();
  137. vaild_ = false;
  138. return;
  139. }
  140. if ((std::numeric_limits<T>::max)() < value_) {
  141. value_ = (std::numeric_limits<T>::max)();
  142. vaild_ = false;
  143. return;
  144. }
  145. }
  146. operator T () const { return static_cast<T>(value_); }
  147. bool valid() const { return vaild_;}
  148. private:
  149. uintmax_t value_;
  150. bool vaild_;
  151. };
  152. template <typename T>
  153. class __float_number_cast {
  154. public:
  155. __float_number_cast(const char* _str):value_(0), vaild_(false) {
  156. if (_str == NULL)
  157. return;
  158. char *end = NULL;
  159. vaild_ = true;
  160. value_ = strtod(_str, &end);
  161. if (_str == end) {
  162. vaild_ = false;
  163. }
  164. }
  165. operator T() const { return static_cast<T>(value_); }
  166. bool valid() const { return vaild_;}
  167. private:
  168. double value_;
  169. bool vaild_;
  170. };
  171. }
  172. template <typename T> class number_cast {};
  173. template <> class number_cast<int8_t > : public detail::__signed_number_cast<int8_t >
  174. { public: number_cast(const char* _str):__signed_number_cast(_str){}; };
  175. template <> class number_cast<int16_t> : public detail::__signed_number_cast<int16_t>
  176. { public: number_cast(const char* _str):__signed_number_cast(_str){}; };
  177. template <> class number_cast<int32_t> : public detail::__signed_number_cast<int32_t>
  178. { public: number_cast(const char* _str):__signed_number_cast(_str){}; };
  179. template <> class number_cast<long> : public detail::__signed_number_cast<long>
  180. { public: number_cast(const char* _str):__signed_number_cast(_str){}; };
  181. template <> class number_cast<long long> : public detail::__signed_number_cast<long long>
  182. { public: number_cast(const char* _str):__signed_number_cast(_str){}; };
  183. template <> class number_cast<uint8_t > : public detail::__unsigned_number_cast<uint8_t >
  184. { public: number_cast(const char* _str) :__unsigned_number_cast(_str){}; };
  185. template <> class number_cast<uint16_t> : public detail::__unsigned_number_cast<uint16_t>
  186. { public: number_cast(const char* _str) :__unsigned_number_cast(_str){}; };
  187. template <> class number_cast<uint32_t> : public detail::__unsigned_number_cast<uint32_t>
  188. { public: number_cast(const char* _str) :__unsigned_number_cast(_str){}; };
  189. template <> class number_cast<unsigned long> : public detail::__unsigned_number_cast<unsigned long>
  190. { public: number_cast(const char* _str) :__unsigned_number_cast(_str){}; };
  191. template <> class number_cast<unsigned long long> : public detail::__unsigned_number_cast<unsigned long long>
  192. { public: number_cast(const char* _str) :__unsigned_number_cast(_str){}; };
  193. template <> class number_cast<float> : public detail::__float_number_cast<float>
  194. { public: number_cast(const char* _str):__float_number_cast(_str){}; };
  195. template <> class number_cast<double> : public detail::__float_number_cast<double>
  196. { public: number_cast(const char* _str):__float_number_cast(_str){}; };
  197. template <>
  198. class number_cast<const char*> {
  199. public:
  200. number_cast(const char* _str):value_(NULL), vaild_(false) {
  201. if (_str == NULL)
  202. return;
  203. value_ = _str;
  204. vaild_ = true;
  205. }
  206. operator const char*() const { return value_; }
  207. bool valid() const { return vaild_;}
  208. private:
  209. const char* value_;
  210. bool vaild_;
  211. };
  212. template <>
  213. class number_cast<bool> {
  214. public:
  215. number_cast(const char* _str):value_(false), vaild_(false) {
  216. if (_str == NULL)
  217. return;
  218. std::vector<std::string> vec_split;
  219. strutil::SplitToken(_str, strutil::default_delimiters<std::string>::value(), vec_split);
  220. if (vec_split.empty()) { return; }
  221. if (vec_split[0] == "1" || 0 == strcasecmp("true", vec_split[0].c_str())) { vaild_ = true; value_ = true; }
  222. if (vec_split[0] == "0" || 0 == strcasecmp("false", vec_split[0].c_str())) { vaild_ = true; value_ = false;}
  223. }
  224. operator bool() const { return value_; }
  225. bool valid() const { return vaild_;}
  226. private:
  227. bool value_;
  228. bool vaild_;
  229. };
  230. #endif /* STRING_CAST_H_ */