From 935bd0fef8e26f4ec65fe411a1d29942493f8d46 Mon Sep 17 00:00:00 2001 From: Manfred Stienstra Date: Sun, 1 Nov 2009 17:18:27 +0100 Subject: Add ActiveSupport::Multibyte::Chars#limit. The limit method limits the number of bytes in a string. Useful when the storage space of the string is limited, for instance in a database column definition. Sharpen up the implementation of translate offset. [#3192 state:committed] --- .../lib/active_support/multibyte/chars.rb | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'activesupport/lib/active_support/multibyte') diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index c9bcfbd313..51b870de8c 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -363,6 +363,16 @@ module ActiveSupport #:nodoc: slice end + # Limit the byte size of the string to a number of bytes without breaking characters. Usable + # when the storage for a string is limited for some reason. + # + # Example: + # s = 'こんにちは' + # s.mb_chars.limit(7) #=> "こに" + def limit(limit) + slice(0...translate_offset(limit)) + end + # Returns the codepoint of the first character in the string. # # Example: @@ -651,24 +661,15 @@ module ActiveSupport #:nodoc: end protected - + def translate_offset(byte_offset) #:nodoc: return nil if byte_offset.nil? return 0 if @wrapped_string == '' - chunk = @wrapped_string[0..byte_offset] begin - begin - chunk.unpack('U*').length - 1 - rescue ArgumentError => e - chunk = @wrapped_string[0..(byte_offset+=1)] - # Stop retrying at the end of the string - raise e unless byte_offset < chunk.length - # We damaged a character, retry - retry - end - # Catch the ArgumentError so we can throw our own - rescue ArgumentError - raise EncodingError, 'malformed UTF-8 character' + @wrapped_string[0...byte_offset].unpack('U*').length + rescue ArgumentError => e + byte_offset -= 1 + retry end end -- cgit v1.2.3