* Searches for substring starting at the next cell from (myRow, myCol). * Returns (row,col) if found, (-1,-1) if not */
| 270 | * Returns (row,col) if found, (-1,-1) if not |
| 271 | */ |
| 272 | std::tuple<table_index_t, table_index_t> CsvTable::findSubstring(std::string search, table_index_t startRow, table_index_t startCol, std::vector<table_index_t> sel, bool caseSensitive, bool useRegex) { |
| 273 | table_index_t r; |
| 274 | table_index_t c; |
| 275 | int cnt; // `cnt` is used to avoid endless loops in do-while below |
| 276 | table_index_t searchAreaSize; |
| 277 | std::string lowerSearch; |
| 278 | std::string status; |
| 279 | searchArea = sel; |
| 280 | searchAreaSize = (sel[2]-sel[0]+1) * (sel[3]-sel[1]+1); |
| 281 | std::tuple<table_index_t, std::string> executeReturn; // for JS search |
| 282 | |
| 283 | // |
| 284 | // if a Regex search, use JS |
| 285 | // |
| 286 | if( useRegex ) { |
| 287 | std::string js = createJsFindSubstring(search, startRow, startCol, caseSensitive); |
| 288 | executeReturn = macro.execute(this, {sel[0],sel[1],sel[2],sel[3]}, js); |
| 289 | // if( std::get<0>(executeReturn) == -1 ) { |
| 290 | // printf("ERROR: %s\n", std::get<1>(executeReturn).c_str()); |
| 291 | // } |
| 292 | std::vector<int> result = Macro::getLastResultInts(); |
| 293 | if( result.size() == 2 ) { |
| 294 | return std::make_tuple(result[0], result[1]); |
| 295 | } |
| 296 | return std::make_tuple(-1, -1); |
| 297 | } |
| 298 | |
| 299 | if( !caseSensitive ) { |
| 300 | lowerSearch = Utf8CppUtils::utf8::casefold(search); |
| 301 | } |
| 302 | |
| 303 | r = startRow; |
| 304 | c = startCol; |
| 305 | // step over to first cell within `searchArea` |
| 306 | cnt = 0; |
| 307 | do { |
| 308 | std::tie(r,c) = nextField(r,c); |
| 309 | ++cnt; |
| 310 | } while( (r < searchArea[0] || r > searchArea[2] || c < searchArea[1] || c > searchArea[3]) && cnt <= searchAreaSize ); |
| 311 | startRow = r; |
| 312 | startCol = c; |
| 313 | // start searching ... |
| 314 | cnt = 0; |
| 315 | // TODO Avoid multiple searches in the same row (to improve performance) |
| 316 | do { |
| 317 | if( caseSensitive ) { |
| 318 | if( |
| 319 | storage.getRow(r).find(search) != std::string::npos && // first search in rows – only if matching, search in cell |
| 320 | getCell(r,c).find(search) != std::string::npos |
| 321 | ) { |
| 322 | return std::make_tuple(r, c); |
| 323 | } |
| 324 | } else { |
| 325 | if( |
| 326 | Utf8CppUtils::utf8::casefold(storage.getRow(r)).find(lowerSearch) != std::string::npos && |
| 327 | Utf8CppUtils::utf8::casefold(getCell(r,c)).find(lowerSearch) != std::string::npos |
| 328 | ) { |
| 329 | return std::make_tuple(r, c); |
no test coverage detected