sdl4r 0.9.9 → 0.9.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +70 -1
- data/LICENSE +499 -497
- data/Rakefile +38 -28
- data/TODO +194 -45
- data/doc/classes/SDL4R/AbbreviationTimezoneProxy.html +151 -0
- data/doc/classes/SDL4R/ConstantTimezone.html +129 -0
- data/doc/classes/SDL4R/Element.html +148 -0
- data/doc/classes/SDL4R/Reader.html +683 -0
- data/doc/classes/SDL4R/RelativeTimezone.html +187 -0
- data/doc/classes/SDL4R/SdlBinary.html +188 -0
- data/doc/classes/SDL4R/SdlParseError.html +110 -0
- data/doc/classes/SDL4R/SdlTimeSpan.html +651 -0
- data/doc/classes/SDL4R/Serializer.html +557 -0
- data/doc/classes/SDL4R/Serializer/Ref.html +138 -0
- data/doc/classes/SDL4R/TZAbbreviationDB/Record.html +117 -0
- data/doc/classes/SDL4R/Tag.html +1274 -0
- data/doc/classes/SDL4R/Token.html +131 -0
- data/doc/created.rid +1 -0
- data/doc/files/CHANGELOG.html +290 -0
- data/doc/files/LICENSE.html +53 -0
- data/doc/files/README.html +405 -0
- data/doc/files/lib/sdl4r/abbreviation_timezone_proxy_rb.html +63 -0
- data/doc/files/lib/sdl4r/constant_timezone_rb.html +54 -0
- data/doc/files/lib/sdl4r/element_rb.html +54 -0
- data/doc/files/lib/sdl4r/reader_rb.html +68 -0
- data/doc/files/lib/sdl4r/relative_timezone_rb.html +62 -0
- data/doc/files/lib/sdl4r/sdl4r_rb.html +66 -0
- data/doc/files/lib/sdl4r/sdl4r_tzinfo_rb.html +64 -0
- data/doc/files/lib/sdl4r/sdl4r_version_rb.html +54 -0
- data/doc/files/lib/sdl4r/sdl_binary_rb.html +54 -0
- data/doc/files/lib/sdl4r/sdl_parse_error_rb.html +54 -0
- data/doc/files/lib/sdl4r/sdl_time_span_rb.html +54 -0
- data/doc/files/lib/sdl4r/serializer_rb.html +62 -0
- data/doc/files/lib/sdl4r/tag_rb.html +66 -0
- data/doc/files/lib/sdl4r/token_rb.html +54 -0
- data/doc/files/lib/sdl4r/tokenizer_rb.html +64 -0
- data/doc/files/lib/sdl4r/tz_abbreviation_db_rb.html +67 -0
- data/doc/files/lib/sdl4r_rb.html +54 -0
- data/doc/files/lib/sdl4r_tzinfo_rb.html +54 -0
- data/doc/fr_class_index.html +23 -0
- data/doc/fr_file_index.html +40 -0
- data/doc/fr_method_index.html +4711 -0
- data/doc/index.html +15 -0
- data/doc/rdoc-style.css +328 -0
- data/lib/sdl4r.rb +3 -1
- data/lib/sdl4r/abbreviation_timezone_proxy.rb +38 -0
- data/lib/sdl4r/constant_timezone.rb +58 -0
- data/{test/sdl4r/sdl_test.rb → lib/sdl4r/element.rb} +19 -14
- data/lib/sdl4r/reader.rb +772 -0
- data/lib/sdl4r/relative_timezone.rb +156 -0
- data/lib/sdl4r/sdl4r.rb +187 -45
- data/lib/sdl4r/sdl4r_tzinfo.rb +75 -0
- data/lib/sdl4r/sdl4r_version.rb +24 -0
- data/lib/sdl4r/sdl_parse_error.rb +1 -1
- data/lib/sdl4r/sdl_time_span.rb +5 -1
- data/lib/sdl4r/serializer.rb +473 -60
- data/lib/sdl4r/tag.rb +126 -51
- data/lib/sdl4r/token.rb +49 -0
- data/lib/sdl4r/tokenizer.rb +431 -0
- data/lib/sdl4r/tz_abbreviation_db.rb +266 -0
- data/read_jprof.html +16934 -0
- data/read_jprof_pull.html +14451 -0
- data/read_prof.html +4983 -0
- data/read_prof_pull.html +4896 -0
- data/test/sdl4r/parser_test.rb +577 -503
- data/test/sdl4r/read_jprof.rb +58 -0
- data/test/sdl4r/read_prof.rb +70 -0
- data/test/sdl4r/reader_test.rb +173 -0
- data/test/sdl4r/relative_timezone_test.rb +102 -0
- data/test/sdl4r/sdl4r_test.rb +611 -528
- data/test/sdl4r/sdl4r_tzinfo_test.rb +108 -0
- data/test/sdl4r/sdl_test_case.rb +60 -0
- data/test/sdl4r/serializer_test.rb +448 -11
- data/test/sdl4r/tag_test.rb +84 -5
- data/test/sdl4r/tokenizer_test.rb +128 -0
- metadata +69 -11
- data/lib/sdl4r/parser.rb +0 -648
- data/lib/sdl4r/parser/reader.rb +0 -184
- data/lib/sdl4r/parser/time_span_with_zone.rb +0 -57
- data/lib/sdl4r/parser/token.rb +0 -138
- data/lib/sdl4r/parser/tokenizer.rb +0 -507
@@ -0,0 +1,156 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
#--
|
5
|
+
#
|
6
|
+
# Simple Declarative Language (SDL) for Ruby
|
7
|
+
# Copyright 2005 Ikayzo, inc.
|
8
|
+
#
|
9
|
+
# This program is free software. You can distribute or modify it under the
|
10
|
+
# terms of the GNU Lesser General Public License version 2.1 as published by
|
11
|
+
# the Free Software Foundation.
|
12
|
+
#
|
13
|
+
# This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
|
14
|
+
# INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
15
|
+
# See the GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
19
|
+
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
20
|
+
#++
|
21
|
+
|
22
|
+
module SDL4R
|
23
|
+
|
24
|
+
require 'sdl4r/tz_abbreviation_db'
|
25
|
+
|
26
|
+
# Represents a Timezone which is distant from a standard timezone by a fixed offset.
|
27
|
+
#
|
28
|
+
class RelativeTimezone < TZInfo::Timezone
|
29
|
+
|
30
|
+
# Returns a timezone by its identifier (e.g. "Europe/London",
|
31
|
+
# "America/Chicago" or "UTC").
|
32
|
+
#
|
33
|
+
# Supports relative timezones in the following formats: "UTC+2", "GMT+01:30",
|
34
|
+
# "Europe/Paris-10:00".
|
35
|
+
#
|
36
|
+
# Raises InvalidTimezoneIdentifier if the timezone couldn't be found.
|
37
|
+
#
|
38
|
+
def self.get(identifier)
|
39
|
+
base_identifier, offset_text, offset = RelativeTimezone::parse_relative_identifier(identifier)
|
40
|
+
|
41
|
+
tz = TZAbbreviationDB.get_timezone(base_identifier)
|
42
|
+
|
43
|
+
offset ?
|
44
|
+
RelativeTimezone.new(base_identifier + offset_text.to_s, offset_text, offset, tz) :
|
45
|
+
tz
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a proxy for the Timezone with the given identifier. The proxy
|
49
|
+
# will cause the real timezone to be loaded when an attempt is made to
|
50
|
+
# find a period or convert a time. get_proxy will not validate the
|
51
|
+
# identifier. If an invalid identifier is specified, no exception will be
|
52
|
+
# raised until the proxy is used.
|
53
|
+
#
|
54
|
+
# Supports relative timezones in the following format: "GMT+01:30", "CET-10:00".
|
55
|
+
#
|
56
|
+
def self.get_proxy(identifier)
|
57
|
+
base_identifier, offset_text, offset = RelativeTimezone::parse_relative_identifier(identifier)
|
58
|
+
|
59
|
+
proxy = TZAbbreviationDB.get_timezone_proxy(base_identifier)
|
60
|
+
|
61
|
+
offset ?
|
62
|
+
RelativeTimezone.new(base_identifier + offset_text.to_s, offset_text, offset, proxy) :
|
63
|
+
proxy
|
64
|
+
end
|
65
|
+
|
66
|
+
# Parses the specified identifier of the shape "GMT" or "CET+7" or "Asia/Shanghai-03:30" and
|
67
|
+
# returns an array containing respectively the simple zone identifier (e.g. "CET",
|
68
|
+
# "Asia/Shanghai"), the offset part (e.g. "-6", "+08:30") and the offset (seconds).
|
69
|
+
#
|
70
|
+
def self.parse_relative_identifier(identifier) # :nodoc:
|
71
|
+
offset = nil
|
72
|
+
|
73
|
+
if identifier =~ /^([a-zA-Z0-9\/_]+)(([+\-])(\d+)(?::(\d+))?)?$/
|
74
|
+
identifier, offset_text, sign_part, hour_part, minute_part = $1, $2, $3, $4, $5
|
75
|
+
|
76
|
+
if sign_part # relative offset
|
77
|
+
offset = 0
|
78
|
+
offset += 3600 * hour_part.to_i if hour_part
|
79
|
+
offset += 60 * minute_part.to_i if minute_part
|
80
|
+
offset = -offset if sign_part == '-'
|
81
|
+
|
82
|
+
offset = nil if offset == 0
|
83
|
+
|
84
|
+
# We regenerate/normalize the offset text "+7:3" ==> "+07:03".
|
85
|
+
offset_text = ""
|
86
|
+
if offset
|
87
|
+
offset_text << (offset >= 0 ? '+' : '-')
|
88
|
+
|
89
|
+
hours = offset.abs / 3600
|
90
|
+
minutes = (offset.abs % 3600) / 60
|
91
|
+
if minutes == 0
|
92
|
+
offset_text << hours.to_s
|
93
|
+
else
|
94
|
+
offset_text << sprintf("%02d:%02d", hours, minutes)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
return identifier, offset_text, offset
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.new(identifier, offset_text, offset, base_timezone)
|
104
|
+
o = super()
|
105
|
+
o.send(:_initialize, identifier, offset_text, offset, base_timezone)
|
106
|
+
o
|
107
|
+
end
|
108
|
+
|
109
|
+
# _base_timezone_:: timezone on which this RelativeTimezone is based
|
110
|
+
# _offset_:: the fixed offset (seconds)
|
111
|
+
#
|
112
|
+
def _initialize(identifier, offset_text, offset, base_timezone) # :nodoc:
|
113
|
+
raise ArgumentError, 'identifier' if identifier.nil?
|
114
|
+
raise ArgumentError, 'offset' if offset.nil?
|
115
|
+
raise ArgumentError, 'base_timezone' if base_timezone.nil?
|
116
|
+
|
117
|
+
@identifier = identifier
|
118
|
+
@base_timezone =
|
119
|
+
base_timezone.is_a?(String) ? TZInfo::Timezone.get(base_timezone) : base_timezone
|
120
|
+
@relative_offset_text = offset_text
|
121
|
+
@relative_offset = offset
|
122
|
+
end
|
123
|
+
protected :_initialize
|
124
|
+
|
125
|
+
attr_reader :identifier, :relative_offset
|
126
|
+
|
127
|
+
def period_for_utc(utc)
|
128
|
+
period = @base_timezone.period_for_utc(utc)
|
129
|
+
|
130
|
+
translated_offset =
|
131
|
+
period.offset ?
|
132
|
+
TZInfo::TimezoneOffsetInfo.new(
|
133
|
+
period.offset.utc_offset + @relative_offset,
|
134
|
+
period.offset.std_offset,
|
135
|
+
(period.offset.abbreviation.to_s + @relative_offset_text).to_sym) :
|
136
|
+
nil
|
137
|
+
|
138
|
+
return TZInfo::TimezonePeriod.new(nil, nil, translated_offset)
|
139
|
+
end
|
140
|
+
|
141
|
+
def periods_for_local(local)
|
142
|
+
periods = @base_timezone.periods_for_local(local)
|
143
|
+
|
144
|
+
return periods.collect { |period|
|
145
|
+
translated_offset =
|
146
|
+
period.offset ?
|
147
|
+
TZInfo::TimezoneOffsetInfo.new(
|
148
|
+
period.offset.utc_offset + @relative_offset,
|
149
|
+
period.offset.std_offset,
|
150
|
+
(period.offset.abbreviation.to_s + @relative_offset_text).to_sym) :
|
151
|
+
nil
|
152
|
+
TZInfo::TimezonePeriod.new(nil, nil, translated_offset)
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
data/lib/sdl4r/sdl4r.rb
CHANGED
@@ -22,7 +22,12 @@ require 'base64'
|
|
22
22
|
require 'bigdecimal'
|
23
23
|
require 'date'
|
24
24
|
|
25
|
-
|
25
|
+
require 'sdl4r/sdl4r_version'
|
26
|
+
require 'sdl4r/serializer'
|
27
|
+
|
28
|
+
# Utility methods and general constants for SDL4R.
|
29
|
+
#
|
30
|
+
# For more information about SDL4R, see the {link README file}[../../files/README.html]
|
26
31
|
#
|
27
32
|
module SDL4R
|
28
33
|
|
@@ -47,10 +52,10 @@ module SDL4R
|
|
47
52
|
def self.format(o, add_quotes = true, line_prefix = "", indent = "\t")
|
48
53
|
case o
|
49
54
|
when String
|
50
|
-
return format_string(o)
|
55
|
+
return format_string(o, add_quotes)
|
51
56
|
|
52
57
|
when Symbol
|
53
|
-
return format_string(o.to_s)
|
58
|
+
return format_string(o.to_s, add_quotes)
|
54
59
|
|
55
60
|
when Bignum
|
56
61
|
return o.to_s + "BD"
|
@@ -99,46 +104,77 @@ module SDL4R
|
|
99
104
|
# Below, we use "#{o.year}" instead of "%Y" because "%Y" always emit 4 chars at least even if
|
100
105
|
# the date is before 1000.
|
101
106
|
when DateTime, Time
|
102
|
-
|
103
|
-
|
104
|
-
if milliseconds == 0
|
105
|
-
zone_part = o.strftime("%:z")
|
106
|
-
if zone_part and zone_part != "+00:00"
|
107
|
-
return o.strftime("#{o.year}/%m/%d %H:%M:%S#{zone_part}")
|
108
|
-
else
|
109
|
-
return o.strftime("#{o.year}/%m/%d %H:%M:%S")
|
110
|
-
end
|
111
|
-
else
|
112
|
-
ms_part = milliseconds.to_s.ljust(3, '0')
|
113
|
-
if zone_part and zone_part != "+00:00"
|
114
|
-
return o.strftime("#{o.year}/%m/%d %H:%M:%S." + ms_part + zone_part)
|
115
|
-
else
|
116
|
-
return o.strftime("#{o.year}/%m/%d %H:%M:%S." + ms_part)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
107
|
+
return format_time(o)
|
108
|
+
|
120
109
|
when Date
|
121
|
-
return o.strftime("#{o.year}/%m/%d")
|
110
|
+
return "#{o.strftime("#{o.year}/%m/%d")}"
|
122
111
|
|
123
112
|
else
|
124
113
|
return o.to_s
|
125
114
|
end
|
126
115
|
end
|
127
116
|
|
128
|
-
|
129
|
-
|
130
|
-
|
117
|
+
def self.format_time(time)
|
118
|
+
s = "" # important as strftime() tends to return a US-ASCII string
|
119
|
+
s << time.strftime("#{time.year}/%m/%d %H:%M:%S") # %Y tends to return "88" for 1988 in many implementations
|
120
|
+
|
121
|
+
milliseconds = get_datetime_milliseconds(time)
|
122
|
+
s << sprintf(".%03d", milliseconds) if milliseconds != 0
|
123
|
+
|
124
|
+
zone_part = time.strftime("%z") # >> "+0130" -- "%:z" is not supported by every interpreter
|
125
|
+
unless zone_part.nil? or zone_part.empty? or zone_part == "+0000" or not zone_part =~ /[+-]\d+/
|
126
|
+
zone_part.insert(3, ":")
|
127
|
+
s << "-GMT" << zone_part
|
128
|
+
end
|
129
|
+
|
130
|
+
return s
|
131
|
+
end
|
132
|
+
|
133
|
+
@@use_datetime = true
|
134
|
+
|
135
|
+
# Indicates whether DateTime is used to represent times. If false, Time is used instead. True by
|
136
|
+
# default.
|
137
|
+
def self.use_datetime?
|
138
|
+
@@use_datetime
|
139
|
+
end
|
140
|
+
|
141
|
+
# Sets whether DateTime should be used for representing times at parsing.
|
142
|
+
# If set to false, Time will be used instead (true by default).
|
143
|
+
#
|
144
|
+
def self.use_datetime=(bool)
|
145
|
+
@@use_datetime = bool
|
146
|
+
end
|
147
|
+
|
148
|
+
# Creates and returns the object representing a time (DateTime by default).
|
149
|
+
# This method is called by the Parser class.
|
131
150
|
#
|
132
|
-
#
|
133
|
-
# def self.new_date_time(year, month, day, hour, min, sec, time_zone_offset)
|
134
|
-
# Time.utc(year, month, day, hour, min, sec)
|
135
|
-
# end
|
136
|
-
# end
|
151
|
+
# See #use_datetime=
|
137
152
|
#
|
138
|
-
def self.
|
139
|
-
|
153
|
+
def self.new_time(year, month, day, hour, min, sec, msec, timezone_code)
|
154
|
+
if @@use_datetime
|
155
|
+
timezone_code ||= Time.now.zone
|
156
|
+
sec_msec = (msec == 0)? sec : Rational(sec * 1000 + msec, 1000)
|
157
|
+
return DateTime.civil(year, month, day, hour, min, sec_msec, timezone_code)
|
158
|
+
|
159
|
+
else
|
160
|
+
if timezone_code =~ /\A(?:GMT|UTC)([+-]\d+:\d+)\Z/
|
161
|
+
timezone_code = $1
|
162
|
+
end
|
163
|
+
timezone_offset = Time.zone_offset(timezone_code, year) if timezone_code
|
164
|
+
if timezone_offset
|
165
|
+
timezone_offset_hour = timezone_offset.abs / 3600
|
166
|
+
timezone_offset_min = (timezone_offset.abs % 3600) / 60
|
167
|
+
return Time.xmlschema(
|
168
|
+
sprintf(
|
169
|
+
"%d-%02d-%02dT%02d:%02d:%02d.%03d#{timezone_offset >= 0 ? '+' : '-'}%02d:%02d",
|
170
|
+
year, month, day, hour, min, sec, msec, timezone_offset_hour, timezone_offset_min))
|
171
|
+
|
172
|
+
else
|
173
|
+
return Time.local(year, month, day, hour, min, sec, msec * 1000)
|
174
|
+
end
|
175
|
+
end
|
140
176
|
end
|
141
|
-
|
177
|
+
|
142
178
|
# Coerce the type to a standard SDL type or raises an ArgumentError.
|
143
179
|
#
|
144
180
|
# Returns +o+ if of the following classes:
|
@@ -175,7 +211,7 @@ module SDL4R
|
|
175
211
|
raise ArgumentError, "#{o.class.name} is not coercible to an SDL type"
|
176
212
|
end
|
177
213
|
|
178
|
-
# Indicates whether 'o' is coercible to a SDL
|
214
|
+
# Indicates whether 'o' is coercible to a SDL literal type.
|
179
215
|
# See #coerce_or_fail
|
180
216
|
#
|
181
217
|
def self.is_coercible?(o)
|
@@ -187,6 +223,42 @@ module SDL4R
|
|
187
223
|
false
|
188
224
|
end
|
189
225
|
end
|
226
|
+
|
227
|
+
# We disable the warnings as Ruby 1.8.7 prints one for the tested regex. We don't need this
|
228
|
+
# warning as we are precisely testing whether this regular expression works.
|
229
|
+
# Unfortunately, creating the regex with Regexp.new() doesn't help: we would have liked getting a
|
230
|
+
# RegexpError.
|
231
|
+
begin
|
232
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
233
|
+
@@UNICODE_REGEXP_SUPPORTED = ('é' =~ Regexp.new("\\p{Alnum}")) != nil
|
234
|
+
ensure
|
235
|
+
$VERBOSE = old_verbose
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.supports_unicode_identifiers?
|
239
|
+
@@UNICODE_REGEXP_SUPPORTED
|
240
|
+
end
|
241
|
+
|
242
|
+
IDENTIFIER_START_CLASS = @@UNICODE_REGEXP_SUPPORTED ? '[\\p{Alpha}_]' : '[a-zA-Z_]'
|
243
|
+
|
244
|
+
# Matches the first character of a valid SDL identifier.
|
245
|
+
IDENTIFIER_START_REGEXP =
|
246
|
+
@@UNICODE_REGEXP_SUPPORTED ? /\A#{IDENTIFIER_START_CLASS}/u : /\A#{IDENTIFIER_START_CLASS}/
|
247
|
+
|
248
|
+
IDENTIFIER_PART_CLASS =
|
249
|
+
@@UNICODE_REGEXP_SUPPORTED ? '[\\p{Alnum}_\\-\\.$]' : '[\\w\\-\\.$]'
|
250
|
+
|
251
|
+
# Matches characters of a valid SDL identifier after the first one.
|
252
|
+
# Works with one character long strings.
|
253
|
+
IDENTIFIER_PART_REGEXP =
|
254
|
+
@@UNICODE_REGEXP_SUPPORTED ?
|
255
|
+
/\A#{IDENTIFIER_PART_CLASS}\Z/u :
|
256
|
+
/\A#{IDENTIFIER_PART_CLASS}\Z/
|
257
|
+
|
258
|
+
# Matches a valid SDL identifier (start to end).
|
259
|
+
IDENTIFIER_REGEXP = @@UNICODE_REGEXP_SUPPORTED ?
|
260
|
+
/\A#{IDENTIFIER_START_CLASS}#{IDENTIFIER_PART_CLASS}*\Z/u :
|
261
|
+
/\A#{IDENTIFIER_START_CLASS}#{IDENTIFIER_PART_CLASS}*\Z/
|
190
262
|
|
191
263
|
# Validates an SDL identifier String. SDL Identifiers must start with a
|
192
264
|
# Unicode letter or underscore (_) and contain only unicode letters,
|
@@ -203,17 +275,17 @@ module SDL4R
|
|
203
275
|
end
|
204
276
|
|
205
277
|
# in Java, was if(!Character.isJavaIdentifierStart(identifier.charAt(0)))
|
206
|
-
unless identifier =~
|
278
|
+
unless identifier =~ IDENTIFIER_START_REGEXP
|
207
279
|
raise ArgumentError,
|
208
|
-
"'" + identifier[
|
280
|
+
"'" + identifier[/^./] +
|
209
281
|
"' is not a legal first character for an SDL identifier. " +
|
210
282
|
"SDL Identifiers must start with a unicode letter or " +
|
211
|
-
"an underscore (_)."
|
283
|
+
"an underscore (_). (identifier=<#{identifier}>)"
|
212
284
|
end
|
213
|
-
|
214
|
-
unless identifier.length == 1 or identifier =~
|
285
|
+
|
286
|
+
unless identifier.length == 1 or identifier =~ IDENTIFIER_REGEXP
|
215
287
|
for i in 1..identifier.length
|
216
|
-
unless identifier[i..i] =~
|
288
|
+
unless identifier[i..i] =~ IDENTIFIER_PART_REGEXP
|
217
289
|
raise ArgumentError,
|
218
290
|
"'" + identifier[i..i] +
|
219
291
|
"' is not a legal character for an SDL identifier. " +
|
@@ -225,16 +297,23 @@ module SDL4R
|
|
225
297
|
end
|
226
298
|
end
|
227
299
|
|
300
|
+
# Returns whether the specified SDL identifier is valid.
|
301
|
+
# See SDL4R#validate_identifier.
|
302
|
+
#
|
303
|
+
def self.valid_identifier?(identifier)
|
304
|
+
!IDENTIFIER_REGEXP.match(identifier).nil?
|
305
|
+
end
|
306
|
+
|
228
307
|
# Creates and returns a tag named "root" and add all the tags specified in the given +input+.
|
229
308
|
#
|
230
309
|
# +input+:: String, IO, Pathname or URI.
|
231
310
|
#
|
232
|
-
# root = SDL4R::read(<<
|
311
|
+
# root = SDL4R::read(<<EOS
|
233
312
|
# planets {
|
234
313
|
# earth area_km2=510900000
|
235
314
|
# mars
|
236
315
|
# }
|
237
|
-
#
|
316
|
+
# EOS
|
238
317
|
# )
|
239
318
|
#
|
240
319
|
# root = SDL4R::read(Pathname.new("my_dir/my_file.sdl"))
|
@@ -288,11 +367,74 @@ module SDL4R
|
|
288
367
|
return read("atts " + s).child.attributes
|
289
368
|
end
|
290
369
|
|
370
|
+
# Loads the specified 'input' and deserializes into the returned object.
|
371
|
+
#
|
372
|
+
# _input_:: an input as accepted by SDL4R#read or a Tag.
|
373
|
+
#
|
374
|
+
# example:
|
375
|
+
#
|
376
|
+
# top = SDL4R::load(<<EOS
|
377
|
+
# food name="chili con carne" {
|
378
|
+
# ingredient "beans"
|
379
|
+
# ingredient "chili"
|
380
|
+
# ingredient "cheese"
|
381
|
+
# note 8.9
|
382
|
+
# }
|
383
|
+
# EOS
|
384
|
+
# )
|
385
|
+
#
|
386
|
+
# top.food.name # => "chili con carne"
|
387
|
+
# top.food.ingredient # => ["beans", "chili", "cheese"]
|
388
|
+
# top.food.note # => 8.9
|
389
|
+
#
|
390
|
+
def self.load(input)
|
391
|
+
if input.is_a? Tag
|
392
|
+
tag = input
|
393
|
+
else
|
394
|
+
tag = read(input)
|
395
|
+
end
|
396
|
+
|
397
|
+
return Serializer.new.deserialize(tag)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Dumps the specified object to a given output or returns the corresponding SDL string if output
|
401
|
+
# is +nil+.
|
402
|
+
#
|
403
|
+
# _o_:: the root object (equivalent to a root SDL tag, therefore it's values and attributes are
|
404
|
+
# NOT dumped. See below for an example.)
|
405
|
+
# _output_:: an output as accepted by Tag#write or +nil+ in order to convert to a SDL string.
|
406
|
+
#
|
407
|
+
# example:
|
408
|
+
#
|
409
|
+
# food = OpenStruct.new(:name => 'french fries', 'comment' => 'eat with bier')
|
410
|
+
# food.fan = OpenStruct.new(:firstname => 'Homer')
|
411
|
+
#
|
412
|
+
# puts SDL4R::dump(:food => food)
|
413
|
+
#
|
414
|
+
# gives us
|
415
|
+
#
|
416
|
+
# food comment="eat with bier" name="french fries" {
|
417
|
+
# fan firstname="Homer"
|
418
|
+
# }
|
419
|
+
#
|
420
|
+
def self.dump(o, output = nil)
|
421
|
+
tag = Serializer.new.serialize(o)
|
422
|
+
|
423
|
+
if output.nil?
|
424
|
+
tag.children_to_string
|
425
|
+
else
|
426
|
+
tag.write(output)
|
427
|
+
output
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
291
431
|
# The following is a not so readable way to implement module private methods in Ruby: we add
|
292
432
|
# private methods to the singleton class of +self+ i.e. the SDL4R module.
|
293
433
|
class << self
|
294
434
|
private
|
295
435
|
|
436
|
+
SECONDS_IN_DAY = 24 * 3600 # :nodoc:
|
437
|
+
|
296
438
|
# Returns the specified string 's' formatted as a SDL string.
|
297
439
|
# See SDL4R#format.
|
298
440
|
#
|
@@ -384,12 +526,12 @@ module SDL4R
|
|
384
526
|
# least, some revisions of Ruby 1.9.
|
385
527
|
#
|
386
528
|
def get_datetime_milliseconds(datetime)
|
387
|
-
if
|
388
|
-
return (datetime.usec / 1000).round
|
529
|
+
if datetime.respond_to?(:usec)
|
530
|
+
return (datetime.usec / 1000.0).round
|
389
531
|
else
|
390
532
|
# Here don't believe that we could use '%3N' to get the milliseconds directly: the "3" is
|
391
533
|
# ignored for DateTime.strftime() in Ruby 1.8.
|
392
|
-
nanoseconds =
|
534
|
+
nanoseconds = datetime.strftime("%N").to_i
|
393
535
|
return (nanoseconds / 1000000).round
|
394
536
|
end
|
395
537
|
end
|