int Melder_stringMatchesCriterion (const wchar_t *value, int which_kMelder_string, const wchar_t *criterion) { if (value == NULL) { value = L""; /* Regard null strings as empty strings, as is usual in Praat. */ } if (criterion == NULL) { criterion = L""; /* Regard null strings as empty strings, as is usual in Praat. */ } if (which_kMelder_string <= kMelder_string_NOT_EQUAL_TO) { int matchPositiveCriterion = wcsequ (value, criterion); return (which_kMelder_string == kMelder_string_EQUAL_TO) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_CONTAIN) { int matchPositiveCriterion = wcsstr (value, criterion) != NULL; return (which_kMelder_string == kMelder_string_CONTAINS) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_START_WITH) { int matchPositiveCriterion = wcsnequ (value, criterion, wcslen (criterion)); return (which_kMelder_string == kMelder_string_STARTS_WITH) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_END_WITH) { int criterionLength = wcslen (criterion), valueLength = wcslen (value); int matchPositiveCriterion = criterionLength <= valueLength && wcsequ (value + valueLength - criterionLength, criterion); return (which_kMelder_string == kMelder_string_ENDS_WITH) == matchPositiveCriterion; } if (which_kMelder_string == kMelder_string_MATCH_REGEXP) { wchar_t *place = NULL, *errorMessage; regexp *compiled_regexp = CompileRE (criterion, & errorMessage, 0); if (compiled_regexp == NULL) return FALSE; // BUG: what about removing errorMessage? if (ExecRE (compiled_regexp, NULL, value, NULL, 0, '\0', '\0', NULL, NULL, NULL)) place = compiled_regexp -> startp [0]; free (compiled_regexp); return place != NULL; } return 0; /* Should not occur. */ }
bool Melder_stringMatchesCriterion (const char32 *value, int which_kMelder_string, const char32 *criterion) { if (! value) { value = U""; // regard null strings as empty strings, as is usual in Praat } if (! criterion) { criterion = U""; // regard null strings as empty strings, as is usual in Praat } if (which_kMelder_string <= kMelder_string_NOT_EQUAL_TO) { bool matchPositiveCriterion = str32equ (value, criterion); return ( which_kMelder_string == kMelder_string_EQUAL_TO ) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_CONTAIN) { bool matchPositiveCriterion = !! str32str (value, criterion); return ( which_kMelder_string == kMelder_string_CONTAINS ) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_START_WITH) { bool matchPositiveCriterion = str32nequ (value, criterion, str32len (criterion)); return ( which_kMelder_string == kMelder_string_STARTS_WITH ) == matchPositiveCriterion; } if (which_kMelder_string <= kMelder_string_DOES_NOT_END_WITH) { int criterionLength = str32len (criterion), valueLength = str32len (value); bool matchPositiveCriterion = ( criterionLength <= valueLength && str32equ (value + valueLength - criterionLength, criterion) ); return (which_kMelder_string == kMelder_string_ENDS_WITH) == matchPositiveCriterion; } if (which_kMelder_string == kMelder_string_MATCH_REGEXP) { char32 *place = nullptr; regexp *compiled_regexp = CompileRE_throwable (criterion, 0); if (ExecRE (compiled_regexp, nullptr, value, nullptr, 0, '\0', '\0', nullptr, nullptr, nullptr)) place = compiled_regexp -> startp [0]; free (compiled_regexp); return !! place; } return false; // should not occur }
char32 *strstr_regexp (const char32 *string, const char32 *search_regexp) { char32 *charp = 0; regexp *compiled_regexp = CompileRE_throwable (search_regexp, 0); if (ExecRE (compiled_regexp, NULL, string, NULL, 0, '\0', '\0', NULL, NULL, NULL)) { charp = compiled_regexp -> startp[0]; } free (compiled_regexp); return charp; }
char32 *strstr_regexp (const char32 *string, const char32 *search_regexp) { char32 *charp = 0; const char32 *compileMsg; regexp *compiled_regexp = CompileRE (search_regexp, &compileMsg, 0); if (compiled_regexp == 0) { Melder_throw (U"No regexp"); } if (ExecRE (compiled_regexp, NULL, string, NULL, 0, '\0', '\0', NULL, NULL, NULL)) { charp = compiled_regexp -> startp[0]; } free (compiled_regexp); return charp; }
char32 *str_replace_regexp (const char32 *string, regexp *compiledSearchRE, const char32 *replaceRE, long maximumNumberOfReplaces, long *nmatches) { int buf_nchar = 0; /* # characters in 'buf' */ int gap_copied = 0; int nchar, reverse = 0; int errorType; char32 prev_char = '\0'; const char32 *pos; /* current position in 'string' / start of current match */ const char32 *posp; /* end of previous match */ autostring32 buf; *nmatches = 0; if (string == 0 || compiledSearchRE == 0 || replaceRE == 0) { return 0; } int string_length = str32len (string); //int replace_length = str32len (replaceRE); if (string_length == 0) { maximumNumberOfReplaces = 1; } long i = maximumNumberOfReplaces > 0 ? 0 : - string_length; /* We do not know the size of the replaced string in advance, therefor, we allocate a replace buffer twice the size of the original string. After all replaces have taken place we do a final realloc to the then exactly known size. If during the replace, the size of the buffer happens to be too small (this is signalled by the replaceRE function), we double its size and restart the replace. */ int buf_size = 2 * string_length; buf_size = buf_size < 100 ? 100 : buf_size; buf.resize (buf_size); pos = posp = string; while (ExecRE (compiledSearchRE, 0, pos, 0, reverse, prev_char, '\0', 0, 0, 0) && i++ < maximumNumberOfReplaces) { /* Copy gap between the end of the previous match and the start of the current match. Check buffer overflow. pos == posp ? '\0' : pos[-1], */ pos = compiledSearchRE -> startp[0]; nchar = pos - posp; if (nchar > 0 && ! gap_copied) { if (buf_nchar + nchar + 1 > buf_size) { buf_size *= 2; buf.resize (buf_size); } str32ncpy (buf.peek() + buf_nchar, posp, nchar); buf_nchar += nchar; } gap_copied = 1; /* Do the substitution. We can only check afterwards for buffer overflow. SubstituteRE puts null byte at last replaced position and signals when overflow. */ if ( (SubstituteRE (compiledSearchRE, replaceRE, buf.peek() + buf_nchar, buf_size - buf_nchar, &errorType)) == false) { if (errorType == 1) { // not enough memory buf_size *= 2; buf.resize (buf_size); Melder_clearError (); i--; // retry continue; } Melder_throw (U"Error during substitution."); } // Buffer is not full, get number of characters added; nchar = str32len (buf.peek() + buf_nchar); buf_nchar += nchar; // Update next start position in search string. posp = pos; pos = (char32 *) compiledSearchRE -> endp[0]; if (pos != posp) { prev_char = pos[-1]; } gap_copied = 0; posp = pos; //pb 20080121 (*nmatches) ++; // at end of string? // we need this because .* matches at end of a string if (pos - string == string_length) { break; } } // Copy last part of string to destination string nchar = (string + string_length) - pos; buf_size = buf_nchar + nchar + 1; buf.resize (buf_size); str32ncpy (buf.peek() + buf_nchar, pos, nchar); buf[buf_size - 1] = '\0'; return buf.transfer(); }