<commit_before>#include "stdafx.h"

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

namespace GameServer
{
    namespace Fixes
    {
        void CPlayer::load()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.set_hook(&ATF::CPlayer::Load, &CPlayer::Load);
            core.set_hook(&ATF::CPlayer::CalcPvP, &CPlayer::CalcPvP);
            core.set_hook(&ATF::CPlayer::CalPvpTempCash, &CPlayer::CalPvpTempCash);
            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);
        }

        void CPlayer::unload()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.unset_hook(&ATF::CPlayer::Load);
            core.unset_hook(&ATF::CPlayer::CalcPvP);
            core.unset_hook(&ATF::CPlayer::CalPvpTempCash);
            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);
        }

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

        bool WINAPIV CPlayer::Load(
            ATF::CPlayer * pObj,
            ATF::CUserDB * pUser,
            bool bFirstStart,
            ATF::info::CPlayerLoad366_ptr next)
        {
            bool bResult = next(pObj, pUser, bFirstStart);
            if (bResult && !pObj->m_Param.m_pGuild)
            {
                auto dwDestroyerSerial = ATF::global::g_HolySys->GetDestroyerSerial();
                if (pObj->m_Param.GetCharSerial() != dwDestroyerSerial)
                {
                    pObj->SetLastAttBuff(false);
                }
            }
            return bResult;
        }

        void WINAPIV CPlayer::CalcPvP(
            ATF::CPlayer * pObj,
            ATF::CPlayer * pDier,
            char byKillerObjID,
            ATF::info::CPlayerCalcPvP74_ptr next)
        {
            if (pObj->m_Param.GetRaceCode() == pDier->m_Param.GetRaceCode())
            {
                return;
            }

            next(pObj, pDier, byKillerObjID);
        }

        void WINAPIV CPlayer::CalPvpTempCash(
            ATF::CPlayer * pObj,
            ATF::CPlayer * pDier,
            char byKillerObjID,
            ATF::info::CPlayerCalPvpTempCash52_ptr next)
        {
            if (pObj->m_Param.GetRaceCode() == pDier->m_Param.GetRaceCode())
                return;

            next(pObj, pDier, byKillerObjID);
        }

        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)
        {
            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, pfPos, 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)
        {
            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, pfPos, 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(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);
        }
    }
}<commit_msg>Update fix for create trap/tower<commit_after>#include "stdafx.h"

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

namespace GameServer
{
    namespace Fixes
    {
        void CPlayer::load()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.set_hook(&ATF::CPlayer::Load, &CPlayer::Load);
            core.set_hook(&ATF::CPlayer::CalcPvP, &CPlayer::CalcPvP);
            core.set_hook(&ATF::CPlayer::CalPvpTempCash, &CPlayer::CalPvpTempCash);
            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);
        }

        void CPlayer::unload()
        {
            auto& core = ATF::CATFCore::get_instance();
            core.unset_hook(&ATF::CPlayer::Load);
            core.unset_hook(&ATF::CPlayer::CalcPvP);
            core.unset_hook(&ATF::CPlayer::CalPvpTempCash);
            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);
        }

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

        bool WINAPIV CPlayer::Load(
            ATF::CPlayer * pObj,
            ATF::CUserDB * pUser,
            bool bFirstStart,
            ATF::info::CPlayerLoad366_ptr next)
        {
            bool bResult = next(pObj, pUser, bFirstStart);
            if (bResult && !pObj->m_Param.m_pGuild)
            {
                auto dwDestroyerSerial = ATF::global::g_HolySys->GetDestroyerSerial();
                if (pObj->m_Param.GetCharSerial() != dwDestroyerSerial)
                {
                    pObj->SetLastAttBuff(false);
                }
            }
            return bResult;
        }

        void WINAPIV CPlayer::CalcPvP(
            ATF::CPlayer * pObj,
            ATF::CPlayer * pDier,
            char byKillerObjID,
            ATF::info::CPlayerCalcPvP74_ptr next)
        {
            if (pObj->m_Param.GetRaceCode() == pDier->m_Param.GetRaceCode())
            {
                return;
            }

            next(pObj, pDier, byKillerObjID);
        }

        void WINAPIV CPlayer::CalPvpTempCash(
            ATF::CPlayer * pObj,
            ATF::CPlayer * pDier,
            char byKillerObjID,
            ATF::info::CPlayerCalPvpTempCash52_ptr next)
        {
            if (pObj->m_Param.GetRaceCode() == pDier->m_Param.GetRaceCode())
                return;

            next(pObj, pDier, byKillerObjID);
        }

        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)
        {
            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)
        {
            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(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);
        }
    }
}<|endoftext|>


<commit_before>namespace grndr {

PipelineSpec* PipelineSpec::get_default_2d()
{
  PipelineSpec* spec;

  spec = new(std::nothrow) PipelineSpec;
  if (!spec) { return nullptr; }

  size_t stride = sizeof(GLfloat)*4;

  PipelineSpec::VertexAttribute pos;
  pos.vbo_list_idx = 0;
  pos.index = 0;
  pos.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  pos.stride = stride;
  pos.offset = 0;
  pos.name = "pos";

  PipelineSpec::VertexAttribute uv;
  uv.vbo_list_idx = 0;
  uv.index = 1;
  uv.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  uv.stride = stride;
  uv.offset = sizeof(GLfloat)*2;
  uv.name = "uv";

  spec->attributes.push_back(pos);
  spec->attributes.push_back(uv);

  static char vs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
#define attribute in
#define varying out
#endif

uniform mat4 u_proj;

attribute vec2 pos;
attribute vec2 uv;

varying vec2 v_uv;

void main()
{
  gl_Position = u_proj * vec4(pos, 0.0, 1.0);
  v_uv = uv;
}
)";

  static char fs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
out vec4 FragColor;
#define varying in
#define texture2D texture
#define gl_FragColor FragColor
#endif

uniform sampler2D u_tex;

varying vec2 v_uv;

void main()
{
  gl_FragColor = texture2D(u_tex, v_uv);
}
)";

  if (ogl::Info::gles) {
    fs[9] = vs[9] = '1';
    fs[10] = vs[10] = '0';
    fs[11] = vs[11] = '0';
  }
  else {
    fs[9] = vs[9] = '3';
    fs[10] = vs[10] = '3';
    fs[11] = vs[11] = '0';
  }

  spec->shader.vs = vs;
  spec->shader.fs = fs;
  spec->shader.glFragColor = "FragColor";

  PipelineSpec::Shader::Uniform proj;
  proj.type = PipelineSpec::Shader::Uniform::Type::MAT4;
  proj.name = "u_proj";

  spec->uniforms.push_back(proj);

  return spec;
}

PipelineSpec* PipelineSpec::get_default_3d()
{
  PipelineSpec* spec;

  spec = new(std::nothrow) PipelineSpec;
  if (!spec) { return nullptr; }

  size_t stride = sizeof(GLfloat)*5;

  PipelineSpec::VertexAttribute pos;
  pos.vbo_list_idx = 0;
  pos.index = 0;
  pos.format = PipelineSpec::VertexAttribute::Format::FLOAT3;
  pos.stride = stride;
  pos.offset = 0;
  pos.name = "pos";

  PipelineSpec::VertexAttribute uv;
  uv.vbo_list_idx = 0;
  uv.index = 1;
  uv.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  uv.stride = stride;
  uv.offset = sizeof(GLfloat)*3;
  uv.name = "uv";

  spec->attributes.push_back(pos);
  spec->attributes.push_back(uv);

  static char vs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
#define attribute in
#define varying out
#endif

uniform mat4 u_MVP;

attribute vec3 pos;
attribute vec2 uv;

varying vec2 v_uv;

void main()
{
  gl_Position = u_MVP * vec4(pos, 1.0);
  v_uv = uv;
}
)";

  static char fs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
out vec4 FragColor;
#define varying in
#define texture2D texture
#define gl_FragColor FragColor
#endif

uniform sampler2D u_tex;

varying vec2 v_uv;

void main()
{
  gl_FragColor = texture2D(u_tex, v_uv);
}
)";

  if (ogl::Info::gles) {
    fs[9] = vs[9] = '1';
    fs[10] = vs[10] = '0';
    fs[11] = vs[11] = '0';
  }
  else {
    fs[9] = vs[9] = '3';
    fs[10] = vs[10] = '3';
    fs[11] = vs[11] = '0';
  }

  spec->shader.vs = vs;
  spec->shader.fs = fs;
  spec->shader.glFragColor = "FragColor";

  PipelineSpec::Shader::Uniform proj;
  proj.type = PipelineSpec::Shader::Uniform::Type::MAT4;
  proj.name = "u_MVP";

  spec->uniforms.push_back(proj);

  return spec;
}

bool PipelineSpec::compile_shader()
{
  this->shader.glsl.create_program();

  if (!this->shader.glsl.compile_vert(this->shader.vs)) { return false; }
  if (!this->shader.glsl.compile_frag(this->shader.fs)) { return false; }

  for (const PipelineSpec::VertexAttribute& attr : this->attributes) {
    this->shader.glsl.bind_attr(attr.index, attr.name);
  }

  if (!ogl::Info::gles) {
    this->shader.glsl.bind_frag_data_location(0, this->shader.glFragColor);
  }

  if (!this->shader.glsl.link()) { return false; }

  this->shader.glsl.use();
  for (PipelineSpec::Shader::Uniform& u : this->uniforms) {
    u.location = this->shader.glsl.get_uniform_location(u.name);
    if (u.location < 0) { ogl::ShaderGLSL::use_zero(); return false; }
  }
  ogl::ShaderGLSL::use_zero();

  this->compiled = true;

  return true;
}

} // namespace grndr
<commit_msg>Use static variable instead of dynamic allocate for default shaders<commit_after>namespace grndr {

PipelineSpec* PipelineSpec::get_default_2d()
{
  static PipelineSpec spec;

  size_t stride = sizeof(GLfloat)*4;

  PipelineSpec::VertexAttribute pos;
  pos.vbo_list_idx = 0;
  pos.index = 0;
  pos.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  pos.stride = stride;
  pos.offset = 0;
  pos.name = "pos";

  PipelineSpec::VertexAttribute uv;
  uv.vbo_list_idx = 0;
  uv.index = 1;
  uv.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  uv.stride = stride;
  uv.offset = sizeof(GLfloat)*2;
  uv.name = "uv";

  spec.attributes.push_back(pos);
  spec.attributes.push_back(uv);

  static char vs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
#define attribute in
#define varying out
#endif

uniform mat4 u_proj;

attribute vec2 pos;
attribute vec2 uv;

varying vec2 v_uv;

void main()
{
  gl_Position = u_proj * vec4(pos, 0.0, 1.0);
  v_uv = uv;
}
)";

  static char fs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
out vec4 FragColor;
#define varying in
#define texture2D texture
#define gl_FragColor FragColor
#endif

uniform sampler2D u_tex;

varying vec2 v_uv;

void main()
{
  gl_FragColor = texture2D(u_tex, v_uv);
}
)";

  if (ogl::Info::gles) {
    fs[9] = vs[9] = '1';
    fs[10] = vs[10] = '0';
    fs[11] = vs[11] = '0';
  }
  else {
    fs[9] = vs[9] = '3';
    fs[10] = vs[10] = '3';
    fs[11] = vs[11] = '0';
  }

  spec.shader.vs = vs;
  spec.shader.fs = fs;
  spec.shader.glFragColor = "FragColor";

  PipelineSpec::Shader::Uniform proj;
  proj.type = PipelineSpec::Shader::Uniform::Type::MAT4;
  proj.name = "u_proj";

  spec.uniforms.push_back(proj);

  return &spec;
}

PipelineSpec* PipelineSpec::get_default_3d()
{
  static PipelineSpec spec;

  size_t stride = sizeof(GLfloat)*5;

  PipelineSpec::VertexAttribute pos;
  pos.vbo_list_idx = 0;
  pos.index = 0;
  pos.format = PipelineSpec::VertexAttribute::Format::FLOAT3;
  pos.stride = stride;
  pos.offset = 0;
  pos.name = "pos";

  PipelineSpec::VertexAttribute uv;
  uv.vbo_list_idx = 0;
  uv.index = 1;
  uv.format = PipelineSpec::VertexAttribute::Format::FLOAT2;
  uv.stride = stride;
  uv.offset = sizeof(GLfloat)*3;
  uv.name = "uv";

  spec.attributes.push_back(pos);
  spec.attributes.push_back(uv);

  static char vs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
#define attribute in
#define varying out
#endif

uniform mat4 u_MVP;

attribute vec3 pos;
attribute vec2 uv;

varying vec2 v_uv;

void main()
{
  gl_Position = u_MVP * vec4(pos, 1.0);
  v_uv = uv;
}
)";

  static char fs[] = R"(#version XXX
#ifdef GL_ES
precision mediump float;
#else
out vec4 FragColor;
#define varying in
#define texture2D texture
#define gl_FragColor FragColor
#endif

uniform sampler2D u_tex;

varying vec2 v_uv;

void main()
{
  gl_FragColor = texture2D(u_tex, v_uv);
}
)";

  if (ogl::Info::gles) {
    fs[9] = vs[9] = '1';
    fs[10] = vs[10] = '0';
    fs[11] = vs[11] = '0';
  }
  else {
    fs[9] = vs[9] = '3';
    fs[10] = vs[10] = '3';
    fs[11] = vs[11] = '0';
  }

  spec.shader.vs = vs;
  spec.shader.fs = fs;
  spec.shader.glFragColor = "FragColor";

  PipelineSpec::Shader::Uniform proj;
  proj.type = PipelineSpec::Shader::Uniform::Type::MAT4;
  proj.name = "u_MVP";

  spec.uniforms.push_back(proj);

  return &spec;
}

bool PipelineSpec::compile_shader()
{
  this->shader.glsl.create_program();

  if (!this->shader.glsl.compile_vert(this->shader.vs)) { return false; }
  if (!this->shader.glsl.compile_frag(this->shader.fs)) { return false; }

  for (const PipelineSpec::VertexAttribute& attr : this->attributes) {
    this->shader.glsl.bind_attr(attr.index, attr.name);
  }

  if (!ogl::Info::gles) {
    this->shader.glsl.bind_frag_data_location(0, this->shader.glFragColor);
  }

  if (!this->shader.glsl.link()) { return false; }

  this->shader.glsl.use();
  for (PipelineSpec::Shader::Uniform& u : this->uniforms) {
    u.location = this->shader.glsl.get_uniform_location(u.name);
    if (u.location < 0) { ogl::ShaderGLSL::use_zero(); return false; }
  }
  ogl::ShaderGLSL::use_zero();

  this->compiled = true;

  return true;
}

} // namespace grndr
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "filesearch.h"
#include <cctype>

#include <QtCore/QIODevice>
#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtCore/QCoreApplication>

#include <qtconcurrent/runextensions.h>

using namespace Utils;

static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: canceled. %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched, int filesSize)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 of %3 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched).arg(filesSize);
}

namespace {

void runFileSearch(QFutureInterface<FileSearchResultList> &future,
                   QString searchTerm,
                   FileIterator *files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    int numFilesSearched = 0;
    int numMatches = 0;
    future.setProgressRange(0, files->maxProgress());
    future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    QFile file;
    QBuffer buffer;
    FileSearchResultList results;
    while (files->hasNext()) {
        const QString &s = files->next();
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }
        QIODevice *device;
        if (fileToContentsMap.contains(s)) {
            buffer.setData(fileToContentsMap.value(s).toLocal8Bit());
            device = &buffer;
        } else {
            file.setFileName(s);
            device = &file;
        }
        if (!device->open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!device->atEnd()) {
            if (!firstChunk)
                device->seek(device->pos()-sa.length()+1);

            const QByteArray chunk = device->read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                            (  isalnum((unsigned char)*beforeRegion)
                            || (*beforeRegion == '_')
                            || isalnum((unsigned char)*afterRegion)
                            || (*afterRegion == '_'))) {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            results << FileSearchResult(s, lineNr, QString::fromUtf8(res),
                                                          regionPtr - startOfLastLine, sa.length(),
                                                          QStringList());
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        if (future.isProgressUpdateNeeded()) {
            if (!results.isEmpty()) {
                future.reportResult(results);
                results.clear();
            }
            future.setProgressRange(0, files->maxProgress());
            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
        }
        device->close();
    }
    if (!results.isEmpty()) {
        future.reportResult(results);
        results.clear();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    delete files;
}

void runFileSearchRegExp(QFutureInterface<FileSearchResultList> &future,
                   QString searchTerm,
                   FileIterator *files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    int numFilesSearched = 0;
    int numMatches = 0;
    future.setProgressRange(0, files->maxProgress());
    future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString::fromLatin1("\\b%1\\b").arg(searchTerm);
    const Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    const QRegExp expression(searchTerm, caseSensitivity);

    QFile file;
    QString str;
    QTextStream stream;
    FileSearchResultList results;
    while (files->hasNext()) {
        const QString &s = files->next();
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }

        bool needsToCloseFile = false;
        if (fileToContentsMap.contains(s)) {
            str = fileToContentsMap.value(s);
            stream.setString(&str);
        } else {
            file.setFileName(s);
            if (!file.open(QIODevice::ReadOnly))
                continue;
            needsToCloseFile = true;
            stream.setDevice(&file);
        }
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                results << FileSearchResult(s, lineNr, line,
                                              pos, expression.matchedLength(),
                                              expression.capturedTexts());
                ++numMatches;
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        if (future.isProgressUpdateNeeded()) {
            if (!results.isEmpty()) {
                future.reportResult(results);
                results.clear();
            }
            future.setProgressRange(0, files->maxProgress());
            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
        }
        if (needsToCloseFile)
            file.close();
    }
    if (!results.isEmpty()) {
        future.reportResult(results);
        results.clear();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    delete files;
}

} // namespace

QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm, FileIterator *files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResultList, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearch, searchTerm, files, flags, fileToContentsMap);
}

QFuture<FileSearchResultList> Utils::findInFilesRegExp(const QString &searchTerm, FileIterator *files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResultList, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
}

QString Utils::expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts)
{
    QString result;
    int numCaptures = capturedTexts.size() - 1;
    for (int i = 0; i < replaceText.length(); ++i) {
        QChar c = replaceText.at(i);
        if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
            c = replaceText.at(++i);
            if (c == QLatin1Char('\\')) {
                result += QLatin1Char('\\');
            } else if (c == QLatin1Char('&')) {
                result += QLatin1Char('&');
            } else if (c.isDigit()) {
                int index = c.unicode()-'1';
                if (index < numCaptures) {
                    result += capturedTexts.at(index+1);
                } else {
                    result += QLatin1Char('\\');
                    result += c;
                }
            } else {
                result += QLatin1Char('\\');
                result += c;
            }
        } else if (c == QLatin1Char('&')) {
            result += capturedTexts.at(0);
        } else {
            result += c;
        }
    }
    return result;
}

// #pragma mark -- FileIterator

FileIterator::FileIterator()
    : m_list(QStringList()),
    m_iterator(0),
    m_index(0)
{
}

FileIterator::FileIterator(const QStringList &fileList)
    : m_list(fileList),
    m_iterator(new QStringListIterator(m_list)),
    m_index(0)
{
}

FileIterator::~FileIterator()
{
    if (m_iterator)
        delete m_iterator;
}

bool FileIterator::hasNext() const
{
    Q_ASSERT(m_iterator);
    return m_iterator->hasNext();
}

QString FileIterator::next()
{
    Q_ASSERT(m_iterator);
    ++m_index;
    return m_iterator->next();
}

int FileIterator::maxProgress() const
{
    return m_list.size();
}

int FileIterator::currentProgress() const
{
    return m_index;
}

// #pragma mark -- SubDirFileIterator

namespace {
    const int MAX_PROGRESS = 1000;
}

SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters)
    : m_filters(filters), m_progress(0)
{
    qreal maxPer = MAX_PROGRESS/directories.count();
    foreach (const QString &directoryEntry, directories) {
        if (!directoryEntry.isEmpty()) {
            m_dirs.push(QDir(directoryEntry));
            m_progressValues.push(maxPer);
            m_processedValues.push(false);
        }
    }
}

bool SubDirFileIterator::hasNext() const
{
    if (!m_currentFiles.isEmpty())
        return true;
    while(!m_dirs.isEmpty() && m_currentFiles.isEmpty()) {
        QDir dir = m_dirs.pop();
        qreal dirProgressMax = m_progressValues.pop();
        bool processed = m_processedValues.pop();
        if (dir.exists()) {
            QStringList subDirs;
            if (!processed) {
                subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
            }
            if (subDirs.isEmpty()) {
                QStringList fileEntries = dir.entryList(m_filters,
                    QDir::Files|QDir::Hidden);
                QStringListIterator it(fileEntries);
                it.toBack();
                while (it.hasPrevious()) {
                    const QString &file = it.previous();
                    m_currentFiles.append(dir.path()+ QLatin1Char('/') +file);
                }
                m_progress += dirProgressMax;
            } else {
                qreal subProgress = dirProgressMax/(subDirs.size()+1);
                m_dirs.push(dir);
                m_progressValues.push(subProgress);
                m_processedValues.push(true);
                QStringListIterator it(subDirs);
                it.toBack();
                while (it.hasPrevious()) {
                    const QString &directory = it.previous();
                    m_dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory));
                    m_progressValues.push(subProgress);
                    m_processedValues.push(false);
                }
            }
        } else {
            m_progress += dirProgressMax;
        }
    }
    if (m_currentFiles.isEmpty()) {
        m_progress = MAX_PROGRESS;
        return false;
    }

    return true;
}

QString SubDirFileIterator::next()
{
    Q_ASSERT(!m_currentFiles.isEmpty());
    return m_currentFiles.takeFirst();
}

int SubDirFileIterator::maxProgress() const
{
    return MAX_PROGRESS;
}

int SubDirFileIterator::currentProgress() const
{
    return qMin(qRound(m_progress), MAX_PROGRESS);
}
<commit_msg>Yet another missing utf8 encoding for file search.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "filesearch.h"
#include <cctype>

#include <QtCore/QIODevice>
#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtCore/QCoreApplication>

#include <qtconcurrent/runextensions.h>

using namespace Utils;

static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: canceled. %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched, int filesSize)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 of %3 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched).arg(filesSize);
}

namespace {

void runFileSearch(QFutureInterface<FileSearchResultList> &future,
                   QString searchTerm,
                   FileIterator *files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    int numFilesSearched = 0;
    int numMatches = 0;
    future.setProgressRange(0, files->maxProgress());
    future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    QFile file;
    QBuffer buffer;
    FileSearchResultList results;
    while (files->hasNext()) {
        const QString &s = files->next();
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }
        QIODevice *device;
        if (fileToContentsMap.contains(s)) {
            buffer.setData(fileToContentsMap.value(s).toUtf8());
            device = &buffer;
        } else {
            file.setFileName(s);
            device = &file;
        }
        if (!device->open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!device->atEnd()) {
            if (!firstChunk)
                device->seek(device->pos()-sa.length()+1);

            const QByteArray chunk = device->read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                            (  isalnum((unsigned char)*beforeRegion)
                            || (*beforeRegion == '_')
                            || isalnum((unsigned char)*afterRegion)
                            || (*afterRegion == '_'))) {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            results << FileSearchResult(s, lineNr, QString::fromUtf8(res),
                                                          regionPtr - startOfLastLine, sa.length(),
                                                          QStringList());
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        if (future.isProgressUpdateNeeded()) {
            if (!results.isEmpty()) {
                future.reportResult(results);
                results.clear();
            }
            future.setProgressRange(0, files->maxProgress());
            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
        }
        device->close();
    }
    if (!results.isEmpty()) {
        future.reportResult(results);
        results.clear();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    delete files;
}

void runFileSearchRegExp(QFutureInterface<FileSearchResultList> &future,
                   QString searchTerm,
                   FileIterator *files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    int numFilesSearched = 0;
    int numMatches = 0;
    future.setProgressRange(0, files->maxProgress());
    future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString::fromLatin1("\\b%1\\b").arg(searchTerm);
    const Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    const QRegExp expression(searchTerm, caseSensitivity);

    QFile file;
    QString str;
    QTextStream stream;
    FileSearchResultList results;
    while (files->hasNext()) {
        const QString &s = files->next();
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }

        bool needsToCloseFile = false;
        if (fileToContentsMap.contains(s)) {
            str = fileToContentsMap.value(s);
            stream.setString(&str);
        } else {
            file.setFileName(s);
            if (!file.open(QIODevice::ReadOnly))
                continue;
            needsToCloseFile = true;
            stream.setDevice(&file);
        }
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                results << FileSearchResult(s, lineNr, line,
                                              pos, expression.matchedLength(),
                                              expression.capturedTexts());
                ++numMatches;
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        if (future.isProgressUpdateNeeded()) {
            if (!results.isEmpty()) {
                future.reportResult(results);
                results.clear();
            }
            future.setProgressRange(0, files->maxProgress());
            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
        }
        if (needsToCloseFile)
            file.close();
    }
    if (!results.isEmpty()) {
        future.reportResult(results);
        results.clear();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
    delete files;
}

} // namespace

QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm, FileIterator *files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResultList, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearch, searchTerm, files, flags, fileToContentsMap);
}

QFuture<FileSearchResultList> Utils::findInFilesRegExp(const QString &searchTerm, FileIterator *files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResultList, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
}

QString Utils::expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts)
{
    QString result;
    int numCaptures = capturedTexts.size() - 1;
    for (int i = 0; i < replaceText.length(); ++i) {
        QChar c = replaceText.at(i);
        if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
            c = replaceText.at(++i);
            if (c == QLatin1Char('\\')) {
                result += QLatin1Char('\\');
            } else if (c == QLatin1Char('&')) {
                result += QLatin1Char('&');
            } else if (c.isDigit()) {
                int index = c.unicode()-'1';
                if (index < numCaptures) {
                    result += capturedTexts.at(index+1);
                } else {
                    result += QLatin1Char('\\');
                    result += c;
                }
            } else {
                result += QLatin1Char('\\');
                result += c;
            }
        } else if (c == QLatin1Char('&')) {
            result += capturedTexts.at(0);
        } else {
            result += c;
        }
    }
    return result;
}

// #pragma mark -- FileIterator

FileIterator::FileIterator()
    : m_list(QStringList()),
    m_iterator(0),
    m_index(0)
{
}

FileIterator::FileIterator(const QStringList &fileList)
    : m_list(fileList),
    m_iterator(new QStringListIterator(m_list)),
    m_index(0)
{
}

FileIterator::~FileIterator()
{
    if (m_iterator)
        delete m_iterator;
}

bool FileIterator::hasNext() const
{
    Q_ASSERT(m_iterator);
    return m_iterator->hasNext();
}

QString FileIterator::next()
{
    Q_ASSERT(m_iterator);
    ++m_index;
    return m_iterator->next();
}

int FileIterator::maxProgress() const
{
    return m_list.size();
}

int FileIterator::currentProgress() const
{
    return m_index;
}

// #pragma mark -- SubDirFileIterator

namespace {
    const int MAX_PROGRESS = 1000;
}

SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters)
    : m_filters(filters), m_progress(0)
{
    qreal maxPer = MAX_PROGRESS/directories.count();
    foreach (const QString &directoryEntry, directories) {
        if (!directoryEntry.isEmpty()) {
            m_dirs.push(QDir(directoryEntry));
            m_progressValues.push(maxPer);
            m_processedValues.push(false);
        }
    }
}

bool SubDirFileIterator::hasNext() const
{
    if (!m_currentFiles.isEmpty())
        return true;
    while(!m_dirs.isEmpty() && m_currentFiles.isEmpty()) {
        QDir dir = m_dirs.pop();
        qreal dirProgressMax = m_progressValues.pop();
        bool processed = m_processedValues.pop();
        if (dir.exists()) {
            QStringList subDirs;
            if (!processed) {
                subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
            }
            if (subDirs.isEmpty()) {
                QStringList fileEntries = dir.entryList(m_filters,
                    QDir::Files|QDir::Hidden);
                QStringListIterator it(fileEntries);
                it.toBack();
                while (it.hasPrevious()) {
                    const QString &file = it.previous();
                    m_currentFiles.append(dir.path()+ QLatin1Char('/') +file);
                }
                m_progress += dirProgressMax;
            } else {
                qreal subProgress = dirProgressMax/(subDirs.size()+1);
                m_dirs.push(dir);
                m_progressValues.push(subProgress);
                m_processedValues.push(true);
                QStringListIterator it(subDirs);
                it.toBack();
                while (it.hasPrevious()) {
                    const QString &directory = it.previous();
                    m_dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory));
                    m_progressValues.push(subProgress);
                    m_processedValues.push(false);
                }
            }
        } else {
            m_progress += dirProgressMax;
        }
    }
    if (m_currentFiles.isEmpty()) {
        m_progress = MAX_PROGRESS;
        return false;
    }

    return true;
}

QString SubDirFileIterator::next()
{
    Q_ASSERT(!m_currentFiles.isEmpty());
    return m_currentFiles.takeFirst();
}

int SubDirFileIterator::maxProgress() const
{
    return MAX_PROGRESS;
}

int SubDirFileIterator::currentProgress() const
{
    return qMin(qRound(m_progress), MAX_PROGRESS);
}
<|endoftext|>


<commit_before>//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
using namespace clang;

Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
                                              ExprTy **Strings,
                                              unsigned NumStrings) {
  SourceLocation AtLoc = AtLocs[0];
  StringLiteral* S = static_cast<StringLiteral *>(Strings[0]);
  if (NumStrings > 1) {
    // Concatenate objc strings.
    StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]);
    SourceLocation EndLoc = ES->getSourceRange().getEnd();
    unsigned Length = 0;
    for (unsigned i = 0; i < NumStrings; i++)
      Length += static_cast<StringLiteral *>(Strings[i])->getByteLength();
    char *strBuf = new char [Length];
    char *p = strBuf;
    bool isWide = false;
    for (unsigned i = 0; i < NumStrings; i++) {
      S = static_cast<StringLiteral *>(Strings[i]);
      if (S->isWide())
        isWide = true;
      memcpy(p, S->getStrData(), S->getByteLength());
      p += S->getByteLength();
      delete S;
    }
    S = new StringLiteral(strBuf, Length,
                          isWide, Context.getPointerType(Context.CharTy),
                          AtLoc, EndLoc);
  }

  if (CheckBuiltinCFStringArgument(S))
    return true;

  if (Context.getObjCConstantStringInterface().isNull()) {
    // Initialize the constant string interface lazily. This assumes
    // the NSConstantString interface is seen in this translation unit.
    IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
    ScopedDecl *IFace = LookupScopedDecl(NSIdent, Decl::IDNS_Ordinary,
                                         SourceLocation(), TUScope);
    ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
    if (!strIFace)
      return Diag(S->getLocStart(), diag::err_undef_interface,
                  NSIdent->getName());
    Context.setObjCConstantStringInterface(strIFace);
  }
  QualType t = Context.getObjCConstantStringInterface();
  t = Context.getPointerType(t);
  return new ObjCStringLiteral(S, t, AtLoc);
}

Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
                                                 SourceLocation EncodeLoc,
                                                 SourceLocation LParenLoc,
                                                 TypeTy *Ty,
                                                 SourceLocation RParenLoc) {
  QualType EncodedType = QualType::getFromOpaquePtr(Ty);

  QualType t = Context.getPointerType(Context.CharTy);
  return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
}

Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                                   SourceLocation AtLoc,
                                                   SourceLocation SelLoc,
                                                   SourceLocation LParenLoc,
                                                   SourceLocation RParenLoc) {
  QualType t = Context.getObjCSelType();
  return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
}

Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
                                                   SourceLocation AtLoc,
                                                   SourceLocation ProtoLoc,
                                                   SourceLocation LParenLoc,
                                                   SourceLocation RParenLoc) {
  ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId];
  if (!PDecl) {
    Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName());
    return true;
  }

  QualType t = Context.getObjCProtoType();
  if (t.isNull())
    return true;
  t = Context.getPointerType(t);
  return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc);
}

bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
                                     ObjCMethodDecl *Method) {
  bool anyIncompatibleArgs = false;

  for (unsigned i = 0; i < NumArgs; i++) {
    Expr *argExpr = Args[i];
    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");

    QualType lhsType = Method->getParamDecl(i)->getType();
    QualType rhsType = argExpr->getType();

    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
    if (const ArrayType *ary = lhsType->getAsArrayType())
      lhsType = Context.getPointerType(ary->getElementType());
    else if (lhsType->isFunctionType())
      lhsType = Context.getPointerType(lhsType);

    AssignConvertType Result = CheckSingleAssignmentConstraints(lhsType,
                                                                argExpr);
    if (Args[i] != argExpr) // The expression was converted.
      Args[i] = argExpr; // Make sure we store the converted expression.

    anyIncompatibleArgs |=
      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
                               argExpr, "sending");
  }
  return anyIncompatibleArgs;
}

// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
Sema::ExprResult Sema::ActOnClassMessage(
  Scope *S,
  IdentifierInfo *receiverName, Selector Sel,
  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
{
  assert(receiverName && "missing receiver class name");

  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
  ObjCInterfaceDecl* ClassDecl = 0;
  if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) {
    ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass();
    if (ClassDecl && CurMethodDecl->isInstance()) {
      // Synthesize a cast to the super class. This hack allows us to loosely
      // represent super without creating a special expression node.
      IdentifierInfo &II = Context.Idents.get("self");
      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false);
      QualType superTy = Context.getObjCInterfaceType(ClassDecl);
      superTy = Context.getPointerType(superTy);
      ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(),
                                   SourceLocation(), ReceiverExpr.Val);
      // We are really in an instance method, redirect.
      return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac,
                                  Args, NumArgs);
    }
    // We are sending a message to 'super' within a class method. Do nothing,
    // the receiver will pass through as 'super' (how convenient:-).
  } else
    ClassDecl = getObjCInterfaceDecl(receiverName);

  // FIXME: can ClassDecl ever be null?
  ObjCMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
  QualType returnType;

  // Before we give up, check if the selector is an instance method.
  if (!Method)
    Method = ClassDecl->lookupInstanceMethod(Sel);
  if (!Method) {
    Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
         SourceRange(lbrac, rbrac));
    returnType = Context.getObjCIdType();
  } else {
    returnType = Method->getResultType();
    if (Sel.getNumArgs()) {
      if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
        return true;
    }
  }
  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
                             lbrac, rbrac, ArgExprs, NumArgs);
}

// ActOnInstanceMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
Sema::ExprResult Sema::ActOnInstanceMessage(
  ExprTy *receiver, Selector Sel,
  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
{
  assert(receiver && "missing receiver expression");

  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
  Expr *RExpr = static_cast<Expr *>(receiver);
  QualType receiverType = RExpr->getType();
  QualType returnType;
  ObjCMethodDecl *Method = 0;

  if (receiverType == Context.getObjCIdType() ||
      receiverType == Context.getObjCClassType()) {
    Method = InstanceMethodPool[Sel].Method;
	if (!Method)
	  Method = FactoryMethodPool[Sel].Method;
    if (!Method) {
      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
           SourceRange(lbrac, rbrac));
      returnType = Context.getObjCIdType();
    } else {
      returnType = Method->getResultType();
      if (Sel.getNumArgs())
        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
          return true;
    }
  } else {
    bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType);
    // FIXME (snaroff): checking in this code from Patrick. Needs to be
    // revisited. how do we get the ClassDecl from the receiver expression?
    if (!receiverIsQualId)
      while (receiverType->isPointerType()) {
        PointerType *pointerType =
          static_cast<PointerType*>(receiverType.getTypePtr());
        receiverType = pointerType->getPointeeType();
      }
    ObjCInterfaceDecl* ClassDecl = 0;
    if (ObjCQualifiedInterfaceType *QIT =
        dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) {
      ClassDecl = QIT->getDecl();
      Method = ClassDecl->lookupInstanceMethod(Sel);
      if (!Method) {
        // search protocols
        for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
          ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
            break;
        }
      }
      if (!Method)
        Diag(lbrac, diag::warn_method_not_found_in_protocol,
             std::string("-"), Sel.getName(),
             SourceRange(lbrac, rbrac));
    }
    else if (ObjCQualifiedIdType *QIT =
             dyn_cast<ObjCQualifiedIdType>(receiverType)) {
      // search protocols
      for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
        ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
        if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
          break;
      }
      if (!Method)
        Diag(lbrac, diag::warn_method_not_found_in_protocol,
             std::string("-"), Sel.getName(),
             SourceRange(lbrac, rbrac));
    }
    else {
      if (!isa<ObjCInterfaceType>(receiverType.getTypePtr())) {
        Diag(lbrac, diag::error_bad_receiver_type, receiverType.getAsString());
        return true;
      }
      ClassDecl = static_cast<ObjCInterfaceType*>(
                    receiverType.getTypePtr())->getDecl();
      // FIXME: consider using InstanceMethodPool, since it will be faster
      // than the following method (which can do *many* linear searches). The
      // idea is to add class info to InstanceMethodPool...
      Method = ClassDecl->lookupInstanceMethod(Sel);
    }
    if (!Method) {
      // If we have an implementation in scope, check "private" methods.
      if (ClassDecl)
        if (ObjCImplementationDecl *ImpDecl =
            ObjCImplementations[ClassDecl->getIdentifier()])
          Method = ImpDecl->getInstanceMethod(Sel);
	  // If we still haven't found a method, look in the global pool. This
	  // behavior isn't very desirable, however we need it for GCC
          // compatibility.
	  if (!Method)
	    Method = InstanceMethodPool[Sel].Method;
    }
    if (!Method) {
      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
           SourceRange(lbrac, rbrac));
      returnType = Context.getObjCIdType();
    } else {
      returnType = Method->getResultType();
      if (Sel.getNumArgs())
        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
          return true;
    }
  }
  return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac,
                             ArgExprs, NumArgs);
}
<commit_msg>Sema::ActOnInstanceMessage is generally doing bad things with typedefs, but here I fix just one.  The loop that rips through pointers should use getAsPointerType() not static_cast<PointerType*> to get the pointee.  This fixes a crash on a large testcase.<commit_after>//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
using namespace clang;

Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
                                              ExprTy **Strings,
                                              unsigned NumStrings) {
  SourceLocation AtLoc = AtLocs[0];
  StringLiteral* S = static_cast<StringLiteral *>(Strings[0]);
  if (NumStrings > 1) {
    // Concatenate objc strings.
    StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]);
    SourceLocation EndLoc = ES->getSourceRange().getEnd();
    unsigned Length = 0;
    for (unsigned i = 0; i < NumStrings; i++)
      Length += static_cast<StringLiteral *>(Strings[i])->getByteLength();
    char *strBuf = new char [Length];
    char *p = strBuf;
    bool isWide = false;
    for (unsigned i = 0; i < NumStrings; i++) {
      S = static_cast<StringLiteral *>(Strings[i]);
      if (S->isWide())
        isWide = true;
      memcpy(p, S->getStrData(), S->getByteLength());
      p += S->getByteLength();
      delete S;
    }
    S = new StringLiteral(strBuf, Length,
                          isWide, Context.getPointerType(Context.CharTy),
                          AtLoc, EndLoc);
  }

  if (CheckBuiltinCFStringArgument(S))
    return true;

  if (Context.getObjCConstantStringInterface().isNull()) {
    // Initialize the constant string interface lazily. This assumes
    // the NSConstantString interface is seen in this translation unit.
    IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
    ScopedDecl *IFace = LookupScopedDecl(NSIdent, Decl::IDNS_Ordinary,
                                         SourceLocation(), TUScope);
    ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
    if (!strIFace)
      return Diag(S->getLocStart(), diag::err_undef_interface,
                  NSIdent->getName());
    Context.setObjCConstantStringInterface(strIFace);
  }
  QualType t = Context.getObjCConstantStringInterface();
  t = Context.getPointerType(t);
  return new ObjCStringLiteral(S, t, AtLoc);
}

Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
                                                 SourceLocation EncodeLoc,
                                                 SourceLocation LParenLoc,
                                                 TypeTy *Ty,
                                                 SourceLocation RParenLoc) {
  QualType EncodedType = QualType::getFromOpaquePtr(Ty);

  QualType t = Context.getPointerType(Context.CharTy);
  return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
}

Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                                   SourceLocation AtLoc,
                                                   SourceLocation SelLoc,
                                                   SourceLocation LParenLoc,
                                                   SourceLocation RParenLoc) {
  QualType t = Context.getObjCSelType();
  return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
}

Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
                                                   SourceLocation AtLoc,
                                                   SourceLocation ProtoLoc,
                                                   SourceLocation LParenLoc,
                                                   SourceLocation RParenLoc) {
  ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId];
  if (!PDecl) {
    Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName());
    return true;
  }

  QualType t = Context.getObjCProtoType();
  if (t.isNull())
    return true;
  t = Context.getPointerType(t);
  return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc);
}

bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
                                     ObjCMethodDecl *Method) {
  bool anyIncompatibleArgs = false;

  for (unsigned i = 0; i < NumArgs; i++) {
    Expr *argExpr = Args[i];
    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");

    QualType lhsType = Method->getParamDecl(i)->getType();
    QualType rhsType = argExpr->getType();

    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
    if (const ArrayType *ary = lhsType->getAsArrayType())
      lhsType = Context.getPointerType(ary->getElementType());
    else if (lhsType->isFunctionType())
      lhsType = Context.getPointerType(lhsType);

    AssignConvertType Result = CheckSingleAssignmentConstraints(lhsType,
                                                                argExpr);
    if (Args[i] != argExpr) // The expression was converted.
      Args[i] = argExpr; // Make sure we store the converted expression.

    anyIncompatibleArgs |=
      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
                               argExpr, "sending");
  }
  return anyIncompatibleArgs;
}

// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
Sema::ExprResult Sema::ActOnClassMessage(
  Scope *S,
  IdentifierInfo *receiverName, Selector Sel,
  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
{
  assert(receiverName && "missing receiver class name");

  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
  ObjCInterfaceDecl* ClassDecl = 0;
  if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) {
    ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass();
    if (ClassDecl && CurMethodDecl->isInstance()) {
      // Synthesize a cast to the super class. This hack allows us to loosely
      // represent super without creating a special expression node.
      IdentifierInfo &II = Context.Idents.get("self");
      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false);
      QualType superTy = Context.getObjCInterfaceType(ClassDecl);
      superTy = Context.getPointerType(superTy);
      ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(),
                                   SourceLocation(), ReceiverExpr.Val);
      // We are really in an instance method, redirect.
      return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac,
                                  Args, NumArgs);
    }
    // We are sending a message to 'super' within a class method. Do nothing,
    // the receiver will pass through as 'super' (how convenient:-).
  } else
    ClassDecl = getObjCInterfaceDecl(receiverName);

  // FIXME: can ClassDecl ever be null?
  ObjCMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
  QualType returnType;

  // Before we give up, check if the selector is an instance method.
  if (!Method)
    Method = ClassDecl->lookupInstanceMethod(Sel);
  if (!Method) {
    Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
         SourceRange(lbrac, rbrac));
    returnType = Context.getObjCIdType();
  } else {
    returnType = Method->getResultType();
    if (Sel.getNumArgs()) {
      if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
        return true;
    }
  }
  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
                             lbrac, rbrac, ArgExprs, NumArgs);
}

// ActOnInstanceMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
Sema::ExprResult Sema::ActOnInstanceMessage(
  ExprTy *receiver, Selector Sel,
  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
{
  assert(receiver && "missing receiver expression");

  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
  Expr *RExpr = static_cast<Expr *>(receiver);
  QualType receiverType = RExpr->getType();
  QualType returnType;
  ObjCMethodDecl *Method = 0;

  // FIXME:
  // FIXME: This code is not stripping off type qualifiers or typedefs!
  // FIXME:
  if (receiverType == Context.getObjCIdType() ||
      receiverType == Context.getObjCClassType()) {
    Method = InstanceMethodPool[Sel].Method;
	if (!Method)
	  Method = FactoryMethodPool[Sel].Method;
    if (!Method) {
      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
           SourceRange(lbrac, rbrac));
      returnType = Context.getObjCIdType();
    } else {
      returnType = Method->getResultType();
      if (Sel.getNumArgs())
        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
          return true;
    }
  } else {
    bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType);
    // FIXME (snaroff): checking in this code from Patrick. Needs to be
    // revisited. how do we get the ClassDecl from the receiver expression?
    if (!receiverIsQualId)
      while (const PointerType *PTy = receiverType->getAsPointerType())
        receiverType = PTy->getPointeeType();

    ObjCInterfaceDecl* ClassDecl = 0;
    if (ObjCQualifiedInterfaceType *QIT =
        dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) {
      ClassDecl = QIT->getDecl();
      Method = ClassDecl->lookupInstanceMethod(Sel);
      if (!Method) {
        // search protocols
        for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
          ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
            break;
        }
      }
      if (!Method)
        Diag(lbrac, diag::warn_method_not_found_in_protocol,
             std::string("-"), Sel.getName(),
             SourceRange(lbrac, rbrac));
    }
    else if (ObjCQualifiedIdType *QIT =
             dyn_cast<ObjCQualifiedIdType>(receiverType)) {
      // search protocols
      for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
        ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
        if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
          break;
      }
      if (!Method)
        Diag(lbrac, diag::warn_method_not_found_in_protocol,
             std::string("-"), Sel.getName(),
             SourceRange(lbrac, rbrac));
    }
    else {
      ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType);
      if (OCIReceiver == 0) {
        Diag(lbrac, diag::error_bad_receiver_type, receiverType.getAsString());
        return true;
      }
      ClassDecl = OCIReceiver->getDecl();
      // FIXME: consider using InstanceMethodPool, since it will be faster
      // than the following method (which can do *many* linear searches). The
      // idea is to add class info to InstanceMethodPool...
      Method = ClassDecl->lookupInstanceMethod(Sel);
    }
    if (!Method) {
      // If we have an implementation in scope, check "private" methods.
      if (ClassDecl)
        if (ObjCImplementationDecl *ImpDecl =
            ObjCImplementations[ClassDecl->getIdentifier()])
          Method = ImpDecl->getInstanceMethod(Sel);
	  // If we still haven't found a method, look in the global pool. This
	  // behavior isn't very desirable, however we need it for GCC
          // compatibility.
	  if (!Method)
	    Method = InstanceMethodPool[Sel].Method;
    }
    if (!Method) {
      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
           SourceRange(lbrac, rbrac));
      returnType = Context.getObjCIdType();
    } else {
      returnType = Method->getResultType();
      if (Sel.getNumArgs())
        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
          return true;
    }
  }
  return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac,
                             ArgExprs, NumArgs);
}
<|endoftext|>


<commit_before>#include "NFComm/NFPluginModule/NFPlatform.h"

#if NF_PLATFORM == NF_PLATFORM_WIN
#endif

#pragma comment( lib, "Dbghelp.lib" )

#ifdef NF_DEBUG_MODE

#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DYNAMIC_PLUGIN
#pragma comment( lib, "NFCore_d.lib" )
#pragma comment( lib, "Theron_d.lib" )

#else
#pragma comment( lib, "NFCore_d.lib" )
#pragma comment( lib, "Theron_d.lib" )
#endif

//#pragma comment( lib, "Theron_d.lib" )
#pragma comment( lib, "libglog_static_d.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "NFCore_d.a" )
#pragma comment( lib, "libglog_d.a" )
#pragma comment( lib, "libtherond.a")
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#endif

#else

#if NF_PLATFORM == NF_PLATFORM_WIN
#ifdef NF_DYNAMIC_PLUGIN
#pragma comment( lib, "NFCore.lib" )
#pragma comment( lib, "Theron.lib" )
#else
#pragma comment( lib, "NFCorec.lib" )
#pragma comment( lib, "Theron.lib" )
#endif

//#pragma comment( lib, "Theron.lib" )
#pragma comment( lib, "libglog_static.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "NFCore.a" )
#pragma comment( lib, "libglog.a" )
#pragma comment( lib, "libtherond.a")
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#endif

#endif
<commit_msg>remove glog lib linking<commit_after>#include "NFComm/NFPluginModule/NFPlatform.h"

#if NF_PLATFORM == NF_PLATFORM_WIN
#endif

#pragma comment( lib, "Dbghelp.lib" )

#ifdef NF_DEBUG_MODE

#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DYNAMIC_PLUGIN
#pragma comment( lib, "NFCore_d.lib" )
#pragma comment( lib, "Theron_d.lib" )

#else
#pragma comment( lib, "NFCore_d.lib" )
#pragma comment( lib, "Theron_d.lib" )
#endif

//#pragma comment( lib, "Theron_d.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "NFCore_d.a" )
#pragma comment( lib, "libtherond.a")
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#endif

#else

#if NF_PLATFORM == NF_PLATFORM_WIN
#ifdef NF_DYNAMIC_PLUGIN
#pragma comment( lib, "NFCore.lib" )
#pragma comment( lib, "Theron.lib" )
#else
#pragma comment( lib, "NFCorec.lib" )
#pragma comment( lib, "Theron.lib" )
#endif

//#pragma comment( lib, "Theron.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "NFCore.a" )
#pragma comment( lib, "libtherond.a")
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#endif

#endif
<|endoftext|>