# String Pattern
今日は文字列が一致しているか調べる関数について呼ぶ。
[MatchPattern](https://source.chromium.org/chromium/chromium/src/+/main:base/strings/pattern.h;l=18-19;drc=e4622aaeccea84652488d1822c28c78b7115684f) は`string`がワイルドカードを含む`pattern`とマッチするをか調べる。
## APIの概要
以下のようなMatchPatternの関数が定義されている。
```cpp=
BASE_EXPORT bool MatchPattern(StringPiece string, StringPiece pattern);
BASE_EXPORT bool MatchPattern(StringPiece16 string, StringPiece16 pattern);
```
`pattern`は`\*`や`\?`(ワイルドカードと呼ぶ)を含める。`\`は`*`と`?`のエスケープに使われ、`*`は0文字以上の任意のstringに、`?`は0-1文字の任意の文字に一致する。
## 実装
MatchPatternの中身は以下のような感じでループを回している。
大まかに言うと、ワイルドカードごとに進めて確認していって一致しないことが確定したら失敗、最後まで失敗しなければ成功。
```cpp=
template <typename CHAR, typename NEXT>
constexpr bool MatchPatternT(const CHAR* eval,
const CHAR* eval_end,
const CHAR* pattern,
const CHAR* pattern_end,
NEXT next) {
do {
int maximum_wildcard_length = EatWildcards(&pattern, pattern_end, next);
if (!SearchForChars(&pattern, pattern_end, &eval, eval_end,
maximum_wildcard_length, next)) {
return false;
}
} while (pattern != pattern_end);
return true;
}
```
まず[EatWildcards](https://source.chromium.org/chromium/chromium/src/+/main:base/strings/pattern.cc;l=90;drc=353683321da2061bb47d7655d4b3fc04c1540ed3)で`?, *`を確認。
連続で何文字分のワイルドカードがあるかを計算して返す。`*`が入ったら何文字でもよいため、`-1`を返して表現する。なお`?`は0文字でもよいため、`*`が入った時点で無視して良い。
この文字数を`maximum_distance`としながら[SearchForChars](https://source.chromium.org/chromium/chromium/src/+/main:base/strings/pattern.cc;l=22;drc=353683321da2061bb47d7655d4b3fc04c1540ed3)を呼ぶ。
ここでも`string`をインクリメントしながらマッチを調べる。
もしpatternとstringの次の文字が同じならOK。patternとstringを両方インクリメントして次のループへGO。
あとは`maximum_distance`分でマッチできるかを確認する。
`maximum_distance`をデクリメントして不一致1文字分を許して、stringだけインクリメントする。もしすでに`maximum_distance`が0ならマッチ不能なので失敗、終了。
なお`*`が含まれている時`-1`がセットされているが、デクリメントしても一生0にはならないのでOK(一応オーバーフローすると困るがそのサイズの文字列はそもそも扱えない)。
このループを文字列最後までいけたらクリア、成功として返す。
その前に新たなワイルドカードとぶつかったら、一旦ここまでは成功として返して、MatchPatternTの中のループをまた回して次のワイルドカード軍団についてSearchForCharsをやる。
`string`の最後まで到達して一度も失敗しなければ成功を返して成功。
## Next について
文字列のインクリメントは[CBU8_NEXT](https://source.chromium.org/chromium/chromium/src/+/main:base/third_party/icu/icu_utf.h;l=237;drc=353683321da2061bb47d7655d4b3fc04c1540ed3)が使われている。
ICUはthird partyのライブラリで、文字列をいい感じに扱ってくれるやつ。
[ICU: International Components for Unicode](https://icu.unicode.org/)