| 205 | } |
| 206 | |
| 207 | txSize fxCacheUnicodeToUTF8Offset(txMachine* the, txString string, txSize offset) |
| 208 | { |
| 209 | txStringInfo* info; |
| 210 | if (offset <= 0) |
| 211 | return offset ? -1 : 0; |
| 212 | info = fxCacheStringInfo(the, string); |
| 213 | if (info) { |
| 214 | txSize delta, sign, unicodeOffset, utf8Offset; |
| 215 | txU1* p; |
| 216 | if ((offset < 0) || (info->unicodeLength < offset)) |
| 217 | return -1; |
| 218 | if ((info->ascii) || (offset == 0)) |
| 219 | return offset; |
| 220 | if (offset == info->unicodeLength) |
| 221 | return info->utf8Length; |
| 222 | delta = offset - info->unicodeOffset; |
| 223 | if (delta == 0) |
| 224 | return info->utf8Offset; |
| 225 | if (delta > 0) { |
| 226 | if (delta < info->unicodeLength - offset) { |
| 227 | sign = 1; |
| 228 | unicodeOffset = info->unicodeOffset + 1; |
| 229 | utf8Offset = info->utf8Offset + 1; |
| 230 | } |
| 231 | else { |
| 232 | sign = -1; |
| 233 | unicodeOffset = info->unicodeLength - 1; |
| 234 | utf8Offset = info->utf8Length - 1; |
| 235 | } |
| 236 | } |
| 237 | else { |
| 238 | if (0 - delta < offset) { |
| 239 | sign = -1; |
| 240 | unicodeOffset = info->unicodeOffset - 1; |
| 241 | utf8Offset = info->utf8Offset - 1; |
| 242 | } |
| 243 | else { |
| 244 | sign = 1; |
| 245 | unicodeOffset = 1; |
| 246 | utf8Offset = 1; |
| 247 | } |
| 248 | } |
| 249 | p = (txU1*)string + utf8Offset; |
| 250 | for (;;) { |
| 251 | if ((*p & 0xC0) != 0x80) { |
| 252 | if (unicodeOffset == offset) |
| 253 | break; |
| 254 | unicodeOffset += sign; |
| 255 | } |
| 256 | p += sign; |
| 257 | utf8Offset += sign; |
| 258 | } |
| 259 | info->utf8Offset = utf8Offset; |
| 260 | info->unicodeOffset = unicodeOffset; |
| 261 | return utf8Offset; |
| 262 | } |
| 263 | return fxUnicodeToUTF8Offset(string, offset); |
| 264 | } |
no test coverage detected