stringhelper.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // -*- C++ -*-
  2. // Module: Log4CPLUS
  3. // File: stringhelper.h
  4. // Created: 3/2003
  5. // Author: Tad E. Smith
  6. //
  7. //
  8. // Copyright 2003-2017 Tad E. Smith
  9. //
  10. // Licensed under the Apache License, Version 2.0 (the "License");
  11. // you may not use this file except in compliance with the License.
  12. // You may obtain a copy of the License at
  13. //
  14. // http://www.apache.org/licenses/LICENSE-2.0
  15. //
  16. // Unless required by applicable law or agreed to in writing, software
  17. // distributed under the License is distributed on an "AS IS" BASIS,
  18. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. // See the License for the specific language governing permissions and
  20. // limitations under the License.
  21. /** @file */
  22. #ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_
  23. #define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_
  24. #include <log4cplus/config.hxx>
  25. #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
  26. #pragma once
  27. #endif
  28. #include <log4cplus/tstring.h>
  29. #include <algorithm>
  30. #include <limits>
  31. namespace log4cplus {
  32. namespace helpers {
  33. /**
  34. * Returns <code>s</code> in upper case.
  35. */
  36. LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s);
  37. LOG4CPLUS_EXPORT tchar toUpper(tchar);
  38. /**
  39. * Returns <code>s</code> in lower case.
  40. */
  41. LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s);
  42. LOG4CPLUS_EXPORT tchar toLower(tchar);
  43. /**
  44. * Tokenize <code>s</code> using <code>c</code> as the delimiter and
  45. * put the resulting tokens in <code>_result</code>. If
  46. * <code>collapseTokens</code> is false, multiple adjacent delimiters
  47. * will result in zero length tokens.
  48. *
  49. * <b>Example:</b>
  50. * <pre>
  51. * string s = // Set string with '.' as delimiters
  52. * list<log4cplus::tstring> tokens;
  53. * tokenize(s, '.', back_insert_iterator<list<string> >(tokens));
  54. * </pre>
  55. */
  56. template <class StringType, class OutputIter>
  57. inline
  58. void
  59. tokenize(const StringType& s, typename StringType::value_type c,
  60. OutputIter result, bool collapseTokens = true)
  61. {
  62. typedef typename StringType::size_type size_type;
  63. size_type const slen = s.length();
  64. size_type first = 0;
  65. size_type i = 0;
  66. for (i=0; i < slen; ++i)
  67. {
  68. if (s[i] == c)
  69. {
  70. *result = StringType (s, first, i - first);
  71. ++result;
  72. if (collapseTokens)
  73. while (i+1 < slen && s[i+1] == c)
  74. ++i;
  75. first = i + 1;
  76. }
  77. }
  78. if (first != i)
  79. *result = StringType (s, first, i - first);
  80. else if (! collapseTokens && first == i)
  81. *result = StringType ();
  82. }
  83. template <typename intType, typename stringType, bool isSigned>
  84. struct ConvertIntegerToStringHelper;
  85. template <typename intType, typename charType>
  86. struct ConvertIntegerToStringHelper<intType, charType, true>
  87. {
  88. static inline
  89. void
  90. step1 (charType * & it, intType & value)
  91. {
  92. // The sign of the result of the modulo operator is
  93. // implementation defined. That's why we work with
  94. // positive counterpart instead. Also, in twos
  95. // complement arithmetic the smallest negative number
  96. // does not have positive counterpart; the range is
  97. // asymetric. That's why we handle the case of value
  98. // == min() specially here.
  99. if (LOG4CPLUS_UNLIKELY (
  100. value == (std::numeric_limits<intType>::min) ()))
  101. {
  102. intType const r = value / 10;
  103. intType const a = (-r) * 10;
  104. intType const mod = -(a + value);
  105. value = -r;
  106. *(it - 1)
  107. = static_cast<charType>(LOG4CPLUS_TEXT('0') + mod);
  108. --it;
  109. }
  110. else
  111. value = -value;
  112. }
  113. static
  114. bool
  115. is_negative (intType val)
  116. {
  117. return val < 0;
  118. }
  119. };
  120. template <typename intType, typename charType>
  121. struct ConvertIntegerToStringHelper<intType, charType, false>
  122. {
  123. static inline
  124. void
  125. step1 (charType * &, intType &)
  126. {
  127. // This will never be called for unsigned types.
  128. }
  129. static
  130. bool
  131. is_negative (intType)
  132. {
  133. return false;
  134. }
  135. };
  136. template <class stringType, class intType>
  137. inline
  138. void
  139. convertIntegerToString (stringType & str, intType value)
  140. {
  141. typedef std::numeric_limits<intType> intTypeLimits;
  142. typedef typename stringType::value_type charType;
  143. typedef ConvertIntegerToStringHelper<intType, charType,
  144. intTypeLimits::is_signed> HelperType;
  145. charType buffer[intTypeLimits::digits10 + 2];
  146. const std::size_t buffer_size
  147. = sizeof (buffer) / sizeof (charType);
  148. charType * it = &buffer[buffer_size];
  149. charType const * const buf_end = &buffer[buffer_size];
  150. if (LOG4CPLUS_UNLIKELY (value == 0))
  151. {
  152. --it;
  153. *it = LOG4CPLUS_TEXT('0');
  154. }
  155. else
  156. {
  157. bool const negative = HelperType::is_negative (value);
  158. if (negative)
  159. HelperType::step1 (it, value);
  160. for (; value != 0; --it)
  161. {
  162. intType mod = value % 10;
  163. value = value / 10;
  164. *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0')
  165. + mod);
  166. }
  167. if (negative)
  168. {
  169. --it;
  170. *it = LOG4CPLUS_TEXT('-');
  171. }
  172. }
  173. str.assign (static_cast<charType const *>(it), buf_end);
  174. }
  175. template<class intType>
  176. inline
  177. tstring
  178. convertIntegerToString (intType value)
  179. {
  180. tstring result;
  181. convertIntegerToString (result, value);
  182. return result;
  183. }
  184. template<class intType>
  185. inline
  186. std::string
  187. convertIntegerToNarrowString (intType value)
  188. {
  189. std::string result;
  190. convertIntegerToString (result, value);
  191. return result;
  192. }
  193. //! Join a list of items into a string.
  194. template <typename Iterator, typename Separator>
  195. inline
  196. void
  197. join_worker (tstring & result, Iterator & start, Iterator & last,
  198. Separator const & sep)
  199. {
  200. if (start != last)
  201. result = *start++;
  202. for (; start != last; ++start)
  203. {
  204. result += sep;
  205. result += *start;
  206. }
  207. }
  208. //! Join a list of items into a string.
  209. template <typename Iterator>
  210. inline
  211. void
  212. join (tstring & result, Iterator start, Iterator last,
  213. tstring const & sep)
  214. {
  215. join_worker (result, start, last, sep);
  216. }
  217. //! Join a list of items into a string.
  218. template <typename Iterator>
  219. inline
  220. void
  221. join (tstring & result, Iterator start, Iterator last,
  222. tstring::value_type sep)
  223. {
  224. join_worker (result, start, last, sep);
  225. }
  226. } // namespace helpers
  227. } // namespace log4cplus
  228. #endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_