| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller ( mueller@kde.org ) | 4 * (C) 2001 Dirk Mueller ( mueller@kde.org ) |
| 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All r
ights reserved. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All r
ights reserved. |
| 6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 return true; | 1155 return true; |
| 1156 } | 1156 } |
| 1157 | 1157 |
| 1158 size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start) | 1158 size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start) |
| 1159 { | 1159 { |
| 1160 if (is8Bit()) | 1160 if (is8Bit()) |
| 1161 return WTF::find(characters8(), m_length, matchFunction, start); | 1161 return WTF::find(characters8(), m_length, matchFunction, start); |
| 1162 return WTF::find(characters16(), m_length, matchFunction, start); | 1162 return WTF::find(characters16(), m_length, matchFunction, start); |
| 1163 } | 1163 } |
| 1164 | 1164 |
| 1165 size_t StringImpl::find(const LChar* matchString, unsigned index) | |
| 1166 { | |
| 1167 // Check for null or empty string to match against | |
| 1168 if (!matchString) | |
| 1169 return kNotFound; | |
| 1170 size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString)
); | |
| 1171 RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max()); | |
| 1172 unsigned matchLength = matchStringLength; | |
| 1173 if (!matchLength) | |
| 1174 return min(index, length()); | |
| 1175 | |
| 1176 // Optimization 1: fast case for strings of length 1. | |
| 1177 if (matchLength == 1) | |
| 1178 return WTF::find(characters16(), length(), *matchString, index); | |
| 1179 | |
| 1180 // Check index & matchLength are in range. | |
| 1181 if (index > length()) | |
| 1182 return kNotFound; | |
| 1183 unsigned searchLength = length() - index; | |
| 1184 if (matchLength > searchLength) | |
| 1185 return kNotFound; | |
| 1186 // delta is the number of additional times to test; delta == 0 means test on
ly once. | |
| 1187 unsigned delta = searchLength - matchLength; | |
| 1188 | |
| 1189 const UChar* searchCharacters = characters16() + index; | |
| 1190 | |
| 1191 // Optimization 2: keep a running hash of the strings, | |
| 1192 // only call equal if the hashes match. | |
| 1193 unsigned searchHash = 0; | |
| 1194 unsigned matchHash = 0; | |
| 1195 for (unsigned i = 0; i < matchLength; ++i) { | |
| 1196 searchHash += searchCharacters[i]; | |
| 1197 matchHash += matchString[i]; | |
| 1198 } | |
| 1199 | |
| 1200 unsigned i = 0; | |
| 1201 // keep looping until we match | |
| 1202 while (searchHash != matchHash || !equal(searchCharacters + i, matchString,
matchLength)) { | |
| 1203 if (i == delta) | |
| 1204 return kNotFound; | |
| 1205 searchHash += searchCharacters[i + matchLength]; | |
| 1206 searchHash -= searchCharacters[i]; | |
| 1207 ++i; | |
| 1208 } | |
| 1209 return index + i; | |
| 1210 } | |
| 1211 | |
| 1212 template<typename CharType> | |
| 1213 ALWAYS_INLINE size_t findIgnoringCaseInternal(const CharType* searchCharacters,
const LChar* matchString, unsigned index, unsigned searchLength, unsigned matchL
ength) | |
| 1214 { | |
| 1215 // delta is the number of additional times to test; delta == 0 means test on
ly once. | |
| 1216 unsigned delta = searchLength - matchLength; | |
| 1217 | |
| 1218 unsigned i = 0; | |
| 1219 while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) { | |
| 1220 if (i == delta) | |
| 1221 return kNotFound; | |
| 1222 ++i; | |
| 1223 } | |
| 1224 return index + i; | |
| 1225 } | |
| 1226 | |
| 1227 size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index) | |
| 1228 { | |
| 1229 // Check for null or empty string to match against | |
| 1230 if (!matchString) | |
| 1231 return kNotFound; | |
| 1232 size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString)
); | |
| 1233 RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max()); | |
| 1234 unsigned matchLength = matchStringLength; | |
| 1235 if (!matchLength) | |
| 1236 return min(index, length()); | |
| 1237 | |
| 1238 // Check index & matchLength are in range. | |
| 1239 if (index > length()) | |
| 1240 return kNotFound; | |
| 1241 unsigned searchLength = length() - index; | |
| 1242 if (matchLength > searchLength) | |
| 1243 return kNotFound; | |
| 1244 | |
| 1245 if (is8Bit()) | |
| 1246 return findIgnoringCaseInternal(characters8() + index, matchString, inde
x, searchLength, matchLength); | |
| 1247 return findIgnoringCaseInternal(characters16() + index, matchString, index,
searchLength, matchLength); | |
| 1248 } | |
| 1249 | |
| 1250 template <typename SearchCharacterType, typename MatchCharacterType> | 1165 template <typename SearchCharacterType, typename MatchCharacterType> |
| 1251 ALWAYS_INLINE static size_t findInternal(const SearchCharacterType* searchCharac
ters, const MatchCharacterType* matchCharacters, unsigned index, unsigned search
Length, unsigned matchLength) | 1166 ALWAYS_INLINE static size_t findInternal(const SearchCharacterType* searchCharac
ters, const MatchCharacterType* matchCharacters, unsigned index, unsigned search
Length, unsigned matchLength) |
| 1252 { | 1167 { |
| 1253 // Optimization: keep a running hash of the strings, | 1168 // Optimization: keep a running hash of the strings, |
| 1254 // only call equal() if the hashes match. | 1169 // only call equal() if the hashes match. |
| 1255 | 1170 |
| 1256 // delta is the number of additional times to test; delta == 0 means test on
ly once. | 1171 // delta is the number of additional times to test; delta == 0 means test on
ly once. |
| 1257 unsigned delta = searchLength - matchLength; | 1172 unsigned delta = searchLength - matchLength; |
| 1258 | 1173 |
| 1259 unsigned searchHash = 0; | 1174 unsigned searchHash = 0; |
| 1260 unsigned matchHash = 0; | 1175 unsigned matchHash = 0; |
| 1261 | 1176 |
| 1262 for (unsigned i = 0; i < matchLength; ++i) { | 1177 for (unsigned i = 0; i < matchLength; ++i) { |
| 1263 searchHash += searchCharacters[i]; | 1178 searchHash += searchCharacters[i]; |
| 1264 matchHash += matchCharacters[i]; | 1179 matchHash += matchCharacters[i]; |
| 1265 } | 1180 } |
| 1266 | 1181 |
| 1267 unsigned i = 0; | 1182 unsigned i = 0; |
| 1268 // keep looping until we match | 1183 // keep looping until we match |
| 1269 while (searchHash != matchHash || !equal(searchCharacters + i, matchCharacte
rs, matchLength)) { | 1184 while (searchHash != matchHash || !equal(searchCharacters + i, matchCharacte
rs, matchLength)) { |
| 1270 if (i == delta) | 1185 if (i == delta) |
| 1271 return kNotFound; | 1186 return kNotFound; |
| 1272 searchHash += searchCharacters[i + matchLength]; | 1187 searchHash += searchCharacters[i + matchLength]; |
| 1273 searchHash -= searchCharacters[i]; | 1188 searchHash -= searchCharacters[i]; |
| 1274 ++i; | 1189 ++i; |
| 1275 } | 1190 } |
| 1276 return index + i; | 1191 return index + i; |
| 1277 } | 1192 } |
| 1278 | 1193 |
| 1279 size_t StringImpl::find(StringImpl* matchString) | 1194 size_t StringImpl::find(const StringView& matchString, unsigned index) |
| 1280 { | 1195 { |
| 1281 // Check for null string to match against | 1196 if (UNLIKELY(matchString.isNull())) |
| 1282 if (UNLIKELY(!matchString)) | |
| 1283 return kNotFound; | |
| 1284 unsigned matchLength = matchString->length(); | |
| 1285 | |
| 1286 // Optimization 1: fast case for strings of length 1. | |
| 1287 if (matchLength == 1) { | |
| 1288 if (is8Bit()) { | |
| 1289 if (matchString->is8Bit()) | |
| 1290 return WTF::find(characters8(), length(), matchString->character
s8()[0]); | |
| 1291 return WTF::find(characters8(), length(), matchString->characters16(
)[0]); | |
| 1292 } | |
| 1293 if (matchString->is8Bit()) | |
| 1294 return WTF::find(characters16(), length(), matchString->characters8(
)[0]); | |
| 1295 return WTF::find(characters16(), length(), matchString->characters16()[0
]); | |
| 1296 } | |
| 1297 | |
| 1298 // Check matchLength is in range. | |
| 1299 if (matchLength > length()) | |
| 1300 return kNotFound; | 1197 return kNotFound; |
| 1301 | 1198 |
| 1302 // Check for empty string to match against | 1199 unsigned matchLength = matchString.length(); |
| 1303 if (UNLIKELY(!matchLength)) | |
| 1304 return 0; | |
| 1305 | |
| 1306 if (is8Bit()) { | |
| 1307 if (matchString->is8Bit()) | |
| 1308 return findInternal(characters8(), matchString->characters8(), 0, le
ngth(), matchLength); | |
| 1309 return findInternal(characters8(), matchString->characters16(), 0, lengt
h(), matchLength); | |
| 1310 } | |
| 1311 | |
| 1312 if (matchString->is8Bit()) | |
| 1313 return findInternal(characters16(), matchString->characters8(), 0, lengt
h(), matchLength); | |
| 1314 | |
| 1315 return findInternal(characters16(), matchString->characters16(), 0, length()
, matchLength); | |
| 1316 } | |
| 1317 | |
| 1318 size_t StringImpl::find(StringImpl* matchString, unsigned index) | |
| 1319 { | |
| 1320 // Check for null or empty string to match against | |
| 1321 if (UNLIKELY(!matchString)) | |
| 1322 return kNotFound; | |
| 1323 | |
| 1324 unsigned matchLength = matchString->length(); | |
| 1325 | 1200 |
| 1326 // Optimization 1: fast case for strings of length 1. | 1201 // Optimization 1: fast case for strings of length 1. |
| 1327 if (matchLength == 1) { | 1202 if (matchLength == 1) { |
| 1328 if (is8Bit()) | 1203 if (is8Bit()) |
| 1329 return WTF::find(characters8(), length(), (*matchString)[0], index); | 1204 return WTF::find(characters8(), length(), matchString[0], index); |
| 1330 return WTF::find(characters16(), length(), (*matchString)[0], index); | 1205 return WTF::find(characters16(), length(), matchString[0], index); |
| 1331 } | 1206 } |
| 1332 | 1207 |
| 1333 if (UNLIKELY(!matchLength)) | 1208 if (UNLIKELY(!matchLength)) |
| 1334 return min(index, length()); | 1209 return min(index, length()); |
| 1335 | 1210 |
| 1336 // Check index & matchLength are in range. | 1211 // Check index & matchLength are in range. |
| 1337 if (index > length()) | 1212 if (index > length()) |
| 1338 return kNotFound; | 1213 return kNotFound; |
| 1339 unsigned searchLength = length() - index; | 1214 unsigned searchLength = length() - index; |
| 1340 if (matchLength > searchLength) | 1215 if (matchLength > searchLength) |
| 1341 return kNotFound; | 1216 return kNotFound; |
| 1342 | 1217 |
| 1343 if (is8Bit()) { | 1218 if (is8Bit()) { |
| 1344 if (matchString->is8Bit()) | 1219 if (matchString.is8Bit()) |
| 1345 return findInternal(characters8() + index, matchString->characters8(
), index, searchLength, matchLength); | 1220 return findInternal(characters8() + index, matchString.characters8()
, index, searchLength, matchLength); |
| 1346 return findInternal(characters8() + index, matchString->characters16(),
index, searchLength, matchLength); | 1221 return findInternal(characters8() + index, matchString.characters16(), i
ndex, searchLength, matchLength); |
| 1347 } | 1222 } |
| 1348 | 1223 if (matchString.is8Bit()) |
| 1349 if (matchString->is8Bit()) | 1224 return findInternal(characters16() + index, matchString.characters8(), i
ndex, searchLength, matchLength); |
| 1350 return findInternal(characters16() + index, matchString->characters8(),
index, searchLength, matchLength); | 1225 return findInternal(characters16() + index, matchString.characters16(), inde
x, searchLength, matchLength); |
| 1351 | |
| 1352 return findInternal(characters16() + index, matchString->characters16(), ind
ex, searchLength, matchLength); | |
| 1353 } | 1226 } |
| 1354 | 1227 |
| 1355 template <typename SearchCharacterType, typename MatchCharacterType> | 1228 template <typename SearchCharacterType, typename MatchCharacterType> |
| 1356 ALWAYS_INLINE static size_t findIgnoringCaseInner(const SearchCharacterType* sea
rchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsign
ed searchLength, unsigned matchLength) | 1229 ALWAYS_INLINE static size_t findIgnoringCaseInternal(const SearchCharacterType*
searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, uns
igned searchLength, unsigned matchLength) |
| 1357 { | 1230 { |
| 1358 // delta is the number of additional times to test; delta == 0 means test on
ly once. | 1231 // delta is the number of additional times to test; delta == 0 means test on
ly once. |
| 1359 unsigned delta = searchLength - matchLength; | 1232 unsigned delta = searchLength - matchLength; |
| 1360 | 1233 |
| 1361 unsigned i = 0; | 1234 unsigned i = 0; |
| 1362 // keep looping until we match | 1235 // keep looping until we match |
| 1363 while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength
)) { | 1236 while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength
)) { |
| 1364 if (i == delta) | 1237 if (i == delta) |
| 1365 return kNotFound; | 1238 return kNotFound; |
| 1366 ++i; | 1239 ++i; |
| 1367 } | 1240 } |
| 1368 return index + i; | 1241 return index + i; |
| 1369 } | 1242 } |
| 1370 | 1243 |
| 1371 size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index) | 1244 size_t StringImpl::findIgnoringCase(const StringView& matchString, unsigned inde
x) |
| 1372 { | 1245 { |
| 1373 // Check for null or empty string to match against | 1246 if (UNLIKELY(matchString.isNull())) |
| 1374 if (!matchString) | |
| 1375 return kNotFound; | 1247 return kNotFound; |
| 1376 unsigned matchLength = matchString->length(); | 1248 |
| 1249 unsigned matchLength = matchString.length(); |
| 1377 if (!matchLength) | 1250 if (!matchLength) |
| 1378 return min(index, length()); | 1251 return min(index, length()); |
| 1379 | 1252 |
| 1380 // Check index & matchLength are in range. | 1253 // Check index & matchLength are in range. |
| 1381 if (index > length()) | 1254 if (index > length()) |
| 1382 return kNotFound; | 1255 return kNotFound; |
| 1383 unsigned searchLength = length() - index; | 1256 unsigned searchLength = length() - index; |
| 1384 if (matchLength > searchLength) | 1257 if (matchLength > searchLength) |
| 1385 return kNotFound; | 1258 return kNotFound; |
| 1386 | 1259 |
| 1387 if (is8Bit()) { | 1260 if (is8Bit()) { |
| 1388 if (matchString->is8Bit()) | 1261 if (matchString.is8Bit()) |
| 1389 return findIgnoringCaseInner(characters8() + index, matchString->cha
racters8(), index, searchLength, matchLength); | 1262 return findIgnoringCaseInternal(characters8() + index, matchString.c
haracters8(), index, searchLength, matchLength); |
| 1390 return findIgnoringCaseInner(characters8() + index, matchString->charact
ers16(), index, searchLength, matchLength); | 1263 return findIgnoringCaseInternal(characters8() + index, matchString.chara
cters16(), index, searchLength, matchLength); |
| 1391 } | 1264 } |
| 1392 | 1265 if (matchString.is8Bit()) |
| 1393 if (matchString->is8Bit()) | 1266 return findIgnoringCaseInternal(characters16() + index, matchString.char
acters8(), index, searchLength, matchLength); |
| 1394 return findIgnoringCaseInner(characters16() + index, matchString->charac
ters8(), index, searchLength, matchLength); | 1267 return findIgnoringCaseInternal(characters16() + index, matchString.characte
rs16(), index, searchLength, matchLength); |
| 1395 | |
| 1396 return findIgnoringCaseInner(characters16() + index, matchString->characters
16(), index, searchLength, matchLength); | |
| 1397 } | 1268 } |
| 1398 | 1269 |
| 1399 template <typename SearchCharacterType, typename MatchCharacterType> | 1270 template <typename SearchCharacterType, typename MatchCharacterType> |
| 1400 ALWAYS_INLINE static size_t findIgnoringASCIICaseInner(const SearchCharacterType
* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, u
nsigned searchLength, unsigned matchLength) | 1271 ALWAYS_INLINE static size_t findIgnoringASCIICaseInternal(const SearchCharacterT
ype* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index
, unsigned searchLength, unsigned matchLength) |
| 1401 { | 1272 { |
| 1402 // delta is the number of additional times to test; delta == 0 means test on
ly once. | 1273 // delta is the number of additional times to test; delta == 0 means test on
ly once. |
| 1403 unsigned delta = searchLength - matchLength; | 1274 unsigned delta = searchLength - matchLength; |
| 1404 | 1275 |
| 1405 unsigned i = 0; | 1276 unsigned i = 0; |
| 1406 // keep looping until we match | 1277 // keep looping until we match |
| 1407 while (!equalIgnoringASCIICase(searchCharacters + i, matchCharacters, matchL
ength)) { | 1278 while (!equalIgnoringASCIICase(searchCharacters + i, matchCharacters, matchL
ength)) { |
| 1408 if (i == delta) | 1279 if (i == delta) |
| 1409 return kNotFound; | 1280 return kNotFound; |
| 1410 ++i; | 1281 ++i; |
| 1411 } | 1282 } |
| 1412 return index + i; | 1283 return index + i; |
| 1413 } | 1284 } |
| 1414 | 1285 |
| 1415 size_t StringImpl::findIgnoringASCIICase(StringImpl* matchString, unsigned index
) | 1286 size_t StringImpl::findIgnoringASCIICase(const StringView& matchString, unsigned
index) |
| 1416 { | 1287 { |
| 1417 // Check for null or empty string to match against | 1288 if (UNLIKELY(matchString.isNull())) |
| 1418 if (!matchString) | |
| 1419 return kNotFound; | 1289 return kNotFound; |
| 1420 unsigned matchLength = matchString->length(); | 1290 |
| 1291 unsigned matchLength = matchString.length(); |
| 1421 if (!matchLength) | 1292 if (!matchLength) |
| 1422 return min(index, length()); | 1293 return min(index, length()); |
| 1423 | 1294 |
| 1424 // Check index & matchLength are in range. | 1295 // Check index & matchLength are in range. |
| 1425 if (index > length()) | 1296 if (index > length()) |
| 1426 return kNotFound; | 1297 return kNotFound; |
| 1427 unsigned searchLength = length() - index; | 1298 unsigned searchLength = length() - index; |
| 1428 if (matchLength > searchLength) | 1299 if (matchLength > searchLength) |
| 1429 return kNotFound; | 1300 return kNotFound; |
| 1430 | 1301 |
| 1431 if (is8Bit()) { | 1302 if (is8Bit()) { |
| 1432 const LChar* searchStart = characters8() + index; | 1303 if (matchString.is8Bit()) |
| 1433 if (matchString->is8Bit()) | 1304 return findIgnoringASCIICaseInternal(characters8() + index, matchStr
ing.characters8(), index, searchLength, matchLength); |
| 1434 return findIgnoringASCIICaseInner(searchStart, matchString->characte
rs8(), index, searchLength, matchLength); | 1305 return findIgnoringASCIICaseInternal(characters8() + index, matchString.
characters16(), index, searchLength, matchLength); |
| 1435 return findIgnoringASCIICaseInner(searchStart, matchString->characters16
(), index, searchLength, matchLength); | |
| 1436 } | 1306 } |
| 1437 | 1307 if (matchString.is8Bit()) |
| 1438 const UChar* searchStart = characters16() + index; | 1308 return findIgnoringASCIICaseInternal(characters16() + index, matchString
.characters8(), index, searchLength, matchLength); |
| 1439 if (matchString->is8Bit()) | 1309 return findIgnoringASCIICaseInternal(characters16() + index, matchString.cha
racters16(), index, searchLength, matchLength); |
| 1440 return findIgnoringASCIICaseInner(searchStart, matchString->characters8(
), index, searchLength, matchLength); | |
| 1441 return findIgnoringASCIICaseInner(searchStart, matchString->characters16(),
index, searchLength, matchLength); | |
| 1442 } | 1310 } |
| 1443 | 1311 |
| 1444 size_t StringImpl::reverseFind(UChar c, unsigned index) | 1312 size_t StringImpl::reverseFind(UChar c, unsigned index) |
| 1445 { | 1313 { |
| 1446 if (is8Bit()) | 1314 if (is8Bit()) |
| 1447 return WTF::reverseFind(characters8(), m_length, c, index); | 1315 return WTF::reverseFind(characters8(), m_length, c, index); |
| 1448 return WTF::reverseFind(characters16(), m_length, c, index); | 1316 return WTF::reverseFind(characters16(), m_length, c, index); |
| 1449 } | 1317 } |
| 1450 | 1318 |
| 1451 template <typename SearchCharacterType, typename MatchCharacterType> | 1319 template <typename SearchCharacterType, typename MatchCharacterType> |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 } else if (localeIdMatchesLang(localeIdentifier, "lt")) { | 2013 } else if (localeIdMatchesLang(localeIdentifier, "lt")) { |
| 2146 // TODO(rob.buis) implement upper-casing rules for lt | 2014 // TODO(rob.buis) implement upper-casing rules for lt |
| 2147 // like in StringImpl::upper(locale). | 2015 // like in StringImpl::upper(locale). |
| 2148 } | 2016 } |
| 2149 } | 2017 } |
| 2150 | 2018 |
| 2151 return toUpper(c); | 2019 return toUpper(c); |
| 2152 } | 2020 } |
| 2153 | 2021 |
| 2154 } // namespace WTF | 2022 } // namespace WTF |
| OLD | NEW |