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
@@ -0,0 +1,392 @@
1
+ module ActiveSupport
2
+ module Multibyte
3
+ module Unicode
4
+
5
+ extend self
6
+
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.2.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::Unicode.default_normalization_form = :c
19
+ attr_accessor :default_normalization_form
20
+ @default_normalization_form = :kc
21
+
22
+ # Hangul character boundaries and properties
23
+ HANGUL_SBASE = 0xAC00
24
+ HANGUL_LBASE = 0x1100
25
+ HANGUL_VBASE = 0x1161
26
+ HANGUL_TBASE = 0x11A7
27
+ HANGUL_LCOUNT = 19
28
+ HANGUL_VCOUNT = 21
29
+ HANGUL_TCOUNT = 28
30
+ HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
31
+ HANGUL_SCOUNT = 11172
32
+ HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
33
+ HANGUL_JAMO_FIRST = 0x1100
34
+ HANGUL_JAMO_LAST = 0x11FF
35
+
36
+ # All the unicode whitespace
37
+ WHITESPACE = [
38
+ (0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
39
+ 0x0020, # White_Space # Zs SPACE
40
+ 0x0085, # White_Space # Cc <control-0085>
41
+ 0x00A0, # White_Space # Zs NO-BREAK SPACE
42
+ 0x1680, # White_Space # Zs OGHAM SPACE MARK
43
+ 0x180E, # White_Space # Zs MONGOLIAN VOWEL SEPARATOR
44
+ (0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
45
+ 0x2028, # White_Space # Zl LINE SEPARATOR
46
+ 0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
47
+ 0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
48
+ 0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
49
+ 0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
50
+ ].flatten.freeze
51
+
52
+ # BOM (byte order mark) can also be seen as whitespace, it's a non-rendering character used to distinguish
53
+ # between little and big endian. This is not an issue in utf-8, so it must be ignored.
54
+ LEADERS_AND_TRAILERS = WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
55
+
56
+ # Returns a regular expression pattern that matches the passed Unicode codepoints
57
+ def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
58
+ array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
59
+ end
60
+ TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
61
+ LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
62
+
63
+ # Unpack the string at codepoints boundaries. Raises an EncodingError when the encoding of the string isn't
64
+ # valid UTF-8.
65
+ #
66
+ # Example:
67
+ # Unicode.u_unpack('Café') #=> [67, 97, 102, 233]
68
+ def u_unpack(string)
69
+ begin
70
+ string.unpack 'U*'
71
+ rescue ArgumentError
72
+ raise EncodingError, 'malformed UTF-8 character'
73
+ end
74
+ end
75
+
76
+ # Detect whether the codepoint is in a certain character class. Returns +true+ when it's in the specified
77
+ # character class and +false+ otherwise. Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
78
+ # <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
79
+ #
80
+ # Primarily used by the grapheme cluster support.
81
+ def in_char_class?(codepoint, classes)
82
+ classes.detect { |c| database.boundary[c] === codepoint } ? true : false
83
+ end
84
+
85
+ # Unpack the string at grapheme boundaries. Returns a list of character lists.
86
+ #
87
+ # Example:
88
+ # Unicode.g_unpack('क्षि') #=> [[2325, 2381], [2359], [2367]]
89
+ # Unicode.g_unpack('Café') #=> [[67], [97], [102], [233]]
90
+ def g_unpack(string)
91
+ codepoints = u_unpack(string)
92
+ unpacked = []
93
+ pos = 0
94
+ marker = 0
95
+ eoc = codepoints.length
96
+ while(pos < eoc)
97
+ pos += 1
98
+ previous = codepoints[pos-1]
99
+ current = codepoints[pos]
100
+ if (
101
+ # CR X LF
102
+ ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
103
+ # L X (L|V|LV|LVT)
104
+ ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
105
+ # (LV|V) X (V|T)
106
+ ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
107
+ # (LVT|T) X (T)
108
+ ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
109
+ # X Extend
110
+ (database.boundary[:extend] === current)
111
+ )
112
+ else
113
+ unpacked << codepoints[marker..pos-1]
114
+ marker = pos
115
+ end
116
+ end
117
+ unpacked
118
+ end
119
+
120
+ # Reverse operation of g_unpack.
121
+ #
122
+ # Example:
123
+ # Unicode.g_pack(Unicode.g_unpack('क्षि')) #=> 'क्षि'
124
+ def g_pack(unpacked)
125
+ (unpacked.flatten).pack('U*')
126
+ end
127
+
128
+ # Re-order codepoints so the string becomes canonical.
129
+ def reorder_characters(codepoints)
130
+ length = codepoints.length- 1
131
+ pos = 0
132
+ while pos < length do
133
+ cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos+1]]
134
+ if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
135
+ codepoints[pos..pos+1] = cp2.code, cp1.code
136
+ pos += (pos > 0 ? -1 : 1)
137
+ else
138
+ pos += 1
139
+ end
140
+ end
141
+ codepoints
142
+ end
143
+
144
+ # Decompose composed characters to the decomposed form.
145
+ def decompose_codepoints(type, codepoints)
146
+ codepoints.inject([]) do |decomposed, cp|
147
+ # if it's a hangul syllable starter character
148
+ if HANGUL_SBASE <= cp and cp < HANGUL_SLAST
149
+ sindex = cp - HANGUL_SBASE
150
+ ncp = [] # new codepoints
151
+ ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
152
+ ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
153
+ tindex = sindex % HANGUL_TCOUNT
154
+ ncp << (HANGUL_TBASE + tindex) unless tindex == 0
155
+ decomposed.concat ncp
156
+ # if the codepoint is decomposable in with the current decomposition type
157
+ elsif (ncp = database.codepoints[cp].decomp_mapping) and (!database.codepoints[cp].decomp_type || type == :compatability)
158
+ decomposed.concat decompose_codepoints(type, ncp.dup)
159
+ else
160
+ decomposed << cp
161
+ end
162
+ end
163
+ end
164
+
165
+ # Compose decomposed characters to the composed form.
166
+ def compose_codepoints(codepoints)
167
+ pos = 0
168
+ eoa = codepoints.length - 1
169
+ starter_pos = 0
170
+ starter_char = codepoints[0]
171
+ previous_combining_class = -1
172
+ while pos < eoa
173
+ pos += 1
174
+ lindex = starter_char - HANGUL_LBASE
175
+ # -- Hangul
176
+ if 0 <= lindex and lindex < HANGUL_LCOUNT
177
+ vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
178
+ if 0 <= vindex and vindex < HANGUL_VCOUNT
179
+ tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
180
+ if 0 <= tindex and tindex < HANGUL_TCOUNT
181
+ j = starter_pos + 2
182
+ eoa -= 2
183
+ else
184
+ tindex = 0
185
+ j = starter_pos + 1
186
+ eoa -= 1
187
+ end
188
+ codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
189
+ end
190
+ starter_pos += 1
191
+ starter_char = codepoints[starter_pos]
192
+ # -- Other characters
193
+ else
194
+ current_char = codepoints[pos]
195
+ current = database.codepoints[current_char]
196
+ if current.combining_class > previous_combining_class
197
+ if ref = database.composition_map[starter_char]
198
+ composition = ref[current_char]
199
+ else
200
+ composition = nil
201
+ end
202
+ unless composition.nil?
203
+ codepoints[starter_pos] = composition
204
+ starter_char = composition
205
+ codepoints.delete_at pos
206
+ eoa -= 1
207
+ pos -= 1
208
+ previous_combining_class = -1
209
+ else
210
+ previous_combining_class = current.combining_class
211
+ end
212
+ else
213
+ previous_combining_class = current.combining_class
214
+ end
215
+ if current.combining_class == 0
216
+ starter_pos = pos
217
+ starter_char = codepoints[pos]
218
+ end
219
+ end
220
+ end
221
+ codepoints
222
+ end
223
+
224
+ # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
225
+ #
226
+ # Passing +true+ will forcibly tidy all bytes, assuming that the string's encoding is entirely CP1252 or ISO-8859-1.
227
+ def tidy_bytes(string, force = false)
228
+ if force
229
+ return string.unpack("C*").map do |b|
230
+ tidy_byte(b)
231
+ end.flatten.compact.pack("C*").unpack("U*").pack("U*")
232
+ end
233
+
234
+ bytes = string.unpack("C*")
235
+ conts_expected = 0
236
+ last_lead = 0
237
+
238
+ bytes.each_index do |i|
239
+
240
+ byte = bytes[i]
241
+ is_cont = byte > 127 && byte < 192
242
+ is_lead = byte > 191 && byte < 245
243
+ is_unused = byte > 240
244
+ is_restricted = byte > 244
245
+
246
+ # Impossible or highly unlikely byte? Clean it.
247
+ if is_unused || is_restricted
248
+ bytes[i] = tidy_byte(byte)
249
+ elsif is_cont
250
+ # Not expecting contination byte? Clean up. Otherwise, now expect one less.
251
+ conts_expected == 0 ? bytes[i] = tidy_byte(byte) : conts_expected -= 1
252
+ else
253
+ if conts_expected > 0
254
+ # Expected continuation, but got ASCII or leading? Clean backwards up to
255
+ # the leading byte.
256
+ (1..(i - last_lead)).each {|j| bytes[i - j] = tidy_byte(bytes[i - j])}
257
+ conts_expected = 0
258
+ end
259
+ if is_lead
260
+ # Final byte is leading? Clean it.
261
+ if i == bytes.length - 1
262
+ bytes[i] = tidy_byte(bytes.last)
263
+ else
264
+ # Valid leading byte? Expect continuations determined by position of
265
+ # first zero bit, with max of 3.
266
+ conts_expected = byte < 224 ? 1 : byte < 240 ? 2 : 3
267
+ last_lead = i
268
+ end
269
+ end
270
+ end
271
+ end
272
+ bytes.empty? ? "" : bytes.flatten.compact.pack("C*").unpack("U*").pack("U*")
273
+ end
274
+
275
+ # Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
276
+ # passing strings to databases and validations.
277
+ #
278
+ # * <tt>string</tt> - The string to perform normalization on.
279
+ # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
280
+ # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
281
+ # ActiveSupport::Multibyte.default_normalization_form
282
+ def normalize(string, form=nil)
283
+ form ||= @default_normalization_form
284
+ # See http://www.unicode.org/reports/tr15, Table 1
285
+ codepoints = u_unpack(string)
286
+ case form
287
+ when :d
288
+ reorder_characters(decompose_codepoints(:canonical, codepoints))
289
+ when :c
290
+ compose_codepoints(reorder_characters(decompose_codepoints(:canonical, codepoints)))
291
+ when :kd
292
+ reorder_characters(decompose_codepoints(:compatability, codepoints))
293
+ when :kc
294
+ compose_codepoints(reorder_characters(decompose_codepoints(:compatability, codepoints)))
295
+ else
296
+ raise ArgumentError, "#{form} is not a valid normalization variant", caller
297
+ end.pack('U*')
298
+ end
299
+
300
+ def apply_mapping(string, mapping) #:nodoc:
301
+ u_unpack(string).map do |codepoint|
302
+ cp = database.codepoints[codepoint]
303
+ if cp and (ncp = cp.send(mapping)) and ncp > 0
304
+ ncp
305
+ else
306
+ codepoint
307
+ end
308
+ end.pack('U*')
309
+ end
310
+
311
+ # Holds data about a codepoint in the Unicode database
312
+ class Codepoint
313
+ attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
314
+ end
315
+
316
+ # Holds static data from the Unicode database
317
+ class UnicodeDatabase
318
+ ATTRIBUTES = :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
319
+
320
+ attr_writer(*ATTRIBUTES)
321
+
322
+ def initialize
323
+ @codepoints = Hash.new(Codepoint.new)
324
+ @composition_exclusion = []
325
+ @composition_map = {}
326
+ @boundary = {}
327
+ @cp1252 = {}
328
+ end
329
+
330
+ # Lazy load the Unicode database so it's only loaded when it's actually used
331
+ ATTRIBUTES.each do |attr_name|
332
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
333
+ def #{attr_name} # def codepoints
334
+ load # load
335
+ @#{attr_name} # @codepoints
336
+ end # end
337
+ EOS
338
+ end
339
+
340
+ # Loads the Unicode database and returns all the internal objects of UnicodeDatabase.
341
+ def load
342
+ begin
343
+ @codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
344
+ rescue Exception => e
345
+ raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
346
+ end
347
+
348
+ # Redefine the === method so we can write shorter rules for grapheme cluster breaks
349
+ @boundary.each do |k,_|
350
+ @boundary[k].instance_eval do
351
+ def ===(other)
352
+ detect { |i| i === other } ? true : false
353
+ end
354
+ end if @boundary[k].kind_of?(Array)
355
+ end
356
+
357
+ # define attr_reader methods for the instance variables
358
+ class << self
359
+ attr_reader(*ATTRIBUTES)
360
+ end
361
+ end
362
+
363
+ # Returns the directory in which the data files are stored
364
+ def self.dirname
365
+ File.dirname(__FILE__) + '/../values/'
366
+ end
367
+
368
+ # Returns the filename for the data file for this version
369
+ def self.filename
370
+ File.expand_path File.join(dirname, "unicode_tables.dat")
371
+ end
372
+ end
373
+
374
+ private
375
+
376
+ def tidy_byte(byte)
377
+ if byte < 160
378
+ [database.cp1252[byte] || byte].pack("U").unpack("C*")
379
+ elsif byte < 192
380
+ [194, byte]
381
+ else
382
+ [195, byte - 64]
383
+ end
384
+ end
385
+
386
+ def database
387
+ @database ||= UnicodeDatabase.new
388
+ end
389
+
390
+ end
391
+ end
392
+ end
@@ -26,11 +26,11 @@ module ActiveSupport #:nodoc:
26
26
  else
27
27
  def self.verify(string)
28
28
  if expression = valid_character
29
- for c in string.split(//)
30
- return false unless expression.match(c)
31
- end
29
+ # Splits the string on character boundaries, which are determined based on $KCODE.
30
+ string.split(//).all? { |c| expression =~ c }
31
+ else
32
+ true
32
33
  end
33
- true
34
34
  end
35
35
  end
36
36
 
@@ -49,9 +49,8 @@ module ActiveSupport #:nodoc:
49
49
  else
50
50
  def self.clean(string)
51
51
  if expression = valid_character
52
- stripped = []; for c in string.split(//)
53
- stripped << c if expression.match(c)
54
- end; stripped.join
52
+ # Splits the string on character boundaries, which are determined based on $KCODE.
53
+ string.split(//).grep(expression).join
55
54
  else
56
55
  string
57
56
  end
@@ -1,6 +1,4 @@
1
- require 'thread'
2
1
  require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/module/attribute_accessors'
4
2
 
5
3
  module ActiveSupport
6
4
  # Notifications provides an instrumentation API for Ruby. To instrument an
@@ -11,12 +9,12 @@ module ActiveSupport
11
9
  # end
12
10
  #
13
11
  # You can consume those events and the information they provide by registering
14
- # a subscriber. For instance, let's store all instrumented events in an array:
12
+ # a log subscriber. For instance, let's store all instrumented events in an array:
15
13
  #
16
14
  # @events = []
17
15
  #
18
- # ActiveSupport::Notifications.subscribe do |event|
19
- # @events << event
16
+ # ActiveSupport::Notifications.subscribe do |*args|
17
+ # @events << ActiveSupport::Notifications::Event.new(*args)
20
18
  # end
21
19
  #
22
20
  # ActiveSupport::Notifications.instrument(:render, :extra => :information) do
@@ -24,10 +22,8 @@ module ActiveSupport
24
22
  # end
25
23
  #
26
24
  # event = @events.first
27
- # event.class #=> ActiveSupport::Notifications::Event
28
25
  # event.name #=> :render
29
- # event.duration #=> 10 (in miliseconds)
30
- # event.result #=> "Foo"
26
+ # event.duration #=> 10 (in milliseconds)
31
27
  # event.payload #=> { :extra => :information }
32
28
  #
33
29
  # When subscribing to Notifications, you can pass a pattern, to only consume
@@ -38,134 +34,45 @@ module ActiveSupport
38
34
  # end
39
35
  #
40
36
  # Notifications ships with a queue implementation that consumes and publish events
41
- # to subscribers in a thread. You can use any queue implementation you want.
37
+ # to log subscribers in a thread. You can use any queue implementation you want.
42
38
  #
43
39
  module Notifications
44
- mattr_accessor :queue
40
+ autoload :Instrumenter, 'active_support/notifications/instrumenter'
41
+ autoload :Event, 'active_support/notifications/instrumenter'
42
+ autoload :Fanout, 'active_support/notifications/fanout'
45
43
 
46
- class << self
47
- delegate :instrument, :to => :instrumenter
48
-
49
- def instrumenter
50
- Thread.current[:notifications_instrumeter] ||= Instrumenter.new(publisher)
51
- end
52
-
53
- def publisher
54
- @publisher ||= Publisher.new(queue)
55
- end
56
-
57
- def subscribe(pattern=nil, &block)
58
- Subscriber.new(queue).bind(pattern).subscribe(&block)
59
- end
60
- end
61
-
62
- class Instrumenter
63
- def initialize(publisher)
64
- @publisher = publisher
65
- end
44
+ @instrumenters = Hash.new { |h,k| h[k] = notifier.listening?(k) }
66
45
 
67
- def instrument(name, payload={})
68
- payload[:time] = Time.now
69
- payload[:thread_id] = Thread.current.object_id
70
- payload[:result] = yield if block_given?
71
- ensure
72
- payload[:duration] = 1000 * (Time.now.to_f - payload[:time].to_f)
73
- @publisher.publish(name, payload)
74
- end
75
- end
76
-
77
- class Publisher
78
- def initialize(queue)
79
- @queue = queue
80
- end
81
-
82
- def publish(name, payload)
83
- @queue.publish(name, payload)
84
- end
85
- end
86
-
87
- class Subscriber
88
- def initialize(queue)
89
- @queue = queue
90
- end
91
-
92
- def bind(pattern)
93
- @pattern = pattern
94
- self
95
- end
96
-
97
- def subscribe
98
- @queue.subscribe(@pattern) do |name, payload|
99
- yield Event.new(name, payload)
46
+ class << self
47
+ attr_writer :notifier
48
+ delegate :publish, :to => :notifier
49
+
50
+ def instrument(name, payload = {})
51
+ if @instrumenters[name]
52
+ instrumenter.instrument(name, payload) { yield payload if block_given? }
53
+ else
54
+ yield payload if block_given?
100
55
  end
101
56
  end
102
- end
103
-
104
- class Event
105
- attr_reader :name, :time, :duration, :thread_id, :result, :payload
106
-
107
- def initialize(name, payload)
108
- @name = name
109
- @payload = payload.dup
110
- @time = @payload.delete(:time)
111
- @thread_id = @payload.delete(:thread_id)
112
- @result = @payload.delete(:result)
113
- @duration = @payload.delete(:duration)
114
- end
115
-
116
- def parent_of?(event)
117
- start = (self.time - event.time) * 1000
118
- start <= 0 && (start + self.duration >= event.duration)
119
- end
120
- end
121
-
122
- # This is a default queue implementation that ships with Notifications. It
123
- # consumes events in a thread and publish them to all registered subscribers.
124
- #
125
- class LittleFanout
126
- def initialize
127
- @listeners, @stream = [], Queue.new
128
- @thread = Thread.new { consume }
129
- end
130
57
 
131
- def publish(*event)
132
- @stream.push(event)
58
+ def subscribe(*args, &block)
59
+ notifier.subscribe(*args, &block).tap do
60
+ @instrumenters.clear
61
+ end
133
62
  end
134
63
 
135
- def subscribe(pattern=nil, &block)
136
- @listeners << Listener.new(pattern, &block)
64
+ def unsubscribe(*args)
65
+ notifier.unsubscribe(*args)
66
+ @instrumenters.clear
137
67
  end
138
68
 
139
- def consume
140
- while event = @stream.shift
141
- @listeners.each { |l| l.publish(*event) }
142
- end
69
+ def notifier
70
+ @notifier ||= Fanout.new
143
71
  end
144
72
 
145
- class Listener
146
- attr_reader :thread
147
-
148
- def initialize(pattern, &block)
149
- @pattern = pattern
150
- @subscriber = block
151
- @queue = Queue.new
152
- @thread = Thread.new { consume }
153
- end
154
-
155
- def publish(name, payload)
156
- unless @pattern && !(@pattern === name.to_s)
157
- @queue << [name, payload]
158
- end
159
- end
160
-
161
- def consume
162
- while event = @queue.shift
163
- @subscriber.call(*event)
164
- end
165
- end
73
+ def instrumenter
74
+ Thread.current[:"instrumentation_#{notifier.object_id}"] ||= Instrumenter.new(notifier)
166
75
  end
167
76
  end
168
77
  end
169
-
170
- Notifications.queue = Notifications::LittleFanout.new
171
78
  end