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
@@ -1,24 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
require 'active_support/core_ext/module/attribute_accessors'
|
4
3
|
|
5
4
|
module ActiveSupport #:nodoc:
|
6
5
|
module Multibyte
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# The Unicode version that is supported by the implementation
|
12
|
-
UNICODE_VERSION = '5.1.0'
|
13
|
-
|
14
|
-
# The default normalization used for operations that require normalization. It can be set to any of the
|
15
|
-
# normalizations in NORMALIZATION_FORMS.
|
16
|
-
#
|
17
|
-
# Example:
|
18
|
-
# ActiveSupport::Multibyte.default_normalization_form = :c
|
19
|
-
mattr_accessor :default_normalization_form
|
20
|
-
self.default_normalization_form = :kc
|
21
|
-
|
6
|
+
autoload :EncodingError, 'active_support/multibyte/exceptions'
|
7
|
+
autoload :Chars, 'active_support/multibyte/chars'
|
8
|
+
autoload :Unicode, 'active_support/multibyte/unicode'
|
9
|
+
|
22
10
|
# The proxy class returned when calling mb_chars. You can use this accessor to configure your own proxy
|
23
11
|
# class so you can support other encodings. See the ActiveSupport::Multibyte::Chars implementation for
|
24
12
|
# an example how to do this.
|
@@ -29,7 +17,7 @@ module ActiveSupport #:nodoc:
|
|
29
17
|
@proxy_class = klass
|
30
18
|
end
|
31
19
|
|
32
|
-
# Returns the
|
20
|
+
# Returns the current proxy class
|
33
21
|
def self.proxy_class
|
34
22
|
@proxy_class ||= ActiveSupport::Multibyte::Chars
|
35
23
|
end
|
@@ -47,13 +35,10 @@ module ActiveSupport #:nodoc:
|
|
47
35
|
\xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn,
|
48
36
|
# Quick check for valid Shift-JIS characters, disregards the odd-even pairing
|
49
37
|
'Shift_JIS' => /\A(?:
|
50
|
-
[\x00-\x7e
|
51
|
-
[\x81-\x9f
|
38
|
+
[\x00-\x7e\xa1-\xdf] |
|
39
|
+
[\x81-\x9f\xe0-\xef] [\x40-\x7e\x80-\x9e\x9f-\xfc])\z /xn
|
52
40
|
}
|
53
41
|
end
|
54
42
|
end
|
55
43
|
|
56
|
-
require 'active_support/multibyte/
|
57
|
-
require 'active_support/multibyte/exceptions'
|
58
|
-
require 'active_support/multibyte/unicode_database'
|
59
|
-
require 'active_support/multibyte/utils'
|
44
|
+
require 'active_support/multibyte/utils'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/string/access'
|
2
3
|
require 'active_support/core_ext/string/behavior'
|
3
4
|
|
4
5
|
module ActiveSupport #:nodoc:
|
@@ -18,7 +19,7 @@ module ActiveSupport #:nodoc:
|
|
18
19
|
# bad.explicit_checking_method "T".mb_chars.downcase.to_s
|
19
20
|
#
|
20
21
|
# The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different
|
21
|
-
# encodings you can write your own multibyte string handler and configure it through
|
22
|
+
# encodings you can write your own multibyte string handler and configure it through
|
22
23
|
# ActiveSupport::Multibyte.proxy_class.
|
23
24
|
#
|
24
25
|
# class CharsForUTF32
|
@@ -33,54 +34,11 @@ module ActiveSupport #:nodoc:
|
|
33
34
|
#
|
34
35
|
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
35
36
|
class Chars
|
36
|
-
# Hangul character boundaries and properties
|
37
|
-
HANGUL_SBASE = 0xAC00
|
38
|
-
HANGUL_LBASE = 0x1100
|
39
|
-
HANGUL_VBASE = 0x1161
|
40
|
-
HANGUL_TBASE = 0x11A7
|
41
|
-
HANGUL_LCOUNT = 19
|
42
|
-
HANGUL_VCOUNT = 21
|
43
|
-
HANGUL_TCOUNT = 28
|
44
|
-
HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
|
45
|
-
HANGUL_SCOUNT = 11172
|
46
|
-
HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
|
47
|
-
HANGUL_JAMO_FIRST = 0x1100
|
48
|
-
HANGUL_JAMO_LAST = 0x11FF
|
49
|
-
|
50
|
-
# All the unicode whitespace
|
51
|
-
UNICODE_WHITESPACE = [
|
52
|
-
(0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
|
53
|
-
0x0020, # White_Space # Zs SPACE
|
54
|
-
0x0085, # White_Space # Cc <control-0085>
|
55
|
-
0x00A0, # White_Space # Zs NO-BREAK SPACE
|
56
|
-
0x1680, # White_Space # Zs OGHAM SPACE MARK
|
57
|
-
0x180E, # White_Space # Zs MONGOLIAN VOWEL SEPARATOR
|
58
|
-
(0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
|
59
|
-
0x2028, # White_Space # Zl LINE SEPARATOR
|
60
|
-
0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
|
61
|
-
0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
|
62
|
-
0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
|
63
|
-
0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
|
64
|
-
].flatten.freeze
|
65
|
-
|
66
|
-
# BOM (byte order mark) can also be seen as whitespace, it's a non-rendering character used to distinguish
|
67
|
-
# between little and big endian. This is not an issue in utf-8, so it must be ignored.
|
68
|
-
UNICODE_LEADERS_AND_TRAILERS = UNICODE_WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
|
69
|
-
|
70
|
-
# Returns a regular expression pattern that matches the passed Unicode codepoints
|
71
|
-
def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
|
72
|
-
array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
|
73
|
-
end
|
74
|
-
UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/
|
75
|
-
UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/
|
76
|
-
|
77
|
-
UTF8_PAT = ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8']
|
78
|
-
|
79
37
|
attr_reader :wrapped_string
|
80
38
|
alias to_s wrapped_string
|
81
39
|
alias to_str wrapped_string
|
82
40
|
|
83
|
-
if
|
41
|
+
if RUBY_VERSION >= "1.9"
|
84
42
|
# Creates a new Chars instance by wrapping _string_.
|
85
43
|
def initialize(string)
|
86
44
|
@wrapped_string = string
|
@@ -114,12 +72,6 @@ module ActiveSupport #:nodoc:
|
|
114
72
|
true
|
115
73
|
end
|
116
74
|
|
117
|
-
# Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
|
118
|
-
# +false+ otherwise.
|
119
|
-
def self.wants?(string)
|
120
|
-
$KCODE == 'UTF8' && consumes?(string)
|
121
|
-
end
|
122
|
-
|
123
75
|
# Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise.
|
124
76
|
def self.consumes?(string)
|
125
77
|
# Unpack is a little bit faster than regular expressions.
|
@@ -141,79 +93,160 @@ module ActiveSupport #:nodoc:
|
|
141
93
|
@wrapped_string <=> other.to_s
|
142
94
|
end
|
143
95
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
96
|
+
if RUBY_VERSION < "1.9"
|
97
|
+
# Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
|
98
|
+
# +false+ otherwise.
|
99
|
+
def self.wants?(string)
|
100
|
+
$KCODE == 'UTF8' && consumes?(string)
|
101
|
+
end
|
151
102
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
103
|
+
# Returns a new Chars object containing the _other_ object concatenated to the string.
|
104
|
+
#
|
105
|
+
# Example:
|
106
|
+
# ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
|
107
|
+
def +(other)
|
108
|
+
chars(@wrapped_string + other)
|
109
|
+
end
|
159
110
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end
|
111
|
+
# Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
|
112
|
+
#
|
113
|
+
# Example:
|
114
|
+
# 'Café périferôl'.mb_chars =~ /ô/ #=> 12
|
115
|
+
def =~(other)
|
116
|
+
translate_offset(@wrapped_string =~ other)
|
117
|
+
end
|
168
118
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
119
|
+
# Inserts the passed string at specified codepoint offsets.
|
120
|
+
#
|
121
|
+
# Example:
|
122
|
+
# 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
|
123
|
+
def insert(offset, fragment)
|
124
|
+
unpacked = Unicode.u_unpack(@wrapped_string)
|
125
|
+
unless offset > unpacked.length
|
126
|
+
@wrapped_string.replace(
|
127
|
+
Unicode.u_unpack(@wrapped_string).insert(offset, *Unicode.u_unpack(fragment)).pack('U*')
|
128
|
+
)
|
129
|
+
else
|
130
|
+
raise IndexError, "index #{offset} out of string"
|
131
|
+
end
|
132
|
+
self
|
181
133
|
end
|
182
|
-
self
|
183
|
-
end
|
184
134
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
135
|
+
# Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
|
136
|
+
#
|
137
|
+
# Example:
|
138
|
+
# 'Café'.mb_chars.include?('é') #=> true
|
139
|
+
def include?(other)
|
140
|
+
# We have to redefine this method because Enumerable defines it.
|
141
|
+
@wrapped_string.include?(other)
|
142
|
+
end
|
193
143
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
144
|
+
# Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
|
145
|
+
#
|
146
|
+
# Example:
|
147
|
+
# 'Café périferôl'.mb_chars.index('ô') #=> 12
|
148
|
+
# 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
|
149
|
+
def index(needle, offset=0)
|
150
|
+
wrapped_offset = first(offset).wrapped_string.length
|
151
|
+
index = @wrapped_string.index(needle, wrapped_offset)
|
152
|
+
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
153
|
+
end
|
154
|
+
|
155
|
+
# Returns the position _needle_ in the string, counting in
|
156
|
+
# codepoints, searching backward from _offset_ or the end of the
|
157
|
+
# string. Returns +nil+ if _needle_ isn't found.
|
158
|
+
#
|
159
|
+
# Example:
|
160
|
+
# 'Café périferôl'.mb_chars.rindex('é') #=> 6
|
161
|
+
# 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
|
162
|
+
def rindex(needle, offset=nil)
|
163
|
+
offset ||= length
|
164
|
+
wrapped_offset = first(offset).wrapped_string.length
|
165
|
+
index = @wrapped_string.rindex(needle, wrapped_offset)
|
166
|
+
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
167
|
+
end
|
168
|
+
|
169
|
+
# Returns the number of codepoints in the string
|
170
|
+
def size
|
171
|
+
Unicode.u_unpack(@wrapped_string).size
|
172
|
+
end
|
173
|
+
alias_method :length, :size
|
174
|
+
|
175
|
+
# Strips entire range of Unicode whitespace from the right of the string.
|
176
|
+
def rstrip
|
177
|
+
chars(@wrapped_string.gsub(Unicode::TRAILERS_PAT, ''))
|
178
|
+
end
|
179
|
+
|
180
|
+
# Strips entire range of Unicode whitespace from the left of the string.
|
181
|
+
def lstrip
|
182
|
+
chars(@wrapped_string.gsub(Unicode::LEADERS_PAT, ''))
|
183
|
+
end
|
184
|
+
|
185
|
+
# Strips entire range of Unicode whitespace from the right and left of the string.
|
186
|
+
def strip
|
187
|
+
rstrip.lstrip
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns the codepoint of the first character in the string.
|
191
|
+
#
|
192
|
+
# Example:
|
193
|
+
# 'こんにちは'.mb_chars.ord #=> 12371
|
194
|
+
def ord
|
195
|
+
Unicode.u_unpack(@wrapped_string)[0]
|
196
|
+
end
|
197
|
+
|
198
|
+
# Works just like <tt>String#rjust</tt>, only integer specifies characters instead of bytes.
|
199
|
+
#
|
200
|
+
# Example:
|
201
|
+
#
|
202
|
+
# "¾ cup".mb_chars.rjust(8).to_s
|
203
|
+
# #=> " ¾ cup"
|
204
|
+
#
|
205
|
+
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
206
|
+
# #=> " ¾ cup"
|
207
|
+
def rjust(integer, padstr=' ')
|
208
|
+
justify(integer, :right, padstr)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Works just like <tt>String#ljust</tt>, only integer specifies characters instead of bytes.
|
212
|
+
#
|
213
|
+
# Example:
|
214
|
+
#
|
215
|
+
# "¾ cup".mb_chars.rjust(8).to_s
|
216
|
+
# #=> "¾ cup "
|
217
|
+
#
|
218
|
+
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
219
|
+
# #=> "¾ cup "
|
220
|
+
def ljust(integer, padstr=' ')
|
221
|
+
justify(integer, :left, padstr)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Works just like <tt>String#center</tt>, only integer specifies characters instead of bytes.
|
225
|
+
#
|
226
|
+
# Example:
|
227
|
+
#
|
228
|
+
# "¾ cup".mb_chars.center(8).to_s
|
229
|
+
# #=> " ¾ cup "
|
230
|
+
#
|
231
|
+
# "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
|
232
|
+
# #=> " ¾ cup "
|
233
|
+
def center(integer, padstr=' ')
|
234
|
+
justify(integer, :center, padstr)
|
235
|
+
end
|
236
|
+
|
237
|
+
else
|
238
|
+
def =~(other)
|
239
|
+
@wrapped_string =~ other
|
240
|
+
end
|
203
241
|
end
|
204
242
|
|
205
|
-
#
|
206
|
-
#
|
207
|
-
# string. Returns +nil+ if _needle_ isn't found.
|
243
|
+
# Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars
|
244
|
+
# instances instead of String. This makes chaining methods easier.
|
208
245
|
#
|
209
246
|
# Example:
|
210
|
-
# 'Café périferôl'.mb_chars.
|
211
|
-
|
212
|
-
|
213
|
-
offset ||= length
|
214
|
-
wrapped_offset = self.first(offset).wrapped_string.length
|
215
|
-
index = @wrapped_string.rindex(needle, wrapped_offset)
|
216
|
-
index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
247
|
+
# 'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } #=> ["CAF", " P", "RIFERÔL"]
|
248
|
+
def split(*args)
|
249
|
+
@wrapped_string.split(*args).map { |i| i.mb_chars }
|
217
250
|
end
|
218
251
|
|
219
252
|
# Like <tt>String#[]=</tt>, except instead of byte offsets you specify character offsets.
|
@@ -235,7 +268,7 @@ module ActiveSupport #:nodoc:
|
|
235
268
|
if args.first.is_a?(Regexp)
|
236
269
|
@wrapped_string[*args] = replace_by
|
237
270
|
else
|
238
|
-
result =
|
271
|
+
result = Unicode.u_unpack(@wrapped_string)
|
239
272
|
if args[0].is_a?(Fixnum)
|
240
273
|
raise IndexError, "index #{args[0]} out of string" if args[0] >= result.length
|
241
274
|
min = args[0]
|
@@ -248,80 +281,20 @@ module ActiveSupport #:nodoc:
|
|
248
281
|
else
|
249
282
|
needle = args[0].to_s
|
250
283
|
min = index(needle)
|
251
|
-
max = min +
|
284
|
+
max = min + Unicode.u_unpack(needle).length - 1
|
252
285
|
range = Range.new(min, max)
|
253
286
|
end
|
254
|
-
result[range] =
|
287
|
+
result[range] = Unicode.u_unpack(replace_by)
|
255
288
|
@wrapped_string.replace(result.pack('U*'))
|
256
289
|
end
|
257
290
|
end
|
258
291
|
|
259
|
-
# Works just like <tt>String#rjust</tt>, only integer specifies characters instead of bytes.
|
260
|
-
#
|
261
|
-
# Example:
|
262
|
-
#
|
263
|
-
# "¾ cup".mb_chars.rjust(8).to_s
|
264
|
-
# #=> " ¾ cup"
|
265
|
-
#
|
266
|
-
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
267
|
-
# #=> " ¾ cup"
|
268
|
-
def rjust(integer, padstr=' ')
|
269
|
-
justify(integer, :right, padstr)
|
270
|
-
end
|
271
|
-
|
272
|
-
# Works just like <tt>String#ljust</tt>, only integer specifies characters instead of bytes.
|
273
|
-
#
|
274
|
-
# Example:
|
275
|
-
#
|
276
|
-
# "¾ cup".mb_chars.rjust(8).to_s
|
277
|
-
# #=> "¾ cup "
|
278
|
-
#
|
279
|
-
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
280
|
-
# #=> "¾ cup "
|
281
|
-
def ljust(integer, padstr=' ')
|
282
|
-
justify(integer, :left, padstr)
|
283
|
-
end
|
284
|
-
|
285
|
-
# Works just like <tt>String#center</tt>, only integer specifies characters instead of bytes.
|
286
|
-
#
|
287
|
-
# Example:
|
288
|
-
#
|
289
|
-
# "¾ cup".mb_chars.center(8).to_s
|
290
|
-
# #=> " ¾ cup "
|
291
|
-
#
|
292
|
-
# "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
|
293
|
-
# #=> " ¾ cup "
|
294
|
-
def center(integer, padstr=' ')
|
295
|
-
justify(integer, :center, padstr)
|
296
|
-
end
|
297
|
-
|
298
|
-
# Strips entire range of Unicode whitespace from the right of the string.
|
299
|
-
def rstrip
|
300
|
-
chars(@wrapped_string.gsub(UNICODE_TRAILERS_PAT, ''))
|
301
|
-
end
|
302
|
-
|
303
|
-
# Strips entire range of Unicode whitespace from the left of the string.
|
304
|
-
def lstrip
|
305
|
-
chars(@wrapped_string.gsub(UNICODE_LEADERS_PAT, ''))
|
306
|
-
end
|
307
|
-
|
308
|
-
# Strips entire range of Unicode whitespace from the right and left of the string.
|
309
|
-
def strip
|
310
|
-
rstrip.lstrip
|
311
|
-
end
|
312
|
-
|
313
|
-
# Returns the number of codepoints in the string
|
314
|
-
def size
|
315
|
-
self.class.u_unpack(@wrapped_string).size
|
316
|
-
end
|
317
|
-
alias_method :length, :size
|
318
|
-
|
319
292
|
# Reverses all characters in the string.
|
320
293
|
#
|
321
294
|
# Example:
|
322
295
|
# 'Café'.mb_chars.reverse.to_s #=> 'éfaC'
|
323
296
|
def reverse
|
324
|
-
chars(
|
297
|
+
chars(Unicode.g_unpack(@wrapped_string).reverse.flatten.pack('U*'))
|
325
298
|
end
|
326
299
|
|
327
300
|
# Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
|
@@ -337,46 +310,37 @@ module ActiveSupport #:nodoc:
|
|
337
310
|
elsif (args.size == 2 && !args[1].is_a?(Numeric))
|
338
311
|
raise TypeError, "cannot convert #{args[1].class} into Integer" # Do as if we were native
|
339
312
|
elsif args[0].kind_of? Range
|
340
|
-
cps =
|
313
|
+
cps = Unicode.u_unpack(@wrapped_string).slice(*args)
|
341
314
|
result = cps.nil? ? nil : cps.pack('U*')
|
342
315
|
elsif args[0].kind_of? Regexp
|
343
316
|
result = @wrapped_string.slice(*args)
|
344
317
|
elsif args.size == 1 && args[0].kind_of?(Numeric)
|
345
|
-
character =
|
346
|
-
result = character
|
318
|
+
character = Unicode.u_unpack(@wrapped_string)[args[0]]
|
319
|
+
result = character && [character].pack('U')
|
347
320
|
else
|
348
|
-
|
321
|
+
cps = Unicode.u_unpack(@wrapped_string).slice(*args)
|
322
|
+
result = cps && cps.pack('U*')
|
349
323
|
end
|
350
|
-
result
|
324
|
+
result && chars(result)
|
351
325
|
end
|
352
326
|
alias_method :[], :slice
|
353
327
|
|
354
|
-
#
|
328
|
+
# Limit the byte size of the string to a number of bytes without breaking characters. Usable
|
329
|
+
# when the storage for a string is limited for some reason.
|
355
330
|
#
|
356
331
|
# Example:
|
357
332
|
# s = 'こんにちは'
|
358
|
-
# s.mb_chars.
|
359
|
-
|
360
|
-
|
361
|
-
slice = self[*args]
|
362
|
-
self[*args] = ''
|
363
|
-
slice
|
364
|
-
end
|
365
|
-
|
366
|
-
# Returns the codepoint of the first character in the string.
|
367
|
-
#
|
368
|
-
# Example:
|
369
|
-
# 'こんにちは'.mb_chars.ord #=> 12371
|
370
|
-
def ord
|
371
|
-
self.class.u_unpack(@wrapped_string)[0]
|
333
|
+
# s.mb_chars.limit(7) #=> "こに"
|
334
|
+
def limit(limit)
|
335
|
+
slice(0...translate_offset(limit))
|
372
336
|
end
|
373
337
|
|
374
338
|
# Convert characters in the string to uppercase.
|
375
339
|
#
|
376
340
|
# Example:
|
377
|
-
# 'Laurent,
|
341
|
+
# 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s #=> "LAURENT, OÙ SONT LES TESTS ?"
|
378
342
|
def upcase
|
379
|
-
apply_mapping :uppercase_mapping
|
343
|
+
chars(Unicode.apply_mapping @wrapped_string, :uppercase_mapping)
|
380
344
|
end
|
381
345
|
|
382
346
|
# Convert characters in the string to lowercase.
|
@@ -384,7 +348,7 @@ module ActiveSupport #:nodoc:
|
|
384
348
|
# Example:
|
385
349
|
# 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s #=> "věda a výzkum"
|
386
350
|
def downcase
|
387
|
-
apply_mapping :lowercase_mapping
|
351
|
+
chars(Unicode.apply_mapping @wrapped_string, :lowercase_mapping)
|
388
352
|
end
|
389
353
|
|
390
354
|
# Converts the first character to uppercase and the remainder to lowercase.
|
@@ -395,28 +359,24 @@ module ActiveSupport #:nodoc:
|
|
395
359
|
(slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
|
396
360
|
end
|
397
361
|
|
362
|
+
# Capitalizes the first letter of every word, when possible.
|
363
|
+
#
|
364
|
+
# Example:
|
365
|
+
# "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
|
366
|
+
# "日本語".mb_chars.titleize # => "日本語"
|
367
|
+
def titleize
|
368
|
+
chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.apply_mapping $1, :uppercase_mapping })
|
369
|
+
end
|
370
|
+
alias_method :titlecase, :titleize
|
371
|
+
|
398
372
|
# Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
|
399
373
|
# passing strings to databases and validations.
|
400
374
|
#
|
401
|
-
# * <tt>str</tt> - The string to perform normalization on.
|
402
375
|
# * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
|
403
376
|
# <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
|
404
|
-
# ActiveSupport::Multibyte.default_normalization_form
|
405
|
-
def normalize(form=
|
406
|
-
|
407
|
-
codepoints = self.class.u_unpack(@wrapped_string)
|
408
|
-
chars(case form
|
409
|
-
when :d
|
410
|
-
self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints))
|
411
|
-
when :c
|
412
|
-
self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints)))
|
413
|
-
when :kd
|
414
|
-
self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints))
|
415
|
-
when :kc
|
416
|
-
self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints)))
|
417
|
-
else
|
418
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
419
|
-
end.pack('U*'))
|
377
|
+
# ActiveSupport::Multibyte::Unicode.default_normalization_form
|
378
|
+
def normalize(form = nil)
|
379
|
+
chars(Unicode.normalize(@wrapped_string, form))
|
420
380
|
end
|
421
381
|
|
422
382
|
# Performs canonical decomposition on all the characters.
|
@@ -425,7 +385,7 @@ module ActiveSupport #:nodoc:
|
|
425
385
|
# 'é'.length #=> 2
|
426
386
|
# 'é'.mb_chars.decompose.to_s.length #=> 3
|
427
387
|
def decompose
|
428
|
-
chars(
|
388
|
+
chars(Unicode.decompose_codepoints(:canonical, Unicode.u_unpack(@wrapped_string)).pack('U*'))
|
429
389
|
end
|
430
390
|
|
431
391
|
# Performs composition on all the characters.
|
@@ -434,7 +394,7 @@ module ActiveSupport #:nodoc:
|
|
434
394
|
# 'é'.length #=> 3
|
435
395
|
# 'é'.mb_chars.compose.to_s.length #=> 2
|
436
396
|
def compose
|
437
|
-
chars(
|
397
|
+
chars(Unicode.compose_codepoints(Unicode.u_unpack(@wrapped_string)).pack('U*'))
|
438
398
|
end
|
439
399
|
|
440
400
|
# Returns the number of grapheme clusters in the string.
|
@@ -443,210 +403,24 @@ module ActiveSupport #:nodoc:
|
|
443
403
|
# 'क्षि'.mb_chars.length #=> 4
|
444
404
|
# 'क्षि'.mb_chars.g_length #=> 3
|
445
405
|
def g_length
|
446
|
-
|
406
|
+
Unicode.g_unpack(@wrapped_string).length
|
447
407
|
end
|
448
408
|
|
449
409
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
end
|
464
|
-
|
465
|
-
class << self
|
466
|
-
|
467
|
-
# Unpack the string at codepoints boundaries. Raises an EncodingError when the encoding of the string isn't
|
468
|
-
# valid UTF-8.
|
469
|
-
#
|
470
|
-
# Example:
|
471
|
-
# Chars.u_unpack('Café') #=> [67, 97, 102, 233]
|
472
|
-
def u_unpack(string)
|
473
|
-
begin
|
474
|
-
string.unpack 'U*'
|
475
|
-
rescue ArgumentError
|
476
|
-
raise EncodingError, 'malformed UTF-8 character'
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
# Detect whether the codepoint is in a certain character class. Returns +true+ when it's in the specified
|
481
|
-
# character class and +false+ otherwise. Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
|
482
|
-
# <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
|
483
|
-
#
|
484
|
-
# Primarily used by the grapheme cluster support.
|
485
|
-
def in_char_class?(codepoint, classes)
|
486
|
-
classes.detect { |c| UCD.boundary[c] === codepoint } ? true : false
|
487
|
-
end
|
488
|
-
|
489
|
-
# Unpack the string at grapheme boundaries. Returns a list of character lists.
|
490
|
-
#
|
491
|
-
# Example:
|
492
|
-
# Chars.g_unpack('क्षि') #=> [[2325, 2381], [2359], [2367]]
|
493
|
-
# Chars.g_unpack('Café') #=> [[67], [97], [102], [233]]
|
494
|
-
def g_unpack(string)
|
495
|
-
codepoints = u_unpack(string)
|
496
|
-
unpacked = []
|
497
|
-
pos = 0
|
498
|
-
marker = 0
|
499
|
-
eoc = codepoints.length
|
500
|
-
while(pos < eoc)
|
501
|
-
pos += 1
|
502
|
-
previous = codepoints[pos-1]
|
503
|
-
current = codepoints[pos]
|
504
|
-
if (
|
505
|
-
# CR X LF
|
506
|
-
one = ( previous == UCD.boundary[:cr] and current == UCD.boundary[:lf] ) or
|
507
|
-
# L X (L|V|LV|LVT)
|
508
|
-
two = ( UCD.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
|
509
|
-
# (LV|V) X (V|T)
|
510
|
-
three = ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
|
511
|
-
# (LVT|T) X (T)
|
512
|
-
four = ( in_char_class?(previous, [:lvt,:t]) and UCD.boundary[:t] === current ) or
|
513
|
-
# X Extend
|
514
|
-
five = (UCD.boundary[:extend] === current)
|
515
|
-
)
|
516
|
-
else
|
517
|
-
unpacked << codepoints[marker..pos-1]
|
518
|
-
marker = pos
|
519
|
-
end
|
520
|
-
end
|
521
|
-
unpacked
|
522
|
-
end
|
523
|
-
|
524
|
-
# Reverse operation of g_unpack.
|
525
|
-
#
|
526
|
-
# Example:
|
527
|
-
# Chars.g_pack(Chars.g_unpack('क्षि')) #=> 'क्षि'
|
528
|
-
def g_pack(unpacked)
|
529
|
-
(unpacked.flatten).pack('U*')
|
530
|
-
end
|
531
|
-
|
532
|
-
def padding(padsize, padstr=' ') #:nodoc:
|
533
|
-
if padsize != 0
|
534
|
-
new(padstr * ((padsize / u_unpack(padstr).size) + 1)).slice(0, padsize)
|
535
|
-
else
|
536
|
-
''
|
537
|
-
end
|
538
|
-
end
|
539
|
-
|
540
|
-
# Re-order codepoints so the string becomes canonical.
|
541
|
-
def reorder_characters(codepoints)
|
542
|
-
length = codepoints.length- 1
|
543
|
-
pos = 0
|
544
|
-
while pos < length do
|
545
|
-
cp1, cp2 = UCD.codepoints[codepoints[pos]], UCD.codepoints[codepoints[pos+1]]
|
546
|
-
if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
|
547
|
-
codepoints[pos..pos+1] = cp2.code, cp1.code
|
548
|
-
pos += (pos > 0 ? -1 : 1)
|
549
|
-
else
|
550
|
-
pos += 1
|
551
|
-
end
|
552
|
-
end
|
553
|
-
codepoints
|
554
|
-
end
|
555
|
-
|
556
|
-
# Decompose composed characters to the decomposed form.
|
557
|
-
def decompose_codepoints(type, codepoints)
|
558
|
-
codepoints.inject([]) do |decomposed, cp|
|
559
|
-
# if it's a hangul syllable starter character
|
560
|
-
if HANGUL_SBASE <= cp and cp < HANGUL_SLAST
|
561
|
-
sindex = cp - HANGUL_SBASE
|
562
|
-
ncp = [] # new codepoints
|
563
|
-
ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
|
564
|
-
ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
|
565
|
-
tindex = sindex % HANGUL_TCOUNT
|
566
|
-
ncp << (HANGUL_TBASE + tindex) unless tindex == 0
|
567
|
-
decomposed.concat ncp
|
568
|
-
# if the codepoint is decomposable in with the current decomposition type
|
569
|
-
elsif (ncp = UCD.codepoints[cp].decomp_mapping) and (!UCD.codepoints[cp].decomp_type || type == :compatability)
|
570
|
-
decomposed.concat decompose_codepoints(type, ncp.dup)
|
571
|
-
else
|
572
|
-
decomposed << cp
|
573
|
-
end
|
574
|
-
end
|
575
|
-
end
|
576
|
-
|
577
|
-
# Compose decomposed characters to the composed form.
|
578
|
-
def compose_codepoints(codepoints)
|
579
|
-
pos = 0
|
580
|
-
eoa = codepoints.length - 1
|
581
|
-
starter_pos = 0
|
582
|
-
starter_char = codepoints[0]
|
583
|
-
previous_combining_class = -1
|
584
|
-
while pos < eoa
|
585
|
-
pos += 1
|
586
|
-
lindex = starter_char - HANGUL_LBASE
|
587
|
-
# -- Hangul
|
588
|
-
if 0 <= lindex and lindex < HANGUL_LCOUNT
|
589
|
-
vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
|
590
|
-
if 0 <= vindex and vindex < HANGUL_VCOUNT
|
591
|
-
tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
|
592
|
-
if 0 <= tindex and tindex < HANGUL_TCOUNT
|
593
|
-
j = starter_pos + 2
|
594
|
-
eoa -= 2
|
595
|
-
else
|
596
|
-
tindex = 0
|
597
|
-
j = starter_pos + 1
|
598
|
-
eoa -= 1
|
599
|
-
end
|
600
|
-
codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
|
601
|
-
end
|
602
|
-
starter_pos += 1
|
603
|
-
starter_char = codepoints[starter_pos]
|
604
|
-
# -- Other characters
|
605
|
-
else
|
606
|
-
current_char = codepoints[pos]
|
607
|
-
current = UCD.codepoints[current_char]
|
608
|
-
if current.combining_class > previous_combining_class
|
609
|
-
if ref = UCD.composition_map[starter_char]
|
610
|
-
composition = ref[current_char]
|
611
|
-
else
|
612
|
-
composition = nil
|
613
|
-
end
|
614
|
-
unless composition.nil?
|
615
|
-
codepoints[starter_pos] = composition
|
616
|
-
starter_char = composition
|
617
|
-
codepoints.delete_at pos
|
618
|
-
eoa -= 1
|
619
|
-
pos -= 1
|
620
|
-
previous_combining_class = -1
|
621
|
-
else
|
622
|
-
previous_combining_class = current.combining_class
|
623
|
-
end
|
624
|
-
else
|
625
|
-
previous_combining_class = current.combining_class
|
626
|
-
end
|
627
|
-
if current.combining_class == 0
|
628
|
-
starter_pos = pos
|
629
|
-
starter_char = codepoints[pos]
|
630
|
-
end
|
631
|
-
end
|
410
|
+
#
|
411
|
+
# Passing +true+ will forcibly tidy all bytes, assuming that the string's encoding is entirely CP1252 or ISO-8859-1.
|
412
|
+
def tidy_bytes(force = false)
|
413
|
+
chars(Unicode.tidy_bytes(@wrapped_string, force))
|
414
|
+
end
|
415
|
+
|
416
|
+
%w(capitalize downcase lstrip reverse rstrip slice strip tidy_bytes upcase).each do |method|
|
417
|
+
# Only define a corresponding bang method for methods defined in the proxy; On 1.9 the proxy will
|
418
|
+
# exclude lstrip!, rstrip! and strip! because they are already work as expected on multibyte strings.
|
419
|
+
if public_method_defined?(method)
|
420
|
+
define_method("#{method}!") do |*args|
|
421
|
+
@wrapped_string = send(args.nil? ? method : method, *args).to_s
|
422
|
+
self
|
632
423
|
end
|
633
|
-
codepoints
|
634
|
-
end
|
635
|
-
|
636
|
-
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
|
637
|
-
def tidy_bytes(string)
|
638
|
-
string.split(//u).map do |c|
|
639
|
-
c.force_encoding(Encoding::ASCII) if c.respond_to?(:force_encoding)
|
640
|
-
|
641
|
-
if !ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'].match(c)
|
642
|
-
n = c.unpack('C')[0]
|
643
|
-
n < 128 ? n.chr :
|
644
|
-
n < 160 ? [UCD.cp1252[n] || n].pack('U') :
|
645
|
-
n < 192 ? "\xC2" + n.chr : "\xC3" + (n-64).chr
|
646
|
-
else
|
647
|
-
c
|
648
|
-
end
|
649
|
-
end.join
|
650
424
|
end
|
651
425
|
end
|
652
426
|
|
@@ -655,20 +429,16 @@ module ActiveSupport #:nodoc:
|
|
655
429
|
def translate_offset(byte_offset) #:nodoc:
|
656
430
|
return nil if byte_offset.nil?
|
657
431
|
return 0 if @wrapped_string == ''
|
658
|
-
|
432
|
+
|
433
|
+
if @wrapped_string.respond_to?(:force_encoding)
|
434
|
+
@wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT)
|
435
|
+
end
|
436
|
+
|
659
437
|
begin
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
# Stop retrying at the end of the string
|
665
|
-
raise e unless byte_offset < chunk.length
|
666
|
-
# We damaged a character, retry
|
667
|
-
retry
|
668
|
-
end
|
669
|
-
# Catch the ArgumentError so we can throw our own
|
670
|
-
rescue ArgumentError
|
671
|
-
raise EncodingError, 'malformed UTF-8 character'
|
438
|
+
@wrapped_string[0...byte_offset].unpack('U*').length
|
439
|
+
rescue ArgumentError => e
|
440
|
+
byte_offset -= 1
|
441
|
+
retry
|
672
442
|
end
|
673
443
|
end
|
674
444
|
|
@@ -678,26 +448,23 @@ module ActiveSupport #:nodoc:
|
|
678
448
|
padsize = padsize > 0 ? padsize : 0
|
679
449
|
case way
|
680
450
|
when :right
|
681
|
-
result = @wrapped_string.dup.insert(0,
|
451
|
+
result = @wrapped_string.dup.insert(0, padding(padsize, padstr))
|
682
452
|
when :left
|
683
|
-
result = @wrapped_string.dup.insert(-1,
|
453
|
+
result = @wrapped_string.dup.insert(-1, padding(padsize, padstr))
|
684
454
|
when :center
|
685
|
-
lpad =
|
686
|
-
rpad =
|
455
|
+
lpad = padding((padsize / 2.0).floor, padstr)
|
456
|
+
rpad = padding((padsize / 2.0).ceil, padstr)
|
687
457
|
result = @wrapped_string.dup.insert(0, lpad).insert(-1, rpad)
|
688
458
|
end
|
689
459
|
chars(result)
|
690
460
|
end
|
691
461
|
|
692
|
-
def
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
codepoint
|
699
|
-
end
|
700
|
-
end.pack('U*'))
|
462
|
+
def padding(padsize, padstr=' ') #:nodoc:
|
463
|
+
if padsize != 0
|
464
|
+
chars(padstr * ((padsize / Unicode.u_unpack(padstr).size) + 1)).slice(0, padsize)
|
465
|
+
else
|
466
|
+
''
|
467
|
+
end
|
701
468
|
end
|
702
469
|
|
703
470
|
def chars(string) #:nodoc:
|