| 3408 | /************************************************************************/ |
| 3409 | |
| 3410 | std::unique_ptr<GDALAlgorithm> |
| 3411 | GDALAlgorithm::InstantiateSubAlgorithm(const std::string &name, |
| 3412 | bool suggestionAllowed) const |
| 3413 | { |
| 3414 | auto ret = m_subAlgRegistry.Instantiate(name); |
| 3415 | auto childCallPath = m_callPath; |
| 3416 | childCallPath.push_back(name); |
| 3417 | if (!ret) |
| 3418 | { |
| 3419 | ret = GDALGlobalAlgorithmRegistry::GetSingleton() |
| 3420 | .InstantiateDeclaredSubAlgorithm(childCallPath); |
| 3421 | } |
| 3422 | if (ret) |
| 3423 | { |
| 3424 | ret->SetCallPath(childCallPath); |
| 3425 | } |
| 3426 | else if (suggestionAllowed) |
| 3427 | { |
| 3428 | std::string bestCandidate; |
| 3429 | size_t bestDistance = std::numeric_limits<size_t>::max(); |
| 3430 | for (const std::string &candidate : GetSubAlgorithmNames()) |
| 3431 | { |
| 3432 | const size_t distance = |
| 3433 | CPLLevenshteinDistance(name.c_str(), candidate.c_str(), |
| 3434 | /* transpositionAllowed = */ true); |
| 3435 | if (distance < bestDistance) |
| 3436 | { |
| 3437 | bestCandidate = candidate; |
| 3438 | bestDistance = distance; |
| 3439 | } |
| 3440 | else if (distance == bestDistance) |
| 3441 | { |
| 3442 | bestCandidate.clear(); |
| 3443 | } |
| 3444 | } |
| 3445 | if (!bestCandidate.empty() && bestDistance <= 2) |
| 3446 | { |
| 3447 | CPLError(CE_Failure, CPLE_AppDefined, |
| 3448 | "Algorithm '%s' is unknown. Do you mean '%s'?", |
| 3449 | name.c_str(), bestCandidate.c_str()); |
| 3450 | } |
| 3451 | } |
| 3452 | return ret; |
| 3453 | } |
| 3454 | |
| 3455 | /************************************************************************/ |
| 3456 | /* GDALAlgorithm::GetSuggestionForArgumentName() */ |