barx 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/xri_parser.rb ADDED
@@ -0,0 +1,163 @@
1
+ module XriParser
2
+ class AuthorityParser
3
+ ## AuthorityParser.parse(xri) returns an AuthorityParser object
4
+ ## Pass in <false> as a second arg to parse a local (rootless) XRI
5
+ class <<self
6
+ def parse(xri, get_root=true)
7
+ AuthorityParser.new(xri, get_root)
8
+ end
9
+ end
10
+
11
+ attr_reader :root, :subsegments, :authority, :local, :query, :qxri
12
+ attr_accessor :path
13
+
14
+ def initialize(xri, get_root=true)
15
+ @root = String.new
16
+ @subsegments = Array.new
17
+ xri = xri.strip rescue nil
18
+ xri = xri_strip_scheme(xri) rescue nil
19
+ @qxri = xri
20
+ raise 'No XRI Received' if xri.nil? or xri.empty?
21
+ #get root
22
+ if get_root
23
+ gcs_chars = Regexp.escape("@=!+*()")
24
+ gcs_connectors = Regexp.escape("@=!+*")
25
+ dns_rgx = Regexp.new("\\A(\\$dns\\*[^#{gcs_chars}]+)([#{gcs_connectors}].*)\\z", true)
26
+ ## equivalent to: /\A(\$dns\*[^@=!\+\*\(\)]+)([@=!\+\*].*)\z/i
27
+ ip_rgx = Regexp.new("\\A(\\$ip\\*[^#{gcs_chars}]+)([#{gcs_connectors}].*)\\z", true)
28
+ ## equivalent to: /\A(\$ip\*[^@=!\+\*\(\)]+)([@=!\+\*].*)\z/i
29
+ simple_roots = [?=, ?@, ?!, ?+]
30
+ if simple_roots.include? xri[0]
31
+ @root = xri[0].chr
32
+ xri = xri[1..-1] # xri is now the rest of xri after the root
33
+ elsif xri[0,2] == '$('
34
+ paren = 0
35
+ pointer = 0
36
+
37
+ @root = '$'
38
+ xri = xri[1..-1]
39
+ xri.each_byte do |c|
40
+ paren += 1 if c == ?(
41
+ paren -= 1 if c == ?)
42
+ pointer += 1
43
+ @root << c.chr
44
+ break if paren.zero?
45
+ end
46
+
47
+ xri = xri[pointer..-1] # xri is now the rest of xri after the root
48
+ elsif xri =~ dns_rgx
49
+ @root = $1
50
+ xri = $2
51
+ elsif xri =~ ip_rgx
52
+ @root = $1
53
+ xri = $2
54
+ else
55
+ raise XRIRootMissing, 'No XRI root'
56
+ end
57
+ end
58
+
59
+ if xri.length < 1
60
+ return true
61
+ end
62
+ if (@root == '!') and (xri[0] != ?!)
63
+ raise 'XRIs in the ! registry must start with !'
64
+ end
65
+
66
+ subsegment_delimiters = [?@, ?=, ?!, ?+, ?*]
67
+ #add implicit * after root if neccessary
68
+ xri.insert(0,'*') unless subsegment_delimiters.include? xri[0]
69
+ open_paren = 0
70
+ close_paren = 0
71
+ segment_buf = String.new
72
+
73
+ # get subsegments
74
+ xri.each_byte do |c|
75
+ open_paren += 1 if c == ?(
76
+ close_paren += 1 if c == ?)
77
+ # if we're inside an xref keep adding to buffer
78
+ if (open_paren > 0) and (open_paren != close_paren)
79
+ segment_buf << c.chr
80
+ next
81
+ end
82
+ # starting a new subsegment
83
+ if subsegment_delimiters.include? c
84
+ # flush the buffer
85
+ @subsegments << segment_buf unless segment_buf.empty?
86
+ # initialize a new buffer
87
+ segment_buf = ""
88
+ # add the delimiter to the buffer
89
+ segment_buf << c.chr
90
+ elsif (c == ?/) or (c == ??) or (c == ?#) #end of authority parsing
91
+ break
92
+ else
93
+ # add the character to the buffer
94
+ segment_buf << c.chr
95
+ end
96
+ end
97
+
98
+ @subsegments << segment_buf # flush buffer at the end
99
+ @local = xri[@subsegments.to_s.length..-1] # the rest of xri
100
+ @path = @local.index('?') ? @local[/^(.*)\?/, 1] : @local # path is everything up to a question mark
101
+ @query = @local.index('?') ? @local[/\?(.*)$/, 1] : '' # query is everything after a question mark
102
+ @authority = self.normalized
103
+ true
104
+ end
105
+
106
+ def xri_strip_scheme(xri)
107
+ if xri[0..5] =~ /xri:\/\//i
108
+ xri[6..-1]
109
+ elsif xri[0..3] =~ /xri:/i
110
+ xri[4..-1]
111
+ else
112
+ xri
113
+ end
114
+ end
115
+
116
+ def is_inumber?
117
+ @subsegments.each {|seg| return false if seg[0] != ?!}
118
+ true
119
+ end
120
+
121
+ def community
122
+ all_but_last_seg = @subsegments[0..-2].to_s
123
+ # strip off leading * if i-name and root is = or @
124
+ if @root == '@' or @root == '='
125
+ all_but_last_seg = all_but_last_seg[1..-1] if all_but_last_seg[0] == ?*
126
+ end
127
+ unless all_but_last_seg.nil? or all_but_last_seg.empty?
128
+ @root + all_but_last_seg
129
+ else
130
+ @root
131
+ end
132
+ end
133
+
134
+ def local_iname
135
+ unless self.is_inumber?
136
+ if @subsegments.last[0] == ?* # strip off leading * on local i-name
137
+ @subsegments.last[1..-1]
138
+ else
139
+ @subsegments.last
140
+ end
141
+ end
142
+ end
143
+
144
+ def local_inumber
145
+ @subsegments.last[0..-1] if self.is_inumber?
146
+ end
147
+
148
+ def fully_qualified
149
+ @root + @subsegments.to_s
150
+ end
151
+
152
+ def normalized
153
+ if @root == '@' or @root == '='
154
+ @root + @subsegments.to_s[1..-1]
155
+ else
156
+ @root + @subsegments.to_s
157
+ end
158
+ end
159
+
160
+ end
161
+
162
+ class XRIRootMissing < RuntimeError; end
163
+ end