243 lines
8.1 KiB
C++
243 lines
8.1 KiB
C++
/*
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see http://gnu.org/licenses
|
|
*/
|
|
|
|
#include "CBot/CBotVar/CBotVarPointer.h"
|
|
#include "CBot/CBotToken.h"
|
|
#include "CBot/CBotClass.h"
|
|
#include "CBot/CBotVar/CBotVarClass.h"
|
|
|
|
#include "CBot/CBotEnums.h"
|
|
#include "CBot/CBotUtils.h"
|
|
|
|
#include <cassert>
|
|
|
|
namespace CBot
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVarPointer::CBotVarPointer(const CBotToken& name, CBotTypResult& type) : CBotVar(name)
|
|
{
|
|
if ( !type.Eq(CBotTypPointer) &&
|
|
!type.Eq(CBotTypNullPointer) &&
|
|
!type.Eq(CBotTypClass) && // for convenience accepts Class and Intrinsic
|
|
!type.Eq(CBotTypIntrinsic) ) assert(0);
|
|
|
|
m_next = nullptr;
|
|
m_pMyThis = nullptr;
|
|
m_pUserPtr = nullptr;
|
|
|
|
m_type = type;
|
|
if ( !type.Eq(CBotTypNullPointer) )
|
|
m_type.SetType(CBotTypPointer); // anyway, this is a pointer
|
|
m_binit = CBotVar::InitType::UNDEF;
|
|
m_pClass = nullptr;
|
|
m_pVarClass = nullptr; // will be defined by a SetPointer()
|
|
|
|
SetClass(type.GetClass());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVarPointer::~CBotVarPointer()
|
|
{
|
|
if (m_pVarClass != nullptr) m_pVarClass->DecrementUse(); // decrement reference
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::Update(void* pUser)
|
|
{
|
|
if (m_pVarClass != nullptr) m_pVarClass->Update(pUser);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVar* CBotVarPointer::GetItem(const std::string& name)
|
|
{
|
|
if ( m_pVarClass == nullptr) // no existing instance?
|
|
return m_pClass->GetItem(name); // makes the pointer in the class itself
|
|
|
|
return m_pVarClass->GetItem(name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVar* CBotVarPointer::GetItemRef(int nIdent)
|
|
{
|
|
if ( m_pVarClass == nullptr) // no existing instance?
|
|
return m_pClass->GetItemRef(nIdent);// makes the pointer to the class itself
|
|
|
|
return m_pVarClass->GetItemRef(nIdent);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVar* CBotVarPointer::GetItemList()
|
|
{
|
|
if ( m_pVarClass == nullptr) return nullptr;
|
|
return m_pVarClass->GetItemList();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
std::string CBotVarPointer::GetValString() const
|
|
{
|
|
std::string s = "Pointer to ";
|
|
if ( m_pVarClass == nullptr ) s = "Null pointer" ;
|
|
else s += m_pVarClass->GetValString();
|
|
return s;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::ConstructorSet()
|
|
{
|
|
if ( m_pVarClass != nullptr) m_pVarClass->ConstructorSet();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::SetPointer(CBotVar* pVarClass)
|
|
{
|
|
m_binit = CBotVar::InitType::DEF; // init, even on a null pointer
|
|
|
|
if ( m_pVarClass == pVarClass) return; // special, not decrement and reincrement
|
|
// because the decrement can destroy the object
|
|
|
|
if ( pVarClass != nullptr )
|
|
{
|
|
if ( pVarClass->GetType() == CBotTypPointer )
|
|
pVarClass = pVarClass->GetPointer(); // the real pointer to the object
|
|
|
|
// if ( pVarClass->GetType() != CBotTypClass )
|
|
if ( !pVarClass->m_type.Eq(CBotTypClass) )
|
|
assert(0);
|
|
|
|
(static_cast<CBotVarClass*>(pVarClass))->IncrementUse(); // increment the reference
|
|
m_pClass = (static_cast<CBotVarClass*>(pVarClass))->m_pClass;
|
|
m_pUserPtr = pVarClass->m_pUserPtr; // not really necessary
|
|
m_type = CBotTypResult(CBotTypPointer, m_pClass); // what kind of a pointer
|
|
}
|
|
|
|
if ( m_pVarClass != nullptr ) m_pVarClass->DecrementUse();
|
|
m_pVarClass = static_cast<CBotVarClass*>(pVarClass);
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotVarClass* CBotVarPointer::GetPointer()
|
|
{
|
|
if ( m_pVarClass == nullptr ) return nullptr;
|
|
return m_pVarClass->GetPointer();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::SetIdent(long n)
|
|
{
|
|
if ( m_pVarClass == nullptr ) return;
|
|
m_pVarClass->SetIdent( n );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
long CBotVarPointer::GetIdent()
|
|
{
|
|
if ( m_pVarClass == nullptr ) return 0;
|
|
return m_pVarClass->m_ItemIdent;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::SetClass(CBotClass* pClass)
|
|
{
|
|
// int nIdent = 0;
|
|
m_type.m_class = m_pClass = pClass;
|
|
if ( m_pVarClass != nullptr ) m_pVarClass->SetClass(pClass); //, nIdent);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotClass* CBotVarPointer::GetClass()
|
|
{
|
|
if ( m_pVarClass != nullptr ) return m_pVarClass->GetClass();
|
|
|
|
return m_pClass;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool CBotVarPointer::Save1State(std::ostream &ostr)
|
|
{
|
|
if ( m_type.GetClass() != nullptr )
|
|
{
|
|
if (!WriteString(ostr, m_type.GetClass()->GetName())) return false; // name of the class
|
|
}
|
|
else
|
|
{
|
|
if (!WriteString(ostr, "")) return false;
|
|
}
|
|
|
|
if (!WriteLong(ostr, GetIdent())) return false; // the unique reference
|
|
|
|
// also saves the proceedings copies
|
|
return SaveVars(ostr, GetPointer());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void CBotVarPointer::Copy(CBotVar* pSrc, bool bName)
|
|
{
|
|
if ( pSrc->GetType() != CBotTypPointer &&
|
|
pSrc->GetType() != CBotTypNullPointer)
|
|
assert(0);
|
|
|
|
CBotVarPointer* p = static_cast<CBotVarPointer*>(pSrc);
|
|
|
|
if ( bName) *m_token = *p->m_token;
|
|
m_type = p->m_type;
|
|
// m_pVarClass = p->m_pVarClass;
|
|
m_pVarClass = p->GetPointer();
|
|
|
|
if ( m_pVarClass != nullptr )
|
|
m_pVarClass->IncrementUse(); // incerement the reference
|
|
|
|
m_pClass = p->m_pClass;
|
|
m_binit = p->m_binit;
|
|
//- m_bStatic = p->m_bStatic;
|
|
m_next = nullptr;
|
|
m_pMyThis = nullptr;//p->m_pMyThis;
|
|
m_pUserPtr = p->m_pUserPtr;
|
|
|
|
// keeps indentificator the same (by default)
|
|
if (m_ident == 0 ) m_ident = p->m_ident;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool CBotVarPointer::Eq(CBotVar* left, CBotVar* right)
|
|
{
|
|
CBotVarClass* l = left->GetPointer();
|
|
CBotVarClass* r = right->GetPointer();
|
|
|
|
if ( l == r ) return true;
|
|
if ( l == nullptr && r->GetUserPtr() == OBJECTDELETED ) return true;
|
|
if ( r == nullptr && l->GetUserPtr() == OBJECTDELETED ) return true;
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool CBotVarPointer::Ne(CBotVar* left, CBotVar* right)
|
|
{
|
|
CBotVarClass* l = left->GetPointer();
|
|
CBotVarClass* r = right->GetPointer();
|
|
|
|
if ( l == r ) return false;
|
|
if ( l == nullptr && r->GetUserPtr() == OBJECTDELETED ) return false;
|
|
if ( r == nullptr && l->GetUserPtr() == OBJECTDELETED ) return false;
|
|
return true;
|
|
}
|
|
|
|
} // namespace CBot
|