activesupport 3.0.pre → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (351) hide show
  1. data/CHANGELOG +121 -1
  2. data/README.rdoc +33 -0
  3. data/lib/active_support.rb +42 -4
  4. data/lib/active_support/backtrace_cleaner.rb +31 -9
  5. data/lib/active_support/benchmarkable.rb +1 -0
  6. data/lib/active_support/buffered_logger.rb +5 -2
  7. data/lib/active_support/builder.rb +6 -0
  8. data/lib/active_support/cache.rb +454 -84
  9. data/lib/active_support/cache/compressed_mem_cache_store.rb +6 -13
  10. data/lib/active_support/cache/file_store.rb +140 -41
  11. data/lib/active_support/cache/mem_cache_store.rb +121 -76
  12. data/lib/active_support/cache/memory_store.rb +127 -27
  13. data/lib/active_support/cache/strategy/local_cache.rb +111 -58
  14. data/lib/active_support/cache/synchronized_memory_store.rb +2 -38
  15. data/lib/active_support/callbacks.rb +105 -76
  16. data/lib/active_support/configurable.rb +19 -18
  17. data/lib/active_support/core_ext/array.rb +1 -0
  18. data/lib/active_support/core_ext/array/access.rb +1 -1
  19. data/lib/active_support/core_ext/array/conversions.rb +29 -54
  20. data/lib/active_support/core_ext/array/extract_options.rb +16 -1
  21. data/lib/active_support/core_ext/array/grouping.rb +1 -1
  22. data/lib/active_support/core_ext/array/random_access.rb +26 -5
  23. data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
  24. data/lib/active_support/core_ext/array/wrap.rb +13 -9
  25. data/lib/active_support/core_ext/benchmark.rb +0 -12
  26. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +2 -0
  27. data/lib/active_support/core_ext/class.rb +2 -1
  28. data/lib/active_support/core_ext/class/attribute.rb +67 -0
  29. data/lib/active_support/core_ext/class/attribute_accessors.rb +33 -27
  30. data/lib/active_support/core_ext/class/delegating_attributes.rb +35 -41
  31. data/lib/active_support/core_ext/class/inheritable_attributes.rb +23 -14
  32. data/lib/active_support/core_ext/class/subclasses.rb +50 -0
  33. data/lib/active_support/core_ext/date/calculations.rb +35 -12
  34. data/lib/active_support/core_ext/date/conversions.rb +5 -5
  35. data/lib/active_support/core_ext/date/zones.rb +14 -0
  36. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +24 -5
  38. data/lib/active_support/core_ext/date_time/zones.rb +4 -0
  39. data/lib/active_support/core_ext/enumerable.rb +5 -9
  40. data/lib/active_support/core_ext/exception.rb +0 -47
  41. data/lib/active_support/core_ext/file.rb +1 -0
  42. data/lib/active_support/core_ext/file/atomic.rb +3 -2
  43. data/lib/active_support/core_ext/file/path.rb +5 -0
  44. data/lib/active_support/core_ext/float/rounding.rb +3 -2
  45. data/lib/active_support/core_ext/hash/conversions.rb +65 -145
  46. data/lib/active_support/core_ext/hash/deep_merge.rb +6 -7
  47. data/lib/active_support/core_ext/hash/except.rb +8 -1
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -0
  49. data/lib/active_support/core_ext/hash/keys.rb +10 -11
  50. data/lib/active_support/core_ext/hash/slice.rb +6 -0
  51. data/lib/active_support/core_ext/integer.rb +1 -1
  52. data/lib/active_support/core_ext/integer/multiple.rb +6 -0
  53. data/lib/active_support/core_ext/kernel.rb +1 -1
  54. data/lib/active_support/core_ext/kernel/debugger.rb +3 -2
  55. data/lib/active_support/core_ext/kernel/reporting.rb +2 -1
  56. data/lib/active_support/core_ext/kernel/requires.rb +2 -2
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
  58. data/lib/active_support/core_ext/load_error.rb +17 -30
  59. data/lib/active_support/core_ext/logger.rb +2 -40
  60. data/lib/active_support/core_ext/module.rb +5 -3
  61. data/lib/active_support/core_ext/module/aliasing.rb +1 -1
  62. data/lib/active_support/core_ext/module/anonymous.rb +24 -0
  63. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +1 -1
  64. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  65. data/lib/active_support/core_ext/module/attribute_accessors.rb +20 -22
  66. data/lib/active_support/core_ext/module/delegation.rb +21 -10
  67. data/lib/active_support/core_ext/module/introspection.rb +8 -8
  68. data/lib/active_support/core_ext/module/method_names.rb +14 -0
  69. data/lib/active_support/core_ext/module/reachable.rb +10 -0
  70. data/lib/active_support/core_ext/module/remove_method.rb +11 -0
  71. data/lib/active_support/core_ext/module/synchronization.rb +2 -1
  72. data/lib/active_support/core_ext/name_error.rb +3 -1
  73. data/lib/active_support/core_ext/object.rb +5 -3
  74. data/lib/active_support/core_ext/object/blank.rb +20 -2
  75. data/lib/active_support/core_ext/object/conversions.rb +2 -16
  76. data/lib/active_support/core_ext/object/duplicable.rb +23 -1
  77. data/lib/active_support/core_ext/object/instance_variables.rb +0 -7
  78. data/lib/active_support/core_ext/object/to_json.rb +19 -0
  79. data/lib/active_support/core_ext/object/to_param.rb +49 -0
  80. data/lib/active_support/core_ext/object/to_query.rb +27 -0
  81. data/lib/active_support/core_ext/object/with_options.rb +2 -0
  82. data/lib/active_support/core_ext/proc.rb +4 -4
  83. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  84. data/lib/active_support/core_ext/regexp.rb +0 -22
  85. data/lib/active_support/core_ext/rexml.rb +4 -1
  86. data/lib/active_support/core_ext/string.rb +3 -2
  87. data/lib/active_support/core_ext/string/access.rb +4 -2
  88. data/lib/active_support/core_ext/string/conversions.rb +28 -1
  89. data/lib/active_support/core_ext/string/encoding.rb +11 -0
  90. data/lib/active_support/core_ext/string/exclude.rb +6 -0
  91. data/lib/active_support/core_ext/string/filters.rb +29 -0
  92. data/lib/active_support/core_ext/string/inflections.rb +12 -12
  93. data/lib/active_support/core_ext/string/interpolation.rb +2 -92
  94. data/lib/active_support/core_ext/string/multibyte.rb +16 -19
  95. data/lib/active_support/core_ext/string/output_safety.rb +101 -35
  96. data/lib/active_support/core_ext/string/starts_ends_with.rb +0 -14
  97. data/lib/active_support/core_ext/string/xchar.rb +1 -1
  98. data/lib/active_support/core_ext/time/calculations.rb +14 -7
  99. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  100. data/lib/active_support/core_ext/time/marshal.rb +56 -0
  101. data/lib/active_support/core_ext/time/zones.rb +2 -5
  102. data/lib/active_support/core_ext/uri.rb +10 -4
  103. data/lib/active_support/dependencies.rb +200 -197
  104. data/lib/active_support/dependencies/autoload.rb +50 -0
  105. data/lib/active_support/deprecation/behaviors.rb +13 -9
  106. data/lib/active_support/deprecation/method_wrappers.rb +10 -9
  107. data/lib/active_support/deprecation/proxy_wrappers.rb +7 -0
  108. data/lib/active_support/deprecation/reporting.rb +5 -3
  109. data/lib/active_support/descendants_tracker.rb +43 -0
  110. data/lib/active_support/duration.rb +8 -4
  111. data/lib/active_support/file_update_checker.rb +36 -0
  112. data/lib/active_support/hash_with_indifferent_access.rb +9 -1
  113. data/lib/active_support/i18n.rb +9 -0
  114. data/lib/active_support/i18n_railtie.rb +81 -0
  115. data/lib/active_support/inflections.rb +1 -1
  116. data/lib/active_support/inflector.rb +4 -407
  117. data/lib/active_support/inflector/inflections.rb +211 -0
  118. data/lib/active_support/inflector/methods.rb +151 -0
  119. data/lib/active_support/inflector/transliterate.rb +97 -0
  120. data/lib/active_support/json/backends/jsongem.rb +12 -9
  121. data/lib/active_support/json/backends/yajl.rb +40 -0
  122. data/lib/active_support/json/backends/yaml.rb +1 -1
  123. data/lib/active_support/json/decoding.rb +17 -2
  124. data/lib/active_support/json/encoding.rb +48 -31
  125. data/lib/active_support/json/variable.rb +2 -4
  126. data/lib/active_support/lazy_load_hooks.rb +27 -0
  127. data/lib/active_support/locale/en.yml +5 -2
  128. data/lib/active_support/log_subscriber.rb +123 -0
  129. data/lib/active_support/log_subscriber/test_helper.rb +99 -0
  130. data/lib/active_support/memoizable.rb +1 -1
  131. data/lib/active_support/message_encryptor.rb +1 -0
  132. data/lib/active_support/message_verifier.rb +2 -1
  133. data/lib/active_support/multibyte.rb +8 -23
  134. data/lib/active_support/multibyte/chars.rb +213 -446
  135. data/lib/active_support/multibyte/unicode.rb +392 -0
  136. data/lib/active_support/multibyte/utils.rb +6 -7
  137. data/lib/active_support/notifications.rb +29 -122
  138. data/lib/active_support/notifications/fanout.rb +61 -0
  139. data/lib/active_support/notifications/instrumenter.rb +54 -0
  140. data/lib/active_support/ordered_hash.rb +59 -14
  141. data/lib/active_support/ordered_options.rb +6 -0
  142. data/lib/active_support/railtie.rb +60 -0
  143. data/lib/active_support/rescuable.rb +7 -4
  144. data/lib/active_support/ruby/shim.rb +4 -6
  145. data/lib/active_support/test_case.rb +2 -7
  146. data/lib/active_support/testing/assertions.rb +15 -0
  147. data/lib/active_support/testing/declarative.rb +1 -1
  148. data/lib/active_support/testing/isolation.rb +64 -17
  149. data/lib/active_support/testing/performance.rb +306 -335
  150. data/lib/active_support/testing/setup_and_teardown.rb +51 -29
  151. data/lib/active_support/time.rb +24 -3
  152. data/lib/active_support/time_with_zone.rb +10 -14
  153. data/lib/active_support/values/time_zone.rb +192 -234
  154. data/lib/active_support/values/unicode_tables.dat +0 -0
  155. data/lib/active_support/version.rb +3 -2
  156. data/lib/active_support/whiny_nil.rb +9 -7
  157. data/lib/active_support/xml_mini.rb +130 -1
  158. data/lib/active_support/xml_mini/jdom.rb +2 -0
  159. data/lib/active_support/xml_mini/libxml.rb +23 -86
  160. data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
  161. data/lib/active_support/xml_mini/nokogiri.rb +27 -24
  162. data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
  163. data/lib/active_support/xml_mini/rexml.rb +8 -2
  164. metadata +62 -195
  165. data/README +0 -43
  166. data/lib/active_support/autoload.rb +0 -28
  167. data/lib/active_support/core_ext/boolean.rb +0 -1
  168. data/lib/active_support/core_ext/boolean/conversions.rb +0 -11
  169. data/lib/active_support/core_ext/class/removal.rb +0 -53
  170. data/lib/active_support/core_ext/date.rb +0 -7
  171. data/lib/active_support/core_ext/date_time.rb +0 -5
  172. data/lib/active_support/core_ext/integer/even_odd.rb +0 -16
  173. data/lib/active_support/core_ext/kernel/daemonizing.rb +0 -7
  174. data/lib/active_support/core_ext/module/inclusion.rb +0 -30
  175. data/lib/active_support/core_ext/module/loading.rb +0 -23
  176. data/lib/active_support/core_ext/nil.rb +0 -1
  177. data/lib/active_support/core_ext/nil/conversions.rb +0 -5
  178. data/lib/active_support/core_ext/object/extending.rb +0 -80
  179. data/lib/active_support/core_ext/object/metaclass.rb +0 -13
  180. data/lib/active_support/core_ext/object/misc.rb +0 -3
  181. data/lib/active_support/core_ext/object/returning.rb +0 -42
  182. data/lib/active_support/core_ext/object/tap.rb +0 -16
  183. data/lib/active_support/core_ext/string/bytesize.rb +0 -5
  184. data/lib/active_support/core_ext/string/iterators.rb +0 -13
  185. data/lib/active_support/core_ext/symbol.rb +0 -1
  186. data/lib/active_support/core_ext/symbol/to_proc.rb +0 -14
  187. data/lib/active_support/core_ext/time.rb +0 -10
  188. data/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +0 -22
  189. data/lib/active_support/deprecated_callbacks.rb +0 -283
  190. data/lib/active_support/multibyte/unicode_database.rb +0 -71
  191. data/lib/active_support/vendor.rb +0 -16
  192. data/lib/active_support/vendor/builder-2.1.2/lib/blankslate.rb +0 -113
  193. data/lib/active_support/vendor/builder-2.1.2/lib/builder.rb +0 -13
  194. data/lib/active_support/vendor/builder-2.1.2/lib/builder/blankslate.rb +0 -20
  195. data/lib/active_support/vendor/builder-2.1.2/lib/builder/css.rb +0 -250
  196. data/lib/active_support/vendor/builder-2.1.2/lib/builder/xchar.rb +0 -115
  197. data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlbase.rb +0 -139
  198. data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlevents.rb +0 -63
  199. data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlmarkup.rb +0 -328
  200. data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +0 -20
  201. data/lib/active_support/vendor/i18n-0.1.3/README.textile +0 -20
  202. data/lib/active_support/vendor/i18n-0.1.3/Rakefile +0 -5
  203. data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +0 -27
  204. data/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb +0 -204
  205. data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb +0 -215
  206. data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb +0 -53
  207. data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +0 -5
  208. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +0 -99
  209. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +0 -124
  210. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +0 -1
  211. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +0 -3
  212. data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +0 -567
  213. data/lib/active_support/vendor/memcache-client-1.7.5/lib/memcache.rb +0 -1133
  214. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo.rb +0 -33
  215. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone.rb +0 -47
  216. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone_info.rb +0 -228
  217. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Algiers.rb +0 -55
  218. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Cairo.rb +0 -219
  219. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Casablanca.rb +0 -42
  220. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Harare.rb +0 -18
  221. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Johannesburg.rb +0 -25
  222. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Monrovia.rb +0 -22
  223. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Nairobi.rb +0 -23
  224. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +0 -166
  225. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/San_Juan.rb +0 -86
  226. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Bogota.rb +0 -23
  227. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Caracas.rb +0 -23
  228. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chicago.rb +0 -283
  229. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chihuahua.rb +0 -136
  230. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Denver.rb +0 -204
  231. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Godthab.rb +0 -161
  232. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Guatemala.rb +0 -27
  233. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Halifax.rb +0 -274
  234. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Indiana/Indianapolis.rb +0 -149
  235. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Juneau.rb +0 -194
  236. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/La_Paz.rb +0 -22
  237. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Lima.rb +0 -35
  238. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Los_Angeles.rb +0 -232
  239. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mazatlan.rb +0 -139
  240. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mexico_City.rb +0 -144
  241. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Monterrey.rb +0 -131
  242. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/New_York.rb +0 -282
  243. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Phoenix.rb +0 -30
  244. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Regina.rb +0 -74
  245. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Santiago.rb +0 -205
  246. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Sao_Paulo.rb +0 -171
  247. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/St_Johns.rb +0 -288
  248. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Tijuana.rb +0 -196
  249. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Almaty.rb +0 -67
  250. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baghdad.rb +0 -73
  251. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baku.rb +0 -161
  252. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Bangkok.rb +0 -20
  253. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Chongqing.rb +0 -33
  254. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Colombo.rb +0 -30
  255. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Dhaka.rb +0 -27
  256. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Hong_Kong.rb +0 -87
  257. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Irkutsk.rb +0 -165
  258. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jakarta.rb +0 -30
  259. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jerusalem.rb +0 -163
  260. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kabul.rb +0 -20
  261. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kamchatka.rb +0 -163
  262. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Karachi.rb +0 -32
  263. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kathmandu.rb +0 -20
  264. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kolkata.rb +0 -25
  265. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Krasnoyarsk.rb +0 -163
  266. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuala_Lumpur.rb +0 -31
  267. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuwait.rb +0 -18
  268. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Magadan.rb +0 -163
  269. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Muscat.rb +0 -18
  270. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Novosibirsk.rb +0 -164
  271. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Rangoon.rb +0 -24
  272. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Riyadh.rb +0 -18
  273. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Seoul.rb +0 -34
  274. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Shanghai.rb +0 -35
  275. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Singapore.rb +0 -33
  276. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Taipei.rb +0 -59
  277. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tashkent.rb +0 -47
  278. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tbilisi.rb +0 -78
  279. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tehran.rb +0 -121
  280. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tokyo.rb +0 -30
  281. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Ulaanbaatar.rb +0 -65
  282. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Urumqi.rb +0 -33
  283. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Vladivostok.rb +0 -164
  284. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yakutsk.rb +0 -163
  285. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yekaterinburg.rb +0 -165
  286. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yerevan.rb +0 -165
  287. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Azores.rb +0 -270
  288. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Cape_Verde.rb +0 -23
  289. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/South_Georgia.rb +0 -18
  290. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Adelaide.rb +0 -187
  291. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Brisbane.rb +0 -35
  292. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Darwin.rb +0 -29
  293. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Hobart.rb +0 -193
  294. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Melbourne.rb +0 -185
  295. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Perth.rb +0 -37
  296. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Sydney.rb +0 -185
  297. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Etc/UTC.rb +0 -16
  298. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Amsterdam.rb +0 -228
  299. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Athens.rb +0 -185
  300. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Belgrade.rb +0 -163
  301. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Berlin.rb +0 -188
  302. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bratislava.rb +0 -13
  303. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Brussels.rb +0 -232
  304. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bucharest.rb +0 -181
  305. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Budapest.rb +0 -197
  306. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Copenhagen.rb +0 -179
  307. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Dublin.rb +0 -276
  308. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Helsinki.rb +0 -163
  309. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Istanbul.rb +0 -218
  310. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Kiev.rb +0 -168
  311. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Lisbon.rb +0 -268
  312. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Ljubljana.rb +0 -13
  313. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/London.rb +0 -288
  314. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Madrid.rb +0 -211
  315. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Minsk.rb +0 -170
  316. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Moscow.rb +0 -181
  317. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Paris.rb +0 -232
  318. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Prague.rb +0 -187
  319. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Riga.rb +0 -176
  320. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Rome.rb +0 -215
  321. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sarajevo.rb +0 -13
  322. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Skopje.rb +0 -13
  323. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sofia.rb +0 -173
  324. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Stockholm.rb +0 -165
  325. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Tallinn.rb +0 -172
  326. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vienna.rb +0 -183
  327. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vilnius.rb +0 -170
  328. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Warsaw.rb +0 -212
  329. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Zagreb.rb +0 -13
  330. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Auckland.rb +0 -202
  331. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Fiji.rb +0 -23
  332. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Guam.rb +0 -22
  333. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Honolulu.rb +0 -28
  334. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Majuro.rb +0 -20
  335. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Midway.rb +0 -25
  336. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Noumea.rb +0 -25
  337. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Pago_Pago.rb +0 -26
  338. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Port_Moresby.rb +0 -20
  339. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Tongatapu.rb +0 -27
  340. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/info_timezone.rb +0 -52
  341. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone.rb +0 -51
  342. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone_info.rb +0 -44
  343. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/offset_rationals.rb +0 -98
  344. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/ruby_core_support.rb +0 -56
  345. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/time_or_datetime.rb +0 -292
  346. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone.rb +0 -508
  347. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_definition.rb +0 -56
  348. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_info.rb +0 -40
  349. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_offset_info.rb +0 -94
  350. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_period.rb +0 -198
  351. data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_transition_info.rb +0 -129
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/object/metaclass'
1
+ require 'active_support/core_ext/kernel/singleton_class'
2
2
  require 'active_support/core_ext/module/aliasing'
3
3
 
4
4
  module ActiveSupport
@@ -1,4 +1,5 @@
1
1
  require 'openssl'
2
+ require 'active_support/base64'
2
3
 
3
4
  module ActiveSupport
4
5
  # MessageEncryptor is a simple way to encrypt values which get stored somewhere
@@ -1,4 +1,5 @@
1
- require 'active_support/core_ext/string/bytesize'
1
+ require 'active_support/base64'
2
+ require 'active_support/core_ext/object/blank'
2
3
 
3
4
  module ActiveSupport
4
5
  # MessageVerifier makes it easy to generate and verify messages which are signed
@@ -1,24 +1,12 @@
1
1
  # encoding: utf-8
2
-
3
2
  require 'active_support/core_ext/module/attribute_accessors'
4
3
 
5
4
  module ActiveSupport #:nodoc:
6
5
  module Multibyte
7
- # A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more
8
- # information about normalization.
9
- NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
10
-
11
- # The Unicode version that is supported by the implementation
12
- UNICODE_VERSION = '5.1.0'
13
-
14
- # The default normalization used for operations that require normalization. It can be set to any of the
15
- # normalizations in NORMALIZATION_FORMS.
16
- #
17
- # Example:
18
- # ActiveSupport::Multibyte.default_normalization_form = :c
19
- mattr_accessor :default_normalization_form
20
- self.default_normalization_form = :kc
21
-
6
+ autoload :EncodingError, 'active_support/multibyte/exceptions'
7
+ autoload :Chars, 'active_support/multibyte/chars'
8
+ autoload :Unicode, 'active_support/multibyte/unicode'
9
+
22
10
  # The proxy class returned when calling mb_chars. You can use this accessor to configure your own proxy
23
11
  # class so you can support other encodings. See the ActiveSupport::Multibyte::Chars implementation for
24
12
  # an example how to do this.
@@ -29,7 +17,7 @@ module ActiveSupport #:nodoc:
29
17
  @proxy_class = klass
30
18
  end
31
19
 
32
- # Returns the currect proxy class
20
+ # Returns the current proxy class
33
21
  def self.proxy_class
34
22
  @proxy_class ||= ActiveSupport::Multibyte::Chars
35
23
  end
@@ -47,13 +35,10 @@ module ActiveSupport #:nodoc:
47
35
  \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn,
48
36
  # Quick check for valid Shift-JIS characters, disregards the odd-even pairing
49
37
  'Shift_JIS' => /\A(?:
50
- [\x00-\x7e \xa1-\xdf] |
51
- [\x81-\x9f \xe0-\xef] [\x40-\x7e \x80-\x9e \x9f-\xfc])\z /xn
38
+ [\x00-\x7e\xa1-\xdf] |
39
+ [\x81-\x9f\xe0-\xef] [\x40-\x7e\x80-\x9e\x9f-\xfc])\z /xn
52
40
  }
53
41
  end
54
42
  end
55
43
 
56
- require 'active_support/multibyte/chars'
57
- require 'active_support/multibyte/exceptions'
58
- require 'active_support/multibyte/unicode_database'
59
- require 'active_support/multibyte/utils'
44
+ require 'active_support/multibyte/utils'
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require 'active_support/core_ext/string/access'
2
3
  require 'active_support/core_ext/string/behavior'
3
4
 
4
5
  module ActiveSupport #:nodoc:
@@ -18,7 +19,7 @@ module ActiveSupport #:nodoc:
18
19
  # bad.explicit_checking_method "T".mb_chars.downcase.to_s
19
20
  #
20
21
  # The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different
21
- # encodings you can write your own multibyte string handler and configure it through
22
+ # encodings you can write your own multibyte string handler and configure it through
22
23
  # ActiveSupport::Multibyte.proxy_class.
23
24
  #
24
25
  # class CharsForUTF32
@@ -33,54 +34,11 @@ module ActiveSupport #:nodoc:
33
34
  #
34
35
  # ActiveSupport::Multibyte.proxy_class = CharsForUTF32
35
36
  class Chars
36
- # Hangul character boundaries and properties
37
- HANGUL_SBASE = 0xAC00
38
- HANGUL_LBASE = 0x1100
39
- HANGUL_VBASE = 0x1161
40
- HANGUL_TBASE = 0x11A7
41
- HANGUL_LCOUNT = 19
42
- HANGUL_VCOUNT = 21
43
- HANGUL_TCOUNT = 28
44
- HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
45
- HANGUL_SCOUNT = 11172
46
- HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
47
- HANGUL_JAMO_FIRST = 0x1100
48
- HANGUL_JAMO_LAST = 0x11FF
49
-
50
- # All the unicode whitespace
51
- UNICODE_WHITESPACE = [
52
- (0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
53
- 0x0020, # White_Space # Zs SPACE
54
- 0x0085, # White_Space # Cc <control-0085>
55
- 0x00A0, # White_Space # Zs NO-BREAK SPACE
56
- 0x1680, # White_Space # Zs OGHAM SPACE MARK
57
- 0x180E, # White_Space # Zs MONGOLIAN VOWEL SEPARATOR
58
- (0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
59
- 0x2028, # White_Space # Zl LINE SEPARATOR
60
- 0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
61
- 0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
62
- 0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
63
- 0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
64
- ].flatten.freeze
65
-
66
- # BOM (byte order mark) can also be seen as whitespace, it's a non-rendering character used to distinguish
67
- # between little and big endian. This is not an issue in utf-8, so it must be ignored.
68
- UNICODE_LEADERS_AND_TRAILERS = UNICODE_WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
69
-
70
- # Returns a regular expression pattern that matches the passed Unicode codepoints
71
- def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
72
- array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
73
- end
74
- UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/
75
- UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/
76
-
77
- UTF8_PAT = ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8']
78
-
79
37
  attr_reader :wrapped_string
80
38
  alias to_s wrapped_string
81
39
  alias to_str wrapped_string
82
40
 
83
- if '1.9'.respond_to?(:force_encoding)
41
+ if RUBY_VERSION >= "1.9"
84
42
  # Creates a new Chars instance by wrapping _string_.
85
43
  def initialize(string)
86
44
  @wrapped_string = string
@@ -114,12 +72,6 @@ module ActiveSupport #:nodoc:
114
72
  true
115
73
  end
116
74
 
117
- # Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
118
- # +false+ otherwise.
119
- def self.wants?(string)
120
- $KCODE == 'UTF8' && consumes?(string)
121
- end
122
-
123
75
  # Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise.
124
76
  def self.consumes?(string)
125
77
  # Unpack is a little bit faster than regular expressions.
@@ -141,79 +93,160 @@ module ActiveSupport #:nodoc:
141
93
  @wrapped_string <=> other.to_s
142
94
  end
143
95
 
144
- # Returns a new Chars object containing the _other_ object concatenated to the string.
145
- #
146
- # Example:
147
- # ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
148
- def +(other)
149
- self << other
150
- end
96
+ if RUBY_VERSION < "1.9"
97
+ # Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
98
+ # +false+ otherwise.
99
+ def self.wants?(string)
100
+ $KCODE == 'UTF8' && consumes?(string)
101
+ end
151
102
 
152
- # Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
153
- #
154
- # Example:
155
- # 'Café périferôl'.mb_chars =~ /ô/ #=> 12
156
- def =~(other)
157
- translate_offset(@wrapped_string =~ other)
158
- end
103
+ # Returns a new Chars object containing the _other_ object concatenated to the string.
104
+ #
105
+ # Example:
106
+ # ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
107
+ def +(other)
108
+ chars(@wrapped_string + other)
109
+ end
159
110
 
160
- # Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars
161
- # instances instead of String. This makes chaining methods easier.
162
- #
163
- # Example:
164
- # 'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } #=> ["CAF", " P", "RIFERÔL"]
165
- def split(*args)
166
- @wrapped_string.split(*args).map { |i| i.mb_chars }
167
- end
111
+ # Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
112
+ #
113
+ # Example:
114
+ # 'Café périferôl'.mb_chars =~ /ô/ #=> 12
115
+ def =~(other)
116
+ translate_offset(@wrapped_string =~ other)
117
+ end
168
118
 
169
- # Inserts the passed string at specified codepoint offsets.
170
- #
171
- # Example:
172
- # 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
173
- def insert(offset, fragment)
174
- unpacked = self.class.u_unpack(@wrapped_string)
175
- unless offset > unpacked.length
176
- @wrapped_string.replace(
177
- self.class.u_unpack(@wrapped_string).insert(offset, *self.class.u_unpack(fragment)).pack('U*')
178
- )
179
- else
180
- raise IndexError, "index #{offset} out of string"
119
+ # Inserts the passed string at specified codepoint offsets.
120
+ #
121
+ # Example:
122
+ # 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
123
+ def insert(offset, fragment)
124
+ unpacked = Unicode.u_unpack(@wrapped_string)
125
+ unless offset > unpacked.length
126
+ @wrapped_string.replace(
127
+ Unicode.u_unpack(@wrapped_string).insert(offset, *Unicode.u_unpack(fragment)).pack('U*')
128
+ )
129
+ else
130
+ raise IndexError, "index #{offset} out of string"
131
+ end
132
+ self
181
133
  end
182
- self
183
- end
184
134
 
185
- # Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
186
- #
187
- # Example:
188
- # 'Café'.mb_chars.include?('é') #=> true
189
- def include?(other)
190
- # We have to redefine this method because Enumerable defines it.
191
- @wrapped_string.include?(other)
192
- end
135
+ # Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
136
+ #
137
+ # Example:
138
+ # 'Café'.mb_chars.include?('é') #=> true
139
+ def include?(other)
140
+ # We have to redefine this method because Enumerable defines it.
141
+ @wrapped_string.include?(other)
142
+ end
193
143
 
194
- # Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
195
- #
196
- # Example:
197
- # 'Café périferôl'.mb_chars.index('ô') #=> 12
198
- # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
199
- def index(needle, offset=0)
200
- wrapped_offset = self.first(offset).wrapped_string.length
201
- index = @wrapped_string.index(needle, wrapped_offset)
202
- index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
144
+ # Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
145
+ #
146
+ # Example:
147
+ # 'Café périferôl'.mb_chars.index('ô') #=> 12
148
+ # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
149
+ def index(needle, offset=0)
150
+ wrapped_offset = first(offset).wrapped_string.length
151
+ index = @wrapped_string.index(needle, wrapped_offset)
152
+ index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
153
+ end
154
+
155
+ # Returns the position _needle_ in the string, counting in
156
+ # codepoints, searching backward from _offset_ or the end of the
157
+ # string. Returns +nil+ if _needle_ isn't found.
158
+ #
159
+ # Example:
160
+ # 'Café périferôl'.mb_chars.rindex('é') #=> 6
161
+ # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
162
+ def rindex(needle, offset=nil)
163
+ offset ||= length
164
+ wrapped_offset = first(offset).wrapped_string.length
165
+ index = @wrapped_string.rindex(needle, wrapped_offset)
166
+ index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
167
+ end
168
+
169
+ # Returns the number of codepoints in the string
170
+ def size
171
+ Unicode.u_unpack(@wrapped_string).size
172
+ end
173
+ alias_method :length, :size
174
+
175
+ # Strips entire range of Unicode whitespace from the right of the string.
176
+ def rstrip
177
+ chars(@wrapped_string.gsub(Unicode::TRAILERS_PAT, ''))
178
+ end
179
+
180
+ # Strips entire range of Unicode whitespace from the left of the string.
181
+ def lstrip
182
+ chars(@wrapped_string.gsub(Unicode::LEADERS_PAT, ''))
183
+ end
184
+
185
+ # Strips entire range of Unicode whitespace from the right and left of the string.
186
+ def strip
187
+ rstrip.lstrip
188
+ end
189
+
190
+ # Returns the codepoint of the first character in the string.
191
+ #
192
+ # Example:
193
+ # 'こんにちは'.mb_chars.ord #=> 12371
194
+ def ord
195
+ Unicode.u_unpack(@wrapped_string)[0]
196
+ end
197
+
198
+ # Works just like <tt>String#rjust</tt>, only integer specifies characters instead of bytes.
199
+ #
200
+ # Example:
201
+ #
202
+ # "¾ cup".mb_chars.rjust(8).to_s
203
+ # #=> " ¾ cup"
204
+ #
205
+ # "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
206
+ # #=> "   ¾ cup"
207
+ def rjust(integer, padstr=' ')
208
+ justify(integer, :right, padstr)
209
+ end
210
+
211
+ # Works just like <tt>String#ljust</tt>, only integer specifies characters instead of bytes.
212
+ #
213
+ # Example:
214
+ #
215
+ # "¾ cup".mb_chars.rjust(8).to_s
216
+ # #=> "¾ cup "
217
+ #
218
+ # "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
219
+ # #=> "¾ cup   "
220
+ def ljust(integer, padstr=' ')
221
+ justify(integer, :left, padstr)
222
+ end
223
+
224
+ # Works just like <tt>String#center</tt>, only integer specifies characters instead of bytes.
225
+ #
226
+ # Example:
227
+ #
228
+ # "¾ cup".mb_chars.center(8).to_s
229
+ # #=> " ¾ cup "
230
+ #
231
+ # "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
232
+ # #=> " ¾ cup  "
233
+ def center(integer, padstr=' ')
234
+ justify(integer, :center, padstr)
235
+ end
236
+
237
+ else
238
+ def =~(other)
239
+ @wrapped_string =~ other
240
+ end
203
241
  end
204
242
 
205
- # Returns the position _needle_ in the string, counting in
206
- # codepoints, searching backward from _offset_ or the end of the
207
- # string. Returns +nil+ if _needle_ isn't found.
243
+ # Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars
244
+ # instances instead of String. This makes chaining methods easier.
208
245
  #
209
246
  # Example:
210
- # 'Café périferôl'.mb_chars.rindex('é') #=> 6
211
- # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
212
- def rindex(needle, offset=nil)
213
- offset ||= length
214
- wrapped_offset = self.first(offset).wrapped_string.length
215
- index = @wrapped_string.rindex(needle, wrapped_offset)
216
- index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
247
+ # 'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } #=> ["CAF", " P", "RIFERÔL"]
248
+ def split(*args)
249
+ @wrapped_string.split(*args).map { |i| i.mb_chars }
217
250
  end
218
251
 
219
252
  # Like <tt>String#[]=</tt>, except instead of byte offsets you specify character offsets.
@@ -235,7 +268,7 @@ module ActiveSupport #:nodoc:
235
268
  if args.first.is_a?(Regexp)
236
269
  @wrapped_string[*args] = replace_by
237
270
  else
238
- result = self.class.u_unpack(@wrapped_string)
271
+ result = Unicode.u_unpack(@wrapped_string)
239
272
  if args[0].is_a?(Fixnum)
240
273
  raise IndexError, "index #{args[0]} out of string" if args[0] >= result.length
241
274
  min = args[0]
@@ -248,80 +281,20 @@ module ActiveSupport #:nodoc:
248
281
  else
249
282
  needle = args[0].to_s
250
283
  min = index(needle)
251
- max = min + self.class.u_unpack(needle).length - 1
284
+ max = min + Unicode.u_unpack(needle).length - 1
252
285
  range = Range.new(min, max)
253
286
  end
254
- result[range] = self.class.u_unpack(replace_by)
287
+ result[range] = Unicode.u_unpack(replace_by)
255
288
  @wrapped_string.replace(result.pack('U*'))
256
289
  end
257
290
  end
258
291
 
259
- # Works just like <tt>String#rjust</tt>, only integer specifies characters instead of bytes.
260
- #
261
- # Example:
262
- #
263
- # "¾ cup".mb_chars.rjust(8).to_s
264
- # #=> " ¾ cup"
265
- #
266
- # "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
267
- # #=> "   ¾ cup"
268
- def rjust(integer, padstr=' ')
269
- justify(integer, :right, padstr)
270
- end
271
-
272
- # Works just like <tt>String#ljust</tt>, only integer specifies characters instead of bytes.
273
- #
274
- # Example:
275
- #
276
- # "¾ cup".mb_chars.rjust(8).to_s
277
- # #=> "¾ cup "
278
- #
279
- # "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
280
- # #=> "¾ cup   "
281
- def ljust(integer, padstr=' ')
282
- justify(integer, :left, padstr)
283
- end
284
-
285
- # Works just like <tt>String#center</tt>, only integer specifies characters instead of bytes.
286
- #
287
- # Example:
288
- #
289
- # "¾ cup".mb_chars.center(8).to_s
290
- # #=> " ¾ cup "
291
- #
292
- # "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
293
- # #=> " ¾ cup  "
294
- def center(integer, padstr=' ')
295
- justify(integer, :center, padstr)
296
- end
297
-
298
- # Strips entire range of Unicode whitespace from the right of the string.
299
- def rstrip
300
- chars(@wrapped_string.gsub(UNICODE_TRAILERS_PAT, ''))
301
- end
302
-
303
- # Strips entire range of Unicode whitespace from the left of the string.
304
- def lstrip
305
- chars(@wrapped_string.gsub(UNICODE_LEADERS_PAT, ''))
306
- end
307
-
308
- # Strips entire range of Unicode whitespace from the right and left of the string.
309
- def strip
310
- rstrip.lstrip
311
- end
312
-
313
- # Returns the number of codepoints in the string
314
- def size
315
- self.class.u_unpack(@wrapped_string).size
316
- end
317
- alias_method :length, :size
318
-
319
292
  # Reverses all characters in the string.
320
293
  #
321
294
  # Example:
322
295
  # 'Café'.mb_chars.reverse.to_s #=> 'éfaC'
323
296
  def reverse
324
- chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*'))
297
+ chars(Unicode.g_unpack(@wrapped_string).reverse.flatten.pack('U*'))
325
298
  end
326
299
 
327
300
  # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
@@ -337,46 +310,37 @@ module ActiveSupport #:nodoc:
337
310
  elsif (args.size == 2 && !args[1].is_a?(Numeric))
338
311
  raise TypeError, "cannot convert #{args[1].class} into Integer" # Do as if we were native
339
312
  elsif args[0].kind_of? Range
340
- cps = self.class.u_unpack(@wrapped_string).slice(*args)
313
+ cps = Unicode.u_unpack(@wrapped_string).slice(*args)
341
314
  result = cps.nil? ? nil : cps.pack('U*')
342
315
  elsif args[0].kind_of? Regexp
343
316
  result = @wrapped_string.slice(*args)
344
317
  elsif args.size == 1 && args[0].kind_of?(Numeric)
345
- character = self.class.u_unpack(@wrapped_string)[args[0]]
346
- result = character.nil? ? nil : [character].pack('U')
318
+ character = Unicode.u_unpack(@wrapped_string)[args[0]]
319
+ result = character && [character].pack('U')
347
320
  else
348
- result = self.class.u_unpack(@wrapped_string).slice(*args).pack('U*')
321
+ cps = Unicode.u_unpack(@wrapped_string).slice(*args)
322
+ result = cps && cps.pack('U*')
349
323
  end
350
- result.nil? ? nil : chars(result)
324
+ result && chars(result)
351
325
  end
352
326
  alias_method :[], :slice
353
327
 
354
- # Like <tt>String#slice!</tt>, except instead of byte offsets you specify character offsets.
328
+ # Limit the byte size of the string to a number of bytes without breaking characters. Usable
329
+ # when the storage for a string is limited for some reason.
355
330
  #
356
331
  # Example:
357
332
  # s = 'こんにちは'
358
- # s.mb_chars.slice!(2..3).to_s #=> "にち"
359
- # s #=> "こんは"
360
- def slice!(*args)
361
- slice = self[*args]
362
- self[*args] = ''
363
- slice
364
- end
365
-
366
- # Returns the codepoint of the first character in the string.
367
- #
368
- # Example:
369
- # 'こんにちは'.mb_chars.ord #=> 12371
370
- def ord
371
- self.class.u_unpack(@wrapped_string)[0]
333
+ # s.mb_chars.limit(7) #=> "こに"
334
+ def limit(limit)
335
+ slice(0...translate_offset(limit))
372
336
  end
373
337
 
374
338
  # Convert characters in the string to uppercase.
375
339
  #
376
340
  # Example:
377
- # 'Laurent, òu sont les tests?'.mb_chars.upcase.to_s #=> "LAURENT, ÒU SONT LES TESTS?"
341
+ # 'Laurent, sont les tests ?'.mb_chars.upcase.to_s #=> "LAURENT, SONT LES TESTS ?"
378
342
  def upcase
379
- apply_mapping :uppercase_mapping
343
+ chars(Unicode.apply_mapping @wrapped_string, :uppercase_mapping)
380
344
  end
381
345
 
382
346
  # Convert characters in the string to lowercase.
@@ -384,7 +348,7 @@ module ActiveSupport #:nodoc:
384
348
  # Example:
385
349
  # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s #=> "věda a výzkum"
386
350
  def downcase
387
- apply_mapping :lowercase_mapping
351
+ chars(Unicode.apply_mapping @wrapped_string, :lowercase_mapping)
388
352
  end
389
353
 
390
354
  # Converts the first character to uppercase and the remainder to lowercase.
@@ -395,28 +359,24 @@ module ActiveSupport #:nodoc:
395
359
  (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
396
360
  end
397
361
 
362
+ # Capitalizes the first letter of every word, when possible.
363
+ #
364
+ # Example:
365
+ # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
366
+ # "日本語".mb_chars.titleize # => "日本語"
367
+ def titleize
368
+ chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.apply_mapping $1, :uppercase_mapping })
369
+ end
370
+ alias_method :titlecase, :titleize
371
+
398
372
  # Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
399
373
  # passing strings to databases and validations.
400
374
  #
401
- # * <tt>str</tt> - The string to perform normalization on.
402
375
  # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
403
376
  # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
404
- # ActiveSupport::Multibyte.default_normalization_form
405
- def normalize(form=ActiveSupport::Multibyte.default_normalization_form)
406
- # See http://www.unicode.org/reports/tr15, Table 1
407
- codepoints = self.class.u_unpack(@wrapped_string)
408
- chars(case form
409
- when :d
410
- self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints))
411
- when :c
412
- self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints)))
413
- when :kd
414
- self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints))
415
- when :kc
416
- self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints)))
417
- else
418
- raise ArgumentError, "#{form} is not a valid normalization variant", caller
419
- end.pack('U*'))
377
+ # ActiveSupport::Multibyte::Unicode.default_normalization_form
378
+ def normalize(form = nil)
379
+ chars(Unicode.normalize(@wrapped_string, form))
420
380
  end
421
381
 
422
382
  # Performs canonical decomposition on all the characters.
@@ -425,7 +385,7 @@ module ActiveSupport #:nodoc:
425
385
  # 'é'.length #=> 2
426
386
  # 'é'.mb_chars.decompose.to_s.length #=> 3
427
387
  def decompose
428
- chars(self.class.decompose_codepoints(:canonical, self.class.u_unpack(@wrapped_string)).pack('U*'))
388
+ chars(Unicode.decompose_codepoints(:canonical, Unicode.u_unpack(@wrapped_string)).pack('U*'))
429
389
  end
430
390
 
431
391
  # Performs composition on all the characters.
@@ -434,7 +394,7 @@ module ActiveSupport #:nodoc:
434
394
  # 'é'.length #=> 3
435
395
  # 'é'.mb_chars.compose.to_s.length #=> 2
436
396
  def compose
437
- chars(self.class.compose_codepoints(self.class.u_unpack(@wrapped_string)).pack('U*'))
397
+ chars(Unicode.compose_codepoints(Unicode.u_unpack(@wrapped_string)).pack('U*'))
438
398
  end
439
399
 
440
400
  # Returns the number of grapheme clusters in the string.
@@ -443,210 +403,24 @@ module ActiveSupport #:nodoc:
443
403
  # 'क्षि'.mb_chars.length #=> 4
444
404
  # 'क्षि'.mb_chars.g_length #=> 3
445
405
  def g_length
446
- self.class.g_unpack(@wrapped_string).length
406
+ Unicode.g_unpack(@wrapped_string).length
447
407
  end
448
408
 
449
409
  # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
450
- def tidy_bytes
451
- chars(self.class.tidy_bytes(@wrapped_string))
452
- end
453
-
454
- %w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method|
455
- define_method("#{method}!") do |*args|
456
- unless args.nil?
457
- @wrapped_string = send(method, *args).to_s
458
- else
459
- @wrapped_string = send(method).to_s
460
- end
461
- self
462
- end
463
- end
464
-
465
- class << self
466
-
467
- # Unpack the string at codepoints boundaries. Raises an EncodingError when the encoding of the string isn't
468
- # valid UTF-8.
469
- #
470
- # Example:
471
- # Chars.u_unpack('Café') #=> [67, 97, 102, 233]
472
- def u_unpack(string)
473
- begin
474
- string.unpack 'U*'
475
- rescue ArgumentError
476
- raise EncodingError, 'malformed UTF-8 character'
477
- end
478
- end
479
-
480
- # Detect whether the codepoint is in a certain character class. Returns +true+ when it's in the specified
481
- # character class and +false+ otherwise. Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
482
- # <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
483
- #
484
- # Primarily used by the grapheme cluster support.
485
- def in_char_class?(codepoint, classes)
486
- classes.detect { |c| UCD.boundary[c] === codepoint } ? true : false
487
- end
488
-
489
- # Unpack the string at grapheme boundaries. Returns a list of character lists.
490
- #
491
- # Example:
492
- # Chars.g_unpack('क्षि') #=> [[2325, 2381], [2359], [2367]]
493
- # Chars.g_unpack('Café') #=> [[67], [97], [102], [233]]
494
- def g_unpack(string)
495
- codepoints = u_unpack(string)
496
- unpacked = []
497
- pos = 0
498
- marker = 0
499
- eoc = codepoints.length
500
- while(pos < eoc)
501
- pos += 1
502
- previous = codepoints[pos-1]
503
- current = codepoints[pos]
504
- if (
505
- # CR X LF
506
- one = ( previous == UCD.boundary[:cr] and current == UCD.boundary[:lf] ) or
507
- # L X (L|V|LV|LVT)
508
- two = ( UCD.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
509
- # (LV|V) X (V|T)
510
- three = ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
511
- # (LVT|T) X (T)
512
- four = ( in_char_class?(previous, [:lvt,:t]) and UCD.boundary[:t] === current ) or
513
- # X Extend
514
- five = (UCD.boundary[:extend] === current)
515
- )
516
- else
517
- unpacked << codepoints[marker..pos-1]
518
- marker = pos
519
- end
520
- end
521
- unpacked
522
- end
523
-
524
- # Reverse operation of g_unpack.
525
- #
526
- # Example:
527
- # Chars.g_pack(Chars.g_unpack('क्षि')) #=> 'क्षि'
528
- def g_pack(unpacked)
529
- (unpacked.flatten).pack('U*')
530
- end
531
-
532
- def padding(padsize, padstr=' ') #:nodoc:
533
- if padsize != 0
534
- new(padstr * ((padsize / u_unpack(padstr).size) + 1)).slice(0, padsize)
535
- else
536
- ''
537
- end
538
- end
539
-
540
- # Re-order codepoints so the string becomes canonical.
541
- def reorder_characters(codepoints)
542
- length = codepoints.length- 1
543
- pos = 0
544
- while pos < length do
545
- cp1, cp2 = UCD.codepoints[codepoints[pos]], UCD.codepoints[codepoints[pos+1]]
546
- if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
547
- codepoints[pos..pos+1] = cp2.code, cp1.code
548
- pos += (pos > 0 ? -1 : 1)
549
- else
550
- pos += 1
551
- end
552
- end
553
- codepoints
554
- end
555
-
556
- # Decompose composed characters to the decomposed form.
557
- def decompose_codepoints(type, codepoints)
558
- codepoints.inject([]) do |decomposed, cp|
559
- # if it's a hangul syllable starter character
560
- if HANGUL_SBASE <= cp and cp < HANGUL_SLAST
561
- sindex = cp - HANGUL_SBASE
562
- ncp = [] # new codepoints
563
- ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
564
- ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
565
- tindex = sindex % HANGUL_TCOUNT
566
- ncp << (HANGUL_TBASE + tindex) unless tindex == 0
567
- decomposed.concat ncp
568
- # if the codepoint is decomposable in with the current decomposition type
569
- elsif (ncp = UCD.codepoints[cp].decomp_mapping) and (!UCD.codepoints[cp].decomp_type || type == :compatability)
570
- decomposed.concat decompose_codepoints(type, ncp.dup)
571
- else
572
- decomposed << cp
573
- end
574
- end
575
- end
576
-
577
- # Compose decomposed characters to the composed form.
578
- def compose_codepoints(codepoints)
579
- pos = 0
580
- eoa = codepoints.length - 1
581
- starter_pos = 0
582
- starter_char = codepoints[0]
583
- previous_combining_class = -1
584
- while pos < eoa
585
- pos += 1
586
- lindex = starter_char - HANGUL_LBASE
587
- # -- Hangul
588
- if 0 <= lindex and lindex < HANGUL_LCOUNT
589
- vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
590
- if 0 <= vindex and vindex < HANGUL_VCOUNT
591
- tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
592
- if 0 <= tindex and tindex < HANGUL_TCOUNT
593
- j = starter_pos + 2
594
- eoa -= 2
595
- else
596
- tindex = 0
597
- j = starter_pos + 1
598
- eoa -= 1
599
- end
600
- codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
601
- end
602
- starter_pos += 1
603
- starter_char = codepoints[starter_pos]
604
- # -- Other characters
605
- else
606
- current_char = codepoints[pos]
607
- current = UCD.codepoints[current_char]
608
- if current.combining_class > previous_combining_class
609
- if ref = UCD.composition_map[starter_char]
610
- composition = ref[current_char]
611
- else
612
- composition = nil
613
- end
614
- unless composition.nil?
615
- codepoints[starter_pos] = composition
616
- starter_char = composition
617
- codepoints.delete_at pos
618
- eoa -= 1
619
- pos -= 1
620
- previous_combining_class = -1
621
- else
622
- previous_combining_class = current.combining_class
623
- end
624
- else
625
- previous_combining_class = current.combining_class
626
- end
627
- if current.combining_class == 0
628
- starter_pos = pos
629
- starter_char = codepoints[pos]
630
- end
631
- end
410
+ #
411
+ # Passing +true+ will forcibly tidy all bytes, assuming that the string's encoding is entirely CP1252 or ISO-8859-1.
412
+ def tidy_bytes(force = false)
413
+ chars(Unicode.tidy_bytes(@wrapped_string, force))
414
+ end
415
+
416
+ %w(capitalize downcase lstrip reverse rstrip slice strip tidy_bytes upcase).each do |method|
417
+ # Only define a corresponding bang method for methods defined in the proxy; On 1.9 the proxy will
418
+ # exclude lstrip!, rstrip! and strip! because they are already work as expected on multibyte strings.
419
+ if public_method_defined?(method)
420
+ define_method("#{method}!") do |*args|
421
+ @wrapped_string = send(args.nil? ? method : method, *args).to_s
422
+ self
632
423
  end
633
- codepoints
634
- end
635
-
636
- # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
637
- def tidy_bytes(string)
638
- string.split(//u).map do |c|
639
- c.force_encoding(Encoding::ASCII) if c.respond_to?(:force_encoding)
640
-
641
- if !ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'].match(c)
642
- n = c.unpack('C')[0]
643
- n < 128 ? n.chr :
644
- n < 160 ? [UCD.cp1252[n] || n].pack('U') :
645
- n < 192 ? "\xC2" + n.chr : "\xC3" + (n-64).chr
646
- else
647
- c
648
- end
649
- end.join
650
424
  end
651
425
  end
652
426
 
@@ -655,20 +429,16 @@ module ActiveSupport #:nodoc:
655
429
  def translate_offset(byte_offset) #:nodoc:
656
430
  return nil if byte_offset.nil?
657
431
  return 0 if @wrapped_string == ''
658
- chunk = @wrapped_string[0..byte_offset]
432
+
433
+ if @wrapped_string.respond_to?(:force_encoding)
434
+ @wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT)
435
+ end
436
+
659
437
  begin
660
- begin
661
- chunk.unpack('U*').length - 1
662
- rescue ArgumentError => e
663
- chunk = @wrapped_string[0..(byte_offset+=1)]
664
- # Stop retrying at the end of the string
665
- raise e unless byte_offset < chunk.length
666
- # We damaged a character, retry
667
- retry
668
- end
669
- # Catch the ArgumentError so we can throw our own
670
- rescue ArgumentError
671
- raise EncodingError, 'malformed UTF-8 character'
438
+ @wrapped_string[0...byte_offset].unpack('U*').length
439
+ rescue ArgumentError => e
440
+ byte_offset -= 1
441
+ retry
672
442
  end
673
443
  end
674
444
 
@@ -678,26 +448,23 @@ module ActiveSupport #:nodoc:
678
448
  padsize = padsize > 0 ? padsize : 0
679
449
  case way
680
450
  when :right
681
- result = @wrapped_string.dup.insert(0, self.class.padding(padsize, padstr))
451
+ result = @wrapped_string.dup.insert(0, padding(padsize, padstr))
682
452
  when :left
683
- result = @wrapped_string.dup.insert(-1, self.class.padding(padsize, padstr))
453
+ result = @wrapped_string.dup.insert(-1, padding(padsize, padstr))
684
454
  when :center
685
- lpad = self.class.padding((padsize / 2.0).floor, padstr)
686
- rpad = self.class.padding((padsize / 2.0).ceil, padstr)
455
+ lpad = padding((padsize / 2.0).floor, padstr)
456
+ rpad = padding((padsize / 2.0).ceil, padstr)
687
457
  result = @wrapped_string.dup.insert(0, lpad).insert(-1, rpad)
688
458
  end
689
459
  chars(result)
690
460
  end
691
461
 
692
- def apply_mapping(mapping) #:nodoc:
693
- chars(self.class.u_unpack(@wrapped_string).map do |codepoint|
694
- cp = UCD.codepoints[codepoint]
695
- if cp and (ncp = cp.send(mapping)) and ncp > 0
696
- ncp
697
- else
698
- codepoint
699
- end
700
- end.pack('U*'))
462
+ def padding(padsize, padstr=' ') #:nodoc:
463
+ if padsize != 0
464
+ chars(padstr * ((padsize / Unicode.u_unpack(padstr).size) + 1)).slice(0, padsize)
465
+ else
466
+ ''
467
+ end
701
468
  end
702
469
 
703
470
  def chars(string) #:nodoc: