26#if defined (HAVE_CONFIG_H)
54do_regexp_ptn_string_escapes (
const std::string& s,
bool is_sq_str)
60 std::size_t
len = s.length ();
66 if (s[j] ==
'\\' && j+1 <
len)
83 retval.insert (i,
"(?<=\\W|^)");
88 retval.insert (i,
"(?=\\W|$)");
94 bool bad_esc_seq = (j+1 >=
len);
97 if (! bad_esc_seq && s[++j] ==
'{')
105 for (k = j; k < std::min (j+3+brace,
len); k++)
107 int digit = s[k] -
'0';
108 if (digit < 0 || digit > 7)
113 if (bad_esc_seq || (brace && s[k++] !=
'}'))
116 warning (R
"(malformed octal escape sequence '\o' -- converting to '\0')");
144do_regexp_rep_string_escapes (
const std::string& s)
150 std::size_t
len = s.length ();
156 if (s[j] ==
'\\' && j+1 <
len)
198 int tmpi = s[j] -
'0';
199 for (k = j+1; k < std::min (j+3,
len); k++)
201 int digit = s[k] -
'0';
202 if (digit < 0 || digit > 7)
214 bool bad_esc_seq = (j+1 >=
len);
217 if (! bad_esc_seq && s[++j] ==
'{')
225 for (k = j; k < std::min (j+3+brace,
len); k++)
227 int digit = s[k] -
'0';
228 if (digit < 0 || digit > 7)
233 if (bad_esc_seq || (brace && s[k++] !=
'}'))
235 warning (R
"(malformed octal escape sequence '\o' -- converting to '\0')");
245 bool bad_esc_seq = (j+1 >=
len);
248 if (! bad_esc_seq && s[++j] ==
'{')
256 for (k = j; k < std::min (j+2+brace,
len); k++)
258 if (! isxdigit (s[k]))
264 tmpi += digit -
'a' + 10;
265 else if (digit >=
'A')
266 tmpi += digit -
'A' + 10;
270 if (bad_esc_seq || (brace && s[k++] !=
'}'))
272 warning (R
"(malformed hex escape sequence '\x' -- converting to '\0')");
285 retval[i] =
'\\'; retval[++i] =
'$';
289 retval[i] =
'\\'; retval[++i] =
'\\';
313 const std::string& who,
int skip,
bool& extra_args)
317 for (
int i = skip; i < args.
length (); i++)
321 str = args(i).xstring_value (
"%s: optional arguments must be strings", who.c_str ());
323 std::transform (str.begin (), str.end (), str.begin (), tolower);
325 if (str.find (
"once", 0) == 0)
327 else if (str.find (
"matchcase", 0) == 0)
329 else if (str.find (
"ignorecase", 0) == 0)
331 else if (str.find (
"dotall", 0) == 0)
333 else if (str.find (
"stringanchors", 0) == 0)
335 else if (str.find (
"literalspacing", 0) == 0)
337 else if (str.find (
"noemptymatch", 0) == 0)
339 else if (str.find (
"dotexceptnewline", 0) == 0)
341 else if (str.find (
"lineanchors", 0) == 0)
343 else if (str.find (
"freespacing", 0) == 0)
345 else if (str.find (
"emptymatch", 0) == 0)
347 else if (str.find (
"start", 0) == 0
348 || str.find (
"end", 0) == 0
349 || str.find (
"tokenextents", 0) == 0
350 || str.find (
"match", 0) == 0
351 || str.find (
"tokens", 0) == 0
352 || str.find (
"names", 0) == 0
353 || str.find (
"split", 0) == 0)
356 error (
"%s: unrecognized option", who.c_str ());
362 const std::string& who,
bool case_insensitive =
false)
366 int nargin = args.
length ();
369 const std::string buffer = args(0).string_value ();
371 std::string pattern = args(1).string_value ();
374 pattern = do_regexp_ptn_string_escapes (pattern, args(1).is_sq_string ());
378 bool extra_options =
false;
379 parse_options (options, args, who, 2, extra_options);
386 std::size_t sz = rx_lst.size ();
396 for (
int j = 0; j < named_pats.
numel (); j++)
401 for (
const auto& match_data : rx_lst)
405 ctmp(i++) = named_tokens(j);
408 nmap.
assign (named_pats(j), ctmp);
415 auto p = rx_lst.begin ();
417 retval(4) = (sz ? p->tokens () :
Cell ());
418 retval(3) = (sz ? p->match_string () :
"");
419 retval(2) = (sz ? p->token_extents () :
Matrix ());
423 double start = p->start ();
424 double end = p->end ();
427 split(0) = buffer.substr (0, start-1);
428 split(1) = buffer.substr (end);
449 std::size_t sp_start = 0;
452 for (
const auto& match_data : rx_lst)
454 double s = match_data.start ();
455 double e = match_data.end ();
459 match_string(i) = match_data.match_string ();
460 token_extents(i) = match_data.token_extents ();
463 split(i) = buffer.substr (sp_start, s-sp_start-1);
468 split(i) = buffer.substr (sp_start);
472 retval(3) = match_string;
473 retval(2) = token_extents;
484 new_retval.
resize (nargout);
488 for (
int j = 2; j < nargin; j++)
491 std::string str = args(j).string_value ();
492 std::transform (str.begin (), str.end (), str.begin (), tolower);
494 if (str.find (
"once", 0) == 0
495 || str.find (
"stringanchors", 0) == 0
496 || str.find (
"lineanchors", 0) == 0
497 || str.find (
"matchcase", 0) == 0
498 || str.find (
"ignorecase", 0) == 0
499 || str.find (
"dotall", 0) == 0
500 || str.find (
"dotexceptnewline", 0) == 0
501 || str.find (
"literalspacing", 0) == 0
502 || str.find (
"freespacing", 0) == 0
503 || str.find (
"noemptymatch", 0) == 0
504 || str.find (
"emptymatch", 0) == 0)
506 else if (str.find (
"start", 0) == 0)
508 else if (str.find (
"end", 0) == 0)
510 else if (str.find (
"tokenextents", 0) == 0)
512 else if (str.find (
"match", 0) == 0)
514 else if (str.find (
"tokens", 0) == 0)
516 else if (str.find (
"names", 0) == 0)
518 else if (str.find (
"split", 0) == 0)
521 new_retval(n++) = retval(k);
531 for (
int j = 0; j < 7; j++)
534 new_retval(n++) = retval(j);
546 const std::string& who,
bool case_insensitive =
false)
550 if (args(0).iscell ())
555 if (args(1).iscell ())
559 if (cellpat.
numel () == 1)
561 for (
int j = 0; j < nargout; j++)
562 newretval[j].resize (cellstr.
dims ());
564 new_args(1) = cellpat(0);
568 new_args(0) = cellstr(i);
572 for (
int j = 0; j < nargout; j++)
573 newretval[j](i) = tmp(j);
576 else if (cellstr.
numel () == 1)
578 for (
int j = 0; j < nargout; j++)
579 newretval[j].resize (cellpat.
dims ());
581 new_args(0) = cellstr(0);
585 new_args(1) = cellpat(i);
589 for (
int j = 0; j < nargout; j++)
590 newretval[j](i) = tmp(j);
593 else if (cellstr.
numel () == cellpat.
numel ())
595 if (cellstr.
dims () != cellpat.
dims ())
596 error (
"%s: inconsistent cell array dimensions", who.c_str ());
598 for (
int j = 0; j < nargout; j++)
599 newretval[j].resize (cellstr.
dims ());
603 new_args(0) = cellstr(i);
604 new_args(1) = cellpat(i);
609 for (
int j = 0; j < nargout; j++)
610 newretval[j](i) = tmp(j);
614 error (
"regexp: cell array arguments must be scalar or equal size");
618 for (
int j = 0; j < nargout; j++)
619 newretval[j].resize (cellstr.
dims ());
623 new_args(0) = cellstr(i);
627 for (
int j = 0; j < nargout; j++)
628 newretval[j](i) = tmp(j);
632 for (
int j = 0; j < nargout; j++)
635 else if (args(1).iscell ())
641 for (
int j = 0; j < nargout; j++)
642 newretval[j].resize (cellpat.
dims ());
646 new_args(1) = cellpat(i);
650 for (
int j = 0; j < nargout; j++)
651 newretval[j](i) = tmp(j);
654 for (
int j = 0; j < nargout; j++)
658 retval = octregexp (args, nargout, who, case_insensitive);
897 if (args(0).iscell () || args(1).iscell ())
898 retval = (octcellregexp (args, (nargout > 0 ? nargout : 1),
"regexp"));
900 retval = octregexp (args, nargout,
"regexp");
1223DEFUN (regexpi, args, nargout,
1240 if (args(0).iscell () || args(1).iscell ())
1241 return octcellregexp (args, (nargout > 0 ? nargout : 1),
"regexpi",
true);
1243 return octregexp (args, nargout,
"regexpi",
true);
1386 int nargin = args.
length ();
1389 const std::string buffer = args(0).string_value ();
1391 std::string pattern = args(1).string_value ();
1394 pattern = do_regexp_ptn_string_escapes (pattern, args(1).is_sq_string ());
1396 std::string replacement = args(2).string_value ();
1399 if (args(2).is_sq_string ())
1400 replacement = do_regexp_rep_string_escapes (replacement);
1407 for (
int i = 3; i < nargin; i++)
1409 const std::string opt = args(i).string_value ();
1410 if (opt !=
"tokenize" && opt !=
"start" && opt !=
"end"
1411 && opt !=
"tokenextents" && opt !=
"match" && opt !=
"tokens"
1412 && opt !=
"names" && opt !=
"split" && opt !=
"warnings")
1414 regexpargs(
len++) = args(i);
1417 regexpargs.resize (
len);
1420 bool extra_args =
false;
1421 parse_options (options, regexpargs, who, 0, extra_args);
1426DEFUN (regexprep, args, ,
1473 if (args(0).iscell () || args(1).iscell () || args(2).iscell ())
1479 if (args(0).iscell ())
1482 str =
Cell (args(0));
1484 if (args(1).iscell ())
1487 pat =
Cell (args(1));
1489 if (args(2).iscell ())
1492 rep =
Cell (args(2));
1495 if (pat.
numel () != 1)
1498 if (rep.
numel () != 1 && dv1 != rep.
dims ())
1499 error (
"regexprep: inconsistent cell array dimensions");
1501 else if (rep.
numel () != 1)
1509 new_args(0) = str(i);
1510 if (pat.
numel () == 1)
1511 new_args(1) = pat(0);
1512 if (rep.
numel () == 1)
1513 new_args(2) = rep(0);
1517 if (pat.
numel () != 1)
1518 new_args(1) = pat(j);
1519 if (rep.
numel () != 1)
1520 new_args(2) = rep(j);
1521 new_args(0) = octregexprep (new_args,
"regexprep");
1524 ret(i) = new_args(0);
1527 retval = (args(0).iscell () ?
ovl (ret) :
ovl (ret(0)));
1530 retval = octregexprep (args,
"regexprep");
1615OCTAVE_END_NAMESPACE(octave)
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
octave_idx_type numel() const
Number of elements in the array.
Vector representing the dimensions (size) of an Array.
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
void assign(const std::string &k, const Cell &val)
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
octave_idx_type length() const
string_vector named_patterns() const
void dotexceptnewline(bool val)
void lineanchors(bool val)
void case_insensitive(bool val)
void freespacing(bool val)
void emptymatch(bool val)
std::string replace(const std::string &buffer, const std::string &replacement) const
match_data match(const std::string &buffer) const
octave_idx_type numel() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void warning(const char *fmt,...)
void error(const char *fmt,...)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.