|
|
|
@ -9,7 +9,10 @@
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <iconv.h>
|
|
|
|
|
|
|
|
|
|
#ifndef __WIN32__
|
|
|
|
|
#include <iconv.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <libs/mangle/stream/stream.hpp>
|
|
|
|
|
#include <libs/mangle/stream/servers/file_stream.hpp>
|
|
|
|
@ -618,89 +621,93 @@ public:
|
|
|
|
|
return convertToUTF8(res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert a string from the encoding used by Morrowind to UTF-8
|
|
|
|
|
std::string convertToUTF8(std::string input)
|
|
|
|
|
{
|
|
|
|
|
std::string output = "";
|
|
|
|
|
|
|
|
|
|
//create convert description
|
|
|
|
|
iconv_t cd = iconv_open("UTF-8", "WINDOWS-1252");
|
|
|
|
|
|
|
|
|
|
if (cd == (iconv_t)-1) //error handling
|
|
|
|
|
{
|
|
|
|
|
std::string errMsg = "Creating description for UTF-8 converting failed: ";
|
|
|
|
|
|
|
|
|
|
switch (errno) //detailed error messages (maybe it contains too much detail :)
|
|
|
|
|
{
|
|
|
|
|
case EMFILE:
|
|
|
|
|
errMsg += "{OPEN_MAX} files descriptors are currently open in the calling process.";
|
|
|
|
|
case ENFILE:
|
|
|
|
|
errMsg += "Too many files are currently open in the system.";
|
|
|
|
|
case ENOMEM:
|
|
|
|
|
errMsg +="Insufficient storage space is available.";
|
|
|
|
|
case EINVAL:
|
|
|
|
|
errMsg += "The conversion specified by fromcode and tocode is not supported by the implementation.";
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
errMsg += "Unknown Error\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fail(errMsg);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
// Convert a string from the encoding used by Morrowind to UTF-8
|
|
|
|
|
std::string convertToUTF8 (std::string input)
|
|
|
|
|
{
|
|
|
|
|
const size_t inputSize = input.size();
|
|
|
|
|
#ifdef __WIN32__
|
|
|
|
|
return input;
|
|
|
|
|
#else
|
|
|
|
|
std::string output = "";
|
|
|
|
|
|
|
|
|
|
if (inputSize) //input is not empty
|
|
|
|
|
{
|
|
|
|
|
//convert function doesn't accept const char *, therefore copy content into an char *
|
|
|
|
|
std::vector<char> inputBuffer(input.begin(), input.end());
|
|
|
|
|
char *inputBufferBegin = &inputBuffer[0];
|
|
|
|
|
//create convert description
|
|
|
|
|
iconv_t cd = iconv_open ("UTF-8", "WINDOWS-1252");
|
|
|
|
|
|
|
|
|
|
size_t inputBytesLeft = inputSize; //bytes to convert
|
|
|
|
|
if (cd == (iconv_t)-1) //error handling
|
|
|
|
|
{
|
|
|
|
|
std::string errMsg = "Creating description for UTF-8 converting failed: ";
|
|
|
|
|
|
|
|
|
|
static const size_t outputSize = 1000;
|
|
|
|
|
size_t outputBytesLeft;
|
|
|
|
|
switch (errno) //detailed error messages (maybe it contains too much detail :)
|
|
|
|
|
{
|
|
|
|
|
case EMFILE:
|
|
|
|
|
errMsg += "{OPEN_MAX} files descriptors are currently open in the calling process.";
|
|
|
|
|
case ENFILE:
|
|
|
|
|
errMsg += "Too many files are currently open in the system.";
|
|
|
|
|
case ENOMEM:
|
|
|
|
|
errMsg +="Insufficient storage space is available.";
|
|
|
|
|
case EINVAL:
|
|
|
|
|
errMsg += "The conversion specified by fromcode and tocode is not supported by the implementation.";
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
errMsg += "Unknown Error\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char outputBuffer[outputSize];
|
|
|
|
|
char *outputBufferBegin;
|
|
|
|
|
fail (errMsg);
|
|
|
|
|
|
|
|
|
|
while (inputBytesLeft > 0 )
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
outputBytesLeft = outputSize;
|
|
|
|
|
outputBufferBegin = outputBuffer;
|
|
|
|
|
const size_t inputSize = input.size();
|
|
|
|
|
|
|
|
|
|
if (iconv(cd, &inputBufferBegin, &inputBytesLeft, &outputBufferBegin, &outputBytesLeft) == (size_t)-1)
|
|
|
|
|
{
|
|
|
|
|
switch (errno)
|
|
|
|
|
if (inputSize) //input is not empty
|
|
|
|
|
{
|
|
|
|
|
case E2BIG: //outputBuffer is full
|
|
|
|
|
output += std::string(outputBuffer, outputSize);
|
|
|
|
|
break;
|
|
|
|
|
case EILSEQ:
|
|
|
|
|
fail("Iconv: Invalid multibyte sequence.\n");
|
|
|
|
|
break;
|
|
|
|
|
case EINVAL:
|
|
|
|
|
fail("Iconv: Incomplete multibyte sequence.\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fail("Iconv: Unknown Error\n");
|
|
|
|
|
}
|
|
|
|
|
//convert function doesn't accept const char *, therefore copy content into an char *
|
|
|
|
|
std::vector<char> inputBuffer (input.begin(), input.end());
|
|
|
|
|
char *inputBufferBegin = &inputBuffer[0];
|
|
|
|
|
|
|
|
|
|
size_t inputBytesLeft = inputSize; //bytes to convert
|
|
|
|
|
|
|
|
|
|
static const size_t outputSize = 1000;
|
|
|
|
|
size_t outputBytesLeft;
|
|
|
|
|
|
|
|
|
|
char outputBuffer[outputSize];
|
|
|
|
|
char *outputBufferBegin;
|
|
|
|
|
|
|
|
|
|
while (inputBytesLeft > 0)
|
|
|
|
|
{
|
|
|
|
|
outputBytesLeft = outputSize;
|
|
|
|
|
outputBufferBegin = outputBuffer;
|
|
|
|
|
|
|
|
|
|
if (iconv (cd, &inputBufferBegin, &inputBytesLeft, &outputBufferBegin, &outputBytesLeft) == (size_t)-1)
|
|
|
|
|
{
|
|
|
|
|
switch (errno)
|
|
|
|
|
{
|
|
|
|
|
case E2BIG: //outputBuffer is full
|
|
|
|
|
output += std::string (outputBuffer, outputSize);
|
|
|
|
|
break;
|
|
|
|
|
case EILSEQ:
|
|
|
|
|
fail ("Iconv: Invalid multibyte sequence.\n");
|
|
|
|
|
break;
|
|
|
|
|
case EINVAL:
|
|
|
|
|
fail ("Iconv: Incomplete multibyte sequence.\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fail ("Iconv: Unknown Error\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//read only relevant bytes from outputBuffer
|
|
|
|
|
output += std::string (outputBuffer, outputSize - outputBytesLeft);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//read only relevant bytes from outputBuffer
|
|
|
|
|
output += std::string(outputBuffer, outputSize - outputBytesLeft);
|
|
|
|
|
iconv_close (cd);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iconv_close (cd);
|
|
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void skip(int bytes) { esm->seek(esm->tell()+bytes); }
|
|
|
|
|
uint64_t getOffset() { return esm->tell(); }
|
|
|
|
|