Fix what I broke.

This commit is contained in:
Jordan Woyak 2013-03-02 22:57:49 -06:00
parent 88cb11ba0a
commit aeb4fc9846
9 changed files with 108 additions and 151 deletions

View File

@ -17,13 +17,19 @@
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include "Common.h"
#include "CommonPaths.h"
#include "StringUtil.h"
#ifdef _WIN32
#include <Windows.h>
#include <Windows.h>
#elif defined(ANDROID)
#else
#include <iconv.h>
#include <errno.h>
#endif
// faster than sscanf
@ -418,18 +424,80 @@ std::string SHIFTJISToUTF8(const std::string& input)
return UTF16ToUTF8(CPToUTF16(932, input));
}
std::string CP1252ToUTF8(const std::string& input)
{
return UTF16ToUTF8(CPToUTF16(1252, input));
}
#else
std::string UTF16ToUTF8(const std::wstring& input)
template <typename T>
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
{
// TODO: implement
return std::string();
std::string result;
#if defined(ANDROID)
result = "Not implemented on Android!";
#else
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)-1 == conv_desc)
{
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
}
else
{
size_t const in_bytes = sizeof(T) * input.size();
size_t const out_buffer_size = 4 * in_bytes;
std::string out_buffer;
out_buffer.resize(out_buffer_size);
auto src_buffer = &input[0];
size_t src_bytes = in_bytes;
auto dst_buffer = &out_buffer[0];
size_t dst_bytes = out_buffer.size();
size_t const iconv_size = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
&dst_buffer, &dst_bytes);
if ((size_t)-1 == iconv_size)
{
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
}
else
{
out_buffer.resize(out_buffer_size - dst_bytes);
out_buffer.swap(result);
// TODO: why is this needed?
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
}
iconv_close(conv_desc);
}
#endif
return result;
}
std::string CP1252ToUTF8(const std::string& input)
{
return CodeToUTF8("CP1252", input);
}
std::string SHIFTJISToUTF8(const std::string& input)
{
// TODO: implement
return std::string();
//return CodeToUTF8("CP932", input);
return CodeToUTF8("SJIS", input);
}
std::string UTF16ToUTF8(const std::wstring& input)
{
//return CodeToUTF8("UCS-2", input);
//return CodeToUTF8("UCS-2LE", input);
//return CodeToUTF8("UTF-16", input);
return CodeToUTF8("UTF-16LE", input);
}
#endif

View File

@ -97,6 +97,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc);
std::string CP1252ToUTF8(const std::string& str);
std::string SHIFTJISToUTF8(const std::string& str);
std::string UTF16ToUTF8(const std::wstring& str);

View File

@ -33,7 +33,7 @@ IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVo
}
if (_rFileSystem.IsValid())
{
return new CBannerLoaderGC(_rFileSystem);
return new CBannerLoaderGC(_rFileSystem, pVolume);
}
return NULL;

View File

@ -44,12 +44,6 @@ class IBannerLoader
virtual std::vector<std::string> GetNames() = 0;
virtual std::string GetCompany() = 0;
virtual std::vector<std::string> GetDescriptions() = 0;
private:
u16 swap16(u16 data)
{
return ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
}
};
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume);

View File

@ -23,9 +23,10 @@
namespace DiscIO
{
CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem)
: m_pBannerFile(NULL),
m_IsValid(false)
CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume)
: m_pBannerFile(NULL)
, m_IsValid(false)
, m_country(volume->GetCountry())
{
// load the opening.bnr
size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr");
@ -104,7 +105,7 @@ std::vector<std::string> CBannerLoaderGC::GetNames()
auto const banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
for (int i = 0; i != name_count; ++i)
for (u32 i = 0; i != name_count; ++i)
{
auto& comment = banner->comment[i];
@ -167,7 +168,7 @@ std::vector<std::string> CBannerLoaderGC::GetDescriptions()
auto banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
for (int i = 0; i != desc_count; ++i)
for (u32 i = 0; i != desc_count; ++i)
{
auto& data = banner->comment[i].comment;
descriptions.push_back(GetDecodedString(data));

View File

@ -19,6 +19,7 @@
#define _BANNER_LOADER_GC_H_
#include "BannerLoader.h"
#include "StringUtil.h"
namespace DiscIO
{
@ -26,7 +27,7 @@ class CBannerLoaderGC
: public IBannerLoader
{
public:
CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem);
CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume);
virtual ~CBannerLoaderGC();
virtual bool IsValid();
@ -76,8 +77,12 @@ class CBannerLoaderGC
template <u32 N>
std::string GetDecodedString(const char (&data)[N])
{
// Can I always assume SHIFT-JIS?
return SHIFTJISToUTF8(std::string(data, strnlen(data, sizeof(data))));
auto const string_decoder = (DiscIO::IVolume::COUNTRY_JAPAN == m_country ||
DiscIO::IVolume::COUNTRY_TAIWAN == m_country) ?
SHIFTJISToUTF8 : CP1252ToUTF8;
// strnlen to trim NULLs
return string_decoder(std::string(data, strnlen(data, sizeof(data))));
}
u8* m_pBannerFile;
@ -86,6 +91,8 @@ class CBannerLoaderGC
void decode5A3image(u32* dst, u16* src, int width, int height);
BANNER_TYPE getBannerType();
DiscIO::IVolume::ECountry const m_country;
};
} // namespace

View File

@ -25,25 +25,6 @@
#include "FileUtil.h"
#include "FileHandlerARC.h"
// HyperIris: dunno if this suitable, may be need move.
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/param.h>
#ifndef ANDROID
#include <iconv.h>
#endif
#include <errno.h>
#endif
#ifndef ICONV_CONST
#if defined __FreeBSD__ || __NetBSD__
#define ICONV_CONST const
#else
#define ICONV_CONST
#endif
#endif
namespace DiscIO
{
@ -164,35 +145,24 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage)
return true;
}
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s)
{
bool ret = false;
if (IsValid())
{
// find Banner type
SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile;
// TODO: trim NULLs
ret = CopyBeUnicodeToString(s, pBanner->m_Comment[index], COMMENT_SIZE);
}
return ret;
}
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s)
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result)
{
if (IsValid())
{
// find Banner type
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
auto const banner = reinterpret_cast<const SWiiBanner*>(m_pBannerFile);
auto const src_ptr = banner->m_Comment[index];
std::wstring description;
for (int i = 0; i < COMMENT_SIZE; ++i)
description.push_back(Common::swap16(pBanner->m_Comment[index][i]));
// Trim at first NULL
auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr;
std::wstring src;
src.resize(length);
std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16);
result = UTF16ToUTF8(src);
s = description;
return true;
}
return false;
}
@ -237,87 +207,4 @@ void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height)
}
}
bool CBannerLoaderWii::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length )
{
bool returnCode = false;
#ifdef _WIN32
if (_src)
{
std::wstring src;
src.resize(length);
std::transform(_src, _src + length, &src[0], (u16(&)(u16))Common::swap16);
_rDestination = UTF16ToUTF8(src);
returnCode = true;
}
#else
#ifdef ANDROID
return false;
#else
if (_src)
{
iconv_t conv_desc = iconv_open("UTF-8", "CP932");
if (conv_desc == (iconv_t) -1)
{
// Initialization failure.
if (errno == EINVAL)
{
ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported.");
}
else
{
ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno));
}
return false;
}
char* src_buffer = new char[length];
for (int i = 0; i < length; i++)
src_buffer[i] = swap16(_src[i]);
size_t inbytes = sizeof(char) * length;
size_t outbytes = 2 * inbytes;
char* utf8_buffer = new char[outbytes + 1];
memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char));
// Save the buffer locations because iconv increments them
char* utf8_buffer_start = utf8_buffer;
char* src_buffer_start = src_buffer;
size_t iconv_size = iconv(conv_desc,
(ICONV_CONST char**)&src_buffer, &inbytes,
&utf8_buffer, &outbytes);
// Handle failures
if (iconv_size == (size_t) -1)
{
ERROR_LOG(DISCIO, "iconv failed.");
switch (errno) {
case EILSEQ:
ERROR_LOG(DISCIO, "Invalid multibyte sequence.");
break;
case EINVAL:
ERROR_LOG(DISCIO, "Incomplete multibyte sequence.");
break;
case E2BIG:
ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer.");
break;
default:
ERROR_LOG(DISCIO, "Error: %s.", strerror(errno));
}
}
else
{
_rDestination = utf8_buffer_start;
returnCode = true;
}
delete[] utf8_buffer_start;
delete[] src_buffer_start;
iconv_close(conv_desc);
}
#endif
#endif
return returnCode;
}
} // namespace

View File

@ -75,9 +75,6 @@ class CBannerLoaderWii
void decode5A3image(u32* dst, u16* src, int width, int height);
bool GetStringFromComments(const CommentIndex index, std::string& s);
bool GetStringFromComments(const CommentIndex index, std::wstring& s);
bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length);
};
} // namespace

View File

@ -22,6 +22,7 @@
#include <vector>
#include "Common.h"
#include "StringUtil.h"
namespace DiscIO
{
@ -37,6 +38,7 @@ public:
virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; }
virtual std::string GetUniqueID() const = 0;
virtual std::string GetMakerID() const = 0;
// TODO: eliminate?
virtual std::string GetName() const;
virtual std::vector<std::string> GetNames() const = 0;
virtual u32 GetFSTSize() const = 0;