1/* 2 * Copyright (C) 2023 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 */ 16import {assertTrue} from './assert_utils'; 17 18/** 19 * String utility functions. 20 */ 21export class StringUtils { 22 static parseBigIntStrippingUnit(s: string): bigint { 23 const match = s.match(/^\s*(-?\d+)\D*.*$/); 24 if (!match) { 25 throw new Error(`Cannot parse '${s}' as bigint`); 26 } 27 return BigInt(match[1]); 28 } 29 30 static convertCamelToSnakeCase(s: string): string { 31 const result: string[] = []; 32 33 let prevChar: string | undefined; 34 for (const currChar of s) { 35 const prevCharCouldBeWordEnd = 36 prevChar && 37 (StringUtils.isDigit(prevChar) || StringUtils.isLowerCase(prevChar)); 38 const currCharCouldBeWordStart = StringUtils.isUpperCase(currChar); 39 if (prevCharCouldBeWordEnd && currCharCouldBeWordStart) { 40 result.push('_'); 41 result.push(currChar.toLowerCase()); 42 } else { 43 result.push(currChar); 44 } 45 prevChar = currChar; 46 } 47 48 return result.join(''); 49 } 50 51 static convertSnakeToCamelCase(s: string): string { 52 const tokens = s.split('_').filter((token) => token.length > 0); 53 const tokensCapitalized = tokens.map((token) => { 54 return StringUtils.capitalizeFirstCharIfAlpha(token); 55 }); 56 57 const inputStartsWithUnderscore = s[0] === '_'; 58 let result = inputStartsWithUnderscore ? '_' : ''; 59 result += tokens[0]; 60 for (const token of tokensCapitalized.slice(1)) { 61 if (!StringUtils.isAlpha(token[0])) { 62 result += '_'; 63 } 64 result += token; 65 } 66 67 return result; 68 } 69 70 static isAlpha(char: string): boolean { 71 assertTrue(char.length === 1, () => 'Input must be a single character'); 72 return char[0].toLowerCase() !== char[0].toUpperCase(); 73 } 74 75 static isDigit(char: string): boolean { 76 assertTrue(char.length === 1, () => 'Input must be a single character'); 77 return char >= '0' && char <= '9'; 78 } 79 80 static isLowerCase(char: string): boolean { 81 assertTrue(char.length === 1, () => 'Input must be a single character'); 82 return StringUtils.isAlpha(char) && char === char.toLowerCase(); 83 } 84 85 static isUpperCase(char: string): boolean { 86 assertTrue(char.length === 1, () => 'Input must be a single character'); 87 return StringUtils.isAlpha(char) && char === char.toUpperCase(); 88 } 89 90 static isBlank(str: string): boolean { 91 return str.replace(/\s/g, '').length === 0; 92 } 93 94 static isNumeric(str: string): boolean { 95 return Number(str).toString() === str; 96 } 97 98 private static capitalizeFirstCharIfAlpha(word: string): string { 99 if (word.length === 0) { 100 return word; 101 } 102 103 if (!StringUtils.isAlpha(word[0])) { 104 return word; 105 } 106 return word[0].toUpperCase() + word.slice(1); 107 } 108} 109