/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.j2objc.nio.charset;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.UnsupportedCharsetException;
/**
* iOS native charset encoder.
*
* @author Tom Ball
*/
public class IOSCharsetEncoder extends CharsetEncoder {
private char[] inBuffer;
private byte[] byteBuffer;
private int outIndex;
protected IOSCharsetEncoder(Charset charset, float maxBytesPerChar) {
super(charset, maxBytesPerChar, maxBytesPerChar, new byte[] { (byte) '?' });
}
@Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
if (byteBuffer != null) {
while (out.hasRemaining() && outIndex < byteBuffer.length) {
out.put(byteBuffer[outIndex++]);
}
if (outIndex == byteBuffer.length){
byteBuffer = null;
return CoderResult.UNDERFLOW;
} else {
return CoderResult.OVERFLOW;
}
} else if (in.hasRemaining()) {
byte[] b = encodeImpl(in);
if (b.length == 0) {
return CoderResult.UNDERFLOW;
}
if (out.remaining() < b.length){
byteBuffer = b;
outIndex = 0;
return encodeLoop(in, out);
} else {
out.put(b);
}
}
return CoderResult.UNDERFLOW; // All input data was decoded.
}
private byte[] encodeImpl(CharBuffer in) {
Charset cs = charset();
if (!(cs instanceof IOSCharset)) {
throw new UnsupportedCharsetException(cs.name());
}
char[] chars;
int i;
if (inBuffer != null) {
i = inBuffer.length;
chars = new char[i + in.remaining()];
System.arraycopy(inBuffer, 0, chars, 0, inBuffer.length);
inBuffer = null;
} else {
if (((IOSCharset) cs).nsEncoding() == /* NSUnicodeStringEncoding */ 10L) {
// Prepend required BOM for Java's big-endian encoding default.
chars = new char[in.remaining() + 1];
chars[0] = (char) 0xFEFF;
i = 1;
} else {
i = 0;
chars = new char[in.remaining()];
}
}
in.get(chars, i, chars.length - i);
byte[] bytes = encode(chars, ((IOSCharset) cs).nsEncoding());
if (bytes.length == 0) {
inBuffer = chars;
} else {
inBuffer = null;
}
return bytes;
}
private static native byte[] encode(char[] in, long encoding) /*-[
if (encoding == NSUnicodeStringEncoding) {
// Force encoding to be big-endian to match Java encoding.
encoding = NSUTF16BigEndianStringEncoding;
}
NSString *s = [NSString stringWithCharacters:inArg->buffer_
length:inArg->size_];
NSData *data = [s dataUsingEncoding:(NSStringEncoding) encoding allowLossyConversion:NO];
return [IOSByteArray arrayWithBytes:(const jbyte *)[data bytes] count:(jint)[data length]];
]-*/;
}