* Copyright 2016, Haiku, inc.
* Distributed under terms of the MIT license.
*/
#include "TextEncoding.h"
#include <unicode/ucnv.h>
#include <unicode/ucsdet.h>
#include <algorithm>
namespace BPrivate {
BTextEncoding::BTextEncoding(BString name)
:
fName(name),
fUtf8Converter(NULL),
fConverter(NULL)
{
}
BTextEncoding::BTextEncoding(const char* data, size_t length)
:
fUtf8Converter(NULL),
fConverter(NULL)
{
UErrorCode error = U_ZERO_ERROR;
UCharsetDetector* detector = ucsdet_open(&error);
ucsdet_setText(detector, data, length, &error);
const UCharsetMatch* encoding = ucsdet_detect(detector, &error);
fName = ucsdet_getName(encoding, &error);
ucsdet_close(detector);
}
BTextEncoding::~BTextEncoding()
{
if (fUtf8Converter != NULL)
ucnv_close(fUtf8Converter);
if (fConverter != NULL)
ucnv_close(fConverter);
}
status_t
BTextEncoding::InitCheck()
{
if (fName.IsEmpty())
return B_NO_INIT;
else
return B_OK;
}
status_t
BTextEncoding::Decode(const char* input, size_t& inputLength, char* output,
size_t& outputLength)
{
const char* base = input;
char* target = output;
if (fName == "UTF-8") {
outputLength = std::min(inputLength, outputLength);
inputLength = outputLength;
memcpy(output, input, inputLength);
return B_OK;
}
UErrorCode error = U_ZERO_ERROR;
if (fUtf8Converter == NULL)
fUtf8Converter = ucnv_open("UTF-8", &error);
if (fConverter == NULL)
fConverter = ucnv_open(fName.String(), &error);
ucnv_convertEx(fUtf8Converter, fConverter, &target, output + outputLength,
&base, input + inputLength, NULL, NULL, NULL, NULL, FALSE, TRUE,
&error);
inputLength = base - input;
outputLength = target - output;
if (!U_SUCCESS(error))
return B_ERROR;
return B_OK;
}
status_t
BTextEncoding::Encode(const char* input, size_t& inputLength, char* output,
size_t& outputLength)
{
const char* base = input;
char* target = output;
if (fName == "UTF-8") {
outputLength = std::min(inputLength, outputLength);
inputLength = outputLength;
memcpy(output, input, inputLength);
return B_OK;
}
UErrorCode error = U_ZERO_ERROR;
if (fUtf8Converter == NULL)
fUtf8Converter = ucnv_open("UTF-8", &error);
if (fConverter == NULL)
fConverter = ucnv_open(fName.String(), &error);
ucnv_convertEx(fConverter, fUtf8Converter, &target, output + outputLength,
&base, input + inputLength, NULL, NULL, NULL, NULL, FALSE, TRUE,
&error);
inputLength = base - input;
outputLength = target - output;
if (!U_SUCCESS(error))
return B_ERROR;
return B_OK;
}
status_t
BTextEncoding::Flush(char* output, size_t& outputLength)
{
char* target = output;
if (fName == "UTF-8")
return B_OK;
if (fUtf8Converter == NULL || fConverter == NULL)
return B_NO_INIT;
UErrorCode error = U_ZERO_ERROR;
ucnv_convertEx(fConverter, fUtf8Converter, &target, output + outputLength,
NULL, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE,
&error);
if (!U_SUCCESS(error))
return B_ERROR;
return B_OK;
}
BString
BTextEncoding::GetName()
{
return fName;
}
};