/*
 * Class:     fr_umlv_unitex_jni_UnitexJni
 * Method:    getUnitexFileData
 * Signature: (Ljava/lang/String;)[B
 */
JNIEXPORT jbyteArray JNICALL Java_fr_umlv_unitex_jni_UnitexJni_getUnitexFileData
  (JNIEnv *env, jclass, jstring filename)
{
	jstringToCUtf jstc_filename;
	jstc_filename.initJString(env,filename);

    UNITEXFILEMAPPED *amf;
    const void*buffer;
    size_t size_file;
	GetUnitexFileReadBuffer(jstc_filename.getJString(),&amf, &buffer,&size_file);
	jbyteArray jarrRet=env->NewByteArray((jsize)size_file);
	if (jarrRet != NULL)
		env->SetByteArrayRegion(jarrRet,0,(jsize)size_file,(const jbyte*)buffer);
    CloseUnitexFileReadBuffer(amf, buffer, size_file);
    return jarrRet;
}
/*
 * Class:     fr_umlv_unitex_jni_UnitexJni
 * Method:    getUnitexFileString
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_fr_umlv_unitex_jni_UnitexJni_getUnitexFileString
  (JNIEnv *env, jclass, jstring filename)
{
	jstringToCUtf jstc_filename;
	jstc_filename.initJString(env,filename);
	jstring jstrRet=NULL;

    UNITEXFILEMAPPED *amf;
    const void*buffer;
    size_t size_file;
	GetUnitexFileReadBuffer(jstc_filename.getJString(),&amf, &buffer,&size_file);
	const unsigned char* bufchar=(const unsigned char*)buffer;
	size_t size_bom=0;
	bool is_utf16_native_endianess=false;
	bool is_utf16_swap_endianess = false;

    if (size_file>1)
        if (((*(bufchar))==0xff) && ((*(bufchar+1))==0xfe))
        {
			// little endian
			is_utf16_native_endianess = is_little_endian();
            is_utf16_swap_endianess = ! is_utf16_native_endianess;
            size_bom = 2;
        }
    
    if (size_file>1)
        if (((*(bufchar))==0xfe) && ((*(bufchar+1))==0xff))
        {
			// big endian
			is_utf16_native_endianess = ! is_little_endian();
            is_utf16_swap_endianess = ! is_utf16_native_endianess;
            size_bom = 2;
        }
    
    if (size_file>2)
        if (((*(bufchar))==0xef) && ((*(bufchar+1))==0xbb) && ((*(bufchar+2))==0xbf))
        {
            size_bom = 3;
        }

	if (is_utf16_native_endianess)
	{
		jstrRet = env->NewString((const jchar*)(bufchar+size_bom), (jsize)((size_file - size_bom) / sizeof(jchar)));
	}
	else
    if (is_utf16_swap_endianess)
	{
		unsigned char* returnedUTF16buffer = (unsigned char*)malloc(size_file);
		if (returnedUTF16buffer != NULL)
		{
			for (size_t i=0;i<size_file;i+=2)
			{
				unsigned char c1 = *(bufchar+i);
				unsigned char c2 = *(bufchar+i+1);
				*(returnedUTF16buffer+i) = c2;
				*(returnedUTF16buffer+i+1) = c1;
			}
			jstrRet = env->NewString((const jchar*)(returnedUTF16buffer+size_bom), (jsize)((size_file - size_bom) / sizeof(jchar)));
			free(returnedUTF16buffer);
		}
	}
	else
	{
		char* stringUtf = (char*)malloc(size_file+1);
		memcpy(stringUtf,bufchar+size_bom,size_file-size_bom);
		*(stringUtf+size_file-size_bom)='\0';
		jstrRet = env->NewStringUTF(stringUtf);
		free(stringUtf);
	}

    CloseUnitexFileReadBuffer(amf, buffer, size_file);
    return jstrRet;
}
    /// <summary>
    /// Gets the whole contents of a (virtual) file into a Unicode string.
    /// </summary>
    /// <param name='fileName'>The file name.</param>
    /// <param name='uString'>The Unicode string where to store the file contents.</param>
    /// <returns>1 if ok, 0 if failed.</returns>
    UNITEX_FUNC int UNITEX_CALL GetUnicodeStringFromUnitexFile(const char* filename, UnicodeString& uString)
    {
        uString.remove();

        UNITEXFILEMAPPED* pFileHandle;
        const void* buffer = NULL;
        size_t bufferSize = 0;
        GetUnitexFileReadBuffer(filename, &pFileHandle, &buffer, &bufferSize);

        if (pFileHandle != NULL) {
            if (bufferSize > 0) {
                const unsigned char* bufchar= (const unsigned char*) buffer;
                size_t size_bom = 0;
                bool is_utf16_native_endianess = false;
                bool is_utf16_swap_endianess = false;

                if (bufferSize > 1) {
                    UChar UTF16Bom = *((const UChar*)buffer);

                    if (UTF16Bom == 0xfeff)
                    {
                        // native endian
                        is_utf16_native_endianess = true;
                        size_bom = 2;
                    }

                    if (UTF16Bom == 0xfffe)
                    {
                        // reverse endian
                        is_utf16_swap_endianess = true;
                        size_bom = 2;
                    }
                }


                if (bufferSize > 2) {
                    if (((*(bufchar)) == 0xef) && ((*(bufchar + 1)) == 0xbb) && ((*(bufchar + 2)) == 0xbf))
                    {
                        size_bom = 3;
                    }
                }

                if (is_utf16_native_endianess)
                {
                    const UChar* uBuffer = (const UChar*)(bufchar + size_bom);
                    size_t uSize = (bufferSize - size_bom) / U_SIZEOF_UCHAR;
                    uString.setTo(uBuffer, uSize);
                }
                else if (is_utf16_swap_endianess)
                {
                    unsigned char* returnedUTF16buffer = new unsigned char [bufferSize];
                    if (returnedUTF16buffer != NULL)
                    {
                        for (size_t i = 0; i<bufferSize; i += 2)
                        {
                            unsigned char c1 = *(bufchar + i);
                            unsigned char c2 = *(bufchar + i + 1);
                            *(returnedUTF16buffer + i) = c2;
                            *(returnedUTF16buffer + i + 1) = c1;
                        }
                        const UChar* uBuffer = (const UChar*)(returnedUTF16buffer + size_bom);
                        size_t uSize = (bufferSize - size_bom) / U_SIZEOF_UCHAR;
                        uString.setTo(uBuffer, uSize);
                        delete [] returnedUTF16buffer;
                    }
                }
                else
                {
                    size_t len_buf_UChar = bufferSize+1+1;
                    UChar* stringUChar = new UChar[len_buf_UChar + 1];


                    size_t nb_written = 0;
                    unpack_utf8_string(stringUChar,len_buf_UChar,&nb_written,bufchar + size_bom, bufferSize - size_bom);


                    uString.setTo((const UChar*)stringUChar, nb_written);
                    delete [] stringUChar;
                }
            }
            CloseUnitexFileReadBuffer(pFileHandle, buffer, bufferSize);
            return 1;
        }

        return 0;
    }