monetra-ruby 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/Rakefile +35 -0
  2. data/lib/monetra.rb +239 -0
  3. data/lib/monetra/active_support.rb +42 -0
  4. data/lib/monetra/active_support/binding_of_caller.rb +84 -0
  5. data/lib/monetra/active_support/breakpoint.rb +523 -0
  6. data/lib/monetra/active_support/caching_tools.rb +62 -0
  7. data/lib/monetra/active_support/clean_logger.rb +38 -0
  8. data/lib/monetra/active_support/core_ext.rb +1 -0
  9. data/lib/monetra/active_support/core_ext/array.rb +7 -0
  10. data/lib/monetra/active_support/core_ext/array/conversions.rb +72 -0
  11. data/lib/monetra/active_support/core_ext/array/grouping.rb +46 -0
  12. data/lib/monetra/active_support/core_ext/bigdecimal.rb +3 -0
  13. data/lib/monetra/active_support/core_ext/bigdecimal/formatting.rb +7 -0
  14. data/lib/monetra/active_support/core_ext/blank.rb +50 -0
  15. data/lib/monetra/active_support/core_ext/cgi.rb +5 -0
  16. data/lib/monetra/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -0
  17. data/lib/monetra/active_support/core_ext/class.rb +3 -0
  18. data/lib/monetra/active_support/core_ext/class/attribute_accessors.rb +44 -0
  19. data/lib/monetra/active_support/core_ext/class/inheritable_attributes.rb +115 -0
  20. data/lib/monetra/active_support/core_ext/class/removal.rb +24 -0
  21. data/lib/monetra/active_support/core_ext/date.rb +6 -0
  22. data/lib/monetra/active_support/core_ext/date/conversions.rb +39 -0
  23. data/lib/monetra/active_support/core_ext/enumerable.rb +62 -0
  24. data/lib/monetra/active_support/core_ext/exception.rb +33 -0
  25. data/lib/monetra/active_support/core_ext/hash.rb +13 -0
  26. data/lib/monetra/active_support/core_ext/hash/conversions.rb +148 -0
  27. data/lib/monetra/active_support/core_ext/hash/diff.rb +11 -0
  28. data/lib/monetra/active_support/core_ext/hash/indifferent_access.rb +88 -0
  29. data/lib/monetra/active_support/core_ext/hash/keys.rb +53 -0
  30. data/lib/monetra/active_support/core_ext/hash/reverse_merge.rb +25 -0
  31. data/lib/monetra/active_support/core_ext/integer.rb +7 -0
  32. data/lib/monetra/active_support/core_ext/integer/even_odd.rb +24 -0
  33. data/lib/monetra/active_support/core_ext/integer/inflections.rb +15 -0
  34. data/lib/monetra/active_support/core_ext/kernel.rb +4 -0
  35. data/lib/monetra/active_support/core_ext/kernel/agnostics.rb +11 -0
  36. data/lib/monetra/active_support/core_ext/kernel/daemonizing.rb +15 -0
  37. data/lib/monetra/active_support/core_ext/kernel/reporting.rb +51 -0
  38. data/lib/monetra/active_support/core_ext/kernel/requires.rb +24 -0
  39. data/lib/monetra/active_support/core_ext/load_error.rb +38 -0
  40. data/lib/monetra/active_support/core_ext/logger.rb +16 -0
  41. data/lib/monetra/active_support/core_ext/module.rb +7 -0
  42. data/lib/monetra/active_support/core_ext/module/aliasing.rb +57 -0
  43. data/lib/monetra/active_support/core_ext/module/attr_internal.rb +31 -0
  44. data/lib/monetra/active_support/core_ext/module/attribute_accessors.rb +44 -0
  45. data/lib/monetra/active_support/core_ext/module/delegation.rb +41 -0
  46. data/lib/monetra/active_support/core_ext/module/inclusion.rb +11 -0
  47. data/lib/monetra/active_support/core_ext/module/introspection.rb +21 -0
  48. data/lib/monetra/active_support/core_ext/module/loading.rb +13 -0
  49. data/lib/monetra/active_support/core_ext/name_error.rb +20 -0
  50. data/lib/monetra/active_support/core_ext/numeric.rb +7 -0
  51. data/lib/monetra/active_support/core_ext/numeric/bytes.rb +44 -0
  52. data/lib/monetra/active_support/core_ext/numeric/time.rb +72 -0
  53. data/lib/monetra/active_support/core_ext/object.rb +2 -0
  54. data/lib/monetra/active_support/core_ext/object/extending.rb +47 -0
  55. data/lib/monetra/active_support/core_ext/object/misc.rb +34 -0
  56. data/lib/monetra/active_support/core_ext/pathname.rb +7 -0
  57. data/lib/monetra/active_support/core_ext/pathname/clean_within.rb +14 -0
  58. data/lib/monetra/active_support/core_ext/proc.rb +12 -0
  59. data/lib/monetra/active_support/core_ext/range.rb +5 -0
  60. data/lib/monetra/active_support/core_ext/range/conversions.rb +21 -0
  61. data/lib/monetra/active_support/core_ext/string.rb +13 -0
  62. data/lib/monetra/active_support/core_ext/string/access.rb +58 -0
  63. data/lib/monetra/active_support/core_ext/string/conversions.rb +19 -0
  64. data/lib/monetra/active_support/core_ext/string/inflections.rb +153 -0
  65. data/lib/monetra/active_support/core_ext/string/iterators.rb +17 -0
  66. data/lib/monetra/active_support/core_ext/string/starts_ends_with.rb +20 -0
  67. data/lib/monetra/active_support/core_ext/symbol.rb +12 -0
  68. data/lib/monetra/active_support/core_ext/time.rb +7 -0
  69. data/lib/monetra/active_support/core_ext/time/calculations.rb +188 -0
  70. data/lib/monetra/active_support/core_ext/time/conversions.rb +36 -0
  71. data/lib/monetra/active_support/dependencies.rb +187 -0
  72. data/lib/monetra/active_support/deprecation.rb +106 -0
  73. data/lib/monetra/active_support/inflections.rb +53 -0
  74. data/lib/monetra/active_support/inflector.rb +179 -0
  75. data/lib/monetra/active_support/json.rb +37 -0
  76. data/lib/monetra/active_support/json/encoders.rb +25 -0
  77. data/lib/monetra/active_support/json/encoders/core.rb +65 -0
  78. data/lib/monetra/active_support/option_merger.rb +25 -0
  79. data/lib/monetra/active_support/ordered_options.rb +50 -0
  80. data/lib/monetra/active_support/reloadable.rb +30 -0
  81. data/lib/monetra/active_support/values/time_zone.rb +180 -0
  82. data/lib/monetra/active_support/vendor/builder.rb +13 -0
  83. data/lib/monetra/active_support/vendor/builder/blankslate.rb +63 -0
  84. data/lib/monetra/active_support/vendor/builder/xchar.rb +112 -0
  85. data/lib/monetra/active_support/vendor/builder/xmlbase.rb +145 -0
  86. data/lib/monetra/active_support/vendor/builder/xmlevents.rb +63 -0
  87. data/lib/monetra/active_support/vendor/builder/xmlmarkup.rb +328 -0
  88. data/lib/monetra/active_support/vendor/flexmock.rb +84 -0
  89. data/lib/monetra/active_support/vendor/xml_simple.rb +1019 -0
  90. data/lib/monetra/active_support/version.rb +9 -0
  91. data/lib/monetra/active_support/whiny_nil.rb +38 -0
  92. data/test/test.rb +21 -0
  93. metadata +167 -0
@@ -0,0 +1,25 @@
1
+ module ActiveSupport
2
+ class OptionMerger #:nodoc:
3
+ instance_methods.each do |method|
4
+ undef_method(method) if method !~ /^(__|instance_eval)/
5
+ end
6
+
7
+ def initialize(context, options)
8
+ @context, @options = context, options
9
+ end
10
+
11
+ private
12
+ def method_missing(method, *arguments, &block)
13
+ merge_argument_options! arguments
14
+ @context.send(method, *arguments, &block)
15
+ end
16
+
17
+ def merge_argument_options!(arguments)
18
+ arguments << if arguments.last.respond_to? :to_hash
19
+ @options.merge(arguments.pop)
20
+ else
21
+ @options.dup
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ # OrderedHash is namespaced to prevent conflicts with other implementations
2
+ module ActiveSupport
3
+ class OrderedHash < Array #:nodoc:
4
+ def []=(key, value)
5
+ if pair = find_pair(key)
6
+ pair.pop
7
+ pair << value
8
+ else
9
+ self << [key, value]
10
+ end
11
+ end
12
+
13
+ def [](key)
14
+ pair = find_pair(key)
15
+ pair ? pair.last : nil
16
+ end
17
+
18
+ def keys
19
+ collect { |key, value| key }
20
+ end
21
+
22
+ def values
23
+ collect { |key, value| value }
24
+ end
25
+
26
+ private
27
+ def find_pair(key)
28
+ self.each { |i| return i if i.first == key }
29
+ return false
30
+ end
31
+ end
32
+ end
33
+
34
+ class OrderedOptions < ActiveSupport::OrderedHash #:nodoc:
35
+ def []=(key, value)
36
+ super(key.to_sym, value)
37
+ end
38
+
39
+ def [](key)
40
+ super(key.to_sym)
41
+ end
42
+
43
+ def method_missing(name, *args)
44
+ if name.to_s =~ /(.*)=$/
45
+ self[$1.to_sym] = args.first
46
+ else
47
+ self[name]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,30 @@
1
+ # Classes that include this module will automatically be reloaded
2
+ # by the Rails dispatcher when Dependencies.mechanism = :load.
3
+ module Reloadable
4
+ class << self
5
+ def included(base) #nodoc:
6
+ raise TypeError, "Only Classes can be Reloadable!" unless base.is_a? Class
7
+
8
+ unless base.respond_to?(:reloadable?)
9
+ class << base
10
+ define_method(:reloadable?) { true }
11
+ end
12
+ end
13
+ end
14
+
15
+ def reloadable_classes
16
+ included_in_classes.select { |klass| klass.reloadable? }
17
+ end
18
+ end
19
+
20
+ # Captures the common pattern where a base class should not be reloaded,
21
+ # but its subclasses should be.
22
+ module Subclasses
23
+ def self.included(base) #nodoc:
24
+ base.send :include, Reloadable
25
+ (class << base; self; end).send(:define_method, :reloadable?) do
26
+ base != self
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,180 @@
1
+ # A value object representing a time zone. A time zone is simply a named
2
+ # offset (in seconds) from GMT. Note that two time zone objects are only
3
+ # equivalent if they have both the same offset, and the same name.
4
+ #
5
+ # A TimeZone instance may be used to convert a Time value to the corresponding
6
+ # time zone.
7
+ #
8
+ # The class also includes #all, which returns a list of all TimeZone objects.
9
+ class TimeZone
10
+ include Comparable
11
+
12
+ attr_reader :name, :utc_offset
13
+
14
+ # Create a new TimeZone object with the given name and offset. The offset is
15
+ # the number of seconds that this time zone is offset from UTC (GMT). Seconds
16
+ # were chosen as the offset unit because that is the unit that Ruby uses
17
+ # to represent time zone offsets (see Time#utc_offset).
18
+ def initialize(name, utc_offset)
19
+ @name = name
20
+ @utc_offset = utc_offset
21
+ end
22
+
23
+ # Returns the offset of this time zone as a formatted string, of the
24
+ # format "+HH:MM". If the offset is zero, this returns the empty
25
+ # string. If +colon+ is false, a colon will not be inserted into the
26
+ # result.
27
+ def formatted_offset( colon=true )
28
+ return "" if utc_offset == 0
29
+ sign = (utc_offset < 0 ? -1 : 1)
30
+ hours = utc_offset.abs / 3600
31
+ minutes = (utc_offset.abs % 3600) / 60
32
+ "%+03d%s%02d" % [ hours * sign, colon ? ":" : "", minutes ]
33
+ end
34
+
35
+ # Compute and return the current time, in the time zone represented by
36
+ # +self+.
37
+ def now
38
+ adjust(Time.now)
39
+ end
40
+
41
+ # Return the current date in this time zone.
42
+ def today
43
+ now.to_date
44
+ end
45
+
46
+ # Adjust the given time to the time zone represented by +self+.
47
+ def adjust(time)
48
+ time = time.to_time
49
+ time + utc_offset - time.utc_offset
50
+ end
51
+
52
+ # Reinterprets the given time value as a time in the current time
53
+ # zone, and then adjusts it to return the corresponding time in the
54
+ # local time zone.
55
+ def unadjust(time)
56
+ time = Time.local(*time.to_time.to_a)
57
+ time - utc_offset + time.utc_offset
58
+ end
59
+
60
+ # Compare this time zone to the parameter. The two are comapred first on
61
+ # their offsets, and then by name.
62
+ def <=>(zone)
63
+ result = (utc_offset <=> zone.utc_offset)
64
+ result = (name <=> zone.name) if result == 0
65
+ result
66
+ end
67
+
68
+ # Returns a textual representation of this time zone.
69
+ def to_s
70
+ "(GMT#{formatted_offset}) #{name}"
71
+ end
72
+
73
+ @@zones = nil
74
+
75
+ class << self
76
+ # Create a new TimeZone instance with the given name and offset.
77
+ def create(name, offset)
78
+ zone = allocate
79
+ zone.send :initialize, name, offset
80
+ zone
81
+ end
82
+
83
+ # Return a TimeZone instance with the given name, or +nil+ if no
84
+ # such TimeZone instance exists. (This exists to support the use of
85
+ # this class with the #composed_of macro.)
86
+ def new(name)
87
+ self[name]
88
+ end
89
+
90
+ # Return an array of all TimeZone objects. There are multiple TimeZone
91
+ # objects per time zone, in many cases, to make it easier for users to
92
+ # find their own time zone.
93
+ def all
94
+ unless @@zones
95
+ @@zones = []
96
+ [[-43_200, "International Date Line West" ],
97
+ [-39_600, "Midway Island", "Samoa" ],
98
+ [-36_000, "Hawaii" ],
99
+ [-32_400, "Alaska" ],
100
+ [-28_800, "Pacific Time (US & Canada)", "Tijuana" ],
101
+ [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "La Paz",
102
+ "Mazatlan", "Arizona" ],
103
+ [-21_600, "Central Time (US & Canada)", "Saskatchewan", "Guadalajara",
104
+ "Mexico City", "Monterrey", "Central America" ],
105
+ [-18_000, "Eastern Time (US & Canada)", "Indiana (East)", "Bogota",
106
+ "Lima", "Quito" ],
107
+ [-14_400, "Atlantic Time (Canada)", "Caracas", "La Paz", "Santiago" ],
108
+ [-12_600, "Newfoundland" ],
109
+ [-10_800, "Brasilia", "Buenos Aires", "Georgetown", "Greenland" ],
110
+ [ -7_200, "Mid-Atlantic" ],
111
+ [ -3_600, "Azores", "Cape Verde Is." ],
112
+ [ 0, "Dublin", "Edinburgh", "Lisbon", "London", "Casablanca",
113
+ "Monrovia" ],
114
+ [ 3_600, "Belgrade", "Bratislava", "Budapest", "Ljubljana", "Prague",
115
+ "Sarajevo", "Skopje", "Warsaw", "Zagreb", "Brussels",
116
+ "Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin",
117
+ "Bern", "Rome", "Stockholm", "Vienna",
118
+ "West Central Africa" ],
119
+ [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyev", "Riga", "Sofia",
120
+ "Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk",
121
+ "Jerusalem", "Harare", "Pretoria" ],
122
+ [ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh",
123
+ "Nairobi", "Baghdad" ],
124
+ [ 12_600, "Tehran" ],
125
+ [ 14_400, "Abu Dhabi", "Muscat", "Baku", "Tbilisi", "Yerevan" ],
126
+ [ 16_200, "Kabul" ],
127
+ [ 18_000, "Ekaterinburg", "Islamabad", "Karachi", "Tashkent" ],
128
+ [ 19_800, "Chennai", "Kolkata", "Mumbai", "New Delhi" ],
129
+ [ 20_700, "Kathmandu" ],
130
+ [ 21_600, "Astana", "Dhaka", "Sri Jayawardenepura", "Almaty",
131
+ "Novosibirsk" ],
132
+ [ 23_400, "Rangoon" ],
133
+ [ 25_200, "Bangkok", "Hanoi", "Jakarta", "Krasnoyarsk" ],
134
+ [ 28_800, "Beijing", "Chongqing", "Hong Kong", "Urumqi",
135
+ "Kuala Lumpur", "Singapore", "Taipei", "Perth", "Irkutsk",
136
+ "Ulaan Bataar" ],
137
+ [ 32_400, "Seoul", "Osaka", "Sapporo", "Tokyo", "Yakutsk" ],
138
+ [ 34_200, "Darwin", "Adelaide" ],
139
+ [ 36_000, "Canberra", "Melbourne", "Sydney", "Brisbane", "Hobart",
140
+ "Vladivostok", "Guam", "Port Moresby" ],
141
+ [ 39_600, "Magadan", "Solomon Is.", "New Caledonia" ],
142
+ [ 43_200, "Fiji", "Kamchatka", "Marshall Is.", "Auckland",
143
+ "Wellington" ],
144
+ [ 46_800, "Nuku'alofa" ]].
145
+ each do |offset, *places|
146
+ places.each { |place| @@zones << create(place, offset).freeze }
147
+ end
148
+ @@zones.sort!
149
+ end
150
+ @@zones
151
+ end
152
+
153
+ # Locate a specific time zone object. If the argument is a string, it
154
+ # is interpreted to mean the name of the timezone to locate. If it is a
155
+ # numeric value it is either the hour offset, or the second offset, of the
156
+ # timezone to find. (The first one with that offset will be returned.)
157
+ # Returns +nil+ if no such time zone is known to the system.
158
+ def [](arg)
159
+ case arg
160
+ when String
161
+ all.find { |z| z.name == arg }
162
+ when Numeric
163
+ arg *= 3600 if arg.abs <= 13
164
+ all.find { |z| z.utc_offset == arg.to_i }
165
+ else
166
+ raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
167
+ end
168
+ end
169
+
170
+ # A regular expression that matches the names of all time zones in
171
+ # the USA.
172
+ US_ZONES = /US|Arizona|Indiana|Hawaii|Alaska/ unless defined?(US_ZONES)
173
+
174
+ # A convenience method for returning a collection of TimeZone objects
175
+ # for time zones in the USA.
176
+ def us_zones
177
+ all.find_all { |z| z.name =~ US_ZONES }
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ require 'builder/xmlmarkup'
13
+ require 'builder/xmlevents'
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ module Builder #:nodoc:
12
+
13
+ # BlankSlate provides an abstract base class with no predefined
14
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
15
+ # BlankSlate is useful as a base class when writing classes that
16
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
17
+ class BlankSlate
18
+ class << self
19
+
20
+ # Hide the method named +name+ in the BlankSlate class. Don't
21
+ # hide +instance_eval+ or any method beginning with "__".
22
+ def hide(name)
23
+ undef_method name if
24
+ instance_methods.include?(name.to_s) and
25
+ name !~ /^(__|instance_eval)/
26
+ end
27
+ end
28
+
29
+ instance_methods.each { |m| hide(m) }
30
+ end
31
+ end
32
+
33
+ # Since Ruby is very dynamic, methods added to the ancestors of
34
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
35
+ # list of available BlankSlate methods. We handle this by defining a
36
+ # hook in the Object and Kernel classes that will hide any defined
37
+ module Kernel #:nodoc:
38
+ class << self
39
+ alias_method :blank_slate_method_added, :method_added
40
+
41
+ # Detect method additions to Kernel and remove them in the
42
+ # BlankSlate class.
43
+ def method_added(name)
44
+ blank_slate_method_added(name)
45
+ return if self != Kernel
46
+ Builder::BlankSlate.hide(name)
47
+ end
48
+ end
49
+ end
50
+
51
+ class Object #:nodoc:
52
+ class << self
53
+ alias_method :blank_slate_method_added, :method_added
54
+
55
+ # Detect method additions to Object and remove them in the
56
+ # BlankSlate class.
57
+ def method_added(name)
58
+ blank_slate_method_added(name)
59
+ return if self != Object
60
+ Builder::BlankSlate.hide(name)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # The XChar library is provided courtesy of Sam Ruby (See
4
+ # http://intertwingly.net/stories/2005/09/28/xchar.rb)
5
+
6
+ # --------------------------------------------------------------------
7
+
8
+ # If the Builder::XChar module is not currently defined, fail on any
9
+ # name clashes in standard library classes.
10
+
11
+ module Builder
12
+ def self.check_for_name_collision(klass, method_name, defined_constant=nil)
13
+ if klass.instance_methods.include?(method_name)
14
+ fail RuntimeError,
15
+ "Name Collision: Method '#{method_name}' is already defined in #{klass}"
16
+ end
17
+ end
18
+ end
19
+
20
+ if ! defined?(Builder::XChar)
21
+ Builder.check_for_name_collision(String, "to_xs")
22
+ Builder.check_for_name_collision(Fixnum, "xchr")
23
+ end
24
+
25
+ ######################################################################
26
+ module Builder
27
+
28
+ ####################################################################
29
+ # XML Character converter, from Sam Ruby:
30
+ # (see http://intertwingly.net/stories/2005/09/28/xchar.rb).
31
+ #
32
+ module XChar # :nodoc:
33
+
34
+ # See
35
+ # http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
36
+ # for details.
37
+ CP1252 = { # :nodoc:
38
+ 128 => 8364, # euro sign
39
+ 130 => 8218, # single low-9 quotation mark
40
+ 131 => 402, # latin small letter f with hook
41
+ 132 => 8222, # double low-9 quotation mark
42
+ 133 => 8230, # horizontal ellipsis
43
+ 134 => 8224, # dagger
44
+ 135 => 8225, # double dagger
45
+ 136 => 710, # modifier letter circumflex accent
46
+ 137 => 8240, # per mille sign
47
+ 138 => 352, # latin capital letter s with caron
48
+ 139 => 8249, # single left-pointing angle quotation mark
49
+ 140 => 338, # latin capital ligature oe
50
+ 142 => 381, # latin capital letter z with caron
51
+ 145 => 8216, # left single quotation mark
52
+ 146 => 8217, # right single quotation mark
53
+ 147 => 8220, # left double quotation mark
54
+ 148 => 8221, # right double quotation mark
55
+ 149 => 8226, # bullet
56
+ 150 => 8211, # en dash
57
+ 151 => 8212, # em dash
58
+ 152 => 732, # small tilde
59
+ 153 => 8482, # trade mark sign
60
+ 154 => 353, # latin small letter s with caron
61
+ 155 => 8250, # single right-pointing angle quotation mark
62
+ 156 => 339, # latin small ligature oe
63
+ 158 => 382, # latin small letter z with caron
64
+ 159 => 376, # latin capital letter y with diaeresis
65
+ }
66
+
67
+ # See http://www.w3.org/TR/REC-xml/#dt-chardata for details.
68
+ PREDEFINED = {
69
+ 38 => '&amp;', # ampersand
70
+ 60 => '&lt;', # left angle bracket
71
+ 62 => '&gt;', # right angle bracket
72
+ }
73
+
74
+ # See http://www.w3.org/TR/REC-xml/#charsets for details.
75
+ VALID = [
76
+ [0x9, 0xA, 0xD],
77
+ (0x20..0xD7FF),
78
+ (0xE000..0xFFFD),
79
+ (0x10000..0x10FFFF)
80
+ ]
81
+ end
82
+
83
+ end
84
+
85
+
86
+ ######################################################################
87
+ # Enhance the Fixnum class with a XML escaped character conversion.
88
+ #
89
+ class Fixnum #:nodoc:
90
+ XChar = Builder::XChar if ! defined?(XChar)
91
+
92
+ # XML escaped version of chr
93
+ def xchr
94
+ n = XChar::CP1252[self] || self
95
+ n = 42 unless XChar::VALID.find {|range| range.include? n}
96
+ XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
97
+ end
98
+ end
99
+
100
+
101
+ ######################################################################
102
+ # Enhance the String class with a XML escaped character version of
103
+ # to_s.
104
+ #
105
+ class String #:nodoc:
106
+ # XML escaped version of to_s
107
+ def to_xs
108
+ unpack('U*').map {|n| n.xchr}.join # ASCII, UTF-8
109
+ rescue
110
+ unpack('C*').map {|n| n.xchr}.join # ISO-8859-1, WIN-1252
111
+ end
112
+ end