You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.0 KiB

  1. // -*- C++ -*-
  2. // Module: Log4CPLUS
  3. // File: stringhelper.h
  4. // Created: 3/2003
  5. // Author: Tad E. Smith
  6. //
  7. //
  8. // Copyright 2003-2010 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. /**
  38. * Returns <code>s</code> in lower case.
  39. */
  40. LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s);
  41. /**
  42. * Tokenize <code>s</code> using <code>c</code> as the delimiter and
  43. * put the resulting tokens in <code>_result</code>. If
  44. * <code>collapseTokens</code> is false, multiple adjacent delimiters
  45. * will result in zero length tokens.
  46. *
  47. * <b>Example:</b>
  48. * <pre>
  49. * string s = // Set string with '.' as delimiters
  50. * list<log4cplus::tstring> tokens;
  51. * tokenize(s, '.', back_insert_iterator<list<string> >(tokens));
  52. * </pre>
  53. */
  54. template <class StringType, class OutputIter>
  55. inline
  56. void
  57. tokenize(const StringType& s, typename StringType::value_type c,
  58. OutputIter result, bool collapseTokens = true)
  59. {
  60. typedef typename StringType::size_type size_type;
  61. size_type const slen = s.length();
  62. size_type first = 0;
  63. size_type i = 0;
  64. for (i=0; i < slen; ++i)
  65. {
  66. if (s[i] == c)
  67. {
  68. *result = StringType (s, first, i - first);
  69. ++result;
  70. if (collapseTokens)
  71. while (i+1 < slen && s[i+1] == c)
  72. ++i;
  73. first = i + 1;
  74. }
  75. }
  76. if (first != i)
  77. *result = StringType (s, first, i - first);
  78. }
  79. template <typename intType, bool isSigned>
  80. struct ConvertIntegerToStringHelper;
  81. template <typename intType>
  82. struct ConvertIntegerToStringHelper<intType, true>
  83. {
  84. static inline
  85. void
  86. step1 (tchar * & it, intType & value)
  87. {
  88. // The sign of the result of the modulo operator is
  89. // implementation defined. That's why we work with
  90. // positive counterpart instead. Also, in twos
  91. // complement arithmetic the smallest negative number
  92. // does not have positive counterpart; the range is
  93. // asymetric. That's why we handle the case of value
  94. // == min() specially here.
  95. if (value == (std::numeric_limits<intType>::min) ())
  96. {
  97. intType const r = value / 10;
  98. intType const a = (-r) * 10;
  99. intType const mod = -(a + value);
  100. value = -r;
  101. *(it - 1) = LOG4CPLUS_TEXT('0') + static_cast<tchar>(mod);
  102. --it;
  103. }
  104. else
  105. value = -value;
  106. }
  107. static inline
  108. bool
  109. is_negative (intType val)
  110. {
  111. return val < 0;
  112. }
  113. };
  114. template <typename intType>
  115. struct ConvertIntegerToStringHelper<intType, false>
  116. {
  117. static inline
  118. void
  119. step1 (tchar * &, intType &)
  120. {
  121. // This will never be called for unsigned types.
  122. }
  123. static inline
  124. bool
  125. is_negative (intType)
  126. {
  127. return false;
  128. }
  129. };
  130. template<class intType>
  131. inline
  132. void
  133. convertIntegerToString (tstring & str, intType value)
  134. {
  135. typedef std::numeric_limits<intType> intTypeLimits;
  136. typedef ConvertIntegerToStringHelper<intType, intTypeLimits::is_signed>
  137. HelperType;
  138. const std::size_t buffer_size
  139. = intTypeLimits::digits10 + 2;
  140. tchar buffer[buffer_size];
  141. tchar * it = &buffer[buffer_size];
  142. tchar const * const buf_end = it;
  143. if (value == 0)
  144. {
  145. --it;
  146. *it = LOG4CPLUS_TEXT('0');
  147. }
  148. bool const negative = HelperType::is_negative (value);
  149. if (negative)
  150. HelperType::step1 (it, value);
  151. for (; value != 0; --it)
  152. {
  153. intType mod = value % 10;
  154. value = value / 10;
  155. *(it - 1) = LOG4CPLUS_TEXT('0') + static_cast<tchar>(mod);
  156. }
  157. if (negative)
  158. {
  159. --it;
  160. *it = LOG4CPLUS_TEXT('-');
  161. }
  162. str.assign (static_cast<tchar const *>(it), buf_end);
  163. }
  164. template<class intType>
  165. inline
  166. tstring
  167. convertIntegerToString (intType value)
  168. {
  169. tstring result;
  170. convertIntegerToString (result, value);
  171. return result;
  172. }
  173. } // namespace helpers
  174. } // namespace log4cplus
  175. #endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_