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.
- data/CHANGELOG +121 -1
- data/README.rdoc +33 -0
- data/lib/active_support.rb +42 -4
- data/lib/active_support/backtrace_cleaner.rb +31 -9
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/buffered_logger.rb +5 -2
- data/lib/active_support/builder.rb +6 -0
- data/lib/active_support/cache.rb +454 -84
- data/lib/active_support/cache/compressed_mem_cache_store.rb +6 -13
- data/lib/active_support/cache/file_store.rb +140 -41
- data/lib/active_support/cache/mem_cache_store.rb +121 -76
- data/lib/active_support/cache/memory_store.rb +127 -27
- data/lib/active_support/cache/strategy/local_cache.rb +111 -58
- data/lib/active_support/cache/synchronized_memory_store.rb +2 -38
- data/lib/active_support/callbacks.rb +105 -76
- data/lib/active_support/configurable.rb +19 -18
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/conversions.rb +29 -54
- data/lib/active_support/core_ext/array/extract_options.rb +16 -1
- data/lib/active_support/core_ext/array/grouping.rb +1 -1
- data/lib/active_support/core_ext/array/random_access.rb +26 -5
- data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +13 -9
- data/lib/active_support/core_ext/benchmark.rb +0 -12
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +2 -0
- data/lib/active_support/core_ext/class.rb +2 -1
- data/lib/active_support/core_ext/class/attribute.rb +67 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +33 -27
- data/lib/active_support/core_ext/class/delegating_attributes.rb +35 -41
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +23 -14
- data/lib/active_support/core_ext/class/subclasses.rb +50 -0
- data/lib/active_support/core_ext/date/calculations.rb +35 -12
- data/lib/active_support/core_ext/date/conversions.rb +5 -5
- data/lib/active_support/core_ext/date/zones.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +24 -5
- data/lib/active_support/core_ext/date_time/zones.rb +4 -0
- data/lib/active_support/core_ext/enumerable.rb +5 -9
- data/lib/active_support/core_ext/exception.rb +0 -47
- data/lib/active_support/core_ext/file.rb +1 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -2
- data/lib/active_support/core_ext/file/path.rb +5 -0
- data/lib/active_support/core_ext/float/rounding.rb +3 -2
- data/lib/active_support/core_ext/hash/conversions.rb +65 -145
- data/lib/active_support/core_ext/hash/deep_merge.rb +6 -7
- data/lib/active_support/core_ext/hash/except.rb +8 -1
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -0
- data/lib/active_support/core_ext/hash/keys.rb +10 -11
- data/lib/active_support/core_ext/hash/slice.rb +6 -0
- data/lib/active_support/core_ext/integer.rb +1 -1
- data/lib/active_support/core_ext/integer/multiple.rb +6 -0
- data/lib/active_support/core_ext/kernel.rb +1 -1
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -1
- data/lib/active_support/core_ext/kernel/requires.rb +2 -2
- data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
- data/lib/active_support/core_ext/load_error.rb +17 -30
- data/lib/active_support/core_ext/logger.rb +2 -40
- data/lib/active_support/core_ext/module.rb +5 -3
- data/lib/active_support/core_ext/module/aliasing.rb +1 -1
- data/lib/active_support/core_ext/module/anonymous.rb +24 -0
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +20 -22
- data/lib/active_support/core_ext/module/delegation.rb +21 -10
- data/lib/active_support/core_ext/module/introspection.rb +8 -8
- data/lib/active_support/core_ext/module/method_names.rb +14 -0
- data/lib/active_support/core_ext/module/reachable.rb +10 -0
- data/lib/active_support/core_ext/module/remove_method.rb +11 -0
- data/lib/active_support/core_ext/module/synchronization.rb +2 -1
- data/lib/active_support/core_ext/name_error.rb +3 -1
- data/lib/active_support/core_ext/object.rb +5 -3
- data/lib/active_support/core_ext/object/blank.rb +20 -2
- data/lib/active_support/core_ext/object/conversions.rb +2 -16
- data/lib/active_support/core_ext/object/duplicable.rb +23 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +0 -7
- data/lib/active_support/core_ext/object/to_json.rb +19 -0
- data/lib/active_support/core_ext/object/to_param.rb +49 -0
- data/lib/active_support/core_ext/object/to_query.rb +27 -0
- data/lib/active_support/core_ext/object/with_options.rb +2 -0
- data/lib/active_support/core_ext/proc.rb +4 -4
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +0 -22
- data/lib/active_support/core_ext/rexml.rb +4 -1
- data/lib/active_support/core_ext/string.rb +3 -2
- data/lib/active_support/core_ext/string/access.rb +4 -2
- data/lib/active_support/core_ext/string/conversions.rb +28 -1
- data/lib/active_support/core_ext/string/encoding.rb +11 -0
- data/lib/active_support/core_ext/string/exclude.rb +6 -0
- data/lib/active_support/core_ext/string/filters.rb +29 -0
- data/lib/active_support/core_ext/string/inflections.rb +12 -12
- data/lib/active_support/core_ext/string/interpolation.rb +2 -92
- data/lib/active_support/core_ext/string/multibyte.rb +16 -19
- data/lib/active_support/core_ext/string/output_safety.rb +101 -35
- data/lib/active_support/core_ext/string/starts_ends_with.rb +0 -14
- data/lib/active_support/core_ext/string/xchar.rb +1 -1
- data/lib/active_support/core_ext/time/calculations.rb +14 -7
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/core_ext/time/marshal.rb +56 -0
- data/lib/active_support/core_ext/time/zones.rb +2 -5
- data/lib/active_support/core_ext/uri.rb +10 -4
- data/lib/active_support/dependencies.rb +200 -197
- data/lib/active_support/dependencies/autoload.rb +50 -0
- data/lib/active_support/deprecation/behaviors.rb +13 -9
- data/lib/active_support/deprecation/method_wrappers.rb +10 -9
- data/lib/active_support/deprecation/proxy_wrappers.rb +7 -0
- data/lib/active_support/deprecation/reporting.rb +5 -3
- data/lib/active_support/descendants_tracker.rb +43 -0
- data/lib/active_support/duration.rb +8 -4
- data/lib/active_support/file_update_checker.rb +36 -0
- data/lib/active_support/hash_with_indifferent_access.rb +9 -1
- data/lib/active_support/i18n.rb +9 -0
- data/lib/active_support/i18n_railtie.rb +81 -0
- data/lib/active_support/inflections.rb +1 -1
- data/lib/active_support/inflector.rb +4 -407
- data/lib/active_support/inflector/inflections.rb +211 -0
- data/lib/active_support/inflector/methods.rb +151 -0
- data/lib/active_support/inflector/transliterate.rb +97 -0
- data/lib/active_support/json/backends/jsongem.rb +12 -9
- data/lib/active_support/json/backends/yajl.rb +40 -0
- data/lib/active_support/json/backends/yaml.rb +1 -1
- data/lib/active_support/json/decoding.rb +17 -2
- data/lib/active_support/json/encoding.rb +48 -31
- data/lib/active_support/json/variable.rb +2 -4
- data/lib/active_support/lazy_load_hooks.rb +27 -0
- data/lib/active_support/locale/en.yml +5 -2
- data/lib/active_support/log_subscriber.rb +123 -0
- data/lib/active_support/log_subscriber/test_helper.rb +99 -0
- data/lib/active_support/memoizable.rb +1 -1
- data/lib/active_support/message_encryptor.rb +1 -0
- data/lib/active_support/message_verifier.rb +2 -1
- data/lib/active_support/multibyte.rb +8 -23
- data/lib/active_support/multibyte/chars.rb +213 -446
- data/lib/active_support/multibyte/unicode.rb +392 -0
- data/lib/active_support/multibyte/utils.rb +6 -7
- data/lib/active_support/notifications.rb +29 -122
- data/lib/active_support/notifications/fanout.rb +61 -0
- data/lib/active_support/notifications/instrumenter.rb +54 -0
- data/lib/active_support/ordered_hash.rb +59 -14
- data/lib/active_support/ordered_options.rb +6 -0
- data/lib/active_support/railtie.rb +60 -0
- data/lib/active_support/rescuable.rb +7 -4
- data/lib/active_support/ruby/shim.rb +4 -6
- data/lib/active_support/test_case.rb +2 -7
- data/lib/active_support/testing/assertions.rb +15 -0
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/isolation.rb +64 -17
- data/lib/active_support/testing/performance.rb +306 -335
- data/lib/active_support/testing/setup_and_teardown.rb +51 -29
- data/lib/active_support/time.rb +24 -3
- data/lib/active_support/time_with_zone.rb +10 -14
- data/lib/active_support/values/time_zone.rb +192 -234
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -2
- data/lib/active_support/whiny_nil.rb +9 -7
- data/lib/active_support/xml_mini.rb +130 -1
- data/lib/active_support/xml_mini/jdom.rb +2 -0
- data/lib/active_support/xml_mini/libxml.rb +23 -86
- data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
- data/lib/active_support/xml_mini/nokogiri.rb +27 -24
- data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
- data/lib/active_support/xml_mini/rexml.rb +8 -2
- metadata +62 -195
- data/README +0 -43
- data/lib/active_support/autoload.rb +0 -28
- data/lib/active_support/core_ext/boolean.rb +0 -1
- data/lib/active_support/core_ext/boolean/conversions.rb +0 -11
- data/lib/active_support/core_ext/class/removal.rb +0 -53
- data/lib/active_support/core_ext/date.rb +0 -7
- data/lib/active_support/core_ext/date_time.rb +0 -5
- data/lib/active_support/core_ext/integer/even_odd.rb +0 -16
- data/lib/active_support/core_ext/kernel/daemonizing.rb +0 -7
- data/lib/active_support/core_ext/module/inclusion.rb +0 -30
- data/lib/active_support/core_ext/module/loading.rb +0 -23
- data/lib/active_support/core_ext/nil.rb +0 -1
- data/lib/active_support/core_ext/nil/conversions.rb +0 -5
- data/lib/active_support/core_ext/object/extending.rb +0 -80
- data/lib/active_support/core_ext/object/metaclass.rb +0 -13
- data/lib/active_support/core_ext/object/misc.rb +0 -3
- data/lib/active_support/core_ext/object/returning.rb +0 -42
- data/lib/active_support/core_ext/object/tap.rb +0 -16
- data/lib/active_support/core_ext/string/bytesize.rb +0 -5
- data/lib/active_support/core_ext/string/iterators.rb +0 -13
- data/lib/active_support/core_ext/symbol.rb +0 -1
- data/lib/active_support/core_ext/symbol/to_proc.rb +0 -14
- data/lib/active_support/core_ext/time.rb +0 -10
- data/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +0 -22
- data/lib/active_support/deprecated_callbacks.rb +0 -283
- data/lib/active_support/multibyte/unicode_database.rb +0 -71
- data/lib/active_support/vendor.rb +0 -16
- data/lib/active_support/vendor/builder-2.1.2/lib/blankslate.rb +0 -113
- data/lib/active_support/vendor/builder-2.1.2/lib/builder.rb +0 -13
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/blankslate.rb +0 -20
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/css.rb +0 -250
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xchar.rb +0 -115
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlbase.rb +0 -139
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlevents.rb +0 -63
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlmarkup.rb +0 -328
- data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +0 -20
- data/lib/active_support/vendor/i18n-0.1.3/README.textile +0 -20
- data/lib/active_support/vendor/i18n-0.1.3/Rakefile +0 -5
- data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +0 -27
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb +0 -204
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb +0 -215
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb +0 -53
- data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +0 -5
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +0 -99
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +0 -124
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +0 -1
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +0 -3
- data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +0 -567
- data/lib/active_support/vendor/memcache-client-1.7.5/lib/memcache.rb +0 -1133
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo.rb +0 -33
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone.rb +0 -47
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone_info.rb +0 -228
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Algiers.rb +0 -55
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Cairo.rb +0 -219
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Casablanca.rb +0 -42
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Harare.rb +0 -18
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Johannesburg.rb +0 -25
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Monrovia.rb +0 -22
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Nairobi.rb +0 -23
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +0 -166
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/San_Juan.rb +0 -86
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Bogota.rb +0 -23
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Caracas.rb +0 -23
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chicago.rb +0 -283
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chihuahua.rb +0 -136
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Denver.rb +0 -204
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Godthab.rb +0 -161
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Guatemala.rb +0 -27
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Halifax.rb +0 -274
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Indiana/Indianapolis.rb +0 -149
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Juneau.rb +0 -194
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/La_Paz.rb +0 -22
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Lima.rb +0 -35
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Los_Angeles.rb +0 -232
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mazatlan.rb +0 -139
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mexico_City.rb +0 -144
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Monterrey.rb +0 -131
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/New_York.rb +0 -282
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Phoenix.rb +0 -30
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Regina.rb +0 -74
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Santiago.rb +0 -205
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Sao_Paulo.rb +0 -171
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/St_Johns.rb +0 -288
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Tijuana.rb +0 -196
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Almaty.rb +0 -67
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baghdad.rb +0 -73
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baku.rb +0 -161
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Bangkok.rb +0 -20
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Chongqing.rb +0 -33
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Colombo.rb +0 -30
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Dhaka.rb +0 -27
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Hong_Kong.rb +0 -87
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Irkutsk.rb +0 -165
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jakarta.rb +0 -30
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jerusalem.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kabul.rb +0 -20
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kamchatka.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Karachi.rb +0 -32
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kathmandu.rb +0 -20
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kolkata.rb +0 -25
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Krasnoyarsk.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuala_Lumpur.rb +0 -31
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuwait.rb +0 -18
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Magadan.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Muscat.rb +0 -18
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Novosibirsk.rb +0 -164
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Rangoon.rb +0 -24
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Riyadh.rb +0 -18
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Seoul.rb +0 -34
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Shanghai.rb +0 -35
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Singapore.rb +0 -33
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Taipei.rb +0 -59
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tashkent.rb +0 -47
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tbilisi.rb +0 -78
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tehran.rb +0 -121
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tokyo.rb +0 -30
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Ulaanbaatar.rb +0 -65
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Urumqi.rb +0 -33
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Vladivostok.rb +0 -164
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yakutsk.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yekaterinburg.rb +0 -165
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yerevan.rb +0 -165
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Azores.rb +0 -270
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Cape_Verde.rb +0 -23
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/South_Georgia.rb +0 -18
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Adelaide.rb +0 -187
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Brisbane.rb +0 -35
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Darwin.rb +0 -29
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Hobart.rb +0 -193
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Melbourne.rb +0 -185
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Perth.rb +0 -37
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Sydney.rb +0 -185
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Etc/UTC.rb +0 -16
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Amsterdam.rb +0 -228
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Athens.rb +0 -185
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Belgrade.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Berlin.rb +0 -188
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bratislava.rb +0 -13
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Brussels.rb +0 -232
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bucharest.rb +0 -181
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Budapest.rb +0 -197
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Copenhagen.rb +0 -179
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Dublin.rb +0 -276
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Helsinki.rb +0 -163
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Istanbul.rb +0 -218
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Kiev.rb +0 -168
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Lisbon.rb +0 -268
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Ljubljana.rb +0 -13
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/London.rb +0 -288
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Madrid.rb +0 -211
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Minsk.rb +0 -170
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Moscow.rb +0 -181
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Paris.rb +0 -232
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Prague.rb +0 -187
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Riga.rb +0 -176
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Rome.rb +0 -215
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sarajevo.rb +0 -13
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Skopje.rb +0 -13
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sofia.rb +0 -173
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Stockholm.rb +0 -165
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Tallinn.rb +0 -172
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vienna.rb +0 -183
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vilnius.rb +0 -170
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Warsaw.rb +0 -212
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Zagreb.rb +0 -13
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Auckland.rb +0 -202
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Fiji.rb +0 -23
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Guam.rb +0 -22
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Honolulu.rb +0 -28
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Majuro.rb +0 -20
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Midway.rb +0 -25
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Noumea.rb +0 -25
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Pago_Pago.rb +0 -26
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Port_Moresby.rb +0 -20
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Tongatapu.rb +0 -27
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/info_timezone.rb +0 -52
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone.rb +0 -51
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone_info.rb +0 -44
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/offset_rationals.rb +0 -98
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/ruby_core_support.rb +0 -56
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/time_or_datetime.rb +0 -292
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone.rb +0 -508
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_definition.rb +0 -56
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_info.rb +0 -40
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_offset_info.rb +0 -94
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_period.rb +0 -198
- 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
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
53
|
-
|
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 |
|
19
|
-
# @events <<
|
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
|
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
|
-
|
40
|
+
autoload :Instrumenter, 'active_support/notifications/instrumenter'
|
41
|
+
autoload :Event, 'active_support/notifications/instrumenter'
|
42
|
+
autoload :Fanout, 'active_support/notifications/fanout'
|
45
43
|
|
46
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
132
|
-
|
58
|
+
def subscribe(*args, &block)
|
59
|
+
notifier.subscribe(*args, &block).tap do
|
60
|
+
@instrumenters.clear
|
61
|
+
end
|
133
62
|
end
|
134
63
|
|
135
|
-
def
|
136
|
-
|
64
|
+
def unsubscribe(*args)
|
65
|
+
notifier.unsubscribe(*args)
|
66
|
+
@instrumenters.clear
|
137
67
|
end
|
138
68
|
|
139
|
-
def
|
140
|
-
|
141
|
-
@listeners.each { |l| l.publish(*event) }
|
142
|
-
end
|
69
|
+
def notifier
|
70
|
+
@notifier ||= Fanout.new
|
143
71
|
end
|
144
72
|
|
145
|
-
|
146
|
-
|
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
|