001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.misc.accessors;
019:
020: import java.nio.ByteOrder;
021: import java.io.UnsupportedEncodingException;
022:
023: import org.apache.harmony.misc.internal.nls.Messages;
024:
025: /**
026: * This class allows to copy data from String objects to native buffers, and
027: * construct String objects from native strings. This allows to pass and receive
028: * string arguments from native libraries.
029: *
030: * The main difference between modified UTF8 and UTF8 is two trailing 0 instead
031: * of one (see JNI 5.0 spec on Modified UTF-8 Strings).
032: */
033: public class StringAccessor {
034:
035: private static StringAccessor instance;
036:
037: static StringAccessor getInstance() {
038: if (instance == null) {
039: System.loadLibrary("accessors"); //$NON-NLS-1$
040: instance = new StringAccessor();
041: }
042: return instance;
043: }
044:
045: private StringAccessor() {
046: }
047:
048: /**
049: * Creates modified UTF8 encoded copy of String object in native heap.
050: * Allocates buffer enough to represent 0 terminated string in native heap.
051: * Adds 2 trailing 0 to the end of native string. The returned buffer should
052: * be deallocated by {@link MemoryAccessor#free}
053: * <p>
054: * This method has an effect of GetStringUTFChars JNI call.
055: *
056: * @param str
057: * string to copy
058: * @return buffer memory address
059: */
060: public native long getUTFChars(String str);
061:
062: /**
063: * Copies len modified UTF8 encoded chars or buflen bytes whichever is
064: * smaller from String to native buffer. If there is a room in buffer after
065: * last copied string char, 2 trailing 0 are added. For ANSI chars buffer
066: * should be at least len bytes, for international chars buffer should be at
067: * least 3 * len bytes (see JNI 5.0 spec on Modified UTF-8 Strings) to
068: * guaranty String chars will fully fit.
069: * <p>
070: * This method has an effect of GetStringUTFRegion JNI call.
071: *
072: * @param buf
073: * memory address of native buf
074: * @param buflen
075: * length of buffer in bytes
076: * @param str
077: * string to copy
078: * @param start
079: * first char index
080: * @param len
081: * number of chars to copy
082: * @return buf
083: */
084: public long getUTFChars(long buf, long buflen, String str,
085: int start, int len) {
086: String substr = str.substring(start, start + len);
087: long addr = getUTFChars(substr);
088: Malloc.strncpy(buf, addr, buflen);
089: Malloc.free(addr);
090: return buf;
091: }
092:
093: /**
094: * Creates UTF16 (Unicode) copy of String object in native heap. Allocates
095: * buffer enough to represent 0 terminated string in native heap. The
096: * returned buffer should be deallocated by {@link MemoryAccessor#free}
097: * <p>
098: * This method has an effect of GetStringChars JNI call.
099: *
100: * @param str -
101: * string to copy
102: * @return buffer memory address
103: */
104: public native long getChars(String str);
105:
106: /**
107: * Copies len UTF16 (Unicode) encoded chars or buflen bytes whichever is
108: * smaller from String to native buffer. If there is a room in buffer after
109: * last copied string char, 2 trailing 0 are added. Buffer should be at
110: * least 2 * len bytes to guaranty String chars will fully fit.
111: * <p>
112: * This method has an effect of GetStringRegion JNI call.
113: *
114: * @param buf
115: * memory address of native buf
116: * @param buflen
117: * length of buffer in bytes
118: * @param str
119: * string to copy
120: * @param start
121: * first char index
122: * @param len
123: * number of chars to copy
124: * @return buf
125: */
126: public long getChars(long buf, long buflen, String str, int start,
127: int len) {
128: String substr = str.substring(start, start + len);
129: long addr = getChars(substr);
130: Malloc.memcpy(buf, addr, Math.min(buflen,
131: (substr.length() + 1) * 2));
132: Malloc.free(addr);
133: return buf;
134: }
135:
136: /**
137: * Creates String from 0 terminated modified UTF8 native string
138: * <p>
139: * This method has an effect of NewStringUTF JNI call.
140: *
141: * @param str
142: * memory address of native
143: * @return new String
144: */
145: public native String createStringUTF(long str);
146:
147: /**
148: * Creates String from 0 terminated UTF16 (Unicode) native string
149: * <p>
150: * This method has an effect of NewString JNI call.
151: *
152: * @param wstr
153: * memory address of native
154: * @return new String
155: */
156: public native String createString(long wstr);
157:
158: /**
159: * Creates String from 0 terminated modified UTF8 native string of max
160: * strlen length in bytes.
161: * <p>
162: * This method has an effect of NewStringUTF JNI call.
163: *
164: * @param str
165: * memory address of native
166: * @param strlen
167: * max length of native string in bytes
168: * @return new String
169: */
170: public native String createStringUTF(long str, long strlen);
171:
172: /**
173: * Creates String from 0 terminated UTF16 (Unicode) native string of max
174: * strlen length in bytes.
175: * <p>
176: * This method has an effect of NewString JNI call.
177: *
178: * @param wstr
179: * memory address of native
180: * @param strlen
181: * max length of native string in bytes
182: * @return new String
183: */
184: public native String createString(long wstr, long strlen);
185:
186: /**
187: * Creates String from 0 terminated UTF16 (Unicode) native string of max
188: * strlen length in bytes.
189: * <p>
190: * This method has an effect of NewString JNI call.
191: *
192: * @param wstr
193: * memory address of native
194: * @param order
195: * byte order
196: * @return new String
197: */
198: public native String createOrderedString(long wstr, int order);
199:
200: /**
201: * Lexicographically compares Java string with native UTF-8 encoded string .
202: * The comparison is based on the Unicode value of each character in the
203: * strings. The character sequence represented by String object is compared
204: * lexicographically to the character sequence represented by the native
205: * UTF-8 string. The result is a negative integer if String object
206: * lexicographically precedes the argument str. The result is a positive
207: * integer if this String object lexicographically follows the argument str.
208: * The result is zero if the strings are equal.
209: * @param strObj Java string
210: * @param str native string memory address
211: * @return 0 if strings are equal,
212: * <0 if Java string is lexicographically less than the native string,
213: * >0 if Java string is lexicographically greater than the native string.
214: */
215: public int compareStringUTF(String strObj, long str) {
216: return strObj.compareTo(createStringUTF(str));
217: }
218:
219: /**
220: * Lexicographically compares Java string with native UTF-16 encoded string
221: * in byteOrder order.
222: * @param strObj Java string
223: * @param str native string memory address
224: * @param len length of native string
225: * @param byteOrder either ByteOrder.BIG_ENDIAN or ByteOrder.LITTLE_ENDIAN
226: * @return 0 if strings are equal,
227: * <0 if Java string is lexicographically less than the native string,
228: * >0 if Java string is lexicographically greater than the native string.
229: */
230: public int compareString(String strObj, long str, int len,
231: int byteOrder) {
232: ByteOrder or = ByteOrder.nativeOrder();
233: String cmpTo = createString(str, 2 * len);
234: if ((byteOrder == 1 && or == ByteOrder.BIG_ENDIAN)
235: || (byteOrder == 2 && or == ByteOrder.LITTLE_ENDIAN)) {
236: return strObj.compareTo(cmpTo);
237: }
238: try {
239: if (byteOrder == 1) {
240: cmpTo = new String(
241: cmpTo.getBytes("UTF-16BE"), "UTF-16BE"); //$NON-NLS-1$ //$NON-NLS-2$
242: } else {
243: cmpTo = new String(
244: cmpTo.getBytes("UTF-16LE"), "UTF-16LE"); //$NON-NLS-1$ //$NON-NLS-2$
245: }
246: } catch (UnsupportedEncodingException e) {
247: throw new InternalError(
248: // misc.6=Failed to get UTF-16 support, this is a bug
249: Messages.getString("misc.6")); //$NON-NLS-1$
250: }
251: return strObj.compareTo(cmpTo);
252: }
253:
254: /**
255: * Lexicographically compares Java string with native UTF-16 encoded string
256: * in platform default order.
257: * @param strObj Java string
258: * @param str native string memory address
259: * @param len length of native string
260: * @return 0 if strings are equal,
261: * <0 if Java string is lexicographically less than the native string,
262: * >0 if Java string is lexicographically greater than the native string.
263: */
264: public int compareString(String strObj, long str, int len) {
265: return strObj.compareTo(createString(str, 2 * len));
266: }
267:
268: /**
269: * Lexicographically compares the Java string with the character sequence
270: * represented by the part of char array str.
271: * @param strObj Java string
272: * @param str char array
273: * @param offset offset within char array
274: * @return 0 if strings are equal,
275: * <0 if Java string is lexicographically less than the native string,
276: * >0 if Java string is lexicographically greater than the native string.
277: */
278: public int compareStringAndChars(String strObj, char[] str,
279: int offset, int len) {
280: return strObj.compareTo(new String(str, offset, len));
281: }
282:
283: }
|