1#!/usr/bin/env python3 2# coding=utf-8 3# 4# Copyright (c) 2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17 18"""Module provides custom text tools for parsing.""" 19 20from typing import Tuple, Dict 21from log_tools import warning_log 22 23 24MAX_LEN = 10000000 25 26 27def find_first_not_restricted_character(restricted: str, data: str, pos: int = 0, pos_end: int = MAX_LEN) -> int: 28 for i in range(pos, min(len(data), pos_end)): 29 if data[i] not in restricted: 30 return i 31 return len(data) 32 33 34def rfind_first_not_restricted_character(restricted: str, data: str, pos: int, pos_end: int = 0) -> int: 35 """pos_end includes in searching""" 36 if pos > len(data): 37 pos = len(data) - 1 38 while pos >= max(0, pos_end): 39 if data[pos] not in restricted: 40 return pos 41 pos -= 1 42 return len(data) 43 44 45def find_first_of_characters(characters: str, data: str, pos: int = 0, pos_end: int = MAX_LEN) -> int: 46 for i in range(pos, min(len(data), pos_end)): 47 if data[i] in characters: 48 return i 49 return len(data) 50 51 52def rfind_first_of_characters(characters: str, data: str, pos: int, pos_end: int = 0) -> int: 53 """pos_end includes in searching""" 54 if pos > len(data): 55 pos = len(data) - 1 56 while pos >= max(0, pos_end): 57 if data[pos] in characters: 58 return pos 59 pos -= 1 60 return len(data) 61 62 63def find_scope_borders(data: str, start: int = 0, opening: str = "{") -> Tuple[int, int]: 64 """ 65 Returns pos of opening and closing brackets in 'data'. 66 If it can't find proper scope -> raise error. 67 """ 68 brackets_match: Dict[str, str] = { 69 "{": "}", 70 "(": ")", 71 "<": ">", 72 "[": "]", 73 } 74 75 if opening == "": 76 opening_pos = find_first_of_characters("({<[", data, start) 77 if opening_pos == len(data): 78 raise RuntimeError("Error while finding end of scope in ANY mode") 79 opening = data[opening_pos] 80 81 closing = brackets_match[opening] 82 start_of_scope = data.find(opening, start) 83 84 if start_of_scope == -1: 85 raise RuntimeError("No opening bracket found!") 86 87 end_of_scope = start_of_scope + 1 88 89 def check_opening_closing() -> bool: 90 openings = data[start_of_scope : end_of_scope + 1].count(opening) 91 closings = data[start_of_scope : end_of_scope + 1].count(closing) 92 return openings == closings 93 94 while not check_opening_closing(): 95 end_of_scope = data.find(closing, end_of_scope + 1) 96 97 if end_of_scope == -1: 98 raise RuntimeError("Error while finding end of scope.") 99 100 return start_of_scope, end_of_scope 101 102 103def smart_split_by(data: str, delim: str = ",") -> list: 104 data = data.strip(" \n") 105 106 res = [] 107 segment_start = 0 108 109 while segment_start < len(data): 110 111 next_delim = smart_find_first_of_characters(delim, data, segment_start) 112 113 segment = data[segment_start:next_delim].strip(" \n") 114 if segment != "": 115 res.append(segment) 116 else: 117 warning_log("Warning: empty segment in smart_split_by") 118 119 segment_start = find_first_not_restricted_character(f"{delim} \n", data, next_delim) 120 121 return res 122 123 124def smart_find_first_of_characters(characters: str, data: str, pos: int) -> int: 125 i = pos 126 while i < len(data): 127 if data[i] in characters: 128 return i 129 130 if data[i] in "<({[": 131 _, close_bracket = find_scope_borders(data, i, "") 132 i = close_bracket 133 134 elif data[i] == '"': 135 i = data.find('"', i + 1) 136 while i != -1 and data[i] == '"' and i != 0 and data[i - 1] == "\\": 137 i = data.find('"', i + 1) 138 139 elif data[i] == "'": 140 i = data.find("'", i + 1) 141 142 i += 1 143 144 return len(data) 145 146 147def check_cpp_name(data: str) -> bool: 148 data = data.lower() 149 forbidden_chars = " ~!@#$%^&*()-+=[]\\{}|;:'\",./<>?" 150 return find_first_of_characters(forbidden_chars, data) == len(data) 151