vcard 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +15 -5
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +17 -0
  5. data/Rakefile +4 -52
  6. data/{LICENSE → VPIM-LICENSE.txt} +2 -2
  7. data/lib/vcard.rb +304 -28
  8. data/lib/vcard/attachment.rb +10 -12
  9. data/lib/vcard/bnf.rb +66 -0
  10. data/lib/vcard/dirinfo.rb +24 -26
  11. data/lib/vcard/enumerator.rb +5 -7
  12. data/lib/vcard/errors.rb +23 -0
  13. data/lib/vcard/field.rb +56 -58
  14. data/lib/vcard/vcard.rb +210 -240
  15. data/lib/vcard/version.rb +3 -0
  16. data/test/field_test.rb +55 -55
  17. data/test/fixtures/bday_decode.vcard +3 -0
  18. data/test/fixtures/bday_decode_2.vcard +6 -0
  19. data/test/fixtures/empty_tel.vcard +3 -0
  20. data/test/fixtures/ex1.vcard +7 -0
  21. data/test/fixtures/ex2.vcard +9 -0
  22. data/test/fixtures/ex3.vcard +30 -0
  23. data/test/fixtures/ex_21.vcard +16 -0
  24. data/test/fixtures/ex_21_case0.vcard +15 -0
  25. data/test/fixtures/ex_apple1.vcard +13 -0
  26. data/test/fixtures/ex_attach.vcard +16 -0
  27. data/test/fixtures/ex_bdays.vcard +8 -0
  28. data/test/fixtures/ex_encode_1.vcard +10 -0
  29. data/test/fixtures/ex_ical_1.vcal +47 -0
  30. data/test/fixtures/gmail.vcard +27 -0
  31. data/test/fixtures/highrise.vcard +41 -0
  32. data/test/fixtures/multiple_occurences_of_type.vcard +17 -0
  33. data/test/fixtures/nickname0.vcard +2 -0
  34. data/test/fixtures/nickname1.vcard +3 -0
  35. data/test/fixtures/nickname2.vcard +3 -0
  36. data/test/fixtures/nickname3.vcard +3 -0
  37. data/test/fixtures/nickname4.vcard +4 -0
  38. data/test/fixtures/nickname5.vcard +5 -0
  39. data/test/fixtures/slash_in_field_name.vcard +3 -0
  40. data/test/fixtures/tst1.vcard +9 -0
  41. data/test/fixtures/url_decode.vcard +4 -0
  42. data/test/test_helper.rb +34 -6
  43. data/test/vcard_test.rb +87 -577
  44. data/vcard.gemspec +19 -0
  45. metadata +88 -43
  46. data/.document +0 -5
  47. data/README.rdoc +0 -7
  48. data/VERSION +0 -1
  49. data/lib/vcard/rfc2425.rb +0 -367
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vcard/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "vcard"
8
+ gem.version = Vcard::VERSION
9
+ gem.authors = ["Kuba Kuźma"]
10
+ gem.email = ["kuba@jah.pl"]
11
+ gem.description = %q{Vcard extracted from Vpim}
12
+ gem.summary = %q{Vcard extracted from Vpim}
13
+ gem.homepage = "http://github.com/qoobaa/vcard"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata CHANGED
@@ -1,73 +1,118 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: vcard
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
- - "Jakub Ku\xC5\xBAma"
7
+ authors:
8
+ - Kuba Kuźma
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2009-10-20 00:00:00 +02:00
13
- default_executable:
12
+ date: 2012-11-26 00:00:00.000000000 Z
14
13
  dependencies: []
15
-
16
- description:
17
- email: qoobaa@gmail.com
14
+ description: Vcard extracted from Vpim
15
+ email:
16
+ - kuba@jah.pl
18
17
  executables: []
19
-
20
18
  extensions: []
21
-
22
- extra_rdoc_files:
23
- - LICENSE
24
- - README.rdoc
25
- files:
26
- - .document
19
+ extra_rdoc_files: []
20
+ files:
27
21
  - .gitignore
28
- - LICENSE
29
- - README.rdoc
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
30
25
  - Rakefile
31
- - VERSION
26
+ - VPIM-LICENSE.txt
32
27
  - lib/vcard.rb
33
28
  - lib/vcard/attachment.rb
29
+ - lib/vcard/bnf.rb
34
30
  - lib/vcard/dirinfo.rb
35
31
  - lib/vcard/enumerator.rb
32
+ - lib/vcard/errors.rb
36
33
  - lib/vcard/field.rb
37
- - lib/vcard/rfc2425.rb
38
34
  - lib/vcard/vcard.rb
35
+ - lib/vcard/version.rb
39
36
  - test/field_test.rb
37
+ - test/fixtures/bday_decode.vcard
38
+ - test/fixtures/bday_decode_2.vcard
39
+ - test/fixtures/empty_tel.vcard
40
+ - test/fixtures/ex1.vcard
41
+ - test/fixtures/ex2.vcard
42
+ - test/fixtures/ex3.vcard
43
+ - test/fixtures/ex_21.vcard
44
+ - test/fixtures/ex_21_case0.vcard
45
+ - test/fixtures/ex_apple1.vcard
46
+ - test/fixtures/ex_attach.vcard
47
+ - test/fixtures/ex_bdays.vcard
48
+ - test/fixtures/ex_encode_1.vcard
49
+ - test/fixtures/ex_ical_1.vcal
50
+ - test/fixtures/gmail.vcard
51
+ - test/fixtures/highrise.vcard
52
+ - test/fixtures/multiple_occurences_of_type.vcard
53
+ - test/fixtures/nickname0.vcard
54
+ - test/fixtures/nickname1.vcard
55
+ - test/fixtures/nickname2.vcard
56
+ - test/fixtures/nickname3.vcard
57
+ - test/fixtures/nickname4.vcard
58
+ - test/fixtures/nickname5.vcard
59
+ - test/fixtures/slash_in_field_name.vcard
60
+ - test/fixtures/tst1.vcard
61
+ - test/fixtures/url_decode.vcard
40
62
  - test/test_helper.rb
41
63
  - test/vcard_test.rb
42
- has_rdoc: true
64
+ - vcard.gemspec
43
65
  homepage: http://github.com/qoobaa/vcard
44
66
  licenses: []
45
-
46
67
  post_install_message:
47
- rdoc_options:
48
- - --charset=UTF-8
49
- require_paths:
68
+ rdoc_options: []
69
+ require_paths:
50
70
  - lib
51
- required_ruby_version: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: "0"
56
- version:
57
- required_rubygems_version: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: "0"
62
- version:
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
63
83
  requirements: []
64
-
65
84
  rubyforge_project:
66
- rubygems_version: 1.3.5
85
+ rubygems_version: 1.8.24
67
86
  signing_key:
68
87
  specification_version: 3
69
- summary: Vcard support extracted from Vpim (Ruby 1.9.1 compatible)
70
- test_files:
88
+ summary: Vcard extracted from Vpim
89
+ test_files:
71
90
  - test/field_test.rb
91
+ - test/fixtures/bday_decode.vcard
92
+ - test/fixtures/bday_decode_2.vcard
93
+ - test/fixtures/empty_tel.vcard
94
+ - test/fixtures/ex1.vcard
95
+ - test/fixtures/ex2.vcard
96
+ - test/fixtures/ex3.vcard
97
+ - test/fixtures/ex_21.vcard
98
+ - test/fixtures/ex_21_case0.vcard
99
+ - test/fixtures/ex_apple1.vcard
100
+ - test/fixtures/ex_attach.vcard
101
+ - test/fixtures/ex_bdays.vcard
102
+ - test/fixtures/ex_encode_1.vcard
103
+ - test/fixtures/ex_ical_1.vcal
104
+ - test/fixtures/gmail.vcard
105
+ - test/fixtures/highrise.vcard
106
+ - test/fixtures/multiple_occurences_of_type.vcard
107
+ - test/fixtures/nickname0.vcard
108
+ - test/fixtures/nickname1.vcard
109
+ - test/fixtures/nickname2.vcard
110
+ - test/fixtures/nickname3.vcard
111
+ - test/fixtures/nickname4.vcard
112
+ - test/fixtures/nickname5.vcard
113
+ - test/fixtures/slash_in_field_name.vcard
114
+ - test/fixtures/tst1.vcard
115
+ - test/fixtures/url_decode.vcard
72
116
  - test/test_helper.rb
73
117
  - test/vcard_test.rb
118
+ has_rdoc:
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
@@ -1,7 +0,0 @@
1
- = vcard
2
-
3
- Description goes here.
4
-
5
- == Copyright
6
-
7
- Copyright (c) 2009 Jakub Kuźma. See LICENSE for details.
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.1
@@ -1,367 +0,0 @@
1
- =begin
2
- Copyright (C) 2008 Sam Roberts
3
-
4
- This library is free software; you can redistribute it and/or modify it
5
- under the same terms as the ruby language itself, see the file COPYING for
6
- details.
7
- =end
8
-
9
- require "date"
10
-
11
- module Vpim
12
- # Contains regular expression strings for the EBNF of RFC 2425.
13
- module Bnf #:nodoc:
14
-
15
- # 1*(ALPHA / DIGIT / "-")
16
- # Note: I think I can add A-Z here, and get rid of the "i" matches elsewhere.
17
- # Note: added '_' to allowed because its produced by Notes (X-LOTUS-CHILD_UID:)
18
- # Note: added '/' to allowed because its produced by KAddressBook (X-messaging/xmpp-All:)
19
- # Note: added ' ' to allowed because its produced by highrisehq.com (X-GOOGLE TALK:)
20
- NAME = '[-a-z0-9_/][-a-z0-9_/ ]*'
21
-
22
- # <"> <Any character except CTLs, DQUOTE> <">
23
- QSTR = '"([^"]*)"'
24
-
25
- # *<Any character except CTLs, DQUOTE, ";", ":", ",">
26
- PTEXT = '([^";:,]+)'
27
-
28
- # param-value = ptext / quoted-string
29
- PVALUE = "(?:#{QSTR}|#{PTEXT})"
30
-
31
- # param = name "=" param-value *("," param-value)
32
- # Note: v2.1 allows a type or encoding param-value to appear without the type=
33
- # or the encoding=. This is hideous, but we try and support it, if there
34
- # is no "=", then $2 will be "", and we will treat it as a v2.1 param.
35
- PARAM = ";(#{NAME})(=?)((?:#{PVALUE})?(?:,#{PVALUE})*)"
36
-
37
- # V3.0: contentline = [group "."] name *(";" param) ":" value
38
- # V2.1: contentline = *( group "." ) name *(";" param) ":" value
39
- #
40
- # We accept the V2.1 syntax for backwards compatibility.
41
- #LINE = "((?:#{NAME}\\.)*)?(#{NAME})([^:]*)\:(.*)"
42
- LINE = "^((?:#{NAME}\\.)*)?(#{NAME})((?:#{PARAM})*):(.*)$"
43
-
44
- # date = date-fullyear ["-"] date-month ["-"] date-mday
45
- # date-fullyear = 4 DIGIT
46
- # date-month = 2 DIGIT
47
- # date-mday = 2 DIGIT
48
- DATE = '(\d\d\d\d)-?(\d\d)-?(\d\d)'
49
-
50
- # time = time-hour [":"] time-minute [":"] time-second [time-secfrac] [time-zone]
51
- # time-hour = 2 DIGIT
52
- # time-minute = 2 DIGIT
53
- # time-second = 2 DIGIT
54
- # time-secfrac = "," 1*DIGIT
55
- # time-zone = "Z" / time-numzone
56
- # time-numzone = sign time-hour [":"] time-minute
57
- TIME = '(\d\d):?(\d\d):?(\d\d)(\.\d+)?(Z|[-+]\d\d:?\d\d)?'
58
-
59
- # integer = (["+"] / "-") 1*DIGIT
60
- INTEGER = '[-+]?\d+'
61
-
62
- # QSAFE-CHAR = WSP / %x21 / %x23-7E / NON-US-ASCII
63
- # ; Any character except CTLs and DQUOTE
64
- QSAFECHAR = '[ \t\x21\x23-\x7e\x80-\xff]'
65
-
66
- # SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-US-ASCII
67
- # ; Any character except CTLs, DQUOTE, ";", ":", ","
68
- SAFECHAR = '[ \t\x21\x23-\x2b\x2d-\x39\x3c-\x7e\x80-\xff]'
69
- end
70
- end
71
-
72
- module Vpim
73
- # Split on \r\n or \n to get the lines, unfold continued lines (they
74
- # start with ' ' or \t), and return the array of unfolded lines.
75
- #
76
- # This also supports the (invalid) encoding convention of allowing empty
77
- # lines to be inserted for readability - it does this by dropping zero-length
78
- # lines.
79
- def Vpim.unfold(card) #:nodoc:
80
- unfolded = []
81
-
82
- card.lines do |line|
83
- line.chomp!
84
- # If it's a continuation line, add it to the last.
85
- # If it's an empty line, drop it from the input.
86
- if( line =~ /^[ \t]/ )
87
- unfolded[-1] << line[1, line.size-1]
88
- elsif( line =~ /^$/ )
89
- else
90
- unfolded << line
91
- end
92
- end
93
-
94
- unfolded
95
- end
96
-
97
- # Convert a +sep+-seperated list of values into an array of values.
98
- def Vpim.decode_list(value, sep = ',') # :nodoc:
99
- list = []
100
-
101
- value.split(sep).each do |item|
102
- item.chomp!(sep)
103
- list << yield(item)
104
- end
105
- list
106
- end
107
-
108
- # Convert a RFC 2425 date into an array of [year, month, day].
109
- def Vpim.decode_date(v) # :nodoc:
110
- unless v =~ %r{^\s*#{Bnf::DATE}\s*$}
111
- raise Vpim::InvalidEncodingError, "date not valid (#{v})"
112
- end
113
- [$1.to_i, $2.to_i, $3.to_i]
114
- end
115
-
116
- # Convert a RFC 2425 date into a Date object.
117
- def self.decode_date_to_date(v)
118
- Date.new(*decode_date(v))
119
- end
120
-
121
- # Note in the following the RFC2425 allows yyyy-mm-ddThh:mm:ss, but RFC2445
122
- # does not. I choose to encode to the subset that is valid for both.
123
-
124
- # Encode a Date object as "yyyymmdd".
125
- def Vpim.encode_date(d) # :nodoc:
126
- "%0.4d%0.2d%0.2d" % [ d.year, d.mon, d.day ]
127
- end
128
-
129
- # Encode a Date object as "yyyymmdd".
130
- def Vpim.encode_time(d) # :nodoc:
131
- "%0.4d%0.2d%0.2d" % [ d.year, d.mon, d.day ]
132
- end
133
-
134
- # Encode a Time or DateTime object as "yyyymmddThhmmss"
135
- def Vpim.encode_date_time(d) # :nodoc:
136
- "%0.4d%0.2d%0.2dT%0.2d%0.2d%0.2d" % [ d.year, d.mon, d.day, d.hour, d.min, d.sec ]
137
- end
138
-
139
- # Convert a RFC 2425 time into an array of [hour,min,sec,secfrac,timezone]
140
- def Vpim.decode_time(v) # :nodoc:
141
- unless match = %r{^\s*#{Bnf::TIME}\s*$}.match(v)
142
- raise Vpim::InvalidEncodingError, "time '#{v}' not valid"
143
- end
144
- hour, min, sec, secfrac, tz = match.to_a[1..5]
145
-
146
- [hour.to_i, min.to_i, sec.to_i, secfrac ? secfrac.to_f : 0, tz]
147
- end
148
-
149
- def self.array_datetime_to_time(dtarray) #:nodoc:
150
- # We get [ year, month, day, hour, min, sec, usec, tz ]
151
- begin
152
- tz = (dtarray.pop == "Z") ? :gm : :local
153
- Time.send(tz, *dtarray)
154
- rescue ArgumentError => e
155
- raise Vpim::InvalidEncodingError, "#{tz} #{e} (#{dtarray.join(', ')})"
156
- end
157
- end
158
-
159
- # Convert a RFC 2425 time into an array of Time objects.
160
- def Vpim.decode_time_to_time(v) # :nodoc:
161
- array_datetime_to_time(decode_date_time(v))
162
- end
163
-
164
- # Convert a RFC 2425 date-time into an array of [year,mon,day,hour,min,sec,secfrac,timezone]
165
- def Vpim.decode_date_time(v) # :nodoc:
166
- unless match = %r{^\s*#{Bnf::DATE}T#{Bnf::TIME}\s*$}.match(v)
167
- raise Vpim::InvalidEncodingError, "date-time '#{v}' not valid"
168
- end
169
- year, month, day, hour, min, sec, secfrac, tz = match.to_a[1..8]
170
-
171
- [
172
- # date
173
- year.to_i, month.to_i, day.to_i,
174
- # time
175
- hour.to_i, min.to_i, sec.to_i, secfrac ? secfrac.to_f : 0, tz
176
- ]
177
- end
178
-
179
- def Vpim.decode_date_time_to_datetime(v) #:nodoc:
180
- year, month, day, hour, min, sec, secfrac, tz = Vpim.decode_date_time(v)
181
- # TODO - DateTime understands timezones, so we could decode tz and use it.
182
- DateTime.civil(year, month, day, hour, min, sec, 0)
183
- end
184
-
185
- # Vpim.decode_boolean
186
- #
187
- # float
188
- #
189
- # float_list
190
- =begin
191
- =end
192
-
193
- # Convert an RFC2425 INTEGER value into an Integer
194
- def Vpim.decode_integer(v) # :nodoc:
195
- unless match = %r{\s*#{Bnf::INTEGER}\s*}.match(v)
196
- raise Vpim::InvalidEncodingError, "integer not valid (#{v})"
197
- end
198
- v.to_i
199
- end
200
-
201
- #
202
- # integer_list
203
-
204
- # Convert a RFC2425 date-list into an array of dates.
205
- def Vpim.decode_date_list(v) # :nodoc:
206
- Vpim.decode_list(v) do |date|
207
- date.strip!
208
- if date.length > 0
209
- Vpim.decode_date(date)
210
- end
211
- end.compact
212
- end
213
-
214
- # Convert a RFC 2425 time-list into an array of times.
215
- def Vpim.decode_time_list(v) # :nodoc:
216
- Vpim.decode_list(v) do |time|
217
- time.strip!
218
- if time.length > 0
219
- Vpim.decode_time(time)
220
- end
221
- end.compact
222
- end
223
-
224
- # Convert a RFC 2425 date-time-list into an array of date-times.
225
- def Vpim.decode_date_time_list(v) # :nodoc:
226
- Vpim.decode_list(v) do |datetime|
227
- datetime.strip!
228
- if datetime.length > 0
229
- Vpim.decode_date_time(datetime)
230
- end
231
- end.compact
232
- end
233
-
234
- # Convert RFC 2425 text into a String.
235
- # \\ -> \
236
- # \n -> NL
237
- # \N -> NL
238
- # \, -> ,
239
- # \; -> ;
240
- #
241
- # I've seen double-quote escaped by iCal.app. Hmm. Ok, if you aren't supposed
242
- # to escape anything but the above, everything else is ambiguous, so I'll
243
- # just support it.
244
- def Vpim.decode_text(v) # :nodoc:
245
- # FIXME - I think this should trim leading and trailing space
246
- v.gsub(/\\(.)/) do
247
- case $1
248
- when 'n', 'N'
249
- "\n"
250
- else
251
- $1
252
- end
253
- end
254
- end
255
-
256
- def Vpim.encode_text(v) #:nodoc:
257
- v.to_str.gsub(/([\\,;\n])/) { $1 == "\n" ? "\\n" : "\\"+$1 }
258
- end
259
-
260
- # v is an Array of String, or just a single String
261
- def Vpim.encode_text_list(v, sep = ",") #:nodoc:
262
- begin
263
- v.to_ary.map{ |t| Vpim.encode_text(t) }.join(sep)
264
- rescue
265
- Vpim.encode_text(v)
266
- end
267
- end
268
-
269
- # Convert a +sep+-seperated list of TEXT values into an array of values.
270
- def Vpim.decode_text_list(value, sep = ',') # :nodoc:
271
- # Need to do in two stages, as best I can find.
272
- list = value.scan(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)#{sep}/).map do |v|
273
- Vpim.decode_text(v.first)
274
- end
275
- if value.match(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)$/)
276
- list << $1
277
- end
278
- list
279
- end
280
-
281
- # param-value = paramtext / quoted-string
282
- # paramtext = *SAFE-CHAR
283
- # quoted-string = DQUOTE *QSAFE-CHAR DQUOTE
284
- def Vpim.encode_paramtext(value)
285
- case value
286
- when %r{\A#{Bnf::SAFECHAR}*\z}
287
- value
288
- else
289
- raise Vpim::Unencodable, "paramtext #{value.inspect}"
290
- end
291
- end
292
-
293
- def Vpim.encode_paramvalue(value)
294
- case value
295
- when %r{\A#{Bnf::SAFECHAR}*\z}
296
- value
297
- when %r{\A#{Bnf::QSAFECHAR}*\z}
298
- '"' + value + '"'
299
- else
300
- raise Vpim::Unencodable, "param-value #{value.inspect}"
301
- end
302
- end
303
-
304
-
305
- # Unfold the lines in +card+, then return an array of one Field object per
306
- # line.
307
- def Vpim.decode(card) #:nodoc:
308
- content = Vpim.unfold(card).collect { |line| DirectoryInfo::Field.decode(line) }
309
- end
310
-
311
-
312
- # Expand an array of fields into its syntactic entities. Each entity is a sequence
313
- # of fields where the sequences is delimited by a BEGIN/END field. Since
314
- # BEGIN/END delimited entities can be nested, we build a tree. Each entry in
315
- # the array is either a Field or an array of entries (where each entry is
316
- # either a Field, or an array of entries...).
317
- def Vpim.expand(src) #:nodoc:
318
- # output array to expand the src to
319
- dst = []
320
- # stack used to track our nesting level, as we see begin/end we start a
321
- # new/finish the current entity, and push/pop that entity from the stack
322
- current = [ dst ]
323
-
324
- for f in src
325
- if f.name? 'BEGIN'
326
- e = [ f ]
327
-
328
- current.last.push(e)
329
- current.push(e)
330
-
331
- elsif f.name? 'END'
332
- current.last.push(f)
333
-
334
- unless current.last.first.value? current.last.last.value
335
- raise "BEGIN/END mismatch (#{current.last.first.value} != #{current.last.last.value})"
336
- end
337
-
338
- current.pop
339
-
340
- else
341
- current.last.push(f)
342
- end
343
- end
344
-
345
- dst
346
- end
347
-
348
- # Split an array into an array of all the fields at the outer level, and
349
- # an array of all the inner arrays of fields. Return the array [outer,
350
- # inner].
351
- def Vpim.outer_inner(fields) #:nodoc:
352
- # TODO - use Enumerable#partition
353
- # seperate into the outer-level fields, and the arrays of component
354
- # fields
355
- outer = []
356
- inner = []
357
- fields.each do |line|
358
- case line
359
- when Array; inner << line
360
- else; outer << line
361
- end
362
- end
363
- return outer, inner
364
- end
365
-
366
- end
367
-