module PCRE2::Lib
Constants
- PCRE2_SIZE
- PCRE2_SPTR
- PCRE2_UCHAR
For 8-bit PCRE
- PCRE2_UCHAR16
- PCRE2_UCHAR32
- PCRE2_UCHAR8
- RETURN_CODE_NO_ERROR
Public Class Methods
compile_pattern(pattern, options = [])
click to toggle source
Some utility functions to help make the above more palatable
# File lib/pcre2/lib.rb, line 62 def self.compile_pattern(pattern, options = []) pattern_string_ptr = FFI::MemoryPointer.from_string(pattern) error_code_ptr = FFI::MemoryPointer.new(:int, 1) error_offset_ptr = FFI::MemoryPointer.new(PCRE2_SIZE, 1) options = options.flatten.inject(0) { |memo, option| memo | option } pattern_ptr = PCRE2::Lib.pcre2_compile_8(pattern_string_ptr, pattern.size, options, error_code_ptr, error_offset_ptr, nil) if pattern_ptr.null? error_code = error_code_ptr.read_int error_offset = error_offset_ptr.read(PCRE2_SIZE) raise PCRE2::Error.from_error_code(error_code, "while compiling pattern #{pattern} @ #{error_offset}") end FFI::AutoPointer.new(pattern_ptr, PCRE2::Lib.method(:pcre2_code_free_8)) end
create_match_data_for_pattern(pattern_ptr)
click to toggle source
# File lib/pcre2/lib.rb, line 80 def self.create_match_data_for_pattern(pattern_ptr) match_data_ptr = PCRE2::Lib.pcre2_match_data_create_from_pattern_8(pattern_ptr, nil) FFI::AutoPointer.new(match_data_ptr, PCRE2::Lib.method(:pcre2_match_data_free_8)) end
get_error_message(error_code)
click to toggle source
# File lib/pcre2/lib.rb, line 43 def self.get_error_message(error_code) if error_code.kind_of?(FFI::MemoryPointer) error_code = error_code.read_int end buffer = FFI::MemoryPointer.new(PCRE2_UCHAR, 120) result = pcre2_get_error_message_8(error_code, buffer, buffer.size) case result when PCRE2::PCRE2_ERROR_BADDATA "Error number #{error_code} unknown" when PCRE2::PCRE2_ERROR_NOMEMORY raise PCRE2::Error, "Buffer of #{buffer.size} is not large enough to contain message" else buffer.read_string end end
get_ovector_pairs(match_data_ptr, pair_count)
click to toggle source
# File lib/pcre2/lib.rb, line 118 def self.get_ovector_pairs(match_data_ptr, pair_count) if pair_count.nil? pair_count = PCRE2::Lib.pcre2_get_ovector_count_8(match_data_ptr) end ovector_ptr = PCRE2::Lib.pcre2_get_ovector_pointer_8(match_data_ptr) type_size = FFI.type_size(:size_t) pair_count.times.map do |i| [ ovector_ptr.get(:size_t, i*2 * type_size), ovector_ptr.get(:size_t, (i*2+1) * type_size) ] end end
match(pattern_ptr, body, position: 0, match_data_ptr: nil)
click to toggle source
# File lib/pcre2/lib.rb, line 85 def self.match(pattern_ptr, body, position: 0, match_data_ptr: nil) position ||= 0 match_data_ptr ||= create_match_data_for_pattern(pattern_ptr) body_ptr = FFI::MemoryPointer.from_string(body) return_code = PCRE2::Lib.pcre2_match_8( pattern_ptr, body_ptr, body_ptr.size, position, 0, match_data_ptr, nil ) case return_code when 0 raise PCRE2::Error, "Not enough memory in MatchData to store all captures" when PCRE2::PCRE2_ERROR_NOMATCH result_count = 0 else if return_code < 0 raise PCRE2::Error.from_error_code(return_code) else result_count = return_code end end [result_count, match_data_ptr] end
named_captures(pattern_ptr)
click to toggle source
# File lib/pcre2/lib.rb, line 134 def self.named_captures(pattern_ptr) named_captures_count = FFI::MemoryPointer.new(:uint32_t, 1) name_entry_size = FFI::MemoryPointer.new(:uint32_t, 1) name_table_ptr = FFI::MemoryPointer.new(:pointer, 1) if PCRE2::Lib.pcre2_pattern_info_8(pattern_ptr, PCRE2::PCRE2_INFO_NAMECOUNT, named_captures_count) != 0 raise "Something went wrong" end if PCRE2::Lib.pcre2_pattern_info_8(pattern_ptr, PCRE2::PCRE2_INFO_NAMEENTRYSIZE, name_entry_size) != 0 raise "Something went wrong" end if PCRE2::Lib.pcre2_pattern_info_8(pattern_ptr, PCRE2::PCRE2_INFO_NAMETABLE, name_table_ptr) != 0 raise "Something went wrong" end named_captures_count = named_captures_count.read_uint32 name_entry_size = name_entry_size.read_uint32 name_table_ptr = name_table_ptr.read_pointer names_and_positions = named_captures_count.times.map do |i| ovector_position = (name_table_ptr.get_int8(0) << 8) + name_table_ptr.get_int8(1) match_name = (name_table_ptr+2).read_string_to_null name_table_ptr += name_entry_size [match_name, ovector_position] end # Convert an array of [name, position] into a Hash of name => [position (, position, ...)], with possible duplicate names names_and_positions.each_with_object(Hash.new {[]} ) { |(name, position), hash| hash[name] <<= position } end