| 100 | /// Replaces all occurences of the 'from' symbol in a string to the 'to' symbol. |
| 101 | template <class TStringType> |
| 102 | inline size_t SubstCharGlobalImpl(TStringType& s, typename TStringType::value_type from, typename TStringType::value_type to, size_t fromPos = 0) { |
| 103 | if (fromPos >= s.size()) { |
| 104 | return 0; |
| 105 | } |
| 106 | |
| 107 | size_t result = 0; |
| 108 | fromPos = s.find(from, fromPos); |
| 109 | |
| 110 | // s.begin() might cause memory copying, so call it only if needed |
| 111 | if (fromPos != TStringType::npos) { |
| 112 | auto* it = &*s.begin() + fromPos; |
| 113 | *it = to; |
| 114 | ++result; |
| 115 | // at this point string is copied and it's safe to use constant s.end() to iterate |
| 116 | const auto* const sEnd = &*s.end(); |
| 117 | // unrolled loop goes first because it is more likely that `it` will be properly aligned |
| 118 | for (const auto* const end = sEnd - (sEnd - it) % 4; it < end;) { |
| 119 | if (*it == from) { |
| 120 | *it = to; |
| 121 | ++result; |
| 122 | } |
| 123 | ++it; |
| 124 | if (*it == from) { |
| 125 | *it = to; |
| 126 | ++result; |
| 127 | } |
| 128 | ++it; |
| 129 | if (*it == from) { |
| 130 | *it = to; |
| 131 | ++result; |
| 132 | } |
| 133 | ++it; |
| 134 | if (*it == from) { |
| 135 | *it = to; |
| 136 | ++result; |
| 137 | } |
| 138 | ++it; |
| 139 | } |
| 140 | for (; it < sEnd; ++it) { |
| 141 | if (*it == from) { |
| 142 | *it = to; |
| 143 | ++result; |
| 144 | } |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | return result; |
| 149 | } |
| 150 | |
| 151 | /* Standard says that `char16_t` is a distinct type and has same size, signedness and alignment as |
| 152 | * `std::uint_least16_t`, so we check if `char16_t` has same signedness and size as `wchar16` to be |
no test coverage detected