summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2019-05-03 13:40:48 +0100
committerChris Liddell <chris.liddell@artifex.com>2019-05-24 13:09:53 +0100
commit1552c8f7b223f77d6de2c0595bb50f2e27a3a2d8 (patch)
treed0fd1202305d9a47ff6809090a06a95f0609fafd
parenta9d2fc1651055d76b6881a2feca19df2a36a0228 (diff)
downloadghostpdl-1552c8f7b223f77d6de2c0595bb50f2e27a3a2d8.tar.gz
Add a non-standard string 'reverse search" operator
The search operator searches for the first occurrence of a character code in a string (i.e. searches forwards from the start of the string), 'rsearch' finds the last instance of a character code (i.e. search backwards from the end of the string).
-rw-r--r--psi/zstring.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/psi/zstring.c b/psi/zstring.c
index 24afcc6e4..fac72fa86 100644
--- a/psi/zstring.c
+++ b/psi/zstring.c
@@ -103,10 +103,10 @@ zanchorsearch(i_ctx_t *i_ctx_p)
return 0;
}
-/* <string> <pattern> search <post> <match> <pre> -true- */
-/* <string> <pattern> search <string> -false- */
+/* <string> <pattern> (r)search <post> <match> <pre> -true- */
+/* <string> <pattern> (r)search <string> -false- */
static int
-zsearch(i_ctx_t *i_ctx_p)
+search_impl(i_ctx_t *i_ctx_p, bool forward)
{
os_ptr op = osp;
os_ptr op1 = op - 1;
@@ -115,6 +115,7 @@ zsearch(i_ctx_t *i_ctx_p)
byte *pat;
byte *ptr;
byte ch;
+ int incr = forward ? 1 : -1;
check_read_type(*op1, t_string);
check_read_type(*op, t_string);
@@ -126,12 +127,14 @@ zsearch(i_ctx_t *i_ctx_p)
ptr = op1->value.bytes;
if (size == 0)
goto found;
+ if (!forward)
+ ptr += count;
pat = op->value.bytes;
ch = pat[0];
do {
if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
goto found;
- ptr++;
+ ptr += incr;
}
while (count--);
/* No match */
@@ -145,11 +148,25 @@ found:
op[-1] = *op1;
r_set_size(op - 1, ptr - op[-1].value.bytes);
op1->value.bytes = ptr + size;
- r_set_size(op1, count);
+ r_set_size(op1, count + (!forward ? (size - 1) : 0));
make_true(op);
return 0;
}
+/* Search from the start of the string */
+static int
+zsearch(i_ctx_t *i_ctx_p)
+{
+ return search_impl(i_ctx_p, true);
+}
+
+/* Search from the end of the string */
+static int
+zrsearch(i_ctx_t *i_ctx_p)
+{
+ return search_impl(i_ctx_p, false);
+}
+
/* <string> <charstring> .stringbreak <int|null> */
static int
zstringbreak(i_ctx_t *i_ctx_p)
@@ -208,6 +225,7 @@ const op_def zstring_op_defs[] =
{"2anchorsearch", zanchorsearch},
{"1.namestring", znamestring},
{"2search", zsearch},
+ {"2rsearch", zrsearch},
{"1string", zstring},
{"2.stringbreak", zstringbreak},
{"2.stringmatch", zstringmatch},