/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/pool.h>
#include <stdlib.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/helpers/charsetencoder.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/loglog.h>
#include <vector>
#include <cstring>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>

#if LOG4CXX_CFSTRING_API
	#include <CoreFoundation/CFString.h>
#endif

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;


void Transcoder::decodeUTF8(const std::string& src, LogString& dst)
{
	std::string::const_iterator iter = src.begin();

	while (iter != src.end())
	{
		unsigned int sv = decode(src, iter);

		if (sv != 0xFFFF)
		{
			encode(sv, dst);
		}
		else
		{
			dst.append(1, LOSSCHAR);
			iter++;
		}
	}
}

void Transcoder::encodeUTF8(const LogString& src, std::string& dst)
{
#if LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	LogString::const_iterator iter = src.begin();

	while (iter != src.end())
	{
		unsigned int sv = decode(src, iter);

		if (sv != 0xFFFF)
		{
			encode(sv, dst);
		}
		else
		{
			dst.append(1, LOSSCHAR);
			iter++;
		}
	}

#endif
}

char* Transcoder::encodeUTF8(const LogString& src, Pool& p)
{
#if LOG4CXX_LOGCHAR_IS_UTF8
	return p.pstrdup(src);
#else
	std::string tmp;
	encodeUTF8(src, tmp);
	return p.pstrdup(tmp);
#endif
}


void Transcoder::encodeUTF8(unsigned int sv, ByteBuffer& dst)
{
	size_t bytes = encodeUTF8(sv, dst.current());
	dst.position(dst.position() + bytes);
}


size_t Transcoder::encodeUTF8(unsigned int ch, char* dst)
{
	if (ch < 0x80)
	{
		dst[0] = (char) ch;
		return 1;
	}
	else if (ch < 0x800)
	{
		dst[0] = (char) (0xC0 + (ch >> 6));
		dst[1] = (char) (0x80 + (ch & 0x3F));
		return 2;
	}
	else if (ch < 0x10000)
	{
		dst[0] = (char) (0xE0 + (ch >> 12));
		dst[1] = (char) (0x80 + ((ch >> 6) & 0x3F));
		dst[2] = (char) (0x80 + (ch & 0x3F));
		return 3;
	}
	else if (ch <= 0x10FFFF)
	{
		dst[0] = (char) (0xF0 + (ch >> 18));
		dst[1] = (char) (0x80 + ((ch >> 12) & 0x3F));
		dst[2] = (char) (0x80 + ((ch >> 6) & 0x3F));
		dst[3] = (char) (0x80 + (ch & 0x3F));
		return 4;
	}
	else
	{
		//
		//  output UTF-8 encoding of 0xFFFF
		//
		dst[0] = (char) 0xEF;
		dst[1] = (char) 0xBF;
		dst[2] = (char) 0xBF;
		return 3;
	}
}

void Transcoder::encodeUTF16BE(unsigned int sv, ByteBuffer& dst)
{
	size_t bytes = encodeUTF16BE(sv, dst.current());
	dst.position(dst.position() + bytes);
}


size_t Transcoder::encodeUTF16BE(unsigned int ch, char* dst)
{
	if (ch <= 0xFFFF)
	{
		dst[0] = (char) (ch >> 8);
		dst[1] = (char) (ch & 0xFF);
		return 2;
	}

	if (ch <= 0x10FFFF)
	{
		unsigned char w = (unsigned char) ((ch >> 16) - 1);
		dst[0] = (char) (0xD8 + (w >> 2));
		dst[1] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
		dst[2] = (char) (0xDC + ((ch & 0x30) >> 4));
		dst[3] = (char) (ch & 0xFF);
		return 4;
	}

	dst[0] = dst[1] = (char) 0xFF;
	return 2;
}

void Transcoder::encodeUTF16LE(unsigned int sv, ByteBuffer& dst)
{
	size_t bytes = encodeUTF16LE(sv, dst.current());
	dst.position(dst.position() + bytes);
}

size_t Transcoder::encodeUTF16LE(unsigned int ch, char* dst)
{
	if (ch <= 0xFFFF)
	{
		dst[1] = (char) (ch >> 8);
		dst[0] = (char) (ch & 0xFF);
		return 2;
	}

	if (ch <= 0x10FFFF)
	{
		unsigned char w = (unsigned char) ((ch >> 16) - 1);
		dst[1] = (char) (0xD8 + (w >> 2));
		dst[0] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
		dst[3] = (char) (0xDC + ((ch & 0x30) >> 4));
		dst[2] = (char) (ch & 0xFF);
		return 4;
	}

	dst[0] = dst[1] = (char) 0xFF;
	return 2;
}


unsigned int Transcoder::decode(const std::string& src,
	std::string::const_iterator& iter)
{
	std::string::const_iterator start(iter);
	unsigned char ch1 = *(iter++);

	if (ch1 <= 0x7F)
	{
		return ch1;
	}

	//
	//   should not have continuation character here
	//
	if ((ch1 & 0xC0) != 0x80 && iter != src.end())
	{
		unsigned char ch2 = *(iter++);

		//
		//   should be continuation
		if ((ch2 & 0xC0) != 0x80)
		{
			iter = start;
			return 0xFFFF;
		}

		if ((ch1 & 0xE0) == 0xC0)
		{
			if ((ch2 & 0xC0) == 0x80)
			{
				unsigned int rv = ((ch1 & 0x1F) << 6) + (ch2 & 0x3F);

				if (rv >= 0x80)
				{
					return rv;
				}
			}

			iter = start;
			return 0xFFFF;
		}

		if (iter != src.end())
		{
			unsigned char ch3 = *(iter++);

			//
			//   should be continuation
			//
			if ((ch3 & 0xC0) != 0x80)
			{
				iter = start;
				return 0xFFFF;
			}

			if ((ch1 & 0xF0) == 0xE0)
			{
				unsigned rv = ((ch1 & 0x0F) << 12)
					+ ((ch2 & 0x3F) << 6)
					+ (ch3 & 0x3F);

				if (rv <= 0x800)
				{
					iter = start;
					return 0xFFFF;
				}

				return rv;
			}

			if (iter != src.end())
			{
				unsigned char ch4 = *(iter++);

				if ((ch4 & 0xC0) != 0x80)
				{
					iter = start;
					return 0xFFFF;
				}

				unsigned int rv = ((ch1 & 0x07) << 18)
					+ ((ch2 & 0x3F) << 12)
					+ ((ch3 & 0x3F) << 6)
					+ (ch4 & 0x3F);

				if (rv > 0xFFFF)
				{
					return rv;
				}

			}
		}
	}

	iter = start;
	return 0xFFFF;
}


void Transcoder::encode(unsigned int sv, std::string& dst)
{
	char tmp[8];
	size_t bytes = encodeUTF8(sv, tmp);
	dst.append(tmp, bytes);
}


void Transcoder::decode(const std::string& src, LogString& dst)
{
#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	static CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder());
	dst.reserve(dst.size() + src.size());
	std::string::const_iterator iter = src.begin();
#if !LOG4CXX_CHARSET_EBCDIC

	for (;
		iter != src.end() && ((unsigned char) *iter) < 0x80;
		iter++)
	{
		dst.append(1, *iter);
	}

#endif

	if (iter != src.end())
	{
		size_t offset = iter - src.begin();
		ByteBuffer buf(const_cast<char*>(src.data() + offset), src.size() - offset);

		while (buf.remaining() > 0)
		{
			log4cxx_status_t stat = decoder->decode(buf, dst);

			if (CharsetDecoder::isError(stat))
			{
				dst.append(1, LOSSCHAR);
				buf.position(buf.position() + 1);
			}
		}

		decoder->decode(buf, dst);
	}

#endif
}

char* Transcoder::encode(const LogString& src, Pool& p)
{
#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
	return p.pstrdup(src);
#else
	std::string tmp;
	encode(src, tmp);
	return p.pstrdup(tmp);
#endif
}



void Transcoder::encode(const LogString& src, std::string& dst)
{
#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	static CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder());
	dst.reserve(dst.size() + src.size());
	LogString::const_iterator iter = src.begin();
#if !LOG4CXX_CHARSET_EBCDIC

	for (;
		iter != src.end() && ((unsigned int) *iter) < 0x80;
		iter++)
	{
		dst.append(1, *iter);
	}

#endif

	if (iter != src.end())
	{
		char buf[BUFSIZE];
		ByteBuffer out(buf, BUFSIZE);

		while (iter != src.end())
		{
			log4cxx_status_t stat = encoder->encode(src, iter, out);
			out.flip();
			dst.append(out.data(), out.limit());
			out.clear();

			if (CharsetEncoder::isError(stat))
			{
				dst.append(1, LOSSCHAR);
				iter++;
			}
		}

		encoder->encode(src, iter, out);
	}

#endif
}


template<class String, class Iterator>
static unsigned int decodeUTF16(const String& in, Iterator& iter)
{
	unsigned int ch1 = *iter;

	//
	//   if not surrogate pair
	//
	if (ch1 < 0xD800 || ch1 > 0xDFFF)
	{
		//
		//  then advance iterator and return wchar_t value
		//
		if (ch1 != 0xFFFF)
		{
			iter++;
		}

		return ch1;
	}
	else if (ch1 < 0xDC00)
	{
		//
		//  started with high-surrogate value
		//     if there is an additional wchar_t
		Iterator iter2 = iter + 1;

		if (iter2 != in.end())
		{
			unsigned int ch2 = *iter2;

			//
			//    if it is a matching low surrogate then
			//       advance the iterator and return the scalar value
			if (ch2 >= 0xDC00 && ch2 <= 0xDFFF)
			{
				iter += 2;
				return (ch1 - 0xD800) * 0x400 + (ch2 - 0xDC00) + 0x10000;
			}
		}
	}

	//
	//    unrecognized value, do not advance iterator
	//
	return 0xFFFF;
}

template<class String>
static void encodeUTF16(unsigned int sv, String& dst)
{
	if (sv < 0x10000)
	{
		dst.append(1, sv);
	}
	else
	{
		unsigned char u = (unsigned char) (sv >> 16);
		unsigned char w = (unsigned char) (u - 1);
		unsigned short hs = (0xD800 + ((w & 0xF) << 6) + ((sv & 0xFFFF) >> 10));
		unsigned short ls = (0xDC00 + (sv & 0x3FF));
		dst.append(1, hs);
		dst.append(1, ls);
	}
}



#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR_T || defined(WIN32) || defined(_WIN32)
void Transcoder::decode(const std::wstring& src, LogString& dst)
{
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
	dst.append(src, len);
#else
	std::wstring::const_iterator i = src.begin();

	while (i != src.end())
	{
		unsigned int cp = decode(src, i);

		if (cp != 0xFFFF)
		{
			encode(cp, dst);
		}
		else
		{
			dst.append(1, LOSSCHAR);
			i++;
		}
	}

#endif
}

void Transcoder::encode(const LogString& src, std::wstring& dst)
{
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
	dst.append(src);
#else

	for (LogString::const_iterator i = src.begin(); i != src.end();)
	{
		unsigned int cp = Transcoder::decode(src, i);

		if (cp != 0xFFFF)
		{
			encode(cp, dst);
		}
		else
		{
			dst.append(1, LOSSCHAR);
			i++;
		}
	}

#endif
}

wchar_t* Transcoder::wencode(const LogString& src, Pool& p)
{
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
	std::wstring& tmp = src;
#else
	std::wstring tmp;
	encode(src, tmp);
#endif
	wchar_t* dst = (wchar_t*) p.palloc((tmp.length() + 1) * sizeof(wchar_t));
	dst[tmp.length()] = 0;
	std::memcpy(dst, tmp.data(), tmp.length() * sizeof(wchar_t));
	return dst;
}


unsigned int Transcoder::decode(const std::wstring& in,
	std::wstring::const_iterator& iter)
{
#if defined(__STDC_ISO_10646__)
	return *(iter++);
#else
	return decodeUTF16(in, iter);
#endif
}


void Transcoder::encode(unsigned int sv, std::wstring& dst)
{
#if defined(__STDC_ISO_10646__)
	dst.append(1, sv);
#else

	if (sizeof(wchar_t) == 4)
	{
		dst.append(1, sv);
	}
	else
	{
		encodeUTF16(sv, dst);
	}

#endif
}

#endif



#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
void Transcoder::decode(const std::basic_string<UniChar>& src, LogString& dst)
{
#if LOG4CXX_LOGCHAR_IS_UNICHAR
	dst.append(src);
#else

	for (std::basic_string<UniChar>::const_iterator i = src.begin();
		i != src.end();)
	{
		unsigned int cp = decode(src, i);
		encode(cp, dst);
	}

#endif
}

void Transcoder::encode(const LogString& src, std::basic_string<UniChar>& dst)
{
#if LOG4CXX_LOGCHAR_IS_UNICHAR
	dst.append(src);
#else

	for (LogString::const_iterator i = src.begin();
		i != src.end();)
	{
		unsigned int cp = decode(src, i);
		encode(cp, dst);
	}

#endif
}

unsigned int Transcoder::decode(const std::basic_string<UniChar>& in,
	std::basic_string<UniChar>::const_iterator& iter)
{
	return decodeUTF16(in, iter);
}

void Transcoder::encode(unsigned int sv, std::basic_string<UniChar>& dst)
{
	encodeUTF16(sv, dst);
}

#endif

#if LOG4CXX_CFSTRING_API
void Transcoder::decode(const CFStringRef& src, LogString& dst)
{
	auto length = CFStringGetLength(src);
#if defined(_DEBUG)
	Pool pool;
	LogString msg(LOG4CXX_STR("Transcoder::decodeCFString"));
	msg += LOG4CXX_STR(" length ");
	StringHelper::toString((size_t)length, pool, msg);
	LogLog::debug(msg);
#endif

	if (length > 0)
	{
		std::vector<unsigned short> tmp(length);
		CFStringGetCharacters(src, CFRangeMake(0, length), &tmp[0]);
		for (auto i = tmp.begin(); i != tmp.end(); )
		{
			unsigned int cp = decodeUTF16(tmp, i);
			encode(cp, dst);
		}
	}
}

CFStringRef Transcoder::encode(const LogString& src)
{
	std::basic_string<unsigned short> tmp;
	for (auto ch : src)
		encodeUTF16(ch, tmp);
	return CFStringCreateWithCharacters(kCFAllocatorDefault, tmp.data(), tmp.size());
}
#endif // #if LOG4CXX_CFSTRING_API


logchar Transcoder::decode(char val)
{
#if LOG4CXX_CHARSET_EBCDIC
	LogString dst;
	Transcoder::decode(std::string(1, val), dst);
	return dst[0];
#else
	return val;
#endif
}

LogString Transcoder::decode(const char* val)
{
#if LOG4CXX_LOGCHAR_IS_UTF8 && !LOG4CXX_CHARSET_EBCDIC
	return val;
#else
	LogString dst;
	Transcoder::decode(val, dst);
	return dst;
#endif
}


std::string Transcoder::encodeCharsetName(const LogString& val)
{
	char asciiTable[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
			'@', 'A', 'B', 'C', 'D', 'E', 'F',  'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
			'P', 'Q', 'R', 'S', 'T', 'U', 'V',  'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
			'`', 'a', 'b', 'c', 'd', 'e', 'f',  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
			'p', 'q', 'r', 's', 't', 'u', 'v',  'w', 'x', 'y', 'z', '{', '|', '}', '~'
		};
	std::string out;

	for (LogString::const_iterator iter = val.begin();
		iter != val.end();
		iter++)
	{
		if (*iter >= 0x20 && *iter < 0x7F)
		{
			out.append(1, asciiTable[*iter - 0x20]);
		}
		else
		{
			out.append(1, LOSSCHAR);
		}
	}

	return out;
}
