-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
Copy pathpcre.jl
133 lines (118 loc) · 4.21 KB
/
pcre.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
## low-level pcre interface ##
module PCRE
include("pcre_h.jl")
const VERSION = bytestring(ccall((:pcre_version, :libpcre), Ptr{Uint8}, ()))
# supported options for different use cases
const COMPILE_MASK =
ANCHORED |
CASELESS |
DOLLAR_ENDONLY |
DOTALL |
EXTENDED |
FIRSTLINE |
JAVASCRIPT_COMPAT |
MULTILINE |
NEWLINE_ANY |
NEWLINE_ANYCRLF |
NEWLINE_CR |
NEWLINE_CRLF |
NEWLINE_LF |
NO_AUTO_CAPTURE |
NO_START_OPTIMIZE |
NO_UTF8_CHECK |
UNGREEDY |
UTF8
const EXECUTE_MASK =
NEWLINE_ANY |
NEWLINE_ANYCRLF |
NEWLINE_CR |
NEWLINE_CRLF |
NEWLINE_LF |
NOTBOL |
NOTEMPTY |
NOTEMPTY_ATSTART |
NOTEOL |
NO_START_OPTIMIZE |
NO_UTF8_CHECK |
PARTIAL_HARD |
PARTIAL_SOFT
const OPTIONS_MASK = COMPILE_MASK | EXECUTE_MASK
function info{T}(
regex::Union(Ptr{Void},Vector{Uint8}),
extra::Ptr{Void}, what::Integer, ::Type{T}
)
buf = Array(Uint8,sizeof(T))
ret = ccall((:pcre_fullinfo, :libpcre), Int32,
(Ptr{Void}, Ptr{Void}, Int32, Ptr{Uint8}),
regex, extra, what, buf)
if ret != 0
error("info: ",
ret == ERROR_NULL ? "NULL regex object" :
ret == ERROR_BADMAGIC ? "invalid regex object" :
ret == ERROR_BADOPTION ? "invalid option flags" :
"unknown error $ret")
end
reinterpret(T,buf)[1]
end
function config{T}(what::Integer, ::Type{T})
buf = Array(Uint8, sizeof(T))
ret = ccall((:pcre_config, :libpcre), Int32,
(Int32, Ptr{Uint8}),
what, buf)
if ret != 0
error("config: error $n")
end
reinterpret(T,buf)[1]
end
function compile(pattern::String, options::Integer)
errstr = Array(Ptr{Uint8},1)
erroff = Array(Int32,1)
re_ptr = (()->ccall((:pcre_compile, :libpcre), Ptr{Void},
(Ptr{Uint8}, Int32, Ptr{Ptr{Uint8}}, Ptr{Int32}, Ptr{Uint8}),
pattern, options, errstr, erroff, C_NULL))()
if re_ptr == C_NULL
error("compile: $(bytestring(errstr[1]))",
" at position $(erroff[1]+1)",
" in $(repr(pattern))")
end
size = info(re_ptr, C_NULL, INFO_SIZE, Int32)
regex = Array(Uint8,size)
ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), regex, re_ptr, size)
regex
end
function study(regex::Array{Uint8}, options::Integer)
# NOTE: options should always be zero in current PCRE
errstr = Array(Ptr{Uint8},1)
extra = ccall((:pcre_study, :libpcre), Ptr{Void},
(Ptr{Void}, Int32, Ptr{Ptr{Uint8}}),
regex, options, errstr)
if errstr[1] != C_NULL
error("study: $(bytestring(errstr[1]))")
end
extra
end
study(re::Array{Uint8}) = study(re, int32(0))
free_study(extra::Ptr{Void}) =
ccall((:pcre_free_study, :libpcre), Void, (Ptr{Void},), extra)
exec(regex::Array{Uint8}, extra::Ptr{Void}, str::SubString, offset::Integer, options::Integer, cap::Bool) =
exec(regex, extra, str.string, str.offset, offset, sizeof(str), options, cap)
exec(regex::Array{Uint8}, extra::Ptr{Void}, str::ByteString, offset::Integer, options::Integer, cap::Bool) =
exec(regex, extra, str, 0, offset, sizeof(str), options, cap)
function exec(regex::Array{Uint8}, extra::Ptr{Void},
str::ByteString, shift::Integer, offset::Integer, len::Integer, options::Integer, cap::Bool)
if offset < 0 || len < offset || len+shift > sizeof(str)
error(BoundsError)
end
ncap = info(regex, extra, INFO_CAPTURECOUNT, Int32)
ovec = Array(Int32, 3(ncap+1))
n = ccall((:pcre_exec, :libpcre), Int32,
(Ptr{Void}, Ptr{Void}, Ptr{Uint8}, Int32,
Int32, Int32, Ptr{Int32}, Int32),
regex, extra, pointer(str.data,shift+1), len,
offset, options, ovec, length(ovec))
if n < -1
error("exec: error $n")
end
cap ? ((n > -1 ? ovec[1:2(ncap+1)] : Array(Int32,0)), ncap) : n > -1
end
end # module