activesupport 2.1.2 → 2.2.2

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 (240) hide show
  1. data/CHANGELOG +64 -5
  2. data/lib/active_support.rb +6 -6
  3. data/lib/active_support/base64.rb +13 -2
  4. data/lib/active_support/basic_object.rb +1 -1
  5. data/lib/active_support/buffered_logger.rb +15 -14
  6. data/lib/active_support/cache.rb +116 -40
  7. data/lib/active_support/cache/compressed_mem_cache_store.rb +7 -2
  8. data/lib/active_support/cache/file_store.rb +7 -5
  9. data/lib/active_support/cache/mem_cache_store.rb +48 -21
  10. data/lib/active_support/cache/memory_store.rb +16 -2
  11. data/lib/active_support/cache/synchronized_memory_store.rb +47 -0
  12. data/lib/active_support/callbacks.rb +14 -9
  13. data/lib/active_support/core_ext/array/access.rb +27 -0
  14. data/lib/active_support/core_ext/array/conversions.rb +12 -7
  15. data/lib/active_support/core_ext/array/grouping.rb +53 -10
  16. data/lib/active_support/core_ext/base64/encoding.rb +3 -0
  17. data/lib/active_support/core_ext/bigdecimal/conversions.rb +18 -22
  18. data/lib/active_support/core_ext/blank.rb +5 -0
  19. data/lib/active_support/core_ext/class/inheritable_attributes.rb +5 -5
  20. data/lib/active_support/core_ext/date/behavior.rb +3 -0
  21. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  22. data/lib/active_support/core_ext/date_time/calculations.rb +19 -5
  23. data/lib/active_support/core_ext/duplicable.rb +6 -0
  24. data/lib/active_support/core_ext/enumerable.rb +42 -4
  25. data/lib/active_support/core_ext/file.rb +4 -20
  26. data/lib/active_support/core_ext/file/atomic.rb +46 -0
  27. data/lib/active_support/core_ext/float.rb +2 -0
  28. data/lib/active_support/core_ext/float/time.rb +27 -0
  29. data/lib/active_support/core_ext/hash.rb +2 -1
  30. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  31. data/lib/active_support/core_ext/hash/deep_merge.rb +23 -0
  32. data/lib/active_support/core_ext/hash/except.rb +1 -1
  33. data/lib/active_support/core_ext/hash/reverse_merge.rb +12 -5
  34. data/lib/active_support/core_ext/hash/slice.rb +7 -4
  35. data/lib/active_support/core_ext/integer.rb +2 -0
  36. data/lib/active_support/core_ext/integer/time.rb +45 -0
  37. data/lib/active_support/core_ext/kernel/debugger.rb +4 -4
  38. data/lib/active_support/core_ext/logger.rb +128 -1
  39. data/lib/active_support/core_ext/module.rb +11 -1
  40. data/lib/active_support/core_ext/module/aliasing.rb +71 -67
  41. data/lib/active_support/core_ext/module/delegation.rb +32 -1
  42. data/lib/active_support/core_ext/module/introspection.rb +81 -66
  43. data/lib/active_support/core_ext/module/model_naming.rb +8 -7
  44. data/lib/active_support/core_ext/module/synchronization.rb +39 -0
  45. data/lib/active_support/core_ext/numeric/time.rb +0 -10
  46. data/lib/active_support/core_ext/object.rb +1 -0
  47. data/lib/active_support/core_ext/object/extending.rb +29 -7
  48. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  49. data/lib/active_support/core_ext/object/metaclass.rb +13 -0
  50. data/lib/active_support/core_ext/object/misc.rb +36 -21
  51. data/lib/active_support/core_ext/rexml.rb +2 -2
  52. data/lib/active_support/core_ext/string.rb +6 -2
  53. data/lib/active_support/core_ext/string/access.rb +5 -5
  54. data/lib/active_support/core_ext/string/behavior.rb +13 -0
  55. data/lib/active_support/core_ext/string/inflections.rb +21 -2
  56. data/lib/active_support/core_ext/string/multibyte.rb +81 -0
  57. data/lib/active_support/core_ext/time/calculations.rb +39 -12
  58. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  59. data/lib/active_support/core_ext/time/zones.rb +1 -1
  60. data/lib/active_support/dependencies.rb +178 -110
  61. data/lib/active_support/deprecation.rb +24 -4
  62. data/lib/active_support/inflector.rb +122 -38
  63. data/lib/active_support/json.rb +1 -1
  64. data/lib/active_support/json/encoders/date.rb +9 -2
  65. data/lib/active_support/json/encoders/date_time.rb +9 -2
  66. data/lib/active_support/json/encoders/time.rb +10 -3
  67. data/lib/active_support/locale/en.yml +32 -0
  68. data/lib/active_support/memoizable.rb +82 -0
  69. data/lib/active_support/multibyte.rb +31 -7
  70. data/lib/active_support/multibyte/chars.rb +664 -122
  71. data/lib/active_support/multibyte/exceptions.rb +8 -0
  72. data/lib/active_support/multibyte/unicode_database.rb +71 -0
  73. data/lib/active_support/option_merger.rb +2 -10
  74. data/lib/active_support/ordered_hash.rb +15 -0
  75. data/lib/active_support/rescuable.rb +108 -0
  76. data/lib/active_support/secure_random.rb +197 -0
  77. data/lib/active_support/string_inquirer.rb +11 -1
  78. data/lib/active_support/test_case.rb +16 -5
  79. data/lib/active_support/testing/core_ext/test.rb +6 -0
  80. data/lib/active_support/{core_ext → testing/core_ext}/test/unit/assertions.rb +14 -6
  81. data/lib/active_support/testing/performance.rb +452 -0
  82. data/lib/active_support/testing/setup_and_teardown.rb +34 -7
  83. data/lib/active_support/time_with_zone.rb +66 -42
  84. data/lib/active_support/values/time_zone.rb +11 -4
  85. data/lib/active_support/values/unicode_tables.dat +0 -0
  86. data/lib/active_support/vendor.rb +13 -5
  87. data/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb +1 -1
  88. data/lib/active_support/vendor/i18n-0.0.1/i18n.rb +194 -0
  89. data/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb +216 -0
  90. data/lib/active_support/vendor/i18n-0.0.1/i18n/exceptions.rb +53 -0
  91. data/lib/active_support/vendor/{memcache-client-1.5.0 → memcache-client-1.5.1}/memcache.rb +5 -5
  92. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo.rb +0 -0
  93. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/data_timezone.rb +0 -0
  94. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/data_timezone_info.rb +0 -0
  95. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Algiers.rb +0 -0
  96. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Cairo.rb +0 -0
  97. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Casablanca.rb +0 -0
  98. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Harare.rb +0 -0
  99. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Johannesburg.rb +0 -0
  100. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Monrovia.rb +0 -0
  101. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Africa/Nairobi.rb +0 -0
  102. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +0 -0
  103. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/San_Juan.rb +86 -0
  104. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Bogota.rb +0 -0
  105. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Caracas.rb +0 -0
  106. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Chicago.rb +0 -0
  107. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Chihuahua.rb +0 -0
  108. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Denver.rb +0 -0
  109. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Godthab.rb +0 -0
  110. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Guatemala.rb +0 -0
  111. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Halifax.rb +0 -0
  112. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Indiana/Indianapolis.rb +0 -0
  113. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Juneau.rb +0 -0
  114. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/La_Paz.rb +0 -0
  115. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Lima.rb +0 -0
  116. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Los_Angeles.rb +0 -0
  117. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Mazatlan.rb +0 -0
  118. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Mexico_City.rb +0 -0
  119. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Monterrey.rb +0 -0
  120. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/New_York.rb +0 -0
  121. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Phoenix.rb +0 -0
  122. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Regina.rb +0 -0
  123. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Santiago.rb +0 -0
  124. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Sao_Paulo.rb +0 -0
  125. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/St_Johns.rb +0 -0
  126. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/America/Tijuana.rb +0 -0
  127. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Almaty.rb +0 -0
  128. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Baghdad.rb +0 -0
  129. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Baku.rb +0 -0
  130. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Bangkok.rb +0 -0
  131. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Chongqing.rb +0 -0
  132. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Colombo.rb +30 -0
  133. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Dhaka.rb +0 -0
  134. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Hong_Kong.rb +0 -0
  135. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Irkutsk.rb +0 -0
  136. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Jakarta.rb +0 -0
  137. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Jerusalem.rb +0 -0
  138. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Kabul.rb +0 -0
  139. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Kamchatka.rb +0 -0
  140. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Karachi.rb +0 -0
  141. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Katmandu.rb +0 -0
  142. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Kolkata.rb +0 -0
  143. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Krasnoyarsk.rb +0 -0
  144. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Kuala_Lumpur.rb +0 -0
  145. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Kuwait.rb +0 -0
  146. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Magadan.rb +0 -0
  147. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Muscat.rb +0 -0
  148. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Novosibirsk.rb +0 -0
  149. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Rangoon.rb +0 -0
  150. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Riyadh.rb +0 -0
  151. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Seoul.rb +0 -0
  152. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Shanghai.rb +0 -0
  153. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Singapore.rb +0 -0
  154. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Taipei.rb +0 -0
  155. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Tashkent.rb +0 -0
  156. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Tbilisi.rb +0 -0
  157. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Tehran.rb +0 -0
  158. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Tokyo.rb +0 -0
  159. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Ulaanbaatar.rb +0 -0
  160. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Urumqi.rb +0 -0
  161. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Vladivostok.rb +0 -0
  162. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Yakutsk.rb +0 -0
  163. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Yekaterinburg.rb +0 -0
  164. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Asia/Yerevan.rb +0 -0
  165. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Atlantic/Azores.rb +0 -0
  166. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Atlantic/Cape_Verde.rb +0 -0
  167. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Atlantic/South_Georgia.rb +0 -0
  168. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Adelaide.rb +0 -0
  169. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Brisbane.rb +0 -0
  170. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Darwin.rb +0 -0
  171. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Hobart.rb +0 -0
  172. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Melbourne.rb +0 -0
  173. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Perth.rb +0 -0
  174. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Australia/Sydney.rb +0 -0
  175. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Etc/UTC.rb +0 -0
  176. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Amsterdam.rb +0 -0
  177. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Athens.rb +0 -0
  178. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Belgrade.rb +0 -0
  179. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Berlin.rb +0 -0
  180. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Bratislava.rb +0 -0
  181. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Brussels.rb +0 -0
  182. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Bucharest.rb +0 -0
  183. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Budapest.rb +0 -0
  184. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Copenhagen.rb +0 -0
  185. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Dublin.rb +0 -0
  186. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Helsinki.rb +0 -0
  187. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Istanbul.rb +0 -0
  188. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Kiev.rb +0 -0
  189. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Lisbon.rb +0 -0
  190. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Ljubljana.rb +0 -0
  191. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/London.rb +0 -0
  192. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Madrid.rb +0 -0
  193. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Minsk.rb +0 -0
  194. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Moscow.rb +0 -0
  195. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Paris.rb +0 -0
  196. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Prague.rb +0 -0
  197. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Riga.rb +0 -0
  198. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Rome.rb +0 -0
  199. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Sarajevo.rb +0 -0
  200. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Skopje.rb +0 -0
  201. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Sofia.rb +0 -0
  202. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Stockholm.rb +0 -0
  203. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Tallinn.rb +0 -0
  204. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Vienna.rb +0 -0
  205. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Vilnius.rb +0 -0
  206. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Warsaw.rb +0 -0
  207. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Europe/Zagreb.rb +0 -0
  208. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Auckland.rb +0 -0
  209. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Fiji.rb +0 -0
  210. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Guam.rb +0 -0
  211. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Honolulu.rb +0 -0
  212. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Majuro.rb +0 -0
  213. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Midway.rb +0 -0
  214. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Noumea.rb +0 -0
  215. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Pago_Pago.rb +0 -0
  216. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Port_Moresby.rb +0 -0
  217. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/definitions/Pacific/Tongatapu.rb +0 -0
  218. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/info_timezone.rb +0 -0
  219. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/linked_timezone.rb +0 -0
  220. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/linked_timezone_info.rb +0 -0
  221. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/offset_rationals.rb +0 -0
  222. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/ruby_core_support.rb +0 -0
  223. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/time_or_datetime.rb +0 -0
  224. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone.rb +0 -0
  225. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone_definition.rb +0 -0
  226. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone_info.rb +0 -0
  227. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone_offset_info.rb +0 -0
  228. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone_period.rb +0 -0
  229. data/lib/active_support/vendor/{tzinfo-0.3.11 → tzinfo-0.3.12}/tzinfo/timezone_transition_info.rb +0 -0
  230. data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +3 -3
  231. data/lib/active_support/version.rb +1 -1
  232. metadata +185 -167
  233. data/lib/active_support/clean_logger.rb +0 -127
  234. data/lib/active_support/core_ext/string/unicode.rb +0 -66
  235. data/lib/active_support/core_ext/test.rb +0 -1
  236. data/lib/active_support/multibyte/generators/generate_tables.rb +0 -149
  237. data/lib/active_support/multibyte/handlers/passthru_handler.rb +0 -9
  238. data/lib/active_support/multibyte/handlers/utf8_handler.rb +0 -564
  239. data/lib/active_support/multibyte/handlers/utf8_handler_proc.rb +0 -43
  240. data/lib/active_support/vendor/tzinfo-0.3.11/tzinfo/definitions/America/Argentina/San_Juan.rb +0 -170
@@ -1,127 +0,0 @@
1
- require 'logger'
2
- require 'active_support/core_ext/class/attribute_accessors'
3
-
4
- # Extensions to the built in Ruby logger.
5
- #
6
- # If you want to use the default log formatter as defined in the Ruby core, then you
7
- # will need to set the formatter for the logger as in:
8
- #
9
- # logger.formatter = Formatter.new
10
- #
11
- # You can then specify the datetime format, for example:
12
- #
13
- # logger.datetime_format = "%Y-%m-%d"
14
- #
15
- # Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
16
- class Logger
17
- # Set to false to disable the silencer
18
- cattr_accessor :silencer
19
- self.silencer = true
20
-
21
- # Silences the logger for the duration of the block.
22
- def silence(temporary_level = Logger::ERROR)
23
- if silencer
24
- begin
25
- old_logger_level, self.level = level, temporary_level
26
- yield self
27
- ensure
28
- self.level = old_logger_level
29
- end
30
- else
31
- yield self
32
- end
33
- end
34
-
35
- alias :old_datetime_format= :datetime_format=
36
- # Logging date-time format (string passed to +strftime+). Ignored if the formatter
37
- # does not respond to datetime_format=.
38
- def datetime_format=(datetime_format)
39
- formatter.datetime_format = datetime_format if formatter.respond_to?(:datetime_format=)
40
- end
41
-
42
- alias :old_datetime_format :datetime_format
43
- # Get the logging datetime format. Returns nil if the formatter does not support
44
- # datetime formatting.
45
- def datetime_format
46
- formatter.datetime_format if formatter.respond_to?(:datetime_format)
47
- end
48
-
49
- alias :old_formatter :formatter if method_defined?(:formatter)
50
- # Get the current formatter. The default formatter is a SimpleFormatter which only
51
- # displays the log message
52
- def formatter
53
- @formatter ||= SimpleFormatter.new
54
- end
55
-
56
- unless const_defined? :Formatter
57
- class Formatter
58
- Format = "%s, [%s#%d] %5s -- %s: %s\n"
59
-
60
- attr_accessor :datetime_format
61
-
62
- def initialize
63
- @datetime_format = nil
64
- end
65
-
66
- def call(severity, time, progname, msg)
67
- Format % [severity[0..0], format_datetime(time), $$, severity, progname,
68
- msg2str(msg)]
69
- end
70
-
71
- private
72
- def format_datetime(time)
73
- if @datetime_format.nil?
74
- time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % time.usec
75
- else
76
- time.strftime(@datetime_format)
77
- end
78
- end
79
-
80
- def msg2str(msg)
81
- case msg
82
- when ::String
83
- msg
84
- when ::Exception
85
- "#{ msg.message } (#{ msg.class })\n" <<
86
- (msg.backtrace || []).join("\n")
87
- else
88
- msg.inspect
89
- end
90
- end
91
- end
92
- end
93
-
94
- # Simple formatter which only displays the message.
95
- class SimpleFormatter < Logger::Formatter
96
- # This method is invoked when a log event occurs
97
- def call(severity, timestamp, progname, msg)
98
- "#{String === msg ? msg : msg.inspect}\n"
99
- end
100
- end
101
-
102
- private
103
- alias old_format_message format_message
104
-
105
- # Ruby 1.8.3 transposed the msg and progname arguments to format_message.
106
- # We can't test RUBY_VERSION because some distributions don't keep Ruby
107
- # and its standard library in sync, leading to installations of Ruby 1.8.2
108
- # with Logger from 1.8.3 and vice versa.
109
- if method_defined?(:formatter=)
110
- def format_message(severity, timestamp, progname, msg)
111
- formatter.call(severity, timestamp, progname, msg)
112
- end
113
- else
114
- def format_message(severity, timestamp, msg, progname)
115
- formatter.call(severity, timestamp, progname, msg)
116
- end
117
-
118
- attr_writer :formatter
119
- public :formatter=
120
-
121
- alias old_format_datetime format_datetime
122
- def format_datetime(datetime) datetime end
123
-
124
- alias old_msg2str msg2str
125
- def msg2str(msg) msg end
126
- end
127
- end
@@ -1,66 +0,0 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module String #:nodoc:
4
- # Define methods for handling unicode data.
5
- module Unicode
6
- def self.append_features(base)
7
- if '1.8.7 and later'.respond_to?(:chars)
8
- base.class_eval { remove_method :chars }
9
- end
10
- super
11
- end
12
-
13
- unless '1.9'.respond_to?(:force_encoding)
14
- # +chars+ is a Unicode safe proxy for string methods. It creates and returns an instance of the
15
- # ActiveSupport::Multibyte::Chars class which encapsulates the original string. A Unicode safe version of all
16
- # the String methods are defined on this proxy class. Undefined methods are forwarded to String, so all of the
17
- # string overrides can also be called through the +chars+ proxy.
18
- #
19
- # name = 'Claus Müller'
20
- # name.reverse # => "rell??M sualC"
21
- # name.length # => 13
22
- #
23
- # name.chars.reverse.to_s # => "rellüM sualC"
24
- # name.chars.length # => 12
25
- #
26
- #
27
- # All the methods on the chars proxy which normally return a string will return a Chars object. This allows
28
- # method chaining on the result of any of these methods.
29
- #
30
- # name.chars.reverse.length # => 12
31
- #
32
- # The Char object tries to be as interchangeable with String objects as possible: sorting and comparing between
33
- # String and Char work like expected. The bang! methods change the internal string representation in the Chars
34
- # object. Interoperability problems can be resolved easily with a +to_s+ call.
35
- #
36
- # For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars and
37
- # ActiveSupport::Multibyte::Handlers::UTF8Handler.
38
- def chars
39
- ActiveSupport::Multibyte::Chars.new(self)
40
- end
41
-
42
- # Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
43
- # them), returns false otherwise.
44
- def is_utf8?
45
- ActiveSupport::Multibyte::Handlers::UTF8Handler.consumes?(self)
46
- end
47
- else
48
- def chars #:nodoc:
49
- self
50
- end
51
-
52
- def is_utf8? #:nodoc:
53
- case encoding
54
- when Encoding::UTF_8
55
- valid_encoding?
56
- when Encoding::ASCII_8BIT
57
- dup.force_encoding('UTF-8').valid_encoding?
58
- else
59
- false
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1 +0,0 @@
1
- require 'active_support/core_ext/test/unit/assertions'
@@ -1,149 +0,0 @@
1
- #!/usr/bin/env ruby
2
- begin
3
- require File.dirname(__FILE__) + '/../../../active_support'
4
- rescue IOError
5
- end
6
- require 'open-uri'
7
- require 'tmpdir'
8
-
9
- module ActiveSupport::Multibyte::Handlers #:nodoc:
10
- class UnicodeDatabase #:nodoc:
11
- def self.load
12
- [Hash.new(Codepoint.new),[],{},{}]
13
- end
14
- end
15
-
16
- class UnicodeTableGenerator #:nodoc:
17
- BASE_URI = "http://www.unicode.org/Public/#{ActiveSupport::Multibyte::UNICODE_VERSION}/ucd/"
18
- SOURCES = {
19
- :codepoints => BASE_URI + 'UnicodeData.txt',
20
- :composition_exclusion => BASE_URI + 'CompositionExclusions.txt',
21
- :grapheme_break_property => BASE_URI + 'auxiliary/GraphemeBreakProperty.txt',
22
- :cp1252 => 'http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT'
23
- }
24
-
25
- def initialize
26
- @ucd = UnicodeDatabase.new
27
-
28
- default = Codepoint.new
29
- default.combining_class = 0
30
- default.uppercase_mapping = 0
31
- default.lowercase_mapping = 0
32
- @ucd.codepoints = Hash.new(default)
33
-
34
- @ucd.composition_exclusion = []
35
- @ucd.composition_map = {}
36
- @ucd.boundary = {}
37
- @ucd.cp1252 = {}
38
- end
39
-
40
- def parse_codepoints(line)
41
- codepoint = Codepoint.new
42
- raise "Could not parse input." unless line =~ /^
43
- ([0-9A-F]+); # code
44
- ([^;]+); # name
45
- ([A-Z]+); # general category
46
- ([0-9]+); # canonical combining class
47
- ([A-Z]+); # bidi class
48
- (<([A-Z]*)>)? # decomposition type
49
- ((\ ?[0-9A-F]+)*); # decompomposition mapping
50
- ([0-9]*); # decimal digit
51
- ([0-9]*); # digit
52
- ([^;]*); # numeric
53
- ([YN]*); # bidi mirrored
54
- ([^;]*); # unicode 1.0 name
55
- ([^;]*); # iso comment
56
- ([0-9A-F]*); # simple uppercase mapping
57
- ([0-9A-F]*); # simple lowercase mapping
58
- ([0-9A-F]*)$/ix # simple titlecase mapping
59
- codepoint.code = $1.hex
60
- #codepoint.name = $2
61
- #codepoint.category = $3
62
- codepoint.combining_class = Integer($4)
63
- #codepoint.bidi_class = $5
64
- codepoint.decomp_type = $7
65
- codepoint.decomp_mapping = ($8=='') ? nil : $8.split.collect { |element| element.hex }
66
- #codepoint.bidi_mirrored = ($13=='Y') ? true : false
67
- codepoint.uppercase_mapping = ($16=='') ? 0 : $16.hex
68
- codepoint.lowercase_mapping = ($17=='') ? 0 : $17.hex
69
- #codepoint.titlecase_mapping = ($18=='') ? nil : $18.hex
70
- @ucd.codepoints[codepoint.code] = codepoint
71
- end
72
-
73
- def parse_grapheme_break_property(line)
74
- if line =~ /^([0-9A-F\.]+)\s*;\s*([\w]+)\s*#/
75
- type = $2.downcase.intern
76
- @ucd.boundary[type] ||= []
77
- if $1.include? '..'
78
- parts = $1.split '..'
79
- @ucd.boundary[type] << (parts[0].hex..parts[1].hex)
80
- else
81
- @ucd.boundary[type] << $1.hex
82
- end
83
- end
84
- end
85
-
86
- def parse_composition_exclusion(line)
87
- if line =~ /^([0-9A-F]+)/i
88
- @ucd.composition_exclusion << $1.hex
89
- end
90
- end
91
-
92
- def parse_cp1252(line)
93
- if line =~ /^([0-9A-Fx]+)\s([0-9A-Fx]+)/i
94
- @ucd.cp1252[$1.hex] = $2.hex
95
- end
96
- end
97
-
98
- def create_composition_map
99
- @ucd.codepoints.each do |_, cp|
100
- if !cp.nil? and cp.combining_class == 0 and cp.decomp_type.nil? and !cp.decomp_mapping.nil? and cp.decomp_mapping.length == 2 and @ucd[cp.decomp_mapping[0]].combining_class == 0 and !@ucd.composition_exclusion.include?(cp.code)
101
- @ucd.composition_map[cp.decomp_mapping[0]] ||= {}
102
- @ucd.composition_map[cp.decomp_mapping[0]][cp.decomp_mapping[1]] = cp.code
103
- end
104
- end
105
- end
106
-
107
- def normalize_boundary_map
108
- @ucd.boundary.each do |k,v|
109
- if [:lf, :cr].include? k
110
- @ucd.boundary[k] = v[0]
111
- end
112
- end
113
- end
114
-
115
- def parse
116
- SOURCES.each do |type, url|
117
- filename = File.join(Dir.tmpdir, "#{url.split('/').last}")
118
- unless File.exist?(filename)
119
- $stderr.puts "Downloading #{url.split('/').last}"
120
- File.open(filename, 'wb') do |target|
121
- open(url) do |source|
122
- source.each_line { |line| target.write line }
123
- end
124
- end
125
- end
126
- File.open(filename) do |file|
127
- file.each_line { |line| send "parse_#{type}".intern, line }
128
- end
129
- end
130
- create_composition_map
131
- normalize_boundary_map
132
- end
133
-
134
- def dump_to(filename)
135
- File.open(filename, 'wb') do |f|
136
- f.write Marshal.dump([@ucd.codepoints, @ucd.composition_exclusion, @ucd.composition_map, @ucd.boundary, @ucd.cp1252])
137
- end
138
- end
139
- end
140
- end
141
-
142
- if __FILE__ == $0
143
- filename = ActiveSupport::Multibyte::Handlers::UnicodeDatabase.filename
144
- generator = ActiveSupport::Multibyte::Handlers::UnicodeTableGenerator.new
145
- generator.parse
146
- print "Writing to: #{filename}"
147
- generator.dump_to filename
148
- puts " (#{File.size(filename)} bytes)"
149
- end
@@ -1,9 +0,0 @@
1
- # Chars uses this handler when $KCODE is not set to 'UTF8'. Because this handler doesn't define any methods all call
2
- # will be forwarded to String.
3
- class ActiveSupport::Multibyte::Handlers::PassthruHandler #:nodoc:
4
-
5
- # Return the original byteoffset
6
- def self.translate_offset(string, byte_offset) #:nodoc:
7
- byte_offset
8
- end
9
- end
@@ -1,564 +0,0 @@
1
- # Contains all the handlers and helper classes
2
- module ActiveSupport::Multibyte::Handlers #:nodoc:
3
- class EncodingError < ArgumentError #:nodoc:
4
- end
5
-
6
- class Codepoint #:nodoc:
7
- attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
8
- end
9
-
10
- class UnicodeDatabase #:nodoc:
11
- attr_writer :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
12
-
13
- # self-expiring methods that lazily load the Unicode database and then return the value.
14
- [:codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252].each do |attr_name|
15
- class_eval(<<-EOS, __FILE__, __LINE__)
16
- def #{attr_name}
17
- load
18
- @#{attr_name}
19
- end
20
- EOS
21
- end
22
-
23
- # Shortcut to ucd.codepoints[]
24
- def [](index); codepoints[index]; end
25
-
26
- # Returns the directory in which the data files are stored
27
- def self.dirname
28
- File.dirname(__FILE__) + '/../../values/'
29
- end
30
-
31
- # Returns the filename for the data file for this version
32
- def self.filename
33
- File.expand_path File.join(dirname, "unicode_tables.dat")
34
- end
35
-
36
- # Loads the unicode database and returns all the internal objects of UnicodeDatabase
37
- # Once the values have been loaded, define attr_reader methods for the instance variables.
38
- def load
39
- begin
40
- @codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
41
- rescue Exception => e
42
- raise IOError.new("Couldn't load the unicode tables for UTF8Handler (#{e.message}), handler is unusable")
43
- end
44
- @codepoints ||= Hash.new(Codepoint.new)
45
- @composition_exclusion ||= []
46
- @composition_map ||= {}
47
- @boundary ||= {}
48
- @cp1252 ||= {}
49
-
50
- # Redefine the === method so we can write shorter rules for grapheme cluster breaks
51
- @boundary.each do |k,_|
52
- @boundary[k].instance_eval do
53
- def ===(other)
54
- detect { |i| i === other } ? true : false
55
- end
56
- end if @boundary[k].kind_of?(Array)
57
- end
58
-
59
- # define attr_reader methods for the instance variables
60
- class << self
61
- attr_reader :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
62
- end
63
- end
64
- end
65
-
66
- # UTF8Handler implements Unicode aware operations for strings, these operations will be used by the Chars
67
- # proxy when $KCODE is set to 'UTF8'.
68
- class UTF8Handler
69
- # Hangul character boundaries and properties
70
- HANGUL_SBASE = 0xAC00
71
- HANGUL_LBASE = 0x1100
72
- HANGUL_VBASE = 0x1161
73
- HANGUL_TBASE = 0x11A7
74
- HANGUL_LCOUNT = 19
75
- HANGUL_VCOUNT = 21
76
- HANGUL_TCOUNT = 28
77
- HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
78
- HANGUL_SCOUNT = 11172
79
- HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
80
- HANGUL_JAMO_FIRST = 0x1100
81
- HANGUL_JAMO_LAST = 0x11FF
82
-
83
- # All the unicode whitespace
84
- UNICODE_WHITESPACE = [
85
- (0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
86
- 0x0020, # White_Space # Zs SPACE
87
- 0x0085, # White_Space # Cc <control-0085>
88
- 0x00A0, # White_Space # Zs NO-BREAK SPACE
89
- 0x1680, # White_Space # Zs OGHAM SPACE MARK
90
- 0x180E, # White_Space # Zs MONGOLIAN VOWEL SEPARATOR
91
- (0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
92
- 0x2028, # White_Space # Zl LINE SEPARATOR
93
- 0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
94
- 0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
95
- 0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
96
- 0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
97
- ].flatten.freeze
98
-
99
- # BOM (byte order mark) can also be seen as whitespace, it's a non-rendering character used to distinguish
100
- # between little and big endian. This is not an issue in utf-8, so it must be ignored.
101
- UNICODE_LEADERS_AND_TRAILERS = UNICODE_WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
102
-
103
- # Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site)
104
- UTF8_PAT = /\A(?:
105
- [\x00-\x7f] |
106
- [\xc2-\xdf] [\x80-\xbf] |
107
- \xe0 [\xa0-\xbf] [\x80-\xbf] |
108
- [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] |
109
- \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
110
- [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
111
- \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
112
- )*\z/xn
113
-
114
- # Returns a regular expression pattern that matches the passed Unicode codepoints
115
- def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
116
- array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
117
- end
118
- UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/
119
- UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/
120
-
121
- class << self
122
-
123
- # ///
124
- # /// BEGIN String method overrides
125
- # ///
126
-
127
- # Inserts the passed string at specified codepoint offsets
128
- def insert(str, offset, fragment)
129
- str.replace(
130
- u_unpack(str).insert(
131
- offset,
132
- u_unpack(fragment)
133
- ).flatten.pack('U*')
134
- )
135
- end
136
-
137
- # Returns the position of the passed argument in the string, counting in codepoints
138
- def index(str, *args)
139
- bidx = str.index(*args)
140
- bidx ? (u_unpack(str.slice(0...bidx)).size) : nil
141
- end
142
-
143
- # Works just like the indexed replace method on string, except instead of byte offsets you specify
144
- # character offsets.
145
- #
146
- # Example:
147
- #
148
- # s = "Müller"
149
- # s.chars[2] = "e" # Replace character with offset 2
150
- # s # => "Müeler"
151
- #
152
- # s = "Müller"
153
- # s.chars[1, 2] = "ö" # Replace 2 characters at character offset 1
154
- # s # => "Möler"
155
- def []=(str, *args)
156
- replace_by = args.pop
157
- # Indexed replace with regular expressions already works
158
- return str[*args] = replace_by if args.first.is_a?(Regexp)
159
- result = u_unpack(str)
160
- if args[0].is_a?(Fixnum)
161
- raise IndexError, "index #{args[0]} out of string" if args[0] >= result.length
162
- min = args[0]
163
- max = args[1].nil? ? min : (min + args[1] - 1)
164
- range = Range.new(min, max)
165
- replace_by = [replace_by].pack('U') if replace_by.is_a?(Fixnum)
166
- elsif args.first.is_a?(Range)
167
- raise RangeError, "#{args[0]} out of range" if args[0].min >= result.length
168
- range = args[0]
169
- else
170
- needle = args[0].to_s
171
- min = index(str, needle)
172
- max = min + length(needle) - 1
173
- range = Range.new(min, max)
174
- end
175
- result[range] = u_unpack(replace_by)
176
- str.replace(result.pack('U*'))
177
- end
178
-
179
- # Works just like String#rjust, only integer specifies characters instead of bytes.
180
- #
181
- # Example:
182
- #
183
- # "¾ cup".chars.rjust(8).to_s
184
- # # => " ¾ cup"
185
- #
186
- # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace
187
- # # => "   ¾ cup"
188
- def rjust(str, integer, padstr=' ')
189
- justify(str, integer, :right, padstr)
190
- end
191
-
192
- # Works just like String#ljust, only integer specifies characters instead of bytes.
193
- #
194
- # Example:
195
- #
196
- # "¾ cup".chars.rjust(8).to_s
197
- # # => "¾ cup "
198
- #
199
- # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace
200
- # # => "¾ cup   "
201
- def ljust(str, integer, padstr=' ')
202
- justify(str, integer, :left, padstr)
203
- end
204
-
205
- # Works just like String#center, only integer specifies characters instead of bytes.
206
- #
207
- # Example:
208
- #
209
- # "¾ cup".chars.center(8).to_s
210
- # # => " ¾ cup "
211
- #
212
- # "¾ cup".chars.center(8, " ").to_s # Use non-breaking whitespace
213
- # # => " ¾ cup  "
214
- def center(str, integer, padstr=' ')
215
- justify(str, integer, :center, padstr)
216
- end
217
-
218
- # Does Unicode-aware rstrip
219
- def rstrip(str)
220
- str.gsub(UNICODE_TRAILERS_PAT, '')
221
- end
222
-
223
- # Does Unicode-aware lstrip
224
- def lstrip(str)
225
- str.gsub(UNICODE_LEADERS_PAT, '')
226
- end
227
-
228
- # Removed leading and trailing whitespace
229
- def strip(str)
230
- str.gsub(UNICODE_LEADERS_PAT, '').gsub(UNICODE_TRAILERS_PAT, '')
231
- end
232
-
233
- # Returns the number of codepoints in the string
234
- def size(str)
235
- u_unpack(str).size
236
- end
237
- alias_method :length, :size
238
-
239
- # Reverses codepoints in the string.
240
- def reverse(str)
241
- u_unpack(str).reverse.pack('U*')
242
- end
243
-
244
- # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
245
- # character.
246
- def slice(str, *args)
247
- if args.size > 2
248
- raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" # Do as if we were native
249
- elsif (args.size == 2 && !(args.first.is_a?(Numeric) || args.first.is_a?(Regexp)))
250
- raise TypeError, "cannot convert #{args.first.class} into Integer" # Do as if we were native
251
- elsif (args.size == 2 && !args[1].is_a?(Numeric))
252
- raise TypeError, "cannot convert #{args[1].class} into Integer" # Do as if we were native
253
- elsif args[0].kind_of? Range
254
- cps = u_unpack(str).slice(*args)
255
- cps.nil? ? nil : cps.pack('U*')
256
- elsif args[0].kind_of? Regexp
257
- str.slice(*args)
258
- elsif args.size == 1 && args[0].kind_of?(Numeric)
259
- u_unpack(str)[args[0]]
260
- else
261
- u_unpack(str).slice(*args).pack('U*')
262
- end
263
- end
264
- alias_method :[], :slice
265
-
266
- # Convert characters in the string to uppercase
267
- def upcase(str); to_case :uppercase_mapping, str; end
268
-
269
- # Convert characters in the string to lowercase
270
- def downcase(str); to_case :lowercase_mapping, str; end
271
-
272
- # Returns a copy of +str+ with the first character converted to uppercase and the remainder to lowercase
273
- def capitalize(str)
274
- upcase(slice(str, 0..0)) + downcase(slice(str, 1..-1) || '')
275
- end
276
-
277
- # ///
278
- # /// Extra String methods for unicode operations
279
- # ///
280
-
281
- # Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
282
- # passing strings to databases and validations.
283
- #
284
- # * <tt>str</tt> - The string to perform normalization on.
285
- # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
286
- # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
287
- # ActiveSupport::Multibyte::DEFAULT_NORMALIZATION_FORM.
288
- def normalize(str, form=ActiveSupport::Multibyte::DEFAULT_NORMALIZATION_FORM)
289
- # See http://www.unicode.org/reports/tr15, Table 1
290
- codepoints = u_unpack(str)
291
- case form
292
- when :d
293
- reorder_characters(decompose_codepoints(:canonical, codepoints))
294
- when :c
295
- compose_codepoints reorder_characters(decompose_codepoints(:canonical, codepoints))
296
- when :kd
297
- reorder_characters(decompose_codepoints(:compatability, codepoints))
298
- when :kc
299
- compose_codepoints reorder_characters(decompose_codepoints(:compatability, codepoints))
300
- else
301
- raise ArgumentError, "#{form} is not a valid normalization variant", caller
302
- end.pack('U*')
303
- end
304
-
305
- # Perform decomposition on the characters in the string
306
- def decompose(str)
307
- decompose_codepoints(:canonical, u_unpack(str)).pack('U*')
308
- end
309
-
310
- # Perform composition on the characters in the string
311
- def compose(str)
312
- compose_codepoints u_unpack(str).pack('U*')
313
- end
314
-
315
- # ///
316
- # /// BEGIN Helper methods for unicode operation
317
- # ///
318
-
319
- # Used to translate an offset from bytes to characters, for instance one received from a regular expression match
320
- def translate_offset(str, byte_offset)
321
- return nil if byte_offset.nil?
322
- return 0 if str == ''
323
- chunk = str[0..byte_offset]
324
- begin
325
- begin
326
- chunk.unpack('U*').length - 1
327
- rescue ArgumentError => e
328
- chunk = str[0..(byte_offset+=1)]
329
- # Stop retrying at the end of the string
330
- raise e unless byte_offset < chunk.length
331
- # We damaged a character, retry
332
- retry
333
- end
334
- # Catch the ArgumentError so we can throw our own
335
- rescue ArgumentError
336
- raise EncodingError.new('malformed UTF-8 character')
337
- end
338
- end
339
-
340
- # Checks if the string is valid UTF8.
341
- def consumes?(str)
342
- # Unpack is a little bit faster than regular expressions
343
- begin
344
- str.unpack('U*')
345
- true
346
- rescue ArgumentError
347
- false
348
- end
349
- end
350
-
351
- # Returns the number of grapheme clusters in the string. This method is very likely to be moved or renamed
352
- # in future versions.
353
- def g_length(str)
354
- g_unpack(str).length
355
- end
356
-
357
- # Replaces all the non-utf-8 bytes by their iso-8859-1 or cp1252 equivalent resulting in a valid utf-8 string
358
- def tidy_bytes(str)
359
- str.split(//u).map do |c|
360
- if !UTF8_PAT.match(c)
361
- n = c.unpack('C')[0]
362
- n < 128 ? n.chr :
363
- n < 160 ? [UCD.cp1252[n] || n].pack('U') :
364
- n < 192 ? "\xC2" + n.chr : "\xC3" + (n-64).chr
365
- else
366
- c
367
- end
368
- end.join
369
- end
370
-
371
- protected
372
-
373
- # Detect whether the codepoint is in a certain character class. Primarily used by the
374
- # grapheme cluster support.
375
- def in_char_class?(codepoint, classes)
376
- classes.detect { |c| UCD.boundary[c] === codepoint } ? true : false
377
- end
378
-
379
- # Unpack the string at codepoints boundaries
380
- def u_unpack(str)
381
- begin
382
- str.unpack 'U*'
383
- rescue ArgumentError
384
- raise EncodingError.new('malformed UTF-8 character')
385
- end
386
- end
387
-
388
- # Unpack the string at grapheme boundaries instead of codepoint boundaries
389
- def g_unpack(str)
390
- codepoints = u_unpack(str)
391
- unpacked = []
392
- pos = 0
393
- marker = 0
394
- eoc = codepoints.length
395
- while(pos < eoc)
396
- pos += 1
397
- previous = codepoints[pos-1]
398
- current = codepoints[pos]
399
- if (
400
- # CR X LF
401
- one = ( previous == UCD.boundary[:cr] and current == UCD.boundary[:lf] ) or
402
- # L X (L|V|LV|LVT)
403
- two = ( UCD.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
404
- # (LV|V) X (V|T)
405
- three = ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
406
- # (LVT|T) X (T)
407
- four = ( in_char_class?(previous, [:lvt,:t]) and UCD.boundary[:t] === current ) or
408
- # X Extend
409
- five = (UCD.boundary[:extend] === current)
410
- )
411
- else
412
- unpacked << codepoints[marker..pos-1]
413
- marker = pos
414
- end
415
- end
416
- unpacked
417
- end
418
-
419
- # Reverse operation of g_unpack
420
- def g_pack(unpacked)
421
- unpacked.flatten
422
- end
423
-
424
- # Justifies a string in a certain way. Valid values for <tt>way</tt> are <tt>:right</tt>, <tt>:left</tt> and
425
- # <tt>:center</tt>. Is primarily used as a helper method by <tt>rjust</tt>, <tt>ljust</tt> and <tt>center</tt>.
426
- def justify(str, integer, way, padstr=' ')
427
- raise ArgumentError, "zero width padding" if padstr.length == 0
428
- padsize = integer - size(str)
429
- padsize = padsize > 0 ? padsize : 0
430
- case way
431
- when :right
432
- str.dup.insert(0, padding(padsize, padstr))
433
- when :left
434
- str.dup.insert(-1, padding(padsize, padstr))
435
- when :center
436
- lpad = padding((padsize / 2.0).floor, padstr)
437
- rpad = padding((padsize / 2.0).ceil, padstr)
438
- str.dup.insert(0, lpad).insert(-1, rpad)
439
- end
440
- end
441
-
442
- # Generates a padding string of a certain size.
443
- def padding(padsize, padstr=' ')
444
- if padsize != 0
445
- slice(padstr * ((padsize / size(padstr)) + 1), 0, padsize)
446
- else
447
- ''
448
- end
449
- end
450
-
451
- # Convert characters to a different case
452
- def to_case(way, str)
453
- u_unpack(str).map do |codepoint|
454
- cp = UCD[codepoint]
455
- unless cp.nil?
456
- ncp = cp.send(way)
457
- ncp > 0 ? ncp : codepoint
458
- else
459
- codepoint
460
- end
461
- end.pack('U*')
462
- end
463
-
464
- # Re-order codepoints so the string becomes canonical
465
- def reorder_characters(codepoints)
466
- length = codepoints.length- 1
467
- pos = 0
468
- while pos < length do
469
- cp1, cp2 = UCD[codepoints[pos]], UCD[codepoints[pos+1]]
470
- if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
471
- codepoints[pos..pos+1] = cp2.code, cp1.code
472
- pos += (pos > 0 ? -1 : 1)
473
- else
474
- pos += 1
475
- end
476
- end
477
- codepoints
478
- end
479
-
480
- # Decompose composed characters to the decomposed form
481
- def decompose_codepoints(type, codepoints)
482
- codepoints.inject([]) do |decomposed, cp|
483
- # if it's a hangul syllable starter character
484
- if HANGUL_SBASE <= cp and cp < HANGUL_SLAST
485
- sindex = cp - HANGUL_SBASE
486
- ncp = [] # new codepoints
487
- ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
488
- ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
489
- tindex = sindex % HANGUL_TCOUNT
490
- ncp << (HANGUL_TBASE + tindex) unless tindex == 0
491
- decomposed.concat ncp
492
- # if the codepoint is decomposable in with the current decomposition type
493
- elsif (ncp = UCD[cp].decomp_mapping) and (!UCD[cp].decomp_type || type == :compatability)
494
- decomposed.concat decompose_codepoints(type, ncp.dup)
495
- else
496
- decomposed << cp
497
- end
498
- end
499
- end
500
-
501
- # Compose decomposed characters to the composed form
502
- def compose_codepoints(codepoints)
503
- pos = 0
504
- eoa = codepoints.length - 1
505
- starter_pos = 0
506
- starter_char = codepoints[0]
507
- previous_combining_class = -1
508
- while pos < eoa
509
- pos += 1
510
- lindex = starter_char - HANGUL_LBASE
511
- # -- Hangul
512
- if 0 <= lindex and lindex < HANGUL_LCOUNT
513
- vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
514
- if 0 <= vindex and vindex < HANGUL_VCOUNT
515
- tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
516
- if 0 <= tindex and tindex < HANGUL_TCOUNT
517
- j = starter_pos + 2
518
- eoa -= 2
519
- else
520
- tindex = 0
521
- j = starter_pos + 1
522
- eoa -= 1
523
- end
524
- codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
525
- end
526
- starter_pos += 1
527
- starter_char = codepoints[starter_pos]
528
- # -- Other characters
529
- else
530
- current_char = codepoints[pos]
531
- current = UCD[current_char]
532
- if current.combining_class > previous_combining_class
533
- if ref = UCD.composition_map[starter_char]
534
- composition = ref[current_char]
535
- else
536
- composition = nil
537
- end
538
- unless composition.nil?
539
- codepoints[starter_pos] = composition
540
- starter_char = composition
541
- codepoints.delete_at pos
542
- eoa -= 1
543
- pos -= 1
544
- previous_combining_class = -1
545
- else
546
- previous_combining_class = current.combining_class
547
- end
548
- else
549
- previous_combining_class = current.combining_class
550
- end
551
- if current.combining_class == 0
552
- starter_pos = pos
553
- starter_char = codepoints[pos]
554
- end
555
- end
556
- end
557
- codepoints
558
- end
559
-
560
- # UniCode Database
561
- UCD = UnicodeDatabase.new
562
- end
563
- end
564
- end