summaryrefslogtreecommitdiff
path: root/prism/memchr.c
diff options
context:
space:
mode:
Diffstat (limited to 'prism/memchr.c')
-rw-r--r--prism/memchr.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/prism/memchr.c b/prism/memchr.c
new file mode 100644
index 0000000000..900e6245b7
--- /dev/null
+++ b/prism/memchr.c
@@ -0,0 +1,37 @@
+#include "prism/internal/memchr.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#define TRAILING_BYTE_MINIMUM 0x40
+
+/**
+ * We need to roll our own memchr to handle cases where the encoding changes and
+ * we need to search for a character in a buffer that could be the trailing byte
+ * of a multibyte character.
+ */
+const void *
+pm_memchr(const void *memory, int character, size_t number, bool encoding_changed, const pm_encoding_t *encoding) {
+ if (encoding_changed && encoding->multibyte && character >= TRAILING_BYTE_MINIMUM) {
+ const uint8_t *source = (const uint8_t *) memory;
+ size_t index = 0;
+
+ while (index < number) {
+ if (source[index] == character) {
+ return (void *) (source + index);
+ }
+
+ size_t width = encoding->char_width(source + index, (ptrdiff_t) (number - index));
+ if (width == 0) {
+ return NULL;
+ }
+
+ index += width;
+ }
+
+ return NULL;
+ } else {
+ return memchr(memory, character, number);
+ }
+}