<commit_before>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-10-23.
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "Converter.hpp"

#include <vector>
#include "../EncodingInfo.hpp"
#include "../PrivatePlatformDetails.hpp"
#include "../YstringException.hpp"
#include "Utf8Decoder.hpp"
#include "Utf8Encoder.hpp"
#include "Utf16Decoder.hpp"
#include "Utf16Encoder.hpp"
#include "Utf32Decoder.hpp"
#include "Utf32Encoder.hpp"

namespace Ystring { namespace Conversion {

    namespace {

        const size_t DEFAULT_BUFFER_SIZE = 256;

        std::unique_ptr<AbstractDecoder> makeDecoder(Encoding_t encoding);

        std::unique_ptr<AbstractEncoder> makeEncoder(Encoding_t encoding);

        template<typename CharT, typename StringT>
        size_t copy(const CharT* src,
                    size_t srcLength,
                    StringT& dst,
                    size_t charSize);

        template <typename T>
        void swapEndianness(T* str, size_t length);

    }

    Converter::Converter(Encoding_t srcEncoding, Encoding_t dstEncoding)
        : m_Decoder(makeDecoder(srcEncoding)),
          m_Encoder(makeEncoder(dstEncoding)),
          m_ConversionType(getConversionType(srcEncoding, dstEncoding)),
          m_BufferSize(DEFAULT_BUFFER_SIZE)
    {}

    Converter::~Converter()
    {}

    size_t Converter::bufferSize() const
    {
        return m_BufferSize;
    }

    void Converter::setBufferSize(size_t value)
    {
        m_BufferSize = value;
    }

    void Converter::setErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        setDecoderErrorHandlingPolicy(value);
        setEncoderErrorHandlingPolicy(value);
    }

    ErrorHandlingPolicy_t Converter::decoderErrorHandlingPolicy() const
    {
        return m_Decoder->errorHandlingPolicy();
    }

    void Converter::setDecoderErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        m_Decoder->setErrorHandlingPolicy(value);
    }

    ErrorHandlingPolicy_t Converter::encoderErrorHandlingPolicy() const
    {
        return m_Encoder->errorHandlingPolicy();
    }

    void Converter::setEncoderErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        m_Encoder->setErrorHandlingPolicy(value);
    }

    void Converter::setReplacementCharacter(char32_t value)
    {
        setDecoderReplacementCharacter(value);
        setEncoderReplacementCharacter(value);
    }

    char32_t Converter::decoderReplacementCharacter() const
    {
        return m_Decoder->replacementCharacter();
    }

    void Converter::setDecoderReplacementCharacter(char32_t value)
    {
        m_Decoder->setReplacementCharacter(value);
    }

    char32_t Converter::encoderReplacementCharacter() const
    {
        return m_Encoder->replacementCharacter();
    }

    void Converter::setEncoderReplacementCharacter(char32_t value)
    {
        m_Encoder->setReplacementCharacter(value);
    }

    Encoding_t Converter::decoderEncoding() const
    {
        if (!m_Decoder)
            return Encoding::UNKNOWN;
        return m_Decoder->encoding();
    }

    Encoding_t Converter::encoderEncoding() const
    {
        if (!m_Encoder)
            return Encoding::UNKNOWN;
        return m_Encoder->encoding();
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    Converter::ConversionType Converter::getConversionType(
            Encoding_t src, Encoding_t dst)
    {
        if (src == dst)
            return COPY;
        if ((src == Encoding::UTF_16_LE && dst == Encoding::UTF_16_BE)
            || (src == Encoding::UTF_16_BE && dst == Encoding::UTF_16_LE)
            || (src == Encoding::UTF_32_LE && dst == Encoding::UTF_32_BE)
            || (src == Encoding::UTF_32_BE && dst == Encoding::UTF_32_LE))
        {
            return SWAP_ENDIANNESS;
        }
        return CONVERT;
    }

    template<typename CharT, typename StringT>
    size_t Converter::convertImpl(const CharT* src,
                                  size_t srcLength,
                                  StringT& dst,
                                  bool sourceIsIncomplete)
    {
        switch (m_ConversionType)
        {
        case SWAP_ENDIANNESS:
            return doCopyAndSwapBytes(src, srcLength, dst, sourceIsIncomplete);
        case COPY:
            return doCopy(src, srcLength, dst, sourceIsIncomplete);
        case CONVERT:
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
        return 0;
    }

    template<typename CharT, typename StringT>
    size_t Converter::doConvert(const CharT* src,
                                size_t srcLength,
                                StringT& dst,
                                bool sourceIsIncomplete)
    {
        auto srcBeg = src;
        auto srcEnd = src + srcLength;
        auto bufSize = std::min(srcLength, m_BufferSize);
        std::vector<char32_t> buffer(bufSize);
        auto bufEnd = buffer.data() + bufSize;
        while (srcBeg != srcEnd)
        {
            auto bufIt = buffer.data();
            auto result = m_Decoder->decode(srcBeg, srcEnd, bufIt, bufEnd,
                                            sourceIsIncomplete);
            auto bufBeg = static_cast<const char32_t*>(buffer.data());
            m_Encoder->encode(bufBeg, bufIt, dst);
            if (result != DecoderResult::OK)
                break;
        }
        return srcBeg - src;
    }

    template<typename CharT, typename StringT>
    size_t Converter::doCopy(const CharT* src,
                             size_t srcLength,
                             StringT& dst,
                             bool sourceIsIncomplete)
    {
        typedef typename StringT::value_type StringChar;
        auto unitSize = m_Decoder->characterUnitSize();
        auto checkResult = m_Decoder->checkString(src, src + srcLength,
                                                  sourceIsIncomplete);
        if (checkResult.first
            && (sizeof(CharT) == 1 || sizeof(CharT) == unitSize)
            && (sizeof(StringChar) == 1 || sizeof(StringChar) == unitSize))
        {
            srcLength = checkResult.second - src;
            return copy(src, srcLength, dst, unitSize);
        }
        else
        {
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
    }

    template<typename CharT, typename StringT>
    size_t Converter::doCopyAndSwapBytes(const CharT* src,
                                         size_t srcLength,
                                         StringT& dst,
                                         bool sourceIsIncomplete)
    {
        typedef typename StringT::value_type StringChar;
        auto unitSize = m_Decoder->characterUnitSize();
        auto checkResult = m_Decoder->checkString(src, src + srcLength,
                                                  sourceIsIncomplete);
        if (checkResult.first
            && (sizeof(CharT) == 1 || sizeof(CharT) == unitSize)
            && sizeof(StringChar) == unitSize)
        {
            auto initialSize = dst.size();
            srcLength = checkResult.second - src;
            auto result = copy(src, srcLength, dst, unitSize);
            swapEndianness(&dst[initialSize], dst.size() - initialSize);
            return result;
        }
        else
        {
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
    }

    namespace {

        std::unique_ptr<AbstractDecoder> makeDecoder(Encoding_t encoding)
        {
            switch (encoding)
            {
            case Encoding::UTF_8:
                return std::unique_ptr<AbstractDecoder>(new Utf8Decoder);
            case Encoding::UTF_16_BE:
                return std::unique_ptr<AbstractDecoder>(new Utf16BEDecoder);
            case Encoding::UTF_16_LE:
                return std::unique_ptr<AbstractDecoder>(new Utf16LEDecoder);
            case Encoding::UTF_32_BE:
                return std::unique_ptr<AbstractDecoder>(new Utf32BEDecoder);
            case Encoding::UTF_32_LE:
                return std::unique_ptr<AbstractDecoder>(new Utf32LEDecoder);
            default:
                break;
            }

            auto info = getEncodingInfo(encoding);
            auto name = info ? info->name()
                             : std::to_string(int64_t(encoding));
            YSTRING_THROW("Unsupported source-encoding: " + name);
        }

        std::unique_ptr<AbstractEncoder> makeEncoder(Encoding_t encoding)
        {
            switch (encoding)
            {
            case Encoding::ASCII:
                break;
            case Encoding::UTF_8:
                return std::unique_ptr<AbstractEncoder>(new Utf8Encoder);
            case Encoding::UTF_16_BE:
                return std::unique_ptr<AbstractEncoder>(new Utf16BEEncoder);
            case Encoding::UTF_16_LE:
                return std::unique_ptr<AbstractEncoder>(new Utf16LEEncoder);
            case Encoding::UTF_32_BE:
                return std::unique_ptr<AbstractEncoder>(new Utf32BEEncoder);
            case Encoding::UTF_32_LE:
                return std::unique_ptr<AbstractEncoder>(new Utf32LEEncoder);
            default:
                break;
            }

            auto info = getEncodingInfo(encoding);
            auto name = info ? info->name()
                             : std::to_string(int64_t(encoding));
            YSTRING_THROW("Unsupported source-encoding: " + name);
        }

        template<typename CharT, typename StringT>
        size_t copy(const CharT* src,
                    size_t srcLength,
                    StringT& dst,
                    size_t charSize)
        {
            typedef typename StringT::value_type DstChar;
            auto srcMemLength = srcLength * sizeof(CharT);
            srcMemLength -= srcMemLength % charSize;
            auto dstLength = srcMemLength / sizeof(DstChar);
            auto initialDstSize = dst.size();
            dst.resize(initialDstSize + dstLength);
            std::memcpy(&dst[initialDstSize], src, srcMemLength);
            return srcMemLength / sizeof(CharT);
        }

        template <typename T>
        void swapEndianness(T* str, size_t length)
        {
            for (size_t i = 0; i < length; ++i)
                str[i] = Utilities::reverseBytes(str[i]);
        }

    }
}}
<commit_msg>Fixing things g++ doesn’t like.<commit_after>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-10-23.
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "Converter.hpp"

#include <vector>
#include "../EncodingInfo.hpp"
#include "../PrivatePlatformDetails.hpp"
#include "../YstringException.hpp"
#include "Utf8Decoder.hpp"
#include "Utf8Encoder.hpp"
#include "Utf16Decoder.hpp"
#include "Utf16Encoder.hpp"
#include "Utf32Decoder.hpp"
#include "Utf32Encoder.hpp"

namespace Ystring { namespace Conversion {

    namespace {

        const size_t DEFAULT_BUFFER_SIZE = 256;

        std::unique_ptr<AbstractDecoder> makeDecoder(Encoding_t encoding);

        std::unique_ptr<AbstractEncoder> makeEncoder(Encoding_t encoding);

        template<typename CharT, typename StringT>
        size_t copy(const CharT* src,
                    size_t srcLength,
                    StringT& dst,
                    size_t charSize);

        template <typename T>
        void swapEndianness(T* str, size_t length);

    }

    Converter::Converter(Encoding_t srcEncoding, Encoding_t dstEncoding)
        : m_Decoder(makeDecoder(srcEncoding)),
          m_Encoder(makeEncoder(dstEncoding)),
          m_ConversionType(getConversionType(srcEncoding, dstEncoding)),
          m_BufferSize(DEFAULT_BUFFER_SIZE)
    {}

    Converter::~Converter()
    {}

    size_t Converter::bufferSize() const
    {
        return m_BufferSize;
    }

    void Converter::setBufferSize(size_t value)
    {
        m_BufferSize = value;
    }

    void Converter::setErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        setDecoderErrorHandlingPolicy(value);
        setEncoderErrorHandlingPolicy(value);
    }

    ErrorHandlingPolicy_t Converter::decoderErrorHandlingPolicy() const
    {
        return m_Decoder->errorHandlingPolicy();
    }

    void Converter::setDecoderErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        m_Decoder->setErrorHandlingPolicy(value);
    }

    ErrorHandlingPolicy_t Converter::encoderErrorHandlingPolicy() const
    {
        return m_Encoder->errorHandlingPolicy();
    }

    void Converter::setEncoderErrorHandlingPolicy(ErrorHandlingPolicy_t value)
    {
        m_Encoder->setErrorHandlingPolicy(value);
    }

    void Converter::setReplacementCharacter(char32_t value)
    {
        setDecoderReplacementCharacter(value);
        setEncoderReplacementCharacter(value);
    }

    char32_t Converter::decoderReplacementCharacter() const
    {
        return m_Decoder->replacementCharacter();
    }

    void Converter::setDecoderReplacementCharacter(char32_t value)
    {
        m_Decoder->setReplacementCharacter(value);
    }

    char32_t Converter::encoderReplacementCharacter() const
    {
        return m_Encoder->replacementCharacter();
    }

    void Converter::setEncoderReplacementCharacter(char32_t value)
    {
        m_Encoder->setReplacementCharacter(value);
    }

    Encoding_t Converter::decoderEncoding() const
    {
        if (!m_Decoder)
            return Encoding::UNKNOWN;
        return m_Decoder->encoding();
    }

    Encoding_t Converter::encoderEncoding() const
    {
        if (!m_Encoder)
            return Encoding::UNKNOWN;
        return m_Encoder->encoding();
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char16_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const char32_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::u16string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::u32string& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    size_t Converter::convert(const wchar_t* source,
                              size_t sourceLength,
                              std::wstring& destination,
                              bool sourceIsIncomplete)
    {
        return convertImpl(internal_char_type_cast(source),
                           sourceLength,
                           destination,
                           sourceIsIncomplete);
    }

    Converter::ConversionType Converter::getConversionType(
            Encoding_t src, Encoding_t dst)
    {
        if (src == dst)
            return COPY;
        if ((src == Encoding::UTF_16_LE && dst == Encoding::UTF_16_BE)
            || (src == Encoding::UTF_16_BE && dst == Encoding::UTF_16_LE)
            || (src == Encoding::UTF_32_LE && dst == Encoding::UTF_32_BE)
            || (src == Encoding::UTF_32_BE && dst == Encoding::UTF_32_LE))
        {
            return SWAP_ENDIANNESS;
        }
        return CONVERT;
    }

    template<typename CharT, typename StringT>
    size_t Converter::convertImpl(const CharT* src,
                                  size_t srcLength,
                                  StringT& dst,
                                  bool sourceIsIncomplete)
    {
        switch (m_ConversionType)
        {
        case SWAP_ENDIANNESS:
            return doCopyAndSwapBytes(src, srcLength, dst, sourceIsIncomplete);
        case COPY:
            return doCopy(src, srcLength, dst, sourceIsIncomplete);
        case CONVERT:
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
        return 0;
    }

    template<typename CharT, typename StringT>
    size_t Converter::doConvert(const CharT* src,
                                size_t srcLength,
                                StringT& dst,
                                bool sourceIsIncomplete)
    {
        auto srcBeg = src;
        auto srcEnd = src + srcLength;
        auto bufSize = std::min(srcLength, m_BufferSize);
        std::vector<char32_t> buffer(bufSize);
        auto bufEnd = buffer.data() + bufSize;
        while (srcBeg != srcEnd)
        {
            auto bufIt = buffer.data();
            auto result = m_Decoder->decode(srcBeg, srcEnd, bufIt, bufEnd,
                                            sourceIsIncomplete);
            auto bufBeg = static_cast<const char32_t*>(buffer.data());
            m_Encoder->encode(bufBeg, bufIt, dst);
            if (result != DecoderResult::OK)
                break;
        }
        return srcBeg - src;
    }

    template<typename CharT, typename StringT>
    size_t Converter::doCopy(const CharT* src,
                             size_t srcLength,
                             StringT& dst,
                             bool sourceIsIncomplete)
    {
        typedef typename StringT::value_type StringChar;
        auto unitSize = m_Decoder->characterUnitSize();
        auto checkResult = m_Decoder->checkString(src, src + srcLength,
                                                  sourceIsIncomplete);
        if (checkResult.first
            && (sizeof(CharT) == 1 || sizeof(CharT) == unitSize)
            && (sizeof(StringChar) == 1 || sizeof(StringChar) == unitSize))
        {
            srcLength = checkResult.second - src;
            return copy(src, srcLength, dst, unitSize);
        }
        else
        {
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
    }

    template<typename CharT, typename StringT>
    size_t Converter::doCopyAndSwapBytes(const CharT* src,
                                         size_t srcLength,
                                         StringT& dst,
                                         bool sourceIsIncomplete)
    {
        typedef typename StringT::value_type StringChar;
        auto unitSize = m_Decoder->characterUnitSize();
        auto checkResult = m_Decoder->checkString(src, src + srcLength,
                                                  sourceIsIncomplete);
        if (checkResult.first
            && (sizeof(CharT) == 1 || sizeof(CharT) == unitSize)
            && sizeof(StringChar) == unitSize)
        {
            auto initialSize = dst.size();
            srcLength = checkResult.second - src;
            auto result = copy(src, srcLength, dst, unitSize);
            swapEndianness(&dst[initialSize], dst.size() - initialSize);
            return result;
        }
        else
        {
            return doConvert(src, srcLength, dst, sourceIsIncomplete);
        }
    }

    namespace {

        std::unique_ptr<AbstractDecoder> makeDecoder(Encoding_t encoding)
        {
            switch (encoding)
            {
            case Encoding::UTF_8:
                return std::unique_ptr<AbstractDecoder>(new Utf8Decoder);
            case Encoding::UTF_16_BE:
                return std::unique_ptr<AbstractDecoder>(new Utf16BEDecoder);
            case Encoding::UTF_16_LE:
                return std::unique_ptr<AbstractDecoder>(new Utf16LEDecoder);
            case Encoding::UTF_32_BE:
                return std::unique_ptr<AbstractDecoder>(new Utf32BEDecoder);
            case Encoding::UTF_32_LE:
                return std::unique_ptr<AbstractDecoder>(new Utf32LEDecoder);
            default:
                break;
            }

            auto info = getEncodingInfo(encoding);
            auto name = info ? info->name()
                             : std::to_string(int64_t(encoding));
            YSTRING_THROW("Unsupported source-encoding: " + name);
        }

        std::unique_ptr<AbstractEncoder> makeEncoder(Encoding_t encoding)
        {
            switch (encoding)
            {
            case Encoding::ASCII:
                break;
            case Encoding::UTF_8:
                return std::unique_ptr<AbstractEncoder>(new Utf8Encoder);
            case Encoding::UTF_16_BE:
                return std::unique_ptr<AbstractEncoder>(new Utf16BEEncoder);
            case Encoding::UTF_16_LE:
                return std::unique_ptr<AbstractEncoder>(new Utf16LEEncoder);
            case Encoding::UTF_32_BE:
                return std::unique_ptr<AbstractEncoder>(new Utf32BEEncoder);
            case Encoding::UTF_32_LE:
                return std::unique_ptr<AbstractEncoder>(new Utf32LEEncoder);
            default:
                break;
            }

            auto info = getEncodingInfo(encoding);
            auto name = info ? info->name()
                             : std::to_string(int64_t(encoding));
            YSTRING_THROW("Unsupported source-encoding: " + name);
        }

        template<typename CharT, typename StringT>
        size_t copy(const CharT* src,
                    size_t srcLength,
                    StringT& dst,
                    size_t charSize)
        {
            typedef typename StringT::value_type DstChar;
            auto srcMemLength = srcLength * sizeof(CharT);
            srcMemLength -= srcMemLength % charSize;
            auto dstLength = srcMemLength / sizeof(DstChar);
            auto initialDstSize = dst.size();
            dst.resize(initialDstSize + dstLength);
            memcpy(&dst[initialDstSize], src, srcMemLength);
            return srcMemLength / sizeof(CharT);
        }

        template <typename T>
        void swapEndianness(T* str, size_t length)
        {
            for (size_t i = 0; i < length; ++i)
                str[i] = Utilities::reverseBytes(str[i]);
        }

    }
}}
<|endoftext|>


<commit_before>//==============================================================================
// Single cell simulation view simulation
//==============================================================================

#include "singlecellsimulationviewcontentswidget.h"
#include "singlecellsimulationviewinformationsimulationwidget.h"
#include "singlecellsimulationviewinformationwidget.h"
#include "singlecellsimulationviewsimulation.h"
#include "singlecellsimulationviewwidget.h"
#include "thread.h"

//==============================================================================

#include "qwt_slider.h"

//==============================================================================

namespace OpenCOR {
namespace SingleCellSimulationView {

//==============================================================================

SingleCellSimulationViewSimulationData::SingleCellSimulationViewSimulationData() :
    mDelay(0),
    mStartingPoint(0.0),
    mEndingPoint(1000.0),
    mPointInterval(1.0)
{
}

//==============================================================================

int SingleCellSimulationViewSimulationData::delay() const
{
    // Return our delay

    return mDelay;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setDelay(const int &pDelay)
{
    // Set our delay

    mDelay = pDelay;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::startingPoint() const
{
    // Return our starting point

    return mStartingPoint;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setStartingPoint(const double &pStartingPoint)
{
    // Set our starting point

    mStartingPoint = pStartingPoint;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::endingPoint() const
{
    // Return our ending point

    return mEndingPoint;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setEndingPoint(const double &pEndingPoint)
{
    // Set our ending point

    mEndingPoint = pEndingPoint;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::pointInterval() const
{
    // Return our point interval

    return mPointInterval;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setPointInterval(const double &pPointInterval)
{
    // Set our point interval

    mPointInterval = pPointInterval;
}

//==============================================================================

SingleCellSimulationViewSimulation::SingleCellSimulationViewSimulation(const QString &pFileName) :
    mWorkerThread(0),
    mWorker(0),
    mFileName(pFileName),
    mData(new SingleCellSimulationViewSimulationData())
{
}

//==============================================================================

SingleCellSimulationViewSimulation::~SingleCellSimulationViewSimulation()
{
    // Stop our worker (just in case...)

    stop();
}

//==============================================================================

QString SingleCellSimulationViewSimulation::fileName() const
{
    // Retrieve and return our file name

    return mFileName;
}

//==============================================================================

SingleCellSimulationViewSimulationWorker::Status SingleCellSimulationViewSimulation::workerStatus() const
{
    // Return the status of our worker, if active

    return (mWorkerThread && mWorker)?
               mWorker->status():
               SingleCellSimulationViewSimulationWorker::Unknown;
}

//==============================================================================

double SingleCellSimulationViewSimulation::workerProgress() const
{
    // Return the progress of our worker, if active

    return (mWorkerThread && mWorker)?
               mWorker->progress():
               0.0;
}

//==============================================================================

void SingleCellSimulationViewSimulation::setData(SingleCellSimulationViewWidget *pGui)
{
    // Set our data using information from the GUI

    // Set our delay

    setDelay(pGui->delayValue());

    // Update some of our data from our GUI's simulation widget

    SingleCellSimulationViewInformationSimulationWidget *simulationWidget = pGui->contentsWidget()->informationWidget()->simulationWidget();

    mData->setStartingPoint(simulationWidget->startingPoint());
    mData->setEndingPoint(simulationWidget->endingPoint());
    mData->setPointInterval(simulationWidget->pointInterval());
}

//==============================================================================

void SingleCellSimulationViewSimulation::setDelay(const int &pDelay)
{
    // Set our delay

    mData->setDelay(pDelay);
}

//==============================================================================

void SingleCellSimulationViewSimulation::run()
{
    // Initialise our worker, if not active

    if (!mWorkerThread && !mWorker) {
        // First, check that our simulation settings we were given are sound

        bool simulationSettingsOk = false;

        if (mData->startingPoint() == mData->endingPoint())
            emit error(tr("the starting and ending points cannot have the same value"));
        else if (mData->pointInterval() == 0)
            emit error(tr("the point interval cannot be equal to zero"));
        else if (   (mData->startingPoint() < mData->endingPoint())
                 && (mData->pointInterval() < 0))
            emit error(tr("the ending point is greater than the starting point, so the point interval should be greater than zero"));
        else if (   (mData->startingPoint() > mData->endingPoint())
                 && (mData->pointInterval() > 0))
            emit error(tr("the ending point is smaller than the starting point, so the point interval should be smaller than zero"));
        else
            simulationSettingsOk = true;

        if (!simulationSettingsOk)
            // Something wrong with our simulation settings, so...

            return;

        // Create our worker and the thread in which it will work

        mWorkerThread = new Core::Thread();
        mWorker       = new SingleCellSimulationViewSimulationWorker(mData);

        // Check that the worker and its thread have been properly created

        if (!mWorkerThread || !mWorker) {
            delete mWorkerThread;
            delete mWorker;

            mWorkerThread = 0;
            mWorker       = 0;

            emit error(tr("the simulation worker and/or its thread could not be initialised"));

            return;
        }

        // Move our worker to its thread

        mWorker->moveToThread(mWorkerThread);

        // Create a few connections

        connect(mWorkerThread, SIGNAL(started()),
                mWorker, SLOT(run()));

        connect(mWorker, SIGNAL(running()),
                this, SIGNAL(running()));
        connect(mWorker, SIGNAL(pausing()),
                this, SIGNAL(pausing()));

        connect(mWorker, SIGNAL(progress(const double &)),
                this, SIGNAL(progress(const double &)));

        connect(mWorker, SIGNAL(finished(const int &)),
                this, SLOT(finished(const int &)));

        connect(mWorker, SIGNAL(finished(const int &)),
                mWorkerThread, SLOT(quit()));
        connect(mWorker, SIGNAL(finished(const int &)),
                mWorker, SLOT(deleteLater()));

        connect(mWorkerThread, SIGNAL(finished()),
                mWorkerThread, SLOT(deleteLater()));

        // Start our worker thread

        mWorkerThread->start();
    } else {
        // Our worker is already active, so just run it
        // Note: it might have been paused in between, in which case it will
        //       automatically resume itself...

        mWorker->run();
    }
}

//==============================================================================

void SingleCellSimulationViewSimulation::pause()
{
    // Ask our worker to pause, if active

    if (mWorkerThread && mWorker)
        mWorker->pause();
}

//==============================================================================

void SingleCellSimulationViewSimulation::stop()
{
    // Ask our worker to stop, if active

    if (mWorkerThread && mWorker)
        mWorker->stop();
}

//==============================================================================

void SingleCellSimulationViewSimulation::finished(const int &pElapsedTime)
{
    // Our worker is done (and it will get deleted and everything), so...

    mWorkerThread = 0;
    mWorker       = 0;

    // Let people know that we have stopped

    emit stopped(pElapsedTime);
}

//==============================================================================

}   // namespace SingleCellSimulationView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Fixed a memory leak.<commit_after>//==============================================================================
// Single cell simulation view simulation
//==============================================================================

#include "singlecellsimulationviewcontentswidget.h"
#include "singlecellsimulationviewinformationsimulationwidget.h"
#include "singlecellsimulationviewinformationwidget.h"
#include "singlecellsimulationviewsimulation.h"
#include "singlecellsimulationviewwidget.h"
#include "thread.h"

//==============================================================================

#include "qwt_slider.h"

//==============================================================================

namespace OpenCOR {
namespace SingleCellSimulationView {

//==============================================================================

SingleCellSimulationViewSimulationData::SingleCellSimulationViewSimulationData() :
    mDelay(0),
    mStartingPoint(0.0),
    mEndingPoint(1000.0),
    mPointInterval(1.0)
{
}

//==============================================================================

int SingleCellSimulationViewSimulationData::delay() const
{
    // Return our delay

    return mDelay;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setDelay(const int &pDelay)
{
    // Set our delay

    mDelay = pDelay;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::startingPoint() const
{
    // Return our starting point

    return mStartingPoint;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setStartingPoint(const double &pStartingPoint)
{
    // Set our starting point

    mStartingPoint = pStartingPoint;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::endingPoint() const
{
    // Return our ending point

    return mEndingPoint;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setEndingPoint(const double &pEndingPoint)
{
    // Set our ending point

    mEndingPoint = pEndingPoint;
}

//==============================================================================

double SingleCellSimulationViewSimulationData::pointInterval() const
{
    // Return our point interval

    return mPointInterval;
}

//==============================================================================

void SingleCellSimulationViewSimulationData::setPointInterval(const double &pPointInterval)
{
    // Set our point interval

    mPointInterval = pPointInterval;
}

//==============================================================================

SingleCellSimulationViewSimulation::SingleCellSimulationViewSimulation(const QString &pFileName) :
    mWorkerThread(0),
    mWorker(0),
    mFileName(pFileName),
    mData(new SingleCellSimulationViewSimulationData())
{
}

//==============================================================================

SingleCellSimulationViewSimulation::~SingleCellSimulationViewSimulation()
{
    // Stop our worker (just in case...)

    stop();

    // Delete some internal objects

    delete mData;
}

//==============================================================================

QString SingleCellSimulationViewSimulation::fileName() const
{
    // Retrieve and return our file name

    return mFileName;
}

//==============================================================================

SingleCellSimulationViewSimulationWorker::Status SingleCellSimulationViewSimulation::workerStatus() const
{
    // Return the status of our worker, if active

    return (mWorkerThread && mWorker)?
               mWorker->status():
               SingleCellSimulationViewSimulationWorker::Unknown;
}

//==============================================================================

double SingleCellSimulationViewSimulation::workerProgress() const
{
    // Return the progress of our worker, if active

    return (mWorkerThread && mWorker)?
               mWorker->progress():
               0.0;
}

//==============================================================================

void SingleCellSimulationViewSimulation::setData(SingleCellSimulationViewWidget *pGui)
{
    // Set our data using information from the GUI

    // Set our delay

    setDelay(pGui->delayValue());

    // Update some of our data from our GUI's simulation widget

    SingleCellSimulationViewInformationSimulationWidget *simulationWidget = pGui->contentsWidget()->informationWidget()->simulationWidget();

    mData->setStartingPoint(simulationWidget->startingPoint());
    mData->setEndingPoint(simulationWidget->endingPoint());
    mData->setPointInterval(simulationWidget->pointInterval());
}

//==============================================================================

void SingleCellSimulationViewSimulation::setDelay(const int &pDelay)
{
    // Set our delay

    mData->setDelay(pDelay);
}

//==============================================================================

void SingleCellSimulationViewSimulation::run()
{
    // Initialise our worker, if not active

    if (!mWorkerThread && !mWorker) {
        // First, check that our simulation settings we were given are sound

        bool simulationSettingsOk = false;

        if (mData->startingPoint() == mData->endingPoint())
            emit error(tr("the starting and ending points cannot have the same value"));
        else if (mData->pointInterval() == 0)
            emit error(tr("the point interval cannot be equal to zero"));
        else if (   (mData->startingPoint() < mData->endingPoint())
                 && (mData->pointInterval() < 0))
            emit error(tr("the ending point is greater than the starting point, so the point interval should be greater than zero"));
        else if (   (mData->startingPoint() > mData->endingPoint())
                 && (mData->pointInterval() > 0))
            emit error(tr("the ending point is smaller than the starting point, so the point interval should be smaller than zero"));
        else
            simulationSettingsOk = true;

        if (!simulationSettingsOk)
            // Something wrong with our simulation settings, so...

            return;

        // Create our worker and the thread in which it will work

        mWorkerThread = new Core::Thread();
        mWorker       = new SingleCellSimulationViewSimulationWorker(mData);

        // Check that the worker and its thread have been properly created

        if (!mWorkerThread || !mWorker) {
            delete mWorkerThread;
            delete mWorker;

            mWorkerThread = 0;
            mWorker       = 0;

            emit error(tr("the simulation worker and/or its thread could not be initialised"));

            return;
        }

        // Move our worker to its thread

        mWorker->moveToThread(mWorkerThread);

        // Create a few connections

        connect(mWorkerThread, SIGNAL(started()),
                mWorker, SLOT(run()));

        connect(mWorker, SIGNAL(running()),
                this, SIGNAL(running()));
        connect(mWorker, SIGNAL(pausing()),
                this, SIGNAL(pausing()));

        connect(mWorker, SIGNAL(progress(const double &)),
                this, SIGNAL(progress(const double &)));

        connect(mWorker, SIGNAL(finished(const int &)),
                this, SLOT(finished(const int &)));

        connect(mWorker, SIGNAL(finished(const int &)),
                mWorkerThread, SLOT(quit()));
        connect(mWorker, SIGNAL(finished(const int &)),
                mWorker, SLOT(deleteLater()));

        connect(mWorkerThread, SIGNAL(finished()),
                mWorkerThread, SLOT(deleteLater()));

        // Start our worker thread

        mWorkerThread->start();
    } else {
        // Our worker is already active, so just run it
        // Note: it might have been paused in between, in which case it will
        //       automatically resume itself...

        mWorker->run();
    }
}

//==============================================================================

void SingleCellSimulationViewSimulation::pause()
{
    // Ask our worker to pause, if active

    if (mWorkerThread && mWorker)
        mWorker->pause();
}

//==============================================================================

void SingleCellSimulationViewSimulation::stop()
{
    // Ask our worker to stop, if active

    if (mWorkerThread && mWorker)
        mWorker->stop();
}

//==============================================================================

void SingleCellSimulationViewSimulation::finished(const int &pElapsedTime)
{
    // Our worker is done (and it will get deleted and everything), so...

    mWorkerThread = 0;
    mWorker       = 0;

    // Let people know that we have stopped

    emit stopped(pElapsedTime);
}

//==============================================================================

}   // namespace SingleCellSimulationView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>#include <stdio.h>

#include <Halide.h>

#include <algorithm>
#include <iostream>

using namespace Halide;
using namespace Halide::Internal;

Scope<Expr> scope;
Scope<int> linearity;

Expr x = Variable::make(Int(32), "x");
Expr y = Variable::make(Int(32), "y");

constexpr int N = 100;
Expr v[N];

void fill_scope() {
    // e.g. let y = 4*x
    scope.push("y", 4*x);
    linearity.push("y", Linearity::Linear);

    for (int i = 0; i < N; ++i) {
        // e.g. let x0 = x*x
        //      let x1 = x0*x0
        //      let x2 = x1*x1
        //      ...
        std::string vi = "v" + int_to_string(i);
        v[i] = Variable::make(Int(32), vi);
        if (i == 0) {
            scope.push(vi, x*x);
        } else {
            scope.push(vi, v[i-1]*v[i-1]);
        }
        linearity.push(vi, Linearity::NonLinear);
    }
}

bool test_branches_in_var() {
    // Test basic functionality of branches_in_var
    Stmt s1 = IfThenElse::make(x < 0, Evaluate::make(0));
    Expr e1 = Select::make(x < 0, 0, x);
    Expr e2 = clamp(x, 0, 100);

    if (!branches_linearly_in_var(s1, "x", linearity)) {
        std::cout << "Expected to branch in x:\n" << s1;
        return false;
    }

    if (!branches_linearly_in_var(e1, "x", linearity)) {
        std::cout << "Expected to branch in x: " << e1 << "\n";
        return false;
    }

    if (branches_linearly_in_var(e2, "x", linearity)) {
        std::cout << "Expected not to branch in x: " << e2 << "\n";
        return false;
    }

    if (!branches_linearly_in_var(e2, "x", linearity, true)) {
        std::cout << "Expected to branch in x: " << e2 << "\n";
        return false;
    }

    // Test branches_in_var uses linearity correctly.
    Stmt s2 = IfThenElse::make(y < 0, Evaluate::make(0));
    Expr e3 = Select::make(y < 0, 0, x);

    if (!branches_linearly_in_var(s2, "x", linearity)) {
        std::cout << "Expected to branch in x:\n" << s2;
        return false;
    }

    if (!branches_linearly_in_var(e3, "x", linearity)) {
        std::cout << "Expected to branch in x: " << e3 << "\n";
        return false;
    }

    // Test branches_in_var doesn't explode with deeply nested linearitys.
    Expr vN = v[N-1];
    Stmt s3 = IfThenElse::make(vN < 0, Evaluate::make(0));

    if (branches_linearly_in_var(s3, "x", linearity)) {
        std::cout << "Expected not to branch in x:\n" << s3;
        return false;
    }

    return true;
}

bool test_normalize_branches() {
    Scope<Interval> bounds;
    Scope<int> free_vars;
    free_vars.push("x", 0);

    Stmt then_case = Evaluate::make(0);
    Stmt else_case = Evaluate::make(1);

    Stmt s1 = IfThenElse::make(x != 0 && x != 1, then_case, else_case);
    Stmt s1_ans1 = IfThenElse::make(x < 1, then_case, IfThenElse::make(1 < x, then_case, else_case));
    Stmt s1_nrm = normalize_branch_conditions(s1, "x", scope, bounds, free_vars);
    Stmt s1_ans = IfThenElse::make(
        x < 0, then_case, IfThenElse::make(
            0 < x, IfThenElse::make(1 < x, then_case, else_case), else_case));

    if (!equal(s1_nrm, s1_ans)) {
        std::cout << "Normalized:\n" << s1_nrm
                  << "Expected:\n" << s1_ans;
        return false;
    }

    Expr e1 = select(x != 0 && x != 1, 0, 1);
    Expr e1_ans1 = select(x < 1, 0, select(1 < x, 0, 1));
    Expr e1_nrm = normalize_branch_conditions(e1, "x", scope, bounds, free_vars);
    Expr e1_ans = select(x < 0, 0, select(0 < x, select(1 < x, 0, 1), 1));

    if (!equal(e1_nrm, e1_ans)) {
        std::cout << "Normalized: " << e1_nrm << "\n"
                  << "Expected: " << e1_ans << "\n";
        return false;
    }

    return true;
}

int main() {
    fill_scope();

    if (!test_branches_in_var()) {
        std::cout << "Failure.\n";
        return -1;
    }

    if (!test_normalize_branches()) {
        std::cout << "Failure.\n";
        return -1;
    }

    std::cout << "Success!\n";
    return 0;
}
<commit_msg>Added test to check the results of branches_linearly_in_vars to demonstrate the correctness of the changes in the last commit.<commit_after>#include <stdio.h>

#include <Halide.h>

#include <algorithm>
#include <iostream>

using namespace Halide;
using namespace Halide::Internal;

Scope<Expr> scope;
Scope<int> linearity;

Expr x = Variable::make(Int(32), "x");
Expr y = Variable::make(Int(32), "y");
Expr z = Variable::make(Int(32), "z");

constexpr int N = 100;
Expr v[N];

void fill_scope() {
    // e.g. let y = 4*x
    scope.push("y", 4*x);
    linearity.push("y", Linearity::Linear);

    for (int i = 0; i < N; ++i) {
        // e.g. let x0 = x*x
        //      let x1 = x0*x0
        //      let x2 = x1*x1
        //      ...
        std::string vi = "v" + int_to_string(i);
        v[i] = Variable::make(Int(32), vi);
        if (i == 0) {
            scope.push(vi, x*x);
        } else {
            scope.push(vi, v[i-1]*v[i-1]);
        }
        linearity.push(vi, Linearity::NonLinear);
    }
}

bool test_branches_in_var() {
    // Test basic functionality of branches_in_var
    Stmt s1 = IfThenElse::make(x < 0, Evaluate::make(0));
    Expr e1 = Select::make(x < 0, 0, x);
    Expr e2 = clamp(x, 0, 100);

    if (!branches_linearly_in_var(s1, "x", linearity)) {
        std::cout << "Expected to branch in x:\n" << s1;
        return false;
    }

    if (!branches_linearly_in_var(e1, "x", linearity)) {
        std::cout << "Expected to branch in x: " << e1 << "\n";
        return false;
    }

    if (branches_linearly_in_var(e2, "x", linearity)) {
        std::cout << "Expected not to branch in x: " << e2 << "\n";
        return false;
    }

    if (!branches_linearly_in_var(e2, "x", linearity, true)) {
        std::cout << "Expected to branch in x: " << e2 << "\n";
        return false;
    }

    // Test branches_in_var uses linearity correctly.
    Stmt s2 = IfThenElse::make(y < 0, Evaluate::make(0));
    Expr e3 = Select::make(y < 0, 0, x);

    if (!branches_linearly_in_var(s2, "x", linearity)) {
        std::cout << "Expected to branch in x:\n" << s2;
        return false;
    }

    if (!branches_linearly_in_var(e3, "x", linearity)) {
        std::cout << "Expected to branch in x: " << e3 << "\n";
        return false;
    }

    // Test branches_in_var doesn't explode with deeply nested linearitys.
    Expr vN = v[N-1];
    Stmt s3 = IfThenElse::make(vN < 0, Evaluate::make(0));

    if (branches_linearly_in_var(s3, "x", linearity)) {
        std::cout << "Expected not to branch in x:\n" << s3;
        return false;
    }

    Stmt s4 = LetStmt::make("z", e3, For::make("w", 0, 10, For::Serial, Store::make("s", 0, z)));

    if (!branches_linearly_in_var(s4, "x", linearity)) {
        std::cout << "Expected to branch in x: " << s4 << "\n";
        return false;
    }

    return true;
}

bool test_normalize_branches() {
    Scope<Interval> bounds;
    Scope<int> free_vars;
    free_vars.push("x", 0);

    Stmt then_case = Evaluate::make(0);
    Stmt else_case = Evaluate::make(1);

    Stmt s1 = IfThenElse::make(x != 0 && x != 1, then_case, else_case);
    Stmt s1_ans1 = IfThenElse::make(x < 1, then_case, IfThenElse::make(1 < x, then_case, else_case));
    Stmt s1_nrm = normalize_branch_conditions(s1, "x", scope, bounds, free_vars);
    Stmt s1_ans = IfThenElse::make(
        x < 0, then_case, IfThenElse::make(
            0 < x, IfThenElse::make(1 < x, then_case, else_case), else_case));

    if (!equal(s1_nrm, s1_ans)) {
        std::cout << "Normalized:\n" << s1_nrm
                  << "Expected:\n" << s1_ans;
        return false;
    }

    Expr e1 = select(x != 0 && x != 1, 0, 1);
    Expr e1_ans1 = select(x < 1, 0, select(1 < x, 0, 1));
    Expr e1_nrm = normalize_branch_conditions(e1, "x", scope, bounds, free_vars);
    Expr e1_ans = select(x < 0, 0, select(0 < x, select(1 < x, 0, 1), 1));

    if (!equal(e1_nrm, e1_ans)) {
        std::cout << "Normalized: " << e1_nrm << "\n"
                  << "Expected: " << e1_ans << "\n";
        return false;
    }

    return true;
}

int main() {
    fill_scope();

    if (!test_branches_in_var()) {
        std::cout << "Failure.\n";
        return -1;
    }

    if (!test_normalize_branches()) {
        std::cout << "Failure.\n";
        return -1;
    }

    std::cout << "Success!\n";
    return 0;
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed 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 <fstream>
#include <sstream>

#include <gflags/gflags.h>
#include <gtest/gtest.h>

DEFINE_string(
    generated_file_path, "",
    "path to the directory containing generated files compiler_test.grpc.pb.h"
    "and compiler_test_mock.grpc.pb.h");

const char kGoldenFilePath[] = "test/cpp/codegen/compiler_test_golden";
const char kMockGoldenFilePath[] = "test/cpp/codegen/compiler_test_mock_golden";

void run_test(std::basic_string<char> generated_file,
              std::basic_string<char> golden_file) {
  std::ifstream generated(generated_file);
  std::ifstream golden(golden_file);

  ASSERT_TRUE(generated.good());
  ASSERT_TRUE(golden.good());

  std::ostringstream gen_oss;
  std::ostringstream gold_oss;
  gen_oss << generated.rdbuf();
  gold_oss << golden.rdbuf();
  EXPECT_EQ(gold_oss.str(), gen_oss.str());

  generated.close();
  golden.close();
}

TEST(GoldenFileTest, TestGeneratedFile) {
  run_test(FLAGS_generated_file_path + "compiler_test.grpc.pb.h",
           kGoldenFilePath);
}

TEST(GoldenMockFileTest, TestGeneratedMockFile) {
  run_test(FLAGS_generated_file_path + "compiler_test_mock.grpc.pb.h",
           kMockGoldenFilePath);
}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  ::google::ParseCommandLineFlags(&argc, &argv, true);
  if (FLAGS_generated_file_path.empty()) {
    FLAGS_generated_file_path = "gens/src/proto/grpc/testing/";
  }
  if (FLAGS_generated_file_path.back() != '/')
    FLAGS_generated_file_path.append("/");
  return RUN_ALL_TESTS();
}
<commit_msg>Use the same ParseCommandLineFlags for golden file test that is used in other test binaries<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed 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 <fstream>
#include <sstream>

#include <gflags/gflags.h>
#include <gtest/gtest.h>

// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;

DEFINE_string(
    generated_file_path, "",
    "path to the directory containing generated files compiler_test.grpc.pb.h"
    "and compiler_test_mock.grpc.pb.h");

const char kGoldenFilePath[] = "test/cpp/codegen/compiler_test_golden";
const char kMockGoldenFilePath[] = "test/cpp/codegen/compiler_test_mock_golden";

void run_test(std::basic_string<char> generated_file,
              std::basic_string<char> golden_file) {
  std::ifstream generated(generated_file);
  std::ifstream golden(golden_file);

  ASSERT_TRUE(generated.good());
  ASSERT_TRUE(golden.good());

  std::ostringstream gen_oss;
  std::ostringstream gold_oss;
  gen_oss << generated.rdbuf();
  gold_oss << golden.rdbuf();
  EXPECT_EQ(gold_oss.str(), gen_oss.str());

  generated.close();
  golden.close();
}

TEST(GoldenFileTest, TestGeneratedFile) {
  run_test(FLAGS_generated_file_path + "compiler_test.grpc.pb.h",
           kGoldenFilePath);
}

TEST(GoldenMockFileTest, TestGeneratedMockFile) {
  run_test(FLAGS_generated_file_path + "compiler_test_mock.grpc.pb.h",
           kMockGoldenFilePath);
}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  ParseCommandLineFlags(&argc, &argv, true);
  if (FLAGS_generated_file_path.empty()) {
    FLAGS_generated_file_path = "gens/src/proto/grpc/testing/";
  }
  if (FLAGS_generated_file_path.back() != '/')
    FLAGS_generated_file_path.append("/");
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2017-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Url.h"
#include "Filename.h"
#include "medialibrary/filesystem/Errors.h"

#include <stdexcept>
#include <cstring>
#include <algorithm>

namespace
{
inline bool isSafe( char c )
{
    return strchr( ".-_~/"
#ifdef _WIN32
                    "\\"
#endif
                   , c ) != nullptr;
}

std::string::const_iterator encodeSegment( std::string& res,
                                           std::string::const_iterator begin,
                                           std::string::const_iterator end,
                                           const char* extraChars )
{
    for ( auto i = begin; i < end; ++i )
    {
        // This must be an unsigned char for the bits operations below to work.
        // auto will yield a signed char here.
        const unsigned char c = *i;
        if ( ( c >= 32 && c <= 126 ) && (
                 ( c >= 'a' && c <= 'z' ) ||
                 ( c >= 'A' && c <= 'Z' ) ||
                 ( c >= '0' && c <= '9' ) ||
                 isSafe( c ) == true ||
                 ( extraChars != nullptr && strchr( extraChars, c ) != nullptr ) )
             )
        {
            res.push_back( c );
        }
        else
            res.append({ '%', "0123456789ABCDEF"[c >> 4], "0123456789ABCDEF"[c & 0xF] });
    }
    return end;
}

inline uint16_t charToVal( char c )
{
    if ( c >= '0' && c <= '9' )
        return c - '0';
    if ( c >= 'a' && c <= 'f' )
        return c - 'a' + 10;
    if ( c >= 'A' && c <= 'F' )
        return c - 'A' + 10;
    throw std::runtime_error( "Incomplete/invalid character sequence" );
}

}

namespace medialibrary
{
namespace utils
{
namespace url
{

parts split( const std::string& url )
{
    parts res{};
    auto schemePos = url.find( "://" );
    if ( schemePos == std::string::npos )
    {
        res.path = url;
        return res;
    }
    std::copy( url.cbegin(), url.cbegin() + schemePos,
               std::back_inserter( res.scheme ) );

    if ( res.scheme == "file" )
    {
        std::copy( url.cbegin() + schemePos + 3, url.cend(),
                   std::back_inserter( res.path ) );
        return res;
    }

    const auto authorityBegin = url.cbegin() + schemePos + 3;
    auto authorityEnd = std::find( authorityBegin, url.cend(), '/' );
    auto queryBegin = std::find( authorityBegin, url.cend(), '?' );
    const auto fragmentBegin = std::find( authorityBegin, url.cend(), '#' );

    /*
     * The fragment must come after the query parameters. Since we use both
     * values at a later point, sanitize them now.
     */
    if ( fragmentBegin != url.cend() && queryBegin != url.cend() &&
         fragmentBegin < queryBegin )
    {
        queryBegin = url.cend();
    }

    /* RFC 3986 §3.2:
     * The authority component is preceded by a double slash ("//") and is
     * terminated by the next slash ("/"), question mark ("?"), or number
     * sign ("#") character, or by the end of the URI.
     */
    if ( authorityEnd == url.cend() )
    {
        if ( queryBegin != url.cend() )
            authorityEnd = queryBegin;
        else
            authorityEnd = fragmentBegin;
    }
    else
    {
        if ( queryBegin != url.cend() && queryBegin < authorityEnd )
            authorityEnd = queryBegin;
        if ( fragmentBegin != url.cend() && fragmentBegin < authorityEnd )
            authorityEnd = fragmentBegin;
    }

    {
        /* Split the authority into its actual components */
        auto userInfoEnd = std::find( authorityBegin, authorityEnd, '@' );
        if ( userInfoEnd != authorityEnd )
        {
            std::copy( authorityBegin, userInfoEnd,
                       std::back_inserter( res.userInfo ) );
            /* Skip the '@' when copying the host */
            ++userInfoEnd;
            res.hostMarker = true;
        }
        else
            userInfoEnd = authorityBegin;

        auto portBegin = std::find( userInfoEnd, authorityEnd, ':' );
        if ( portBegin != authorityEnd )
            std::copy( portBegin + 1, authorityEnd, std::back_inserter( res.port ) );
        else
            portBegin = authorityEnd;
        std::copy( userInfoEnd, portBegin, std::back_inserter( res.host ) );

    }
    if ( authorityEnd == url.cend() )
    {
        /*
         * If we don't have a clear end for the authority segment, it means the
         * end is the url end, so we don't have anything else to split
         */
        return res;
    }

    auto pathEnd = queryBegin != url.cend() ? queryBegin : fragmentBegin;
    std::copy( authorityEnd, pathEnd,
               std::back_inserter( res.path ) );
    if ( queryBegin != url.cend() )
    {
        std::copy( queryBegin + 1,
                   fragmentBegin != url.cend() ? fragmentBegin : url.cend(),
                   std::back_inserter( res.query ) );
    }
    if ( fragmentBegin != url.cend() )
    {
        std::copy( fragmentBegin + 1, url.cend(),
                   std::back_inserter( res.fragments ) );
    }
    return res;
}

std::string decode( const std::string& str )
{
    std::string res;
    res.reserve( str.size() );
    auto it = str.cbegin();
    auto ite = str.cend();
    for ( ; it != ite; ++it )
    {
        if ( *it == '%' )
        {
            ++it;
            const auto c1 = charToVal( *it );
            const auto c2 = charToVal( *( it + 1 ) );
            auto val = c1 * 16 + c2;
            res.push_back( static_cast<std::string::value_type>( val ) );
            ++it;
        }
        else
            res.push_back( *it );
    }
    return res;
}

std::string encode( const std::string& str )
{
    auto parts = split( str );
    std::string res{};
    res.reserve( str.length() );
    /*
     * If the file is a local path, we need to encode everything as the
     * characters won't have any URL related meaning
     */
    if ( parts.scheme == "file" || parts.scheme.empty() == true )
    {
        if ( parts.scheme.empty() == false )
            res += "file://";
        auto pathBegin = parts.path.cbegin();
#ifdef _WIN32
        if ( *pathBegin == '/' && isalpha( *(pathBegin + 1) ) && *(pathBegin + 2) == ':' )
        {
            // Don't encode the ':' after the drive letter.
            // All other ':' need to be encoded, there are not allowed in a file path
            // on windows, but they might appear in urls
            std::copy( pathBegin, pathBegin + 3, std::back_inserter( res ) );
            pathBegin += 3;
        }
#endif
        encodeSegment( res, pathBegin, parts.path.cend(), nullptr );
        return res;
    }
    /*
     * We already accept any character in ".-_~/" through isSafe(), but we need
     * to accept more depending on the URL segments:
     */
    encodeSegment( res, parts.scheme.cbegin(), parts.scheme.cend(), "+" );
    res += "://";
    if ( parts.userInfo.empty() == false )
    {
        encodeSegment( res, parts.userInfo.cbegin(), parts.userInfo.cend(),
                       "!$&'()*+,;=:" );
    }
    if ( parts.hostMarker == true )
        res += '@';
    encodeSegment( res, parts.host.cbegin(), parts.host.cend(), "[]" );
    if ( parts.port.empty() == false )
    {
        res += ':';
        res += parts.port;
    }

    encodeSegment( res, parts.path.cbegin(), parts.path.cend(), "!$&'()*+,;=:@" );

    if ( parts.query.empty() == false )
    {
        res += '?';
        encodeSegment( res, parts.query.cbegin(), parts.query.cend(),
                       "!$&'()*+,;=:@?" );
    }
    if ( parts.fragments.empty() == false )
    {
        res += '#';
        encodeSegment( res, parts.query.cbegin(), parts.query.cend(),
                       "!$&'()*+,;=:@?" );
    }
    return res;
}

std::string stripScheme( const std::string& mrl )
{
    auto pos = mrl.find( "://" );
    if ( pos == std::string::npos )
        throw fs::errors::UnhandledScheme( "<empty scheme>" );
    return mrl.substr( pos + 3 );
}

std::string scheme( const std::string& mrl )
{
    auto pos = mrl.find( "://" );
    if ( pos == std::string::npos )
        throw fs::errors::UnhandledScheme( "<empty scheme>" );
    return mrl.substr( 0, pos + 3 );
}

#ifndef _WIN32

std::string toLocalPath( const std::string& mrl )
{
    if ( mrl.compare( 0, 7, "file://" ) != 0 )
        throw fs::errors::UnhandledScheme( scheme( mrl ) );
    return utils::url::decode( mrl.substr( 7 ) );
}

#else

std::string toLocalPath( const std::string& mrl )
{
    if ( mrl.compare( 0, 7, "file://" ) != 0 )
        throw fs::errors::UnhandledScheme( utils::url::scheme( mrl ) );
    auto path = mrl.substr( 7 );
    // If the path is a local path (ie. X:\path\to and not \\path\to) skip the
    // initial backslash, as it is only part of our representation, and not
    // understood by the win32 API functions
    // Note that the initial '/' (after the 2 forward slashes from the scheme)
    // is not a backslash, as it is not a path separator, so do not use
    // DIR_SEPARATOR_CHAR here.
    if ( path[0] == '/' && isalpha( path[1] ) )
        path.erase( 0, 1 );
    std::replace( begin( path ), end( path ), '/', '\\' );
    return utils::url::decode( path );
}

#endif

bool schemeIs( const std::string& scheme, const std::string& mrl )
{
    return mrl.compare( 0, scheme.size(), scheme ) == 0;
}

std::string path( const std::string &mrl )
{
    auto schemelessMrl = stripScheme( mrl );
    auto host = utils::file::firstFolder( schemelessMrl );
    return utils::file::removePath( schemelessMrl, host );
}

}
}
}
<commit_msg>utils: Fix variable shawoding outer function<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2017-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Url.h"
#include "Filename.h"
#include "medialibrary/filesystem/Errors.h"

#include <stdexcept>
#include <cstring>
#include <algorithm>

namespace
{
inline bool isSafe( char c )
{
    return strchr( ".-_~/"
#ifdef _WIN32
                    "\\"
#endif
                   , c ) != nullptr;
}

std::string::const_iterator encodeSegment( std::string& res,
                                           std::string::const_iterator begin,
                                           std::string::const_iterator end,
                                           const char* extraChars )
{
    for ( auto i = begin; i < end; ++i )
    {
        // This must be an unsigned char for the bits operations below to work.
        // auto will yield a signed char here.
        const unsigned char c = *i;
        if ( ( c >= 32 && c <= 126 ) && (
                 ( c >= 'a' && c <= 'z' ) ||
                 ( c >= 'A' && c <= 'Z' ) ||
                 ( c >= '0' && c <= '9' ) ||
                 isSafe( c ) == true ||
                 ( extraChars != nullptr && strchr( extraChars, c ) != nullptr ) )
             )
        {
            res.push_back( c );
        }
        else
            res.append({ '%', "0123456789ABCDEF"[c >> 4], "0123456789ABCDEF"[c & 0xF] });
    }
    return end;
}

inline uint16_t charToVal( char c )
{
    if ( c >= '0' && c <= '9' )
        return c - '0';
    if ( c >= 'a' && c <= 'f' )
        return c - 'a' + 10;
    if ( c >= 'A' && c <= 'F' )
        return c - 'A' + 10;
    throw std::runtime_error( "Incomplete/invalid character sequence" );
}

}

namespace medialibrary
{
namespace utils
{
namespace url
{

parts split( const std::string& url )
{
    parts res{};
    auto schemePos = url.find( "://" );
    if ( schemePos == std::string::npos )
    {
        res.path = url;
        return res;
    }
    std::copy( url.cbegin(), url.cbegin() + schemePos,
               std::back_inserter( res.scheme ) );

    if ( res.scheme == "file" )
    {
        std::copy( url.cbegin() + schemePos + 3, url.cend(),
                   std::back_inserter( res.path ) );
        return res;
    }

    const auto authorityBegin = url.cbegin() + schemePos + 3;
    auto authorityEnd = std::find( authorityBegin, url.cend(), '/' );
    auto queryBegin = std::find( authorityBegin, url.cend(), '?' );
    const auto fragmentBegin = std::find( authorityBegin, url.cend(), '#' );

    /*
     * The fragment must come after the query parameters. Since we use both
     * values at a later point, sanitize them now.
     */
    if ( fragmentBegin != url.cend() && queryBegin != url.cend() &&
         fragmentBegin < queryBegin )
    {
        queryBegin = url.cend();
    }

    /* RFC 3986 §3.2:
     * The authority component is preceded by a double slash ("//") and is
     * terminated by the next slash ("/"), question mark ("?"), or number
     * sign ("#") character, or by the end of the URI.
     */
    if ( authorityEnd == url.cend() )
    {
        if ( queryBegin != url.cend() )
            authorityEnd = queryBegin;
        else
            authorityEnd = fragmentBegin;
    }
    else
    {
        if ( queryBegin != url.cend() && queryBegin < authorityEnd )
            authorityEnd = queryBegin;
        if ( fragmentBegin != url.cend() && fragmentBegin < authorityEnd )
            authorityEnd = fragmentBegin;
    }

    {
        /* Split the authority into its actual components */
        auto userInfoEnd = std::find( authorityBegin, authorityEnd, '@' );
        if ( userInfoEnd != authorityEnd )
        {
            std::copy( authorityBegin, userInfoEnd,
                       std::back_inserter( res.userInfo ) );
            /* Skip the '@' when copying the host */
            ++userInfoEnd;
            res.hostMarker = true;
        }
        else
            userInfoEnd = authorityBegin;

        auto portBegin = std::find( userInfoEnd, authorityEnd, ':' );
        if ( portBegin != authorityEnd )
            std::copy( portBegin + 1, authorityEnd, std::back_inserter( res.port ) );
        else
            portBegin = authorityEnd;
        std::copy( userInfoEnd, portBegin, std::back_inserter( res.host ) );

    }
    if ( authorityEnd == url.cend() )
    {
        /*
         * If we don't have a clear end for the authority segment, it means the
         * end is the url end, so we don't have anything else to split
         */
        return res;
    }

    auto pathEnd = queryBegin != url.cend() ? queryBegin : fragmentBegin;
    std::copy( authorityEnd, pathEnd,
               std::back_inserter( res.path ) );
    if ( queryBegin != url.cend() )
    {
        std::copy( queryBegin + 1,
                   fragmentBegin != url.cend() ? fragmentBegin : url.cend(),
                   std::back_inserter( res.query ) );
    }
    if ( fragmentBegin != url.cend() )
    {
        std::copy( fragmentBegin + 1, url.cend(),
                   std::back_inserter( res.fragments ) );
    }
    return res;
}

std::string decode( const std::string& str )
{
    std::string res;
    res.reserve( str.size() );
    auto it = str.cbegin();
    auto ite = str.cend();
    for ( ; it != ite; ++it )
    {
        if ( *it == '%' )
        {
            ++it;
            const auto c1 = charToVal( *it );
            const auto c2 = charToVal( *( it + 1 ) );
            auto val = c1 * 16 + c2;
            res.push_back( static_cast<std::string::value_type>( val ) );
            ++it;
        }
        else
            res.push_back( *it );
    }
    return res;
}

std::string encode( const std::string& str )
{
    auto parts = split( str );
    std::string res{};
    res.reserve( str.length() );
    /*
     * If the file is a local path, we need to encode everything as the
     * characters won't have any URL related meaning
     */
    if ( parts.scheme == "file" || parts.scheme.empty() == true )
    {
        if ( parts.scheme.empty() == false )
            res += "file://";
        auto pathBegin = parts.path.cbegin();
#ifdef _WIN32
        if ( *pathBegin == '/' && isalpha( *(pathBegin + 1) ) && *(pathBegin + 2) == ':' )
        {
            // Don't encode the ':' after the drive letter.
            // All other ':' need to be encoded, there are not allowed in a file path
            // on windows, but they might appear in urls
            std::copy( pathBegin, pathBegin + 3, std::back_inserter( res ) );
            pathBegin += 3;
        }
#endif
        encodeSegment( res, pathBegin, parts.path.cend(), nullptr );
        return res;
    }
    /*
     * We already accept any character in ".-_~/" through isSafe(), but we need
     * to accept more depending on the URL segments:
     */
    encodeSegment( res, parts.scheme.cbegin(), parts.scheme.cend(), "+" );
    res += "://";
    if ( parts.userInfo.empty() == false )
    {
        encodeSegment( res, parts.userInfo.cbegin(), parts.userInfo.cend(),
                       "!$&'()*+,;=:" );
    }
    if ( parts.hostMarker == true )
        res += '@';
    encodeSegment( res, parts.host.cbegin(), parts.host.cend(), "[]" );
    if ( parts.port.empty() == false )
    {
        res += ':';
        res += parts.port;
    }

    encodeSegment( res, parts.path.cbegin(), parts.path.cend(), "!$&'()*+,;=:@" );

    if ( parts.query.empty() == false )
    {
        res += '?';
        encodeSegment( res, parts.query.cbegin(), parts.query.cend(),
                       "!$&'()*+,;=:@?" );
    }
    if ( parts.fragments.empty() == false )
    {
        res += '#';
        encodeSegment( res, parts.query.cbegin(), parts.query.cend(),
                       "!$&'()*+,;=:@?" );
    }
    return res;
}

std::string stripScheme( const std::string& mrl )
{
    auto pos = mrl.find( "://" );
    if ( pos == std::string::npos )
        throw fs::errors::UnhandledScheme( "<empty scheme>" );
    return mrl.substr( pos + 3 );
}

std::string scheme( const std::string& mrl )
{
    auto pos = mrl.find( "://" );
    if ( pos == std::string::npos )
        throw fs::errors::UnhandledScheme( "<empty scheme>" );
    return mrl.substr( 0, pos + 3 );
}

#ifndef _WIN32

std::string toLocalPath( const std::string& mrl )
{
    if ( mrl.compare( 0, 7, "file://" ) != 0 )
        throw fs::errors::UnhandledScheme( scheme( mrl ) );
    return utils::url::decode( mrl.substr( 7 ) );
}

#else

std::string toLocalPath( const std::string& mrl )
{
    if ( mrl.compare( 0, 7, "file://" ) != 0 )
        throw fs::errors::UnhandledScheme( utils::url::scheme( mrl ) );
    auto localPath = mrl.substr( 7 );
    // If the path is a local path (ie. X:\path\to and not \\path\to) skip the
    // initial backslash, as it is only part of our representation, and not
    // understood by the win32 API functions
    // Note that the initial '/' (after the 2 forward slashes from the scheme)
    // is not a backslash, as it is not a path separator, so do not use
    // DIR_SEPARATOR_CHAR here.
    if ( localPath[0] == '/' && isalpha( localPath[1] ) )
        localPath.erase( 0, 1 );
    std::replace( begin( localPath ), end( localPath ), '/', '\\' );
    return utils::url::decode( localPath );
}

#endif

bool schemeIs( const std::string& scheme, const std::string& mrl )
{
    return mrl.compare( 0, scheme.size(), scheme ) == 0;
}

std::string path( const std::string &mrl )
{
    auto schemelessMrl = stripScheme( mrl );
    auto host = utils::file::firstFolder( schemelessMrl );
    return utils::file::removePath( schemelessMrl, host );
}

}
}
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/string/TranslatedString.h>

#include <stingraykit/collection/CollectionBuilder.h>
#include <stingraykit/collection/EnumerableHelpers.h>
#include <stingraykit/collection/MapDictionary.h>
#include <stingraykit/serialization/Serialization.h>

namespace stingray
{

	TranslatedString::TranslatedString()
		: _dictionary(make_shared_ptr<MapDictionary<LangCode, std::string> >())
	{ }

	TranslatedString& TranslatedString::AddTranslation(LangCode lang, const std::string& str)
	{
		_dictionary->Set(lang, str);
		return *this;
	}

	bool TranslatedString::HasTranslation(LangCode lang) const
	{
		if (lang == LangCode::Any)
			return !_dictionary->IsEmpty();

		return _dictionary->ContainsKey(lang);
	}

	std::string TranslatedString::GetTranslation(LangCode lang) const
	{
		if (lang == LangCode::Any)
			return _dictionary->GetEnumerator()->Get().Value;

		return _dictionary->Get(lang);
	}

	std::string TranslatedString::SelectTranslation(LangCode l0) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, LangCode::Any)); }

	std::string TranslatedString::SelectTranslation(LangCode l0, LangCode l1) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, l1, LangCode::Any)); }

	std::string TranslatedString::SelectTranslation(LangCode l0, LangCode l1, LangCode l2) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, l1, l2, LangCode::Any)); }

	std::string TranslatedString::DoSelectTranslation(const std::vector<LangCode>& langCodes) const
	{
		for (std::vector<LangCode>::const_iterator it = langCodes.begin(); it != langCodes.end(); ++it)
			if (HasTranslation(*it))
				return GetTranslation(*it);
		return "";
	}

	std::string TranslatedString::SelectTranslation(const std::vector<LangCode>& langCodes) const
	{
		for (std::vector<LangCode>::const_iterator it = langCodes.begin(); it != langCodes.end(); ++it)
			if (HasTranslation(*it))
				return GetTranslation(*it);

		return GetTranslation(LangCode::Any);
	}

	int TranslatedString::DoCompare(const TranslatedString& other) const
	{ return Enumerable::MakeSequenceCmp(comparers::Cmp())(_dictionary, other._dictionary); }

	void TranslatedString::Serialize(ObjectOStream& ar) const
	{ ar.Serialize("translations", *_dictionary); }

	void TranslatedString::Deserialize(ObjectIStream& ar)
	{ ar.Deserialize("translations", *_dictionary); }

	std::string TranslatedString::ToString() const
	{ return stingray::ToString(_dictionary); }

}
<commit_msg>TranslatedString: reorder methods in cpp with same order as in header<commit_after>// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/string/TranslatedString.h>

#include <stingraykit/collection/CollectionBuilder.h>
#include <stingraykit/collection/EnumerableHelpers.h>
#include <stingraykit/collection/MapDictionary.h>
#include <stingraykit/serialization/Serialization.h>

namespace stingray
{

	TranslatedString::TranslatedString()
		: _dictionary(make_shared_ptr<MapDictionary<LangCode, std::string> >())
	{ }

	TranslatedString& TranslatedString::AddTranslation(LangCode lang, const std::string& str)
	{
		_dictionary->Set(lang, str);
		return *this;
	}

	bool TranslatedString::HasTranslation(LangCode lang) const
	{
		if (lang == LangCode::Any)
			return !_dictionary->IsEmpty();

		return _dictionary->ContainsKey(lang);
	}

	std::string TranslatedString::GetTranslation(LangCode lang) const
	{
		if (lang == LangCode::Any)
			return _dictionary->GetEnumerator()->Get().Value;

		return _dictionary->Get(lang);
	}

	void TranslatedString::Serialize(ObjectOStream& ar) const
	{ ar.Serialize("translations", *_dictionary); }

	void TranslatedString::Deserialize(ObjectIStream& ar)
	{ ar.Deserialize("translations", *_dictionary); }

	std::string TranslatedString::ToString() const
	{ return stingray::ToString(_dictionary); }

	std::string TranslatedString::SelectTranslation(LangCode l0) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, LangCode::Any)); }

	std::string TranslatedString::SelectTranslation(LangCode l0, LangCode l1) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, l1, LangCode::Any)); }

	std::string TranslatedString::SelectTranslation(LangCode l0, LangCode l1, LangCode l2) const
	{ return DoSelectTranslation(VectorBuilder<LangCode>(l0, l1, l2, LangCode::Any)); }

	std::string TranslatedString::SelectTranslation(const std::vector<LangCode>& langCodes) const
	{
		for (std::vector<LangCode>::const_iterator it = langCodes.begin(); it != langCodes.end(); ++it)
			if (HasTranslation(*it))
				return GetTranslation(*it);

		return GetTranslation(LangCode::Any);
	}

	std::string TranslatedString::DoSelectTranslation(const std::vector<LangCode>& langCodes) const
	{
		for (std::vector<LangCode>::const_iterator it = langCodes.begin(); it != langCodes.end(); ++it)
			if (HasTranslation(*it))
				return GetTranslation(*it);
		return "";
	}

	int TranslatedString::DoCompare(const TranslatedString& other) const
	{ return Enumerable::MakeSequenceCmp(comparers::Cmp())(_dictionary, other._dictionary); }

}
<|endoftext|>


<commit_before>#include <gflags/gflags.h>
#include <glog/logging.h>
#include <iostream>
#include <fstream>
#include "utils/cluster_rt.h"
#include "proto/singa.pb.h"
#include "utils/common.h"
#ifndef GFLAGS_GFLAGS_H_
  namespace gflags = google;
#endif  // GFLAGS_GFLAGS_H_

DEFINE_string(global, "conf/singa.conf", "Global config file");

int main(int argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  singa::SingaProto global;
  singa::ReadProtoFromTextFile(FLAGS_global.c_str(), &global);
  singa::SetupLog(global.log_dir(), "SingaTool");

  LOG(INFO) << "The global config is \n" << global.DebugString();

  singa::JobManager mng(global.zookeeper_host());
  std::string usage = "singatool usage:\n"
      "./singatool create       :  generate a unique job id\n"
      "./singatool list         :  list running singa jobs\n"
      "./singatool view JOB_ID  :  view procs of a singa job\n"
      "./singatool clean JOB_ID :  clean a job path in zookeeper\n"
      "./singatool cleanup      :  clean all singa data in zookeeper\n"
      "./singatool listall      :  list all singa jobs\n";
  if (argc <= 1) {
    LOG(ERROR) << usage;
    return 1;
  }
  if (!mng.Init()) return 1;
  if (!strcmp(argv[1], "create")) {
    int id = mng.GenerateJobID();
    printf("%d\n", id);
  } else if (!strcmp(argv[1], "list")) {
    std::vector<singa::JobInfo> jobs;
    if (!mng.ListJobs(&jobs)) return 1;
    printf("JOB ID    |NUM PROCS  \n");
    printf("----------|-----------\n");
    for (singa::JobInfo job : jobs) {
      if (!job.procs) continue;
      printf("job-%-6d|%-10d\n", job.id, job.procs);
    }
  } else if (!strcmp(argv[1], "listall")) {
    std::vector<singa::JobInfo> jobs;
    if (!mng.ListJobs(&jobs)) return 1;
    printf("JOB ID    |NUM PROCS  \n");
    printf("----------|-----------\n");
    for (singa::JobInfo job : jobs) {
      printf("job-%-6d|%-10d\n", job.id, job.procs);
    }
  } else if (!strcmp(argv[1], "view")) {
    if (argc <= 2) {
      LOG(ERROR) << usage;
      return 1;
    }
    int id = atoi(argv[2]);
    std::vector<std::string> procs;
    if (!mng.ListJobProcs(id, &procs)) return 1;
    for (std::string s : procs) {
      printf("%s\n", s.c_str());
    }
  } else if (!strcmp(argv[1], "clean")) {
    if (argc <= 2) {
      LOG(ERROR) << usage;
      return 1;
    }
    int id = atoi(argv[2]);
    if (!mng.Clean(id)) return 1;
  } else if (!strcmp(argv[1], "cleanup")) {
    if (!mng.Cleanup()) return 1;
  } else {
    LOG(ERROR) << usage;
    return 1;
  }

  return 0;
}
<commit_msg>SINGA-36 Clean ModelProto, ClusterProto, JobProto and driver program<commit_after>#include <gflags/gflags.h>
#include <glog/logging.h>
#include <iostream>
#include <fstream>
#include "utils/cluster_rt.h"
#include "proto/singa.pb.h"
#include "utils/common.h"
#ifndef GFLAGS_GFLAGS_H_
namespace gflags = google;
#endif  // GFLAGS_GFLAGS_H_

DEFINE_string(global, "conf/singa.conf", "Global config file");

int main(int argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  // set logging level to ERROR and log to STDERR
  FLAGS_logtostderr = 1;
  FLAGS_minloglevel = 2;
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  singa::SingaProto global;
  singa::ReadProtoFromTextFile(FLAGS_global.c_str(), &global);
  LOG(INFO) << "The global config is \n" << global.DebugString();

  singa::JobManager mng(global.zookeeper_host());
  std::string usage = "singatool usage:\n"
      "# ./singatool create       :  generate a unique job id\n"
      "# ./singatool list         :  list running singa jobs\n"
      "# ./singatool view JOB_ID  :  view procs of a singa job\n"
      "# ./singatool clean JOB_ID :  clean a job path in zookeeper\n"
      "# ./singatool cleanup      :  clean all singa data in zookeeper\n"
      "# ./singatool listall      :  list all singa jobs\n";
  if (argc <= 1) {
    LOG(ERROR) << usage;
    return 1;
  }
  if (!mng.Init()) return 1;
  if (!strcmp(argv[1], "create")) {
    int id = mng.GenerateJobID();
    printf("%d\n", id);
  } else if (!strcmp(argv[1], "list")) {
    std::vector<singa::JobInfo> jobs;
    if (!mng.ListJobs(&jobs)) return 1;
    printf("JOB ID    |NUM PROCS  \n");
    printf("----------|-----------\n");
    for (singa::JobInfo job : jobs) {
      if (!job.procs) continue;
      printf("job-%-6d|%-10d\n", job.id, job.procs);
    }
  } else if (!strcmp(argv[1], "listall")) {
    std::vector<singa::JobInfo> jobs;
    if (!mng.ListJobs(&jobs)) return 1;
    printf("JOB ID    |NUM PROCS  \n");
    printf("----------|-----------\n");
    for (singa::JobInfo job : jobs) {
      printf("job-%-6d|%-10d\n", job.id, job.procs);
    }
  } else if (!strcmp(argv[1], "view")) {
    if (argc <= 2) {
      LOG(ERROR) << usage;
      return 1;
    }
    int id = atoi(argv[2]);
    std::vector<std::string> procs;
    if (!mng.ListJobProcs(id, &procs)) return 1;
    for (std::string s : procs) {
      printf("%s\n", s.c_str());
    }
  } else if (!strcmp(argv[1], "clean")) {
    if (argc <= 2) {
      LOG(ERROR) << usage;
      return 1;
    }
    int id = atoi(argv[2]);
    if (!mng.Clean(id)) return 1;
  } else if (!strcmp(argv[1], "cleanup")) {
    if (!mng.Cleanup()) return 1;
  } else {
    LOG(ERROR) << usage;
    return 1;
  }

  return 0;
}
<|endoftext|>