sdl4r 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +0 -0
- data/LICENSE +502 -0
- data/README +296 -1
- data/Rakefile +7 -4
- data/TODO.txt +33 -21
- data/doc/created.rid +1 -0
- data/doc/fr_class_index.html +36 -0
- data/doc/fr_file_index.html +39 -0
- data/doc/fr_method_index.html +141 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/sdl4r/parser.rb +1 -30
- data/lib/sdl4r/parser/reader.rb +175 -0
- data/lib/sdl4r/parser/time_span_with_zone.rb +52 -0
- data/lib/sdl4r/parser/token.rb +133 -0
- data/lib/sdl4r/parser/tokenizer.rb +506 -0
- data/lib/sdl4r/sdl.rb +126 -76
- data/lib/sdl4r/tag.rb +108 -54
- data/test/sdl4r/parser_test.rb +90 -19
- data/test/sdl4r/test.rb +93 -101
- data/test/sdl4r/test_basic_types.sdl +3 -3
- metadata +49 -37
- data/lib/scratchpad.rb +0 -49
- data/lib/sdl4r/reader.rb +0 -171
- data/lib/sdl4r/token.rb +0 -129
- data/lib/sdl4r/tokenizer.rb +0 -501
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
|
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
|
795
|
+
# Returns this Tag after adding all the children read from +input+.
|
763
796
|
#
|
764
797
|
def read(input)
|
765
|
-
if input.is_a?
|
766
|
-
|
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
|
-
|
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
|
#
|