sdl4r 0.9.1 → 0.9.2

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/sdl4r/sdl.rb CHANGED
@@ -22,6 +22,14 @@ require 'date'
22
22
  # Various SDL related utility methods
23
23
  #
24
24
  module SDL4R
25
+
26
+ # Creates and returns a tag named "root" and add all the tags specified in the given +input+.
27
+ #
28
+ # +input+:: String, IO, Pathname or URI.
29
+ #
30
+ def self.read(input)
31
+ Tag.new("root").read(input)
32
+ end
25
33
 
26
34
  MAX_INTEGER_32 = 2**31 - 1
27
35
  MIN_INTEGER_32 = -(2**31)
@@ -29,15 +37,6 @@ module SDL4R
29
37
  MAX_INTEGER_64 = 2**63 - 1
30
38
  MIN_INTEGER_64 = -(2**63)
31
39
 
32
-
33
- # Returns the milliseonds part of a DateTime (by translating the +sec_fraction+ part) as an
34
- # integer.
35
- def self.get_date_milliseconds(date)
36
- sec_fraction = date.sec_fraction() # in days
37
- # 86400000 is the number of milliseconds in a day
38
- return (sec_fraction * 86400000).round()
39
- end
40
-
41
40
  BASE64_WRAP_LINE_LENGTH = 72
42
41
 
43
42
  # Creates an SDL string representation for a given object and returns it.
@@ -130,72 +129,6 @@ module SDL4R
130
129
  return o.to_s
131
130
  end
132
131
  end
133
-
134
- # Wraps lines in "s" (by modifying it). This method only supports 1-byte character strings.
135
- #
136
- def self.wrap_lines_in_ascii(s, line_length, line_prefix = nil)
137
- # We could use such code if it supported any value for "line_prefix": unfortunately it is capped
138
- # at 64 in the regular expressions.
139
- #
140
- # return "#{line_prefix}" + encoded_o.scan(/.{1,#{line_prefix}}/).join("#{$/}#{line_prefix}")
141
-
142
- eol_size = "#{$/}".size
143
-
144
- i = 0
145
- while i < s.size
146
- if i > 0
147
- s.insert(i, $/)
148
- i += eol_size
149
- end
150
-
151
- if line_prefix
152
- s.insert(i, line_prefix)
153
- i += line_prefix.size
154
- end
155
-
156
- i += line_length
157
- end
158
- end
159
-
160
- ESCAPED_QUOTES = {
161
- "\"" => "\\\"",
162
- "'" => "\\'",
163
- "`" => "\\`",
164
- }
165
-
166
- ESCAPED_CHARS = {
167
- "\\" => "\\\\",
168
- "\t" => "\\t",
169
- "\r" => "\\r",
170
- "\n" => "\\n",
171
- }
172
- ESCAPED_CHARS.merge!(ESCAPED_QUOTES)
173
-
174
- # Returns an escaped version of +s+ (i.e. where characters which need to be
175
- # escaped, are escaped).
176
- #
177
- def self.escape(s, quote_char = nil)
178
- escaped_s = ""
179
-
180
- s.each_char { |c|
181
- escaped_char = ESCAPED_CHARS[c]
182
- if escaped_char
183
- if ESCAPED_QUOTES.has_key?(c)
184
- if quote_char && c == quote_char
185
- escaped_s << escaped_char
186
- else
187
- escaped_s << c
188
- end
189
- else
190
- escaped_s << escaped_char
191
- end
192
- else
193
- escaped_s << c
194
- end
195
- }
196
-
197
- return escaped_s
198
- end
199
132
 
200
133
  # This method was kept from the Java code but it is not sure if it should have a usefulness yet.
201
134
  #
@@ -226,7 +159,7 @@ module SDL4R
226
159
  "an underscore (_)."
227
160
  end
228
161
 
229
- unless identifier.length == 1 or identifier =~ /^[a-zA-Z_][a-zA-Z_0-9\-]*$/
162
+ unless identifier.length == 1 or identifier =~ /^[a-zA-Z_][a-zA-Z_0-9\-\.]*$/
230
163
  for i in 1..identifier.length
231
164
  unless identifier[i..i] =~ /^[a-zA-Z_0-9\-]$/
232
165
  raise ArgumentError,
@@ -239,4 +172,121 @@ module SDL4R
239
172
  end
240
173
  end
241
174
  end
175
+
176
+ # Parses and returns the value corresponding with the specified SDL literal.
177
+ #
178
+ def self.to_value(s)
179
+ raise ArgumentError, "'s' cannot be null" if s.nil?
180
+ return read(s).child.value
181
+ end
182
+
183
+ # Parse the string of values and return a list. The string is handled
184
+ # as if it is the values portion of an SDL tag.
185
+ #
186
+ # Example
187
+ #
188
+ # array = SDL4R.to_values("1 true 12:24:01")
189
+ #
190
+ # Will return an int, a boolean, and a time span.
191
+ #
192
+ def self.to_value_array(s)
193
+ raise ArgumentError, "'s' cannot be null" if s.nil?
194
+ return read(s).child.values
195
+ end
196
+
197
+ # Parse a string representing the attributes portion of an SDL tag
198
+ # and return the results as a map.
199
+ #
200
+ # Example
201
+ #
202
+ # hash = SDL4R.to_attribute_hash("value=1 debugging=on time=12:24:01");
203
+ #
204
+ # Will return a map containing value=1, debugging=true, and time=12:24:01
205
+ #
206
+ def self.to_attribute_map(s)
207
+ raise ArgumentError, "'s' cannot be null" if s.nil?
208
+ return read("atts " + s).child.attributes
209
+ end
210
+
211
+ # The following is a not so readable way to implement module private methods in Ruby: we add
212
+ # private methods to the singleton class of +self+ i.e. the SDL4R module.
213
+ class << self
214
+ private
215
+
216
+ # Wraps lines in "s" (by modifying it). This method only supports 1-byte character strings.
217
+ #
218
+ def wrap_lines_in_ascii(s, line_length, line_prefix = nil)
219
+ # We could use such code if it supported any value for "line_prefix": unfortunately it is capped
220
+ # at 64 in the regular expressions.
221
+ #
222
+ # return "#{line_prefix}" + encoded_o.scan(/.{1,#{line_prefix}}/).join("#{$/}#{line_prefix}")
223
+
224
+ eol_size = "#{$/}".size
225
+
226
+ i = 0
227
+ while i < s.size
228
+ if i > 0
229
+ s.insert(i, $/)
230
+ i += eol_size
231
+ end
232
+
233
+ if line_prefix
234
+ s.insert(i, line_prefix)
235
+ i += line_prefix.size
236
+ end
237
+
238
+ i += line_length
239
+ end
240
+ end
241
+
242
+ ESCAPED_QUOTES = {
243
+ "\"" => "\\\"",
244
+ "'" => "\\'",
245
+ "`" => "\\`",
246
+ }
247
+
248
+ ESCAPED_CHARS = {
249
+ "\\" => "\\\\",
250
+ "\t" => "\\t",
251
+ "\r" => "\\r",
252
+ "\n" => "\\n",
253
+ }
254
+ ESCAPED_CHARS.merge!(ESCAPED_QUOTES)
255
+
256
+ # Returns an escaped version of +s+ (i.e. where characters which need to be
257
+ # escaped, are escaped).
258
+ #
259
+ def escape(s, quote_char = nil)
260
+ escaped_s = ""
261
+
262
+ s.each_char { |c|
263
+ escaped_char = ESCAPED_CHARS[c]
264
+ if escaped_char
265
+ if ESCAPED_QUOTES.has_key?(c)
266
+ if quote_char && c == quote_char
267
+ escaped_s << escaped_char
268
+ else
269
+ escaped_s << c
270
+ end
271
+ else
272
+ escaped_s << escaped_char
273
+ end
274
+ else
275
+ escaped_s << c
276
+ end
277
+ }
278
+
279
+ return escaped_s
280
+ end
281
+
282
+ # Returns the milliseonds part of a DateTime (by translating the +sec_fraction+ part) as an
283
+ # integer.
284
+ def get_date_milliseconds(date)
285
+ sec_fraction = date.sec_fraction() # in days
286
+ # 86400000 is the number of milliseconds in a day
287
+ return (sec_fraction * 86400000).round()
288
+ end
289
+
290
+ end
291
+
242
292
  end
data/lib/sdl4r/tag.rb CHANGED
@@ -16,6 +16,8 @@
16
16
 
17
17
  module SDL4R
18
18
 
19
+ require 'pathname'
20
+ require 'open-uri'
19
21
  require 'stringio'
20
22
 
21
23
  require File.dirname(__FILE__) + '/sdl'
@@ -314,7 +316,7 @@ module SDL4R
314
316
  # (see SDL#validate_identifier) or the namespace is non-blank
315
317
  # and is not a legal SDL identifier.
316
318
  #
317
- def initialize(name, namespace = "")
319
+ def initialize(name, namespace = "", &block)
318
320
  namespace = namespace.to_s
319
321
  SDL4R.validate_identifier(namespace) unless namespace.empty?
320
322
  @namespace = namespace
@@ -330,6 +332,25 @@ module SDL4R
330
332
  # a Hash of Hash : {namespace => {name => value}}
331
333
  # The default namespace is represented by an empty string.
332
334
  @attributesByNamespace = {}
335
+
336
+ instance_eval(&block) if block_given?
337
+ end
338
+
339
+ # Creates a new child tag.
340
+ # Can take a block so that you can write something like:
341
+ #
342
+ # car = Tag.new("car") do
343
+ # new_child("wheels") do
344
+ # self << 4
345
+ # end
346
+ # end
347
+ #
348
+ # The context of execution of the given block is the child instance
349
+ #
350
+ # Returns the created child Tag.
351
+ #
352
+ def new_child(*args, &block)
353
+ return add_child Tag.new(*args, &block)
333
354
  end
334
355
 
335
356
  # Add a child to this Tag.
@@ -453,7 +474,7 @@ module SDL4R
453
474
  # +name+:: the name of the child Tag. If +nil+, the first child is returned (+nil+ if there are
454
475
  # no children at all).
455
476
  #
456
- # Returns The first child tag having the given name or +nil+ if no such child exists
477
+ # Returns the first child tag having the given name or +nil+ if no such child exists
457
478
  #
458
479
  def child(name = nil, recursive = false)
459
480
  unless name
@@ -463,6 +484,20 @@ module SDL4R
463
484
  end
464
485
  end
465
486
 
487
+ # Indicates whether the child Tag of given name exists.
488
+ #
489
+ # +name+:: name of the searched child Tag
490
+ #
491
+ def has_child?(name)
492
+ !child(name).nil?
493
+ end
494
+
495
+ # Indicates whether there are children Tag.
496
+ #
497
+ def has_children?
498
+ !@children.empty?
499
+ end
500
+
466
501
  # Enumerates the children +Tag+s of this Tag and calls the given block
467
502
  # providing it the child as parameter.
468
503
  #
@@ -482,6 +517,44 @@ module SDL4R
482
517
  return nil
483
518
  end
484
519
  private :each_child
520
+
521
+ # Returns a new Hash where the children's names as keys and their values as the key's value.
522
+ # Example:
523
+ #
524
+ # child1 "toto"
525
+ # child2 2
526
+ #
527
+ # would give
528
+ #
529
+ # { "child1" => "toto", "child2" => 2 }
530
+ #
531
+ def to_child_hash
532
+ hash = {}
533
+ children { |child| hash[child.name] = child.value }
534
+ return hash
535
+ end
536
+
537
+ # Returns a new Hash where the children's names as keys and their values as the key's value.
538
+ # Values are converted to Strings. +nil+ values become empty Strings.
539
+ # Example:
540
+ #
541
+ # child1 "toto"
542
+ # child2 2
543
+ # child3 null
544
+ #
545
+ # would give
546
+ #
547
+ # { "child1" => "toto", "child2" => "2", "child3" => "" }
548
+ #
549
+ def to_child_string_hash
550
+ hash = {}
551
+ children do |child|
552
+ # FIXME: it is quite hard to be sure whether we should mimic the Java version
553
+ # as there might be a lot of values that don't translate nicely to Strings.
554
+ hash[child.name] = child.value.to_s
555
+ end
556
+ return hash
557
+ end
485
558
 
486
559
  # Adds a value to this Tag. The allowable types are String, Number,
487
560
  # Boolean, Character, byte[], Byte[] (coerced to byte[]), Calendar,
@@ -498,7 +571,7 @@ module SDL4R
498
571
 
499
572
  # Returns true if +v+ is a value of this Tag's.
500
573
  #
501
- def has_value(v)
574
+ def has_value?(v)
502
575
  @values.include?(v)
503
576
  end
504
577
 
@@ -584,7 +657,7 @@ module SDL4R
584
657
  # +key+:: key of the attribute
585
658
  # +namespace+:: namespace of the attribute ("", the default namespace, by default)
586
659
  #
587
- def has_attribute(key, namespace = "")
660
+ def has_attribute?(key, namespace = "")
588
661
  attributes = @attributesByNamespace[namespace]
589
662
  return attributes.nil? ? false : attributes.has_key?(key)
590
663
  end
@@ -716,64 +789,45 @@ module SDL4R
716
789
  SDL4R.validate_identifier(a_namespace) unless a_namespace.empty?
717
790
  @namespace = a_namespace
718
791
  end
719
-
720
- #
721
- # Add all the tags specified in the file at the given URL to this Tag.
722
- #
723
- # +url+:: A UTF8 encoded .sdl file
724
- # @throws IOException If there is an IO problem reading the source
725
- # @throws ParseException If the SDL input is malformed
726
- # Returns This tag after adding all the children read from the reader
727
- #
728
- # public Tag read(URL url) throws IOException, SDLParseException {
729
- # return read(new InputStreamReader(url.openStream(), "UTF8"));
730
- # }
731
-
732
- #
733
- # Add all the tags specified in the given file to this Tag.
734
- #
735
- # +file+:: A UTF8 encoded .sdl file
736
- # @throws IOException If there is an IO problem reading the source
737
- # @throws ParseException If the SDL input is malformed
738
- # Returns This tag after adding all the children read from the reader
739
- #
740
- # public Tag read(File file) throws IOException, SDLParseException {
741
- # return read(new InputStreamReader(new FileInputStream(file), "UTF8"));
742
- # }
743
-
744
- #
745
- # Add all the tags specified in the given String to this Tag.
746
- #
747
- # +text+:: An SDL string
748
- # @throws ParseException If the SDL input is malformed
749
- # Returns This tag after adding all the children read from the reader
750
- #
751
- # public Tag read(String text) throws SDLParseException {
752
- # try {
753
- # return read(new StringReader(text));
754
- # } catch(IOException ioe) {
755
- # // Cannot happen
756
- # throw new InternalError("IOExceptio reading a String");
757
- # }
758
- # }
759
-
760
- # Adds all the tags specified in the given +IO+ or String to this Tag.
792
+
793
+ # Adds all the tags specified in the given IO, String, Pathname or URI to this Tag.
761
794
  #
762
- # Returns this Tag after adding all the children read from _input_.
795
+ # Returns this Tag after adding all the children read from +input+.
763
796
  #
764
797
  def read(input)
765
- if input.is_a?(String)
766
- io = StringIO.new(input)
798
+ if input.is_a? String
799
+ read_from_io(true) { StringIO.new(input) }
800
+
801
+ elsif input.is_a? Pathname
802
+ read_from_io(true) { input.open("r") }
803
+
804
+ elsif input.is_a? URI
805
+ read_from_io(true) { input.open }
806
+
767
807
  else
768
- io = input
808
+ read_from_io(false) { input }
769
809
  end
770
810
 
771
- Parser.new(io).parse.each do |tag|
772
- add_child(tag)
773
- end
774
-
775
811
  return self
776
812
  end
813
+
814
+ # Reads and parses the +io+ returned by the specified block and closes this +io+ if +close_io+
815
+ # is true.
816
+ def read_from_io(close_io)
817
+ io = yield
818
+
819
+ begin
820
+ Parser.new(io).parse.each do |tag|
821
+ add_child(tag)
822
+ end
823
+
824
+ ensure
825
+ if close_io
826
+ io.close rescue IOError
827
+ end
828
+ end
829
+ end
830
+ private_methods :read_io
777
831
 
778
832
  # Write this tag out to the given IO or string (optionally clipping the root.)
779
833
  #