/* SPDX-License-Identifier: GPL-3.0-or-later */ #ifndef REGEX_TOOLS_PCRE2_BRIDGE_H #define REGEX_TOOLS_PCRE2_BRIDGE_H #include #define REGEX_PCRE2_BRIDGE_ABI_VERSION 3u #define REGEX_PCRE2_MAX_PATTERN_BYTES 1048576u #define REGEX_PCRE2_MAX_SUBJECT_BYTES 16777216u #define REGEX_PCRE2_MAX_REPLACEMENT_BYTES 262144u #define REGEX_PCRE2_MAX_MATCHES 10000u #define REGEX_PCRE2_MAX_CAPTURE_ROWS 100000u #define REGEX_PCRE2_MAX_CAPTURE_GROUPS 1000u #define REGEX_PCRE2_MAX_MATCH_LIMIT 100000000u #define REGEX_PCRE2_MAX_DEPTH_LIMIT 100000u #define REGEX_PCRE2_MAX_HEAP_LIMIT_KIB 131072u #define REGEX_PCRE2_MAX_TRACE_EVENTS 50000u #define REGEX_PCRE2_MAX_TRACE_BYTES 10485760u #define REGEX_PCRE2_MAX_TRACE_MARK_BYTES 1024u #define REGEX_PCRE2_UNSET_OFFSET UINT32_MAX enum regex_pcre2_flag { REGEX_PCRE2_CASELESS = 1u << 0, REGEX_PCRE2_MULTILINE = 1u << 1, REGEX_PCRE2_DOTALL = 1u << 2, REGEX_PCRE2_EXTENDED = 1u << 3, REGEX_PCRE2_UNGREEDY = 1u << 4, REGEX_PCRE2_UTF = 1u << 5, REGEX_PCRE2_UCP = 1u << 6, REGEX_PCRE2_DUPNAMES = 1u << 7, REGEX_PCRE2_GLOBAL = 1u << 8 }; enum regex_pcre2_config_flag { REGEX_PCRE2_CONFIG_UNICODE = 1u << 0, REGEX_PCRE2_CONFIG_JIT = 1u << 1 }; enum regex_pcre2_bridge_error { REGEX_PCRE2_ERROR_INVALID_ARGUMENT = -10001, REGEX_PCRE2_ERROR_UNSUPPORTED_FLAGS = -10002, REGEX_PCRE2_ERROR_PATTERN_TOO_LARGE = -10003, REGEX_PCRE2_ERROR_CONFIG = -10004, REGEX_PCRE2_ERROR_SUBJECT_TOO_LARGE = -10005, REGEX_PCRE2_ERROR_REPLACEMENT_TOO_LARGE = -10006, REGEX_PCRE2_ERROR_LIMIT_OUT_OF_RANGE = -10007, REGEX_PCRE2_ERROR_CAPTURE_LIMIT = -10008, REGEX_PCRE2_ERROR_OUTPUT_BUFFER = -10009 }; enum regex_pcre2_error_phase { REGEX_PCRE2_PHASE_NONE = 0, REGEX_PCRE2_PHASE_BRIDGE = 1, REGEX_PCRE2_PHASE_COMPILE = 2, REGEX_PCRE2_PHASE_MATCH = 3, REGEX_PCRE2_PHASE_SUBSTITUTE = 4 }; /* * This 20-byte, five-u32 record is retained for deterministic compile-only * build verification. Runtime callers should use the bounded APIs below. */ typedef struct regex_pcre2_compile_result { int32_t status; uint32_t error_offset; uint32_t capture_count; uint32_t name_count; uint32_t effective_options; } regex_pcre2_compile_result; /* All values are required and validated against the bridge hard maxima. */ typedef struct regex_pcre2_limits { uint32_t maximum_matches; uint32_t maximum_capture_rows; uint32_t match_limit; uint32_t depth_limit; uint32_t heap_limit_kib; } regex_pcre2_limits; /* * One record is emitted for group zero and every capture group of each * retained match. Unset captures use REGEX_PCRE2_UNSET_OFFSET for both bounds. */ typedef struct regex_pcre2_match_record { uint32_t match_number; uint32_t group_number; uint32_t start_byte; uint32_t end_byte; } regex_pcre2_match_record; /* Names are UTF-8 slices into the caller-owned name byte buffer. */ typedef struct regex_pcre2_name_record { uint32_t group_number; uint32_t name_offset; uint32_t name_length; } regex_pcre2_name_record; /* * Trace collection has an independent bound from match materialization. The * byte cap covers the fixed event records plus copied mark bytes. */ typedef struct regex_pcre2_trace_limits { uint32_t maximum_events; uint32_t maximum_trace_bytes; uint32_t match_limit; uint32_t depth_limit; uint32_t heap_limit_kib; } regex_pcre2_trace_limits; /* * Every field except the mark slice is copied directly from a PCRE2 callout * block. Positions and lengths are offsets in the 8-bit UTF-8 pattern or * subject supplied to the engine. */ typedef struct regex_pcre2_trace_event { uint32_t callout_number; uint32_t pattern_position_byte; uint32_t next_item_length_byte; uint32_t subject_position_byte; uint32_t capture_top; uint32_t capture_last; uint32_t mark_offset; uint32_t mark_length; } regex_pcre2_trace_event; /* * A zero status means that a bounded trace was returned. native_match_status * retains pcre2_match()'s exact result, including PCRE2_ERROR_CALLOUT when the * bridge deliberately stopped at a trace cap. last_complete_event is * UINT32_MAX when no complete event was copied. */ typedef struct regex_pcre2_trace_result { int32_t status; uint32_t error_phase; uint32_t error_offset; int32_t native_match_status; uint32_t effective_options; uint32_t event_count; uint32_t total_event_count; uint32_t mark_bytes_length; uint32_t trace_bytes_length; uint32_t events_truncated; uint32_t marks_truncated; uint32_t last_complete_event; uint32_t matched; } regex_pcre2_trace_result; /* * This fixed 60-byte record contains no native pointers. `status` is zero on * success. Otherwise `error_phase` distinguishes bridge validation, compile, * match and replacement errors; `error_offset` is a UTF-8 byte offset when the * phase provides one. */ typedef struct regex_pcre2_run_result { int32_t status; uint32_t error_phase; uint32_t error_offset; uint32_t capture_count; uint32_t name_count; uint32_t match_count; uint32_t record_count; uint32_t name_record_count; uint32_t name_bytes_length; uint32_t effective_options; uint32_t results_truncated; uint32_t names_truncated; uint32_t output_length; uint32_t substitution_count; uint32_t output_truncated; } regex_pcre2_run_result; uint32_t regex_pcre2_bridge_abi_version(void); uint32_t regex_pcre2_config_flags(void); const uint8_t *regex_pcre2_version(void); int32_t regex_pcre2_error_message(int32_t error_code, uint8_t *output, uint32_t output_capacity); int32_t regex_pcre2_compile_probe(const uint8_t *pattern, uint32_t pattern_length, uint32_t application_flags, regex_pcre2_compile_result *result); int32_t regex_pcre2_execute( const uint8_t *pattern, uint32_t pattern_length, const uint8_t *subject, uint32_t subject_length, uint32_t application_flags, const regex_pcre2_limits *limits, regex_pcre2_match_record *records, uint32_t record_capacity, regex_pcre2_name_record *name_records, uint32_t name_record_capacity, uint8_t *name_bytes, uint32_t name_bytes_capacity, regex_pcre2_run_result *result); int32_t regex_pcre2_substitute( const uint8_t *pattern, uint32_t pattern_length, const uint8_t *subject, uint32_t subject_length, const uint8_t *replacement, uint32_t replacement_length, uint32_t application_flags, const regex_pcre2_limits *limits, regex_pcre2_match_record *records, uint32_t record_capacity, regex_pcre2_name_record *name_records, uint32_t name_record_capacity, uint8_t *name_bytes, uint32_t name_bytes_capacity, /* `output` must have output_capacity + 1 writable bytes for PCRE2's NUL. */ uint8_t *output, uint32_t output_capacity, regex_pcre2_run_result *result); int32_t regex_pcre2_trace( const uint8_t *pattern, uint32_t pattern_length, const uint8_t *subject, uint32_t subject_length, uint32_t application_flags, const regex_pcre2_trace_limits *limits, regex_pcre2_trace_event *events, uint32_t event_capacity, uint8_t *mark_bytes, uint32_t mark_bytes_capacity, regex_pcre2_trace_result *result); int32_t regex_pcre2_self_test(void); #endif