stringhelper.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // -*- C++ -*-
  2. // Module: Log4CPLUS
  3. // File: stringhelper.h
  4. // Created: 3/2003
  5. // Author: Tad E. Smith
  6. //
  7. //
  8. // Copyright 2003-2015 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. }
  81. template <typename intType, typename stringType, bool isSigned>
  82. struct ConvertIntegerToStringHelper;
  83. template <typename intType, typename charType>
  84. struct ConvertIntegerToStringHelper<intType, charType, true>
  85. {
  86. static inline
  87. void
  88. step1 (charType * & it, intType & value)
  89. {
  90. // The sign of the result of the modulo operator is
  91. // implementation defined. That's why we work with
  92. // positive counterpart instead. Also, in twos
  93. // complement arithmetic the smallest negative number
  94. // does not have positive counterpart; the range is
  95. // asymetric. That's why we handle the case of value
  96. // == min() specially here.
  97. if (LOG4CPLUS_UNLIKELY (
  98. value == (std::numeric_limits<intType>::min) ()))
  99. {
  100. intType const r = value / 10;
  101. intType const a = (-r) * 10;
  102. intType const mod = -(a + value);
  103. value = -r;
  104. *(it - 1)
  105. = static_cast<charType>(LOG4CPLUS_TEXT('0') + mod);
  106. --it;
  107. }
  108. else
  109. value = -value;
  110. }
  111. static inline
  112. bool
  113. is_negative (intType val)
  114. {
  115. return val < 0;
  116. }
  117. };
  118. template <typename intType, typename charType>
  119. struct ConvertIntegerToStringHelper<intType, charType, false>
  120. {
  121. static inline
  122. void
  123. step1 (charType * &, intType &)
  124. {
  125. // This will never be called for unsigned types.
  126. }
  127. static inline
  128. bool
  129. is_negative (intType)
  130. {
  131. return false;
  132. }
  133. };
  134. template <class stringType, class intType>
  135. inline
  136. void
  137. convertIntegerToString (stringType & str, intType value)
  138. {
  139. typedef std::numeric_limits<intType> intTypeLimits;
  140. typedef typename stringType::value_type charType;
  141. typedef ConvertIntegerToStringHelper<intType, charType,
  142. intTypeLimits::is_signed> HelperType;
  143. charType buffer[intTypeLimits::digits10 + 2];
  144. // We define buffer_size from buffer using sizeof operator
  145. // to apease HP aCC compiler.
  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>
  195. inline
  196. void
  197. join (tstring & result, Iterator start, Iterator last, tstring const & sep)
  198. {
  199. if (start != last)
  200. result = *start++;
  201. for (; start != last; ++start)
  202. {
  203. result += sep;
  204. result += *start;
  205. }
  206. }
  207. } // namespace helpers
  208. } // namespace log4cplus
  209. #endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_