mirror of
https://github.com/macports/macports-ports.git
synced 2026-07-12 18:20:25 -07:00
252 lines
7.9 KiB
Diff
252 lines
7.9 KiB
Diff
Patch made with:
|
|
https://github.com/christian-proust/sqlite3-pcre2/blob/e3e02a4af39d5dfdbd2cc8801696ed9ae2faf569/pcre2.c
|
|
with the additional change to 'const unsigned char *pattern_str, *subject_str;'.
|
|
|
|
|
|
--- pcre.c.orig 2023-06-14 08:44:05.000000000 +0200
|
|
+++ pcre.c 2023-06-14 09:01:48.000000000 +0200
|
|
@@ -1,22 +1,24 @@
|
|
/*
|
|
- * Written by Alexey Tourbin <at@altlinux.org>.
|
|
+ * Initially written by Alexey Tourbin <at@altlinux.org>.
|
|
*
|
|
* The author has dedicated the code to the public domain. Anyone is free
|
|
* to copy, modify, publish, use, compile, sell, or distribute the original
|
|
* code, either in source code form or as a compiled binary, for any purpose,
|
|
* commercial or non-commercial, and by any means.
|
|
*/
|
|
+#define PCRE2_CODE_UNIT_WIDTH 8
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
-#include <pcre.h>
|
|
+#include <pcre2.h>
|
|
#include <sqlite3ext.h>
|
|
+
|
|
SQLITE_EXTENSION_INIT1
|
|
|
|
typedef struct {
|
|
- char *s;
|
|
- pcre *p;
|
|
- pcre_extra *e;
|
|
+ char *pattern_str;
|
|
+ int pattern_len;
|
|
+ pcre2_code *pattern_code;
|
|
} cache_entry;
|
|
|
|
#ifndef CACHE_SIZE
|
|
@@ -24,96 +26,136 @@
|
|
#endif
|
|
|
|
static
|
|
-void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv)
|
|
-{
|
|
- const char *re, *str;
|
|
- pcre *p;
|
|
- pcre_extra *e;
|
|
+void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
|
|
+ const unsigned char *pattern_str, *subject_str;
|
|
+ int pattern_len, subject_len;
|
|
+ pcre2_code *pattern_code;
|
|
|
|
assert(argc == 2);
|
|
+ /* check null */
|
|
+ if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
|
|
+ return;
|
|
+ }
|
|
|
|
- re = (const char *) sqlite3_value_text(argv[0]);
|
|
- if (!re) {
|
|
- sqlite3_result_error(ctx, "no regexp", -1);
|
|
- return;
|
|
+ pattern_str = sqlite3_value_text(argv[0]);
|
|
+ if (!pattern_str) {
|
|
+ sqlite3_result_error(ctx, "no pattern", -1);
|
|
+ return;
|
|
}
|
|
+ pattern_len = sqlite3_value_bytes(argv[0]);
|
|
|
|
- str = (const char *) sqlite3_value_text(argv[1]);
|
|
- if (!str) {
|
|
- sqlite3_result_error(ctx, "no string", -1);
|
|
- return;
|
|
+ subject_str = sqlite3_value_text(argv[1]);
|
|
+ if (!subject_str) {
|
|
+ sqlite3_result_error(ctx, "no subject", -1);
|
|
+ return;
|
|
}
|
|
+ subject_len = sqlite3_value_bytes(argv[1]);
|
|
|
|
/* simple LRU cache */
|
|
{
|
|
- int i;
|
|
- int found = 0;
|
|
- cache_entry *cache = sqlite3_user_data(ctx);
|
|
-
|
|
- assert(cache);
|
|
-
|
|
- for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
|
|
- if (strcmp(re, cache[i].s) == 0) {
|
|
- found = 1;
|
|
- break;
|
|
- }
|
|
- if (found) {
|
|
- if (i > 0) {
|
|
- cache_entry c = cache[i];
|
|
- memmove(cache + 1, cache, i * sizeof(cache_entry));
|
|
- cache[0] = c;
|
|
- }
|
|
- }
|
|
- else {
|
|
- cache_entry c;
|
|
- const char *err;
|
|
- int pos;
|
|
- c.p = pcre_compile(re, 0, &err, &pos, NULL);
|
|
- if (!c.p) {
|
|
- char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos);
|
|
- sqlite3_result_error(ctx, e2, -1);
|
|
- sqlite3_free(e2);
|
|
- return;
|
|
- }
|
|
- c.e = pcre_study(c.p, 0, &err);
|
|
- c.s = strdup(re);
|
|
- if (!c.s) {
|
|
- sqlite3_result_error(ctx, "strdup: ENOMEM", -1);
|
|
- pcre_free(c.p);
|
|
- pcre_free(c.e);
|
|
- return;
|
|
- }
|
|
- i = CACHE_SIZE - 1;
|
|
- if (cache[i].s) {
|
|
- free(cache[i].s);
|
|
- assert(cache[i].p);
|
|
- pcre_free(cache[i].p);
|
|
- pcre_free(cache[i].e);
|
|
- }
|
|
- memmove(cache + 1, cache, i * sizeof(cache_entry));
|
|
- cache[0] = c;
|
|
- }
|
|
- p = cache[0].p;
|
|
- e = cache[0].e;
|
|
+ int i;
|
|
+ int found = 0;
|
|
+ cache_entry *cache = sqlite3_user_data(ctx);
|
|
+
|
|
+ assert(cache);
|
|
+
|
|
+ for (i = 0; i < CACHE_SIZE && cache[i].pattern_str; i++)
|
|
+ if (
|
|
+ pattern_len == cache[i].pattern_len
|
|
+ && memcmp(pattern_str, cache[i].pattern_str, pattern_len) == 0
|
|
+ ) {
|
|
+ found = 1;
|
|
+ break;
|
|
+ }
|
|
+ if (found) {
|
|
+ if (i > 0) {
|
|
+ cache_entry c = cache[i];
|
|
+ memmove(cache + 1, cache, i * sizeof(cache_entry));
|
|
+ cache[0] = c;
|
|
+ }
|
|
+ } else {
|
|
+ cache_entry c;
|
|
+ const char *err;
|
|
+ int error_code;
|
|
+ PCRE2_SIZE error_position;
|
|
+ c.pattern_code = pcre2_compile(
|
|
+ pattern_str, /* the pattern */
|
|
+ pattern_len, /* the length of the pattern */
|
|
+ 0, /* default options */
|
|
+ &error_code, /* for error number */
|
|
+ &error_position, /* for error offset */
|
|
+ NULL); /* use default compile context */
|
|
+ if (!c.pattern_code) {
|
|
+ PCRE2_UCHAR error_buffer[256];
|
|
+ pcre2_get_error_message(error_code, error_buffer, sizeof(error_buffer));
|
|
+ char *e2 = sqlite3_mprintf(
|
|
+ "Cannot compile pattern \"%s\" at offset %d: %s",
|
|
+ pattern_str, (int)error_position, error_buffer);
|
|
+ sqlite3_result_error(ctx, e2, -1);
|
|
+ sqlite3_free(e2);
|
|
+ return;
|
|
+ }
|
|
+ c.pattern_str = malloc(pattern_len);
|
|
+ if (!c.pattern_str) {
|
|
+ sqlite3_result_error(ctx, "malloc: ENOMEM", -1);
|
|
+ pcre2_code_free(c.pattern_code);
|
|
+ return;
|
|
+ }
|
|
+ memcpy(c.pattern_str, pattern_str, pattern_len);
|
|
+ c.pattern_len = pattern_len;
|
|
+ i = CACHE_SIZE - 1;
|
|
+ if (cache[i].pattern_str) {
|
|
+ free(cache[i].pattern_str);
|
|
+ assert(cache[i].pattern_code);
|
|
+ pcre2_code_free(cache[i].pattern_code);
|
|
+ }
|
|
+ memmove(cache + 1, cache, i * sizeof(cache_entry));
|
|
+ cache[0] = c;
|
|
+ }
|
|
+ pattern_code = cache[0].pattern_code;
|
|
}
|
|
|
|
{
|
|
- int rc;
|
|
- assert(p);
|
|
- rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
|
|
- sqlite3_result_int(ctx, rc >= 0);
|
|
- return;
|
|
+ int rc;
|
|
+ pcre2_match_data *match_data;
|
|
+ assert(pattern_code);
|
|
+
|
|
+ match_data = pcre2_match_data_create_from_pattern(pattern_code, NULL);
|
|
+ rc = pcre2_match(
|
|
+ pattern_code, /* the compiled pattern */
|
|
+ subject_str, /* the subject string */
|
|
+ subject_len, /* the length of the subject */
|
|
+ 0, /* start at offset 0 in the subject */
|
|
+ 0, /* default options */
|
|
+ match_data, /* block for storing the result */
|
|
+ NULL); /* use default match context */
|
|
+
|
|
+ assert(rc != 0); // because we have not set match_data
|
|
+ if(rc >= 0) {
|
|
+ // Normal case because we have not set match_data
|
|
+ sqlite3_result_int(ctx, 1);
|
|
+ } else if(rc == PCRE2_ERROR_NOMATCH) {
|
|
+ sqlite3_result_int(ctx, 0);
|
|
+ } else { // (rc < 0 and the code is not one of the above)
|
|
+ PCRE2_UCHAR error_buffer[256];
|
|
+ pcre2_get_error_message(rc, error_buffer, sizeof(error_buffer));
|
|
+ char *e2 = sqlite3_mprintf("%s", error_buffer);
|
|
+ sqlite3_result_error(ctx, e2, -1);
|
|
+ sqlite3_free(e2);
|
|
+ return;
|
|
+ }
|
|
+ pcre2_match_data_free(match_data);
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
-int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api)
|
|
-{
|
|
- SQLITE_EXTENSION_INIT2(api)
|
|
- cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry));
|
|
- if (!cache) {
|
|
- *err = "calloc: ENOMEM";
|
|
- return 1;
|
|
- }
|
|
- sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL);
|
|
- return 0;
|
|
+int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api) {
|
|
+ SQLITE_EXTENSION_INIT2(api)
|
|
+ cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry));
|
|
+ if (!cache) {
|
|
+ *err = "calloc: ENOMEM";
|
|
+ return 1;
|
|
+ }
|
|
+ sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL);
|
|
+ return 0;
|
|
}
|