<commit_before>// Copyright (c) 2014-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"

#include "hash.h"
#include "uint256.h"

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <vector>
#include <string>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
{
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char* ch = strchr(pszBase58, *psz);
        if (ch == NULL)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin();
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
    // Skip & count leading zeroes.
    int zeroes = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        // Apply "b58 = b58 * 256 + ch".
        for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }
        assert(carry == 0);
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    std::vector<unsigned char>::iterator it = b58.begin();
    while (it != b58.end() && *it == 0)
        it++;
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end())
        str += pszBase58[*(it++)];
    return str;
}

std::string EncodeBase58(const std::vector<unsigned char>& vch)
{
    return EncodeBase58(&vch[0], &vch[0] + vch.size());
}

bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58(str.c_str(), vchRet);
}

std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
{
    // add 4-byte hash check to the end
    std::vector<unsigned char> vch(vchIn);
    uint256 hash = Hash(vch.begin(), vch.end());
    vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
    return EncodeBase58(vch);
}

bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
{
    if (!DecodeBase58(psz, vchRet) ||
        (vchRet.size() < 4)) {
        vchRet.clear();
        return false;
    }
    // re-calculate the checksum, insure it matches the included 4-byte checksum
    uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
    if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
        vchRet.clear();
        return false;
    }
    vchRet.resize(vchRet.size() - 4);
    return true;
}

bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58Check(str.c_str(), vchRet);
}

CBase58Data::CBase58Data()
{
    vchVersion.clear();
    vchData.clear();
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
{
    vchVersion = vchVersionIn;
    vchData.resize(nSize);
    if (!vchData.empty())
        memcpy(&vchData[0], pdata, nSize);
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
    SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
{
    std::vector<unsigned char> vchTemp;
    bool rc58 = DecodeBase58Check(psz, vchTemp);
    if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
        vchData.clear();
        vchVersion.clear();
        return false;
    }
    vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
    vchData.resize(vchTemp.size() - nVersionBytes);
    if (!vchData.empty())
        memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
    memory_cleanse(&vchTemp[0], vchTemp.size());
    return true;
}

bool CBase58Data::SetString(const std::string& str)
{
    return SetString(str.c_str());
}

std::string CBase58Data::ToString() const
{
    std::vector<unsigned char> vch = vchVersion;
    vch.insert(vch.end(), vchData.begin(), vchData.end());
    return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data& b58) const
{
    if (vchVersion < b58.vchVersion)
        return -1;
    if (vchVersion > b58.vchVersion)
        return 1;
    if (vchData < b58.vchData)
        return -1;
    if (vchData > b58.vchData)
        return 1;
    return 0;
}

namespace
{
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
{
private:
    CBitcoinAddress* addr;

public:
    CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}

    bool operator()(const CKeyID& id) const { return addr->Set(id); }
    bool operator()(const CScriptID& id) const { return addr->Set(id); }
    bool operator()(const CNoDestination& no) const { return false; }
};

} // anon namespace

bool CBitcoinAddress::Set(const CKeyID& id)
{
    SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CScriptID& id)
{
    SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CTxDestination& dest)
{
    return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
}

bool CBitcoinAddress::IsValid() const
{
    return IsValid(Params());
}

bool CBitcoinAddress::IsValid(const CChainParams& params) const
{
    bool fCorrectSize = vchData.size() == 20;
    bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
                         vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
    return fCorrectSize && fKnownVersion;
}

CTxDestination CBitcoinAddress::Get() const
{
    if (!IsValid())
        return CNoDestination();
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return CKeyID(id);
    else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
        return CScriptID(id);
    else
        return CNoDestination();
}

bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type) const
{
    if (!IsValid()) {
        return false;
    } else if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) {
        memcpy(&hashBytes, &vchData[0], 20);
        type = 1;
        return true;
    } else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) {
        memcpy(&hashBytes, &vchData[0], 20);
        type = 2;
        return true;
    }

    return false;
}

bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
{
    if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return false;
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    keyID = CKeyID(id);
    return true;
}

bool CBitcoinAddress::IsScript() const
{
    return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
}

void CBitcoinSecret::SetKey(const CKey& vchSecret)
{
    assert(vchSecret.IsValid());
    SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
    if (vchSecret.IsCompressed())
        vchData.push_back(1);
}

CKey CBitcoinSecret::GetKey()
{
    CKey ret;
    assert(vchData.size() >= 32);
    ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
    return ret;
}

bool CBitcoinSecret::IsValid() const
{
    bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
    bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
    return fExpectedFormat && fCorrectVersion;
}

bool CBitcoinSecret::SetString(const char* pszSecret)
{
    return CBase58Data::SetString(pszSecret) && IsValid();
}

bool CBitcoinSecret::SetString(const std::string& strSecret)
{
    return SetString(strSecret.c_str());
}
<commit_msg>Improve EncodeBase58/DecodeBase58 performance (#1456)<commit_after>// Copyright (c) 2014-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"

#include "hash.h"
#include "uint256.h"

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <vector>
#include <string>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
{
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
    std::vector<unsigned char> b256(size);
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char* ch = strchr(pszBase58, *psz);
        if (ch == NULL)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        int i = 0;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
    // Skip & count leading zeroes.
    int zeroes = 0;
    int length = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
    std::vector<unsigned char> b58(size);
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        int i = 0;
        // Apply "b58 = b58 * 256 + ch".
        for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }

        assert(carry == 0);
        length = i;
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
    while (it != b58.end() && *it == 0)
        it++;
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end())
        str += pszBase58[*(it++)];
    return str;
}

std::string EncodeBase58(const std::vector<unsigned char>& vch)
{
    return EncodeBase58(&vch[0], &vch[0] + vch.size());
}

bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58(str.c_str(), vchRet);
}

std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
{
    // add 4-byte hash check to the end
    std::vector<unsigned char> vch(vchIn);
    uint256 hash = Hash(vch.begin(), vch.end());
    vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
    return EncodeBase58(vch);
}

bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
{
    if (!DecodeBase58(psz, vchRet) ||
        (vchRet.size() < 4)) {
        vchRet.clear();
        return false;
    }
    // re-calculate the checksum, insure it matches the included 4-byte checksum
    uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
    if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
        vchRet.clear();
        return false;
    }
    vchRet.resize(vchRet.size() - 4);
    return true;
}

bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58Check(str.c_str(), vchRet);
}

CBase58Data::CBase58Data()
{
    vchVersion.clear();
    vchData.clear();
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
{
    vchVersion = vchVersionIn;
    vchData.resize(nSize);
    if (!vchData.empty())
        memcpy(&vchData[0], pdata, nSize);
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
    SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
{
    std::vector<unsigned char> vchTemp;
    bool rc58 = DecodeBase58Check(psz, vchTemp);
    if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
        vchData.clear();
        vchVersion.clear();
        return false;
    }
    vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
    vchData.resize(vchTemp.size() - nVersionBytes);
    if (!vchData.empty())
        memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
    memory_cleanse(&vchTemp[0], vchTemp.size());
    return true;
}

bool CBase58Data::SetString(const std::string& str)
{
    return SetString(str.c_str());
}

std::string CBase58Data::ToString() const
{
    std::vector<unsigned char> vch = vchVersion;
    vch.insert(vch.end(), vchData.begin(), vchData.end());
    return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data& b58) const
{
    if (vchVersion < b58.vchVersion)
        return -1;
    if (vchVersion > b58.vchVersion)
        return 1;
    if (vchData < b58.vchData)
        return -1;
    if (vchData > b58.vchData)
        return 1;
    return 0;
}

namespace
{
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
{
private:
    CBitcoinAddress* addr;

public:
    CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}

    bool operator()(const CKeyID& id) const { return addr->Set(id); }
    bool operator()(const CScriptID& id) const { return addr->Set(id); }
    bool operator()(const CNoDestination& no) const { return false; }
};

} // anon namespace

bool CBitcoinAddress::Set(const CKeyID& id)
{
    SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CScriptID& id)
{
    SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CTxDestination& dest)
{
    return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
}

bool CBitcoinAddress::IsValid() const
{
    return IsValid(Params());
}

bool CBitcoinAddress::IsValid(const CChainParams& params) const
{
    bool fCorrectSize = vchData.size() == 20;
    bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
                         vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
    return fCorrectSize && fKnownVersion;
}

CTxDestination CBitcoinAddress::Get() const
{
    if (!IsValid())
        return CNoDestination();
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return CKeyID(id);
    else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
        return CScriptID(id);
    else
        return CNoDestination();
}

bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type) const
{
    if (!IsValid()) {
        return false;
    } else if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) {
        memcpy(&hashBytes, &vchData[0], 20);
        type = 1;
        return true;
    } else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) {
        memcpy(&hashBytes, &vchData[0], 20);
        type = 2;
        return true;
    }

    return false;
}

bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
{
    if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return false;
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    keyID = CKeyID(id);
    return true;
}

bool CBitcoinAddress::IsScript() const
{
    return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
}

void CBitcoinSecret::SetKey(const CKey& vchSecret)
{
    assert(vchSecret.IsValid());
    SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
    if (vchSecret.IsCompressed())
        vchData.push_back(1);
}

CKey CBitcoinSecret::GetKey()
{
    CKey ret;
    assert(vchData.size() >= 32);
    ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
    return ret;
}

bool CBitcoinSecret::IsValid() const
{
    bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
    bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
    return fExpectedFormat && fCorrectVersion;
}

bool CBitcoinSecret::SetString(const char* pszSecret)
{
    return CBase58Data::SetString(pszSecret) && IsValid();
}

bool CBitcoinSecret::SetString(const std::string& strSecret)
{
    return SetString(strSecret.c_str());
}
<|endoftext|>


<commit_before>#include <myinit.h>
#include "ClipperUtils.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
#ifdef SLIC3RXS
#include "perlglue.hpp"
#endif

namespace Slic3r {

Polygon::operator Polygons() const
{
    Polygons pp;
    pp.push_back(*this);
    return pp;
}

Point&
Polygon::operator[](Points::size_type idx)
{
    return this->points[idx];
}

const Point&
Polygon::operator[](Points::size_type idx) const
{
    return this->points[idx];
}

Point
Polygon::last_point() const
{
    return this->points.front();  // last point == first point for polygons
}

Lines
Polygon::lines() const
{
    Lines lines;
    this->lines(&lines);
    return lines;
}

void
Polygon::lines(Lines* lines) const
{
    lines->reserve(lines->size() + this->points.size());
    for (Points::const_iterator it = this->points.begin(); it != this->points.end()-1; ++it) {
        lines->push_back(Line(*it, *(it + 1)));
    }
    lines->push_back(Line(this->points.back(), this->points.front()));
}

Polyline*
Polygon::split_at(const Point &point) const
{
    // find index of point
    for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {
        if (it->coincides_with(point))
            return this->split_at_index(it - this->points.begin());
    }
    CONFESS("Point not found");
    return NULL;
}

Polyline*
Polygon::split_at_index(int index) const
{
    Polyline* poly = new Polyline;
    poly->points.reserve(this->points.size() + 1);
    for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
        poly->points.push_back(*it);
    for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
        poly->points.push_back(*it);
    return poly;
}

Polyline*
Polygon::split_at_first_point() const
{
    return this->split_at_index(0);
}

Points
Polygon::equally_spaced_points(double distance) const
{
    Polyline* polyline = this->split_at_first_point();
    Points pts = polyline->equally_spaced_points(distance);
    delete polyline;
    return pts;
}

double
Polygon::area() const
{
    ClipperLib::Path p;
    Slic3rMultiPoint_to_ClipperPath(*this, p);
    return ClipperLib::Area(p);
}

bool
Polygon::is_counter_clockwise() const
{
    ClipperLib::Path p;
    Slic3rMultiPoint_to_ClipperPath(*this, p);
    return ClipperLib::Orientation(p);
}

bool
Polygon::is_clockwise() const
{
    return !this->is_counter_clockwise();
}

bool
Polygon::make_counter_clockwise()
{
    if (!this->is_counter_clockwise()) {
        this->reverse();
        return true;
    }
    return false;
}

bool
Polygon::make_clockwise()
{
    if (this->is_counter_clockwise()) {
        this->reverse();
        return true;
    }
    return false;
}

bool
Polygon::is_valid() const
{
    return this->points.size() >= 3;
}

bool
Polygon::contains_point(const Point &point) const
{
    // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
    bool result = false;
    Points::const_iterator i = this->points.begin();
    Points::const_iterator j = this->points.end() - 1;
    for (; i != this->points.end(); j = i++) {
        if ( ((i->y > point.y) != (j->y > point.y))
            && (point.x < (j->x - i->x) * (point.y - i->y) / (j->y - i->y) + i->x) )
            result = !result;
    }
    return result;
}

Polygons
Polygon::simplify(double tolerance) const
{
    Polygon p = *this;
    p.points = MultiPoint::_douglas_peucker(p.points, tolerance);

    Polygons pp;
    pp.push_back(p);
    simplify_polygons(pp, pp);
    return pp;
}

void
Polygon::simplify(double tolerance, Polygons &polygons) const
{
    Polygons pp = this->simplify(tolerance);
    polygons.reserve(polygons.size() + pp.size());
    polygons.insert(polygons.end(), pp.begin(), pp.end());
}

// Only call this on convex polygons or it will return invalid results
void
Polygon::triangulate_convex(Polygons* polygons) const
{
    for (Points::const_iterator it = this->points.begin() + 2; it != this->points.end(); ++it) {
        Polygon p;
        p.points.reserve(3);
        p.points.push_back(this->points.front());
        p.points.push_back(*(it-1));
        p.points.push_back(*it);

        // this should be replaced with a more efficient call to a merge_collinear_segments() method
        if (p.area() > 0) polygons->push_back(p);
    }
}

#ifdef SLIC3RXS

REGISTER_CLASS(Polygon, "Polygon");

SV*
Polygon::to_SV_ref() {
    SV* sv = newSV(0);
    sv_setref_pv( sv, perl_class_name_ref(this), (void*)this );
    return sv;
}

SV*
Polygon::to_SV_clone_ref() const {
    SV* sv = newSV(0);
    sv_setref_pv( sv, perl_class_name(this), new Polygon(*this) );
    return sv;
}

void
Polygon::from_SV_check(SV* poly_sv)
{
    if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(this)) && !sv_isa(poly_sv, perl_class_name_ref(this)))
        CONFESS("Not a valid %s object", perl_class_name(this));

    MultiPoint::from_SV_check(poly_sv);
}
#endif

}
<commit_msg>Fix Polygon::contains_point() overflowing on Windows. #1950<commit_after>#include <myinit.h>
#include "ClipperUtils.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
#ifdef SLIC3RXS
#include "perlglue.hpp"
#endif

namespace Slic3r {

Polygon::operator Polygons() const
{
    Polygons pp;
    pp.push_back(*this);
    return pp;
}

Point&
Polygon::operator[](Points::size_type idx)
{
    return this->points[idx];
}

const Point&
Polygon::operator[](Points::size_type idx) const
{
    return this->points[idx];
}

Point
Polygon::last_point() const
{
    return this->points.front();  // last point == first point for polygons
}

Lines
Polygon::lines() const
{
    Lines lines;
    this->lines(&lines);
    return lines;
}

void
Polygon::lines(Lines* lines) const
{
    lines->reserve(lines->size() + this->points.size());
    for (Points::const_iterator it = this->points.begin(); it != this->points.end()-1; ++it) {
        lines->push_back(Line(*it, *(it + 1)));
    }
    lines->push_back(Line(this->points.back(), this->points.front()));
}

Polyline*
Polygon::split_at(const Point &point) const
{
    // find index of point
    for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {
        if (it->coincides_with(point))
            return this->split_at_index(it - this->points.begin());
    }
    CONFESS("Point not found");
    return NULL;
}

Polyline*
Polygon::split_at_index(int index) const
{
    Polyline* poly = new Polyline;
    poly->points.reserve(this->points.size() + 1);
    for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
        poly->points.push_back(*it);
    for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
        poly->points.push_back(*it);
    return poly;
}

Polyline*
Polygon::split_at_first_point() const
{
    return this->split_at_index(0);
}

Points
Polygon::equally_spaced_points(double distance) const
{
    Polyline* polyline = this->split_at_first_point();
    Points pts = polyline->equally_spaced_points(distance);
    delete polyline;
    return pts;
}

double
Polygon::area() const
{
    ClipperLib::Path p;
    Slic3rMultiPoint_to_ClipperPath(*this, p);
    return ClipperLib::Area(p);
}

bool
Polygon::is_counter_clockwise() const
{
    ClipperLib::Path p;
    Slic3rMultiPoint_to_ClipperPath(*this, p);
    return ClipperLib::Orientation(p);
}

bool
Polygon::is_clockwise() const
{
    return !this->is_counter_clockwise();
}

bool
Polygon::make_counter_clockwise()
{
    if (!this->is_counter_clockwise()) {
        this->reverse();
        return true;
    }
    return false;
}

bool
Polygon::make_clockwise()
{
    if (this->is_counter_clockwise()) {
        this->reverse();
        return true;
    }
    return false;
}

bool
Polygon::is_valid() const
{
    return this->points.size() >= 3;
}

bool
Polygon::contains_point(const Point &point) const
{
    // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
    bool result = false;
    Points::const_iterator i = this->points.begin();
    Points::const_iterator j = this->points.end() - 1;
    for (; i != this->points.end(); j = i++) {
        if ( ((i->y > point.y) != (j->y > point.y))
            && ((double)point.x < (double)(j->x - i->x) * (double)(point.y - i->y) / (double)(j->y - i->y) + (double)i->x) )
            result = !result;
    }
    return result;
}

Polygons
Polygon::simplify(double tolerance) const
{
    Polygon p = *this;
    p.points = MultiPoint::_douglas_peucker(p.points, tolerance);

    Polygons pp;
    pp.push_back(p);
    simplify_polygons(pp, pp);
    return pp;
}

void
Polygon::simplify(double tolerance, Polygons &polygons) const
{
    Polygons pp = this->simplify(tolerance);
    polygons.reserve(polygons.size() + pp.size());
    polygons.insert(polygons.end(), pp.begin(), pp.end());
}

// Only call this on convex polygons or it will return invalid results
void
Polygon::triangulate_convex(Polygons* polygons) const
{
    for (Points::const_iterator it = this->points.begin() + 2; it != this->points.end(); ++it) {
        Polygon p;
        p.points.reserve(3);
        p.points.push_back(this->points.front());
        p.points.push_back(*(it-1));
        p.points.push_back(*it);

        // this should be replaced with a more efficient call to a merge_collinear_segments() method
        if (p.area() > 0) polygons->push_back(p);
    }
}

#ifdef SLIC3RXS

REGISTER_CLASS(Polygon, "Polygon");

SV*
Polygon::to_SV_ref() {
    SV* sv = newSV(0);
    sv_setref_pv( sv, perl_class_name_ref(this), (void*)this );
    return sv;
}

SV*
Polygon::to_SV_clone_ref() const {
    SV* sv = newSV(0);
    sv_setref_pv( sv, perl_class_name(this), new Polygon(*this) );
    return sv;
}

void
Polygon::from_SV_check(SV* poly_sv)
{
    if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(this)) && !sv_isa(poly_sv, perl_class_name_ref(this)))
        CONFESS("Not a valid %s object", perl_class_name(this));

    MultiPoint::from_SV_check(poly_sv);
}
#endif

}
<|endoftext|>


<commit_before>/**
 * @file base64.cpp
 * @brief modified base64 encoding/decoding
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/base64.h"
#include "mega/utils.h"

namespace mega {
// modified base64 conversion (no trailing '=' and '-_' instead of '+/')
unsigned char Base64::to64(byte c)
{
    c &= 63;

    if (c < 26)
    {
        return c + 'A';
    }

    if (c < 52)
    {
        return c - 26 + 'a';
    }

    if (c < 62)
    {
        return c - 52 + '0';
    }

    if (c == 62)
    {
        return '-';
    }

    return '_';
}

unsigned char Base64::from64(byte c)
{
    if ((c >= 'A') && (c <= 'Z'))
    {
        return c - 'A';
    }

    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a' + 26;
    }

    if ((c >= '0') && (c <= '9'))
    {
        return c - '0' + 52;
    }

    if (c == '-' || c == '+')
    {
        return 62;
    }

    if (c == '_' || c == '/')
    {
        return 63;
    }

    return 255;
}

int Base64::atob(const string &in, string &out)
{
    out.resize(in.size() * 3 / 4 + 3);
    out.resize(Base64::atob(in.data(), (byte *) out.data(), (int)out.size()));

    return (int)out.size();
}

std::string Base64::atob(const std::string &in)
{
    string out;
    out.resize(in.size() * 3 / 4 + 3);
    out.resize(Base64::atob(in.data(), (byte *) out.data(), (int)out.size()));

    return out;
}

int Base64::atob(const char* a, byte* b, int blen)
{
    byte c[4];
    int i;
    int p = 0;

    c[3] = 0;

    for (;;)
    {
        for (i = 0; i < 4; i++)
        {
            if ((c[i] = from64(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);

        if ((p >= blen) || (i < 3))
        {
            return p;
        }

        b[p++] = (c[1] << 4) | ((c[2] & 0x3c) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[2] << 6) | c[3];
    }
}

void Base64::itoa(int64_t val, string *result)
{
    byte c;
    int64_t rest;
    if (!result || val < 0)
    {
        return;
    }

    if (!val)
    {
        *result = "A";
        return;
    }

    result->clear();
    while (val)
    {
        rest = val % 64;
        val /= 64;
        c = to64(byte(rest));
        result->insert(result->begin(), (char) c);
    }
}

int64_t Base64::atoi(string *val)
{
    if (!val)
    {
        return -1;
    }

    size_t len = val->size();
    if (len == 0)
    {
        return -1;
    }

    size_t pos = 0;
    int64_t res = 0;
    int valid = 0;
    while (pos < len)
    {
        byte b = from64(val->at(pos));
        if (b == 255)
        {
            pos++;
            continue;
        }

        valid++;
        res *= 64;
        res += b;
        pos++;
    }

    if (!valid || res < 0)
    {
        return -1;
    }

    return res;
}

int Base64::btoa(const string &in, string &out)
{
    out.resize(in.size() * 4 / 3 + 4);
    out.resize(Base64::btoa((const byte*) in.data(), (int)in.size(), (char *) out.data()));

    return (int)out.size();
}

std::string Base64::btoa(const string &in)
{
    string out;
    out.resize(in.size() * 4 / 3 + 4);
    out.resize(Base64::btoa((const byte*) in.data(), (int)in.size(), (char *) out.data()));

    return out;
}

int Base64::btoa(const byte* b, int blen, char* a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to64(*b >> 2);
        a[p++] = to64((*b << 4) | (((blen > 1) ? b[1] : 0) >> 4));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to64(b[1] << 2 | (((blen > 2) ? b[2] : 0) >> 6));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to64(b[2]);

        blen -= 3;
        b += 3;
    }

    a[p] = 0;

    return p;
}

byte Base32::to32(byte c)
{
    c &= 31;

    if (c < 26)
    {
        return c + 'a';
    }

    return c - 26 + '2';
}

byte Base32::from32(byte c)
{
    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a';
    }

    if ((c >= '2') && (c <= '9'))
    {
        return c - '2' + 26;
    }

    return 255;
}

int Base32::btoa(const byte *b, int blen, char *a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to32( *b >> 3);
        a[p++] = to32((*b << 2) | (((blen > 1) ? b[1] : 0) >> 6));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to32(b[1] >> 1);
        a[p++] = to32(b[1] << 4 | (((blen > 2) ? b[2] : 0) >> 4));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to32((b[2] << 1) | (((blen > 3) ? b[3] : 0) >> 7));

        if (blen < 4)
        {
            break;
        }

        a[p++] = to32(b[3] >> 2);
        a[p++] = to32(b[3] << 3 | (((blen > 4) ? b[4] : 0) >> 5));

        if (blen < 5)
        {
            break;
        }

        a[p++] = to32(b[4]);

        blen -= 5;
        b += 5;
    }

    a[p] = 0;

    return p;
}

int Base32::atob(const char *a, byte *b, int blen)
{
    byte c[8];
    int i;
    int p = 0;

    c[7] = 0;

    for (;;)
    {
        for (i = 0; i < 8; i++)
        {
            if ((c[i] = from32(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 3) | ((c[1] & 0x1C) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[1] << 6) | (c[2] << 1) | ((c[3] & 0x10) >> 4);

        if ((p >= blen) || (i < 5))
        {
            return p;
        }

        b[p++] = (c[3] << 4) | ((c[4] & 0x1E) >> 1);

        if ((p >= blen) || (i < 7))
        {
            return p;
        }

        b[p++] = (c[4] << 7) | (c[5] << 2) | ((c[6] & 0x18) >> 3);

        if ((p >= blen) || (i < 8))
        {
            return p;
        }

        b[p++] = (c[6] << 5) | c[7];
    }
}

bool URLCodec::issafe(char c)
{
    if (ishexdigit(c)
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '-' || c == '.'
            || c == '_' || c == '~')
    {
        return true;
    }
    return false;
}

bool URLCodec::ishexdigit(char c)
{
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

void URLCodec::escape(string *plain, string *escaped)
{
    if (!escaped || !plain)
    {
        return;
    }

    escaped->clear();
    int len = (int)plain->size();
    int escapedIndex = 0;
    for (int i = 0; i < len; i++)
    {
        unsigned char c = (unsigned char)plain->at(i);
        if (issafe(c))
        {
            escaped->push_back(c);
            escapedIndex++;
        }
        else
        {
            escaped->resize(escapedIndex + 3);
            sprintf((char *)escaped->c_str() + escapedIndex, "%%%02x", c);
            escapedIndex += 3;
        }
    }
}

void URLCodec::unescape(string *escaped, string *plain)
{
    if (!(escaped && plain))
    {
        return;
    }

    plain->clear();
    plain->reserve(escaped->size());

    const char* m = escaped->c_str();
    const char* n = m + escaped->size();

    while (m < n)
    {
        if (*m == '%' && n - m > 1)
        {
            if (ishexdigit(m[1]) && ishexdigit(m[2]))
            {
                auto c = hexval(m[1]) << 4u | hexval(m[2]);

                plain->push_back(static_cast<char>(c));

                m += 3;
                continue;
            }
        }

        plain->push_back(*m++);
    }
}

} // namespace
<commit_msg>Fix off-by-one error in distance calculation (n - m).<commit_after>/**
 * @file base64.cpp
 * @brief modified base64 encoding/decoding
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/base64.h"
#include "mega/utils.h"

namespace mega {
// modified base64 conversion (no trailing '=' and '-_' instead of '+/')
unsigned char Base64::to64(byte c)
{
    c &= 63;

    if (c < 26)
    {
        return c + 'A';
    }

    if (c < 52)
    {
        return c - 26 + 'a';
    }

    if (c < 62)
    {
        return c - 52 + '0';
    }

    if (c == 62)
    {
        return '-';
    }

    return '_';
}

unsigned char Base64::from64(byte c)
{
    if ((c >= 'A') && (c <= 'Z'))
    {
        return c - 'A';
    }

    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a' + 26;
    }

    if ((c >= '0') && (c <= '9'))
    {
        return c - '0' + 52;
    }

    if (c == '-' || c == '+')
    {
        return 62;
    }

    if (c == '_' || c == '/')
    {
        return 63;
    }

    return 255;
}

int Base64::atob(const string &in, string &out)
{
    out.resize(in.size() * 3 / 4 + 3);
    out.resize(Base64::atob(in.data(), (byte *) out.data(), (int)out.size()));

    return (int)out.size();
}

std::string Base64::atob(const std::string &in)
{
    string out;
    out.resize(in.size() * 3 / 4 + 3);
    out.resize(Base64::atob(in.data(), (byte *) out.data(), (int)out.size()));

    return out;
}

int Base64::atob(const char* a, byte* b, int blen)
{
    byte c[4];
    int i;
    int p = 0;

    c[3] = 0;

    for (;;)
    {
        for (i = 0; i < 4; i++)
        {
            if ((c[i] = from64(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);

        if ((p >= blen) || (i < 3))
        {
            return p;
        }

        b[p++] = (c[1] << 4) | ((c[2] & 0x3c) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[2] << 6) | c[3];
    }
}

void Base64::itoa(int64_t val, string *result)
{
    byte c;
    int64_t rest;
    if (!result || val < 0)
    {
        return;
    }

    if (!val)
    {
        *result = "A";
        return;
    }

    result->clear();
    while (val)
    {
        rest = val % 64;
        val /= 64;
        c = to64(byte(rest));
        result->insert(result->begin(), (char) c);
    }
}

int64_t Base64::atoi(string *val)
{
    if (!val)
    {
        return -1;
    }

    size_t len = val->size();
    if (len == 0)
    {
        return -1;
    }

    size_t pos = 0;
    int64_t res = 0;
    int valid = 0;
    while (pos < len)
    {
        byte b = from64(val->at(pos));
        if (b == 255)
        {
            pos++;
            continue;
        }

        valid++;
        res *= 64;
        res += b;
        pos++;
    }

    if (!valid || res < 0)
    {
        return -1;
    }

    return res;
}

int Base64::btoa(const string &in, string &out)
{
    out.resize(in.size() * 4 / 3 + 4);
    out.resize(Base64::btoa((const byte*) in.data(), (int)in.size(), (char *) out.data()));

    return (int)out.size();
}

std::string Base64::btoa(const string &in)
{
    string out;
    out.resize(in.size() * 4 / 3 + 4);
    out.resize(Base64::btoa((const byte*) in.data(), (int)in.size(), (char *) out.data()));

    return out;
}

int Base64::btoa(const byte* b, int blen, char* a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to64(*b >> 2);
        a[p++] = to64((*b << 4) | (((blen > 1) ? b[1] : 0) >> 4));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to64(b[1] << 2 | (((blen > 2) ? b[2] : 0) >> 6));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to64(b[2]);

        blen -= 3;
        b += 3;
    }

    a[p] = 0;

    return p;
}

byte Base32::to32(byte c)
{
    c &= 31;

    if (c < 26)
    {
        return c + 'a';
    }

    return c - 26 + '2';
}

byte Base32::from32(byte c)
{
    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a';
    }

    if ((c >= '2') && (c <= '9'))
    {
        return c - '2' + 26;
    }

    return 255;
}

int Base32::btoa(const byte *b, int blen, char *a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to32( *b >> 3);
        a[p++] = to32((*b << 2) | (((blen > 1) ? b[1] : 0) >> 6));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to32(b[1] >> 1);
        a[p++] = to32(b[1] << 4 | (((blen > 2) ? b[2] : 0) >> 4));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to32((b[2] << 1) | (((blen > 3) ? b[3] : 0) >> 7));

        if (blen < 4)
        {
            break;
        }

        a[p++] = to32(b[3] >> 2);
        a[p++] = to32(b[3] << 3 | (((blen > 4) ? b[4] : 0) >> 5));

        if (blen < 5)
        {
            break;
        }

        a[p++] = to32(b[4]);

        blen -= 5;
        b += 5;
    }

    a[p] = 0;

    return p;
}

int Base32::atob(const char *a, byte *b, int blen)
{
    byte c[8];
    int i;
    int p = 0;

    c[7] = 0;

    for (;;)
    {
        for (i = 0; i < 8; i++)
        {
            if ((c[i] = from32(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 3) | ((c[1] & 0x1C) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[1] << 6) | (c[2] << 1) | ((c[3] & 0x10) >> 4);

        if ((p >= blen) || (i < 5))
        {
            return p;
        }

        b[p++] = (c[3] << 4) | ((c[4] & 0x1E) >> 1);

        if ((p >= blen) || (i < 7))
        {
            return p;
        }

        b[p++] = (c[4] << 7) | (c[5] << 2) | ((c[6] & 0x18) >> 3);

        if ((p >= blen) || (i < 8))
        {
            return p;
        }

        b[p++] = (c[6] << 5) | c[7];
    }
}

bool URLCodec::issafe(char c)
{
    if (ishexdigit(c)
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '-' || c == '.'
            || c == '_' || c == '~')
    {
        return true;
    }
    return false;
}

bool URLCodec::ishexdigit(char c)
{
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

void URLCodec::escape(string *plain, string *escaped)
{
    if (!escaped || !plain)
    {
        return;
    }

    escaped->clear();
    int len = (int)plain->size();
    int escapedIndex = 0;
    for (int i = 0; i < len; i++)
    {
        unsigned char c = (unsigned char)plain->at(i);
        if (issafe(c))
        {
            escaped->push_back(c);
            escapedIndex++;
        }
        else
        {
            escaped->resize(escapedIndex + 3);
            sprintf((char *)escaped->c_str() + escapedIndex, "%%%02x", c);
            escapedIndex += 3;
        }
    }
}

void URLCodec::unescape(string *escaped, string *plain)
{
    if (!(escaped && plain))
    {
        return;
    }

    plain->clear();
    plain->reserve(escaped->size());

    const char* m = escaped->c_str();
    const char* n = m + escaped->size();

    while (m < n)
    {
        if (*m == '%' && n - m > 2)
        {
            if (ishexdigit(m[1]) && ishexdigit(m[2]))
            {
                auto c = hexval(m[1]) << 4u | hexval(m[2]);

                plain->push_back(static_cast<char>(c));

                m += 3;
                continue;
            }
        }

        plain->push_back(*m++);
    }
}

} // namespace
<|endoftext|>


<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>((Value*)CV))
      O << FunctionAddrPrefix << Mang->getValueName(CV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(CV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>Compile C strings to:<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (NumBits == 0) return;   // No need to emit alignment.
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>((Value*)CV))
      O << FunctionAddrPrefix << Mang->getValueName(CV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(CV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>#ifdef HAVE_CXX11
#include <functional>
#define HAVE_CPP_FUNC_PTR
namespace funcptr = std;
#else
#ifdef HAVE_BOOST
#include <boost/function.hpp>
namespace funcptr = boost;
#define HAVE_CPP_FUNC_PTR
#endif
#endif

#include <fstream>
#include <cctype>

#ifndef WIN32
#include <cstdio>
#include <unistd.h>
#endif

#include <algorithm>

#ifndef YAHTTP_MAX_REQUEST_SIZE
#define YAHTTP_MAX_REQUEST_SIZE 2097152
#endif

#ifndef YAHTTP_MAX_RESPONSE_SIZE
#define YAHTTP_MAX_RESPONSE_SIZE 2097152
#endif

#define YAHTTP_TYPE_REQUEST 1
#define YAHTTP_TYPE_RESPONSE 2

namespace YaHTTP {
  typedef std::map<std::string,Cookie,ASCIICINullSafeComparator> strcookie_map_t; //<! String to Cookie map

  typedef enum {
    urlencoded,
    multipart
  } postformat_t; //<! Enumeration of possible post encodings, url encoding or multipart

  /*! Base class for request and response */
  class HTTPBase {
  public:
    /*! Default renderer for request/response, simply copies body to response */
    class SendBodyRender {
    public:
      SendBodyRender() {};

      size_t operator()(const HTTPBase *doc, std::ostream& os, bool chunked) const {
        if (chunked) {
          std::string::size_type i,cl;
          for(i=0;i<doc->body.length();i+=1024) {
            cl = std::min(static_cast<std::string::size_type>(1024), doc->body.length()-i); // for less than 1k blocks
            os << std::hex << cl << std::dec << "\r\n";
            os << doc->body.substr(i, cl) << "\r\n";
          }
          os << 0 << "\r\n\r\n"; // last chunk
        } else {
          os << doc->body;
        }
        return doc->body.length();
      }; //<! writes body to ostream and returns length
    };
    /* Simple sendfile renderer which streams file to ostream */
    class SendFileRender {
    public:
      SendFileRender(const std::string& path) {
        this->path = path;
      };

      size_t operator()(const HTTPBase *doc __attribute__((unused)), std::ostream& os, bool chunked) const {
        char buf[4096];
        size_t n,k;
#ifdef HAVE_CXX11
        std::ifstream ifs(path, std::ifstream::binary);
#else
        std::ifstream ifs(path.c_str(), std::ifstream::binary);
#endif
        n = 0;

        while(ifs && ifs.good()) {
          ifs.read(buf, sizeof buf);
          n += (k = ifs.gcount());
          if (k) {
            if (chunked) os << std::hex << k << std::dec << "\r\n";
            os.write(buf, k);
            if (chunked) os << "\r\n";
          }
        }
        if (chunked) os << 0 << "\r\n\r\n";
        return n;
      }; //<! writes file to ostream and returns length

      std::string path; //<! File to send
    };

    HTTPBase() {
      initialize();
    };

    virtual void initialize() {
      kind = 0;
      status = 0;
#ifdef HAVE_CPP_FUNC_PTR
      renderer = SendBodyRender();
#endif
      max_request_size = YAHTTP_MAX_REQUEST_SIZE;
      max_response_size = YAHTTP_MAX_RESPONSE_SIZE;
      url = "";
      method = "";
      statusText = "";
      jar.clear();
      headers.clear();
      parameters.clear();
      getvars.clear();
      postvars.clear();
      body = "";
      routeName = "";
      version = 11; // default to version 1.1
    }
protected:
    HTTPBase(const HTTPBase& rhs) {
      this->url = rhs.url; this->kind = rhs.kind;
      this->status = rhs.status; this->statusText = rhs.statusText;
      this->method = rhs.method; this->headers = rhs.headers;
      this->jar = rhs.jar; this->postvars = rhs.postvars;
      this->parameters = rhs.parameters; this->getvars = rhs.getvars;
      this->body = rhs.body; this->max_request_size = rhs.max_request_size;
      this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
      this->renderer = rhs.renderer;
#endif
    };
    HTTPBase& operator=(const HTTPBase& rhs) {
      this->url = rhs.url; this->kind = rhs.kind;
      this->status = rhs.status; this->statusText = rhs.statusText;
      this->method = rhs.method; this->headers = rhs.headers;
      this->jar = rhs.jar; this->postvars = rhs.postvars;
      this->parameters = rhs.parameters; this->getvars = rhs.getvars;
      this->body = rhs.body; this->max_request_size = rhs.max_request_size;
      this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
      this->renderer = rhs.renderer;
#endif
      return *this;
    };
public:
    URL url; //<! URL of this request/response
    int kind; //<! Type of object (1 = request, 2 = response)
    int status; //<! status code
    int version; //<! http version 9 = 0.9, 10 = 1.0, 11 = 1.1
    std::string statusText; //<! textual representation of status code
    std::string method; //<! http verb
    strstr_map_t headers; //<! map of header(s)
    CookieJar jar; //<! cookies
    strstr_map_t postvars; //<! map of POST variables (from POST body)
    strstr_map_t getvars; //<! map of GET variables (from URL)
// these two are for Router
    strstr_map_t parameters; //<! map of route parameters (only if you use YaHTTP::Router)
    std::string routeName; //<! name of the current route (only if you use YaHTTP::Router)

    std::string body; //<! the actual content

    ssize_t max_request_size; //<! maximum size of request
    ssize_t max_response_size;  //<! maximum size of response

#ifdef HAVE_CPP_FUNC_PTR
    funcptr::function<size_t(const HTTPBase*,std::ostream&,bool)> renderer; //<! rendering function
#endif
    void write(std::ostream& os) const; //<! writes request to the given output stream

    strstr_map_t& GET() { return getvars; }; //<! acccessor for getvars
    strstr_map_t& POST() { return postvars; }; //<! accessor for postvars
    strcookie_map_t& COOKIES() { return jar.cookies; }; //<! accessor for cookies

    std::string versionStr(int version) const {
      switch(version) {
      case  9: return "0.9";
      case 10: return "1.0";
      case 11: return "1.1";
      default: throw YaHTTP::Error("Unsupported version");
      }
    };

    std::string str() const {
       std::ostringstream oss;
       write(oss);
       return oss.str();
    }; //<! return string representation of this object
  };

  /*! Response class, represents a HTTP Response document */
  class Response: public HTTPBase {
  public:
    Response() { initialize(); };
    Response(const HTTPBase& rhs): HTTPBase(rhs) {
      this->kind = YAHTTP_TYPE_RESPONSE;
    };
    Response& operator=(const HTTPBase& rhs) {
      HTTPBase::operator=(rhs);
      this->kind = YAHTTP_TYPE_RESPONSE;
      return *this;
    };
    void initialize() {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_RESPONSE;
    }
    void initialize(const HTTPBase& rhs) {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_RESPONSE;
      // copy SOME attributes
      this->url = rhs.url;
      this->method = rhs.method;
      this->jar = rhs.jar;
      this->version = rhs.version;
    }
    friend std::ostream& operator<<(std::ostream& os, const Response &resp);
    friend std::istream& operator>>(std::istream& is, Response &resp);
  };

  /* Request class, represents a HTTP Request document */
  class Request: public HTTPBase {
  public:
    Request() { initialize(); };
    Request(const HTTPBase& rhs): HTTPBase(rhs) {
      this->kind = YAHTTP_TYPE_REQUEST;
    };
    Request& operator=(const HTTPBase& rhs) {
      HTTPBase::operator=(rhs);
      this->kind = YAHTTP_TYPE_REQUEST;
      return *this;
    };
    void initialize() {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_REQUEST;
    }
    void initialize(const HTTPBase& rhs) {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_REQUEST;
      // copy SOME attributes
      this->url = rhs.url;
      this->method = rhs.method;
      this->jar = rhs.jar;
      this->version = rhs.version;
    }
    void setup(const std::string& method, const std::string& url) {
      this->url.parse(url);
      this->headers["host"] = this->url.host;
      this->method = method;
      std::transform(this->method.begin(), this->method.end(), this->method.begin(), ::toupper);
      this->headers["user-agent"] = "YaHTTP v1.0";
    }; //<! Set some initial things for a request

    void preparePost(postformat_t format = urlencoded) {
      std::ostringstream postbuf;
      if (format == urlencoded) {
        for(strstr_map_t::const_iterator i = POST().begin(); i != POST().end(); i++) {
          postbuf << Utility::encodeURL(i->first, false) << "=" << Utility::encodeURL(i->second, false) << "&";
        }
        // remove last bit
        if (postbuf.str().length()>0)
          body = postbuf.str().substr(0, postbuf.str().length()-1);
        else
          body = "";
        headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8";
      } else if (format == multipart) {
        headers["content-type"] = "multipart/form-data; boundary=YaHTTP-12ca543";
        for(strstr_map_t::const_iterator i = POST().begin(); i != POST().end(); i++) {
          postbuf << "--YaHTTP-12ca543\r\nContent-Disposition: form-data; name=\"" << Utility::encodeURL(i->first, false) << "; charset=UTF-8\r\n\r\n"
            << Utility::encodeURL(i->second, false) << "\r\n";
        }
      }

      postbuf.str("");
      postbuf << body.length();
      // set method and change headers
      method = "POST";
      headers["content-length"] = postbuf.str();
    }; //<! convert all postvars into string and stuff it into body

    friend std::ostream& operator<<(std::ostream& os, const Request &resp);
    friend std::istream& operator>>(std::istream& is, Request &resp);
  };

  /*! Asynchronous HTTP document loader */
  template <class T>
  class AsyncLoader {
  public:
    T* target; //<! target to populate
    int state; //<! reader state
    size_t pos; //<! reader position

    std::string buffer; //<! read buffer
    bool chunked; //<! whether we are parsing chunked data
    int chunk_size; //<! expected size of next chunk
    std::ostringstream bodybuf; //<! buffer for body
    size_t maxbody; //<! maximum size of body
    size_t minbody; //<! minimum size of body
    bool hasBody; //<! are we expecting body

    void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value); //<! key value pair parser helper

    void initialize(T* target) {
      chunked = false; chunk_size = 0;
      bodybuf.str(""); maxbody = 0;
      pos = 0; state = 0; this->target = target;
      hasBody = false;
      buffer = "";
      this->target->initialize();
    }; //<! Initialize the parser for target and clear state
    int feed(const std::string& somedata); //<! Feed data to the parser
    bool ready() {
     return (chunked == true && state == 3) || // if it's chunked we get end of data indication
             (chunked == false && state > 1 &&
               (!hasBody ||
                 (bodybuf.str().size() <= maxbody &&
                  bodybuf.str().size() >= minbody)
               )
             );
    }; //<! whether we have received enough data
    void finalize() {
      bodybuf.flush();
      if (ready()) {
        strstr_map_t::iterator pos = target->headers.find("content-type");
        if (pos != target->headers.end() && Utility::iequals(pos->second, "application/x-www-form-urlencoded", 32)) {
          target->postvars = Utility::parseUrlParameters(bodybuf.str());
        }
        target->body = bodybuf.str();
      }
      bodybuf.str("");
      this->target = NULL;
    }; //<! finalize and release target
  };

  /*! Asynchronous HTTP response loader */
  class AsyncResponseLoader: public AsyncLoader<Response> {
  };

  /*! Asynchronous HTTP request loader */
  class AsyncRequestLoader: public AsyncLoader<Request> {
  };

};
<commit_msg>Initialize minbody<commit_after>#ifdef HAVE_CXX11
#include <functional>
#define HAVE_CPP_FUNC_PTR
namespace funcptr = std;
#else
#ifdef HAVE_BOOST
#include <boost/function.hpp>
namespace funcptr = boost;
#define HAVE_CPP_FUNC_PTR
#endif
#endif

#include <fstream>
#include <cctype>

#ifndef WIN32
#include <cstdio>
#include <unistd.h>
#endif

#include <algorithm>

#ifndef YAHTTP_MAX_REQUEST_SIZE
#define YAHTTP_MAX_REQUEST_SIZE 2097152
#endif

#ifndef YAHTTP_MAX_RESPONSE_SIZE
#define YAHTTP_MAX_RESPONSE_SIZE 2097152
#endif

#define YAHTTP_TYPE_REQUEST 1
#define YAHTTP_TYPE_RESPONSE 2

namespace YaHTTP {
  typedef std::map<std::string,Cookie,ASCIICINullSafeComparator> strcookie_map_t; //<! String to Cookie map

  typedef enum {
    urlencoded,
    multipart
  } postformat_t; //<! Enumeration of possible post encodings, url encoding or multipart

  /*! Base class for request and response */
  class HTTPBase {
  public:
    /*! Default renderer for request/response, simply copies body to response */
    class SendBodyRender {
    public:
      SendBodyRender() {};

      size_t operator()(const HTTPBase *doc, std::ostream& os, bool chunked) const {
        if (chunked) {
          std::string::size_type i,cl;
          for(i=0;i<doc->body.length();i+=1024) {
            cl = std::min(static_cast<std::string::size_type>(1024), doc->body.length()-i); // for less than 1k blocks
            os << std::hex << cl << std::dec << "\r\n";
            os << doc->body.substr(i, cl) << "\r\n";
          }
          os << 0 << "\r\n\r\n"; // last chunk
        } else {
          os << doc->body;
        }
        return doc->body.length();
      }; //<! writes body to ostream and returns length
    };
    /* Simple sendfile renderer which streams file to ostream */
    class SendFileRender {
    public:
      SendFileRender(const std::string& path) {
        this->path = path;
      };

      size_t operator()(const HTTPBase *doc __attribute__((unused)), std::ostream& os, bool chunked) const {
        char buf[4096];
        size_t n,k;
#ifdef HAVE_CXX11
        std::ifstream ifs(path, std::ifstream::binary);
#else
        std::ifstream ifs(path.c_str(), std::ifstream::binary);
#endif
        n = 0;

        while(ifs && ifs.good()) {
          ifs.read(buf, sizeof buf);
          n += (k = ifs.gcount());
          if (k) {
            if (chunked) os << std::hex << k << std::dec << "\r\n";
            os.write(buf, k);
            if (chunked) os << "\r\n";
          }
        }
        if (chunked) os << 0 << "\r\n\r\n";
        return n;
      }; //<! writes file to ostream and returns length

      std::string path; //<! File to send
    };

    HTTPBase() {
      initialize();
    };

    virtual void initialize() {
      kind = 0;
      status = 0;
#ifdef HAVE_CPP_FUNC_PTR
      renderer = SendBodyRender();
#endif
      max_request_size = YAHTTP_MAX_REQUEST_SIZE;
      max_response_size = YAHTTP_MAX_RESPONSE_SIZE;
      url = "";
      method = "";
      statusText = "";
      jar.clear();
      headers.clear();
      parameters.clear();
      getvars.clear();
      postvars.clear();
      body = "";
      routeName = "";
      version = 11; // default to version 1.1
    }
protected:
    HTTPBase(const HTTPBase& rhs) {
      this->url = rhs.url; this->kind = rhs.kind;
      this->status = rhs.status; this->statusText = rhs.statusText;
      this->method = rhs.method; this->headers = rhs.headers;
      this->jar = rhs.jar; this->postvars = rhs.postvars;
      this->parameters = rhs.parameters; this->getvars = rhs.getvars;
      this->body = rhs.body; this->max_request_size = rhs.max_request_size;
      this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
      this->renderer = rhs.renderer;
#endif
    };
    HTTPBase& operator=(const HTTPBase& rhs) {
      this->url = rhs.url; this->kind = rhs.kind;
      this->status = rhs.status; this->statusText = rhs.statusText;
      this->method = rhs.method; this->headers = rhs.headers;
      this->jar = rhs.jar; this->postvars = rhs.postvars;
      this->parameters = rhs.parameters; this->getvars = rhs.getvars;
      this->body = rhs.body; this->max_request_size = rhs.max_request_size;
      this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
      this->renderer = rhs.renderer;
#endif
      return *this;
    };
public:
    URL url; //<! URL of this request/response
    int kind; //<! Type of object (1 = request, 2 = response)
    int status; //<! status code
    int version; //<! http version 9 = 0.9, 10 = 1.0, 11 = 1.1
    std::string statusText; //<! textual representation of status code
    std::string method; //<! http verb
    strstr_map_t headers; //<! map of header(s)
    CookieJar jar; //<! cookies
    strstr_map_t postvars; //<! map of POST variables (from POST body)
    strstr_map_t getvars; //<! map of GET variables (from URL)
// these two are for Router
    strstr_map_t parameters; //<! map of route parameters (only if you use YaHTTP::Router)
    std::string routeName; //<! name of the current route (only if you use YaHTTP::Router)

    std::string body; //<! the actual content

    ssize_t max_request_size; //<! maximum size of request
    ssize_t max_response_size;  //<! maximum size of response

#ifdef HAVE_CPP_FUNC_PTR
    funcptr::function<size_t(const HTTPBase*,std::ostream&,bool)> renderer; //<! rendering function
#endif
    void write(std::ostream& os) const; //<! writes request to the given output stream

    strstr_map_t& GET() { return getvars; }; //<! acccessor for getvars
    strstr_map_t& POST() { return postvars; }; //<! accessor for postvars
    strcookie_map_t& COOKIES() { return jar.cookies; }; //<! accessor for cookies

    std::string versionStr(int version) const {
      switch(version) {
      case  9: return "0.9";
      case 10: return "1.0";
      case 11: return "1.1";
      default: throw YaHTTP::Error("Unsupported version");
      }
    };

    std::string str() const {
       std::ostringstream oss;
       write(oss);
       return oss.str();
    }; //<! return string representation of this object
  };

  /*! Response class, represents a HTTP Response document */
  class Response: public HTTPBase {
  public:
    Response() { initialize(); };
    Response(const HTTPBase& rhs): HTTPBase(rhs) {
      this->kind = YAHTTP_TYPE_RESPONSE;
    };
    Response& operator=(const HTTPBase& rhs) {
      HTTPBase::operator=(rhs);
      this->kind = YAHTTP_TYPE_RESPONSE;
      return *this;
    };
    void initialize() {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_RESPONSE;
    }
    void initialize(const HTTPBase& rhs) {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_RESPONSE;
      // copy SOME attributes
      this->url = rhs.url;
      this->method = rhs.method;
      this->jar = rhs.jar;
      this->version = rhs.version;
    }
    friend std::ostream& operator<<(std::ostream& os, const Response &resp);
    friend std::istream& operator>>(std::istream& is, Response &resp);
  };

  /* Request class, represents a HTTP Request document */
  class Request: public HTTPBase {
  public:
    Request() { initialize(); };
    Request(const HTTPBase& rhs): HTTPBase(rhs) {
      this->kind = YAHTTP_TYPE_REQUEST;
    };
    Request& operator=(const HTTPBase& rhs) {
      HTTPBase::operator=(rhs);
      this->kind = YAHTTP_TYPE_REQUEST;
      return *this;
    };
    void initialize() {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_REQUEST;
    }
    void initialize(const HTTPBase& rhs) {
      HTTPBase::initialize();
      this->kind = YAHTTP_TYPE_REQUEST;
      // copy SOME attributes
      this->url = rhs.url;
      this->method = rhs.method;
      this->jar = rhs.jar;
      this->version = rhs.version;
    }
    void setup(const std::string& method, const std::string& url) {
      this->url.parse(url);
      this->headers["host"] = this->url.host;
      this->method = method;
      std::transform(this->method.begin(), this->method.end(), this->method.begin(), ::toupper);
      this->headers["user-agent"] = "YaHTTP v1.0";
    }; //<! Set some initial things for a request

    void preparePost(postformat_t format = urlencoded) {
      std::ostringstream postbuf;
      if (format == urlencoded) {
        for(strstr_map_t::const_iterator i = POST().begin(); i != POST().end(); i++) {
          postbuf << Utility::encodeURL(i->first, false) << "=" << Utility::encodeURL(i->second, false) << "&";
        }
        // remove last bit
        if (postbuf.str().length()>0)
          body = postbuf.str().substr(0, postbuf.str().length()-1);
        else
          body = "";
        headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8";
      } else if (format == multipart) {
        headers["content-type"] = "multipart/form-data; boundary=YaHTTP-12ca543";
        for(strstr_map_t::const_iterator i = POST().begin(); i != POST().end(); i++) {
          postbuf << "--YaHTTP-12ca543\r\nContent-Disposition: form-data; name=\"" << Utility::encodeURL(i->first, false) << "; charset=UTF-8\r\n\r\n"
            << Utility::encodeURL(i->second, false) << "\r\n";
        }
      }

      postbuf.str("");
      postbuf << body.length();
      // set method and change headers
      method = "POST";
      headers["content-length"] = postbuf.str();
    }; //<! convert all postvars into string and stuff it into body

    friend std::ostream& operator<<(std::ostream& os, const Request &resp);
    friend std::istream& operator>>(std::istream& is, Request &resp);
  };

  /*! Asynchronous HTTP document loader */
  template <class T>
  class AsyncLoader {
  public:
    T* target; //<! target to populate
    int state; //<! reader state
    size_t pos; //<! reader position

    std::string buffer; //<! read buffer
    bool chunked; //<! whether we are parsing chunked data
    int chunk_size; //<! expected size of next chunk
    std::ostringstream bodybuf; //<! buffer for body
    size_t maxbody; //<! maximum size of body
    size_t minbody; //<! minimum size of body
    bool hasBody; //<! are we expecting body

    void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value); //<! key value pair parser helper

    void initialize(T* target) {
      chunked = false; chunk_size = 0;
      bodybuf.str(""); minbody = 0; maxbody = 0;
      pos = 0; state = 0; this->target = target;
      hasBody = false;
      buffer = "";
      this->target->initialize();
    }; //<! Initialize the parser for target and clear state
    int feed(const std::string& somedata); //<! Feed data to the parser
    bool ready() {
     return (chunked == true && state == 3) || // if it's chunked we get end of data indication
             (chunked == false && state > 1 &&
               (!hasBody ||
                 (bodybuf.str().size() <= maxbody &&
                  bodybuf.str().size() >= minbody)
               )
             );
    }; //<! whether we have received enough data
    void finalize() {
      bodybuf.flush();
      if (ready()) {
        strstr_map_t::iterator pos = target->headers.find("content-type");
        if (pos != target->headers.end() && Utility::iequals(pos->second, "application/x-www-form-urlencoded", 32)) {
          target->postvars = Utility::parseUrlParameters(bodybuf.str());
        }
        target->body = bodybuf.str();
      }
      bodybuf.str("");
      this->target = NULL;
    }; //<! finalize and release target
  };

  /*! Asynchronous HTTP response loader */
  class AsyncResponseLoader: public AsyncLoader<Response> {
  };

  /*! Asynchronous HTTP request loader */
  class AsyncRequestLoader: public AsyncLoader<Request> {
  };

};
<|endoftext|>