1 28 package org.jruby; 29 30 import java.nio.ByteBuffer ; 31 import java.nio.CharBuffer ; 32 import java.nio.charset.CharacterCodingException ; 33 import java.nio.charset.Charset ; 34 import java.nio.charset.CharsetDecoder ; 35 import java.nio.charset.CharsetEncoder ; 36 import java.nio.charset.CodingErrorAction ; 37 import java.nio.charset.UnmappableCharacterException ; 38 import java.nio.charset.UnsupportedCharsetException ; 39 40 import org.jruby.runtime.Block; 41 import org.jruby.runtime.CallbackFactory; 42 import org.jruby.runtime.ObjectAllocator; 43 import org.jruby.runtime.builtin.IRubyObject; 44 45 import org.jruby.util.ByteList; 46 47 public class RubyIconv extends RubyObject { 48 public RubyIconv(Ruby runtime, RubyClass type) { 49 super(runtime, type); 50 } 51 52 private static ObjectAllocator ICONV_ALLOCATOR = new ObjectAllocator() { 53 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 54 return new RubyIconv(runtime, klass); 55 } 56 }; 57 58 public static void createIconv(Ruby runtime) { 59 RubyClass iconvClass = runtime.defineClass("Iconv", runtime.getObject(), ICONV_ALLOCATOR); 60 61 RubyClass argumentError = runtime.getClass("ArgumentError"); 62 iconvClass.defineClassUnder("IllegalSequence", argumentError, argumentError.getAllocator()); 63 iconvClass.defineClassUnder("InvalidCharacter", argumentError, argumentError.getAllocator()); 64 iconvClass.defineClassUnder("InvalidEncoding", argumentError, argumentError.getAllocator()); 65 66 CallbackFactory callbackFactory = runtime.callbackFactory(RubyIconv.class); 67 68 iconvClass.getMetaClass().defineFastMethod("iconv", callbackFactory.getOptSingletonMethod("iconv")); 69 iconvClass.getMetaClass().defineFastMethod("conv", callbackFactory.getOptSingletonMethod("conv")); 70 71 iconvClass.defineMethod("initialize", callbackFactory.getOptMethod("initialize")); 72 74 } 77 78 97 98 public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { 99 checkArgumentCount(args, 2, 2); 100 101 104 return this; 105 } 106 107 public static IRubyObject iconv(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 108 return convertWithArgs(recv, args, "iconv"); 109 } 110 111 public static IRubyObject conv(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 112 return convertWithArgs(recv, args, "conv").join(recv.getRuntime().newString("")); 113 } 114 115 public static RubyArray convertWithArgs(IRubyObject recv, IRubyObject[] args, String function) { 116 recv.checkArgumentCount(args, 3, -1); 117 118 String fromEncoding = args[1].convertToString().toString(); 119 String toEncoding = args[0].convertToString().toString(); 120 RubyArray array = recv.getRuntime().newArray(); 121 122 for (int i = 2; i < args.length; i++) { 123 array.append(convert2(fromEncoding, toEncoding, args[i].convertToString())); 124 } 125 126 return array; 127 } 128 129 140 141 private static IRubyObject convert2(String fromEncoding, String toEncoding, RubyString original) { 144 try { 145 byte[] bytes = original.getBytes(); 147 ByteBuffer buf = ByteBuffer.wrap(bytes); 148 149 CharsetDecoder decoder = Charset.forName(fromEncoding).newDecoder(); 150 151 decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 152 CharBuffer cbuf = decoder.decode(buf); 153 CharsetEncoder encoder = Charset.forName(toEncoding).newEncoder(); 154 155 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 156 buf = encoder.encode(cbuf); 157 byte[] arr = buf.array(); 158 return RubyString.newString(original.getRuntime(), new ByteList(arr,0,buf.limit())); 159 } catch (UnsupportedCharsetException e) { 160 throw original.getRuntime().newInvalidEncoding("invalid encoding"); 161 } catch (UnmappableCharacterException e) { 162 } catch (CharacterCodingException e) { 163 } 164 return original.getRuntime().getNil(); 165 } 166 } 167 | Popular Tags |