1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16export class PluginConvertUtils { 17 private static crlf: string = '\n'; 18 private static leftBrace: string = '{'; 19 private static rightBrace: string = '}'; 20 static pluginConfig: unknown[] = []; 21 22 public static createHdcCmd(requestString: string, outputPath: string, time: number): string { 23 return `hiprofiler_cmd \\${this.crlf} -c - \\${this.crlf} -o ${outputPath} \\${this.crlf} -t ${time} \\${this.crlf} -s \\${this.crlf} -k \\${this.crlf}<<CONFIG${requestString}CONFIG`; 24 } 25 26 public static BeanToCmdTxt(bean: unknown, needColon: boolean): string { 27 //@ts-ignore 28 PluginConvertUtils.pluginConfig = bean.pluginConfigs; 29 //@ts-ignore 30 return this.handleObj(bean, 0, needColon, 1); 31 } 32 33 public static BeanToCmdTxtWithObjName( 34 bean: unknown, 35 needColon: boolean, 36 objName: string, 37 spacesNumber: number 38 ): string { 39 //@ts-ignore 40 return `${objName}: {${this.handleObj(bean, 0, needColon, spacesNumber)}}`; 41 } 42 43 private static handleObj(bean: object, indentation: number, needColon: boolean, spacesNumber: number): string { 44 let prefixText: string = ''; 45 if (indentation === 0) { 46 prefixText = prefixText + this.crlf; 47 } else { 48 prefixText = prefixText + ' '.repeat(spacesNumber) + this.leftBrace + this.crlf; 49 } 50 if (bean) { 51 prefixText = this.getPrefixText(prefixText, indentation, needColon, spacesNumber, bean); 52 } 53 if (indentation === 0) { 54 return prefixText; 55 } else { 56 return prefixText + ' '.repeat(spacesNumber).repeat(indentation) + this.rightBrace; 57 } 58 } 59 60 private static getPrefixText( 61 prefixText: string, 62 indentation: number, 63 needColon: boolean, 64 spacesNumber: number, 65 bean: unknown 66 ): string { 67 // @ts-ignore 68 for (const [key, value] of Object.entries(bean)) { 69 const repeatedKey = Array.isArray(value); 70 if (repeatedKey) { 71 prefixText = prefixText + this.handleArray(key, value, indentation, needColon, spacesNumber); 72 } else { 73 switch (typeof value) { 74 case 'bigint': 75 prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); 76 break; 77 case 'boolean': 78 prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); 79 break; 80 case 'number': 81 if (value === 0 && !needColon) { 82 break; 83 } 84 prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); 85 break; 86 case 'string': 87 if (value === '') { 88 break; 89 } 90 prefixText = this.handleObjByStr(prefixText, value, spacesNumber, key, indentation); 91 break; 92 case 'object': 93 default: 94 prefixText = this.handleObjByDefault(prefixText, value, spacesNumber, key, indentation, needColon); 95 break; 96 } 97 } 98 } 99 return prefixText; 100 } 101 102 private static handleObjByDefault( 103 prefixText: string, 104 value: unknown, 105 spacesNumber: number, 106 key: string, 107 indentation: number, 108 needColon: boolean 109 ): string { 110 if (needColon) { 111 prefixText = `${ 112 prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) 113 //@ts-ignore 114 }: ${this.handleObj(value, indentation + 1, needColon, spacesNumber)}${this.crlf}`; 115 } else { 116 prefixText = `${ 117 prefixText + 118 ' '.repeat(spacesNumber).repeat(indentation + 1) + 119 this.humpToSnake(key) + 120 //@ts-ignore 121 this.handleObj(value, indentation + 1, needColon, spacesNumber) 122 }${this.crlf}`; 123 } 124 return prefixText; 125 } 126 127 private static handleObjByStr( 128 prefixText: string, 129 value: unknown, 130 spacesNumber: number, 131 key: string, 132 indentation: number 133 ): string { 134 //@ts-ignore 135 if (configEnumList.indexOf(value) >= 0 || value.startsWith('IO_REPORT')) { 136 prefixText = `${prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + //@ts-ignore 137 this.humpToSnake(key)}: ${value.toString()}${this.crlf}`; 138 } else { 139 prefixText = `${prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: "${ 140 //@ts-ignore 141 value.toString() 142 }"${this.crlf}`; 143 } 144 return prefixText; 145 } 146 147 private static handleArray( 148 key: string, 149 arr: Array<Object>, 150 indentation: number, 151 needColon: boolean, 152 spacesNumber: number 153 ): string { 154 let text = ''; 155 arr.forEach((arrValue): void => { 156 switch (typeof arrValue) { 157 case 'bigint': 158 text = this.handleArrayByBigint(text, spacesNumber, indentation, key, arrValue); 159 break; 160 case 'boolean': 161 text = this.handleArrayByBoolean(text, spacesNumber, indentation, key, arrValue); 162 break; 163 case 'number': 164 text = this.handleArrayByNumber(text, spacesNumber, indentation, key, arrValue); 165 break; 166 case 'string': 167 if (arrValue === '') { 168 break; 169 } 170 text = this.handleArrayByStr(text, spacesNumber, indentation, key, arrValue); 171 break; 172 case 'object': 173 default: 174 text = this.handleArrayByDefault(text, spacesNumber, indentation, key, arrValue, needColon); 175 } 176 }); 177 return text; 178 } 179 180 private static handleArrayByBigint( 181 text: string, 182 spacesNumber: number, 183 indentation: number, 184 key: string, 185 arrValue: unknown 186 ): string { 187 //@ts-ignore 188 return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ 189 this.crlf 190 }`; 191 } 192 193 private static handleArrayByBoolean( 194 text: string, 195 spacesNumber: number, 196 indentation: number, 197 key: string, 198 arrValue: unknown 199 ): string { 200 //@ts-ignore 201 return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ 202 this.crlf 203 }`; 204 } 205 206 private static handleArrayByNumber( 207 text: string, 208 spacesNumber: number, 209 indentation: number, 210 key: string, 211 arrValue: unknown 212 ): string { 213 //@ts-ignore 214 return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ 215 this.crlf 216 }`; 217 } 218 219 private static handleArrayByStr( 220 text: string, 221 spacesNumber: number, 222 indentation: number, 223 key: string, 224 arrValue: unknown 225 ): string { 226 //@ts-ignore 227 if (arrValue.startsWith('VMEMINFO') || arrValue.startsWith('PMEM')) { 228 text = `${ 229 text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) 230 //@ts-ignore 231 }: ${arrValue.toString()}${this.crlf}`; 232 //@ts-ignore 233 } else if (arrValue.startsWith('REAL_BATTERY') || arrValue.startsWith('THERMAL_REPORT')) { 234 text = `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) 235 //@ts-ignore 236 }: ${arrValue.toString()}${this.crlf}`; 237 } else { 238 text = `${ 239 text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) 240 //@ts-ignore 241 }: "${arrValue.trim().toString()}"${this.crlf}`; 242 } 243 return text; 244 } 245 246 private static handleArrayByDefault( 247 text: string, 248 spacesNumber: number, 249 indentation: number, 250 key: string, 251 arrValue: unknown, 252 needColon: boolean 253 ): string { 254 if (needColon) { 255 text = `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${this.handleObj( 256 //@ts-ignore 257 arrValue, 258 indentation + 1, 259 needColon, 260 spacesNumber 261 )}${this.crlf}`; 262 } else { 263 text = `${ 264 text + 265 ' '.repeat(spacesNumber).repeat(indentation + 1) + 266 this.humpToSnake(key) + 267 //@ts-ignore 268 this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) 269 }${this.crlf}`; 270 } 271 return text; 272 } 273 274 // 驼峰转snake 275 private static humpToSnake(humpString: string): string { 276 return humpString.replace(/[A-Z]/g, (value) => `_${value.toLowerCase()}`); 277 } 278 279 private static getMontageStrings<T extends Object>( 280 prefixText: string, 281 spacesNumber: number, 282 indentation: number, 283 key: string, 284 value: T 285 ): string { 286 return `${ 287 prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) 288 }: ${value.toString()}${this.crlf}`; 289 } 290} 291 292const LevelConfigEnumList: string[] = ['LEVEL_UNSPECIFIED', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']; 293 294export const ffrtEnumList: string[] = ['BOOTTIME', 'REALTIME', 'REALTIME_COARSE', 'MONOTONIC', 295 'MONOTONIC_COARSE', 'MONOTONIC_RAW']; 296 297const configEnumList: string[] = [...LevelConfigEnumList, ...ffrtEnumList]; 298