123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /* NUMstring.cpp
- *
- * Copyright (C) 2012-2017 David Weenink
- *
- * This code is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This code is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this work. If not, see <http://www.gnu.org/licenses/>.
- */
- /*
- djmw 20121005 First version
- */
- #include <ctype.h>
- #include <wctype.h>
- #include "Interpreter.h"
- #include "NUM2.h"
- autoVEC VEC_createFromString (conststring32 s) {
- autostring32vector tokens = STRVECtokenize (s);
- if (tokens.size < 1)
- Melder_throw (U"Empty string.");
- autoVEC numbers = VECraw (tokens.size);
- for (integer inum = 1; inum <= tokens.size; inum ++)
- Interpreter_numericExpression (0, tokens [inum].get(), & numbers [inum]);
- return numbers;
- }
- char32 *strstr_regexp (conststring32 string, conststring32 search_regexp) {
- char32 *charp = nullptr;
- regexp *compiled_regexp = CompileRE_throwable (search_regexp, 0);
- if (ExecRE (compiled_regexp, nullptr, string, nullptr, false, U'\0', U'\0', nullptr, nullptr)) {
- charp = compiled_regexp -> startp [0];
- }
- free (compiled_regexp);
- return charp;
- }
- static autostring32vector string32vector_searchAndReplace_literal (string32vector me,
- conststring32 search, conststring32 replace, int maximumNumberOfReplaces,
- integer *out_numberOfMatches, integer *out_numberOfStringMatches)
- {
- if (! search || ! replace)
- return autostring32vector();
- autostring32vector result (me.size);
- integer nmatches_sub = 0, nmatches = 0, nstringmatches = 0;
- for (integer i = 1; i <= me.size; i ++) {
- conststring32 string = ( me [i] ? me [i] : U"" ); // treat null as an empty string
- result [i] = STRreplace (string, search, replace, maximumNumberOfReplaces, & nmatches_sub);
- if (nmatches_sub > 0) {
- nmatches += nmatches_sub;
- nstringmatches ++;
- }
- }
- if (out_numberOfMatches)
- *out_numberOfMatches = nmatches;
- if (out_numberOfStringMatches)
- *out_numberOfStringMatches = nstringmatches;
- return result;
- }
- static autostring32vector string32vector_searchAndReplace_regexp (string32vector me,
- conststring32 searchRE, conststring32 replaceRE, int maximumNumberOfReplaces,
- integer *out_numberOfMatches, integer *out_numberOfStringMatches)
- {
- if (! searchRE || ! replaceRE)
- return autostring32vector();
- integer nmatches_sub = 0;
- regexp *compiledRE = CompileRE_throwable (searchRE, 0);
- autostring32vector result (me.size);
- integer nmatches = 0, nstringmatches = 0;
- for (integer i = 1; i <= me.size; i ++) {
- conststring32 string = ( me [i] ? me [i] : U"" ); // treat null as an empty string
- result [i] = STRreplace_regex (string, compiledRE, replaceRE, maximumNumberOfReplaces, & nmatches_sub);
- if (nmatches_sub > 0) {
- nmatches += nmatches_sub;
- nstringmatches ++;
- }
- }
- if (out_numberOfMatches)
- *out_numberOfMatches = nmatches;
- if (out_numberOfStringMatches)
- *out_numberOfStringMatches = nstringmatches;
- return result;
- }
- autostring32vector string32vector_searchAndReplace (string32vector me,
- conststring32 search, conststring32 replace, int maximumNumberOfReplaces,
- integer *nmatches, integer *nstringmatches, bool use_regexp)
- {
- return use_regexp ?
- string32vector_searchAndReplace_regexp (me, search, replace, maximumNumberOfReplaces, nmatches, nstringmatches) :
- string32vector_searchAndReplace_literal (me, search, replace, maximumNumberOfReplaces, nmatches, nstringmatches);
- }
- /*
- * Acceptable ranges e.g. "1 4 2 3:7 4:3 3:5:2" -->
- * 1, 4, 2, 3, 4, 5, 6, 7, 4, 3, 3, 4, 5, 4, 3, 2
- * Overlap is allowed. Ranges can go up and down.
- */
- static autoINTVEC getElementsOfRanges (conststring32 ranges, integer maximumElement, conststring32 elementType) {
- /*
- Count the elements.
- */
- integer previousElement = 0;
- integer numberOfElements = 0;
- const char32 *p = & ranges [0];
- for (;;) {
- while (Melder_isHorizontalSpace (*p)) p ++;
- if (*p == U'\0')
- break;
- if (Melder_isAsciiDecimalNumber (*p)) {
- integer currentElement = Melder_atoi (p);
- Melder_require (currentElement != 0,
- U"No such ", elementType, U": 0 (minimum is 1).");
- Melder_require (currentElement <= maximumElement,
- U"No such ", elementType, U": ", currentElement, U" (maximum is ", maximumElement, U").");
-
- numberOfElements += 1;
- previousElement = currentElement;
- do { p ++; } while (Melder_isAsciiDecimalNumber (*p));
- } else if (*p == ':') {
- Melder_require (previousElement != 0, U"The range should not start with a colon.");
-
- do { p ++; } while (Melder_isHorizontalSpace (*p));
- Melder_require (*p != U'\0',
- U"The range should not end with a colon.");
- Melder_require (Melder_isAsciiDecimalNumber (*p),
- U"End of range should be a positive whole number.");
-
- integer currentElement = Melder_atoi (p);
- Melder_require (currentElement != 0,
- U"No such ", elementType, U": 0 (minimum is 1).");
- Melder_require (currentElement <= maximumElement,
- U"No such ", elementType, U": ", currentElement, U" (maximum is ", maximumElement, U").");
-
- if (currentElement > previousElement) {
- numberOfElements += currentElement - previousElement;
- } else {
- numberOfElements += previousElement - currentElement;
- }
- previousElement = currentElement;
- do { p ++; } while (Melder_isAsciiDecimalNumber (*p));
- } else {
- Melder_throw (U"Start of range should be a positive whole number.");
- }
- }
- /*
- Create room for the elements.
- */
-
- if (numberOfElements == 0)
- Melder_throw (U"No element(s) found");
- autoINTVEC elements = INTVECraw (numberOfElements);
- /*
- Store the elements.
- */
- previousElement = 0;
- numberOfElements = 0;
- p = & ranges [0];
- for (;;) {
- while (Melder_isHorizontalSpace (*p)) p ++;
- if (*p == U'\0')
- break;
- if (Melder_isAsciiDecimalNumber (*p)) {
- integer currentElement = Melder_atoi (p);
- elements [++ numberOfElements] = currentElement;
- previousElement = currentElement;
- do { p ++; } while (Melder_isAsciiDecimalNumber (*p));
- } else if (*p == U':') {
- do { p ++; } while (Melder_isHorizontalSpace (*p));
- integer currentElement = Melder_atoi (p);
- if (currentElement > previousElement) {
- for (integer ielement = previousElement + 1; ielement <= currentElement; ielement ++)
- elements [++ numberOfElements] = ielement;
- } else {
- for (integer ielement = previousElement - 1; ielement >= currentElement; ielement --)
- elements [++ numberOfElements] = ielement;
- }
- previousElement = currentElement;
- do { p ++; } while (Melder_isAsciiDecimalNumber (*p));
- }
- }
- return elements;
- }
- static void NUMlvector_getUniqueNumbers (integer numbers[], integer *inout_numberOfElements) {
- Melder_assert (inout_numberOfElements);
- autoNUMvector< integer> sorted (NUMvector_copy <integer> (numbers, 1, *inout_numberOfElements), 1);
- NUMsort_integer (*inout_numberOfElements, sorted.peek());
- integer numberOfMultiples = 0;
- numbers [1] = sorted [1];
- integer numberOfUniques = 1;
- for (integer i = 2; i <= *inout_numberOfElements; i ++) {
- if (sorted [i] != sorted [i - 1]) {
- numbers [++ numberOfUniques] = sorted [i];
- } else {
- numberOfMultiples ++;
- }
- }
- *inout_numberOfElements = numberOfUniques;
- }
- autoINTVEC NUMstring_getElementsOfRanges (conststring32 ranges, integer maximumElement, conststring32 elementType, bool sortedUniques)
- {
- autoINTVEC elements = getElementsOfRanges (ranges, maximumElement, elementType);
- if (sortedUniques) {
- integer size = elements.size;
- NUMlvector_getUniqueNumbers (elements.at, & size);
- elements.resize (size);
- }
- return elements;
- }
- char32 * NUMstring_timeNoDot (double time) {
- static char32 string [100];
- integer seconds = Melder_ifloor (time);
- integer ms = Melder_iround ((time - seconds) * 1000.0);
- Melder_sprint (string,100, U"_", seconds, U"_", ms);
- return string;
- }
- /* End of file NUMstring.cpp */
|