<commit_before>#include "stdafx.h"

#include "ETypes.h"
#include "Player.h"
#include "PlayerEx.h"
#include <ATF/global.hpp>

namespace GameServer
{
    namespace Fixes
    {
        namespace
        {
            using namespace ATF;
            using namespace GameServer::Extension;
        }

        void CPlayer::load()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.set_hook(&ATF::CPlayer::Load, &CPlayer::Load);
            core.set_hook(&ATF::CPlayer::Loop, &CPlayer::Loop);
            core.set_hook(&ATF::CPlayer::NetClose, &CPlayer::NetClose);
            core.set_hook(&ATF::CPlayer::CalcPvP, &CPlayer::CalcPvP);
            core.set_hook(&ATF::CPlayer::CalPvpTempCash, &CPlayer::CalPvpTempCash);
            core.set_hook(&ATF::CPlayer::UpdatePvpOrderView, &CPlayer::UpdatePvpOrderView);
            core.set_hook(&ATF::CPlayer::pc_MovePortal, &CPlayer::pc_MovePortal);
            core.set_hook(&ATF::CPlayer::pc_MakeTrapRequest, &CPlayer::pc_MakeTrapRequest);
            core.set_hook(&ATF::CPlayer::pc_MakeTowerRequest, &CPlayer::pc_MakeTowerRequest);
            core.set_hook(&ATF::CPlayer::pc_GestureRequest, &CPlayer::pc_GestureRequest);
            core.set_hook(&ATF::CPlayer::pc_GuildManageRequest, &CPlayer::pc_GuildManageRequest);
            core.set_hook(&ATF::CPlayer::pc_CharacterRenameCheck, &CPlayer::pc_CharacterRenameCheck);
            core.set_hook(&ATF::CPlayer::pc_GotoBasePortalRequest, &CPlayer::pc_GotoBasePortalRequest);
            core.set_hook(&ATF::CPlayer::pc_ThrowStorageItem, &CPlayer::pc_ThrowStorageItem);
            core.set_hook(&ATF::CPlayer::pc_ExchangeItem, &CPlayer::pc_ExchangeItem);

            core.set_hook(&ATF::CPlayer::pc_MoveNext, &CPlayer::pc_MoveNext);
            core.set_hook(&ATF::CPlayer::pc_RealMovPos, &CPlayer::pc_RealMovPos);
            core.set_hook(&ATF::CPlayer::pc_MoveStop, &CPlayer::pc_MoveStop);
        }

        void CPlayer::unload()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.unset_hook(&ATF::CPlayer::Load);
            core.unset_hook(&ATF::CPlayer::Loop);
            core.unset_hook(&ATF::CPlayer::NetClose);
            core.unset_hook(&ATF::CPlayer::CalcPvP);
            core.unset_hook(&ATF::CPlayer::CalPvpTempCash);
            core.unset_hook(&ATF::CPlayer::UpdatePvpOrderView);
            core.unset_hook(&ATF::CPlayer::pc_MovePortal);
            core.unset_hook(&ATF::CPlayer::pc_MakeTrapRequest);
            core.unset_hook(&ATF::CPlayer::pc_MakeTowerRequest);
            core.unset_hook(&ATF::CPlayer::pc_GestureRequest);
            core.unset_hook(&ATF::CPlayer::pc_GuildManageRequest);
            core.unset_hook(&ATF::CPlayer::pc_CharacterRenameCheck);
            core.unset_hook(&ATF::CPlayer::pc_GotoBasePortalRequest);
            core.unset_hook(&ATF::CPlayer::pc_ThrowStorageItem);
            core.unset_hook(&ATF::CPlayer::pc_ExchangeItem);
            core.unset_hook(&ATF::CPlayer::pc_MoveNext);
            core.unset_hook(&ATF::CPlayer::pc_RealMovPos);
            core.unset_hook(&ATF::CPlayer::pc_MoveStop);
        }

        void CPlayer::loop()
        {
        }

        ModuleVersion_t CPlayer::get_version()
        {
            return ATF::usVersion;
        }

        ModuleName_t CPlayer::get_name()
        {
            static const ModuleName_t name = "fix_Player";
            return name;
        }

        void CPlayer::configure(
            const rapidjson::Value & nodeConfig)
        {
            UNREFERENCED_PARAMETER(nodeConfig);
        }

        void WINAPIV CPlayer::pc_MakeTrapRequest(
            ATF::CPlayer * pObj,
            uint16_t wSkillIndex,
            uint16_t wTrapItemSerial,
            float * pfPos,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MakeTrapRequest1783_ptr next)
        {
            UNREFERENCED_PARAMETER(pfPos);
            do
            {
                if (pObj->IsMapLoading())
                    break;

                auto pTrapItem = pObj->m_Param.m_dbInven.GetPtrFromSerial(wTrapItemSerial);
                if (!pTrapItem)
                    break;

                if (pTrapItem->m_byTableCode != (BYTE)e_code_item_table::tbl_code_trap)
                    break;

                if (!pObj->IsEffectableEquip(pTrapItem))
                    break;

                next(pObj, wSkillIndex, wTrapItemSerial, pObj->m_fCurPos, pConsumeSerial);
            } while (false);
        }

        void WINAPIV CPlayer::pc_MakeTowerRequest(
            ATF::CPlayer * pObj,
            uint16_t wSkillIndex,
            uint16_t wTowerItemSerial,
            char byMaterialNum,
            ATF::_make_tower_request_clzo::__material * pMaterial,
            float * pfPos,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MakeTowerRequest1781_ptr next)
        {
            UNREFERENCED_PARAMETER(pfPos);
            do
            {
                if (pObj->IsMapLoading())
                    break;

                auto pTrapItem = pObj->m_Param.m_dbInven.GetPtrFromSerial(wTowerItemSerial);
                if (!pTrapItem)
                    break;

                if (pTrapItem->m_byTableCode != (BYTE)e_code_item_table::tbl_code_tower)
                    break;

                if (!pObj->IsEffectableEquip(pTrapItem))
                    break;

                next(pObj, wSkillIndex, wTowerItemSerial, byMaterialNum, pMaterial, pObj->m_fCurPos, pConsumeSerial);
            } while (false);
        }

        void WINAPIV CPlayer::pc_GestureRequest(
            ATF::CPlayer * pObj,
            char byGestureType,
            ATF::Info::CPlayerpc_GestureRequest1719_ptr next)
        {
            if (pObj->IsMineMode())
                return;

            if (pObj->IsActingSiegeMode() || pObj->IsSiegeMode())
                return;

            if (pObj->IsRidingUnit())
                return;

            next(pObj, byGestureType);
        }

        void WINAPIV CPlayer::pc_GuildManageRequest(
            ATF::CPlayer * pObj,
            char byType,
            unsigned int dwDst,
            unsigned int dwObj1,
            unsigned int dwObj2,
            unsigned int dwObj3,
            ATF::Info::CPlayerpc_GuildManageRequest1745_ptr next)
        {
            if (!pObj->m_Param.m_pGuild)
            {
                pObj->SendMsg_GuildManageResult((char)202);
                return;
            }

            next(pObj, byType, dwDst, dwObj1, dwObj2, dwObj3);
        }

        void WINAPIV CPlayer::pc_MovePortal(
            ATF::CPlayer * pObj,
            int nPortalIndex,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MovePortal1795_ptr next)
        {
            if (pObj->Is_Battle_Mode())
            {
                float pNewPos[3]{ 0.0f };
                char byMapIndx = -1;
                char byPortalIndx = -1;

                pObj->SendMsg_MovePortal(4, byMapIndx, byPortalIndx, pNewPos, true);
                return;
            }

            next(pObj, nPortalIndex, pConsumeSerial);;
        }

        char WINAPIV CPlayer::pc_CharacterRenameCheck(
            ATF::CPlayer * pObj,
            char * strCharacterName,
            ATF::Info::CPlayerpc_CharacterRenameCheck1629_ptr next)
        {
            if (ATF::Global::IsSQLValidString(strCharacterName))
                return next(pObj, strCharacterName);

            return 6;
        }

        void WINAPIV CPlayer::pc_GotoBasePortalRequest(
            ATF::CPlayer * pObj,
            unsigned __int16 wItemSerial,
            ATF::Info::CPlayerpc_GotoBasePortalRequest1725_ptr next)
        {
            if (pObj->Is_Battle_Mode() && pObj->m_byUserDgr == 0)
            {
                pObj->SendMsg_GotoBasePortalResult(8);
                return;
            }

            next(pObj, wItemSerial);
        }

        void WINAPIV CPlayer::pc_ThrowStorageItem(
            ATF::CPlayer * pObj,
            ATF::_STORAGE_POS_INDIV* pItem,
            ATF::Info::CPlayerpc_ThrowStorageItem1953_ptr next)
        {
            if (!pObj->m_pUserDB)
                return;

            char byResult = 0;

            do
            {
                auto pStoragePtr = pObj->m_Param.m_pStoragePtr[pItem->byStorageCode];
                if (pObj->m_EP.GetEff_State(ATF::_EFF_STATE::Stone_Lck))
                {
                    byResult = 5;
                    break;
                }

                if (pObj->m_EP.GetEff_State(ATF::_EFF_STATE::Invincible))
                {
                    byResult = 5;
                    break;
                }

                auto pSrc = pStoragePtr->GetPtrFromSerial(pItem->wItemSerial);
                if (!pSrc)
                {
                    byResult = 2;
                    break;
                }

                if (pSrc->m_bLock)
                {
                    byResult = 9;
                    break;
                }

                if (ATF::Global::IsOverLapItem(pSrc->m_byTableCode))
                {
                    if (pItem->byNum <= 0 || pItem->byNum > pSrc->m_dwDur)
                    {
                        pObj->SendMsg_AdjustAmountInform(pItem->byStorageCode, pItem->wItemSerial, static_cast<unsigned int>(pSrc->m_dwDur));
                        byResult = 3;
                        break;
                    }
                }

                next(pObj, pItem);
            } while (false);

            pObj->SendMsg_ThrowStorageResult(byResult);
        }

        void WINAPIV CPlayer::pc_ExchangeItem(
            ATF::CPlayer * pPlayer,
            unsigned __int16 wManualIndex,
            unsigned __int16 wItemSerial,
            ATF::Info::CPlayerpc_ExchangeItem1711_ptr next)
        {
            uint8_t byResult = 0;
            do
            {
                auto pCon = pPlayer->m_Param.m_dbInven.GetPtrFromSerial(wItemSerial);
                if (!pCon)
                {
                    byResult = 4;
                    break;
                }

                if (pCon->m_bLock)
                {
                    byResult = 4;
                    break;
                }

                if (pCon->m_byTableCode != (uint8_t)e_code_item_table::tbl_code_box)
                {
                    byResult = 12;
                    break;
                }

                if (pCon->m_dwDur <= 0 || pCon->m_dwDur > 99)
                {
                    byResult = 4;
                    break;
                }

                next(pPlayer, wManualIndex, wItemSerial);
                return;
            } while (false);

            _STORAGE_LIST::_db_con pNewItem;
            pPlayer->SendMsg_ExchangeItemResult(byResult, &pNewItem);
        }

    }
}<commit_msg>Added fix for teleportation without item<commit_after>#include "stdafx.h"

#include "ETypes.h"
#include "Player.h"
#include "PlayerEx.h"
#include <ATF/global.hpp>

namespace GameServer
{
    namespace Fixes
    {
        namespace
        {
            using namespace ATF;
            using namespace GameServer::Extension;
        }

        void CPlayer::load()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.set_hook(&ATF::CPlayer::Load, &CPlayer::Load);
            core.set_hook(&ATF::CPlayer::Loop, &CPlayer::Loop);
            core.set_hook(&ATF::CPlayer::NetClose, &CPlayer::NetClose);
            core.set_hook(&ATF::CPlayer::CalcPvP, &CPlayer::CalcPvP);
            core.set_hook(&ATF::CPlayer::CalPvpTempCash, &CPlayer::CalPvpTempCash);
            core.set_hook(&ATF::CPlayer::UpdatePvpOrderView, &CPlayer::UpdatePvpOrderView);
            core.set_hook(&ATF::CPlayer::pc_MovePortal, &CPlayer::pc_MovePortal);
            core.set_hook(&ATF::CPlayer::pc_MakeTrapRequest, &CPlayer::pc_MakeTrapRequest);
            core.set_hook(&ATF::CPlayer::pc_MakeTowerRequest, &CPlayer::pc_MakeTowerRequest);
            core.set_hook(&ATF::CPlayer::pc_GestureRequest, &CPlayer::pc_GestureRequest);
            core.set_hook(&ATF::CPlayer::pc_GuildManageRequest, &CPlayer::pc_GuildManageRequest);
            core.set_hook(&ATF::CPlayer::pc_CharacterRenameCheck, &CPlayer::pc_CharacterRenameCheck);
            core.set_hook(&ATF::CPlayer::pc_GotoBasePortalRequest, &CPlayer::pc_GotoBasePortalRequest);
            core.set_hook(&ATF::CPlayer::pc_ThrowStorageItem, &CPlayer::pc_ThrowStorageItem);
            core.set_hook(&ATF::CPlayer::pc_ExchangeItem, &CPlayer::pc_ExchangeItem);

            core.set_hook(&ATF::CPlayer::pc_MoveNext, &CPlayer::pc_MoveNext);
            core.set_hook(&ATF::CPlayer::pc_RealMovPos, &CPlayer::pc_RealMovPos);
            core.set_hook(&ATF::CPlayer::pc_MoveStop, &CPlayer::pc_MoveStop);
        }

        void CPlayer::unload()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.unset_hook(&ATF::CPlayer::Load);
            core.unset_hook(&ATF::CPlayer::Loop);
            core.unset_hook(&ATF::CPlayer::NetClose);
            core.unset_hook(&ATF::CPlayer::CalcPvP);
            core.unset_hook(&ATF::CPlayer::CalPvpTempCash);
            core.unset_hook(&ATF::CPlayer::UpdatePvpOrderView);
            core.unset_hook(&ATF::CPlayer::pc_MovePortal);
            core.unset_hook(&ATF::CPlayer::pc_MakeTrapRequest);
            core.unset_hook(&ATF::CPlayer::pc_MakeTowerRequest);
            core.unset_hook(&ATF::CPlayer::pc_GestureRequest);
            core.unset_hook(&ATF::CPlayer::pc_GuildManageRequest);
            core.unset_hook(&ATF::CPlayer::pc_CharacterRenameCheck);
            core.unset_hook(&ATF::CPlayer::pc_GotoBasePortalRequest);
            core.unset_hook(&ATF::CPlayer::pc_ThrowStorageItem);
            core.unset_hook(&ATF::CPlayer::pc_ExchangeItem);
            core.unset_hook(&ATF::CPlayer::pc_MoveNext);
            core.unset_hook(&ATF::CPlayer::pc_RealMovPos);
            core.unset_hook(&ATF::CPlayer::pc_MoveStop);
        }

        void CPlayer::loop()
        {
        }

        ModuleVersion_t CPlayer::get_version()
        {
            return ATF::usVersion;
        }

        ModuleName_t CPlayer::get_name()
        {
            static const ModuleName_t name = "fix_Player";
            return name;
        }

        void CPlayer::configure(
            const rapidjson::Value & nodeConfig)
        {
            UNREFERENCED_PARAMETER(nodeConfig);
        }

        void WINAPIV CPlayer::pc_MakeTrapRequest(
            ATF::CPlayer * pObj,
            uint16_t wSkillIndex,
            uint16_t wTrapItemSerial,
            float * pfPos,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MakeTrapRequest1783_ptr next)
        {
            UNREFERENCED_PARAMETER(pfPos);
            do
            {
                if (pObj->IsMapLoading())
                    break;

                auto pTrapItem = pObj->m_Param.m_dbInven.GetPtrFromSerial(wTrapItemSerial);
                if (!pTrapItem)
                    break;

                if (pTrapItem->m_byTableCode != (BYTE)e_code_item_table::tbl_code_trap)
                    break;

                if (!pObj->IsEffectableEquip(pTrapItem))
                    break;

                next(pObj, wSkillIndex, wTrapItemSerial, pObj->m_fCurPos, pConsumeSerial);
            } while (false);
        }

        void WINAPIV CPlayer::pc_MakeTowerRequest(
            ATF::CPlayer * pObj,
            uint16_t wSkillIndex,
            uint16_t wTowerItemSerial,
            char byMaterialNum,
            ATF::_make_tower_request_clzo::__material * pMaterial,
            float * pfPos,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MakeTowerRequest1781_ptr next)
        {
            UNREFERENCED_PARAMETER(pfPos);
            do
            {
                if (pObj->IsMapLoading())
                    break;

                auto pTrapItem = pObj->m_Param.m_dbInven.GetPtrFromSerial(wTowerItemSerial);
                if (!pTrapItem)
                    break;

                if (pTrapItem->m_byTableCode != (BYTE)e_code_item_table::tbl_code_tower)
                    break;

                if (!pObj->IsEffectableEquip(pTrapItem))
                    break;

                next(pObj, wSkillIndex, wTowerItemSerial, byMaterialNum, pMaterial, pObj->m_fCurPos, pConsumeSerial);
            } while (false);
        }

        void WINAPIV CPlayer::pc_GestureRequest(
            ATF::CPlayer * pObj,
            char byGestureType,
            ATF::Info::CPlayerpc_GestureRequest1719_ptr next)
        {
            if (pObj->IsMineMode())
                return;

            if (pObj->IsActingSiegeMode() || pObj->IsSiegeMode())
                return;

            if (pObj->IsRidingUnit())
                return;

            next(pObj, byGestureType);
        }

        void WINAPIV CPlayer::pc_GuildManageRequest(
            ATF::CPlayer * pObj,
            char byType,
            unsigned int dwDst,
            unsigned int dwObj1,
            unsigned int dwObj2,
            unsigned int dwObj3,
            ATF::Info::CPlayerpc_GuildManageRequest1745_ptr next)
        {
            if (!pObj->m_Param.m_pGuild)
            {
                pObj->SendMsg_GuildManageResult((char)202);
                return;
            }

            next(pObj, byType, dwDst, dwObj1, dwObj2, dwObj3);
        }

        void WINAPIV CPlayer::pc_MovePortal(
            ATF::CPlayer * pObj,
            int nPortalIndex,
            uint16_t * pConsumeSerial,
            ATF::Info::CPlayerpc_MovePortal1795_ptr next)
        {
            if (pObj->Is_Battle_Mode())
            {
                float pNewPos[3]{ 0.0f };
                char byMapIndx = -1;
                char byPortalIndx = -1;

                pObj->SendMsg_MovePortal(4, byMapIndx, byPortalIndx, pNewPos, true);
                return;
            }

            next(pObj, nPortalIndex, pConsumeSerial);;
        }

        char WINAPIV CPlayer::pc_CharacterRenameCheck(
            ATF::CPlayer * pObj,
            char * strCharacterName,
            ATF::Info::CPlayerpc_CharacterRenameCheck1629_ptr next)
        {
            if (ATF::Global::IsSQLValidString(strCharacterName))
                return next(pObj, strCharacterName);

            return 6;
        }

        void WINAPIV CPlayer::pc_GotoBasePortalRequest(
            ATF::CPlayer * pObj,
            unsigned __int16 wItemSerial,
            ATF::Info::CPlayerpc_GotoBasePortalRequest1725_ptr next)
        {
            if (pObj->m_byUserDgr == 0)
            {
                if (pObj->Is_Battle_Mode())
                {
                    pObj->SendMsg_GotoBasePortalResult(8);
                    return;
                }

                if (wItemSerial == 0xffff)
                {
                    pObj->SendMsg_GotoBasePortalResult(8);
                    return;
                }
            }

            next(pObj, wItemSerial);
        }

        void WINAPIV CPlayer::pc_ThrowStorageItem(
            ATF::CPlayer * pObj,
            ATF::_STORAGE_POS_INDIV* pItem,
            ATF::Info::CPlayerpc_ThrowStorageItem1953_ptr next)
        {
            if (!pObj->m_pUserDB)
                return;

            char byResult = 0;

            do
            {
                auto pStoragePtr = pObj->m_Param.m_pStoragePtr[pItem->byStorageCode];
                if (pObj->m_EP.GetEff_State(ATF::_EFF_STATE::Stone_Lck))
                {
                    byResult = 5;
                    break;
                }

                if (pObj->m_EP.GetEff_State(ATF::_EFF_STATE::Invincible))
                {
                    byResult = 5;
                    break;
                }

                auto pSrc = pStoragePtr->GetPtrFromSerial(pItem->wItemSerial);
                if (!pSrc)
                {
                    byResult = 2;
                    break;
                }

                if (pSrc->m_bLock)
                {
                    byResult = 9;
                    break;
                }

                if (ATF::Global::IsOverLapItem(pSrc->m_byTableCode))
                {
                    if (pItem->byNum <= 0 || pItem->byNum > pSrc->m_dwDur)
                    {
                        pObj->SendMsg_AdjustAmountInform(pItem->byStorageCode, pItem->wItemSerial, static_cast<unsigned int>(pSrc->m_dwDur));
                        byResult = 3;
                        break;
                    }
                }

                next(pObj, pItem);
            } while (false);

            pObj->SendMsg_ThrowStorageResult(byResult);
        }

        void WINAPIV CPlayer::pc_ExchangeItem(
            ATF::CPlayer * pPlayer,
            unsigned __int16 wManualIndex,
            unsigned __int16 wItemSerial,
            ATF::Info::CPlayerpc_ExchangeItem1711_ptr next)
        {
            uint8_t byResult = 0;
            do
            {
                auto pCon = pPlayer->m_Param.m_dbInven.GetPtrFromSerial(wItemSerial);
                if (!pCon)
                {
                    byResult = 4;
                    break;
                }

                if (pCon->m_bLock)
                {
                    byResult = 4;
                    break;
                }

                if (pCon->m_byTableCode != (uint8_t)e_code_item_table::tbl_code_box)
                {
                    byResult = 12;
                    break;
                }

                if (pCon->m_dwDur <= 0 || pCon->m_dwDur > 99)
                {
                    byResult = 4;
                    break;
                }

                next(pPlayer, wManualIndex, wItemSerial);
                return;
            } while (false);

            _STORAGE_LIST::_db_con pNewItem;
            pPlayer->SendMsg_ExchangeItemResult(byResult, &pNewItem);
        }

    }
}<|endoftext|>


<commit_before>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}
}

void SPXCrossSection::ParseCorrections(void) {
	//Check if grid contains corrections
	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(*pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	std::string mn = "ApplyCorrections: ";

	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	std::cout << cn << mn << ">>>>>>>>>>>>>>>>> APPLY CORRECTIONS <<<<<<<<<<<<<<<<<" << std::endl;

	//Loop over the band bins and make sure they match, if not just do nothing

	unsigned int nBins = pdf->h_PDFBand_results->GetN();
	double *x = pdf->h_PDFBand_results->GetX();
	double *y = pdf->h_PDFBand_results->GetY();
	double *exl = pdf->h_PDFBand_results->GetEXlow();
	double *exh = pdf->h_PDFBand_results->GetEXhigh();
	double *eyl = pdf->h_PDFBand_results->GetEYlow();
	double *eyh = pdf->h_PDFBand_results->GetEYhigh();

	unsigned int nBinsCorr = corrections->GetNumberOfBins();
	double *c_x = &(corrections->GetTotalX().at(0));
	double *c_exl = &(corrections->GetTotalEXL().at(0));
	double *c_exh = &(corrections->GetTotalEXH().at(0));
	double *c_y = &(corrections->GetTotalYCorrections().at(0));
	double *c_eyl = &(corrections->GetTotalEYLCorrections().at(0));
	double *c_eyh = &(corrections->GetTotalEYHCorrections().at(0));

	//Loop over the smallest of the two
	unsigned int n = (nBins < nBinsCorr ? nBins : nBinsCorr);

	for(int i = 0; i < nBins; i++) {
		for(int j = 0; j < nBinsCorr; j++) {

			std::cout << "x[" << i << "] - exl[" << i << "] = " << x[i] - exl[i] << std::endl;
			std::cout << "c_exl[" << j << "] = " << c_exl[j] << std::endl;

			std::cout << "x[" << i << "] + exh[" << i << "] = " << x[i] + exh[i] << std::endl;
			std::cout << "c_exh[" << j << "] = " << c_exh[j] << std::endl;

			//Check for bin match
			if(((x[i] - exl[i]) == c_exl[j]) && ((x[i] + exh[i]) == c_exh[j])) {

				//Bins match; Scale y, eyl, and eyh
				y[i] *= c_y[j];
				eyl[i] *= c_eyl[j];
				eyh[i] *= c_eyh[j];

				break;
			}

			std::cout << "NO MATCH: " << i <<
		}
	}

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<commit_msg>Testing Grid Corrections<commit_after>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}
}

void SPXCrossSection::ParseCorrections(void) {
	//Check if grid contains corrections
	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(*pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	std::string mn = "ApplyCorrections: ";

	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	std::cout << cn << mn << ">>>>>>>>>>>>>>>>> APPLY CORRECTIONS <<<<<<<<<<<<<<<<<" << std::endl;

	//Loop over the band bins and make sure they match, if not just do nothing

	unsigned int nBins = pdf->h_PDFBand_results->GetN();
	double *x = pdf->h_PDFBand_results->GetX();
	double *y = pdf->h_PDFBand_results->GetY();
	double *exl = pdf->h_PDFBand_results->GetEXlow();
	double *exh = pdf->h_PDFBand_results->GetEXhigh();
	double *eyl = pdf->h_PDFBand_results->GetEYlow();
	double *eyh = pdf->h_PDFBand_results->GetEYhigh();

	unsigned int nBinsCorr = corrections->GetNumberOfBins();
	double *c_x = &(corrections->GetTotalX().at(0));
	double *c_exl = &(corrections->GetTotalEXL().at(0));
	double *c_exh = &(corrections->GetTotalEXH().at(0));
	double *c_y = &(corrections->GetTotalYCorrections().at(0));
	double *c_eyl = &(corrections->GetTotalEYLCorrections().at(0));
	double *c_eyh = &(corrections->GetTotalEYHCorrections().at(0));

	//Loop over the smallest of the two
	unsigned int n = (nBins < nBinsCorr ? nBins : nBinsCorr);

	for(int i = 0; i < nBins; i++) {
		for(int j = 0; j < nBinsCorr; j++) {

			std::cout << "x[" << i << "] - exl[" << i << "] = " << x[i] - exl[i] << std::endl;
			std::cout << "c_exl[" << j << "] = " << c_exl[j] << std::endl;

			std::cout << "x[" << i << "] + exh[" << i << "] = " << x[i] + exh[i] << std::endl;
			std::cout << "c_exh[" << j << "] = " << c_exh[j] << std::endl;

			//Check for bin match
			if(((x[i] - exl[i]) == c_exl[j]) && ((x[i] + exh[i]) == c_exh[j])) {

				if(debug) std::cout << cn << mn << "Bins Match (i, j): (" << i << ", " << j << ")" << std::endl;

				//Bins match; Scale y, eyl, and eyh
				y[i] *= c_y[j];
				eyl[i] *= c_eyl[j];
				eyh[i] *= c_eyh[j];

				break;
			}
		}
	}

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<|endoftext|>


<commit_before>/* --------------------------------------------------------------------------

   MusicBrainz -- The Intenet music metadatabase

   Copyright (C) 2000 Robert Kaye

   This library 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 library 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 library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

     $Id$

----------------------------------------------------------------------------*/
#include "musicbrainz.h"

extern "C"
{
#include "mb_c.h"

musicbrainz_t mb_New(void)
{
    return (musicbrainz_t)new MusicBrainz();
}

void mb_Delete(musicbrainz_t o)
{
    delete (MusicBrainz *)o;
}

int mb_SetServer(musicbrainz_t o, char *serverAddr, short serverPort)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetServer(string(serverAddr), serverPort);
}

int mb_SetProxy(musicbrainz_t o,char *proxyAddr, short proxyPort)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetServer(string(proxyAddr), proxyPort);
}

int mb_SetDevice(musicbrainz_t o, char *device)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetDevice(string(device));
}

int mb_GetWebSubmitURL(musicbrainz_t o, char *url, int urlLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   urlString;
    int      ret;

    ret = (int)obj->GetWebSubmitURL(urlString);
    if (ret)
    {
       strncpy(url, urlString.c_str(), urlLen - 1);
       url[urlLen - 1] = 0;
    }
    return ret;
}

int mb_Query(musicbrainz_t o, char *xmlObject)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->Query(string(xmlObject));
}

int mb_QueryWithArgs(musicbrainz_t o, char *xmlObject, char **args)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    vector<string>           *argList;
    string                    temp;
    int                       ret;

    argList = new vector<string>;
    for(; *args; args++)
    {
        temp = string(*args);
        argList->push_back(temp);
    }

    ret = obj->Query(string(xmlObject), argList);

    delete argList;

    return (int)ret;
}

void mb_GetQueryError(musicbrainz_t o, char *error, int maxErrorLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string                    err;

    obj->GetQueryError(err);

    strncpy(error, err.c_str(), maxErrorLen);
    error[maxErrorLen - 1] = 0;
}

int mb_GetResultData(musicbrainz_t o, char *resultName,
                      char *data, int maxDataLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   value;

    value = obj->Data(string(resultName));
    if (value.length() == 0)
       return 0;

    strncpy(data, value.c_str(), maxDataLen);
    data[maxDataLen - 1] = 0;

    return 1;
}

int mb_GetResultInt(musicbrainz_t o, char *resultName)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->DataInt(string(resultName));
}

int mb_Select(musicbrainz_t o, char *selectQuery)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->Select(string(selectQuery));
}

int mb_DoesResultExist(musicbrainz_t o, char *resultName)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->DoesResultExist(string(resultName));
}

int mb_GetResultRDF(musicbrainz_t o,char *xml, int maxXMLLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   xmlString;

    if (!obj->GetResultRDF(xmlString))
       return 0;

    strncpy(xml, xmlString.c_str(), maxXMLLen);
    xml[maxXMLLen - 1] = 0;

    return 1;
}

int mb_GetResultRDFLen(musicbrainz_t o)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   xmlString;

    if (!obj->GetResultRDF(xmlString))
       return 0;

    return xmlString.length();
}

int mb_GetNumItems(musicbrainz_t o)
{
    MusicBrainz *obj = (MusicBrainz *)o;

    return obj->GetNumItems();
}

void mb_SetPCMData(musicbrainz_t o, int samplesPerSecond, int numChannels,
                   int bitsPerSample)
{
    MusicBrainz *obj = (MusicBrainz *)o;

    obj->SetPCMDataInfo(samplesPerSecond, numChannels, bitsPerSample);
}

int mb_GenerateSignature(musicbrainz_t o, char *data, int size,
                         char **signature, char *collectionID)
{
    string strGUID;
    string collID;

    if (!collectionID)
        collID = "EMPTY_COLLECTION";
    else
        collID = string(collectionID, 16);

   MusicBrainz *obj = (MusicBrainz *)o;

   bool retvalue = obj->GenerateSignature(data, size, strGUID, collID);

   if (retvalue) {
       *signature = (char *)malloc(sizeof(char) * 17);
       memset(*signature, '\0', 16);
       strncpy(*signature, strGUID.c_str(), 16);

       return 1;
   }
   return 0;
}

void mb_GenerateSignatureNow(musicbrainz_t o, char **signature,
                             char *collectionID)
{
    string strGUID;
    string collID;

    if (!collectionID)
        collID = "EMPTY_COLLECTION";
    else
        collID = string(collectionID, 16);

   MusicBrainz *obj = (MusicBrainz *)o;

   obj->GenerateSignatureNow(strGUID, collID);

   *signature = (char *)malloc(sizeof(char) * 17);
   memset(*signature, '\0', 16);
   strncpy(*signature, strGUID.c_str(), 16);
}

}
<commit_msg>Moved an extern "C" around<commit_after>/* --------------------------------------------------------------------------

   MusicBrainz -- The Intenet music metadatabase

   Copyright (C) 2000 Robert Kaye

   This library 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 library 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 library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

     $Id$

----------------------------------------------------------------------------*/
#include "musicbrainz.h"

#include "mb_c.h"

extern "C"
{

musicbrainz_t mb_New(void)
{
    return (musicbrainz_t)new MusicBrainz();
}

void mb_Delete(musicbrainz_t o)
{
    delete (MusicBrainz *)o;
}

int mb_SetServer(musicbrainz_t o, char *serverAddr, short serverPort)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetServer(string(serverAddr), serverPort);
}

int mb_SetProxy(musicbrainz_t o,char *proxyAddr, short proxyPort)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetServer(string(proxyAddr), proxyPort);
}

int mb_SetDevice(musicbrainz_t o, char *device)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->SetDevice(string(device));
}

int mb_GetWebSubmitURL(musicbrainz_t o, char *url, int urlLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   urlString;
    int      ret;

    ret = (int)obj->GetWebSubmitURL(urlString);
    if (ret)
    {
       strncpy(url, urlString.c_str(), urlLen - 1);
       url[urlLen - 1] = 0;
    }
    return ret;
}

int mb_Query(musicbrainz_t o, char *xmlObject)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return (int)obj->Query(string(xmlObject));
}

int mb_QueryWithArgs(musicbrainz_t o, char *xmlObject, char **args)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    vector<string>           *argList;
    string                    temp;
    int                       ret;

    argList = new vector<string>;
    for(; *args; args++)
    {
        temp = string(*args);
        argList->push_back(temp);
    }

    ret = obj->Query(string(xmlObject), argList);

    delete argList;

    return (int)ret;
}

void mb_GetQueryError(musicbrainz_t o, char *error, int maxErrorLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string                    err;

    obj->GetQueryError(err);

    strncpy(error, err.c_str(), maxErrorLen);
    error[maxErrorLen - 1] = 0;
}

int mb_GetResultData(musicbrainz_t o, char *resultName,
                      char *data, int maxDataLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   value;

    value = obj->Data(string(resultName));
    if (value.length() == 0)
       return 0;

    strncpy(data, value.c_str(), maxDataLen);
    data[maxDataLen - 1] = 0;

    return 1;
}

int mb_GetResultInt(musicbrainz_t o, char *resultName)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->DataInt(string(resultName));
}

int mb_Select(musicbrainz_t o, char *selectQuery)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->Select(string(selectQuery));
}

int mb_DoesResultExist(musicbrainz_t o, char *resultName)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    return obj->DoesResultExist(string(resultName));
}

int mb_GetResultRDF(musicbrainz_t o,char *xml, int maxXMLLen)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   xmlString;

    if (!obj->GetResultRDF(xmlString))
       return 0;

    strncpy(xml, xmlString.c_str(), maxXMLLen);
    xml[maxXMLLen - 1] = 0;

    return 1;
}

int mb_GetResultRDFLen(musicbrainz_t o)
{
    MusicBrainz *obj = (MusicBrainz *)o;
    string   xmlString;

    if (!obj->GetResultRDF(xmlString))
       return 0;

    return xmlString.length();
}

int mb_GetNumItems(musicbrainz_t o)
{
    MusicBrainz *obj = (MusicBrainz *)o;

    return obj->GetNumItems();
}

void mb_SetPCMData(musicbrainz_t o, int samplesPerSecond, int numChannels,
                   int bitsPerSample)
{
    MusicBrainz *obj = (MusicBrainz *)o;

    obj->SetPCMDataInfo(samplesPerSecond, numChannels, bitsPerSample);
}

int mb_GenerateSignature(musicbrainz_t o, char *data, int size,
                         char **signature, char *collectionID)
{
    string strGUID;
    string collID;

    if (!collectionID)
        collID = "EMPTY_COLLECTION";
    else
        collID = string(collectionID, 16);

   MusicBrainz *obj = (MusicBrainz *)o;

   bool retvalue = obj->GenerateSignature(data, size, strGUID, collID);

   if (retvalue) {
       *signature = (char *)malloc(sizeof(char) * 17);
       memset(*signature, '\0', 16);
       strncpy(*signature, strGUID.c_str(), 16);

       return 1;
   }
   return 0;
}

void mb_GenerateSignatureNow(musicbrainz_t o, char **signature,
                             char *collectionID)
{
    string strGUID;
    string collID;

    if (!collectionID)
        collID = "EMPTY_COLLECTION";
    else
        collID = string(collectionID, 16);

   MusicBrainz *obj = (MusicBrainz *)o;

   obj->GenerateSignatureNow(strGUID, collID);

   *signature = (char *)malloc(sizeof(char) * 17);
   memset(*signature, '\0', 16);
   strncpy(*signature, strGUID.c_str(), 16);
}

}
<|endoftext|>


<commit_before>//===-- PPCBranchSelector.cpp - Emit long conditional branches-----*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

static Statistic<> NumExpanded("ppc-branch-select",
                               "Num branches expanded to long format");

namespace {
  struct VISIBILITY_HIDDEN PPCBSel : public MachineFunctionPass {
    /// OffsetMap - Mapping between BB # and byte offset from start of function.
    std::vector<unsigned> OffsetMap;

    virtual bool runOnMachineFunction(MachineFunction &Fn);

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new PPCBSel();
}

/// getNumBytesForInstruction - Return the number of bytes of code the specified
/// instruction may be.  This returns the maximum number of bytes.
///
static unsigned getNumBytesForInstruction(MachineInstr *MI) {
  switch (MI->getOpcode()) {
  case PPC::COND_BRANCH:
    // while this will be 4 most of the time, if we emit 8 it is just a
    // minor pessimization that saves us from having to worry about
    // keeping the offsets up to date later when we emit long branch glue.
    return 8;
  case PPC::IMPLICIT_DEF_GPRC: // no asm emitted
  case PPC::IMPLICIT_DEF_G8RC: // no asm emitted
  case PPC::IMPLICIT_DEF_F4:   // no asm emitted
  case PPC::IMPLICIT_DEF_F8:   // no asm emitted
  case PPC::IMPLICIT_DEF_VRRC: // no asm emitted
    return 0;
  case PPC::INLINEASM: {       // Inline Asm: Variable size.
    MachineFunction *MF = MI->getParent()->getParent();
    const char *AsmStr = MI->getOperand(0).getSymbolName();
    return MF->getTarget().getTargetAsmInfo()->getInlineAsmLength(AsmStr);
  }
  default:
    return 4; // PowerPC instructions are all 4 bytes
  }
}

bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
  // Running total of instructions encountered since beginning of function
  unsigned ByteCount = 0;

  OffsetMap.resize(Fn.getNumBlockIDs());

  // For each MBB, add its offset to the offset map, and count up its
  // instructions
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;
    OffsetMap[MBB->getNumber()] = ByteCount;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI)
      ByteCount += getNumBytesForInstruction(MBBI);
  }

  // We're about to run over the MBB's again, so reset the ByteCount
  ByteCount = 0;

  // For each MBB, find the conditional branch pseudo instructions, and
  // calculate the difference between the target MBB and the current ICount
  // to decide whether or not to emit a short or long branch.
  //
  // short branch:
  // bCC .L_TARGET_MBB
  //
  // long branch:
  // bInverseCC $PC+8
  // b .L_TARGET_MBB
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI) {
      // We may end up deleting the MachineInstr that MBBI points to, so
      // remember its opcode now so we can refer to it after calling erase()
      unsigned ByteSize = getNumBytesForInstruction(MBBI);
      if (MBBI->getOpcode() != PPC::COND_BRANCH) {
        ByteCount += ByteSize;
        continue;
      }

      // condbranch operands:
      // 0. CR register
      // 1. PPC branch opcode
      // 2. Target MBB
      MachineBasicBlock *DestMBB = MBBI->getOperand(2).getMachineBasicBlock();
      unsigned Opcode = MBBI->getOperand(1).getImmedValue();
      unsigned CRReg = MBBI->getOperand(0).getReg();

      int Displacement = OffsetMap[DestMBB->getNumber()] - ByteCount;
      unsigned Inverted = PPCInstrInfo::invertPPCBranchOpcode(Opcode);

      MachineBasicBlock::iterator MBBJ;
      if (Displacement >= -32768 && Displacement <= 32767) {
        MBBJ = BuildMI(*MBB, MBBI, Opcode, 2).addReg(CRReg).addMBB(DestMBB);
      } else {
        // Long branch, skip next branch instruction (i.e. $PC+8).
        ++NumExpanded;
        BuildMI(*MBB, MBBJ, Inverted, 2).addReg(CRReg).addImm(2);
        MBBJ = BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(DestMBB);
      }

      // Erase the psuedo COND_BRANCH instruction, and then back up the
      // iterator so that when the for loop increments it, we end up in
      // the correct place rather than iterating off the end.
      MBB->erase(MBBI);
      MBBI = MBBJ;
      ByteCount += ByteSize;
    }
  }

  OffsetMap.clear();
  return true;
}

<commit_msg>Typo. Fix the nightly tests.<commit_after>//===-- PPCBranchSelector.cpp - Emit long conditional branches-----*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

static Statistic<> NumExpanded("ppc-branch-select",
                               "Num branches expanded to long format");

namespace {
  struct VISIBILITY_HIDDEN PPCBSel : public MachineFunctionPass {
    /// OffsetMap - Mapping between BB # and byte offset from start of function.
    std::vector<unsigned> OffsetMap;

    virtual bool runOnMachineFunction(MachineFunction &Fn);

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new PPCBSel();
}

/// getNumBytesForInstruction - Return the number of bytes of code the specified
/// instruction may be.  This returns the maximum number of bytes.
///
static unsigned getNumBytesForInstruction(MachineInstr *MI) {
  switch (MI->getOpcode()) {
  case PPC::COND_BRANCH:
    // while this will be 4 most of the time, if we emit 8 it is just a
    // minor pessimization that saves us from having to worry about
    // keeping the offsets up to date later when we emit long branch glue.
    return 8;
  case PPC::IMPLICIT_DEF_GPRC: // no asm emitted
  case PPC::IMPLICIT_DEF_G8RC: // no asm emitted
  case PPC::IMPLICIT_DEF_F4:   // no asm emitted
  case PPC::IMPLICIT_DEF_F8:   // no asm emitted
  case PPC::IMPLICIT_DEF_VRRC: // no asm emitted
    return 0;
  case PPC::INLINEASM: {       // Inline Asm: Variable size.
    MachineFunction *MF = MI->getParent()->getParent();
    const char *AsmStr = MI->getOperand(0).getSymbolName();
    return MF->getTarget().getTargetAsmInfo()->getInlineAsmLength(AsmStr);
  }
  default:
    return 4; // PowerPC instructions are all 4 bytes
  }
}

bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
  // Running total of instructions encountered since beginning of function
  unsigned ByteCount = 0;

  OffsetMap.resize(Fn.getNumBlockIDs());

  // For each MBB, add its offset to the offset map, and count up its
  // instructions
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;
    OffsetMap[MBB->getNumber()] = ByteCount;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI)
      ByteCount += getNumBytesForInstruction(MBBI);
  }

  // We're about to run over the MBB's again, so reset the ByteCount
  ByteCount = 0;

  // For each MBB, find the conditional branch pseudo instructions, and
  // calculate the difference between the target MBB and the current ICount
  // to decide whether or not to emit a short or long branch.
  //
  // short branch:
  // bCC .L_TARGET_MBB
  //
  // long branch:
  // bInverseCC $PC+8
  // b .L_TARGET_MBB
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI) {
      // We may end up deleting the MachineInstr that MBBI points to, so
      // remember its opcode now so we can refer to it after calling erase()
      unsigned ByteSize = getNumBytesForInstruction(MBBI);
      if (MBBI->getOpcode() != PPC::COND_BRANCH) {
        ByteCount += ByteSize;
        continue;
      }

      // condbranch operands:
      // 0. CR register
      // 1. PPC branch opcode
      // 2. Target MBB
      MachineBasicBlock *DestMBB = MBBI->getOperand(2).getMachineBasicBlock();
      unsigned Opcode = MBBI->getOperand(1).getImmedValue();
      unsigned CRReg = MBBI->getOperand(0).getReg();

      int Displacement = OffsetMap[DestMBB->getNumber()] - ByteCount;
      unsigned Inverted = PPCInstrInfo::invertPPCBranchOpcode(Opcode);

      MachineBasicBlock::iterator MBBJ;
      if (Displacement >= -32768 && Displacement <= 32767) {
        MBBJ = BuildMI(*MBB, MBBI, Opcode, 2).addReg(CRReg).addMBB(DestMBB);
      } else {
        // Long branch, skip next branch instruction (i.e. $PC+8).
        ++NumExpanded;
        BuildMI(*MBB, MBBI, Inverted, 2).addReg(CRReg).addImm(2);
        MBBJ = BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(DestMBB);
      }

      // Erase the psuedo COND_BRANCH instruction, and then back up the
      // iterator so that when the for loop increments it, we end up in
      // the correct place rather than iterating off the end.
      MBB->erase(MBBI);
      MBBI = MBBJ;
      ByteCount += ByteSize;
    }
  }

  OffsetMap.clear();
  return true;
}

<|endoftext|>


<commit_before>#include <iostream>

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGraphicsItemGroup>
#include <QGraphicsLineItem>
#include <QGraphicsWidget>
#include <QGraphicsEllipseItem>
#include <QTimer>
#include <QPen>

#include "GUI.h"
#include "TTTAction.h"

GUI::GUI(QWidget* parent) :
		QWidget(parent) {
	createPlayerSelect();
	createBoard();

	QVBoxLayout* layout = new QVBoxLayout();

	layout->addWidget(playerSelect);
	layout->addWidget(view);

	setLayout(layout);

	connect(startGame, SIGNAL(clicked(bool)), this, SLOT(newGame()));
}

void GUI::createPlayerSelect() {
	playerSelect = new QGroupBox(tr("Players"));

	player1 = new QLabel(tr("Cross:"));
	player2 = new QLabel(tr("Circle:"));

	player1Select = new QComboBox();
	player2Select = new QComboBox();

	player1Select->addItem(tr("Human"));
	player1Select->addItem(tr("MCTS AI"));

	player2Select->addItem(tr("Human"));
	player2Select->addItem(tr("MCTS AI"));

	startGame = new QPushButton(tr("Start Game"));

	QHBoxLayout* selectLayout = new QHBoxLayout();

	selectLayout->addWidget(player1);
	selectLayout->addWidget(player1Select);
	selectLayout->addWidget(player2);
	selectLayout->addWidget(player2Select);
	selectLayout->addWidget(startGame);

	playerSelect->setLayout(selectLayout);
}

void GUI::createBoard() {
	scene = new QGraphicsScene();
	scene->setSceneRect(0,0,SCENE_SIZE, SCENE_SIZE);

	pen=new QPen();
	pen->setWidth(PEN_WIDTH);

	fillScene();

	view = new QGraphicsView(scene);

	timer = new QTimer();
	timer->setSingleShot(true);
	connect(timer, SIGNAL(timeout()), this, SLOT(movePlayed()));
}

void GUI::fillScene(){
	scene->clear();

	scene->addItem(createGrid(scene->width()));

	for (int x=0; x<3; x++){
		for (int y=0; y<3; y++){
			QGraphicsItem* empty = createEmpty(BOX_SIZE);
			empty->setPos(x*BOX_SIZE, y*BOX_SIZE);
			scene->addItem(empty);
		}
	}
}

QGraphicsItem* GUI::createCross(qreal size) {
	QGraphicsItemGroup* group = new QGraphicsItemGroup();
	QGraphicsLineItem* line = new QGraphicsLineItem(BOX_PADDING, BOX_PADDING,
			size - BOX_PADDING, size - BOX_PADDING);
	line->setPen(*pen);
	group->addToGroup(line);
	line = new QGraphicsLineItem(size - BOX_PADDING,
			BOX_PADDING, BOX_PADDING, size - BOX_PADDING);
	line->setPen(*pen);
	group->addToGroup(line);
	group->setData(0, CROSS);
	return group;
}

QGraphicsItem* GUI::createCircle(qreal size) {
	QGraphicsEllipseItem* item = new QGraphicsEllipseItem(BOX_PADDING,BOX_PADDING,size-BOX_PADDING*2,size-BOX_PADDING*2);
	item->setPen(*pen);
	item->setData(0, CIRCLE);
	return item;
}

QGraphicsItem* GUI::createEmpty(qreal size){
	QGraphicsWidget* item = new QGraphicsWidget();
	item->resize(size,size);
	item->setFlag(QGraphicsItem::ItemIsSelectable, true);
	item->setData(0, NONE);
	return item;
}

QGraphicsItem* GUI::createGrid(qreal size) {
	QGraphicsItemGroup* group = new QGraphicsItemGroup();

	qreal step = size/3;
	for (int i=1; i<3; i++){
		QGraphicsLineItem* line = new QGraphicsLineItem(i * step, 0, i * step,
				size);
		line->setPen(*pen);
		group->addToGroup(line);
		line = new QGraphicsLineItem(0, i * step, size,
				i * step);
		line->setPen(*pen);
		group->addToGroup(line);
	}

	return group;
}

void GUI::endGame(){
	player1Select->setDisabled(false);
	player2Select->setDisabled(false);
	startGame->setDisabled(false);

	disconnect(scene, 0, this, 0);

	delete board;
	delete ai;
}

void GUI::playMove(int x, int y) {
	QGraphicsItem* item = scene->itemAt(x*BOX_SIZE, y*BOX_SIZE, view->transform());
	scene->removeItem(item);
//	delete item;

	item = board->getCurrentPlayer() == CROSS ? createCross(BOX_SIZE) : createCircle(BOX_SIZE);
	item->setPos(x*BOX_SIZE, y*BOX_SIZE);
	scene->addItem(item);

	item->update(item->boundingRect());

	board->play(x, y);

	// Return control back to event loop for redrawing
	timer->start();
}

bool GUI::isCurrentPlayerHuman() {
	Player current=board->getCurrentPlayer();
	int index1 = player1Select->currentIndex();
	int index2 = player2Select->currentIndex();
	return (current==CROSS && index1==0) || (current==CIRCLE && index2==0);
}

void GUI::movePlayed() {
	if (board->won()!=NONE || board->getTurns()>=9){
		endGame();
		return;
	}

	if (!isCurrentPlayerHuman()){
		TTTAction* action = ai->calculateAction();
		playMove(action->getX(), action->getY());
	}
}

void GUI::newGame(){
	player1Select->setDisabled(true);
	player2Select->setDisabled(true);
	startGame->setDisabled(true);

	connect(scene, SIGNAL(selectionChanged()), this, SLOT(boardClicked()));

	fillScene();

	board = new Board();
	ai = new TTTMCTSPlayer(board);

	// Return control back to event loop for redrawing
	timer->start();
}

void GUI::boardClicked(){
	if (isCurrentPlayerHuman()){
		auto selected = scene->selectedItems();
		if (selected.size()>0){
			QGraphicsItem* item = selected[0];
			if (item->data(0)==NONE){
				playMove(item->x()/BOX_SIZE, item->y()/BOX_SIZE);
			}
		}
	}
}

GUI::~GUI() {

}
<commit_msg>Fix crash in TicTacToe sample<commit_after>#include <iostream>

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGraphicsItemGroup>
#include <QGraphicsLineItem>
#include <QGraphicsWidget>
#include <QGraphicsEllipseItem>
#include <QTimer>
#include <QPen>

#include "GUI.h"
#include "TTTAction.h"

GUI::GUI(QWidget* parent) :
		QWidget(parent), board(nullptr) {
	createPlayerSelect();
	createBoard();

	QVBoxLayout* layout = new QVBoxLayout();

	layout->addWidget(playerSelect);
	layout->addWidget(view);

	setLayout(layout);

	connect(startGame, SIGNAL(clicked(bool)), this, SLOT(newGame()));
}

void GUI::createPlayerSelect() {
	playerSelect = new QGroupBox(tr("Players"));

	player1 = new QLabel(tr("Cross:"));
	player2 = new QLabel(tr("Circle:"));

	player1Select = new QComboBox();
	player2Select = new QComboBox();

	player1Select->addItem(tr("Human"));
	player1Select->addItem(tr("MCTS AI"));

	player2Select->addItem(tr("Human"));
	player2Select->addItem(tr("MCTS AI"));

	startGame = new QPushButton(tr("Start Game"));

	QHBoxLayout* selectLayout = new QHBoxLayout();

	selectLayout->addWidget(player1);
	selectLayout->addWidget(player1Select);
	selectLayout->addWidget(player2);
	selectLayout->addWidget(player2Select);
	selectLayout->addWidget(startGame);

	playerSelect->setLayout(selectLayout);
}

void GUI::createBoard() {
	scene = new QGraphicsScene();
	scene->setSceneRect(0,0,SCENE_SIZE, SCENE_SIZE);

	pen=new QPen();
	pen->setWidth(PEN_WIDTH);

	fillScene();

	view = new QGraphicsView(scene);

	timer = new QTimer();
	timer->setSingleShot(true);
	connect(timer, SIGNAL(timeout()), this, SLOT(movePlayed()));
}

void GUI::fillScene(){
	scene->clear();

	scene->addItem(createGrid(scene->width()));

	for (int x=0; x<3; x++){
		for (int y=0; y<3; y++){
			QGraphicsItem* empty = createEmpty(BOX_SIZE);
			empty->setPos(x*BOX_SIZE, y*BOX_SIZE);
			scene->addItem(empty);
		}
	}
}

QGraphicsItem* GUI::createCross(qreal size) {
	QGraphicsItemGroup* group = new QGraphicsItemGroup();
	QGraphicsLineItem* line = new QGraphicsLineItem(BOX_PADDING, BOX_PADDING,
			size - BOX_PADDING, size - BOX_PADDING);
	line->setPen(*pen);
	group->addToGroup(line);
	line = new QGraphicsLineItem(size - BOX_PADDING,
			BOX_PADDING, BOX_PADDING, size - BOX_PADDING);
	line->setPen(*pen);
	group->addToGroup(line);
	group->setData(0, CROSS);
	return group;
}

QGraphicsItem* GUI::createCircle(qreal size) {
	QGraphicsEllipseItem* item = new QGraphicsEllipseItem(BOX_PADDING,BOX_PADDING,size-BOX_PADDING*2,size-BOX_PADDING*2);
	item->setPen(*pen);
	item->setData(0, CIRCLE);
	return item;
}

QGraphicsItem* GUI::createEmpty(qreal size){
	QGraphicsWidget* item = new QGraphicsWidget();
	item->resize(size,size);
	item->setFlag(QGraphicsItem::ItemIsSelectable, true);
	item->setData(0, NONE);
	return item;
}

QGraphicsItem* GUI::createGrid(qreal size) {
	QGraphicsItemGroup* group = new QGraphicsItemGroup();

	qreal step = size/3;
	for (int i=1; i<3; i++){
		QGraphicsLineItem* line = new QGraphicsLineItem(i * step, 0, i * step,
				size);
		line->setPen(*pen);
		group->addToGroup(line);
		line = new QGraphicsLineItem(0, i * step, size,
				i * step);
		line->setPen(*pen);
		group->addToGroup(line);
	}

	return group;
}

void GUI::endGame(){
	player1Select->setDisabled(false);
	player2Select->setDisabled(false);
	startGame->setDisabled(false);

	disconnect(scene, 0, this, 0);

	delete board;
	delete ai;
}

void GUI::playMove(int x, int y) {
	QGraphicsItem* item = scene->itemAt(x*BOX_SIZE, y*BOX_SIZE, view->transform());
	scene->removeItem(item);
//	delete item;

	item = board->getCurrentPlayer() == CROSS ? createCross(BOX_SIZE) : createCircle(BOX_SIZE);
	item->setPos(x*BOX_SIZE, y*BOX_SIZE);
	scene->addItem(item);

	item->update(item->boundingRect());

	board->play(x, y);

	// Return control back to event loop for redrawing
	timer->start();
}

bool GUI::isCurrentPlayerHuman() {
	Player current=board->getCurrentPlayer();
	int index1 = player1Select->currentIndex();
	int index2 = player2Select->currentIndex();
	return (current==CROSS && index1==0) || (current==CIRCLE && index2==0);
}

void GUI::movePlayed() {
	if (board->won()!=NONE || board->getTurns()>=9){
		endGame();
		return;
	}

	if (!isCurrentPlayerHuman()){
		TTTAction* action = ai->calculateAction();
		playMove(action->getX(), action->getY());
	}
}

void GUI::newGame(){
	player1Select->setDisabled(true);
	player2Select->setDisabled(true);
	startGame->setDisabled(true);

	connect(scene, SIGNAL(selectionChanged()), this, SLOT(boardClicked()));

	fillScene();

	board = new Board();
	ai = new TTTMCTSPlayer(board);

	// Return control back to event loop for redrawing
	timer->start();
}

void GUI::boardClicked(){
	if (board!=nullptr && isCurrentPlayerHuman()){
		auto selected = scene->selectedItems();
		if (selected.size()>0){
			QGraphicsItem* item = selected[0];
			if (item->data(0)==NONE){
				playMove(item->x()/BOX_SIZE, item->y()/BOX_SIZE);
			}
		}
	}
}

GUI::~GUI() {

}
<|endoftext|>


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

#include <v8.h>
#include <node.h>
#include <node_events.h>

#include <string>
#include <archive.h>
#include <archive_entry.h>

#include "archive_helpers.h"

using namespace v8;
using namespace node;

/* TODO: share baseclass in Archive{Reader,Writer} */
class ArchiveReader : public EventEmitter
{
public:

  static Persistent<FunctionTemplate> s_ct;
  static void Init(Handle<Object> target)
  {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->Inherit(EventEmitter::constructor_template);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("ArchiveReader"));

    NODE_SET_PROTOTYPE_METHOD(s_ct, "open_file", OpenFile);

    target->Set(String::NewSymbol("ArchiveReader"),
                s_ct->GetFunction());
  }

protected:
  struct archive *m_arc;

  ArchiveReader() : EventEmitter()
  {
    m_arc = archive_read_new();

    /* TODO: these can dlopen shit. should be doing this in an async thread? */
    archive_read_support_compression_all(m_arc);
    archive_read_support_format_all(m_arc);
  }

  ~ArchiveReader()
  {
    archive_read_finish(m_arc);
  }

  static Handle<Value> New(const Arguments& args)
  {
    HandleScope scope;
    ArchiveReader* ar = new ArchiveReader();
    ar->Wrap(args.This());
    return args.This();
  }

  typedef struct openfile_baton_t {
    int rv;
    std::string errstr;
    std::string path;
    /* TODO: refcount this? */
    ArchiveReader *ar;
    Persistent<Function> cb;
  } openfile_baton_t;

  static int EIO_OpenFile(eio_req *req)
  {
    openfile_baton_t *baton = static_cast<openfile_baton_t *>(req->data);

    baton->rv = archive_read_open_filename(baton->ar->m_arc,
                                           baton->path.c_str(),
                                           10240);
    if (baton->rv != ARCHIVE_OK) {
      baton->errstr = archive_error_string(baton->ar->m_arc);
    }

    return 0;
  }

  static int EIO_AfterOpenFile(eio_req *req)
  {
    HandleScope scope;
    ev_unref(EV_DEFAULT_UC);
    openfile_baton_t *baton = static_cast<openfile_baton_t *>(req->data);

    Local<Value> argv[1];
    bool err = false;

    if (baton->rv != ARCHIVE_OK) {
      err = true;
      argv[0] = Exception::Error(String::New(baton->errstr.c_str()));
      fprintf(stderr, "archive error: %s\n", baton->errstr.c_str());
    }

    TryCatch try_catch;

    baton->ar->Unref();
    baton->cb->Call(Context::GetCurrent()->Global(), err ? 1 : 0, argv);

    if (try_catch.HasCaught()) {
      FatalException(try_catch);
    }

    baton->ar->Emit(String::New("ready"), 0, NULL);
    baton->cb.Dispose();

    delete baton;
    return 0;
  }

  static Handle<Value> OpenFile(const Arguments& args)
  {
    HandleScope scope;

    REQ_STR_ARG(0, filename);
    REQ_FUN_ARG(1, cb);

    ArchiveReader* ar = ObjectWrap::Unwrap<ArchiveReader>(args.This());

    openfile_baton_t *baton = new openfile_baton_t();
    baton->rv = 0;
    baton->path = *filename;
    baton->cb = Persistent<Function>::New(cb);
    baton->ar = ar;

    eio_custom(EIO_OpenFile, EIO_PRI_DEFAULT, EIO_AfterOpenFile, baton);

    ev_ref(EV_DEFAULT_UC);
    ar->Ref();

    return Undefined();
  }
};

Persistent<FunctionTemplate> ArchiveReader::s_ct;

extern "C" {
  void init (Handle<Object> target)
  {
    ArchiveReader::Init(target);
  }
}
<commit_msg>kill fprintf<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <v8.h>
#include <node.h>
#include <node_events.h>

#include <string>
#include <archive.h>
#include <archive_entry.h>

#include "archive_helpers.h"

using namespace v8;
using namespace node;

/* TODO: share baseclass in Archive{Reader,Writer} */
class ArchiveReader : public EventEmitter
{
public:

  static Persistent<FunctionTemplate> s_ct;
  static void Init(Handle<Object> target)
  {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->Inherit(EventEmitter::constructor_template);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("ArchiveReader"));

    NODE_SET_PROTOTYPE_METHOD(s_ct, "open_file", OpenFile);

    target->Set(String::NewSymbol("ArchiveReader"),
                s_ct->GetFunction());
  }

protected:
  struct archive *m_arc;

  ArchiveReader() : EventEmitter()
  {
    m_arc = archive_read_new();

    /* TODO: these can dlopen shit. should be doing this in an async thread? */
    archive_read_support_compression_all(m_arc);
    archive_read_support_format_all(m_arc);
  }

  ~ArchiveReader()
  {
    archive_read_finish(m_arc);
  }

  static Handle<Value> New(const Arguments& args)
  {
    HandleScope scope;
    ArchiveReader* ar = new ArchiveReader();
    ar->Wrap(args.This());
    return args.This();
  }

  typedef struct openfile_baton_t {
    int rv;
    std::string errstr;
    std::string path;
    /* TODO: refcount this? */
    ArchiveReader *ar;
    Persistent<Function> cb;
  } openfile_baton_t;

  static int EIO_OpenFile(eio_req *req)
  {
    openfile_baton_t *baton = static_cast<openfile_baton_t *>(req->data);

    baton->rv = archive_read_open_filename(baton->ar->m_arc,
                                           baton->path.c_str(),
                                           10240);
    if (baton->rv != ARCHIVE_OK) {
      baton->errstr = archive_error_string(baton->ar->m_arc);
    }

    return 0;
  }

  static int EIO_AfterOpenFile(eio_req *req)
  {
    HandleScope scope;
    ev_unref(EV_DEFAULT_UC);
    openfile_baton_t *baton = static_cast<openfile_baton_t *>(req->data);

    Local<Value> argv[1];
    bool err = false;

    if (baton->rv != ARCHIVE_OK) {
      err = true;
      argv[0] = Exception::Error(String::New(baton->errstr.c_str()));
    }

    TryCatch try_catch;

    baton->ar->Unref();
    baton->cb->Call(Context::GetCurrent()->Global(), err ? 1 : 0, argv);

    if (try_catch.HasCaught()) {
      FatalException(try_catch);
    }

    baton->ar->Emit(String::New("ready"), 0, NULL);
    baton->cb.Dispose();

    delete baton;
    return 0;
  }

  static Handle<Value> OpenFile(const Arguments& args)
  {
    HandleScope scope;

    REQ_STR_ARG(0, filename);
    REQ_FUN_ARG(1, cb);

    ArchiveReader* ar = ObjectWrap::Unwrap<ArchiveReader>(args.This());

    openfile_baton_t *baton = new openfile_baton_t();
    baton->rv = 0;
    baton->path = *filename;
    baton->cb = Persistent<Function>::New(cb);
    baton->ar = ar;

    eio_custom(EIO_OpenFile, EIO_PRI_DEFAULT, EIO_AfterOpenFile, baton);

    ev_ref(EV_DEFAULT_UC);
    ar->Ref();

    return Undefined();
  }
};

Persistent<FunctionTemplate> ArchiveReader::s_ct;

extern "C" {
  void init (Handle<Object> target)
  {
    ArchiveReader::Init(target);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#ifndef OVK_CORE_TYPE_TRAITS_HPP_INCLUDED
#define OVK_CORE_TYPE_TRAITS_HPP_INCLUDED

#include <ovk/core/Global.hpp>

#include <type_traits>

namespace ovk {
namespace core {

// Remove cv and reference qualifiers
template <typename T> using remove_cvref = typename std::remove_cv<typename std::remove_reference<T
  >::type>::type;

// Apply const & reference qualifiers of one type to another type
namespace mimicked_ref_internal {
template <typename T, typename U> struct helper {
  using type = U;
};
template <typename T, typename U> struct helper<T &, U> {
  using type = typename std::add_lvalue_reference<U>::type;
};
template <typename T, typename U> struct helper<const T &, U> {
  using type = typename std::add_lvalue_reference<typename std::add_const<U>::type>::type;
};
template <typename T, typename U> struct helper<T &&, U> {
  using type = typename std::add_rvalue_reference<U>::type;
};
template <typename T, typename U> struct helper<const T &&, U> {
  using type = typename std::add_rvalue_reference<typename std::add_const<U>::type>::type;
};
}
template <typename T, typename U> using mimicked_ref = typename mimicked_ref_internal::helper<T,
U>::type;

}}

#endif
<commit_msg>added type trait for detecting whether a function can be called with a specified set of argument types<commit_after>// Copyright (c) 2018 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#ifndef OVK_CORE_TYPE_TRAITS_HPP_INCLUDED
#define OVK_CORE_TYPE_TRAITS_HPP_INCLUDED

#include <ovk/core/Global.hpp>

#include <type_traits>

namespace ovk {
namespace core {

// Remove cv and reference qualifiers
template <typename T> using remove_cvref = typename std::remove_cv<typename std::remove_reference<T
  >::type>::type;

// Apply const & reference qualifiers of one type to another type
namespace mimicked_ref_internal {
template <typename T, typename U> struct helper {
  using type = U;
};
template <typename T, typename U> struct helper<T &, U> {
  using type = typename std::add_lvalue_reference<U>::type;
};
template <typename T, typename U> struct helper<const T &, U> {
  using type = typename std::add_lvalue_reference<typename std::add_const<U>::type>::type;
};
template <typename T, typename U> struct helper<T &&, U> {
  using type = typename std::add_rvalue_reference<U>::type;
};
template <typename T, typename U> struct helper<const T &&, U> {
  using type = typename std::add_rvalue_reference<typename std::add_const<U>::type>::type;
};
}
template <typename T, typename U> using mimicked_ref = typename mimicked_ref_internal::helper<T,
U>::type;

// Check if a function can be called with a specified set of argument types
namespace is_callable_with_internal {
template <typename FRef, typename... Args> constexpr std::true_type Test(decltype(
  std::declval<FRef>()(std::declval<Args>()...)) *) { return {}; }
template <typename FRef, typename... Args> constexpr std::false_type Test(...) { return {}; }
}
template <typename FRef, typename... Args> constexpr bool IsCallableWith() {
  return decltype(is_callable_with_internal::Test<FRef, Args...>(nullptr))::value;
}

}}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ISTREAM_HXX
#define ISTREAM_HXX

#include "pool/Holder.hxx"
#include "pool/Notify.hxx"
#include "io/FdType.hxx"
#include "util/LeakDetector.hxx"

#include <algorithm>

#include <assert.h>

class IstreamHandler;
class IstreamBucketList;

/**
 * An asynchronous input stream.
 *
 * The lifetime of an #istream begins when it is created, and ends
 * with one of the following events:
 *
 * - it is closed manually using istream_close()
 * - it is invalidated by a successful istream_as_fd() call
 * - it has reached end-of-file
 * - an error has occurred
 */
class Istream : PoolHolder, LeakDetector {
    /** data sink */
    IstreamHandler *handler = nullptr;

    /** which types of file descriptors are accepted by the handler? */
    FdTypeMask handler_direct = 0;

#ifndef NDEBUG
    bool reading = false, destroyed = false;

    bool closing = false, eof = false;

    bool in_data = false, available_full_set = false;

    /** how much data was available in the previous invocation? */
    size_t data_available = 0;

    off_t available_partial = 0, available_full = 0;
#endif

protected:
    template<typename P>
    explicit Istream(P &&_pool) noexcept
        :PoolHolder(std::forward<P>(_pool)) {}

    Istream(const Istream &) = delete;
    Istream &operator=(const Istream &) = delete;

    virtual ~Istream() noexcept;

    using PoolHolder::GetPool;

public:
    FdTypeMask GetHandlerDirect() const {
        return handler_direct;
    }

protected:
    bool CheckDirect(FdType type) const {
        return (handler_direct & FdTypeMask(type)) != 0;
    }

    void Consumed(size_t nbytes) {
#ifdef NDEBUG
        (void)nbytes;
#else
        if ((off_t)nbytes >= available_partial)
            available_partial = 0;
        else
            available_partial -= nbytes;

        if (available_full_set) {
            assert((off_t)nbytes <= available_full);

            available_full -= (off_t)nbytes;
        }

        data_available -= std::min(nbytes, data_available);
#endif
    }

    bool InvokeReady() noexcept;
    size_t InvokeData(const void *data, size_t length) noexcept;
    ssize_t InvokeDirect(FdType type, int fd, size_t max_length) noexcept;
    void InvokeEof() noexcept;
    void InvokeError(std::exception_ptr ep) noexcept;

    /**
     * Prepare a call to IstreamHandler::OnEof(); the caller is
     * responsible for actually calling it.
     */
    IstreamHandler &PrepareEof() noexcept;

    /**
     * Prepare a call to IstreamHandler::OnError(); the caller is
     * response for actually calling it.
     */
    IstreamHandler &PrepareError() noexcept;

    void Destroy() noexcept {
        this->~Istream();
        /* no need to free memory from the pool */
    }

    void DestroyEof() noexcept {
        InvokeEof();
        Destroy();
    }

    void DestroyError(std::exception_ptr ep) noexcept {
        InvokeError(ep);
        Destroy();
    }

    /**
     * @return the number of bytes still in the buffer
     */
    template<typename Buffer>
    size_t ConsumeFromBuffer(Buffer &buffer) noexcept {
        auto r = buffer.Read().ToVoid();
        if (r.empty())
            return 0;

        size_t consumed = InvokeData(r.data, r.size);
        if (consumed > 0)
            buffer.Consume(consumed);
        return r.size - consumed;
    }

    /**
     * @return the number of bytes consumed
     */
    template<typename Buffer>
    size_t SendFromBuffer(Buffer &buffer) noexcept {
        auto r = buffer.Read().ToVoid();
        if (r.empty())
            return 0;

        size_t consumed = InvokeData(r.data, r.size);
        if (consumed > 0)
            buffer.Consume(consumed);
        return consumed;
    }

public:
    bool HasHandler() const noexcept {
        assert(!destroyed);

        return handler != nullptr;
    }

    void SetHandler(IstreamHandler &_handler,
                    FdTypeMask _handler_direct=0) noexcept {
        assert(!destroyed);

        handler = &_handler;
        handler_direct = _handler_direct;
    }

    /**
     * Detach the handler from this object.  This should only be done
     * if it is going to be reattached to a new handler right after
     * this call.
     */
    void ClearHandler() noexcept {
        handler = nullptr;
        handler_direct = 0;
    }

    void SetDirect(FdTypeMask _handler_direct) noexcept {
        assert(!destroyed);

        handler_direct = _handler_direct;
    }

    /**
     * How much data is available?
     *
     * @param partial if false, the stream must provide the data size
     * until the end of the stream; for partial, a minimum estimate is
     * ok
     * @return the number of bytes available or -1 if the object does
     * not know
     */
    gcc_pure
    off_t GetAvailable(bool partial) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);

        PoolNotify notify(pool);
        reading = true;
#endif

        off_t available = _GetAvailable(partial);

#ifndef NDEBUG
        assert(available >= -1);
        assert(!notify.IsDestroyed());
        assert(!destroyed);
        assert(reading);

        reading = false;

        if (partial) {
            assert(available_partial == 0 ||
                   available >= available_partial);
            if (available > available_partial)
                available_partial = available;
        } else {
            assert(!available_full_set ||
                   available_full == available);
            if (!available_full_set && available != (off_t)-1) {
                available_full = available;
                available_full_set = true;
            }
        }
#endif

        return available;
    }

    /**
     * Skip data without processing it.  By skipping 0 bytes, you can
     * test whether the stream is able to skip at all.
     *
     * @return the number of bytes skipped or -1 if skipping is not supported
     */
    off_t Skip(off_t length) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);

        PoolNotify notify(pool);
        reading = true;
#endif

        off_t nbytes = _Skip(length);
        assert(nbytes <= length);

#ifndef NDEBUG
        if (notify.IsDestroyed() || destroyed)
            return nbytes;

        reading = false;

        if (nbytes > 0) {
            if (nbytes > available_partial)
                available_partial = 0;
            else
                available_partial -= nbytes;

            assert(!available_full_set ||
                   nbytes < available_full);
            if (available_full_set)
                available_full -= nbytes;
        }
#endif

        return nbytes;
    }

    /**
     * Try to read from the stream.  If the stream can read data
     * without blocking, it must provide data.  It may invoke the
     * callbacks any number of times, supposed that the handler itself
     * doesn't block.
     *
     * If the stream does not provide data immediately (and it is not
     * at EOF yet), it must install an event and invoke the handler
     * later, whenever data becomes available.
     *
     * Whenever the handler reports it is blocking, the responsibility
     * for calling back (and calling this function) is handed back to
     * the istream handler.
     */
    void Read() noexcept  {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;
#endif

        _Read();

#ifndef NDEBUG
        if (notify.IsDestroyed() || destroyed)
            return;

        reading = false;
#endif
    }

    /**
     * Append #IstreamBucket instances with consecutive data from this
     * #Istream to the end of the given #IstreamBucketList.  Unless
     * the returned data marks the end of the stream,
     * IstreamBucketList::SetMore() must be called.
     *
     * On error, this method destroys the #Istream instance and throws
     * std::runtime_error.
     */
    void FillBucketList(IstreamBucketList &list) {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;

        try {
#endif

            _FillBucketList(list);

#ifndef NDEBUG
        } catch (...) {
            if (!notify.IsDestroyed()) {
                assert(destroyed);
            }

            throw;
        }

        assert(!notify.IsDestroyed());
        assert(!destroyed);
        assert(reading);

        reading = false;

#if 0
        // TODO: not possible currently due to include dependencies
        size_t total_size = list.GetTotalBufferSize();
        if ((off_t)total_size > available_partial)
            available_partial = total_size;

        if (!list.HasMore() && !list.HasNonBuffer()) {
            if (available_full_set)
                assert((off_t)total_size == available_full);
            else
                available_full = total_size;
        }
#endif
#endif
    }

    /**
     * Consume data from the #IstreamBucketList filled by
     * FillBucketList().
     *
     * @param nbytes the number of bytes to be consumed; may be more
     * than returned by FillBucketList(), because some of the data may
     * be returned by this Istream's successive siblings
     *
     * @return the number of bytes really consumed by this instance
     * (the rest will be consumed by its siblings)
     */
    size_t ConsumeBucketList(size_t nbytes) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);
#endif

        auto result = _ConsumeBucketList(nbytes);

#ifndef NDEBUG
        assert(!destroyed);
        assert(result <= nbytes);
#endif

        return result;
    }

    /**
     * Close the istream object, and return the remaining data as a
     * file descriptor.  This fd can be read until end-of-stream.
     * Returns -1 if this is not possible (the stream object is still
     * usable).
     */
    int AsFd() noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;
#endif

        int fd = _AsFd();

#ifndef NDEBUG
        assert(!notify.IsDestroyed() || fd < 0);

        if (fd < 0)
            reading = false;
#endif

        return fd;
    }

    /**
     * Close the stream and free resources.  This must not be called
     * after the handler's eof() / abort() callbacks were invoked.
     */
    void Close() noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);

        closing = true;
#endif

        _Close();
    }

    /**
     * Close an istream which was never used, i.e. it does not have a
     * handler yet.
     */
    void CloseUnused() noexcept {
        assert(!HasHandler());

        Close();
    }

protected:
    virtual off_t _GetAvailable(gcc_unused bool partial) noexcept {
        return -1;
    }

    virtual off_t _Skip(gcc_unused off_t length) noexcept {
        return -1;
    }

    virtual void _Read() noexcept = 0;

    virtual void _FillBucketList(IstreamBucketList &list);
    virtual size_t _ConsumeBucketList(size_t nbytes) noexcept;

    virtual int _AsFd() noexcept {
        return -1;
    }

    virtual void _Close() noexcept {
        Destroy();
    }
};

#endif
<commit_msg>istream/istream: fix assert() in AsFd()<commit_after>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ISTREAM_HXX
#define ISTREAM_HXX

#include "pool/Holder.hxx"
#include "pool/Notify.hxx"
#include "io/FdType.hxx"
#include "util/LeakDetector.hxx"

#include <algorithm>

#include <assert.h>

class IstreamHandler;
class IstreamBucketList;

/**
 * An asynchronous input stream.
 *
 * The lifetime of an #istream begins when it is created, and ends
 * with one of the following events:
 *
 * - it is closed manually using istream_close()
 * - it is invalidated by a successful istream_as_fd() call
 * - it has reached end-of-file
 * - an error has occurred
 */
class Istream : PoolHolder, LeakDetector {
    /** data sink */
    IstreamHandler *handler = nullptr;

    /** which types of file descriptors are accepted by the handler? */
    FdTypeMask handler_direct = 0;

#ifndef NDEBUG
    bool reading = false, destroyed = false;

    bool closing = false, eof = false;

    bool in_data = false, available_full_set = false;

    /** how much data was available in the previous invocation? */
    size_t data_available = 0;

    off_t available_partial = 0, available_full = 0;
#endif

protected:
    template<typename P>
    explicit Istream(P &&_pool) noexcept
        :PoolHolder(std::forward<P>(_pool)) {}

    Istream(const Istream &) = delete;
    Istream &operator=(const Istream &) = delete;

    virtual ~Istream() noexcept;

    using PoolHolder::GetPool;

public:
    FdTypeMask GetHandlerDirect() const {
        return handler_direct;
    }

protected:
    bool CheckDirect(FdType type) const {
        return (handler_direct & FdTypeMask(type)) != 0;
    }

    void Consumed(size_t nbytes) {
#ifdef NDEBUG
        (void)nbytes;
#else
        if ((off_t)nbytes >= available_partial)
            available_partial = 0;
        else
            available_partial -= nbytes;

        if (available_full_set) {
            assert((off_t)nbytes <= available_full);

            available_full -= (off_t)nbytes;
        }

        data_available -= std::min(nbytes, data_available);
#endif
    }

    bool InvokeReady() noexcept;
    size_t InvokeData(const void *data, size_t length) noexcept;
    ssize_t InvokeDirect(FdType type, int fd, size_t max_length) noexcept;
    void InvokeEof() noexcept;
    void InvokeError(std::exception_ptr ep) noexcept;

    /**
     * Prepare a call to IstreamHandler::OnEof(); the caller is
     * responsible for actually calling it.
     */
    IstreamHandler &PrepareEof() noexcept;

    /**
     * Prepare a call to IstreamHandler::OnError(); the caller is
     * response for actually calling it.
     */
    IstreamHandler &PrepareError() noexcept;

    void Destroy() noexcept {
        this->~Istream();
        /* no need to free memory from the pool */
    }

    void DestroyEof() noexcept {
        InvokeEof();
        Destroy();
    }

    void DestroyError(std::exception_ptr ep) noexcept {
        InvokeError(ep);
        Destroy();
    }

    /**
     * @return the number of bytes still in the buffer
     */
    template<typename Buffer>
    size_t ConsumeFromBuffer(Buffer &buffer) noexcept {
        auto r = buffer.Read().ToVoid();
        if (r.empty())
            return 0;

        size_t consumed = InvokeData(r.data, r.size);
        if (consumed > 0)
            buffer.Consume(consumed);
        return r.size - consumed;
    }

    /**
     * @return the number of bytes consumed
     */
    template<typename Buffer>
    size_t SendFromBuffer(Buffer &buffer) noexcept {
        auto r = buffer.Read().ToVoid();
        if (r.empty())
            return 0;

        size_t consumed = InvokeData(r.data, r.size);
        if (consumed > 0)
            buffer.Consume(consumed);
        return consumed;
    }

public:
    bool HasHandler() const noexcept {
        assert(!destroyed);

        return handler != nullptr;
    }

    void SetHandler(IstreamHandler &_handler,
                    FdTypeMask _handler_direct=0) noexcept {
        assert(!destroyed);

        handler = &_handler;
        handler_direct = _handler_direct;
    }

    /**
     * Detach the handler from this object.  This should only be done
     * if it is going to be reattached to a new handler right after
     * this call.
     */
    void ClearHandler() noexcept {
        handler = nullptr;
        handler_direct = 0;
    }

    void SetDirect(FdTypeMask _handler_direct) noexcept {
        assert(!destroyed);

        handler_direct = _handler_direct;
    }

    /**
     * How much data is available?
     *
     * @param partial if false, the stream must provide the data size
     * until the end of the stream; for partial, a minimum estimate is
     * ok
     * @return the number of bytes available or -1 if the object does
     * not know
     */
    gcc_pure
    off_t GetAvailable(bool partial) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);

        PoolNotify notify(pool);
        reading = true;
#endif

        off_t available = _GetAvailable(partial);

#ifndef NDEBUG
        assert(available >= -1);
        assert(!notify.IsDestroyed());
        assert(!destroyed);
        assert(reading);

        reading = false;

        if (partial) {
            assert(available_partial == 0 ||
                   available >= available_partial);
            if (available > available_partial)
                available_partial = available;
        } else {
            assert(!available_full_set ||
                   available_full == available);
            if (!available_full_set && available != (off_t)-1) {
                available_full = available;
                available_full_set = true;
            }
        }
#endif

        return available;
    }

    /**
     * Skip data without processing it.  By skipping 0 bytes, you can
     * test whether the stream is able to skip at all.
     *
     * @return the number of bytes skipped or -1 if skipping is not supported
     */
    off_t Skip(off_t length) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);

        PoolNotify notify(pool);
        reading = true;
#endif

        off_t nbytes = _Skip(length);
        assert(nbytes <= length);

#ifndef NDEBUG
        if (notify.IsDestroyed() || destroyed)
            return nbytes;

        reading = false;

        if (nbytes > 0) {
            if (nbytes > available_partial)
                available_partial = 0;
            else
                available_partial -= nbytes;

            assert(!available_full_set ||
                   nbytes < available_full);
            if (available_full_set)
                available_full -= nbytes;
        }
#endif

        return nbytes;
    }

    /**
     * Try to read from the stream.  If the stream can read data
     * without blocking, it must provide data.  It may invoke the
     * callbacks any number of times, supposed that the handler itself
     * doesn't block.
     *
     * If the stream does not provide data immediately (and it is not
     * at EOF yet), it must install an event and invoke the handler
     * later, whenever data becomes available.
     *
     * Whenever the handler reports it is blocking, the responsibility
     * for calling back (and calling this function) is handed back to
     * the istream handler.
     */
    void Read() noexcept  {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;
#endif

        _Read();

#ifndef NDEBUG
        if (notify.IsDestroyed() || destroyed)
            return;

        reading = false;
#endif
    }

    /**
     * Append #IstreamBucket instances with consecutive data from this
     * #Istream to the end of the given #IstreamBucketList.  Unless
     * the returned data marks the end of the stream,
     * IstreamBucketList::SetMore() must be called.
     *
     * On error, this method destroys the #Istream instance and throws
     * std::runtime_error.
     */
    void FillBucketList(IstreamBucketList &list) {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;

        try {
#endif

            _FillBucketList(list);

#ifndef NDEBUG
        } catch (...) {
            if (!notify.IsDestroyed()) {
                assert(destroyed);
            }

            throw;
        }

        assert(!notify.IsDestroyed());
        assert(!destroyed);
        assert(reading);

        reading = false;

#if 0
        // TODO: not possible currently due to include dependencies
        size_t total_size = list.GetTotalBufferSize();
        if ((off_t)total_size > available_partial)
            available_partial = total_size;

        if (!list.HasMore() && !list.HasNonBuffer()) {
            if (available_full_set)
                assert((off_t)total_size == available_full);
            else
                available_full = total_size;
        }
#endif
#endif
    }

    /**
     * Consume data from the #IstreamBucketList filled by
     * FillBucketList().
     *
     * @param nbytes the number of bytes to be consumed; may be more
     * than returned by FillBucketList(), because some of the data may
     * be returned by this Istream's successive siblings
     *
     * @return the number of bytes really consumed by this instance
     * (the rest will be consumed by its siblings)
     */
    size_t ConsumeBucketList(size_t nbytes) noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);
#endif

        auto result = _ConsumeBucketList(nbytes);

#ifndef NDEBUG
        assert(!destroyed);
        assert(result <= nbytes);
#endif

        return result;
    }

    /**
     * Close the istream object, and return the remaining data as a
     * file descriptor.  This fd can be read until end-of-stream.
     * Returns -1 if this is not possible (the stream object is still
     * usable).
     */
    int AsFd() noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);
        assert(!reading);
        assert(!in_data);

        PoolNotify notify(pool);
        reading = true;
#endif

        int fd = _AsFd();

#ifndef NDEBUG
        assert((notify.IsDestroyed() || destroyed) == (fd >= 0));

        if (fd < 0)
            reading = false;
#endif

        return fd;
    }

    /**
     * Close the stream and free resources.  This must not be called
     * after the handler's eof() / abort() callbacks were invoked.
     */
    void Close() noexcept {
#ifndef NDEBUG
        assert(!destroyed);
        assert(!closing);
        assert(!eof);

        closing = true;
#endif

        _Close();
    }

    /**
     * Close an istream which was never used, i.e. it does not have a
     * handler yet.
     */
    void CloseUnused() noexcept {
        assert(!HasHandler());

        Close();
    }

protected:
    virtual off_t _GetAvailable(gcc_unused bool partial) noexcept {
        return -1;
    }

    virtual off_t _Skip(gcc_unused off_t length) noexcept {
        return -1;
    }

    virtual void _Read() noexcept = 0;

    virtual void _FillBucketList(IstreamBucketList &list);
    virtual size_t _ConsumeBucketList(size_t nbytes) noexcept;

    virtual int _AsFd() noexcept {
        return -1;
    }

    virtual void _Close() noexcept {
        Destroy();
    }
};

#endif
<|endoftext|>