OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/string_utils.h" | 5 #include "tools/gn/string_utils.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <cctype> | 8 #include <cctype> |
9 | 9 |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 return false; | 277 return false; |
278 } else if (!AppendStringInterpolation(scope, literal, input, size, &i, | 278 } else if (!AppendStringInterpolation(scope, literal, input, size, &i, |
279 &output, err)) | 279 &output, err)) |
280 return false; | 280 return false; |
281 } else { | 281 } else { |
282 output.push_back(input[i]); | 282 output.push_back(input[i]); |
283 } | 283 } |
284 } | 284 } |
285 return true; | 285 return true; |
286 } | 286 } |
| 287 |
| 288 size_t EditDistance(const base::StringPiece& s1, |
| 289 const base::StringPiece& s2, |
| 290 size_t max_edit_distance) { |
| 291 // The algorithm implemented below is the "classic" |
| 292 // dynamic-programming algorithm for computing the Levenshtein |
| 293 // distance, which is described here: |
| 294 // |
| 295 // http://en.wikipedia.org/wiki/Levenshtein_distance |
| 296 // |
| 297 // Although the algorithm is typically described using an m x n |
| 298 // array, only one row plus one element are used at a time, so this |
| 299 // implementation just keeps one vector for the row. To update one entry, |
| 300 // only the entries to the left, top, and top-left are needed. The left |
| 301 // entry is in row[x-1], the top entry is what's in row[x] from the last |
| 302 // iteration, and the top-left entry is stored in previous. |
| 303 size_t m = s1.size(); |
| 304 size_t n = s2.size(); |
| 305 |
| 306 std::vector<size_t> row(n + 1); |
| 307 for (size_t i = 1; i <= n; ++i) |
| 308 row[i] = i; |
| 309 |
| 310 for (size_t y = 1; y <= m; ++y) { |
| 311 row[0] = y; |
| 312 size_t best_this_row = row[0]; |
| 313 |
| 314 size_t previous = y - 1; |
| 315 for (size_t x = 1; x <= n; ++x) { |
| 316 size_t old_row = row[x]; |
| 317 row[x] = std::min(previous + (s1[y - 1] == s2[x - 1] ? 0u : 1u), |
| 318 std::min(row[x - 1], row[x]) + 1u); |
| 319 previous = old_row; |
| 320 best_this_row = std::min(best_this_row, row[x]); |
| 321 } |
| 322 |
| 323 if (max_edit_distance && best_this_row > max_edit_distance) |
| 324 return max_edit_distance + 1; |
| 325 } |
| 326 |
| 327 return row[n]; |
| 328 } |
| 329 |
| 330 base::StringPiece SpellcheckString( |
| 331 const base::StringPiece& text, |
| 332 const std::vector<base::StringPiece>& words) { |
| 333 const size_t kMaxValidEditDistance = 3u; |
| 334 |
| 335 size_t min_distance = kMaxValidEditDistance + 1u; |
| 336 base::StringPiece result; |
| 337 for (base::StringPiece word : words) { |
| 338 size_t distance = EditDistance(word, text, kMaxValidEditDistance); |
| 339 if (distance < min_distance) { |
| 340 min_distance = distance; |
| 341 result = word; |
| 342 } |
| 343 } |
| 344 return result; |
| 345 } |
OLD | NEW |