static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray, jbyteArray infoArray, int n, jboolean haveInfo) { // Parameters are checked on java side // Failures from GetXXXArrayElements indicate a serious out-of-memory condition // that we don't bother to report, we're probably dead anyway. jint result = 0; jchar* chs = env->GetCharArrayElements(chsArray, NULL); if (chs != NULL) { jbyte* info = env->GetByteArrayElements(infoArray, NULL); if (info != NULL) { UErrorCode status = U_ZERO_ERROR; UBiDi* bidi = ubidi_openSized(n, 0, &status); ubidi_setPara(bidi, chs, n, dir, NULL, &status); if (U_SUCCESS(status)) { for (int i = 0; i < n; ++i) { info[i] = ubidi_getLevelAt(bidi, i); } result = ubidi_getParaLevel(bidi); } else { jniThrowException(env, "java/lang/RuntimeException", NULL); } ubidi_close(bidi); env->ReleaseByteArrayElements(infoArray, info, 0); } env->ReleaseCharArrayElements(chsArray, chs, JNI_ABORT); } return result; }
/** * Performs character mirroring. * * @param pTransform Pointer to the <code>UBiDiTransform</code> structure. * @param pErrorCode Pointer to the error code value. * * @return Whether or not this function modifies the text. Besides the return * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>. */ static UBool action_mirror(UBiDiTransform *pTransform, UErrorCode *pErrorCode) { UChar32 c; uint32_t i = 0, j = 0; if (0 == (pTransform->reorderingOptions & UBIDI_DO_MIRRORING)) { return FALSE; } if (pTransform->destSize < pTransform->srcLength) { *pErrorCode = U_BUFFER_OVERFLOW_ERROR; return FALSE; } do { UBool isOdd = ubidi_getLevelAt(pTransform->pBidi, i) & 1; U16_NEXT(pTransform->src, i, pTransform->srcLength, c); U16_APPEND_UNSAFE(pTransform->dest, j, isOdd ? u_charMirror(c) : c); } while (i < pTransform->srcLength); *pTransform->pDestLength = pTransform->srcLength; pTransform->reorderingOptions = UBIDI_REORDER_DEFAULT; return TRUE; }
int icu_bidi_runs(lua_State *L) { size_t input_l; const char* input = luaL_checklstring(L, 1, &input_l); const char* direction = luaL_checkstring(L, 2); UChar *input_as_uchar; int32_t l; utf8_to_uchar(input, input_l, input_as_uchar, l); UBiDiLevel paraLevel = 0; if (strncasecmp(direction, "RTL", 3) == 0) { paraLevel = 1; } /* Now let's bidi! */ UBiDi* bidi = ubidi_open(); UErrorCode err = U_ZERO_ERROR; ubidi_setPara(bidi, input_as_uchar, l, paraLevel, NULL, &err); if (!U_SUCCESS(err)) { free(input_as_uchar); ubidi_close(bidi); return luaL_error(L, "Error in bidi %s", u_errorName(err)); } int count = ubidi_countRuns(bidi,&err); int start, length; lua_checkstack(L,count); for (int i=0; i < count; i++) { UBiDiDirection dir = ubidi_getVisualRun(bidi, i, &start, &length); lua_newtable(L); // Convert back to UTF8... int32_t l3 = 0; char* possibleOutbuf = malloc(4*length); if(!possibleOutbuf) { return luaL_error(L, "Couldn't malloc"); } u_strToUTF8(possibleOutbuf, 4 * length, &l3, input_as_uchar+start, length, &err); if (!U_SUCCESS(err)) { free(possibleOutbuf); return luaL_error(L, "Bidi run too big? %s", u_errorName(err)); } lua_pushstring(L, "run"); lua_pushstring(L, possibleOutbuf); free(possibleOutbuf); lua_settable(L, -3); lua_pushstring(L, "start"); int32_t new_start = start; // Length/start is given in terms of UTF16 codepoints. // But we want a count of Unicode characters. This means // surrogate pairs need to be counted as 1. for (int j=0; j< start; j++) { if (U_IS_TRAIL(*(input_as_uchar+j))) new_start--; } lua_pushinteger(L, new_start); lua_settable(L, -3); lua_pushstring(L, "length"); for (int j=start; j< start+length; j++) { if (U_IS_TRAIL(*(input_as_uchar+j))) length--; } lua_pushinteger(L, length); lua_settable(L, -3); lua_pushstring(L, "dir"); lua_pushstring(L, dir == UBIDI_RTL ? "RTL" : "LTR"); lua_settable(L, -3); lua_pushstring(L, "level"); lua_pushinteger(L, ubidi_getLevelAt(bidi, start)); lua_settable(L, -3); } free(input_as_uchar); ubidi_close(bidi); return count; }