activesupport 3.0.0.beta4 → 3.0.pre
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 +1 -100
- data/lib/active_support.rb +4 -38
- data/lib/active_support/autoload.rb +28 -0
- data/lib/active_support/backtrace_cleaner.rb +9 -31
- data/lib/active_support/benchmarkable.rb +0 -1
- data/lib/active_support/buffered_logger.rb +1 -0
- data/lib/active_support/cache.rb +81 -436
- data/lib/active_support/cache/compressed_mem_cache_store.rb +13 -6
- data/lib/active_support/cache/file_store.rb +41 -139
- data/lib/active_support/cache/mem_cache_store.rb +75 -120
- data/lib/active_support/cache/memory_store.rb +27 -127
- data/lib/active_support/cache/strategy/local_cache.rb +58 -111
- data/lib/active_support/cache/synchronized_memory_store.rb +38 -2
- data/lib/active_support/callbacks.rb +48 -87
- data/lib/active_support/configurable.rb +18 -19
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/conversions.rb +54 -29
- data/lib/active_support/core_ext/array/extract_options.rb +1 -16
- data/lib/active_support/core_ext/array/random_access.rb +5 -19
- data/lib/active_support/core_ext/array/wrap.rb +9 -13
- data/lib/active_support/core_ext/benchmark.rb +12 -0
- data/lib/active_support/core_ext/boolean.rb +1 -0
- data/lib/active_support/core_ext/boolean/conversions.rb +11 -0
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -2
- data/lib/active_support/core_ext/class.rb +1 -1
- data/lib/active_support/core_ext/class/attribute_accessors.rb +27 -33
- data/lib/active_support/core_ext/class/delegating_attributes.rb +41 -35
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +13 -22
- data/lib/active_support/core_ext/class/removal.rb +53 -0
- data/lib/active_support/core_ext/date.rb +7 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -30
- data/lib/active_support/core_ext/date/conversions.rb +2 -2
- data/lib/active_support/core_ext/date_time.rb +5 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +5 -23
- data/lib/active_support/core_ext/enumerable.rb +9 -5
- data/lib/active_support/core_ext/exception.rb +47 -0
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/file/atomic.rb +2 -3
- data/lib/active_support/core_ext/float/rounding.rb +2 -3
- data/lib/active_support/core_ext/hash/conversions.rb +145 -65
- data/lib/active_support/core_ext/hash/deep_merge.rb +7 -6
- data/lib/active_support/core_ext/hash/except.rb +0 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +0 -5
- data/lib/active_support/core_ext/hash/keys.rb +11 -10
- data/lib/active_support/core_ext/hash/slice.rb +0 -6
- data/lib/active_support/core_ext/integer.rb +1 -1
- data/lib/active_support/core_ext/integer/even_odd.rb +16 -0
- data/lib/active_support/core_ext/kernel.rb +1 -1
- data/lib/active_support/core_ext/kernel/daemonizing.rb +7 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -3
- data/lib/active_support/core_ext/kernel/reporting.rb +1 -2
- data/lib/active_support/core_ext/load_error.rb +30 -17
- data/lib/active_support/core_ext/logger.rb +1 -1
- data/lib/active_support/core_ext/module.rb +3 -5
- data/lib/active_support/core_ext/module/aliasing.rb +1 -1
- 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 +21 -25
- data/lib/active_support/core_ext/module/delegation.rb +10 -21
- data/lib/active_support/core_ext/module/inclusion.rb +30 -0
- data/lib/active_support/core_ext/module/introspection.rb +8 -8
- data/lib/active_support/core_ext/module/loading.rb +23 -0
- data/lib/active_support/core_ext/module/synchronization.rb +1 -2
- data/lib/active_support/core_ext/name_error.rb +1 -3
- data/lib/active_support/core_ext/nil.rb +1 -0
- data/lib/active_support/core_ext/nil/conversions.rb +5 -0
- data/lib/active_support/core_ext/object.rb +2 -6
- data/lib/active_support/core_ext/object/blank.rb +2 -20
- data/lib/active_support/core_ext/object/conversions.rb +16 -2
- data/lib/active_support/core_ext/object/duplicable.rb +1 -23
- data/lib/active_support/core_ext/object/extending.rb +77 -8
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -0
- data/lib/active_support/core_ext/object/metaclass.rb +13 -0
- data/lib/active_support/core_ext/object/misc.rb +1 -0
- data/lib/active_support/core_ext/object/tap.rb +16 -0
- data/lib/active_support/core_ext/object/with_options.rb +0 -2
- data/lib/active_support/core_ext/proc.rb +4 -4
- data/lib/active_support/core_ext/regexp.rb +22 -0
- data/lib/active_support/core_ext/rexml.rb +1 -4
- data/lib/active_support/core_ext/string.rb +2 -3
- data/lib/active_support/core_ext/string/access.rb +2 -4
- data/lib/active_support/core_ext/string/bytesize.rb +5 -0
- data/lib/active_support/core_ext/string/conversions.rb +1 -36
- data/lib/active_support/core_ext/string/filters.rb +0 -29
- data/lib/active_support/core_ext/string/inflections.rb +12 -1
- data/lib/active_support/core_ext/string/interpolation.rb +92 -2
- data/lib/active_support/core_ext/string/iterators.rb +13 -0
- data/lib/active_support/core_ext/string/multibyte.rb +19 -16
- data/lib/active_support/core_ext/string/output_safety.rb +35 -101
- data/lib/active_support/core_ext/string/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/string/xchar.rb +1 -1
- data/lib/active_support/core_ext/symbol.rb +1 -0
- data/lib/active_support/core_ext/symbol/to_proc.rb +14 -0
- data/lib/active_support/core_ext/time.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +7 -9
- data/lib/active_support/core_ext/time/conversions.rb +0 -1
- data/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +22 -0
- data/lib/active_support/core_ext/uri.rb +4 -10
- data/lib/active_support/dependencies.rb +192 -179
- data/lib/active_support/deprecated_callbacks.rb +283 -0
- data/lib/active_support/deprecation/behaviors.rb +1 -1
- data/lib/active_support/deprecation/method_wrappers.rb +9 -10
- data/lib/active_support/deprecation/reporting.rb +1 -2
- data/lib/active_support/duration.rb +2 -6
- data/lib/active_support/hash_with_indifferent_access.rb +1 -9
- data/lib/active_support/inflections.rb +1 -1
- data/lib/active_support/inflector.rb +407 -4
- data/lib/active_support/json/backends/jsongem.rb +9 -12
- data/lib/active_support/json/decoding.rb +1 -16
- data/lib/active_support/json/encoding.rb +12 -42
- data/lib/active_support/locale/en.yml +1 -4
- data/lib/active_support/memoizable.rb +1 -1
- data/lib/active_support/message_encryptor.rb +0 -1
- data/lib/active_support/message_verifier.rb +5 -6
- data/lib/active_support/multibyte.rb +22 -7
- data/lib/active_support/multibyte/chars.rb +392 -164
- data/lib/active_support/multibyte/unicode_database.rb +71 -0
- data/lib/active_support/multibyte/utils.rb +7 -6
- data/lib/active_support/notifications.rb +113 -23
- data/lib/active_support/ordered_hash.rb +11 -35
- data/lib/active_support/ordered_options.rb +0 -6
- data/lib/active_support/rescuable.rb +4 -7
- data/lib/active_support/ruby/shim.rb +6 -4
- data/lib/active_support/test_case.rb +7 -2
- data/lib/active_support/testing/assertions.rb +0 -15
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/isolation.rb +19 -63
- data/lib/active_support/testing/performance.rb +337 -342
- data/lib/active_support/testing/setup_and_teardown.rb +29 -51
- data/lib/active_support/time.rb +3 -23
- data/lib/active_support/time_with_zone.rb +10 -5
- data/lib/active_support/values/time_zone.rb +84 -40
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/vendor.rb +16 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/blankslate.rb +113 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder.rb +13 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/blankslate.rb +20 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/css.rb +250 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xchar.rb +115 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlbase.rb +139 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlevents.rb +63 -0
- data/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlmarkup.rb +328 -0
- data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +20 -0
- data/lib/active_support/vendor/i18n-0.1.3/README.textile +20 -0
- data/lib/active_support/vendor/i18n-0.1.3/Rakefile +5 -0
- data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +27 -0
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb +204 -0
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb +215 -0
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb +53 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +5 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +99 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +124 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +1 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +3 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +567 -0
- data/lib/active_support/vendor/memcache-client-1.7.5/lib/memcache.rb +1133 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo.rb +33 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone.rb +47 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone_info.rb +228 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Algiers.rb +55 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Cairo.rb +219 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Casablanca.rb +42 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Harare.rb +18 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Johannesburg.rb +25 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Monrovia.rb +22 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Nairobi.rb +23 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +166 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/San_Juan.rb +86 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Bogota.rb +23 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Caracas.rb +23 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chicago.rb +283 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chihuahua.rb +136 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Denver.rb +204 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Godthab.rb +161 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Guatemala.rb +27 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Halifax.rb +274 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Indiana/Indianapolis.rb +149 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Juneau.rb +194 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/La_Paz.rb +22 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Lima.rb +35 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Los_Angeles.rb +232 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mazatlan.rb +139 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mexico_City.rb +144 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Monterrey.rb +131 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/New_York.rb +282 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Phoenix.rb +30 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Regina.rb +74 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Santiago.rb +205 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Sao_Paulo.rb +171 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/St_Johns.rb +288 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Tijuana.rb +196 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Almaty.rb +67 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baghdad.rb +73 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baku.rb +161 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Bangkok.rb +20 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Chongqing.rb +33 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Colombo.rb +30 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Dhaka.rb +27 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Hong_Kong.rb +87 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Irkutsk.rb +165 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jakarta.rb +30 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jerusalem.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kabul.rb +20 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kamchatka.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Karachi.rb +32 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kathmandu.rb +20 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kolkata.rb +25 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Krasnoyarsk.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuala_Lumpur.rb +31 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuwait.rb +18 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Magadan.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Muscat.rb +18 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Novosibirsk.rb +164 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Rangoon.rb +24 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Riyadh.rb +18 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Seoul.rb +34 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Shanghai.rb +35 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Singapore.rb +33 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Taipei.rb +59 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tashkent.rb +47 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tbilisi.rb +78 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tehran.rb +121 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tokyo.rb +30 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Ulaanbaatar.rb +65 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Urumqi.rb +33 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Vladivostok.rb +164 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yakutsk.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yekaterinburg.rb +165 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yerevan.rb +165 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Azores.rb +270 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Cape_Verde.rb +23 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/South_Georgia.rb +18 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Adelaide.rb +187 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Brisbane.rb +35 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Darwin.rb +29 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Hobart.rb +193 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Melbourne.rb +185 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Perth.rb +37 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Sydney.rb +185 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Etc/UTC.rb +16 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Amsterdam.rb +228 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Athens.rb +185 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Belgrade.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Berlin.rb +188 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bratislava.rb +13 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Brussels.rb +232 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bucharest.rb +181 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Budapest.rb +197 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Copenhagen.rb +179 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Dublin.rb +276 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Helsinki.rb +163 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Istanbul.rb +218 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Kiev.rb +168 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Lisbon.rb +268 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Ljubljana.rb +13 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/London.rb +288 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Madrid.rb +211 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Minsk.rb +170 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Moscow.rb +181 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Paris.rb +232 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Prague.rb +187 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Riga.rb +176 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Rome.rb +215 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sarajevo.rb +13 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Skopje.rb +13 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sofia.rb +173 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Stockholm.rb +165 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Tallinn.rb +172 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vienna.rb +183 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vilnius.rb +170 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Warsaw.rb +212 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Zagreb.rb +13 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Auckland.rb +202 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Fiji.rb +23 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Guam.rb +22 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Honolulu.rb +28 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Majuro.rb +20 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Midway.rb +25 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Noumea.rb +25 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Pago_Pago.rb +26 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Port_Moresby.rb +20 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Tongatapu.rb +27 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/info_timezone.rb +52 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone.rb +51 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone_info.rb +44 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/offset_rationals.rb +98 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/ruby_core_support.rb +56 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/time_or_datetime.rb +292 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone.rb +508 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_definition.rb +56 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_info.rb +40 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_offset_info.rb +94 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_period.rb +198 -0
- data/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_transition_info.rb +129 -0
- data/lib/active_support/version.rb +2 -3
- data/lib/active_support/whiny_nil.rb +7 -9
- data/lib/active_support/xml_mini.rb +1 -126
- data/lib/active_support/xml_mini/jdom.rb +0 -2
- data/lib/active_support/xml_mini/libxml.rb +86 -24
- data/lib/active_support/xml_mini/nokogiri.rb +24 -27
- data/lib/active_support/xml_mini/rexml.rb +1 -7
- metadata +191 -49
- data/lib/active_support/builder.rb +0 -6
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -17
- data/lib/active_support/core_ext/class/attribute.rb +0 -67
- data/lib/active_support/core_ext/class/subclasses.rb +0 -55
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/integer/multiple.rb +0 -6
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -13
- data/lib/active_support/core_ext/module/anonymous.rb +0 -24
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/reachable.rb +0 -10
- data/lib/active_support/core_ext/module/remove_method.rb +0 -6
- data/lib/active_support/core_ext/object/to_param.rb +0 -49
- data/lib/active_support/core_ext/object/to_query.rb +0 -27
- data/lib/active_support/core_ext/string/encoding.rb +0 -11
- data/lib/active_support/core_ext/string/exclude.rb +0 -6
- data/lib/active_support/core_ext/time/marshal.rb +0 -56
- data/lib/active_support/dependencies/autoload.rb +0 -50
- data/lib/active_support/i18n.rb +0 -8
- data/lib/active_support/inflector/inflections.rb +0 -211
- data/lib/active_support/inflector/methods.rb +0 -141
- data/lib/active_support/inflector/transliterate.rb +0 -97
- data/lib/active_support/json/backends/yajl.rb +0 -40
- data/lib/active_support/lazy_load_hooks.rb +0 -27
- data/lib/active_support/multibyte/unicode.rb +0 -393
- data/lib/active_support/notifications/fanout.rb +0 -93
- data/lib/active_support/notifications/instrumenter.rb +0 -56
- data/lib/active_support/railtie.rb +0 -100
- data/lib/active_support/xml_mini/libxmlsax.rb +0 -85
- data/lib/active_support/xml_mini/nokogirisax.rb +0 -83
@@ -23,18 +23,15 @@ module ActiveSupport
|
|
23
23
|
private
|
24
24
|
def convert_dates_from(data)
|
25
25
|
case data
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
else
|
37
|
-
data
|
26
|
+
when DATE_REGEX
|
27
|
+
DateTime.parse(data)
|
28
|
+
when Array
|
29
|
+
data.map! { |d| convert_dates_from(d) }
|
30
|
+
when Hash
|
31
|
+
data.each do |key, value|
|
32
|
+
data[key] = convert_dates_from(value)
|
33
|
+
end
|
34
|
+
else data
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
@@ -6,15 +6,12 @@ module ActiveSupport
|
|
6
6
|
mattr_accessor :parse_json_times
|
7
7
|
|
8
8
|
module JSON
|
9
|
-
# Listed in order of preference.
|
10
|
-
DECODERS = %w(Yajl Yaml)
|
11
|
-
|
12
9
|
class << self
|
13
10
|
attr_reader :parse_error
|
14
11
|
delegate :decode, :to => :backend
|
15
12
|
|
16
13
|
def backend
|
17
|
-
|
14
|
+
self.backend = "Yaml" unless defined?(@backend)
|
18
15
|
@backend
|
19
16
|
end
|
20
17
|
|
@@ -34,18 +31,6 @@ module ActiveSupport
|
|
34
31
|
ensure
|
35
32
|
self.backend = old_backend
|
36
33
|
end
|
37
|
-
|
38
|
-
def set_default_backend
|
39
|
-
DECODERS.find do |name|
|
40
|
-
begin
|
41
|
-
self.backend = name
|
42
|
-
true
|
43
|
-
rescue LoadError
|
44
|
-
# Try next decoder.
|
45
|
-
false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
34
|
end
|
50
35
|
end
|
51
36
|
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'bigdecimal'
|
3
2
|
require 'active_support/core_ext/array/wrap'
|
4
|
-
require 'active_support/core_ext/big_decimal/conversions' # for #to_s
|
5
3
|
require 'active_support/core_ext/hash/except'
|
6
4
|
require 'active_support/core_ext/hash/slice'
|
7
5
|
require 'active_support/core_ext/module/delegation'
|
8
6
|
require 'active_support/core_ext/object/instance_variables'
|
9
7
|
require 'active_support/deprecation'
|
10
8
|
|
11
|
-
require 'active_support/
|
9
|
+
require 'active_support/core_ext/date_time/conversions'
|
10
|
+
require 'active_support/core_ext/time/conversions'
|
11
|
+
require 'active_support/time_with_zone'
|
12
|
+
require 'active_support/values/time_zone'
|
12
13
|
|
13
14
|
# Hack to load json gem first so we can overwrite its to_json.
|
14
15
|
begin
|
@@ -67,15 +68,6 @@ module ActiveSupport
|
|
67
68
|
|
68
69
|
|
69
70
|
ESCAPED_CHARS = {
|
70
|
-
"\x00" => '\u0000', "\x01" => '\u0001', "\x02" => '\u0002',
|
71
|
-
"\x03" => '\u0003', "\x04" => '\u0004', "\x05" => '\u0005',
|
72
|
-
"\x06" => '\u0006', "\x07" => '\u0007', "\x0B" => '\u000B',
|
73
|
-
"\x0E" => '\u000E', "\x0F" => '\u000F', "\x10" => '\u0010',
|
74
|
-
"\x11" => '\u0011', "\x12" => '\u0012', "\x13" => '\u0013',
|
75
|
-
"\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016',
|
76
|
-
"\x17" => '\u0017', "\x18" => '\u0018', "\x19" => '\u0019',
|
77
|
-
"\x1A" => '\u001A', "\x1B" => '\u001B', "\x1C" => '\u001C',
|
78
|
-
"\x1D" => '\u001D', "\x1E" => '\u001E', "\x1F" => '\u001F',
|
79
71
|
"\010" => '\b',
|
80
72
|
"\f" => '\f',
|
81
73
|
"\n" => '\n',
|
@@ -97,16 +89,14 @@ module ActiveSupport
|
|
97
89
|
def escape_html_entities_in_json=(value)
|
98
90
|
self.escape_regex = \
|
99
91
|
if @escape_html_entities_in_json = value
|
100
|
-
/[\
|
92
|
+
/[\010\f\n\r\t"\\><&]/
|
101
93
|
else
|
102
|
-
/[\
|
94
|
+
/[\010\f\n\r\t"\\]/
|
103
95
|
end
|
104
96
|
end
|
105
97
|
|
106
98
|
def escape(string)
|
107
|
-
if string.respond_to?(:force_encoding)
|
108
|
-
string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
|
109
|
-
end
|
99
|
+
string = string.dup.force_encoding(::Encoding::BINARY) if string.respond_to?(:force_encoding)
|
110
100
|
json = string.
|
111
101
|
gsub(escape_regex) { |s| ESCAPED_CHARS[s] }.
|
112
102
|
gsub(/([\xC0-\xDF][\x80-\xBF]|
|
@@ -114,14 +104,11 @@ module ActiveSupport
|
|
114
104
|
[\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
|
115
105
|
s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
|
116
106
|
}
|
117
|
-
|
118
|
-
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
|
119
|
-
json
|
107
|
+
%("#{json}")
|
120
108
|
end
|
121
109
|
end
|
122
110
|
|
123
|
-
self.
|
124
|
-
self.escape_html_entities_in_json = false
|
111
|
+
self.escape_html_entities_in_json = true
|
125
112
|
end
|
126
113
|
|
127
114
|
CircularReferenceError = Deprecation::DeprecatedConstantProxy.new('ActiveSupport::JSON::CircularReferenceError', Encoding::CircularReferenceError)
|
@@ -134,13 +121,7 @@ class Object
|
|
134
121
|
ActiveSupport::JSON.encode(self, options)
|
135
122
|
end
|
136
123
|
|
137
|
-
def as_json(options = nil) #:nodoc:
|
138
|
-
if respond_to?(:to_hash)
|
139
|
-
to_hash
|
140
|
-
else
|
141
|
-
instance_values
|
142
|
-
end
|
143
|
-
end
|
124
|
+
def as_json(options = nil) instance_values end #:nodoc:
|
144
125
|
end
|
145
126
|
|
146
127
|
# A string that returns itself as its JSON-encoded form.
|
@@ -178,20 +159,9 @@ class Numeric
|
|
178
159
|
def encode_json(encoder) to_s end #:nodoc:
|
179
160
|
end
|
180
161
|
|
181
|
-
class BigDecimal
|
182
|
-
# A BigDecimal would be naturally represented as a JSON number. Most libraries,
|
183
|
-
# however, parse non-integer JSON numbers directly as floats. Clients using
|
184
|
-
# those libraries would get in general a wrong number and no way to recover
|
185
|
-
# other than manually inspecting the string with the JSON code itself.
|
186
|
-
#
|
187
|
-
# That's why a JSON string is returned. The JSON literal is not numeric, but if
|
188
|
-
# the other end knows by contract that the data is supposed to be a BigDecimal,
|
189
|
-
# it still has the chance to post-process the string and get the real value.
|
190
|
-
def as_json(options = nil) to_s end #:nodoc:
|
191
|
-
end
|
192
|
-
|
193
162
|
class Regexp
|
194
|
-
def as_json(options = nil)
|
163
|
+
def as_json(options = nil) self end #:nodoc:
|
164
|
+
def encode_json(encoder) inspect end #:nodoc:
|
195
165
|
end
|
196
166
|
|
197
167
|
module Enumerable
|
@@ -15,10 +15,7 @@ en:
|
|
15
15
|
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
|
16
16
|
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
|
17
17
|
# Used in date_select and datime_select.
|
18
|
-
order:
|
19
|
-
- :year
|
20
|
-
- :month
|
21
|
-
- :day
|
18
|
+
order: [ :year, :month, :day ]
|
22
19
|
|
23
20
|
time:
|
24
21
|
formats:
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require 'active_support/
|
2
|
-
require 'active_support/core_ext/object/blank'
|
1
|
+
require 'active_support/core_ext/string/bytesize'
|
3
2
|
|
4
3
|
module ActiveSupport
|
5
4
|
# MessageVerifier makes it easy to generate and verify messages which are signed
|
@@ -47,11 +46,11 @@ module ActiveSupport
|
|
47
46
|
def secure_compare(a, b)
|
48
47
|
return false unless a.bytesize == b.bytesize
|
49
48
|
|
50
|
-
l = a.unpack "C
|
49
|
+
l = a.unpack "C#{a.bytesize}"
|
51
50
|
|
52
|
-
res =
|
53
|
-
b.each_byte { |byte| res
|
54
|
-
res
|
51
|
+
res = 0
|
52
|
+
b.each_byte { |byte| res |= byte ^ l.shift }
|
53
|
+
res == 0
|
55
54
|
end
|
56
55
|
|
57
56
|
def generate_digest(data)
|
@@ -1,12 +1,24 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'active_support/core_ext/module/attribute_accessors'
|
3
4
|
|
4
5
|
module ActiveSupport #:nodoc:
|
5
6
|
module Multibyte
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more
|
8
|
+
# information about normalization.
|
9
|
+
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
10
|
+
|
11
|
+
# The Unicode version that is supported by the implementation
|
12
|
+
UNICODE_VERSION = '5.1.0'
|
13
|
+
|
14
|
+
# The default normalization used for operations that require normalization. It can be set to any of the
|
15
|
+
# normalizations in NORMALIZATION_FORMS.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# ActiveSupport::Multibyte.default_normalization_form = :c
|
19
|
+
mattr_accessor :default_normalization_form
|
20
|
+
self.default_normalization_form = :kc
|
21
|
+
|
10
22
|
# The proxy class returned when calling mb_chars. You can use this accessor to configure your own proxy
|
11
23
|
# class so you can support other encodings. See the ActiveSupport::Multibyte::Chars implementation for
|
12
24
|
# an example how to do this.
|
@@ -35,10 +47,13 @@ module ActiveSupport #:nodoc:
|
|
35
47
|
\xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn,
|
36
48
|
# Quick check for valid Shift-JIS characters, disregards the odd-even pairing
|
37
49
|
'Shift_JIS' => /\A(?:
|
38
|
-
[\x00-\x7e\xa1-\xdf] |
|
39
|
-
[\x81-\x9f\xe0-\xef] [\x40-\x7e\x80-\x9e\x9f-\xfc])\z /xn
|
50
|
+
[\x00-\x7e \xa1-\xdf] |
|
51
|
+
[\x81-\x9f \xe0-\xef] [\x40-\x7e \x80-\x9e \x9f-\xfc])\z /xn
|
40
52
|
}
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
44
|
-
require 'active_support/multibyte/
|
56
|
+
require 'active_support/multibyte/chars'
|
57
|
+
require 'active_support/multibyte/exceptions'
|
58
|
+
require 'active_support/multibyte/unicode_database'
|
59
|
+
require 'active_support/multibyte/utils'
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'active_support/core_ext/string/access'
|
3
2
|
require 'active_support/core_ext/string/behavior'
|
4
3
|
|
5
4
|
module ActiveSupport #:nodoc:
|
@@ -19,7 +18,7 @@ module ActiveSupport #:nodoc:
|
|
19
18
|
# bad.explicit_checking_method "T".mb_chars.downcase.to_s
|
20
19
|
#
|
21
20
|
# The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different
|
22
|
-
# encodings you can write your own multibyte string handler and configure it through
|
21
|
+
# encodings you can write your own multibyte string handler and configure it through
|
23
22
|
# ActiveSupport::Multibyte.proxy_class.
|
24
23
|
#
|
25
24
|
# class CharsForUTF32
|
@@ -34,19 +33,59 @@ module ActiveSupport #:nodoc:
|
|
34
33
|
#
|
35
34
|
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
36
35
|
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']
|
37
78
|
|
38
79
|
attr_reader :wrapped_string
|
39
80
|
alias to_s wrapped_string
|
40
81
|
alias to_str wrapped_string
|
41
82
|
|
42
|
-
if
|
83
|
+
if '1.9'.respond_to?(:force_encoding)
|
43
84
|
# Creates a new Chars instance by wrapping _string_.
|
44
85
|
def initialize(string)
|
45
86
|
@wrapped_string = string
|
46
87
|
@wrapped_string.force_encoding(Encoding::UTF_8) unless @wrapped_string.frozen?
|
47
88
|
end
|
48
|
-
|
49
|
-
undef <=>
|
50
89
|
else
|
51
90
|
def initialize(string) #:nodoc:
|
52
91
|
@wrapped_string = string
|
@@ -75,6 +114,12 @@ module ActiveSupport #:nodoc:
|
|
75
114
|
true
|
76
115
|
end
|
77
116
|
|
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
|
+
|
78
123
|
# Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise.
|
79
124
|
def self.consumes?(string)
|
80
125
|
# Unpack is a little bit faster than regular expressions.
|
@@ -86,122 +131,30 @@ module ActiveSupport #:nodoc:
|
|
86
131
|
|
87
132
|
include Comparable
|
88
133
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
# See <tt>String#<=></tt> for more details.
|
99
|
-
#
|
100
|
-
# Example:
|
101
|
-
# 'é'.mb_chars <=> 'ü'.mb_chars #=> -1
|
102
|
-
def <=>(other)
|
103
|
-
@wrapped_string <=> other.to_s
|
104
|
-
end
|
105
|
-
|
106
|
-
# Returns a new Chars object containing the _other_ object concatenated to the string.
|
107
|
-
#
|
108
|
-
# Example:
|
109
|
-
# ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
|
110
|
-
def +(other)
|
111
|
-
self << other
|
112
|
-
end
|
113
|
-
|
114
|
-
# Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
|
115
|
-
#
|
116
|
-
# Example:
|
117
|
-
# 'Café périferôl'.mb_chars =~ /ô/ #=> 12
|
118
|
-
def =~(other)
|
119
|
-
translate_offset(@wrapped_string =~ other)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Inserts the passed string at specified codepoint offsets.
|
123
|
-
#
|
124
|
-
# Example:
|
125
|
-
# 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
|
126
|
-
def insert(offset, fragment)
|
127
|
-
unpacked = Unicode.u_unpack(@wrapped_string)
|
128
|
-
unless offset > unpacked.length
|
129
|
-
@wrapped_string.replace(
|
130
|
-
Unicode.u_unpack(@wrapped_string).insert(offset, *Unicode.u_unpack(fragment)).pack('U*')
|
131
|
-
)
|
132
|
-
else
|
133
|
-
raise IndexError, "index #{offset} out of string"
|
134
|
-
end
|
135
|
-
self
|
136
|
-
end
|
137
|
-
|
138
|
-
# Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
|
139
|
-
#
|
140
|
-
# Example:
|
141
|
-
# 'Café'.mb_chars.include?('é') #=> true
|
142
|
-
def include?(other)
|
143
|
-
# We have to redefine this method because Enumerable defines it.
|
144
|
-
@wrapped_string.include?(other)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
|
148
|
-
#
|
149
|
-
# Example:
|
150
|
-
# 'Café périferôl'.mb_chars.index('ô') #=> 12
|
151
|
-
# 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
|
152
|
-
def index(needle, offset=0)
|
153
|
-
wrapped_offset = first(offset).wrapped_string.length
|
154
|
-
index = @wrapped_string.index(needle, wrapped_offset)
|
155
|
-
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
156
|
-
end
|
157
|
-
|
158
|
-
# Returns the position _needle_ in the string, counting in
|
159
|
-
# codepoints, searching backward from _offset_ or the end of the
|
160
|
-
# string. Returns +nil+ if _needle_ isn't found.
|
161
|
-
#
|
162
|
-
# Example:
|
163
|
-
# 'Café périferôl'.mb_chars.rindex('é') #=> 6
|
164
|
-
# 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
|
165
|
-
def rindex(needle, offset=nil)
|
166
|
-
offset ||= length
|
167
|
-
wrapped_offset = first(offset).wrapped_string.length
|
168
|
-
index = @wrapped_string.rindex(needle, wrapped_offset)
|
169
|
-
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns the number of codepoints in the string
|
173
|
-
def size
|
174
|
-
Unicode.u_unpack(@wrapped_string).size
|
175
|
-
end
|
176
|
-
alias_method :length, :size
|
177
|
-
|
178
|
-
# Strips entire range of Unicode whitespace from the right of the string.
|
179
|
-
def rstrip
|
180
|
-
chars(@wrapped_string.gsub(Unicode::TRAILERS_PAT, ''))
|
181
|
-
end
|
182
|
-
|
183
|
-
# Strips entire range of Unicode whitespace from the left of the string.
|
184
|
-
def lstrip
|
185
|
-
chars(@wrapped_string.gsub(Unicode::LEADERS_PAT, ''))
|
186
|
-
end
|
187
|
-
|
188
|
-
# Strips entire range of Unicode whitespace from the right and left of the string.
|
189
|
-
def strip
|
190
|
-
rstrip.lstrip
|
191
|
-
end
|
134
|
+
# Returns <tt>-1</tt>, <tt>0</tt> or <tt>+1</tt> depending on whether the Chars object is to be sorted before,
|
135
|
+
# equal or after the object on the right side of the operation. It accepts any object that implements +to_s+.
|
136
|
+
# See <tt>String#<=></tt> for more details.
|
137
|
+
#
|
138
|
+
# Example:
|
139
|
+
# 'é'.mb_chars <=> 'ü'.mb_chars #=> -1
|
140
|
+
def <=>(other)
|
141
|
+
@wrapped_string <=> other.to_s
|
142
|
+
end
|
192
143
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
144
|
+
# Returns a new Chars object containing the _other_ object concatenated to the string.
|
145
|
+
#
|
146
|
+
# Example:
|
147
|
+
# ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
|
148
|
+
def +(other)
|
149
|
+
self << other
|
150
|
+
end
|
200
151
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
152
|
+
# Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
|
153
|
+
#
|
154
|
+
# Example:
|
155
|
+
# 'Café périferôl'.mb_chars =~ /ô/ #=> 12
|
156
|
+
def =~(other)
|
157
|
+
translate_offset(@wrapped_string =~ other)
|
205
158
|
end
|
206
159
|
|
207
160
|
# Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars
|
@@ -213,6 +166,56 @@ module ActiveSupport #:nodoc:
|
|
213
166
|
@wrapped_string.split(*args).map { |i| i.mb_chars }
|
214
167
|
end
|
215
168
|
|
169
|
+
# Inserts the passed string at specified codepoint offsets.
|
170
|
+
#
|
171
|
+
# Example:
|
172
|
+
# 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
|
173
|
+
def insert(offset, fragment)
|
174
|
+
unpacked = self.class.u_unpack(@wrapped_string)
|
175
|
+
unless offset > unpacked.length
|
176
|
+
@wrapped_string.replace(
|
177
|
+
self.class.u_unpack(@wrapped_string).insert(offset, *self.class.u_unpack(fragment)).pack('U*')
|
178
|
+
)
|
179
|
+
else
|
180
|
+
raise IndexError, "index #{offset} out of string"
|
181
|
+
end
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
# Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
|
186
|
+
#
|
187
|
+
# Example:
|
188
|
+
# 'Café'.mb_chars.include?('é') #=> true
|
189
|
+
def include?(other)
|
190
|
+
# We have to redefine this method because Enumerable defines it.
|
191
|
+
@wrapped_string.include?(other)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
|
195
|
+
#
|
196
|
+
# Example:
|
197
|
+
# 'Café périferôl'.mb_chars.index('ô') #=> 12
|
198
|
+
# 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
|
199
|
+
def index(needle, offset=0)
|
200
|
+
wrapped_offset = self.first(offset).wrapped_string.length
|
201
|
+
index = @wrapped_string.index(needle, wrapped_offset)
|
202
|
+
index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
203
|
+
end
|
204
|
+
|
205
|
+
# Returns the position _needle_ in the string, counting in
|
206
|
+
# codepoints, searching backward from _offset_ or the end of the
|
207
|
+
# string. Returns +nil+ if _needle_ isn't found.
|
208
|
+
#
|
209
|
+
# Example:
|
210
|
+
# 'Café périferôl'.mb_chars.rindex('é') #=> 6
|
211
|
+
# 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
|
212
|
+
def rindex(needle, offset=nil)
|
213
|
+
offset ||= length
|
214
|
+
wrapped_offset = self.first(offset).wrapped_string.length
|
215
|
+
index = @wrapped_string.rindex(needle, wrapped_offset)
|
216
|
+
index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
217
|
+
end
|
218
|
+
|
216
219
|
# Like <tt>String#[]=</tt>, except instead of byte offsets you specify character offsets.
|
217
220
|
#
|
218
221
|
# Example:
|
@@ -232,7 +235,7 @@ module ActiveSupport #:nodoc:
|
|
232
235
|
if args.first.is_a?(Regexp)
|
233
236
|
@wrapped_string[*args] = replace_by
|
234
237
|
else
|
235
|
-
result =
|
238
|
+
result = self.class.u_unpack(@wrapped_string)
|
236
239
|
if args[0].is_a?(Fixnum)
|
237
240
|
raise IndexError, "index #{args[0]} out of string" if args[0] >= result.length
|
238
241
|
min = args[0]
|
@@ -245,10 +248,10 @@ module ActiveSupport #:nodoc:
|
|
245
248
|
else
|
246
249
|
needle = args[0].to_s
|
247
250
|
min = index(needle)
|
248
|
-
max = min +
|
251
|
+
max = min + self.class.u_unpack(needle).length - 1
|
249
252
|
range = Range.new(min, max)
|
250
253
|
end
|
251
|
-
result[range] =
|
254
|
+
result[range] = self.class.u_unpack(replace_by)
|
252
255
|
@wrapped_string.replace(result.pack('U*'))
|
253
256
|
end
|
254
257
|
end
|
@@ -292,13 +295,33 @@ module ActiveSupport #:nodoc:
|
|
292
295
|
justify(integer, :center, padstr)
|
293
296
|
end
|
294
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
|
295
318
|
|
296
319
|
# Reverses all characters in the string.
|
297
320
|
#
|
298
321
|
# Example:
|
299
322
|
# 'Café'.mb_chars.reverse.to_s #=> 'éfaC'
|
300
323
|
def reverse
|
301
|
-
chars(
|
324
|
+
chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*'))
|
302
325
|
end
|
303
326
|
|
304
327
|
# Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
|
@@ -314,15 +337,15 @@ module ActiveSupport #:nodoc:
|
|
314
337
|
elsif (args.size == 2 && !args[1].is_a?(Numeric))
|
315
338
|
raise TypeError, "cannot convert #{args[1].class} into Integer" # Do as if we were native
|
316
339
|
elsif args[0].kind_of? Range
|
317
|
-
cps =
|
340
|
+
cps = self.class.u_unpack(@wrapped_string).slice(*args)
|
318
341
|
result = cps.nil? ? nil : cps.pack('U*')
|
319
342
|
elsif args[0].kind_of? Regexp
|
320
343
|
result = @wrapped_string.slice(*args)
|
321
344
|
elsif args.size == 1 && args[0].kind_of?(Numeric)
|
322
|
-
character =
|
345
|
+
character = self.class.u_unpack(@wrapped_string)[args[0]]
|
323
346
|
result = character.nil? ? nil : [character].pack('U')
|
324
347
|
else
|
325
|
-
result =
|
348
|
+
result = self.class.u_unpack(@wrapped_string).slice(*args).pack('U*')
|
326
349
|
end
|
327
350
|
result.nil? ? nil : chars(result)
|
328
351
|
end
|
@@ -340,22 +363,20 @@ module ActiveSupport #:nodoc:
|
|
340
363
|
slice
|
341
364
|
end
|
342
365
|
|
343
|
-
#
|
344
|
-
# when the storage for a string is limited for some reason.
|
366
|
+
# Returns the codepoint of the first character in the string.
|
345
367
|
#
|
346
368
|
# Example:
|
347
|
-
#
|
348
|
-
|
349
|
-
|
350
|
-
slice(0...translate_offset(limit))
|
369
|
+
# 'こんにちは'.mb_chars.ord #=> 12371
|
370
|
+
def ord
|
371
|
+
self.class.u_unpack(@wrapped_string)[0]
|
351
372
|
end
|
352
373
|
|
353
374
|
# Convert characters in the string to uppercase.
|
354
375
|
#
|
355
376
|
# Example:
|
356
|
-
# 'Laurent,
|
377
|
+
# 'Laurent, òu sont les tests?'.mb_chars.upcase.to_s #=> "LAURENT, ÒU SONT LES TESTS?"
|
357
378
|
def upcase
|
358
|
-
|
379
|
+
apply_mapping :uppercase_mapping
|
359
380
|
end
|
360
381
|
|
361
382
|
# Convert characters in the string to lowercase.
|
@@ -363,7 +384,7 @@ module ActiveSupport #:nodoc:
|
|
363
384
|
# Example:
|
364
385
|
# 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s #=> "věda a výzkum"
|
365
386
|
def downcase
|
366
|
-
|
387
|
+
apply_mapping :lowercase_mapping
|
367
388
|
end
|
368
389
|
|
369
390
|
# Converts the first character to uppercase and the remainder to lowercase.
|
@@ -377,11 +398,25 @@ module ActiveSupport #:nodoc:
|
|
377
398
|
# Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
|
378
399
|
# passing strings to databases and validations.
|
379
400
|
#
|
401
|
+
# * <tt>str</tt> - The string to perform normalization on.
|
380
402
|
# * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
|
381
403
|
# <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
|
382
|
-
# ActiveSupport::Multibyte
|
383
|
-
def normalize(form
|
384
|
-
|
404
|
+
# ActiveSupport::Multibyte.default_normalization_form
|
405
|
+
def normalize(form=ActiveSupport::Multibyte.default_normalization_form)
|
406
|
+
# See http://www.unicode.org/reports/tr15, Table 1
|
407
|
+
codepoints = self.class.u_unpack(@wrapped_string)
|
408
|
+
chars(case form
|
409
|
+
when :d
|
410
|
+
self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints))
|
411
|
+
when :c
|
412
|
+
self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints)))
|
413
|
+
when :kd
|
414
|
+
self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints))
|
415
|
+
when :kc
|
416
|
+
self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints)))
|
417
|
+
else
|
418
|
+
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
419
|
+
end.pack('U*'))
|
385
420
|
end
|
386
421
|
|
387
422
|
# Performs canonical decomposition on all the characters.
|
@@ -390,7 +425,7 @@ module ActiveSupport #:nodoc:
|
|
390
425
|
# 'é'.length #=> 2
|
391
426
|
# 'é'.mb_chars.decompose.to_s.length #=> 3
|
392
427
|
def decompose
|
393
|
-
chars(
|
428
|
+
chars(self.class.decompose_codepoints(:canonical, self.class.u_unpack(@wrapped_string)).pack('U*'))
|
394
429
|
end
|
395
430
|
|
396
431
|
# Performs composition on all the characters.
|
@@ -399,7 +434,7 @@ module ActiveSupport #:nodoc:
|
|
399
434
|
# 'é'.length #=> 3
|
400
435
|
# 'é'.mb_chars.compose.to_s.length #=> 2
|
401
436
|
def compose
|
402
|
-
chars(
|
437
|
+
chars(self.class.compose_codepoints(self.class.u_unpack(@wrapped_string)).pack('U*'))
|
403
438
|
end
|
404
439
|
|
405
440
|
# Returns the number of grapheme clusters in the string.
|
@@ -408,14 +443,12 @@ module ActiveSupport #:nodoc:
|
|
408
443
|
# 'क्षि'.mb_chars.length #=> 4
|
409
444
|
# 'क्षि'.mb_chars.g_length #=> 3
|
410
445
|
def g_length
|
411
|
-
|
446
|
+
self.class.g_unpack(@wrapped_string).length
|
412
447
|
end
|
413
448
|
|
414
449
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
|
415
|
-
|
416
|
-
|
417
|
-
def tidy_bytes(force = false)
|
418
|
-
chars(Unicode.tidy_bytes(@wrapped_string, force))
|
450
|
+
def tidy_bytes
|
451
|
+
chars(self.class.tidy_bytes(@wrapped_string))
|
419
452
|
end
|
420
453
|
|
421
454
|
%w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method|
|
@@ -429,21 +462,213 @@ module ActiveSupport #:nodoc:
|
|
429
462
|
end
|
430
463
|
end
|
431
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
|
632
|
+
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
|
+
end
|
651
|
+
end
|
652
|
+
|
432
653
|
protected
|
433
654
|
|
434
655
|
def translate_offset(byte_offset) #:nodoc:
|
435
656
|
return nil if byte_offset.nil?
|
436
657
|
return 0 if @wrapped_string == ''
|
437
|
-
|
438
|
-
if @wrapped_string.respond_to?(:force_encoding)
|
439
|
-
@wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT)
|
440
|
-
end
|
441
|
-
|
658
|
+
chunk = @wrapped_string[0..byte_offset]
|
442
659
|
begin
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
660
|
+
begin
|
661
|
+
chunk.unpack('U*').length - 1
|
662
|
+
rescue ArgumentError => e
|
663
|
+
chunk = @wrapped_string[0..(byte_offset+=1)]
|
664
|
+
# Stop retrying at the end of the string
|
665
|
+
raise e unless byte_offset < chunk.length
|
666
|
+
# We damaged a character, retry
|
667
|
+
retry
|
668
|
+
end
|
669
|
+
# Catch the ArgumentError so we can throw our own
|
670
|
+
rescue ArgumentError
|
671
|
+
raise EncodingError, 'malformed UTF-8 character'
|
447
672
|
end
|
448
673
|
end
|
449
674
|
|
@@ -453,23 +678,26 @@ module ActiveSupport #:nodoc:
|
|
453
678
|
padsize = padsize > 0 ? padsize : 0
|
454
679
|
case way
|
455
680
|
when :right
|
456
|
-
result = @wrapped_string.dup.insert(0, padding(padsize, padstr))
|
681
|
+
result = @wrapped_string.dup.insert(0, self.class.padding(padsize, padstr))
|
457
682
|
when :left
|
458
|
-
result = @wrapped_string.dup.insert(-1, padding(padsize, padstr))
|
683
|
+
result = @wrapped_string.dup.insert(-1, self.class.padding(padsize, padstr))
|
459
684
|
when :center
|
460
|
-
lpad = padding((padsize / 2.0).floor, padstr)
|
461
|
-
rpad = padding((padsize / 2.0).ceil, padstr)
|
685
|
+
lpad = self.class.padding((padsize / 2.0).floor, padstr)
|
686
|
+
rpad = self.class.padding((padsize / 2.0).ceil, padstr)
|
462
687
|
result = @wrapped_string.dup.insert(0, lpad).insert(-1, rpad)
|
463
688
|
end
|
464
689
|
chars(result)
|
465
690
|
end
|
466
691
|
|
467
|
-
def
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
692
|
+
def apply_mapping(mapping) #:nodoc:
|
693
|
+
chars(self.class.u_unpack(@wrapped_string).map do |codepoint|
|
694
|
+
cp = UCD.codepoints[codepoint]
|
695
|
+
if cp and (ncp = cp.send(mapping)) and ncp > 0
|
696
|
+
ncp
|
697
|
+
else
|
698
|
+
codepoint
|
699
|
+
end
|
700
|
+
end.pack('U*'))
|
473
701
|
end
|
474
702
|
|
475
703
|
def chars(string) #:nodoc:
|