1/* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Internal native functions. All of the functions defined here make 5 * direct use of VM functions or data structures, so they can't be written 6 * with JNI and shouldn't really be in a shared library. 7 * 8 * All functions here either complete quickly or are used to enter a wait 9 * state, so we don't set the thread status to THREAD_NATIVE when executing 10 * these methods. This means that the GC will wait for these functions 11 * to finish. DO NOT perform long operations or blocking I/O in here. 12 * 13 * In some cases we're following the division of labor defined by GNU 14 * ClassPath, e.g. java.lang.Thread has "Thread" and "VMThread", with 15 * the VM-specific behavior isolated in VMThread. 16 */ 17 18#include "JNIHelp.h" 19#include "AndroidSystemNatives.h" 20#include "ErrorCode.h" 21#include "unicode/ubrk.h" 22#include "unicode/putil.h" 23#include <stdlib.h> 24 25static jstring getAvailableLocalesImpl(JNIEnv *env, jclass clazz, jint index) { 26 27 const char * locale = ubrk_getAvailable(index); 28 29 return (*env)->NewStringUTF(env, locale); 30 31} 32 33static jint getAvailableLocalesCountImpl(JNIEnv *env, jclass clazz) { 34 return ubrk_countAvailable(); 35} 36 37static jint getCharacterInstanceImpl(JNIEnv *env, jclass clazz, jstring locale) { 38 39 UErrorCode status = U_ZERO_ERROR; 40 41 const char *localeChars = (*env)->GetStringUTFChars(env, locale, 0); 42 43 UBreakIterator *iter = ubrk_open(UBRK_CHARACTER, localeChars, NULL, 0, &status); 44 45 (*env)->ReleaseStringUTFChars(env, locale, localeChars); 46 47 if ( icu4jni_error(env, status) != FALSE) { 48 return 0; 49 } 50 51 return (long) iter; 52} 53 54static jint getLineInstanceImpl(JNIEnv *env, jclass clazz, jstring locale) { 55 56 UErrorCode status = U_ZERO_ERROR; 57 58 const char *localeChars = (*env)->GetStringUTFChars(env, locale, 0); 59 60 enum UBreakIteratorType type = UBRK_LINE; 61 62 UBreakIterator *iter = ubrk_open(type, localeChars, NULL, 0, &status); 63 64 (*env)->ReleaseStringUTFChars(env, locale, localeChars); 65 66 if ( icu4jni_error(env, status) != FALSE) { 67 return 0; 68 } 69 70 return (long) iter; 71} 72 73static jint getSentenceInstanceImpl(JNIEnv *env, jclass clazz, jstring locale) { 74 75 UErrorCode status = U_ZERO_ERROR; 76 77 const char *localeChars = (*env)->GetStringUTFChars(env, locale, 0); 78 79 enum UBreakIteratorType type = UBRK_SENTENCE; 80 81 UBreakIterator *iter = ubrk_open(type, localeChars, NULL, 0, &status); 82 83 (*env)->ReleaseStringUTFChars(env, locale, localeChars); 84 85 if ( icu4jni_error(env, status) != FALSE) { 86 return 0; 87 } 88 89 return (long) iter; 90} 91 92static jint getWordInstanceImpl(JNIEnv *env, jclass clazz, jstring locale) { 93 94 UErrorCode status = U_ZERO_ERROR; 95 96 const char *localeChars = (*env)->GetStringUTFChars(env, locale, 0); 97 98 enum UBreakIteratorType type = UBRK_WORD; 99 100 UBreakIterator *iter = ubrk_open(type, localeChars, NULL, 0, &status); 101 102 (*env)->ReleaseStringUTFChars(env, locale, localeChars); 103 104 if ( icu4jni_error(env, status) != FALSE) { 105 return 0; 106 } 107 108 return (long) iter; 109} 110 111static void closeBreakIteratorImpl(JNIEnv *env, jclass clazz, jint address) { 112 113 UBreakIterator *bi = (UBreakIterator *)(long)address; 114 115 ubrk_close(bi); 116} 117 118static jint cloneImpl(JNIEnv *env, jclass clazz, jint address) { 119 120 UErrorCode status = U_ZERO_ERROR; 121 122 UBreakIterator *bi = (UBreakIterator *)(long)address; 123 124 jint buffersize = U_BRK_SAFECLONE_BUFFERSIZE; 125 126 UBreakIterator *iter = ubrk_safeClone(bi, NULL, &buffersize, &status); 127 128 if (icu4jni_error(env, status) != FALSE) { 129 return 0; 130 } 131 132 return (long) iter; 133} 134 135static void setTextImpl(JNIEnv *env, jclass clazz, jint address, jstring text) { 136 137 UErrorCode status = U_ZERO_ERROR; 138 139 UBreakIterator *bi = (UBreakIterator *)(long)address; 140 141 const UChar *strUChars = (*env)->GetStringChars(env, text, NULL); 142 int strLen = (*env)->GetStringLength(env, text); 143 144 ubrk_setText(bi, strUChars, strLen, &status); 145 146 (*env)->ReleaseStringChars(env, text, strUChars); 147 148 icu4jni_error(env, status); 149} 150 151static jboolean isBoundaryImpl(JNIEnv *env, jclass clazz, jint address, jint offset) { 152 153 UBreakIterator *bi = (UBreakIterator *)(long)address; 154 155 return ubrk_isBoundary(bi, offset); 156} 157 158static jint nextImpl(JNIEnv *env, jclass clazz, jint address, jint n) { 159 160 UBreakIterator *bi = (UBreakIterator *)(long)address; 161 162 if(n < 0) { 163 while(n++ < -1) { 164 ubrk_previous(bi); 165 } 166 return ubrk_previous(bi); 167 } else if(n == 0) { 168 return ubrk_current(bi); 169 } else { 170 while(n-- > 1) { 171 ubrk_next(bi); 172 } 173 return ubrk_next(bi); 174 } 175 176 return -1; 177} 178 179static jint precedingImpl(JNIEnv *env, jclass clazz, jint address, jint offset) { 180 181 UBreakIterator *bi = (UBreakIterator *)(long)address; 182 183 return ubrk_preceding(bi, offset); 184} 185 186static jint firstImpl(JNIEnv *env, jclass clazz, jint address) { 187 188 UBreakIterator *bi = (UBreakIterator *)(long)address; 189 190 return ubrk_first(bi); 191} 192 193static jint followingImpl(JNIEnv *env, jclass clazz, jint address, jint offset) { 194 195 UBreakIterator *bi = (UBreakIterator *)(long)address; 196 197 return ubrk_following(bi, offset); 198} 199 200static jint currentImpl(JNIEnv *env, jclass clazz, jint address) { 201 202 UBreakIterator *bi = (UBreakIterator *)(long)address; 203 204 return ubrk_current(bi); 205} 206 207static jint previousImpl(JNIEnv *env, jclass clazz, jint address) { 208 209 UBreakIterator *bi = (UBreakIterator *)(long)address; 210 211 return ubrk_previous(bi); 212} 213 214static jint lastImpl(JNIEnv *env, jclass clazz, jint address) { 215 216 UBreakIterator *bi = (UBreakIterator *)(long)address; 217 218 return ubrk_last(bi); 219} 220 221/* 222 * JNI registration 223 */ 224static JNINativeMethod gMethods[] = { 225 /* name, signature, funcPtr */ 226 { "getAvailableLocalesImpl", "(I)Ljava/lang/String;", 227 (void*) getAvailableLocalesImpl }, 228 { "getAvailableLocalesCountImpl", "()I", 229 (void*) getAvailableLocalesCountImpl }, 230 { "getCharacterInstanceImpl", "(Ljava/lang/String;)I", 231 (void*) getCharacterInstanceImpl }, 232 { "getLineInstanceImpl", "(Ljava/lang/String;)I", 233 (void*) getLineInstanceImpl }, 234 { "getSentenceInstanceImpl", "(Ljava/lang/String;)I", 235 (void*) getSentenceInstanceImpl }, 236 { "getWordInstanceImpl", "(Ljava/lang/String;)I", 237 (void*) getWordInstanceImpl }, 238 { "closeBreakIteratorImpl", "(I)V", 239 (void*) closeBreakIteratorImpl }, 240 { "cloneImpl", "(I)I", 241 (void*) cloneImpl }, 242 { "setTextImpl", "(ILjava/lang/String;)V", 243 (void*) setTextImpl }, 244 { "isBoundaryImpl", "(II)Z", 245 (void*) isBoundaryImpl }, 246 { "nextImpl", "(II)I", 247 (void*) nextImpl }, 248 { "precedingImpl", "(II)I", 249 (void*) precedingImpl }, 250 { "firstImpl", "(I)I", 251 (void*) firstImpl }, 252 { "lastImpl", "(I)I", 253 (void*) lastImpl }, 254 { "currentImpl", "(I)I", 255 (void*) currentImpl }, 256 { "followingImpl", "(II)I", 257 (void*) followingImpl }, 258 { "previousImpl", "(I)I", 259 (void*) previousImpl }, 260}; 261int register_com_ibm_icu4jni_text_NativeBreakIterator(JNIEnv* env) { 262 return jniRegisterNativeMethods(env, "com/ibm/icu4jni/text/NativeBreakIterator", 263 gMethods, NELEM(gMethods)); 264} 265