/*
 * 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 <vector>
#include <apr.h>
#include <apr_strings.h>
#if !defined(LOG4CXX)
    #define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>

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

using namespace log4cxx;
using namespace log4cxx::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);
        encode(cp, dst);
    }

#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;
    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_CFSTRING_API
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)
{
    const UniChar* chars = CFStringGetCharactersPtr(src);

    if (chars)
    {
        decode(chars, dst);
    }
    else
    {
        size_t length = CFStringGetLength(src);

        if (length > 0)
        {
            std::vector<UniChar> tmp(length);
            CFStringGetCharacters(src, CFRangeMake(0, length), &tmp[0]);
#if LOG4CXX_LOGCHAR_IS_UNICHAR
            dst.append(&tmp[0], tmp.size());
#else
            decode(std::basic_string<UniChar>(&tmp[0], tmp.size()), dst);
#endif
        }
    }
}

CFStringRef Transcoder::encode(const LogString& src)
{
    LOG4CXX_ENCODE_UNICHAR(tmp, src);
    return CFStringCreateWithCharacters(kCFAllocatorDefault, tmp.data(), tmp.size());
}
#endif


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;
}
