ios_parser 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3fa46ea53424609c1cc2bd44edfcebd86cedec95
4
- data.tar.gz: 632d1c06c880ca9d7ba17285c825ae4885fc4f08
3
+ metadata.gz: 181d9adcdc7d222fe6ef05a91624aa1277274371
4
+ data.tar.gz: f9a1920092018240b8e67f972e453f5e104b8bd9
5
5
  SHA512:
6
- metadata.gz: 052fe0ba301f4c002237b35134f4a97d7bf0ac175fd3d7217ee6634e5bc685939a84e0ec7eb44ffa05950c95c27d687010e3998162814db1f01c7d108951ff81
7
- data.tar.gz: c96e847e9af333cfa441588c57c1711c60323ae7d3cac08177a684fa26aa6d0fcd8da816926ffc815d64f50513f2d99c84676cb156eb11698a5cf7a7675c30db
6
+ metadata.gz: 4d4cf9efd75f3c563ffa92034dccbc265a5fd70778afb2f970df71641b1a94edc371befcd99e6d7bf989817b8fd1744a4d60b7340415ac7ec4fa4d2e8afd6586
7
+ data.tar.gz: 5fa9ebc0c746698ce75afd045d272826e9e48d54c86d4c20ab244e790b10f9255a36795a85331b1675d756fde9ac6b5d221bf0506391cb73a032e246e6ab41f7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.5.0 (2017-04-26)
2
+
3
+ Enhancements:
4
+
5
+ - handle EOS-style banners
6
+
7
+
1
8
  ## 0.4.0 (2016-06-08)
2
9
 
3
10
  Enhancements:
data/Guardfile CHANGED
@@ -3,7 +3,7 @@ guard :rake, task: 'compile' do
3
3
  end
4
4
 
5
5
  guard :rspec, cmd: 'bundle exec rspec --color --fail-fast' do
6
- watch(%r{^spec/.+_spec\.rb$}) { |m| m }
6
+ watch(%r{^spec/.+_spec\.rb$})
7
7
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
8
  watch('spec/spec_helper.rb') { 'spec' }
9
9
  watch(%r{^ext/(.+)\.[ch]$}) { 'spec' }
@@ -81,7 +81,7 @@ int is_certificate(LexInfo *lex) {
81
81
  return 1;
82
82
  }
83
83
 
84
- int is_banner(LexInfo *lex) {
84
+ int is_banner_begin(LexInfo *lex) {
85
85
  VALUE banner_ary, banner;
86
86
  int token_count = RARRAY_LEN(lex->tokens);
87
87
  int banner_pos = token_count - 2;
@@ -178,9 +178,20 @@ static VALUE initialize(VALUE self, VALUE input_text) {
178
178
 
179
179
  static void process_root(LexInfo * lex);
180
180
  static void process_start_of_line(LexInfo * lex);
181
+ static void start_banner(LexInfo * lex);
181
182
 
182
183
  static void process_newline(LexInfo *lex) {
183
184
  delimit(lex);
185
+
186
+ if (is_banner_begin(lex)) {
187
+ lex->token_state = LEX_STATE_BANNER;
188
+ start_banner(lex);
189
+ lex->pos = lex->pos + 1;
190
+ lex->token_start = lex->pos;
191
+ lex->token_length = 0;
192
+ return;
193
+ }
194
+
184
195
  lex->token_start = lex->pos;
185
196
  ADD_TOKEN(lex, ID2SYM(rb_intern("EOL")));
186
197
  lex->token_state = LEX_STATE_INDENT;
@@ -203,7 +214,7 @@ static void process_comment(LexInfo *lex) {
203
214
 
204
215
  static void process_quoted_string(LexInfo *lex) {
205
216
  char c = CURRENT_CHAR(lex);
206
-
217
+
207
218
  lex->token_length++;
208
219
  if (!lex->string_terminator) {
209
220
  lex->string_terminator = c;
@@ -301,24 +312,40 @@ static void start_certificate(LexInfo *lex) {
301
312
  process_certificate(lex);
302
313
  }
303
314
 
304
- static void process_banner(LexInfo *lex) {
305
- char c = CURRENT_CHAR(lex);
306
-
307
- if (c == lex->banner_delimiter &&
315
+ int is_banner_end_char(LexInfo *lex) {
316
+ return CURRENT_CHAR(lex) == lex->banner_delimiter &&
308
317
  (0 < lex->pos && '\n' == lex->text[lex->pos - 1] ||
309
- '\n' == lex->text[lex->pos + 1])) {
318
+ '\n' == lex->text[lex->pos + 1]);
319
+ }
320
+
321
+ int is_banner_end_string(LexInfo *lex) {
322
+ /* onlys accept the banner-ending string "EOF" */
323
+ return (CURRENT_CHAR(lex) == 'F' &&
324
+ lex->text[lex->pos - 1] == 'O' &&
325
+ lex->text[lex->pos - 2] == 'E' &&
326
+ lex->text[lex->pos - 3] == '\n');
327
+ }
328
+
329
+ static void process_banner(LexInfo *lex) {
330
+ if (lex->banner_delimiter && is_banner_end_char(lex)) {
310
331
  lex->token_length++;
311
332
  delimit(lex);
312
333
  lex->token_start = lex->pos;
313
334
  ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_END")));
314
335
  if (lex->text[lex->pos + 1] == 'C') { lex->pos++; }
336
+ } else if (!lex->banner_delimiter && is_banner_end_string(lex)) {
337
+ lex->token_length -= 1;
338
+ delimit(lex);
339
+ lex->token_start = lex->pos;
340
+ ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_END")));
315
341
  } else {
316
342
  lex->token_length++;
317
343
  }
318
344
  }
319
345
 
320
346
  static void start_banner(LexInfo *lex) {
321
- lex->banner_delimiter = CURRENT_CHAR(lex);
347
+ char c = CURRENT_CHAR(lex);
348
+ lex->banner_delimiter = (c == '\n') ? 0 : c;
322
349
  ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_BEGIN")));
323
350
  if ('\n' == lex->text[lex->pos + 2]) lex->pos++;
324
351
  }
@@ -359,7 +386,7 @@ static void process_root(LexInfo *lex) {
359
386
  if (IS_SPACE(c)) {
360
387
  delimit(lex);
361
388
 
362
- } else if (is_banner(lex)) {
389
+ } else if (is_banner_begin(lex)) {
363
390
  lex->token_state = LEX_STATE_BANNER;
364
391
  start_banner(lex);
365
392
  lex->pos = lex->pos + 2;
@@ -433,7 +460,7 @@ static VALUE call(VALUE self, VALUE input_text) {
433
460
  case (LEX_STATE_QUOTED_STRING):
434
461
  process_quoted_string(lex);
435
462
  break;
436
-
463
+
437
464
  case (LEX_STATE_WORD):
438
465
  process_word(lex);
439
466
  break;
@@ -81,7 +81,7 @@ module IOSParser
81
81
  self.state = :banner
82
82
  tokens << make_token(:BANNER_BEGIN)
83
83
  @token_start = @this_char + 2
84
- @banner_delimiter = char
84
+ @banner_delimiter = char == "\n" ? 'EOF' : char
85
85
  end
86
86
 
87
87
  def banner_begin?
@@ -89,21 +89,38 @@ module IOSParser
89
89
  end
90
90
 
91
91
  def banner
92
- if char == @banner_delimiter && (@text[@this_char - 1] == "\n" ||
93
- @text[@this_char + 1] == "\n")
94
- banner_end
92
+ if banner_end_char?
93
+ banner_end_char
94
+ elsif banner_end_string?
95
+ banner_end_string
95
96
  else
96
97
  token << char
97
98
  end
98
99
  end
99
100
 
100
- def banner_end
101
+ def banner_end_string
102
+ self.state = :root
103
+ token.chomp!(@banner_delimiter[0..-2])
104
+ tokens << make_token(token) << make_token(:BANNER_END)
105
+ self.token = ''
106
+ end
107
+
108
+ def banner_end_string?
109
+ @banner_delimiter.size > 1 && (token + char).end_with?(@banner_delimiter)
110
+ end
111
+
112
+ def banner_end_char
101
113
  self.state = :root
102
114
  banner_end_clean_token
103
115
  tokens << make_token(token) << make_token(:BANNER_END)
104
116
  self.token = ''
105
117
  end
106
118
 
119
+ def banner_end_char?
120
+ char == @banner_delimiter && (@text[@this_char - 1] == "\n" ||
121
+ @text[@this_char + 1] == "\n")
122
+ end
123
+
107
124
  def banner_end_clean_token
108
125
  token.slice!(0) if token[0] == 'C'
109
126
  token.slice!(0) if ["\n", ' '].include?(token[0])
@@ -157,10 +174,9 @@ module IOSParser
157
174
 
158
175
  def integer
159
176
  self.state = :integer
160
- case
161
- when dot? then decimal
162
- when digit? then token << char
163
- when word? then word
177
+ if dot? then decimal
178
+ elsif digit? then token << char
179
+ elsif word? then word
164
180
  else root
165
181
  end
166
182
  end
@@ -180,10 +196,9 @@ module IOSParser
180
196
 
181
197
  def decimal
182
198
  self.state = :decimal
183
- case
184
- when digit? then token << char
185
- when dot? then token << char
186
- when word? then word
199
+ if digit? then token << char
200
+ elsif dot? then token << char
201
+ elsif word? then word
187
202
  else root
188
203
  end
189
204
  end
@@ -247,6 +262,7 @@ module IOSParser
247
262
 
248
263
  def newline
249
264
  delimit
265
+ return banner_begin if banner_begin?
250
266
  self.state = :line_start
251
267
  self.indent = 0
252
268
  tokens << make_token(:EOL)
@@ -267,6 +283,13 @@ module IOSParser
267
283
 
268
284
  def delimit
269
285
  return if token.empty?
286
+
287
+ unless respond_to?(:"#{state}_token")
288
+ pos = @token_start || @this_char
289
+ raise LexError, "Unterminated #{state} starting at #{pos}: "\
290
+ "#{@text[pos..pos + 20].inspect}"
291
+ end
292
+
270
293
  tokens << send(:"#{state}_token")
271
294
  self.state = :root
272
295
  self.token = ''
@@ -1,7 +1,7 @@
1
1
  module IOSParser
2
2
  class << self
3
3
  def version
4
- '0.4.1'
4
+ '0.5.0'
5
5
  end
6
6
  end
7
7
  end
data/lib/ios_parser.rb CHANGED
@@ -31,7 +31,7 @@ module IOSParser
31
31
  end
32
32
 
33
33
  def json_to_ios(text)
34
- hash_to_ios JSON.load(text)
34
+ hash_to_ios JSON.parse(text)
35
35
  end
36
36
  end
37
37
  end
@@ -63,9 +63,9 @@ END
63
63
  end
64
64
 
65
65
  describe Array do
66
- let(:matcher) {
66
+ let(:matcher) do
67
67
  { contains: ['dscp'.freeze, 'cs1'.freeze].freeze }.freeze
68
- }
68
+ end
69
69
  it { should == expectation }
70
70
  end
71
71
  end # context 'matcher: contains' do
@@ -27,10 +27,8 @@ END
27
27
  'policed-dscp-transmit'],
28
28
  commands: [{ args: %w(set dscp cs1),
29
29
  commands: [], pos: 114 }],
30
- pos: 50
31
- }],
32
- pos: 24
33
- },
30
+ pos: 50 }],
31
+ pos: 24 },
34
32
 
35
33
  { args: %w(class other_service),
36
34
  commands: [{ args: ['police', 600_000_000, 1_000_000,
@@ -40,12 +38,9 @@ END
40
38
  commands: [], pos: 214 },
41
39
  { args: ['command_with_no_args'],
42
40
  commands: [], pos: 230 }],
43
- pos: 150
44
- }],
45
- pos: 128
46
- }],
47
- pos: 0
48
- }]
41
+ pos: 150 }],
42
+ pos: 128 }],
43
+ pos: 0 }]
49
44
  }
50
45
  end
51
46
 
@@ -98,8 +93,7 @@ END
98
93
  'policed-dscp-transmit'],
99
94
  commands: [{ args: %w(set dscp cs1),
100
95
  commands: [], pos: 114 }],
101
- pos: 50
102
- }]
96
+ pos: 50 }]
103
97
  end
104
98
 
105
99
  context 'integer query' do
@@ -37,8 +37,7 @@ END
37
37
  'police', 600_000_000, 1_000_000, 'exceed-action',
38
38
  'policed-dscp-transmit', :EOL,
39
39
  :INDENT,
40
- 'set', 'dscp', 'cs2', :EOL, :DEDENT, :DEDENT, :DEDENT
41
- ]
40
+ 'set', 'dscp', 'cs2', :EOL, :DEDENT, :DEDENT, :DEDENT]
42
41
  end
43
42
 
44
43
  subject { klass.new.call(input).map(&:last) }
@@ -71,8 +70,7 @@ END
71
70
  :DEDENT, :DEDENT, :DEDENT,
72
71
  'router', 'ospf', 12_345, :EOL,
73
72
  :INDENT, 'nsr', :EOL,
74
- :DEDENT
75
- ]
73
+ :DEDENT]
76
74
  end
77
75
 
78
76
  it 'pure' do
@@ -125,6 +123,18 @@ END
125
123
  it { expect(subject_pure.map(&:last)).to eq output }
126
124
  end
127
125
 
126
+ context 'complex eos banner' do
127
+ let(:input) { "banner motd\n'''\nEOF\n" }
128
+
129
+ let(:output) do
130
+ content = input.lines[1..-2].join
131
+ ['banner', 'motd', :BANNER_BEGIN, content, :BANNER_END, :EOL]
132
+ end
133
+
134
+ it { expect(subject.map(&:last)).to eq output }
135
+ it { expect(subject_pure.map(&:last)).to eq output }
136
+ end
137
+
128
138
  context 'decimal number' do
129
139
  let(:input) { 'boson levels at 93.2' }
130
140
  let(:output) { ['boson', 'levels', 'at', 93.2] }
@@ -164,8 +174,7 @@ END
164
174
  'DDDDDDDD DDDDDDDD DDDDDDDD AAAA'],
165
175
  [323, :CERTIFICATE_END],
166
176
  [323, :EOL],
167
- [323, :DEDENT]
168
- ]
177
+ [323, :DEDENT]]
169
178
  end
170
179
 
171
180
  subject { klass.new.call(input) }
@@ -26,10 +26,8 @@ END
26
26
  'policed-dscp-transmit'],
27
27
  commands: [{ args: %w(set dscp cs1),
28
28
  commands: [], pos: 114 }],
29
- pos: 50
30
- }],
31
- pos: 24
32
- },
29
+ pos: 50 }],
30
+ pos: 24 },
33
31
 
34
32
  { args: %w(class other_service),
35
33
  commands: [{ args: ['police', 600_000_000, 1_000_000,
@@ -39,12 +37,9 @@ END
39
37
  commands: [], pos: 214 },
40
38
  { args: ['command_with_no_args'],
41
39
  commands: [], pos: 230 }],
42
- pos: 150
43
- }],
44
- pos: 128
45
- }],
46
- pos: 0
47
- }]
40
+ pos: 150 }],
41
+ pos: 128 }],
42
+ pos: 0 }]
48
43
  }
49
44
  end
50
45
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ios_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Miller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-02 00:00:00.000000000 Z
11
+ date: 2017-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
110
  version: '0'
111
111
  requirements: []
112
112
  rubyforge_project:
113
- rubygems_version: 2.5.1
113
+ rubygems_version: 2.5.2
114
114
  signing_key:
115
115
  specification_version: 4
116
116
  summary: convert network switch and router config files to structured data
@@ -120,4 +120,3 @@ test_files:
120
120
  - spec/lib/ios_parser/lexer_spec.rb
121
121
  - spec/lib/ios_parser_spec.rb
122
122
  - spec/spec_helper.rb
123
- has_rdoc: