/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed 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.
 */

#define LOG_TAG "NativeDecimalFormat"

#include "JNIHelp.h"
#include "cutils/log.h"
#include "unicode/unum.h"
#include "unicode/numfmt.h"
#include "unicode/decimfmt.h"
#include "unicode/fmtable.h"
#include "unicode/ustring.h"
#include "digitlst.h"
#include "ErrorCode.h"
#include "ScopedJavaUnicodeString.h"
#include <stdlib.h>
#include <string.h>

static DecimalFormat* toDecimalFormat(jint addr) {
    return reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
}

static DecimalFormatSymbols* makeDecimalFormatSymbols(JNIEnv* env,
        jstring currencySymbol0, jchar decimalSeparator, jchar digit,
        jchar groupingSeparator0, jstring infinity0,
        jstring internationalCurrencySymbol0, jchar minusSign,
        jchar monetaryDecimalSeparator, jstring nan0, jchar patternSeparator,
        jchar percent, jchar perMill, jchar zeroDigit) {
    ScopedJavaUnicodeString currencySymbol(env, currencySymbol0);
    ScopedJavaUnicodeString infinity(env, infinity0);
    ScopedJavaUnicodeString internationalCurrencySymbol(env, internationalCurrencySymbol0);
    ScopedJavaUnicodeString nan(env, nan0);
    UnicodeString groupingSeparator(groupingSeparator0);

    DecimalFormatSymbols* result = new DecimalFormatSymbols;
    result->setSymbol(DecimalFormatSymbols::kCurrencySymbol, currencySymbol.unicodeString());
    result->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString(decimalSeparator));
    result->setSymbol(DecimalFormatSymbols::kDigitSymbol, UnicodeString(digit));
    result->setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, groupingSeparator);
    result->setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, groupingSeparator);
    result->setSymbol(DecimalFormatSymbols::kInfinitySymbol, infinity.unicodeString());
    result->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, internationalCurrencySymbol.unicodeString());
    result->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, UnicodeString(minusSign));
    result->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString(monetaryDecimalSeparator));
    result->setSymbol(DecimalFormatSymbols::kNaNSymbol, nan.unicodeString());
    result->setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, UnicodeString(patternSeparator));
    result->setSymbol(DecimalFormatSymbols::kPercentSymbol, UnicodeString(percent));
    result->setSymbol(DecimalFormatSymbols::kPerMillSymbol, UnicodeString(perMill));
    result->setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, UnicodeString(zeroDigit));
    return result;
}

static void setDecimalFormatSymbols(JNIEnv* env, jclass, jint addr,
        jstring currencySymbol, jchar decimalSeparator, jchar digit,
        jchar groupingSeparator, jstring infinity,
        jstring internationalCurrencySymbol, jchar minusSign,
        jchar monetaryDecimalSeparator, jstring nan, jchar patternSeparator,
        jchar percent, jchar perMill, jchar zeroDigit) {
    DecimalFormatSymbols* symbols = makeDecimalFormatSymbols(env,
            currencySymbol, decimalSeparator, digit, groupingSeparator,
            infinity, internationalCurrencySymbol, minusSign,
            monetaryDecimalSeparator, nan, patternSeparator, percent, perMill,
            zeroDigit);
    toDecimalFormat(addr)->adoptDecimalFormatSymbols(symbols);
}

static jint openDecimalFormatImpl(JNIEnv* env, jclass, jstring pattern0,
        jstring currencySymbol, jchar decimalSeparator, jchar digit,
        jchar groupingSeparator, jstring infinity,
        jstring internationalCurrencySymbol, jchar minusSign,
        jchar monetaryDecimalSeparator, jstring nan, jchar patternSeparator,
        jchar percent, jchar perMill, jchar zeroDigit) {
    if (pattern0 == NULL) {
        jniThrowNullPointerException(env, NULL);
        return 0;
    }
    UErrorCode status = U_ZERO_ERROR;
    UParseError parseError;
    ScopedJavaUnicodeString pattern(env, pattern0);
    DecimalFormatSymbols* symbols = makeDecimalFormatSymbols(env,
            currencySymbol, decimalSeparator, digit, groupingSeparator,
            infinity, internationalCurrencySymbol, minusSign,
            monetaryDecimalSeparator, nan, patternSeparator, percent, perMill,
            zeroDigit);
    DecimalFormat* fmt = new DecimalFormat(pattern.unicodeString(), symbols, parseError, status);
    if (fmt == NULL) {
        delete symbols;
    }
    icu4jni_error(env, status);
    return static_cast<jint>(reinterpret_cast<uintptr_t>(fmt));
}

static void closeDecimalFormatImpl(JNIEnv*, jclass, jint addr) {
    delete toDecimalFormat(addr);
}

static void setRoundingMode(JNIEnv*, jclass, jint addr, jint mode, jdouble increment) {
    DecimalFormat* fmt = toDecimalFormat(addr);
    fmt->setRoundingMode(static_cast<DecimalFormat::ERoundingMode>(mode));
    fmt->setRoundingIncrement(increment);
}

static void setSymbol(JNIEnv* env, jclass, jint addr, jint symbol, jstring s) {
    const UChar* chars = env->GetStringChars(s, NULL);
    const int32_t charCount = env->GetStringLength(s);
    UErrorCode status = U_ZERO_ERROR;
    UNumberFormat* fmt = reinterpret_cast<UNumberFormat*>(static_cast<uintptr_t>(addr));
    unum_setSymbol(fmt, static_cast<UNumberFormatSymbol>(symbol), chars, charCount, &status);
    icu4jni_error(env, status);
    env->ReleaseStringChars(s, chars);
}

static void setAttribute(JNIEnv*, jclass, jint addr, jint symbol,
        jint value) {

    UNumberFormat *fmt = (UNumberFormat *)(int)addr;

    unum_setAttribute(fmt, (UNumberFormatAttribute) symbol, value);
}

static jint getAttribute(JNIEnv*, jclass, jint addr, jint symbol) {

    UNumberFormat *fmt = (UNumberFormat *)(int)addr;

    int res = unum_getAttribute(fmt, (UNumberFormatAttribute) symbol);

    return res;
}

static void setTextAttribute(JNIEnv* env, jclass, jint addr, jint symbol,
        jstring text) {

    // the errorcode returned by unum_setTextAttribute
    UErrorCode status = U_ZERO_ERROR;

    // get the pointer to the number format
    UNumberFormat *fmt = (UNumberFormat *)(int)addr;

    const UChar *textChars = env->GetStringChars(text, NULL);
    int textLen = env->GetStringLength(text);

    unum_setTextAttribute(fmt, (UNumberFormatTextAttribute) symbol, textChars,
            textLen, &status);

    env->ReleaseStringChars(text, textChars);

    icu4jni_error(env, status);
}

static jstring getTextAttribute(JNIEnv* env, jclass, jint addr,
        jint symbol) {

    uint32_t resultlength, reslenneeded;

    // the errorcode returned by unum_getTextAttribute
    UErrorCode status = U_ZERO_ERROR;

    // get the pointer to the number format
    UNumberFormat *fmt = (UNumberFormat *)(int)addr;

    UChar* result = NULL;
    resultlength=0;

    // find out how long the result will be
    reslenneeded=unum_getTextAttribute(fmt, (UNumberFormatTextAttribute) symbol,
            result, resultlength, &status);

    result = NULL;
    if(status==U_BUFFER_OVERFLOW_ERROR) {
        status=U_ZERO_ERROR;
        resultlength=reslenneeded+1;
        result=(UChar*)malloc(sizeof(UChar) * resultlength);
        reslenneeded=unum_getTextAttribute(fmt,
                (UNumberFormatTextAttribute) symbol, result, resultlength,
                &status);
    }
    if (icu4jni_error(env, status) != FALSE) {
        return NULL;
    }

    jstring res = env->NewString(result, reslenneeded);

    free(result);

    return res;
}

static void applyPatternImpl(JNIEnv* env, jclass, jint addr, jboolean localized, jstring pattern0) {
    if (pattern0 == NULL) {
        jniThrowNullPointerException(env, NULL);
        return;
    }
    ScopedJavaUnicodeString pattern(env, pattern0);
    DecimalFormat* fmt = toDecimalFormat(addr);
    UErrorCode status = U_ZERO_ERROR;
    if (localized) {
        fmt->applyLocalizedPattern(pattern.unicodeString(), status);
    } else {
        fmt->applyPattern(pattern.unicodeString(), status);
    }
    icu4jni_error(env, status);
}

static jstring toPatternImpl(JNIEnv* env, jclass, jint addr, jboolean localized) {
    DecimalFormat* fmt = toDecimalFormat(addr);
    UnicodeString pattern;
    if (localized) {
        fmt->toLocalizedPattern(pattern);
    } else {
        fmt->toPattern(pattern);
    }
    return env->NewString(pattern.getBuffer(), pattern.length());
}

template <typename T>
static jstring format(JNIEnv* env, jint addr, jobject field, jstring fieldType, jobject attributes, T val) {
    DecimalFormat::AttributeBuffer attrBuffer;
    attrBuffer.buffer = NULL;
    DecimalFormat::AttributeBuffer* attrBufferPtr = NULL;
    if (attributes != NULL || (fieldType != NULL && field != NULL)) {
        attrBufferPtr = &attrBuffer;
        // ICU requires that this is dynamically allocated and non-zero size.
        // ICU grows it in chunks of 128 bytes, so that's a reasonable initial size.
        attrBuffer.bufferSize = 128;
        attrBuffer.buffer = new char[attrBuffer.bufferSize];
        attrBuffer.buffer[0] = '\0';
    }

    FieldPosition fp;
    fp.setField(FieldPosition::DONT_CARE);

    UnicodeString str;
    DecimalFormat* fmt = toDecimalFormat(addr);
    fmt->format(val, str, fp, attrBufferPtr);

    if (attrBufferPtr && strlen(attrBuffer.buffer) > 0) {
        // check if we want to get all attributes
        if (attributes != NULL) {
            jstring attrString = env->NewStringUTF(attrBuffer.buffer + 1);  // cut off the leading ';'
            jclass stringBufferClass = env->FindClass("java/lang/StringBuffer");
            jmethodID appendMethodID = env->GetMethodID(stringBufferClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
            env->CallObjectMethod(attributes, appendMethodID, attrString);
        }

        // check if we want one special attribute returned in the given FieldPos
        if (fieldType != NULL && field != NULL) {
            const char* fieldName = env->GetStringUTFChars(fieldType, NULL);

            const char* delimiter = ";";
            char* context = NULL;
            char* resattr = strtok_r(attrBuffer.buffer, delimiter, &context);

            while (resattr != NULL && strcmp(resattr, fieldName) != 0) {
                resattr = strtok_r(NULL, delimiter, &context);
            }

            if (resattr != NULL && strcmp(resattr, fieldName) == 0) {
                resattr = strtok_r(NULL, delimiter, &context);
                int begin = (int) strtol(resattr, NULL, 10);
                resattr = strtok_r(NULL, delimiter, &context);
                int end = (int) strtol(resattr, NULL, 10);

                jclass fieldPositionClass = env->FindClass("java/text/FieldPosition");
                jmethodID setBeginIndexMethodID = env->GetMethodID(fieldPositionClass, "setBeginIndex", "(I)V");
                jmethodID setEndIndexMethodID = env->GetMethodID(fieldPositionClass, "setEndIndex", "(I)V");
                env->CallVoidMethod(field, setBeginIndexMethodID, (jint) begin);
                env->CallVoidMethod(field, setEndIndexMethodID, (jint) end);
            }
            env->ReleaseStringUTFChars(fieldType, fieldName);
        }
    }

    jstring result = env->NewString(str.getBuffer(), str.length());
    delete[] attrBuffer.buffer;
    return result;
}

static jstring formatLong(JNIEnv* env, jclass, jint addr, jlong value,
        jobject field, jstring fieldType, jobject attributes) {
    int64_t longValue = value;
    return format(env, addr, field, fieldType, attributes, longValue);
}

static jstring formatDouble(JNIEnv* env, jclass, jint addr, jdouble value,
        jobject field, jstring fieldType, jobject attributes) {
    double doubleValue = value;
    return format(env, addr, field, fieldType, attributes, doubleValue);
}

static jstring formatDigitList(JNIEnv* env, jclass, jint addr, jstring value,
        jobject field, jstring fieldType, jobject attributes, jint scale) {

    // const char * valueUTF = env->GetStringUTFChars(value, NULL);
    // LOGI("ENTER formatDigitList: %s, scale: %d", valueUTF, scale);
    // env->ReleaseStringUTFChars(value, valueUTF);

    if (scale < 0) {
        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
        return NULL;
    }

    const char * fieldName = NULL;
    if(fieldType != NULL) {
        fieldName = env->GetStringUTFChars(fieldType, NULL);
    }

    uint32_t reslenneeded;

    // prepare digit list

    const char *valueChars = env->GetStringUTFChars(value, NULL);

    bool isInteger = (scale == 0);
    bool isPositive = (*valueChars != '-');

    // skip the '-' if the number is negative
    const char *digits = (isPositive ? valueChars : valueChars + 1);
    int length = strlen(digits);

    DecimalFormat* fmt = toDecimalFormat(addr);

    // The length of our digit list buffer must be the actual string length + 3,
    // because ICU will append some additional characters at the head and at the
    // tail of the string, in order to keep strtod() happy:
    //
    // - The sign "+" or "-" is appended at the head
    // - The exponent "e" and the "\0" terminator is appended at the tail
    //
    // In retrospect, the changes to ICU's DigitList that were necessary for
    // big numbers look a bit hacky. It would make sense to rework all this
    // once ICU 4.x has been integrated into Android. Ideally, big number
    // support would make it into ICU itself, so we don't need our private
    // fix anymore.
    DigitList digitList(length + 3);
    digitList.fCount = length;
    strcpy(digitList.fDigits, digits);
    env->ReleaseStringUTFChars(value, valueChars);

    digitList.fDecimalAt = digitList.fCount - scale;
    digitList.fIsPositive = isPositive;
    digitList.fRoundingMode = fmt->getRoundingMode();
    digitList.round(fmt->getMaximumFractionDigits() + digitList.fDecimalAt);

    UChar *result = NULL;

    FieldPosition fp;
    fp.setField(FieldPosition::DONT_CARE);
    fp.setBeginIndex(0);
    fp.setEndIndex(0);

    UErrorCode status = U_ZERO_ERROR;

    DecimalFormat::AttributeBuffer *attrBuffer = NULL;
    attrBuffer = (DecimalFormat::AttributeBuffer *) calloc(sizeof(DecimalFormat::AttributeBuffer), 1);
    attrBuffer->bufferSize = 128;
    attrBuffer->buffer = (char *) calloc(129 * sizeof(char), 1);

    UnicodeString res;

    fmt->subformat(res, fp, attrBuffer, digitList, isInteger);

    reslenneeded = res.extract(NULL, 0, status);

    if(status==U_BUFFER_OVERFLOW_ERROR) {
        status=U_ZERO_ERROR;

        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));

        res.extract(result, reslenneeded + 1, status);

        if (icu4jni_error(env, status) != FALSE) {
            if(fieldType != NULL) {
                env->ReleaseStringUTFChars(fieldType, fieldName);
            }
            free(result);
            free(attrBuffer->buffer);
            free(attrBuffer);
            return NULL;
        }

    } else {
        if(fieldType != NULL) {
            env->ReleaseStringUTFChars(fieldType, fieldName);
        }
        free(attrBuffer->buffer);
        free(attrBuffer);
        return NULL;
    }

    int attrLength = (strlen(attrBuffer->buffer) + 1 );

    if(attrLength > 1) {

        // check if we want to get all attributes
        if(attributes != NULL) {
            // prepare the classes and method ids
            const char * stringBufferClassName = "java/lang/StringBuffer";
            jclass stringBufferClass = env->FindClass(stringBufferClassName);
            jmethodID appendMethodID = env->GetMethodID(stringBufferClass,
                    "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");

            jstring attrString = env->NewStringUTF(attrBuffer->buffer + 1);  // cut off the leading ';'
            env->CallObjectMethod(attributes, appendMethodID, attrString);
        }

        // check if we want one special attribute returned in the given FieldPos
        if(fieldName != NULL && field != NULL) {
            const char *delimiter = ";";
            int begin;
            int end;
            char * resattr;
            resattr = strtok(attrBuffer->buffer, delimiter);

            while(resattr != NULL && strcmp(resattr, fieldName) != 0) {
                resattr = strtok(NULL, delimiter);
            }

            if(resattr != NULL && strcmp(resattr, fieldName) == 0) {

                // prepare the classes and method ids
                const char * fieldPositionClassName =
                        "java/text/FieldPosition";
                jclass fieldPositionClass = env->FindClass(
                        fieldPositionClassName);
                jmethodID setBeginIndexMethodID = env->GetMethodID(
                        fieldPositionClass, "setBeginIndex", "(I)V");
                jmethodID setEndIndexMethodID = env->GetMethodID(
                       fieldPositionClass, "setEndIndex", "(I)V");


                resattr = strtok(NULL, delimiter);
                begin = (int) strtol(resattr, NULL, 10);
                resattr = strtok(NULL, delimiter);
                end = (int) strtol(resattr, NULL, 10);

                env->CallVoidMethod(field, setBeginIndexMethodID, (jint) begin);
                env->CallVoidMethod(field, setEndIndexMethodID, (jint) end);
            }
        }
    }

    if(fieldType != NULL) {
        env->ReleaseStringUTFChars(fieldType, fieldName);
    }

    jstring resulting = env->NewString(result, reslenneeded);

    free(attrBuffer->buffer);
    free(attrBuffer);
    free(result);
    // const char * resultUTF = env->GetStringUTFChars(resulting, NULL);
    // LOGI("RETURN formatDigitList: %s", resultUTF);
    // env->ReleaseStringUTFChars(resulting, resultUTF);

    return resulting;
}

static jobject parse(JNIEnv* env, jclass, jint addr, jstring text,
        jobject position) {
    // TODO: cache these?
    jclass parsePositionClass = env->FindClass("java/text/ParsePosition");
    jclass longClass =  env->FindClass("java/lang/Long");
    jclass doubleClass =  env->FindClass("java/lang/Double");
    jclass bigDecimalClass = env->FindClass("java/math/BigDecimal");
    jclass bigIntegerClass = env->FindClass("java/math/BigInteger");

    jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass,
            "getIndex", "()I");
    jmethodID setIndexMethodID = env->GetMethodID(parsePositionClass,
            "setIndex", "(I)V");
    jmethodID setErrorIndexMethodID = env->GetMethodID(parsePositionClass,
            "setErrorIndex", "(I)V");

    jmethodID longInitMethodID = env->GetMethodID(longClass, "<init>", "(J)V");
    jmethodID dblInitMethodID = env->GetMethodID(doubleClass, "<init>", "(D)V");
    jmethodID bigDecimalInitMethodID = env->GetMethodID(bigDecimalClass, "<init>", "(Ljava/math/BigInteger;I)V");
    jmethodID bigIntegerInitMethodID = env->GetMethodID(bigIntegerClass, "<init>", "(Ljava/lang/String;)V");

    // make sure the ParsePosition is valid. Actually icu4c would parse a number
    // correctly even if the parsePosition is set to -1, but since the RI fails
    // for that case we have to fail too
    int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
    const int strlength = env->GetStringLength(text);
    if(parsePos < 0 || parsePos > strlength) {
        return NULL;
    }
    
    ParsePosition pp;
    pp.setIndex(parsePos);

    DigitList digits;
    
    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
    Formattable res;
    bool resultAssigned;
    jchar *str = (UChar *)env->GetStringChars(text, NULL);
    const UnicodeString src((UChar*)str, strlength, strlength);
    ((const DecimalFormat*)fmt)->parse(src, resultAssigned, res, pp, FALSE, digits);
    env->ReleaseStringChars(text, str);

    if(pp.getErrorIndex() == -1) {
        parsePos = pp.getIndex();
    } else {
        env->CallVoidMethod(position, setErrorIndexMethodID,
                (jint) pp.getErrorIndex());
        return NULL;
    }

    Formattable::Type numType = res.getType();

    double resultDouble;
    long resultLong;
    int64_t resultInt64;
    jstring resultStr;
    jobject resultObject1, resultObject2;

    if (resultAssigned)
    {
        switch(numType) {
        case Formattable::kDouble:
            resultDouble = res.getDouble();
            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
            return env->NewObject(doubleClass, dblInitMethodID,
                    (jdouble) resultDouble);
        case Formattable::kLong:
            resultLong = res.getLong();
            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
            return env->NewObject(longClass, longInitMethodID,
                    (jlong) resultLong);
        case Formattable::kInt64:
            resultInt64 = res.getInt64();
            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
            return env->NewObject(longClass, longInitMethodID,
                    (jlong) resultInt64);
        default:
            return NULL;
        }
    }
    else
    {
        int scale = digits.fCount - digits.fDecimalAt;
        // ATTENTION: Abuse of Implementation Knowlegde!
        digits.fDigits[digits.fCount] = 0;
        if (digits.fIsPositive) {
            resultStr = env->NewStringUTF(digits.fDigits);
        } else {
            if (digits.fCount == 0) {
                env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
                return env->NewObject(doubleClass, dblInitMethodID, (jdouble)-0);
            } else {
                // ATTENTION: Abuse of Implementation Knowlegde!
                *(digits.fDigits - 1) = '-';
                resultStr = env->NewStringUTF(digits.fDigits - 1);
            }
        }

        env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);

        resultObject1 = env->NewObject(bigIntegerClass, bigIntegerInitMethodID, resultStr);
        resultObject2 = env->NewObject(bigDecimalClass, bigDecimalInitMethodID, resultObject1, scale);
        return resultObject2;
    }
}

static jint cloneDecimalFormatImpl(JNIEnv*, jclass, jint addr) {
    DecimalFormat* fmt = toDecimalFormat(addr);
    return static_cast<jint>(reinterpret_cast<uintptr_t>(fmt->clone()));
}

static JNINativeMethod gMethods[] = {
    {"applyPatternImpl", "(IZLjava/lang/String;)V", (void*) applyPatternImpl},
    {"cloneDecimalFormatImpl", "(I)I", (void*) cloneDecimalFormatImpl},
    {"closeDecimalFormatImpl", "(I)V", (void*) closeDecimalFormatImpl},
    {"format", "(IDLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;", (void*) formatDouble},
    {"format", "(IJLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;", (void*) formatLong},
    {"format", "(ILjava/lang/String;Ljava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;I)Ljava/lang/String;", (void*) formatDigitList},
    {"getAttribute", "(II)I", (void*) getAttribute},
    {"getTextAttribute", "(II)Ljava/lang/String;", (void*) getTextAttribute},
    {"openDecimalFormatImpl", "(Ljava/lang/String;Ljava/lang/String;CCCLjava/lang/String;Ljava/lang/String;CCLjava/lang/String;CCCC)I", (void*) openDecimalFormatImpl},
    {"parse", "(ILjava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Number;", (void*) parse},
    {"setAttribute", "(III)V", (void*) setAttribute},
    {"setDecimalFormatSymbols", "(ILjava/lang/String;CCCLjava/lang/String;Ljava/lang/String;CCLjava/lang/String;CCCC)V", (void*) setDecimalFormatSymbols},
    {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol},
    {"setRoundingMode", "(IID)V", (void*) setRoundingMode},
    {"setTextAttribute", "(IILjava/lang/String;)V", (void*) setTextAttribute},
    {"toPatternImpl", "(IZ)Ljava/lang/String;", (void*) toPatternImpl},
};
int register_com_ibm_icu4jni_text_NativeDecimalFormat(JNIEnv* env) {
    return jniRegisterNativeMethods(env, "com/ibm/icu4jni/text/NativeDecimalFormat", gMethods,
            NELEM(gMethods));
}
