1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {FilterFlag} from 'common/filter_flag'; 18import {StringUtils} from 'common/string_utils'; 19import {StringFilterPredicate} from 'viewers/common/string_filter_predicate'; 20 21export class TextFilter { 22 constructor( 23 public filterString: string = '', 24 public flags: FilterFlag[] = [], 25 ) {} 26 27 getFilterPredicate(): StringFilterPredicate { 28 const matchCase = this.flags.includes(FilterFlag.MATCH_CASE); 29 const matchWord = this.flags.includes(FilterFlag.MATCH_WORD); 30 const useRegex = this.flags.includes(FilterFlag.USE_REGEX); 31 32 if (useRegex) { 33 const regexFlags = useRegex && !matchCase ? 'i' : ''; 34 const regexString = matchWord 35 ? '\\b(?:' + this.filterString + ')\\b' 36 : this.filterString; 37 try { 38 const regex = new RegExp(regexString, regexFlags); 39 return (entryString: string) => { 40 if (this.filterString.length === 0) return true; 41 return regex.test(entryString); 42 }; 43 } catch (e) { 44 return (entryString: string) => false; 45 } 46 } else { 47 const testString = matchCase 48 ? this.filterString 49 : this.filterString.toLowerCase(); 50 return (entryString: string) => { 51 if (this.filterString.length === 0) return true; 52 53 let entrySubstring = matchCase 54 ? entryString 55 : entryString.toLowerCase(); 56 let testStringIndex = entrySubstring.indexOf(testString); 57 58 while (testStringIndex !== -1) { 59 if (!matchWord) return true; 60 61 const nextChar = entrySubstring.at( 62 testStringIndex + testString.length, 63 ); 64 if ( 65 nextChar === undefined || 66 !(StringUtils.isAlpha(nextChar) || StringUtils.isDigit(nextChar)) 67 ) { 68 return true; 69 } 70 71 entrySubstring = entrySubstring.slice( 72 testStringIndex + testString.length, 73 ); 74 testStringIndex = entrySubstring.indexOf(testString); 75 } 76 return false; 77 }; 78 } 79 } 80} 81