FEX: Make fex crap properly convert filenames from 7z archives to utf8 under Linux

This commit is contained in:
bgk 2011-02-24 10:52:01 +00:00
parent a59c64a292
commit 750a57a4a7
2 changed files with 76 additions and 5 deletions

View File

@ -201,6 +201,74 @@ void Zip7_Extractor::close_v()
} }
} }
// This method was taken from ogre-7z (thanks), and is thus LGPL
bool Zip7_Extractor::utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen )
{
static const unsigned char sUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
size_t destPos = 0, srcPos = 0;
for(;;)
{
unsigned int numAdds;
unsigned long value;
if( srcPos == srcLen )
{
*destLen = destPos;
return true;
}
value = src[srcPos++];
if( value < 0x80 )
{
if( dest )
{
dest[destPos] = (char)value;
}
destPos++;
continue;
}
if( value >= 0xD800 && value < 0xE000 )
{
unsigned long c2;
if( value >= 0xDC00 || srcPos == srcLen )
break;
c2 = src[srcPos++];
if( c2 < 0xDC00 || c2 >= 0xE000 )
break;
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
}
for( numAdds = 1; numAdds < 5; numAdds++ )
{
if( value < (((UInt32)1) << (numAdds * 5 + 6)) )
break;
}
if( dest )
{
dest[destPos] = (char)(sUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
}
destPos++;
do
{
numAdds--;
if( dest )
{
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
}
destPos++;
}
while( numAdds != 0 );
}
*destLen = destPos;
return false;
}
blargg_err_t Zip7_Extractor::next_v() blargg_err_t Zip7_Extractor::next_v()
{ {
while ( ++index < (int) impl->db.db.NumFiles ) while ( ++index < (int) impl->db.db.NumFiles )
@ -226,7 +294,7 @@ blargg_err_t Zip7_Extractor::next_v()
localtime_r( &_time, &tm ); localtime_r( &_time, &tm );
#endif #endif
date = ( tm.tm_sec >> 1 ) & 0x1F | date = (( tm.tm_sec >> 1 ) & 0x1F) |
(( tm.tm_min & 0x3F ) << 5 ) | (( tm.tm_min & 0x3F ) << 5 ) |
(( tm.tm_hour & 0x1F ) << 11 ) | (( tm.tm_hour & 0x1F ) << 11 ) |
(( tm.tm_mday & 0x1F ) << 16 ) | (( tm.tm_mday & 0x1F ) << 16 ) |
@ -235,14 +303,15 @@ blargg_err_t Zip7_Extractor::next_v()
} }
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 ); size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
size_t utf8_length = 0;
name16.resize( name_length ); name16.resize( name_length );
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() ); SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
char * temp = blargg_to_utf8( name16.begin() ); unsigned char temp[1024];
if ( !temp ) temp = ""; utf16ToUtf8( temp, &utf8_length, (const short*)name16.begin(), name_length - 1 );
size_t utf8_length = strlen( temp ); temp[utf8_length] = '\0';
name8.resize( utf8_length + 1 ); name8.resize( utf8_length + 1 );
memcpy( name8.begin(), temp, utf8_length + 1 ); memcpy( name8.begin(), temp, utf8_length + 1 );
free( temp );
set_name( name8.begin(), name16.begin() ); set_name( name8.begin(), name16.begin() );
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) ); set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
break; break;

View File

@ -24,6 +24,8 @@ protected:
virtual blargg_err_t data_v( void const** out ); virtual blargg_err_t data_v( void const** out );
bool utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen );
private: private:
Zip7_Extractor_Impl* impl; Zip7_Extractor_Impl* impl;
int index; int index;