/*
 * 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.
 */
#define NOMINMAX /* tell windows not to define min/max macros */
#include <log4cxx/private/string_c11.h>
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/private/bytebuffer_priv.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/loglog.h>
#include <apr_xlate.h>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>
#include <locale.h>
#include <apr_portable.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/transcoder.h>
#include <mutex>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;

IMPLEMENT_LOG4CXX_OBJECT(CharsetDecoder)


namespace LOG4CXX_NS
{
namespace helpers
{

#if APR_HAS_XLATE
/**
 *  Converts from an arbitrary encoding to LogString
 *    using apr_xlate.  Requires real iconv implementation,
*    apr-iconv will crash in use.
 */
class APRCharsetDecoder : public CharsetDecoder
{
	public:
		/**
		 *  Creates a new instance.
		 *  @param frompage name of source encoding.
		 */
		APRCharsetDecoder(const LogString& frompage) : pool()
		{
#if LOG4CXX_LOGCHAR_IS_WCHAR
			const char* topage = "WCHAR_T";
#endif
#if LOG4CXX_LOGCHAR_IS_UTF8
			const char* topage = "UTF-8";
#endif
			std::string fpage(Transcoder::encodeCharsetName(frompage));
			apr_status_t stat = apr_xlate_open(&convset,
					topage,
					fpage.c_str(),
					pool.getAPRPool());

			if (stat != APR_SUCCESS)
			{
				throw IllegalArgumentException(frompage);
			}
		}

		/**
		 *  Destructor.
		 */
		virtual ~APRCharsetDecoder()
		{
		}

		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			enum { BUFSIZE = 256 };
			logchar buf[BUFSIZE];
			const apr_size_t initial_outbytes_left = BUFSIZE * sizeof(logchar);
			apr_status_t stat = APR_SUCCESS;

			if (in.remaining() == 0)
			{
				size_t outbytes_left = initial_outbytes_left;
				{
					std::lock_guard<std::mutex> lock(mutex);
					stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
							NULL, NULL, (char*) buf, &outbytes_left);
				}
				out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
			}
			else
			{
				while (in.remaining() > 0 && stat == APR_SUCCESS)
				{
					size_t inbytes_left = in.remaining();
					size_t initial_inbytes_left = inbytes_left;
					apr_size_t outbytes_left = initial_outbytes_left;
					{
						std::lock_guard<std::mutex> lock(mutex);
						stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
								in.current(),
								&inbytes_left,
								(char*) buf,
								&outbytes_left);
					}
					out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
					if (inbytes_left == initial_inbytes_left && stat == APR_SUCCESS)
					{
						stat = APR_BADCH;
						break;
					}
					in.increment_position(initial_inbytes_left - inbytes_left);
				}
			}

			return stat;
		}

	private:
		APRCharsetDecoder(const APRCharsetDecoder&);
		APRCharsetDecoder& operator=(const APRCharsetDecoder&);
		LOG4CXX_NS::helpers::Pool pool;
		std::mutex mutex;
		apr_xlate_t* convset;
};

#endif

#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
/**
*    Converts from the default multi-byte string to
*        LogString using mbstowcs.
*
*/
class MbstowcsCharsetDecoder : public CharsetDecoder
{
	public:
		MbstowcsCharsetDecoder()
		{
		}

		virtual ~MbstowcsCharsetDecoder()
		{
		}

	private:
		inline log4cxx_status_t append(LogString& out, const wchar_t* buf)
		{
			out.append(buf);
			return APR_SUCCESS;
		}

		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			log4cxx_status_t stat = APR_SUCCESS;
			enum { BUFSIZE = 256 };
			wchar_t wbuf[BUFSIZE];
			char cbuf[BUFSIZE*4];

			mbstate_t mbstate;
			memset(&mbstate, 0, sizeof(mbstate));

			while (in.remaining() > 0)
			{
				const char* src = in.current();

				if (*src == 0)
				{
					out.append(1, (logchar) 0);
					in.increment_position(1);
				}
				else
				{
					auto available = std::min(sizeof (cbuf) - 1, in.remaining());
					strncpy(cbuf, src, available);
					cbuf[available] = 0;
					src = cbuf;
					size_t wCharCount = mbsrtowcs(wbuf,
							&src,
							BUFSIZE - 1,
							&mbstate);
					// mbsrtowcs sets *src to nullptr when it consumes a null wide character.
					// Performing pointer arithmetic on that nullptr (src - cbuf) is undefined
					// behaviour, so recover the consumed byte count from the position of the
					// null that stopped the conversion instead.
					size_t converted;
					if (src == nullptr)
					{
						size_t nullPos = 0;
						while (nullPos < available && cbuf[nullPos] != 0)
						{
							++nullPos;
						}
						// If the null came from the input bytes, it was consumed too;
						// if it is the sentinel we wrote at cbuf[available], stop at available.
						converted = (nullPos < available) ? nullPos + 1 : available;
					}
					else
					{
						converted = static_cast<size_t>(src - cbuf);
					}
					in.increment_position(converted);

					if (wCharCount == (size_t) -1) // Illegal byte sequence?
					{
						LogString msg(LOG4CXX_STR("Illegal byte sequence at "));
						msg.append(std::to_wstring(in.position()));
						msg.append(LOG4CXX_STR(" of "));
						msg.append(std::to_wstring(in.limit()));
						LogLog::warn(msg);
						stat = APR_BADCH;
						break;
					}
					else
					{
						// FIX: Check for incomplete sequence infinite loop.
						// If mbsrtowcs returns success (>=0) but converted 0 bytes while data remains,
						// we are stuck (e.g. incomplete multibyte char at EOF).
						if (converted == 0 && in.remaining() > 0)
						{
							LogString msg(LOG4CXX_STR("Incomplete multibyte sequence at end of buffer"));
							LogLog::warn(msg);
							stat = APR_BADCH;
							break; // Break the infinite loop
						}

						wbuf[wCharCount] = 0;
						stat = append(out, wbuf);
					}
				}
			}

			return stat;
		}



	private:
		MbstowcsCharsetDecoder(const MbstowcsCharsetDecoder&);
		MbstowcsCharsetDecoder& operator=(const MbstowcsCharsetDecoder&);
};
#endif


/**
*    Decoder used when the external and internal charsets
*    are the same.
*
*/
class TrivialCharsetDecoder : public CharsetDecoder
{
	public:
		TrivialCharsetDecoder()
		{
		}

		virtual ~TrivialCharsetDecoder()
		{
		}

		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			size_t remaining = in.remaining();

			if ( remaining > 0)
			{
				auto src = in.current();
				auto count = remaining / sizeof(logchar);
				out.append(reinterpret_cast<const logchar*>(src), count);
				in.increment_position(remaining);
			}

			return APR_SUCCESS;
		}



	private:
		TrivialCharsetDecoder(const TrivialCharsetDecoder&);
		TrivialCharsetDecoder& operator=(const TrivialCharsetDecoder&);
};

/**
*    Converts from UTF-8 to LogString
*
*/
class UTF8CharsetDecoder : public CharsetDecoder
{
	public:
		UTF8CharsetDecoder()
		{
		}

		virtual ~UTF8CharsetDecoder()
		{
		}

	private:
		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			auto availableByteCount = in.remaining();
			while (0 < availableByteCount)
			{
				auto sv = getUTF8CodePoint(in);
				auto nextAvailableByteCount = in.remaining();
				if (sv == 0xFFFF || nextAvailableByteCount == availableByteCount)
					return APR_BADCH;
				Transcoder::encode(sv, out);
				availableByteCount = nextAvailableByteCount;
			}
			return APR_SUCCESS;
		}

	private:
		UTF8CharsetDecoder(const UTF8CharsetDecoder&);
		UTF8CharsetDecoder& operator=(const UTF8CharsetDecoder&);
};

/**
*    Converts from ISO-8859-1 to LogString.
*
*/
class ISOLatinCharsetDecoder : public CharsetDecoder
{
	public:
		ISOLatinCharsetDecoder()
		{
		}

		virtual ~ISOLatinCharsetDecoder()
		{
		}

	private:
		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			auto availableByteCount = in.remaining();
			auto src = in.current();
			auto srcEnd = src + availableByteCount;

			while (src < srcEnd)
			{
				auto sv = static_cast<unsigned int>(static_cast<unsigned char>(*src++));
				Transcoder::encode(sv, out);
			}
			in.increment_position(availableByteCount);

			return APR_SUCCESS;
		}



	private:
		ISOLatinCharsetDecoder(const ISOLatinCharsetDecoder&);
		ISOLatinCharsetDecoder& operator=(const ISOLatinCharsetDecoder&);
};


/**
*    Converts from US-ASCII to LogString.
*
*/
class USASCIICharsetDecoder : public CharsetDecoder
{
	public:
		USASCIICharsetDecoder()
		{
		}

		virtual ~USASCIICharsetDecoder()
		{
		}

	private:

		virtual log4cxx_status_t decode(ByteBuffer& in_param,
			LogString& out)
		{
			auto& in = in_param.impl();
			log4cxx_status_t stat = APR_SUCCESS;

			auto availableByteCount = in.remaining();
			auto src = in.current();
			auto srcEnd = src + availableByteCount;
			size_t byteCount = 0;
			while (src < srcEnd)
			{
				auto sv = static_cast<unsigned int>(*src++);

				if (sv < 0x80)
				{
					++byteCount;
					Transcoder::encode(sv, out);
				}
				else
				{
					stat = APR_BADCH;
					break;
				}
			}
			in.increment_position(byteCount);

			return stat;
		}



	private:
		USASCIICharsetDecoder(const USASCIICharsetDecoder&);
		USASCIICharsetDecoder& operator=(const USASCIICharsetDecoder&);
};

/**
 *    Charset decoder that uses current locale settings.
 */
class LocaleCharsetDecoder : public CharsetDecoder
{
	public:
		LocaleCharsetDecoder() : state()
		{
		}
		log4cxx_status_t decode(ByteBuffer& in_param, LogString& out) override
		{
			auto& in = in_param.impl();
			log4cxx_status_t result = APR_SUCCESS;
			auto p = in.current();
			auto availableByteCount = in.remaining();
			size_t byteCount = 0;
#if !LOG4CXX_CHARSET_EBCDIC
			if (std::mbsinit(&this->state)) // ByteBuffer not partially decoded?
			{
				// Copy single byte characters
				for (; byteCount < availableByteCount && static_cast<unsigned int>(*p) < 0x80; ++byteCount, ++p)
				{
					out.append(1, *p);
				}
			}
#endif
			// Decode characters that may be represented by multiple bytes
			while (byteCount < availableByteCount)
			{
				wchar_t ch = 0;
				size_t n = std::mbrtowc(&ch, p, availableByteCount - byteCount, &this->state);
				if (0 == n) // NULL encountered?
				{
					++byteCount;
					break;
				}
				if (static_cast<std::size_t>(-1) == n) // decoding error?
				{
					result = APR_BADCH;
					break;
				}
				if (static_cast<std::size_t>(-2) == n) // incomplete sequence?
				{
					break;
				}
				Transcoder::encode(static_cast<unsigned int>(ch), out);
				byteCount += n;
				p += n;
			}
			in.increment_position(byteCount);
			return result;
		}

	private:
		std::mbstate_t state;
};



} // namespace helpers

}  //namespace log4cxx


CharsetDecoder::CharsetDecoder()
{
}


CharsetDecoder::~CharsetDecoder()
{
}

CharsetDecoder* CharsetDecoder::createDefaultDecoder()
{
#if LOG4CXX_CHARSET_UTF8
#if LOG4CXX_LOGCHAR_IS_UTF8
	return new TrivialCharsetDecoder();
#else
	return new UTF8CharsetDecoder();
#endif
#elif LOG4CXX_CHARSET_ISO88591 || defined(_WIN32_WCE)
	return new ISOLatinCharsetDecoder();
#elif LOG4CXX_CHARSET_USASCII
	return new USASCIICharsetDecoder();
#elif LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
	return new MbstowcsCharsetDecoder();
#else
	return new LocaleCharsetDecoder();
#endif
}

CharsetDecoderPtr CharsetDecoder::getDefaultDecoder()
{
	static WideLife<CharsetDecoderPtr> decoder(createDefaultDecoder());

	//
	//  if invoked after static variable destruction
	//     (if logging is called in the destructor of a static object)
	//     then create a new decoder.
	//
	if (decoder.value() == 0)
	{
		return CharsetDecoderPtr( createDefaultDecoder() );
	}

	return decoder;
}

CharsetDecoderPtr CharsetDecoder::getUTF8Decoder()
{
	return std::make_shared<UTF8CharsetDecoder>();
}

CharsetDecoderPtr CharsetDecoder::getISOLatinDecoder()
{
	return std::make_shared<ISOLatinCharsetDecoder>();
}


CharsetDecoderPtr CharsetDecoder::getDecoder(const LogString& charset)
{
	if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF8"), LOG4CXX_STR("utf8")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP65001"), LOG4CXX_STR("cp65001")))
	{
#if LOG4CXX_LOGCHAR_IS_UTF8
		return std::make_shared<TrivialCharsetDecoder>();
#else
		return std::make_shared<UTF8CharsetDecoder>();
#endif
	}
	else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
		charset == LOG4CXX_STR("646") ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP20127"), LOG4CXX_STR("cp20127")))
	{
		return std::make_shared<USASCIICharsetDecoder>();
	}
	else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1")) ||
		StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1252"), LOG4CXX_STR("cp1252")))
	{
		return std::make_shared<ISOLatinCharsetDecoder>();
	}
	else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("LOCALE"), LOG4CXX_STR("locale")))
	{
		return std::make_shared<LocaleCharsetDecoder>();
	}

#if APR_HAS_XLATE
	return std::make_shared<APRCharsetDecoder>(charset);
#else
	throw IllegalArgumentException(charset);
#endif
}

log4cxx_status_t CharsetDecoder::decode(const char* in, size_t maxByteCount, LogString& out)
{
	ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount));
	return decode(buf, out);
}

unsigned int CharsetDecoder::getUTF8CodePoint(ByteBufferPriv& in)
{
	auto availableByteCount = in.remaining();
	if (0 == availableByteCount)
		return 0xFFFF;

	auto pChar = in.current();
	auto ch1 = static_cast<unsigned char>(*pChar);
	if (ch1 <= 0x7F)
	{
		in.increment_position(1);
		return ch1;
	}

	//
	//   should not have continuation character here
	//
	if ((ch1 & 0xC0) != 0x80 && 1 < availableByteCount)
	{
		auto ch2 = static_cast<unsigned char>(*(pChar + 1));
		if ((ch2 & 0xC0) != 0x80) // not a continuation?
			return 0xFFFF;

		if ((ch1 & 0xE0) == 0xC0)
		{
			unsigned int rv = ((ch1 & 0x1F) << 6) + (ch2 & 0x3F);
			if (rv >= 0x80)
			{
				in.increment_position(2);
				return rv;
			}
			return 0xFFFF;
		}

		if (2 < availableByteCount)
		{
			auto ch3 = static_cast<unsigned char>(*(pChar + 2));
			if ((ch3 & 0xC0) != 0x80) // not a continuation?
				return 0xFFFF;

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

				// RFC 3629 §3 prohibits UTF-8 encodings of the UTF-16 surrogate
				// halves (U+D800..U+DFFF); accepting them lets malformed Unicode
				// cross the decode boundary into LogString and downstream output.
				if (rv < 0x800 || (0xD800 <= rv && rv <= 0xDFFF))
					return 0xFFFF;

				in.increment_position(3);
				return rv;
			}

			if (3 < availableByteCount)
			{
				auto ch4 = static_cast<unsigned char>(*(pChar + 3));
				if ((ch4 & 0xC0) != 0x80) // not a continuation?
					return 0xFFFF;

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

				// RFC 3629 §3 caps UTF-8 at U+10FFFF; lead bytes F5..F7 (and
				// F4 with an over-high trailer) produce rv > 0x10FFFF, which
				// is not a Unicode code point. Without this bound, encodeUTF16
				// later silently aliases the bogus value to a valid in-range
				// code point — a substitution-collision filter-bypass primitive.
				// Lead bytes F8..FF are never valid UTF-8, but the & 0x07 mask
				// discards their high bits, so without the (ch1 & 0xF8) == 0xF0
				// guard F8 BF BF BF would alias to U+3FFFF instead of being
				// rejected.
				if ((ch1 & 0xF8) == 0xF0 && rv > 0xFFFF && rv <= 0x10FFFF)
				{
					in.increment_position(4);
					return rv;
				}

			}
		}
	}
	return 0xFFFF;
}
