1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-04 18:34:31 +00:00

Merge branch openmw:master into master

This commit is contained in:
Andy Lanzone 2025-07-27 13:21:40 -07:00
commit 31580ffb71
149 changed files with 6962 additions and 5791 deletions

View file

@ -1 +1 @@
VCPKG_DEPS_TAG=2024-11-10 VCPKG_DEPS_TAG=2025-07-23

View file

@ -63,7 +63,7 @@ add_openmw_dir (mwlua
context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings
mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings
postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings
classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings weatherbindings
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus
types/potion types/ingredient types/misc types/repair types/armor types/light types/static types/potion types/ingredient types/misc types/repair types/armor types/light types/static

View file

@ -781,7 +781,6 @@ void OMW::Engine::prepareEngine()
const auto userdefault = mCfgMgr.getUserConfigPath() / "gamecontrollerdb.txt"; const auto userdefault = mCfgMgr.getUserConfigPath() / "gamecontrollerdb.txt";
const auto localdefault = mCfgMgr.getLocalPath() / "gamecontrollerdb.txt"; const auto localdefault = mCfgMgr.getLocalPath() / "gamecontrollerdb.txt";
const auto globaldefault = mCfgMgr.getGlobalPath() / "gamecontrollerdb.txt";
std::filesystem::path userGameControllerdb; std::filesystem::path userGameControllerdb;
if (std::filesystem::exists(userdefault)) if (std::filesystem::exists(userdefault))
@ -790,9 +789,13 @@ void OMW::Engine::prepareEngine()
std::filesystem::path gameControllerdb; std::filesystem::path gameControllerdb;
if (std::filesystem::exists(localdefault)) if (std::filesystem::exists(localdefault))
gameControllerdb = localdefault; gameControllerdb = localdefault;
else if (std::filesystem::exists(globaldefault)) else if (!mCfgMgr.getGlobalPath().empty())
{
const auto globaldefault = mCfgMgr.getGlobalPath() / "gamecontrollerdb.txt";
if (std::filesystem::exists(globaldefault))
gameControllerdb = globaldefault; gameControllerdb = globaldefault;
// else if it doesn't exist, pass in an empty string }
// else if it doesn't exist, pass in an empty path
// gui needs our shaders path before everything else // gui needs our shaders path before everything else
mResourceSystem->getSceneManager()->setShaderPath(mResDir / "shaders"); mResourceSystem->getSceneManager()->setShaderPath(mResDir / "shaders");

View file

@ -22,6 +22,7 @@
namespace osg namespace osg
{ {
class Vec3f; class Vec3f;
class Vec4f;
class Matrixf; class Matrixf;
class Quat; class Quat;
class Image; class Image;
@ -93,6 +94,7 @@ namespace MWWorld
class RefData; class RefData;
class Cell; class Cell;
class DateTimeManager; class DateTimeManager;
class Weather;
typedef std::vector<std::pair<MWWorld::Ptr, MWMechanics::Movement>> PtrMovementList; typedef std::vector<std::pair<MWWorld::Ptr, MWMechanics::Movement>> PtrMovementList;
} }
@ -216,9 +218,21 @@ namespace MWBase
virtual void changeWeather(const ESM::RefId& region, const unsigned int id) = 0; virtual void changeWeather(const ESM::RefId& region, const unsigned int id) = 0;
virtual int getCurrentWeather() const = 0; virtual void changeWeather(const ESM::RefId& region, const ESM::RefId& id) = 0;
virtual int getNextWeather() const = 0; virtual const std::vector<MWWorld::Weather>& getAllWeather() const = 0;
virtual int getCurrentWeatherScriptId() const = 0;
virtual const MWWorld::Weather& getCurrentWeather() const = 0;
virtual const MWWorld::Weather* getWeather(size_t index) const = 0;
virtual const MWWorld::Weather* getWeather(const ESM::RefId& id) const = 0;
virtual int getNextWeatherScriptId() const = 0;
virtual const MWWorld::Weather* getNextWeather() const = 0;
virtual float getWeatherTransition() const = 0; virtual float getWeatherTransition() const = 0;
@ -478,6 +492,7 @@ namespace MWBase
// Allow NPCs to use torches? // Allow NPCs to use torches?
virtual bool useTorches() const = 0; virtual bool useTorches() const = 0;
virtual const osg::Vec4f& getSunLightPosition() const = 0;
virtual float getSunVisibility() const = 0; virtual float getSunVisibility() const = 0;
virtual float getSunPercentage() const = 0; virtual float getSunPercentage() const = 0;

View file

@ -501,7 +501,7 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
case ESM::DialogueCondition::Function_Weather: case ESM::DialogueCondition::Function_Weather:
return MWBase::Environment::get().getWorld()->getCurrentWeather(); return MWBase::Environment::get().getWorld()->getCurrentWeatherScriptId();
case ESM::DialogueCondition::Function_Reputation: case ESM::DialogueCondition::Function_Reputation:
if (!mActor.getClass().isNpc()) if (!mActor.getClass().isNpc())

View file

@ -27,6 +27,7 @@
#include "magicbindings.hpp" #include "magicbindings.hpp"
#include "soundbindings.hpp" #include "soundbindings.hpp"
#include "stats.hpp" #include "stats.hpp"
#include "weatherbindings.hpp"
namespace MWLua namespace MWLua
{ {
@ -104,6 +105,9 @@ namespace MWLua
api["land"] = context.cachePackage("openmw_core_land", [context]() { return initCoreLandBindings(context); }); api["land"] = context.cachePackage("openmw_core_land", [context]() { return initCoreLandBindings(context); });
api["weather"]
= context.cachePackage("openmw_core_weather", [context]() { return initCoreWeatherBindings(context); });
api["factions"] api["factions"]
= context.cachePackage("openmw_core_factions", [context]() { return initCoreFactionBindings(context); }); = context.cachePackage("openmw_core_factions", [context]() { return initCoreFactionBindings(context); });
api["dialogue"] api["dialogue"]

View file

@ -0,0 +1,185 @@
#include "weatherbindings.hpp"
#include <osg/Vec4f>
#include <components/esm3/loadregn.hpp>
#include <components/lua/util.hpp>
#include <components/misc/color.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/weather.hpp"
#include "context.hpp"
namespace
{
class WeatherStore
{
public:
const MWWorld::Weather* get(size_t index) const
{
return MWBase::Environment::get().getWorld()->getWeather(index);
}
const MWWorld::Weather* get(const ESM::RefId& id) const
{
return MWBase::Environment::get().getWorld()->getWeather(id);
}
size_t size() const { return MWBase::Environment::get().getWorld()->getAllWeather().size(); }
};
Misc::Color color(const osg::Vec4f& color)
{
return Misc::Color(color.r(), color.g(), color.b(), color.a());
}
}
namespace MWLua
{
sol::table initCoreWeatherBindings(const Context& context)
{
sol::state_view lua = context.sol();
sol::table api(lua, sol::create);
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
auto weatherT = lua.new_usertype<MWWorld::Weather>("Weather");
weatherT[sol::meta_function::to_string]
= [](const MWWorld::Weather& w) -> std::string { return "Weather[" + w.mName + "]"; };
weatherT["name"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mName; });
weatherT["windSpeed"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mWindSpeed; });
weatherT["cloudSpeed"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mCloudSpeed; });
weatherT["cloudTexture"] = sol::readonly_property([vfs](const MWWorld::Weather& w) {
return Misc::ResourceHelpers::correctTexturePath(w.mCloudTexture, vfs);
});
weatherT["cloudsMaximumPercent"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mCloudsMaximumPercent; });
weatherT["isStorm"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mIsStorm; });
weatherT["stormDirection"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mStormDirection; });
weatherT["glareView"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mGlareView; });
weatherT["rainSpeed"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainSpeed; });
weatherT["rainEntranceSpeed"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainEntranceSpeed; });
weatherT["rainEffect"] = sol::readonly_property([](const MWWorld::Weather& w) -> sol::optional<std::string> {
if (w.mRainEffect.empty())
return sol::nullopt;
return w.mRainEffect;
});
weatherT["rainMaxRaindrops"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainMaxRaindrops; });
weatherT["rainDiameter"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainDiameter; });
weatherT["rainThreshold"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainThreshold; });
weatherT["rainMaxHeight"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainMaxHeight; });
weatherT["rainMinHeight"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainMinHeight; });
weatherT["rainLoopSoundID"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mRainLoopSoundID.serializeText(); });
weatherT["thunderSoundID"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
for (const auto& soundId : w.mThunderSoundID)
result.add(soundId.serializeText());
return result;
});
weatherT["sunDiscSunsetColor"]
= sol::readonly_property([](const MWWorld::Weather& w) { return color(w.mSunDiscSunsetColor); });
weatherT["ambientLoopSoundID"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mAmbientLoopSoundID.serializeText(); });
weatherT["ambientColor"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
result["sunrise"] = color(w.mAmbientColor.getSunriseValue());
result["day"] = color(w.mAmbientColor.getDayValue());
result["sunset"] = color(w.mAmbientColor.getSunsetValue());
result["night"] = color(w.mAmbientColor.getNightValue());
return result;
});
weatherT["fogColor"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
result["sunrise"] = color(w.mFogColor.getSunriseValue());
result["day"] = color(w.mFogColor.getDayValue());
result["sunset"] = color(w.mFogColor.getSunsetValue());
result["night"] = color(w.mFogColor.getNightValue());
return result;
});
weatherT["skyColor"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
result["sunrise"] = color(w.mSkyColor.getSunriseValue());
result["day"] = color(w.mSkyColor.getDayValue());
result["sunset"] = color(w.mSkyColor.getSunsetValue());
result["night"] = color(w.mSkyColor.getNightValue());
return result;
});
weatherT["sunColor"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
result["sunrise"] = color(w.mSunColor.getSunriseValue());
result["day"] = color(w.mSunColor.getDayValue());
result["sunset"] = color(w.mSunColor.getSunsetValue());
result["night"] = color(w.mSunColor.getNightValue());
return result;
});
weatherT["landFogDepth"] = sol::readonly_property([lua](const MWWorld::Weather& w) {
sol::table result(lua, sol::create);
result["sunrise"] = w.mLandFogDepth.getSunriseValue();
result["day"] = w.mLandFogDepth.getDayValue();
result["sunset"] = w.mLandFogDepth.getSunsetValue();
result["night"] = w.mLandFogDepth.getNightValue();
return result;
});
weatherT["particleEffect"]
= sol::readonly_property([](const MWWorld::Weather& w) -> sol::optional<std::string> {
if (w.mParticleEffect.empty())
return sol::nullopt;
return w.mParticleEffect;
});
weatherT["distantLandFogFactor"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mDL.FogFactor; });
weatherT["distantLandFogOffset"]
= sol::readonly_property([](const MWWorld::Weather& w) { return w.mDL.FogOffset; });
weatherT["scriptId"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mScriptId; });
weatherT["recordId"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mId.serializeText(); });
api["getCurrent"] = []() { return MWBase::Environment::get().getWorld()->getCurrentWeather(); };
api["getNext"]
= []() -> const MWWorld::Weather* { return MWBase::Environment::get().getWorld()->getNextWeather(); };
api["getTransition"] = []() { return MWBase::Environment::get().getWorld()->getWeatherTransition(); };
api["changeWeather"] = [](std::string_view regionId, const MWWorld::Weather& weather) {
ESM::RefId region = ESM::RefId::deserializeText(regionId);
MWBase::Environment::get().getESMStore()->get<ESM::Region>().find(region);
MWBase::Environment::get().getWorld()->changeWeather(region, weather.mId);
};
sol::usertype<WeatherStore> storeT = lua.new_usertype<WeatherStore>("WeatherWorldStore");
storeT[sol::meta_function::to_string]
= [](const WeatherStore& store) { return "{" + std::to_string(store.size()) + " Weather records}"; };
storeT[sol::meta_function::length] = [](const WeatherStore& store) { return store.size(); };
storeT[sol::meta_function::index] = sol::overload(
[](const WeatherStore& store, size_t index) -> const MWWorld::Weather* {
return store.get(LuaUtil::fromLuaIndex(index));
},
[](const WeatherStore& store, std::string_view id) -> const MWWorld::Weather* {
return store.get(ESM::RefId::deserializeText(id));
});
storeT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
// Provide access to the store.
api["records"] = WeatherStore{};
api["getCurrentSunLightDirection"] = []() {
osg::Vec4f sunPos = MWBase::Environment::get().getWorld()->getSunLightPosition();
// normalize to get the direction towards the sun
sunPos.normalize();
// and invert it to get the direction of the sun light
return -sunPos;
};
api["getCurrentSunVisibility"] = []() { return MWBase::Environment::get().getWorld()->getSunVisibility(); };
api["getCurrentSunPercentage"] = []() { return MWBase::Environment::get().getWorld()->getSunPercentage(); };
api["getCurrentWindSpeed"] = []() { return MWBase::Environment::get().getWorld()->getWindSpeed(); };
api["getCurrentStormDirection"] = []() { return MWBase::Environment::get().getWorld()->getStormDirection(); };
return LuaUtil::makeReadOnly(api);
}
}

View file

@ -0,0 +1,14 @@
#ifndef MWLUA_WEATHERBINDINGS_H
#define MWLUA_WEATHERBINDINGS_H
#include <sol/forward.hpp>
namespace MWLua
{
struct Context;
sol::table initCoreWeatherBindings(const Context&);
}
#endif // MWLUA_WEATHERBINDINGS_H

View file

@ -73,6 +73,21 @@ namespace
namespace MWMechanics namespace MWMechanics
{ {
struct ActiveSpells::UpdateContext
{
bool mUpdatedEnemy = false;
bool mUpdatedHitOverlay = false;
bool mUpdateSpellWindow = false;
bool mPlayNonLooping = false;
bool mEraseRemoved = false;
bool mUpdate;
UpdateContext(bool update)
: mUpdate(update)
{
}
};
ActiveSpells::IterationGuard::IterationGuard(ActiveSpells& spells) ActiveSpells::IterationGuard::IterationGuard(ActiveSpells& spells)
: mActiveSpells(spells) : mActiveSpells(spells)
{ {
@ -256,8 +271,9 @@ namespace MWMechanics
++spellIt; ++spellIt;
} }
UpdateContext context(duration > 0.f);
for (const auto& spell : mQueue) for (const auto& spell : mQueue)
addToSpells(ptr, spell); addToSpells(ptr, spell, context);
mQueue.clear(); mQueue.clear();
// Vanilla only does this on cell change I think // Vanilla only does this on cell change I think
@ -267,20 +283,17 @@ namespace MWMechanics
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power
&& !isSpellActive(spell->mId)) && !isSpellActive(spell->mId))
{ {
mSpells.emplace_back(ActiveSpellParams{ spell, ptr, true }); initParams(ptr, ActiveSpellParams{ spell, ptr, true }, context);
mSpells.back().setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId());
} }
} }
bool updateSpellWindow = false;
bool playNonLooping = false;
if (ptr.getClass().hasInventoryStore(ptr) if (ptr.getClass().hasInventoryStore(ptr)
&& !(creatureStats.isDead() && !creatureStats.isDeathAnimationFinished())) && !(creatureStats.isDead() && !creatureStats.isDeathAnimationFinished()))
{ {
auto& store = ptr.getClass().getInventoryStore(ptr); auto& store = ptr.getClass().getInventoryStore(ptr);
if (store.getInvListener() != nullptr) if (store.getInvListener() != nullptr)
{ {
playNonLooping = !store.isFirstEquip(); context.mPlayNonLooping = !store.isFirstEquip();
const auto world = MWBase::Environment::get().getWorld(); const auto world = MWBase::Environment::get().getWorld();
for (int slotIndex = 0; slotIndex < MWWorld::InventoryStore::Slots; slotIndex++) for (int slotIndex = 0; slotIndex < MWWorld::InventoryStore::Slots; slotIndex++)
{ {
@ -306,18 +319,40 @@ namespace MWMechanics
// invisibility manually // invisibility manually
purgeEffect(ptr, ESM::MagicEffect::Invisibility); purgeEffect(ptr, ESM::MagicEffect::Invisibility);
applyPurges(ptr); applyPurges(ptr);
ActiveSpellParams& params = mSpells.emplace_back(ActiveSpellParams{ *slot, enchantment, ptr }); ActiveSpellParams* params = initParams(ptr, ActiveSpellParams{ *slot, enchantment, ptr }, context);
params.setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId()); if (params)
updateSpellWindow = true; context.mUpdateSpellWindow = true;
} }
} }
} }
const MWWorld::Ptr player = MWMechanics::getPlayer(); const MWWorld::Ptr player = MWMechanics::getPlayer();
bool updatedHitOverlay = false;
bool updatedEnemy = false;
// Update effects // Update effects
context.mEraseRemoved = true;
for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();) for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();)
{
updateActiveSpell(ptr, duration, spellIt, context);
}
if (Settings::game().mClassicCalmSpellsBehavior)
{
ESM::MagicEffect::Effects effect
= ptr.getClass().isNpc() ? ESM::MagicEffect::CalmHumanoid : ESM::MagicEffect::CalmCreature;
if (creatureStats.getMagicEffects().getOrDefault(effect).getMagnitude() > 0.f)
creatureStats.getAiSequence().stopCombat();
}
if (ptr == player && context.mUpdateSpellWindow)
{
// Something happened with the spell list -- possibly while the game is paused,
// so we want to make the spell window get the memo.
// We don't normally want to do this, so this targets constant enchantments.
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
}
}
bool ActiveSpells::updateActiveSpell(
const MWWorld::Ptr& ptr, float duration, Collection::iterator& spellIt, UpdateContext& context)
{ {
const auto caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId( const auto caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(
spellIt->mCasterActorId); // Maybe make this search outside active grid? spellIt->mCasterActorId); // Maybe make this search outside active grid?
@ -325,7 +360,7 @@ namespace MWMechanics
std::optional<ActiveSpellParams> reflected; std::optional<ActiveSpellParams> reflected;
for (auto it = spellIt->mEffects.begin(); it != spellIt->mEffects.end();) for (auto it = spellIt->mEffects.begin(); it != spellIt->mEffects.end();)
{ {
auto result = applyMagicEffect(ptr, caster, *spellIt, *it, duration, playNonLooping); auto result = applyMagicEffect(ptr, caster, *spellIt, *it, duration, context.mPlayNonLooping);
if (result.mType == MagicApplicationResult::Type::REFLECTED) if (result.mType == MagicApplicationResult::Type::REFLECTED)
{ {
if (!reflected) if (!reflected)
@ -344,16 +379,17 @@ namespace MWMechanics
it = spellIt->mEffects.erase(it); it = spellIt->mEffects.erase(it);
else else
{ {
const MWWorld::Ptr player = MWMechanics::getPlayer();
++it; ++it;
if (!updatedEnemy && result.mShowHealth && caster == player && ptr != player) if (!context.mUpdatedEnemy && result.mShowHealth && caster == player && ptr != player)
{ {
MWBase::Environment::get().getWindowManager()->setEnemy(ptr); MWBase::Environment::get().getWindowManager()->setEnemy(ptr);
updatedEnemy = true; context.mUpdatedEnemy = true;
} }
if (!updatedHitOverlay && result.mShowHit && ptr == player) if (!context.mUpdatedHitOverlay && result.mShowHit && ptr == player)
{ {
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
updatedHitOverlay = true; context.mUpdatedHitOverlay = true;
} }
} }
removedSpell = applyPurges(ptr, &spellIt, &it); removedSpell = applyPurges(ptr, &spellIt, &it);
@ -375,13 +411,16 @@ namespace MWMechanics
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell(*reflected); caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell(*reflected);
} }
if (removedSpell) if (removedSpell)
continue; return true;
if (context.mEraseRemoved)
{
bool remove = false; bool remove = false;
if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore)) if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore))
{ {
try try
{ {
auto& spells = ptr.getClass().getCreatureStats(ptr).getSpells();
remove = !spells.hasSpell(spellIt->mSourceSpellId); remove = !spells.hasSpell(spellIt->mSourceSpellId);
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
@ -413,30 +452,27 @@ namespace MWMechanics
for (const auto& effect : params.mEffects) for (const auto& effect : params.mEffects)
onMagicEffectRemoved(ptr, params, effect); onMagicEffectRemoved(ptr, params, effect);
applyPurges(ptr, &spellIt); applyPurges(ptr, &spellIt);
updateSpellWindow = true; context.mUpdateSpellWindow = true;
continue; return true;
}
} }
++spellIt; ++spellIt;
return false;
} }
if (Settings::game().mClassicCalmSpellsBehavior) ActiveSpells::ActiveSpellParams* ActiveSpells::initParams(
const MWWorld::Ptr& ptr, const ActiveSpellParams& params, UpdateContext& context)
{ {
ESM::MagicEffect::Effects effect mSpells.emplace_back(params).setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId());
= ptr.getClass().isNpc() ? ESM::MagicEffect::CalmHumanoid : ESM::MagicEffect::CalmCreature; auto it = mSpells.end();
if (creatureStats.getMagicEffects().getOrDefault(effect).getMagnitude() > 0.f) --it;
creatureStats.getAiSequence().stopCombat(); // We instantly apply the effect with a duration of 0 so continuous effects can be purged before truly applying
if (context.mUpdate && updateActiveSpell(ptr, 0.f, it, context))
return nullptr;
return &*it;
} }
if (ptr == player && updateSpellWindow) void ActiveSpells::addToSpells(const MWWorld::Ptr& ptr, const ActiveSpellParams& spell, UpdateContext& context)
{
// Something happened with the spell list -- possibly while the game is paused,
// so we want to make the spell window get the memo.
// We don't normally want to do this, so this targets constant enchantments.
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
}
}
void ActiveSpells::addToSpells(const MWWorld::Ptr& ptr, const ActiveSpellParams& spell)
{ {
if (!spell.hasFlag(ESM::ActiveSpells::Flag_Stackable)) if (!spell.hasFlag(ESM::ActiveSpells::Flag_Stackable))
{ {
@ -454,8 +490,7 @@ namespace MWMechanics
onMagicEffectRemoved(ptr, params, effect); onMagicEffectRemoved(ptr, params, effect);
} }
} }
mSpells.emplace_back(spell); initParams(ptr, spell, context);
mSpells.back().setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId());
} }
ActiveSpells::ActiveSpells() ActiveSpells::ActiveSpells()
@ -608,6 +643,8 @@ namespace MWMechanics
{ {
purge( purge(
[=](const ActiveSpellParams&, const ESM::ActiveEffect& effect) { [=](const ActiveSpellParams&, const ESM::ActiveEffect& effect) {
if (!(effect.mFlags & ESM::ActiveEffect::Flag_Applied))
return false;
if (effectArg.empty()) if (effectArg.empty())
return effect.mEffectId == effectId; return effect.mEffectId == effectId;
return effect.mEffectId == effectId && effect.getSkillOrAttribute() == effectArg; return effect.mEffectId == effectId && effect.getSkillOrAttribute() == effectArg;

View file

@ -116,17 +116,23 @@ namespace MWMechanics
IterationGuard(ActiveSpells& spells); IterationGuard(ActiveSpells& spells);
~IterationGuard(); ~IterationGuard();
}; };
struct UpdateContext;
std::list<ActiveSpellParams> mSpells; std::list<ActiveSpellParams> mSpells;
std::vector<ActiveSpellParams> mQueue; std::vector<ActiveSpellParams> mQueue;
std::queue<Predicate> mPurges; std::queue<Predicate> mPurges;
bool mIterating; bool mIterating;
void addToSpells(const MWWorld::Ptr& ptr, const ActiveSpellParams& spell); void addToSpells(const MWWorld::Ptr& ptr, const ActiveSpellParams& spell, UpdateContext& context);
bool applyPurges(const MWWorld::Ptr& ptr, std::list<ActiveSpellParams>::iterator* currentSpell = nullptr, bool applyPurges(const MWWorld::Ptr& ptr, std::list<ActiveSpellParams>::iterator* currentSpell = nullptr,
std::vector<ActiveEffect>::iterator* currentEffect = nullptr); std::vector<ActiveEffect>::iterator* currentEffect = nullptr);
bool updateActiveSpell(
const MWWorld::Ptr& ptr, float duration, Collection::iterator& spellIt, UpdateContext& context);
ActiveSpellParams* initParams(const MWWorld::Ptr& ptr, const ActiveSpellParams& params, UpdateContext& context);
public: public:
ActiveSpells(); ActiveSpells();

View file

@ -1326,19 +1326,37 @@ namespace MWMechanics
const MWWorld::Ptr player = getPlayer(); const MWWorld::Ptr player = getPlayer();
const MWBase::World* const world = MWBase::Environment::get().getWorld(); const MWBase::World* const world = MWBase::Environment::get().getWorld();
struct CacheEntry
{
MWWorld::Ptr mPtr;
float mMaxSpeed;
osg::Vec3f mHalfExtents;
Movement& mMovement;
};
std::vector<CacheEntry> cache;
cache.reserve(mActors.size());
for (const Actor& actor : mActors) for (const Actor& actor : mActors)
{ {
if (actor.isInvalid()) if (actor.isInvalid())
continue; continue;
const MWWorld::Ptr& ptr = actor.getPtr(); const MWWorld::Ptr& ptr = actor.getPtr();
const MWWorld::Class& cls = ptr.getClass();
cache.push_back({ ptr, cls.getMaxSpeed(ptr), world->getHalfExtents(ptr), cls.getMovementSettings(ptr) });
}
for (const CacheEntry& cached : cache)
{
const MWWorld::Ptr& ptr = cached.mPtr;
if (ptr == player) if (ptr == player)
continue; // Don't interfere with player controls. continue; // Don't interfere with player controls.
const float maxSpeed = ptr.getClass().getMaxSpeed(ptr); const float maxSpeed = cached.mMaxSpeed;
if (maxSpeed == 0.0) if (maxSpeed == 0.0)
continue; // Can't move, so there is no sense to predict collisions. continue; // Can't move, so there is no sense to predict collisions.
Movement& movement = ptr.getClass().getMovementSettings(ptr); Movement& movement = cached.mMovement;
const osg::Vec2f origMovement(movement.mPosition[0], movement.mPosition[1]); const osg::Vec2f origMovement(movement.mPosition[0], movement.mPosition[1]);
const bool isMoving = origMovement.length2() > 0.01; const bool isMoving = origMovement.length2() > 0.01;
if (movement.mPosition[1] < 0) if (movement.mPosition[1] < 0)
@ -1379,7 +1397,7 @@ namespace MWMechanics
const osg::Vec2f baseSpeed = origMovement * maxSpeed; const osg::Vec2f baseSpeed = origMovement * maxSpeed;
const osg::Vec3f basePos = ptr.getRefData().getPosition().asVec3(); const osg::Vec3f basePos = ptr.getRefData().getPosition().asVec3();
const float baseRotZ = ptr.getRefData().getPosition().rot[2]; const float baseRotZ = ptr.getRefData().getPosition().rot[2];
const osg::Vec3f halfExtents = world->getHalfExtents(ptr); const osg::Vec3f& halfExtents = cached.mHalfExtents;
const float maxDistToCheck = isMoving ? maxDistForPartialAvoiding : maxDistForStrictAvoiding; const float maxDistToCheck = isMoving ? maxDistForPartialAvoiding : maxDistForStrictAvoiding;
float timeToCheck = maxTimeToCheck; float timeToCheck = maxTimeToCheck;
@ -1392,15 +1410,13 @@ namespace MWMechanics
float angleToApproachingActor = 0; float angleToApproachingActor = 0;
// Iterate through all other actors and predict collisions. // Iterate through all other actors and predict collisions.
for (const Actor& otherActor : mActors) for (const CacheEntry& otherCached : cache)
{ {
if (otherActor.isInvalid()) const MWWorld::Ptr& otherPtr = otherCached.mPtr;
continue;
const MWWorld::Ptr& otherPtr = otherActor.getPtr();
if (otherPtr == ptr || otherPtr == currentTarget) if (otherPtr == ptr || otherPtr == currentTarget)
continue; continue;
const osg::Vec3f otherHalfExtents = world->getHalfExtents(otherPtr); const osg::Vec3f& otherHalfExtents = otherCached.mHalfExtents;
const osg::Vec3f deltaPos = otherPtr.getRefData().getPosition().asVec3() - basePos; const osg::Vec3f deltaPos = otherPtr.getRefData().getPosition().asVec3() - basePos;
const osg::Vec2f relPos = Misc::rotateVec2f(osg::Vec2f(deltaPos.x(), deltaPos.y()), baseRotZ); const osg::Vec2f relPos = Misc::rotateVec2f(osg::Vec2f(deltaPos.x(), deltaPos.y()), baseRotZ);
const float dist = deltaPos.length(); const float dist = deltaPos.length();
@ -1413,8 +1429,7 @@ namespace MWMechanics
if (deltaPos.z() > halfExtents.z() * 2 || deltaPos.z() < -otherHalfExtents.z() * 2) if (deltaPos.z() > halfExtents.z() * 2 || deltaPos.z() < -otherHalfExtents.z() * 2)
continue; continue;
const osg::Vec3f speed = otherPtr.getClass().getMovementSettings(otherPtr).asVec3() const osg::Vec3f speed = otherCached.mMovement.asVec3() * otherCached.mMaxSpeed;
* otherPtr.getClass().getMaxSpeed(otherPtr);
const float rotZ = otherPtr.getRefData().getPosition().rot[2]; const float rotZ = otherPtr.getRefData().getPosition().rot[2];
const osg::Vec2f relSpeed const osg::Vec2f relSpeed
= Misc::rotateVec2f(osg::Vec2f(speed.x(), speed.y()), baseRotZ - rotZ) - baseSpeed; = Misc::rotateVec2f(osg::Vec2f(speed.x(), speed.y()), baseRotZ - rotZ) - baseSpeed;

View file

@ -178,11 +178,16 @@ namespace MWMechanics
currentCell = actor.getCell(); currentCell = actor.getCell();
} }
const MWWorld::Class& actorClass = actor.getClass();
MWMechanics::CreatureStats& stats = actorClass.getCreatureStats(actor);
if (stats.isParalyzed() || stats.getKnockedDown())
return false;
bool forceFlee = false; bool forceFlee = false;
if (!canFight(actor, target)) if (!canFight(actor, target))
{ {
storage.stopAttack(); storage.stopAttack();
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); stats.setAttackingOrSpell(false);
storage.mActionCooldown = 0.f; storage.mActionCooldown = 0.f;
// Continue combat if target is player or player follower/escorter and an attack has been attempted // Continue combat if target is player or player follower/escorter and an attack has been attempted
const auto& playerFollowersAndEscorters const auto& playerFollowersAndEscorters
@ -191,18 +196,14 @@ namespace MWMechanics
= (std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), target) = (std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), target)
!= playerFollowersAndEscorters.end()); != playerFollowersAndEscorters.end());
if ((target == MWMechanics::getPlayer() || targetSidesWithPlayer) if ((target == MWMechanics::getPlayer() || targetSidesWithPlayer)
&& ((actor.getClass().getCreatureStats(actor).getHitAttemptActorId() && ((stats.getHitAttemptActorId() == target.getClass().getCreatureStats(target).getActorId())
== target.getClass().getCreatureStats(target).getActorId()) || (target.getClass().getCreatureStats(target).getHitAttemptActorId() == stats.getActorId())))
|| (target.getClass().getCreatureStats(target).getHitAttemptActorId()
== actor.getClass().getCreatureStats(actor).getActorId())))
forceFlee = true; forceFlee = true;
else // Otherwise end combat else // Otherwise end combat
return true; return true;
} }
const MWWorld::Class& actorClass = actor.getClass(); stats.setMovementFlag(CreatureStats::Flag_Run, true);
actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
float& actionCooldown = storage.mActionCooldown; float& actionCooldown = storage.mActionCooldown;
std::unique_ptr<Action>& currentAction = storage.mCurrentAction; std::unique_ptr<Action>& currentAction = storage.mCurrentAction;
@ -330,7 +331,7 @@ namespace MWMechanics
{ {
storage.mUseCustomDestination = false; storage.mUseCustomDestination = false;
storage.stopAttack(); storage.stopAttack();
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); stats.setAttackingOrSpell(false);
currentAction = std::make_unique<ActionFlee>(); currentAction = std::make_unique<ActionFlee>();
actionCooldown = currentAction->getActionCooldown(); actionCooldown = currentAction->getActionCooldown();
storage.startFleeing(); storage.startFleeing();

View file

@ -2310,17 +2310,13 @@ namespace MWMechanics
} }
else else
{ {
// Do not play turning animation for player if rotation speed is very slow.
// Actual threshold should take framerate in account.
float rotationThreshold = (isPlayer ? 0.015f : 0.001f) * 60 * duration;
// It seems only bipedal actors use turning animations. // It seems only bipedal actors use turning animations.
// Also do not use turning animations in the first-person view and when sneaking. // Also do not use turning animations in the first-person view and when sneaking.
if (!sneak && !isFirstPersonPlayer && isBiped) if (!sneak && !isFirstPersonPlayer && isBiped)
{ {
if (effectiveRotation > rotationThreshold) if (effectiveRotation > 0.f)
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
else if (effectiveRotation < -rotationThreshold) else if (effectiveRotation < 0.f)
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft; movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
} }
} }
@ -2346,20 +2342,6 @@ namespace MWMechanics
vec.y() *= std::sqrt(1.0f - swimUpwardCoef * swimUpwardCoef); vec.y() *= std::sqrt(1.0f - swimUpwardCoef * swimUpwardCoef);
} }
// Player can not use smooth turning as NPCs, so we play turning animation a bit to avoid jittering
if (isPlayer)
{
float threshold = mCurrentMovement.find("swim") == std::string::npos ? 0.4f : 0.8f;
float complete;
bool animPlaying = mAnimation->getInfo(mCurrentMovement, &complete);
if (movestate == CharState_None && jumpstate == JumpState_None && isTurning())
{
if (animPlaying && complete < threshold)
movestate = mMovementState;
}
}
else
{
if (isBiped) if (isBiped)
{ {
if (mTurnAnimationThreshold > 0) if (mTurnAnimationThreshold > 0)
@ -2375,7 +2357,6 @@ namespace MWMechanics
movestate = mMovementState; movestate = mMovementState;
} }
} }
}
if (movestate != CharState_None) if (movestate != CharState_None)
{ {
@ -2402,11 +2383,10 @@ namespace MWMechanics
if (isTurning()) if (isTurning())
{ {
// Adjust animation speed from 1.0 to 1.5 multiplier
if (duration > 0) if (duration > 0)
{ {
float turnSpeed = std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI)); float turnSpeed = std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI));
mAnimation->adjustSpeedMult(mCurrentMovement, std::max(turnSpeed, 1.0f)); mAnimation->adjustSpeedMult(mCurrentMovement, turnSpeed);
} }
} }
else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed) else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed)

View file

@ -215,10 +215,6 @@ namespace MWMechanics
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
effect.mDuration = hasDuration ? static_cast<float>(enam.mData.mDuration) : 1.f; effect.mDuration = hasDuration ? static_cast<float>(enam.mData.mDuration) : 1.f;
bool appliedOnce = magicEffect->mData.mFlags & ESM::MagicEffect::AppliedOnce;
if (!appliedOnce)
effect.mDuration = std::max(1.f, effect.mDuration);
effect.mTimeLeft = effect.mDuration; effect.mTimeLeft = effect.mDuration;
// add to list of active effects, to apply in next frame // add to list of active effects, to apply in next frame

View file

@ -1011,11 +1011,13 @@ namespace MWMechanics
else else
{ {
// Morrowind.exe doesn't apply magic effects while the menu is open, we do because we like to see stats // Morrowind.exe doesn't apply magic effects while the menu is open, we do because we like to see stats
// updated instantly. We don't want to teleport instantly though // updated instantly. We don't want to teleport instantly though. Nor do we want to force players to drink
// invisibility potions in the "right" order
if (!dt if (!dt
&& (effect.mEffectId == ESM::MagicEffect::Recall && (effect.mEffectId == ESM::MagicEffect::Recall
|| effect.mEffectId == ESM::MagicEffect::DivineIntervention || effect.mEffectId == ESM::MagicEffect::DivineIntervention
|| effect.mEffectId == ESM::MagicEffect::AlmsiviIntervention)) || effect.mEffectId == ESM::MagicEffect::AlmsiviIntervention
|| effect.mEffectId == ESM::MagicEffect::Invisibility))
return { MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth }; return { MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth };
auto& stats = target.getClass().getCreatureStats(target); auto& stats = target.getClass().getCreatureStats(target);
auto& magnitudes = stats.getMagicEffects(); auto& magnitudes = stats.getMagicEffects();

View file

@ -943,8 +943,8 @@ namespace MWRender
stateUpdater->setIsUnderwater(isUnderwater); stateUpdater->setIsUnderwater(isUnderwater);
stateUpdater->setFogColor(fogColor); stateUpdater->setFogColor(fogColor);
stateUpdater->setGameHour(world->getTimeStamp().getHour()); stateUpdater->setGameHour(world->getTimeStamp().getHour());
stateUpdater->setWeatherId(world->getCurrentWeather()); stateUpdater->setWeatherId(world->getCurrentWeatherScriptId());
stateUpdater->setNextWeatherId(world->getNextWeather()); stateUpdater->setNextWeatherId(world->getNextWeatherScriptId());
stateUpdater->setWeatherTransition(world->getWeatherTransition()); stateUpdater->setWeatherTransition(world->getWeatherTransition());
stateUpdater->setWindSpeed(world->getWindSpeed()); stateUpdater->setWindSpeed(world->getWindSpeed());
stateUpdater->setSkyColor(mSky->getSkyColor()); stateUpdater->setSkyColor(mSky->getSkyColor());

View file

@ -139,6 +139,7 @@ namespace MWRender
int skyGetSecundaPhase() const; int skyGetSecundaPhase() const;
void skySetMoonColour(bool red); void skySetMoonColour(bool red);
const osg::Vec4f& getSunLightPosition() const { return mSunLight->getPosition(); }
void setSunDirection(const osg::Vec3f& direction); void setSunDirection(const osg::Vec3f& direction);
void setSunColour(const osg::Vec4f& diffuse, const osg::Vec4f& specular, float sunVis); void setSunColour(const osg::Vec4f& diffuse, const osg::Vec4f& specular, float sunVis);
void setNight(bool isNight) { mNight = isNight; } void setNight(bool isNight) { mNight = isNight; }

View file

@ -71,7 +71,7 @@ namespace MWScript
public: public:
void execute(Interpreter::Runtime& runtime) override void execute(Interpreter::Runtime& runtime) override
{ {
runtime.push(MWBase::Environment::get().getWorld()->getCurrentWeather()); runtime.push(MWBase::Environment::get().getWorld()->getCurrentWeatherScriptId());
} }
}; };

View file

@ -1,5 +1,6 @@
#include "weather.hpp" #include "weather.hpp"
#include <components/esm/stringrefid.hpp>
#include <components/settings/values.hpp> #include <components/settings/values.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
@ -141,9 +142,12 @@ namespace MWWorld
return direction; return direction;
} }
Weather::Weather(const std::string& name, float stormWindSpeed, float rainSpeed, float dlFactor, float dlOffset, Weather::Weather(ESM::RefId id, int scriptId, const std::string& name, float stormWindSpeed, float rainSpeed,
const std::string& particleEffect) float dlFactor, float dlOffset, const std::string& particleEffect)
: mCloudTexture(Fallback::Map::getString("Weather_" + name + "_Cloud_Texture")) : mId(id)
, mScriptId(scriptId)
, mName(name)
, mCloudTexture(Fallback::Map::getString("Weather_" + name + "_Cloud_Texture"))
, mSkyColor(Fallback::Map::getColour("Weather_" + name + "_Sky_Sunrise_Color"), , mSkyColor(Fallback::Map::getColour("Weather_" + name + "_Sky_Sunrise_Color"),
Fallback::Map::getColour("Weather_" + name + "_Sky_Day_Color"), Fallback::Map::getColour("Weather_" + name + "_Sky_Day_Color"),
Fallback::Map::getColour("Weather_" + name + "_Sky_Sunset_Color"), Fallback::Map::getColour("Weather_" + name + "_Sky_Sunset_Color"),
@ -676,6 +680,41 @@ namespace MWWorld
stopSounds(); stopSounds();
} }
const Weather* WeatherManager::getWeather(size_t index) const
{
if (index < mWeatherSettings.size())
return &mWeatherSettings[index];
return nullptr;
}
const Weather* WeatherManager::getWeather(const ESM::RefId& id) const
{
auto it = std::find_if(
mWeatherSettings.begin(), mWeatherSettings.end(), [id](const auto& weather) { return weather.mId == id; });
if (it != mWeatherSettings.end())
return &*it;
return nullptr;
}
void WeatherManager::changeWeather(const ESM::RefId& regionID, const ESM::RefId& weatherID)
{
auto wIt = std::find_if(mWeatherSettings.begin(), mWeatherSettings.end(),
[weatherID](const auto& weather) { return weather.mId == weatherID; });
if (wIt != mWeatherSettings.end())
{
auto rIt = mRegions.find(regionID);
if (rIt != mRegions.end())
{
rIt->second.setWeather(std::distance(mWeatherSettings.begin(), wIt));
regionalWeatherChanged(rIt->first, rIt->second);
}
}
}
void WeatherManager::changeWeather(const ESM::RefId& regionID, const unsigned int weatherID) void WeatherManager::changeWeather(const ESM::RefId& regionID, const unsigned int weatherID)
{ {
// In Morrowind, this seems to have the following behavior, when applied to the current region: // In Morrowind, this seems to have the following behavior, when applied to the current region:
@ -1053,8 +1092,9 @@ namespace MWWorld
const std::string& name, float dlFactor, float dlOffset, const std::string& particleEffect) const std::string& name, float dlFactor, float dlOffset, const std::string& particleEffect)
{ {
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->mValue.getFloat(); static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->mValue.getFloat();
ESM::StringRefId id(name);
Weather weather(name, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect); Weather weather(
id, mWeatherSettings.size(), name, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect);
mWeatherSettings.push_back(weather); mWeatherSettings.push_back(weather);
} }

View file

@ -109,6 +109,11 @@ namespace MWWorld
T getValue(const float gameHour, const TimeOfDaySettings& timeSettings, const std::string& prefix) const; T getValue(const float gameHour, const TimeOfDaySettings& timeSettings, const std::string& prefix) const;
const T& getSunriseValue() const { return mSunriseValue; }
const T& getDayValue() const { return mDayValue; }
const T& getSunsetValue() const { return mSunsetValue; }
const T& getNightValue() const { return mNightValue; }
private: private:
T mSunriseValue, mDayValue, mSunsetValue, mNightValue; T mSunriseValue, mDayValue, mSunsetValue, mNightValue;
}; };
@ -119,9 +124,12 @@ namespace MWWorld
public: public:
static osg::Vec3f defaultDirection(); static osg::Vec3f defaultDirection();
Weather(const std::string& name, float stormWindSpeed, float rainSpeed, float dlFactor, float dlOffset, Weather(const ESM::RefId id, const int scriptId, const std::string& name, float stormWindSpeed, float rainSpeed,
const std::string& particleEffect); float dlFactor, float dlOffset, const std::string& particleEffect);
ESM::RefId mId;
int mScriptId;
std::string mName;
std::string mCloudTexture; std::string mCloudTexture;
// Sky (atmosphere) color // Sky (atmosphere) color
@ -289,11 +297,12 @@ namespace MWWorld
~WeatherManager(); ~WeatherManager();
/** /**
* Change the weather in the specified region * Change the weather in the specified region by id of the weather
* @param region that should be changed * @param region that should be changed
* @param ID of the weather setting to shift to * @param ID of the weather setting to shift to
*/ */
void changeWeather(const ESM::RefId& regionID, const unsigned int weatherID); void changeWeather(const ESM::RefId& regionID, const unsigned int weatherID);
void changeWeather(const ESM::RefId& regionID, const ESM::RefId& weatherID);
void modRegion(const ESM::RefId& regionID, const std::vector<uint8_t>& chances); void modRegion(const ESM::RefId& regionID, const std::vector<uint8_t>& chances);
void playerTeleported(const ESM::RefId& playerRegion, bool isExterior); void playerTeleported(const ESM::RefId& playerRegion, bool isExterior);
@ -316,8 +325,23 @@ namespace MWWorld
void advanceTime(double hours, bool incremental); void advanceTime(double hours, bool incremental);
const std::vector<Weather>& getAllWeather() { return mWeatherSettings; }
const Weather& getWeather() { return mWeatherSettings[mCurrentWeather]; }
const Weather* getWeather(size_t index) const;
const Weather* getWeather(const ESM::RefId& id) const;
int getWeatherID() const { return mCurrentWeather; } int getWeatherID() const { return mCurrentWeather; }
const Weather* getNextWeather()
{
if (mNextWeather > -1)
return &mWeatherSettings[mNextWeather];
return nullptr;
}
int getNextWeatherID() const { return mNextWeather; } int getNextWeatherID() const { return mNextWeather; }
float getTransitionFactor() const { return mTransitionFactor; } float getTransitionFactor() const { return mTransitionFactor; }

View file

@ -1868,14 +1868,43 @@ namespace MWWorld
return ESM::Cell::sDefaultWorldspaceId; return ESM::Cell::sDefaultWorldspaceId;
} }
int World::getCurrentWeather() const const std::vector<MWWorld::Weather>& World::getAllWeather() const
{ {
return mWeatherManager->getWeatherID(); return mWeatherManager->getAllWeather();
} }
int World::getNextWeather() const int World::getCurrentWeatherScriptId() const
{ {
return mWeatherManager->getNextWeatherID(); return mWeatherManager->getWeather().mScriptId;
}
const MWWorld::Weather& World::getCurrentWeather() const
{
return mWeatherManager->getWeather();
}
const MWWorld::Weather* World::getWeather(size_t index) const
{
return mWeatherManager->getWeather(index);
}
const MWWorld::Weather* World::getWeather(const ESM::RefId& id) const
{
return mWeatherManager->getWeather(id);
}
int World::getNextWeatherScriptId() const
{
auto next = mWeatherManager->getNextWeather();
if (next == nullptr)
return -1;
return next->mScriptId;
}
const MWWorld::Weather* World::getNextWeather() const
{
return mWeatherManager->getNextWeather();
} }
float World::getWeatherTransition() const float World::getWeatherTransition() const
@ -1893,6 +1922,11 @@ namespace MWWorld
mWeatherManager->changeWeather(region, id); mWeatherManager->changeWeather(region, id);
} }
void World::changeWeather(const ESM::RefId& region, const ESM::RefId& id)
{
mWeatherManager->changeWeather(region, id);
}
void World::modRegion(const ESM::RefId& regionid, const std::vector<uint8_t>& chances) void World::modRegion(const ESM::RefId& regionid, const std::vector<uint8_t>& chances)
{ {
mWeatherManager->modRegion(regionid, chances); mWeatherManager->modRegion(regionid, chances);
@ -3133,6 +3167,11 @@ namespace MWWorld
} }
} }
const osg::Vec4f& World::getSunLightPosition() const
{
return mRendering->getSunLightPosition();
}
float World::getSunVisibility() const float World::getSunVisibility() const
{ {
return mWeatherManager->getSunVisibility(); return mWeatherManager->getSunVisibility();

View file

@ -317,9 +317,16 @@ namespace MWWorld
void changeWeather(const ESM::RefId& region, const unsigned int id) override; void changeWeather(const ESM::RefId& region, const unsigned int id) override;
int getCurrentWeather() const override; void changeWeather(const ESM::RefId& region, const ESM::RefId& id) override;
int getNextWeather() const override; const std::vector<MWWorld::Weather>& getAllWeather() const override;
int getCurrentWeatherScriptId() const override;
const MWWorld::Weather& getCurrentWeather() const override;
const MWWorld::Weather* getWeather(size_t index) const override;
const MWWorld::Weather* getWeather(const ESM::RefId& id) const override;
int getNextWeatherScriptId() const override;
const MWWorld::Weather* getNextWeather() const override;
float getWeatherTransition() const override; float getWeatherTransition() const override;
@ -573,6 +580,7 @@ namespace MWWorld
// Allow NPCs to use torches? // Allow NPCs to use torches?
bool useTorches() const override; bool useTorches() const override;
const osg::Vec4f& getSunLightPosition() const override;
float getSunVisibility() const override; float getSunVisibility() const override;
float getSunPercentage() const override; float getSunPercentage() const override;

View file

@ -7,6 +7,7 @@
#include <components/esm3/loadnpc.hpp> #include <components/esm3/loadnpc.hpp>
#include <components/esm3/readerscache.hpp> #include <components/esm3/readerscache.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
namespace MWWorld namespace MWWorld
@ -36,7 +37,7 @@ namespace MWWorld
LiveCellRef<ESM::NPC> liveCellRef(cellRef, &npc); LiveCellRef<ESM::NPC> liveCellRef(cellRef, &npc);
liveCellRef.mData.setDeletedByContentFile(true); liveCellRef.mData.setDeletedByContentFile(true);
Ptr ptr(&liveCellRef); Ptr ptr(&liveCellRef);
EXPECT_EQ(ptr.toString(), "deleted object0xd00002a (NPC, \"player\")"); EXPECT_THAT(ptr.toString(), StrCaseEq("deleted object0xd00002a (NPC, \"player\")"));
} }
TEST(MWWorldPtrTest, toStringShouldReturnHumanReadableTextRepresentationOfPtr) TEST(MWWorldPtrTest, toStringShouldReturnHumanReadableTextRepresentationOfPtr)
@ -53,7 +54,7 @@ namespace MWWorld
cellRef.mRefNum = ESM::RefNum{ .mIndex = 0x2a, .mContentFile = 0xd }; cellRef.mRefNum = ESM::RefNum{ .mIndex = 0x2a, .mContentFile = 0xd };
LiveCellRef<ESM::NPC> liveCellRef(cellRef, &npc); LiveCellRef<ESM::NPC> liveCellRef(cellRef, &npc);
Ptr ptr(&liveCellRef); Ptr ptr(&liveCellRef);
EXPECT_EQ(ptr.toString(), "object0xd00002a (NPC, \"player\")"); EXPECT_THAT(ptr.toString(), StrCaseEq("object0xd00002a (NPC, \"player\")"));
} }
TEST(MWWorldPtrTest, underlyingLiveCellRefShouldBeDeregisteredOnDestruction) TEST(MWWorldPtrTest, underlyingLiveCellRefShouldBeDeregisteredOnDestruction)

View file

@ -18,37 +18,33 @@ namespace Files
namespace bpo = boost::program_options; namespace bpo = boost::program_options;
namespace
{
#if defined(_WIN32) || defined(__WINDOWS__) #if defined(_WIN32) || defined(__WINDOWS__)
static const char* const applicationName = "OpenMW"; constexpr auto applicationName = "OpenMW";
#else #else
static const char* const applicationName = "openmw"; constexpr auto applicationName = "openmw";
#endif #endif
static constexpr auto localToken = u8"?local?"; using GetPath = const std::filesystem::path& (Files::FixedPath<>::*)() const;
static constexpr auto userConfigToken = u8"?userconfig?"; constexpr std::array<std::pair<std::u8string_view, GetPath>, 4> sTokenMappings = {
static constexpr auto userDataToken = u8"?userdata?"; std::make_pair(u8"?local?", &FixedPath<>::getLocalPath),
static constexpr auto globalToken = u8"?global?"; std::make_pair(u8"?userconfig?", &FixedPath<>::getUserConfigPath),
std::make_pair(u8"?userdata?", &FixedPath<>::getUserDataPath),
std::make_pair(u8"?global?", &FixedPath<>::getGlobalDataPath),
};
}
ConfigurationManager::ConfigurationManager(bool silent) ConfigurationManager::ConfigurationManager(bool silent)
: mFixedPath(applicationName) : mFixedPath(applicationName)
, mSilent(silent) , mSilent(silent)
{ {
setupTokensMapping();
// Initialize with fixed paths, will be overridden in `readConfiguration`. // Initialize with fixed paths, will be overridden in `readConfiguration`.
mUserDataPath = mFixedPath.getUserDataPath(); mUserDataPath = mFixedPath.getUserDataPath();
mScreenshotPath = mFixedPath.getUserDataPath() / "screenshots"; mScreenshotPath = mFixedPath.getUserDataPath() / "screenshots";
} }
ConfigurationManager::~ConfigurationManager() {} ConfigurationManager::~ConfigurationManager() = default;
void ConfigurationManager::setupTokensMapping()
{
mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath));
mTokensMapping.insert(std::make_pair(userConfigToken, &FixedPath<>::getUserConfigPath));
mTokensMapping.insert(std::make_pair(userDataToken, &FixedPath<>::getUserDataPath));
mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath));
}
static bool hasReplaceConfig(const bpo::variables_map& variables) static bool hasReplaceConfig(const bpo::variables_map& variables)
{ {
@ -74,7 +70,7 @@ namespace Files
std::optional<bpo::variables_map> config = loadConfig(mFixedPath.getLocalPath(), description); std::optional<bpo::variables_map> config = loadConfig(mFixedPath.getLocalPath(), description);
if (config) if (config)
mActiveConfigPaths.push_back(mFixedPath.getLocalPath()); mActiveConfigPaths.push_back(mFixedPath.getLocalPath());
else else if (!mFixedPath.getGlobalConfigPath().empty())
{ {
mActiveConfigPaths.push_back(mFixedPath.getGlobalConfigPath()); mActiveConfigPaths.push_back(mFixedPath.getGlobalConfigPath());
config = loadConfig(mFixedPath.getGlobalConfigPath(), description); config = loadConfig(mFixedPath.getGlobalConfigPath(), description);
@ -305,15 +301,18 @@ namespace Files
const auto pos = str.find('?', 1); const auto pos = str.find('?', 1);
if (pos != std::u8string::npos && pos != 0) if (pos != std::u8string::npos && pos != 0)
{ {
auto tokenIt = mTokensMapping.find(str.substr(0, pos + 1)); std::u8string_view view(str);
if (tokenIt != mTokensMapping.end()) auto token = view.substr(0, pos + 1);
auto found = std::find_if(
sTokenMappings.begin(), sTokenMappings.end(), [&](const auto& item) { return item.first == token; });
if (found != sTokenMappings.end())
{ {
auto tempPath(((mFixedPath).*(tokenIt->second))()); auto tempPath(((mFixedPath).*(found->second))());
if (pos < str.length() - 1) if (!tempPath.empty() && pos < view.length() - 1)
{ {
// There is something after the token, so we should // There is something after the token, so we should
// append it to the path // append it to the path
tempPath /= str.substr(pos + 1, str.length() - pos); tempPath /= view.substr(pos + 1, view.length() - pos);
} }
path = std::move(tempPath); path = std::move(tempPath);

View file

@ -62,17 +62,12 @@ namespace Files
private: private:
typedef Files::FixedPath<> FixedPathType; typedef Files::FixedPath<> FixedPathType;
typedef const std::filesystem::path& (FixedPathType::*path_type_f)() const;
typedef std::map<std::u8string, path_type_f> TokensMappingContainer;
std::optional<boost::program_options::variables_map> loadConfig( std::optional<boost::program_options::variables_map> loadConfig(
const std::filesystem::path& path, const boost::program_options::options_description& description) const; const std::filesystem::path& path, const boost::program_options::options_description& description) const;
void addExtraConfigDirs( void addExtraConfigDirs(
std::stack<std::filesystem::path>& dirs, const boost::program_options::variables_map& variables) const; std::stack<std::filesystem::path>& dirs, const boost::program_options::variables_map& variables) const;
void setupTokensMapping();
std::vector<std::filesystem::path> mActiveConfigPaths; std::vector<std::filesystem::path> mActiveConfigPaths;
FixedPathType mFixedPath; FixedPathType mFixedPath;
@ -80,8 +75,6 @@ namespace Files
std::filesystem::path mUserDataPath; std::filesystem::path mUserDataPath;
std::filesystem::path mScreenshotPath; std::filesystem::path mScreenshotPath;
TokensMappingContainer mTokensMapping;
bool mSilent; bool mSilent;
}; };

View file

@ -8,21 +8,11 @@
namespace Files namespace Files
{ {
inline QString getLocalConfigPathQString(const Files::ConfigurationManager& cfgMgr)
{
return Files::pathToQString(cfgMgr.getLocalPath() / openmwCfgFile);
}
inline QString getUserConfigPathQString(const Files::ConfigurationManager& cfgMgr) inline QString getUserConfigPathQString(const Files::ConfigurationManager& cfgMgr)
{ {
return Files::pathToQString(cfgMgr.getUserConfigPath() / openmwCfgFile); return Files::pathToQString(cfgMgr.getUserConfigPath() / openmwCfgFile);
} }
inline QString getGlobalConfigPathQString(const Files::ConfigurationManager& cfgMgr)
{
return Files::pathToQString(cfgMgr.getGlobalPath() / openmwCfgFile);
}
inline QStringList getActiveConfigPathsQString(const Files::ConfigurationManager& cfgMgr) inline QStringList getActiveConfigPathsQString(const Files::ConfigurationManager& cfgMgr)
{ {
const auto& activePaths = cfgMgr.getActiveConfigPaths(); const auto& activePaths = cfgMgr.getActiveConfigPaths();

View file

@ -54,19 +54,7 @@ namespace Files
{ {
// The concept of a global config path is absurd on Windows. // The concept of a global config path is absurd on Windows.
// Always use local config instead. // Always use local config instead.
// The virtual base class requires that we provide this, though. return {};
std::filesystem::path globalPath = std::filesystem::current_path();
PWSTR cString;
HRESULT result = SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, nullptr, &cString);
if (SUCCEEDED(result))
globalPath = std::filesystem::path(cString);
else
Log(Debug::Error) << "Error " << result << " when getting Program Files path";
CoTaskMemFree(cString);
return globalPath / mName;
} }
std::filesystem::path WindowsPath::getLocalPath() const std::filesystem::path WindowsPath::getLocalPath() const

View file

@ -34,7 +34,7 @@ namespace Files
std::filesystem::path getUserDataPath() const; std::filesystem::path getUserDataPath() const;
/** /**
* \brief Returns "X:\Program Files\" * \brief Returns an empty path
* *
* \return std::filesystem::path * \return std::filesystem::path
*/ */

View file

@ -1,5 +1,8 @@
The code in this directory is copied from https://github.com/ThePhD/sol2.git (64096348465b980e2f1d0e5ba9cbeea8782e8f27) The code in this directory is copied from https://github.com/ThePhD/sol2.git (c1f95a773c6f8f4fde8ca3efe872e7286afe4444) and has been patched to include
Additional changes include cherry-picking upstream commit d805d027e0a0a7222e936926139f06e23828ce9f to fix compilation under Clang 19. https://github.com/ThePhD/sol2/pull/1674 (71d85143ad69164f5f52c3bdab91fb503c676eb4)
https://github.com/ThePhD/sol2/pull/1676 (a6872ef46b08704b9069ebf83161f4637459ce63)
https://github.com/ThePhD/sol2/pull/1716 (5b6881ed94c795298eae72b6848308e9a37e42c5)
https://github.com/ThePhD/sol2/pull/1722 (ab874eb0e8ef8aea4c10074a89efa25f62a29d9a)
License: MIT License: MIT

47
extern/sol3/sol/abort.hpp vendored Normal file
View file

@ -0,0 +1,47 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_ABORT_HPP
#define SOL_ABORT_HPP
#include <sol/version.hpp>
#include <sol/base_traits.hpp>
#include <cstdlib>
// clang-format off
#if SOL_IS_ON(SOL_DEBUG_BUILD)
#if SOL_IS_ON(SOL_COMPILER_VCXX)
#define SOL_DEBUG_ABORT() \
if (true) { ::std::abort(); } \
static_assert(true, "")
#else
#define SOL_DEBUG_ABORT() ::std::abort()
#endif
#else
#define SOL_DEBUG_ABORT() static_assert(true, "")
#endif
// clang-format on
#endif // SOL_ABORT_HPP

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -28,7 +28,7 @@
#include <sol/forward.hpp> #include <sol/forward.hpp>
#if SOL_IS_ON(SOL2_CI_I_) #if SOL_IS_ON(SOL2_CI)
struct pre_main { struct pre_main {
pre_main() { pre_main() {
@ -43,15 +43,15 @@ struct pre_main {
// clang-format off // clang-format off
#if SOL_IS_ON(SOL_USER_C_ASSERT_I_) #if SOL_IS_ON(SOL_USER_ASSERT)
#define sol_c_assert(...) SOL_C_ASSERT(__VA_ARGS__) #define SOL_ASSERT(...) SOL_C_ASSERT(__VA_ARGS__)
#else #else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_) #if SOL_IS_ON(SOL_DEBUG_BUILD)
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#define sol_c_assert(...) \ #define SOL_ASSERT(...) \
do { \ do { \
if (!(__VA_ARGS__)) { \ if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \ std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \
@ -59,7 +59,7 @@ struct pre_main {
} \ } \
} while (false) } while (false)
#else #else
#define sol_c_assert(...) \ #define SOL_ASSERT(...) \
do { \ do { \
if (false) { \ if (false) { \
(void)(__VA_ARGS__); \ (void)(__VA_ARGS__); \
@ -68,15 +68,15 @@ struct pre_main {
#endif #endif
#endif #endif
#if SOL_IS_ON(SOL_USER_M_ASSERT_I_) #if SOL_IS_ON(SOL_USER_ASSERT_MSG)
#define sol_m_assert(message, ...) SOL_M_ASSERT(message, __VA_ARGS__) #define SOL_ASSERT_MSG(message, ...) SOL_ASSERT_MSG(message, __VA_ARGS__)
#else #else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_) #if SOL_IS_ON(SOL_DEBUG_BUILD)
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#define sol_m_assert(message, ...) \ #define SOL_ASSERT_MSG(message, ...) \
do { \ do { \
if (!(__VA_ARGS__)) { \ if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \ std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
@ -84,7 +84,7 @@ struct pre_main {
} \ } \
} while (false) } while (false)
#else #else
#define sol_m_assert(message, ...) \ #define SOL_ASSERT_MSG(message, ...) \
do { \ do { \
if (false) { \ if (false) { \
(void)(__VA_ARGS__); \ (void)(__VA_ARGS__); \

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -62,6 +62,39 @@ namespace sol {
template <template <class...> class Trait, class... Args> template <template <class...> class Trait, class... Args>
constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value; constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value;
template <typename _Default, typename _Void, template <typename...> typename _Op, typename... _Args>
class detector {
public:
using value_t = ::std::false_type;
using type = _Default;
};
template <typename _Default, template <typename...> typename _Op, typename... _Args>
class detector<_Default, void_t<_Op<_Args...>>, _Op, _Args...> {
public:
using value_t = ::std::true_type;
using type = _Op<_Args...>;
};
class nonesuch {
public:
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
nonesuch& operator=(nonesuch const&) = delete;
};
template <template <typename...> typename _Op, typename... _Args>
using detected_t = typename detector<nonesuch, void, _Op, _Args...>::type;
template <typename _Default, template <typename...> typename _Op, typename... _Args>
using detected_or = detector<_Default, void, _Op, _Args...>;
template <typename _Default, template <typename...> typename _Op, typename... _Args>
using detected_or_t = typename detector<_Default, void, _Op, _Args...>::type;
template <typename _Default, template <typename...> typename _Op, typename... _Args>
constexpr inline bool detected_or_v = detector<_Default, void, _Op, _Args...>::value;
template <std::size_t I> template <std::size_t I>
using index_value = std::integral_constant<std::size_t, I>; using index_value = std::integral_constant<std::size_t, I>;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -31,7 +31,7 @@
namespace sol { namespace meta { namespace sol { namespace meta {
namespace meta_detail { namespace meta_detail {
template <typename F> template <typename F>
using detect_deducible_signature = decltype(&F::operator(), void()); using detect_deducible_signature = decltype(&F::operator());
} // namespace meta_detail } // namespace meta_detail
template <typename F> template <typename F>
@ -196,7 +196,7 @@ namespace sol { namespace meta {
typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&;
}; };
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
template <typename R, typename... Args> template <typename R, typename... Args>
struct fx_traits<R(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { struct fx_traits<R(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> {
@ -311,7 +311,7 @@ namespace sol { namespace meta {
#endif // noexcept is part of a function's type #endif // noexcept is part of a function's type
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) && SOL_IS_ON(SOL_PLATFORM_X86_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX) && SOL_IS_ON(SOL_PLATFORM_X86)
template <typename R, typename... Args> template <typename R, typename... Args>
struct fx_traits<R __stdcall(Args...), false> : public basic_traits<false, false, void, R, Args...> { struct fx_traits<R __stdcall(Args...), false> : public basic_traits<false, false, void, R, Args...> {
typedef R(__stdcall* function_pointer_type)(Args...); typedef R(__stdcall* function_pointer_type)(Args...);
@ -369,7 +369,7 @@ namespace sol { namespace meta {
typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&;
}; };
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
template <typename R, typename... Args> template <typename R, typename... Args>
struct fx_traits<R __stdcall(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { struct fx_traits<R __stdcall(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -99,7 +99,7 @@ namespace sol {
using storage_t = Container; using storage_t = Container;
const std::byte* p_code = static_cast<const std::byte*>(memory); const std::byte* p_code = static_cast<const std::byte*>(memory);
storage_t& bc = *static_cast<storage_t*>(userdata_pointer); storage_t& bc = *static_cast<storage_t*>(userdata_pointer);
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
bc.insert(bc.cend(), p_code, p_code + memory_size); bc.insert(bc.cend(), p_code, p_code + memory_size);
#else #else
try { try {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -54,7 +54,7 @@ namespace sol {
lua_createtable(L, static_cast<int>(sizeof...(In)), 0); lua_createtable(L, static_cast<int>(sizeof...(In)), 0);
stack_reference deps(L, -1); stack_reference deps(L, -1);
auto per_dep = [&L, &deps](int i) { auto per_dep = [&L, &deps](int i) {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushvalue(L, i); lua_pushvalue(L, i);
@ -79,7 +79,7 @@ namespace sol {
} }
lua_createtable(L, static_cast<int>(sdeps.size()), 0); lua_createtable(L, static_cast<int>(sdeps.size()), 0);
stack_reference deps(L, -1); stack_reference deps(L, -1);
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic); luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
for (std::size_t i = 0; i < sdeps.size(); ++i) { for (std::size_t i = 0; i < sdeps.size(); ++i) {
@ -429,7 +429,7 @@ namespace sol {
} }
}; };
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> { struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> {
static int call(lua_State* L, detail::lua_CFunction_noexcept f) { static int call(lua_State* L, detail::lua_CFunction_noexcept f) {
@ -478,12 +478,13 @@ namespace sol {
using object_type = typename wrap::object_type; using object_type = typename wrap::object_type;
if constexpr (sizeof...(Args) < 1) { if constexpr (sizeof...(Args) < 1) {
using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
static_assert(std::is_base_of_v<object_type, Ta>, static_assert(std::is_same_v<object_type, Ta> || std::is_base_of_v<object_type, Ta>,
"It seems like you might have accidentally bound a class type with a member function method that does not correspond to the " "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the "
"class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" " "class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" "
"but then bind member methods from a complete unrelated class. Check things over!"); "but then bind member methods from a complete unrelated class. Check things over!");
#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_) #if SOL_IS_ON(SOL_SAFE_USERTYPE)
auto maybeo = stack::check_get<Ta*>(L, 1); stack::record tracking {};
auto maybeo = stack::stack_detail::check_get_arg<Ta*>(L, 1, &no_panic, tracking);
if (!maybeo || maybeo.value() == nullptr) { if (!maybeo || maybeo.value() == nullptr) {
return luaL_error(L, return luaL_error(L,
"sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are " "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are "
@ -511,12 +512,13 @@ namespace sol {
if constexpr (is_index) { if constexpr (is_index) {
if constexpr (sizeof...(Args) < 1) { if constexpr (sizeof...(Args) < 1) {
using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
static_assert(std::is_base_of_v<object_type, Ta>, static_assert(std::is_same_v<object_type, Ta> || std::is_base_of_v<object_type, Ta>,
"It seems like you might have accidentally bound a class type with a member function method that does not correspond " "It seems like you might have accidentally bound a class type with a member function method that does not correspond "
"to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one " "to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one "
"class \"T\" but then bind member methods from a complete unrelated class. Check things over!"); "class \"T\" but then bind member methods from a complete unrelated class. Check things over!");
#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_) #if SOL_IS_ON(SOL_SAFE_USERTYPE)
auto maybeo = stack::check_get<Ta*>(L, 1); stack::record tracking {};
auto maybeo = stack::stack_detail::check_get_arg<Ta*>(L, 1, &no_panic, tracking);
if (!maybeo || maybeo.value() == nullptr) { if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) { if (is_variable) {
return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
@ -573,8 +575,9 @@ namespace sol {
} }
else { else {
using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_) #if SOL_IS_ON(SOL_SAFE_USERTYPE)
auto maybeo = stack::check_get<Ta*>(L, 1); stack::record tracking {};
auto maybeo = stack::stack_detail::check_get_arg<Ta*>(L, 1, &no_panic, tracking);
if (!maybeo || maybeo.value() == nullptr) { if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) { if (is_variable) {
return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
@ -811,8 +814,9 @@ namespace sol {
using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>; using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>;
using Ta = T; using Ta = T;
using Oa = std::remove_pointer_t<object_type>; using Oa = std::remove_pointer_t<object_type>;
#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_) #if SOL_IS_ON(SOL_SAFE_USERTYPE)
auto maybeo = stack::check_get<Ta*>(L, 1); stack::record tracking {};
auto maybeo = stack::stack_detail::check_get_arg<Ta*>(L, 1, &no_panic, tracking);
if (!maybeo || maybeo.value() == nullptr) { if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) { if (is_variable) {
return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -32,20 +32,20 @@
#include <sol/version.hpp> #include <sol/version.hpp>
#include <sol/compatibility/lua_version.hpp> #include <sol/compatibility/lua_version.hpp>
#if SOL_IS_ON(SOL_USE_COMPATIBILITY_LAYER_I_) #if SOL_IS_ON(SOL_USE_COMPATIBILITY_LAYER)
#if SOL_IS_ON(SOL_USE_CXX_LUA_I_) || SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_) // clang-format off
#ifndef COMPAT53_LUA_CPP #if SOL_IS_ON(SOL_USING_CXX_LUA) || SOL_IS_ON(SOL_USING_CXX_LUAJIT)
#define COMPAT53_LUA_CPP 1 #ifndef COMPAT53_LUA_CPP
#endif // Build Lua Compat layer as C++ #define COMPAT53_LUA_CPP 1
#endif // Build Lua Compat layer as C++
#endif #endif
#ifndef COMPAT53_INCLUDE_SOURCE #ifndef COMPAT53_INCLUDE_SOURCE
#define COMPAT53_INCLUDE_SOURCE 1 #define COMPAT53_INCLUDE_SOURCE 1
#endif // Build Compat Layer Inline #endif // Build Compat Layer Inline
#include <sol/compatibility/compat-5.3.h>
#include <sol/compatibility/compat-5.3.h> #include <sol/compatibility/compat-5.4.h>
#include <sol/compatibility/compat-5.4.h>
#endif #endif
// clang-format on
#endif // SOL_COMPATIBILITY_HPP #endif // SOL_COMPATIBILITY_HPP

View file

@ -7,9 +7,15 @@
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" { extern "C" {
#endif #endif
#include <lua.h> #if __has_include(<lua/lua.h>)
#include <lauxlib.h> #include <lua/lua.h>
#include <lualib.h> #include <lua/lauxlib.h>
#include <lua/lualib.h>
#else
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#endif
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
} }
#endif #endif

View file

@ -4,9 +4,15 @@
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" { extern "C" {
#endif #endif
#include <lua.h> #if __has_include(<lua/lua.h>)
#include <lauxlib.h> #include <lua/lua.h>
#include <lualib.h> #include <lua/lauxlib.h>
#include <lua/lualib.h>
#else
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#endif
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
} }
#endif #endif

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -21,24 +21,40 @@
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_COMPATIBILITY_VERSION_HPP #ifndef SOL_COMPATIBILITY_LUA_VERSION_HPP
#define SOL_COMPATIBILITY_VERSION_HPP #define SOL_COMPATIBILITY_LUA_VERSION_HPP
#include <sol/version.hpp> #include <sol/version.hpp>
// clang-format off // clang-format off
#if SOL_IS_ON(SOL_USE_CXX_LUA_I_) #if SOL_IS_ON(SOL_USING_CXX_LUA)
#if __has_include(<lua/lua.h>)
#include <lua/lua.h>
#include <lua/lauxlib.h>
#include <lua/lualib.h>
#else
#include <lua.h> #include <lua.h>
#include <lualib.h>
#include <lauxlib.h> #include <lauxlib.h>
#elif SOL_IS_ON(SOL_USE_LUA_HPP_I_) #include <lualib.h>
#endif
#elif SOL_IS_ON(SOL_USE_LUA_HPP)
#if __has_include(<lua/lua.hpp>)
#include <lua/lua.hpp>
#else
#include <lua.hpp> #include <lua.hpp>
#endif
#else #else
extern "C" { extern "C" {
#if __has_include(<lua/lua.h>)
#include <lua/lua.h>
#include <lua/lauxlib.h>
#include <lua/lualib.h>
#else
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
#include <lualib.h> #include <lualib.h>
#endif
} }
#endif // C++ Mangling for Lua vs. Not #endif // C++ Mangling for Lua vs. Not
@ -50,13 +66,15 @@
#endif #endif
#elif defined(LUAJIT_VERSION) #elif defined(LUAJIT_VERSION)
#define SOL_USE_LUAJIT_I_ SOL_ON #define SOL_USE_LUAJIT_I_ SOL_ON
#elif SOL_IS_ON(SOL_USING_CXX_LUAJIT)
#define SOL_USE_LUAJIT_I_ SOL_ON
#else #else
#define SOL_USE_LUAJIT_I_ SOL_DEFAULT_OFF #define SOL_USE_LUAJIT_I_ SOL_DEFAULT_OFF
#endif // luajit #endif // luajit
#if SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_) #if SOL_IS_ON(SOL_USING_CXX_LUAJIT)
#include <luajit.h> #include <luajit.h>
#elif SOL_IS_ON(SOL_USE_LUAJIT_I_) #elif SOL_IS_ON(SOL_USE_LUAJIT)
extern "C" { extern "C" {
#include <luajit.h> #include <luajit.h>
} }
@ -64,7 +82,7 @@
#if defined(SOL_LUAJIT_VERSION) #if defined(SOL_LUAJIT_VERSION)
#define SOL_LUAJIT_VERSION_I_ SOL_LUAJIT_VERSION #define SOL_LUAJIT_VERSION_I_ SOL_LUAJIT_VERSION
#elif SOL_IS_ON(SOL_USE_LUAJIT_I_) #elif SOL_IS_ON(SOL_USE_LUAJIT)
#define SOL_LUAJIT_VERSION_I_ LUAJIT_VERSION_NUM #define SOL_LUAJIT_VERSION_I_ LUAJIT_VERSION_NUM
#else #else
#define SOL_LUAJIT_VERSION_I_ 0 #define SOL_LUAJIT_VERSION_I_ 0
@ -118,21 +136,25 @@
#else #else
#define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
#endif #endif
#elif SOL_LUAJIT_VERSION_I_ >= 20100 #else
#if SOL_IS_ON(SOL_USE_LUAJIT)
#if SOL_USE(SOL_LUAJIT_VERSION) >= 20100
// LuaJIT 2.1.0-beta3 and better have exception support locked in for all platforms (mostly) // LuaJIT 2.1.0-beta3 and better have exception support locked in for all platforms (mostly)
#define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
#elif SOL_LUAJIT_VERSION_I_ >= 20000 #elif SOL_USE(SOL_LUAJIT_VERSION) >= 20000
// LuaJIT 2.0.x have exception support only on x64 builds // LuaJIT 2.0.x have exception support only on x64 builds
#if SOL_IS_ON(SOL_PLATFORM_X64_I_) #if SOL_IS_ON(SOL_PLATFORM_X64)
#define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
#else #else
#define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF
#endif #endif
#else #endif
#else
// otherwise, there is no exception safety for // otherwise, there is no exception safety for
// shoving exceptions through Lua and errors should // shoving exceptions through Lua and errors should
// always be serialized // always be serialized
#define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF
#endif
#endif #endif
// Some configurations work with exceptions, // Some configurations work with exceptions,
@ -144,13 +166,14 @@
#define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_OFF #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_OFF
#endif #endif
#else #else
#if SOL_IS_ON(SOL_USE_LUAJIT_I_) #if SOL_IS_ON(SOL_USE_LUAJIT) || SOL_IS_ON(SOL_USING_CXX_LUAJIT)
#define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF
#elif SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_) #elif SOL_IS_ON(SOL_USING_CXX_LUA)
#define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF // C++ builds of Lua will throw an exception to implement its `yield` behavior;
#elif SOL_IS_ON(SOL_USE_CXX_LUA_I_) // it is irresponsible to "catch all" on this setting.
#define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF
#else #else
// Otherwise, by default, everyhting should be caught.
#define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_ON #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_ON
#endif #endif
#endif #endif
@ -162,7 +185,7 @@
#define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_OFF #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_OFF
#endif #endif
#else #else
#if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) && SOL_IS_ON(SOL_USE_LUAJIT_I_) #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) && SOL_IS_ON(SOL_USE_LUAJIT)
#define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON
#else #else
#define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_DEFAULT_OFF #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_DEFAULT_OFF
@ -176,7 +199,7 @@
#define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_OFF #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_OFF
#endif #endif
#else #else
#if SOL_IS_OFF(SOL_USE_LUAJIT_I_) && (SOL_LUA_VERSION > 501) #if SOL_IS_OFF(SOL_USE_LUAJIT) && (SOL_LUA_VERSION > 501)
#define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON
#else #else
#define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_DEFAULT_OFF #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_DEFAULT_OFF
@ -192,7 +215,11 @@
#else #else
// Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags)
// Lua 5.2, or other versions of Lua with the compat flag, or Lua that is not 5.2 with the specific define (5.4.1 either removed it entirely or broke it) // Lua 5.2, or other versions of Lua with the compat flag, or Lua that is not 5.2 with the specific define (5.4.1 either removed it entirely or broke it)
#if (SOL_LUA_VERSION_I_ == 502) || (defined(LUA_COMPAT_BITLIB) && (LUA_COMPAT_BITLIB != 0)) || (SOL_LUA_VERSION_I_ < 504 && (defined(LUA_COMPAT_5_2) && (LUA_COMPAT_5_2 != 0))) #if (SOL_LUA_VERSION_I_ == 502)
#define SOL_LUA_BIT32_LIB_I_ SOL_ON
#elif defined(LUA_COMPAT_BITLIB)
#define SOL_LUA_BIT32_LIB_I_ SOL_ON
#elif (SOL_LUA_VERSION_I_ < 504 && defined(LUA_COMPAT_5_2))
#define SOL_LUA_BIT32_LIB_I_ SOL_ON #define SOL_LUA_BIT32_LIB_I_ SOL_ON
#else #else
#define SOL_LUA_BIT32_LIB_I_ SOL_DEFAULT_OFF #define SOL_LUA_BIT32_LIB_I_ SOL_DEFAULT_OFF
@ -215,4 +242,4 @@
// clang-format on // clang-format on
#endif // SOL_COMPATIBILITY_VERSION_HPP #endif // SOL_COMPATIBILITY_LUA_VERSION_HPP

50
extern/sol3/sol/config.hpp vendored Normal file
View file

@ -0,0 +1,50 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_CONFIG_HPP
#define SOL_CONFIG_HPP
/* Base, empty configuration file!
To override, place a file in your include paths of the form:
. (your include path here)
| sol (directory, or equivalent)
| config.hpp (your config.hpp file)
So that when sol2 includes the file
#include <sol/config.hpp>
it gives you the configuration values you desire. Configuration values can be
seen in the safety.rst of the doc/src, or at
https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through
the build system, or the command line options of your compiler.
*/
#endif // SOL_CONFIG_HPP

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -94,7 +94,7 @@ namespace sol {
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_coroutine(T&& r) noexcept basic_coroutine(T&& r) noexcept
: base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { : base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_function<meta::unqualified_t<T>>::value) { if (!is_function<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
@ -157,7 +157,7 @@ namespace sol {
} }
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) { basic_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_coroutine>(lua_state(), -1, handler); stack::check<basic_coroutine>(lua_state(), -1, handler);
@ -180,7 +180,7 @@ namespace sol {
: basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_coroutine>(L, index, handler); stack::check<basic_coroutine>(L, index, handler);
#endif // Safety #endif // Safety
@ -189,7 +189,7 @@ namespace sol {
: basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_coroutine>(L, index, handler); stack::check<basic_coroutine>(L, index, handler);
#endif // Safety #endif // Safety
@ -198,7 +198,7 @@ namespace sol {
: basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_coroutine>(lua_state(), -1, handler); stack::check<basic_coroutine>(lua_state(), -1, handler);

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -47,6 +47,17 @@ namespace sol { namespace detail { namespace debug {
inline void print_section(const std::string& message, lua_State* L) { inline void print_section(const std::string& message, lua_State* L) {
std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl;
} }
inline void print_lua_information(lua_State* L) {
std::cout << "Lua Version: " << SOL_USE(SOL_LUA_VERSION) << std::endl;
std::cout << "Lua (C++): " << SOL_IS_ON(SOL_USING_CXX_LUA) << std::endl;
std::cout << "Trampoline Propagate Exceptions?: " << SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) << std::endl;
std::cout << "Catch-all Exceptions?: " << SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) << std::endl;
std::cout << "LuaJIT: " << SOL_IS_ON(SOL_USE_LUAJIT) << std::endl;
std::cout << "LuaJIT Version: " << SOL_USE(SOL_LUAJIT_VERSION) << std::endl;
std::cout << "LuaJIT (C++): " << SOL_IS_ON(SOL_USING_CXX_LUAJIT) << std::endl;
std::cout << "LuaJIT Exception Trampoline: " << SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE) << std::endl;
}
}}} // namespace sol::detail::debug }}} // namespace sol::detail::debug
#endif // SOL_DEBUG_HPP #endif // SOL_DEBUG_HPP

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -28,7 +28,7 @@
#include <string> #include <string>
#include <array> #include <array>
#include <cctype> #include <cctype>
#if SOL_IS_ON(SOL_MINGW_CCTYPE_IS_POISONED_I_) #if SOL_IS_ON(SOL_MINGW_CCTYPE_IS_POISONED)
extern "C" { extern "C" {
#include <ctype.h> #include <ctype.h>
} }
@ -47,7 +47,7 @@ namespace sol { namespace detail {
"`anonymous namespace'" } }; "`anonymous namespace'" } };
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
inline std::string ctti_get_type_name_from_sig(std::string name) { inline std::string ctti_get_type_name_from_sig(std::string name) {
// cardinal sins from MINGW // cardinal sins from MINGW
using namespace std; using namespace std;
@ -85,7 +85,7 @@ namespace sol { namespace detail {
inline std::string ctti_get_type_name() { inline std::string ctti_get_type_name() {
return ctti_get_type_name_from_sig(__PRETTY_FUNCTION__); return ctti_get_type_name_from_sig(__PRETTY_FUNCTION__);
} }
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) #elif SOL_IS_ON(SOL_COMPILER_VCXX)
inline std::string ctti_get_type_name_from_sig(std::string name) { inline std::string ctti_get_type_name_from_sig(std::string name) {
std::size_t start = name.find("get_type_name"); std::size_t start = name.find("get_type_name");
if (start == std::string::npos) if (start == std::string::npos)

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -36,7 +36,7 @@
#else #else
#define SOL_DLL_I_ SOL_OFF #define SOL_DLL_I_ SOL_OFF
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) && (defined(DLL_) || defined(_DLL)) #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL))
#define SOL_DLL_I_ SOL_DEFAULT_ON #define SOL_DLL_I_ SOL_DEFAULT_ON
#else #else
#define SOL_DLL_I_ SOL_DEFAULT_OFF #define SOL_DLL_I_ SOL_DEFAULT_OFF
@ -58,7 +58,7 @@
#else #else
#define SOL_BUILD_I_ SOL_OFF #define SOL_BUILD_I_ SOL_OFF
#endif #endif
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_) #elif SOL_IS_ON(SOL_HEADER_ONLY)
#define SOL_BUILD_I_ SOL_DEFAULT_OFF #define SOL_BUILD_I_ SOL_DEFAULT_OFF
#else #else
#define SOL_BUILD_I_ SOL_DEFAULT_ON #define SOL_BUILD_I_ SOL_DEFAULT_ON
@ -77,7 +77,7 @@
#if defined(SOL_C_FUNCTION_LINKAGE) #if defined(SOL_C_FUNCTION_LINKAGE)
#define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE
#else #else
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_) #if SOL_IS_ON(SOL_BUILD_CXX_MODE)
// C++ // C++
#define SOL_C_FUNCTION_LINKAGE_I_ extern "C" #define SOL_C_FUNCTION_LINKAGE_I_ extern "C"
#else #else
@ -89,12 +89,12 @@
#if defined(SOL_API_LINKAGE) #if defined(SOL_API_LINKAGE)
#define SOL_API_LINKAGE_I_ SOL_API_LINKAGE #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE
#else #else
#if SOL_IS_ON(SOL_DLL_I_) #if SOL_IS_ON(SOL_DLL)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) || SOL_IS_ON(SOL_PLATFORM_WINDOWS_I_) || SOL_IS_ON(SOL_PLATFORM_CYGWIN_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN)
// MSVC Compiler; or, Windows, or Cygwin platforms // MSVC Compiler; or, Windows, or Cygwin platforms
#if SOL_IS_ON(SOL_BUILD_I_) #if SOL_IS_ON(SOL_BUILD)
// Building the library // Building the library
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) #if SOL_IS_ON(SOL_COMPILER_GCC)
// Using GCC // Using GCC
#define SOL_API_LINKAGE_I_ __attribute__((dllexport)) #define SOL_API_LINKAGE_I_ __attribute__((dllexport))
#else #else
@ -102,7 +102,7 @@
#define SOL_API_LINKAGE_I_ __declspec(dllexport) #define SOL_API_LINKAGE_I_ __declspec(dllexport)
#endif #endif
#else #else
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) #if SOL_IS_ON(SOL_COMPILER_GCC)
#define SOL_API_LINKAGE_I_ __attribute__((dllimport)) #define SOL_API_LINKAGE_I_ __attribute__((dllimport))
#else #else
#define SOL_API_LINKAGE_I_ __declspec(dllimport) #define SOL_API_LINKAGE_I_ __declspec(dllimport)
@ -112,9 +112,9 @@
// extern if building normally on non-MSVC // extern if building normally on non-MSVC
#define SOL_API_LINKAGE_I_ extern #define SOL_API_LINKAGE_I_ extern
#endif #endif
#elif SOL_IS_ON(SOL_UNITY_BUILD_I_) #elif SOL_IS_ON(SOL_UNITY_BUILD)
// Built-in library, like how stb typical works // Built-in library, like how stb typical works
#if SOL_IS_ON(SOL_HEADER_ONLY_I_) #if SOL_IS_ON(SOL_HEADER_ONLY)
// Header only, so functions are defined "inline" // Header only, so functions are defined "inline"
#define SOL_API_LINKAGE_I_ inline #define SOL_API_LINKAGE_I_ inline
#else #else
@ -123,7 +123,7 @@
#endif #endif
#else #else
// Normal static library // Normal static library
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_) #if SOL_IS_ON(SOL_BUILD_CXX_MODE)
#define SOL_API_LINKAGE_I_ #define SOL_API_LINKAGE_I_
#else #else
#define SOL_API_LINKAGE_I_ extern #define SOL_API_LINKAGE_I_ extern
@ -157,16 +157,16 @@
#if defined(SOL_FUNC_DECL) #if defined(SOL_FUNC_DECL)
#define SOL_FUNC_DECL_I_ SOL_FUNC_DECL #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_) #elif SOL_IS_ON(SOL_HEADER_ONLY)
#define SOL_FUNC_DECL_I_ #define SOL_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_) #elif SOL_IS_ON(SOL_DLL)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
#if SOL_IS_ON(SOL_BUILD_I_) #if SOL_IS_ON(SOL_BUILD)
#define SOL_FUNC_DECL_I_ extern __declspec(dllexport) #define SOL_FUNC_DECL_I_ extern __declspec(dllexport)
#else #else
#define SOL_FUNC_DECL_I_ extern __declspec(dllimport) #define SOL_FUNC_DECL_I_ extern __declspec(dllimport)
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
#define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else #else
#define SOL_FUNC_DECL_I_ extern #define SOL_FUNC_DECL_I_ extern
@ -175,16 +175,16 @@
#if defined(SOL_FUNC_DEFN) #if defined(SOL_FUNC_DEFN)
#define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_) #elif SOL_IS_ON(SOL_HEADER_ONLY)
#define SOL_FUNC_DEFN_I_ inline #define SOL_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_) #elif SOL_IS_ON(SOL_DLL)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
#if SOL_IS_ON(SOL_BUILD_I_) #if SOL_IS_ON(SOL_BUILD)
#define SOL_FUNC_DEFN_I_ __declspec(dllexport) #define SOL_FUNC_DEFN_I_ __declspec(dllexport)
#else #else
#define SOL_FUNC_DEFN_I_ __declspec(dllimport) #define SOL_FUNC_DEFN_I_ __declspec(dllimport)
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
#define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default")))
#else #else
#define SOL_FUNC_DEFN_I_ #define SOL_FUNC_DEFN_I_
@ -193,16 +193,16 @@
#if defined(SOL_HIDDEN_FUNC_DECL) #if defined(SOL_HIDDEN_FUNC_DECL)
#define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_) #elif SOL_IS_ON(SOL_HEADER_ONLY)
#define SOL_HIDDEN_FUNC_DECL_I_ #define SOL_HIDDEN_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_) #elif SOL_IS_ON(SOL_DLL)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
#if SOL_IS_ON(SOL_BUILD_I_) #if SOL_IS_ON(SOL_BUILD)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport)
#else #else
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport)
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else #else
#define SOL_HIDDEN_FUNC_DECL_I_ extern #define SOL_HIDDEN_FUNC_DECL_I_ extern
@ -211,16 +211,16 @@
#if defined(SOL_HIDDEN_FUNC_DEFN) #if defined(SOL_HIDDEN_FUNC_DEFN)
#define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_) #elif SOL_IS_ON(SOL_HEADER_ONLY)
#define SOL_HIDDEN_FUNC_DEFN_I_ inline #define SOL_HIDDEN_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_) #elif SOL_IS_ON(SOL_DLL)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
#if SOL_IS_ON(SOL_BUILD_I_) #if SOL_IS_ON(SOL_BUILD)
#define SOL_HIDDEN_FUNC_DEFN_I_ #define SOL_HIDDEN_FUNC_DEFN_I_
#else #else
#define SOL_HIDDEN_FUNC_DEFN_I_ #define SOL_HIDDEN_FUNC_DEFN_I_
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
#define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden")))
#else #else
#define SOL_HIDDEN_FUNC_DEFN_I_ #define SOL_HIDDEN_FUNC_DEFN_I_

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -61,7 +61,7 @@ namespace sol {
} }
inline int dump_throw_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) { inline int dump_throw_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip); return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip);
#else #else
(void)L_; (void)L_;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -26,6 +26,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <memory>
namespace sol { namespace detail { namespace sol { namespace detail {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -58,29 +58,29 @@ namespace sol {
basic_environment(env_key_t, const stack_reference& extraction_target) basic_environment(env_key_t, const stack_reference& extraction_target)
: base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<env_key_t>(this->lua_state(), -1, handler); stack::check<env_key_t>(this->lua_state(), -1, handler);
#endif // Safety #endif // Safety
lua_pop(this->lua_state(), 2); lua_pop(this->lua_state(), 1);
} }
template <bool b> template <bool b>
basic_environment(env_key_t, const basic_reference<b>& extraction_target) basic_environment(env_key_t, const basic_reference<b>& extraction_target)
: base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<env_key_t>(this->lua_state(), -1, handler); stack::check<env_key_t>(this->lua_state(), -1, handler);
#endif // Safety #endif // Safety
lua_pop(this->lua_state(), 2); lua_pop(this->lua_state(), 1);
} }
basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_environment>(L, index, handler); stack::check<basic_environment>(L, index, handler);
#endif // Safety #endif // Safety
} }
basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_environment>(L, -1, handler); stack::check<basic_environment>(L, -1, handler);
@ -90,7 +90,7 @@ namespace sol {
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward<T>(r)) { basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_environment<meta::unqualified_t<T>>::value) { if (!is_environment<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
@ -103,7 +103,7 @@ namespace sol {
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward<T>(r)) { basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_environment<meta::unqualified_t<T>>::value) { if (!is_environment<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
@ -136,11 +136,13 @@ namespace sol {
const char* success = lua_setupvalue(L, target_index, 1); const char* success = lua_setupvalue(L, target_index, 1);
if (success == nullptr) { if (success == nullptr) {
// left things alone on the stack, pop them off // left things alone on the stack, pop them off
lua_pop(L, 1); lua_pop(L, 2);
return false; return false;
} }
lua_pop(L, 1);
return true; return true;
} }
lua_pop(L, 1);
return false; return false;
} }
else { else {
@ -152,6 +154,7 @@ namespace sol {
} }
string_view upvalue_name(maybe_upvalue_name); string_view upvalue_name(maybe_upvalue_name);
if (upvalue_name == "_ENV") { if (upvalue_name == "_ENV") {
lua_pop(L, 1);
this->push(); this->push();
const char* success = lua_setupvalue(L, target_index, upvalue_index); const char* success = lua_setupvalue(L, target_index, upvalue_index);
if (success == nullptr) { if (success == nullptr) {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -31,7 +31,7 @@
#undef SOL_PROLOGUE_I_ #undef SOL_PROLOGUE_I_
#endif #endif
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_) #if SOL_IS_ON(SOL_BUILD_CXX_MODE)
#undef _FWD #undef _FWD
#undef _MOVE #undef _MOVE
#endif #endif

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -57,6 +57,23 @@ namespace sol {
} }
return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]); return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]);
} }
class error_exception : public std::runtime_error {
public:
error_exception(const std::string& str) : error_exception(detail::direct_error, "lua: error: " + str) {
}
error_exception(std::string&& str) : error_exception(detail::direct_error, "lua: error: " + std::move(str)) {
}
error_exception(detail::direct_error_tag, const std::string& str) : std::runtime_error(str) {
}
error_exception(detail::direct_error_tag, std::string&& str) : std::runtime_error(str) {
}
error_exception(const error_exception& e) = default;
error_exception(error_exception&& e) = default;
error_exception& operator=(const error_exception& e) = default;
error_exception& operator=(error_exception&& e) = default;
};
} // namespace detail } // namespace detail
class error : public std::runtime_error { class error : public std::runtime_error {
@ -69,19 +86,15 @@ namespace sol {
} }
error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) { error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {
} }
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), what_reason(str) { error(detail::direct_error_tag, const std::string& str) : std::runtime_error(str) {
} }
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), what_reason(std::move(str)) { error(detail::direct_error_tag, std::string&& str) : std::runtime_error(str) {
} }
error(const error& e) = default; error(const error& e) = default;
error(error&& e) = default; error(error&& e) = default;
error& operator=(const error& e) = default; error& operator=(const error& e) = default;
error& operator=(error&& e) = default; error& operator=(error&& e) = default;
virtual const char* what() const noexcept override {
return what_reason.c_str();
}
}; };
} // namespace sol } // namespace sol

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -24,6 +24,7 @@
#ifndef SOL_ERROR_HANDLER_HPP #ifndef SOL_ERROR_HANDLER_HPP
#define SOL_ERROR_HANDLER_HPP #define SOL_ERROR_HANDLER_HPP
#include <sol/config.hpp>
#include <sol/types.hpp> #include <sol/types.hpp>
#include <sol/demangle.hpp> #include <sol/demangle.hpp>
@ -62,7 +63,7 @@ namespace sol {
case type::poly: case type::poly:
return "anything"; return "anything";
case type::userdata: { case type::userdata: {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, 2, "not enough space to push get the type name"); luaL_checkstack(L, 2, "not enough space to push get the type name");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
if (lua_getmetatable(L, index) == 0) { if (lua_getmetatable(L, index) == 0) {
@ -84,7 +85,7 @@ namespace sol {
inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept { inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
const char* err = message.size() == 0 const char* err = message.size() == 0
? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s") ? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s%s")
: "stack index %d, expected %s, received %s: %s %s"; : "stack index %d, expected %s, received %s: %s %s";
const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)); const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected));
{ {
@ -96,12 +97,16 @@ namespace sol {
inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) { inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) {
push_type_panic_string(L, index, expected, actual, message, ""); push_type_panic_string(L, index, expected, actual, message, "");
return lua_error(L); size_t str_size = 0;
const char* str = lua_tolstring(L, -1, &str_size);
return luaL_error(L, str);
} }
inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, ""); push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, "");
return lua_error(L); size_t str_size = 0;
const char* str = lua_tolstring(L, -1, &str_size);
return luaL_error(L, str);
} }
struct type_panic_t { struct type_panic_t {
@ -118,7 +123,9 @@ namespace sol {
struct constructor_handler { struct constructor_handler {
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)"); push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)");
return lua_error(L); size_t str_size = 0;
const char* str = lua_tolstring(L, -1, &str_size);
return luaL_error(L, str);
} }
}; };
@ -126,7 +133,9 @@ namespace sol {
struct argument_handler { struct argument_handler {
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)"); push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)");
return lua_error(L); size_t str_size = 0;
const char* str = lua_tolstring(L, -1, &str_size);
return luaL_error(L, str);
} }
}; };
@ -142,7 +151,9 @@ namespace sol {
aux_message += ")')"; aux_message += ")')";
push_type_panic_string(L, index, expected, actual, message, aux_message); push_type_panic_string(L, index, expected, actual, message, aux_message);
} }
return lua_error(L); size_t str_size = 0;
const char* str = lua_tolstring(L, -1, &str_size);
return luaL_error(L, str);
} }
}; };

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -30,7 +30,7 @@
#include <type_traits> #include <type_traits>
#include <string_view> #include <string_view>
#if SOL_IS_ON(SOL_USE_CXX_LUA_I_) || SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_) #if SOL_IS_ON(SOL_USING_CXX_LUA) || SOL_IS_ON(SOL_USING_CXX_LUAJIT)
struct lua_State; struct lua_State;
#else #else
extern "C" { extern "C" {
@ -117,7 +117,7 @@ namespace sol {
using main_protected_function = main_safe_function; using main_protected_function = main_safe_function;
using stack_protected_function = stack_safe_function; using stack_protected_function = stack_safe_function;
using stack_aligned_protected_function = stack_aligned_safe_function; using stack_aligned_protected_function = stack_aligned_safe_function;
#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS_I_) #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS)
using function = protected_function; using function = protected_function;
using main_function = main_protected_function; using main_function = main_protected_function;
using stack_function = stack_protected_function; using stack_function = stack_protected_function;
@ -133,7 +133,7 @@ namespace sol {
struct unsafe_function_result; struct unsafe_function_result;
struct protected_function_result; struct protected_function_result;
using safe_function_result = protected_function_result; using safe_function_result = protected_function_result;
#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS_I_) #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS)
using function_result = safe_function_result; using function_result = safe_function_result;
#else #else
using function_result = unsafe_function_result; using function_result = unsafe_function_result;
@ -234,7 +234,7 @@ namespace sol {
struct record; struct record;
} }
#if SOL_IS_OFF(SOL_USE_BOOST_I_) #if SOL_IS_OFF(SOL_USE_BOOST)
template <class T> template <class T>
class optional; class optional;
@ -253,7 +253,7 @@ namespace sol {
typedef ::sol::types<__VA_ARGS__> type; \ typedef ::sol::types<__VA_ARGS__> type; \
}; \ }; \
} \ } \
void a_sol3_detail_function_decl_please_no_collide() static_assert(true, "")
#define SOL_DERIVED_CLASSES(T, ...) \ #define SOL_DERIVED_CLASSES(T, ...) \
namespace sol { \ namespace sol { \
template <> \ template <> \
@ -261,6 +261,6 @@ namespace sol {
typedef ::sol::types<__VA_ARGS__> type; \ typedef ::sol::types<__VA_ARGS__> type; \
}; \ }; \
} \ } \
void a_sol3_detail_function_decl_please_no_collide() static_assert(true, "")
#endif // SOL_FORWARD_HPP #endif // SOL_FORWARD_HPP

44
extern/sol3/sol/forward_as.hpp vendored Normal file
View file

@ -0,0 +1,44 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_FORWARD_AS_HPP
#define SOL_FORWARD_AS_HPP
#include <sol/version.hpp>
#include <utility>
#include <type_traits>
namespace sol {
template <typename T, typename U>
constexpr decltype(auto) forward_as(U&& value) noexcept {
if constexpr (::std::is_lvalue_reference_v<T>) {
return value;
}
else {
return ::std::move(value);
}
}
}
#endif // SOL_FORWARD_AS_HPP

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -32,7 +32,7 @@
namespace sol { namespace sol {
namespace detail { namespace detail {
const bool default_safe_function_calls = const bool default_safe_function_calls =
#if SOL_IS_ON(SOL_SAFE_FUNCTION_CALLS_I_) #if SOL_IS_ON(SOL_SAFE_FUNCTION_CALLS)
true; true;
#else #else
false; false;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -217,7 +217,7 @@ namespace sol {
int upvalues = 0; int upvalues = 0;
upvalues += stack::push(L, nullptr); upvalues += stack::push(L, nullptr);
upvalues += stack::push(L, std::forward<Fx>(fx)); upvalues += stack::push(L, std::forward<Fx>(fx));
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) { if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<true>; detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<true>;
lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues); lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
@ -237,7 +237,7 @@ namespace sol {
int upvalues = 0; int upvalues = 0;
upvalues += stack::push(L, nullptr); upvalues += stack::push(L, nullptr);
upvalues += stack::push(L, std::forward<Fx>(fx)); upvalues += stack::push(L, std::forward<Fx>(fx));
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) { if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>; detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues); lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
@ -398,7 +398,7 @@ namespace sol {
struct unqualified_pusher<Signature, struct unqualified_pusher<Signature,
std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>, std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>> meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
, ,
meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>, meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>> meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
@ -711,7 +711,7 @@ namespace sol {
namespace stack_detail { namespace stack_detail {
template <typename Function, typename Handler> template <typename Function, typename Handler>
bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept { bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept {
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_) #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
tracking.use(1); tracking.use(1);
bool success = lua_iscfunction(L, index) == 1; bool success = lua_iscfunction(L, index) == 1;
if (success) { if (success) {
@ -737,7 +737,7 @@ namespace sol {
template <typename Function> template <typename Function>
Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept { Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept {
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_) #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
tracking.use(1); tracking.use(1);
auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index); auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
Function* fx = udata.first; Function* fx = udata.first;
@ -747,7 +747,7 @@ namespace sol {
(void)index; (void)index;
(void)tracking; (void)tracking;
static_assert(meta::meta_detail::always_true<Function>::value, static_assert(meta::meta_detail::always_true<Function>::value,
#if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE_I_) #if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE)
"You are attempting to retrieve a function pointer type. " "You are attempting to retrieve a function pointer type. "
"This is inherently unsafe in sol2. In order to do this, you must turn on the " "This is inherently unsafe in sol2. In order to do this, you must turn on the "
"SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. " "SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. "

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -74,7 +74,7 @@ namespace sol { namespace function_detail {
} }
static int call(lua_State* L, member_function& self) static int call(lua_State* L, member_function& self)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -90,7 +90,7 @@ namespace sol { namespace function_detail {
} }
int operator()(lua_State* L) int operator()(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -35,7 +35,7 @@ namespace sol { namespace function_detail {
using traits_type = meta::bind_traits<function_type>; using traits_type = meta::bind_traits<function_type>;
static int real_call(lua_State* L) static int real_call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -70,7 +70,7 @@ namespace sol { namespace function_detail {
typedef lua_bind_traits<function_type> traits_type; typedef lua_bind_traits<function_type> traits_type;
static int real_call(lua_State* L) static int real_call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -88,7 +88,7 @@ namespace sol { namespace function_detail {
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -110,7 +110,7 @@ namespace sol { namespace function_detail {
} }
int operator()(lua_State* L) int operator()(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -126,7 +126,7 @@ namespace sol { namespace function_detail {
typedef lua_bind_traits<function_type> traits_type; typedef lua_bind_traits<function_type> traits_type;
static int real_call(lua_State* L) static int real_call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -153,7 +153,7 @@ namespace sol { namespace function_detail {
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -175,7 +175,7 @@ namespace sol { namespace function_detail {
} }
int operator()(lua_State* L) int operator()(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -191,7 +191,7 @@ namespace sol { namespace function_detail {
typedef lua_bind_traits<function_type> traits_type; typedef lua_bind_traits<function_type> traits_type;
static int real_call(lua_State* L) static int real_call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -216,7 +216,7 @@ namespace sol { namespace function_detail {
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -238,7 +238,7 @@ namespace sol { namespace function_detail {
} }
int operator()(lua_State* L) int operator()(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -254,7 +254,7 @@ namespace sol { namespace function_detail {
typedef lua_bind_traits<function_type> traits_type; typedef lua_bind_traits<function_type> traits_type;
static int real_call(lua_State* L) static int real_call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -268,7 +268,7 @@ namespace sol { namespace function_detail {
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -290,7 +290,7 @@ namespace sol { namespace function_detail {
} }
int operator()(lua_State* L) int operator()(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) #if SOL_IS_ON(SOL_COMPILER_VCXX)
// MSVC is broken, what a surprise... // MSVC is broken, what a surprise...
#else #else
noexcept(traits_type::is_noexcept) noexcept(traits_type::is_noexcept)
@ -320,7 +320,13 @@ namespace sol { namespace function_detail {
} }
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_CLANG)
// apparent regression in clang 18 - llvm/llvm-project#91362
#else
noexcept(std::is_nothrow_copy_assignable_v<T>)
#endif
{
int nr; int nr;
if constexpr (no_trampoline) { if constexpr (no_trampoline) {
nr = real_call(L); nr = real_call(L);
@ -360,7 +366,13 @@ namespace sol { namespace function_detail {
} }
template <bool is_yielding, bool no_trampoline> template <bool is_yielding, bool no_trampoline>
static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { static int call(lua_State* L)
#if SOL_IS_ON(SOL_COMPILER_CLANG)
// apparent regression in clang 18 - llvm/llvm-project#91362
#else
noexcept(std::is_nothrow_copy_assignable_v<T>)
#endif
{
int nr; int nr;
if constexpr (no_trampoline) { if constexpr (no_trampoline) {
nr = real_call(L); nr = real_call(L);

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -121,7 +121,7 @@ namespace sol {
typedef meta::unqualified_t<F> Fu; typedef meta::unqualified_t<F> Fu;
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
std::is_same<Fu, lua_CFunction>::value std::is_same<Fu, lua_CFunction>::value
#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
|| std::is_same<Fu, detail::lua_CFunction_noexcept>::value || std::is_same<Fu, detail::lua_CFunction_noexcept>::value
#endif #endif
> >

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -39,7 +39,7 @@ namespace sol {
load_status err; load_status err;
public: public:
load_result() noexcept = default; load_result() noexcept : load_result(nullptr) {}
load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept
: L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) {
} }
@ -95,7 +95,7 @@ namespace sol {
if (valid()) { if (valid()) {
return UT(nullopt); return UT(nullopt);
} }
return error(detail::direct_error, stack::get<std::string>(L, index)); return stack::stack_detail::get_error(L, index);
} }
else { else {
if (!valid()) { if (!valid()) {
@ -106,15 +106,15 @@ namespace sol {
} }
else { else {
if constexpr (std::is_same_v<T, error>) { if constexpr (std::is_same_v<T, error>) {
#if SOL_IS_ON(SOL_SAFE_PROXIES_I_) #if SOL_IS_ON(SOL_SAFE_PROXIES)
if (valid()) { if (valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)"); type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)");
} }
#endif // Check proxy type's safety #endif // Check proxy type's safety
return error(detail::direct_error, stack::get<std::string>(L, index)); return stack::stack_detail::get_error(L, index);
} }
else { else {
#if SOL_IS_ON(SOL_SAFE_PROXIES_I_) #if SOL_IS_ON(SOL_SAFE_PROXIES)
if (!valid()) { if (!valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none); type_panic_c_str(L, index, type_of(L, index), type::none);
} }
@ -142,8 +142,10 @@ namespace sol {
}; };
~load_result() { ~load_result() {
if (L != nullptr) {
stack::remove(L, index, popcount); stack::remove(L, index, popcount);
} }
}
}; };
} // namespace sol } // namespace sol

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -50,7 +50,7 @@ namespace sol {
} }
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler); stack::check<basic_lua_table>(lua_state(), -1, handler);
@ -62,13 +62,13 @@ namespace sol {
} }
} }
basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_lua_table>(L, index, handler); stack::check<basic_lua_table>(L, index, handler);
#endif // Safety #endif // Safety
} }
basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler); stack::check<basic_lua_table>(lua_state(), -1, handler);
@ -78,7 +78,7 @@ namespace sol {
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) { basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_table<meta::unqualified_t<T>>::value) { if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -48,7 +48,7 @@ namespace sol {
using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>; using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
static lua_State*& thread_local_lua_state() { static lua_State*& thread_local_lua_state() {
#if SOL_IS_ON(SOL_USE_THREAD_LOCAL_I_) #if SOL_IS_ON(SOL_USE_THREAD_LOCAL)
static thread_local lua_State* L = nullptr; static thread_local lua_State* L = nullptr;
#else #else
static lua_State* L = nullptr; static lua_State* L = nullptr;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -86,20 +86,20 @@ namespace sol {
} }
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_metatable(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { basic_metatable(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_metatable>(lua_state(), -1, handler); stack::check<basic_metatable>(lua_state(), -1, handler);
#endif // Safety #endif // Safety
} }
basic_metatable(lua_State* L, int index = -1) : basic_metatable(detail::no_safety, L, index) { basic_metatable(lua_State* L, int index = -1) : basic_metatable(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_metatable>(L, index, handler); stack::check<basic_metatable>(L, index, handler);
#endif // Safety #endif // Safety
} }
basic_metatable(lua_State* L, ref_index index) : basic_metatable(detail::no_safety, L, index) { basic_metatable(lua_State* L, ref_index index) : basic_metatable(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_metatable>(lua_state(), -1, handler); stack::check<basic_metatable>(lua_state(), -1, handler);
@ -109,7 +109,7 @@ namespace sol {
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_metatable(T&& r) noexcept : basic_metatable(detail::no_safety, std::forward<T>(r)) { basic_metatable(T&& r) noexcept : basic_metatable(detail::no_safety, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_table<meta::unqualified_t<T>>::value) { if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -27,7 +27,7 @@
#include <sol/forward.hpp> #include <sol/forward.hpp>
#include <sol/in_place.hpp> #include <sol/in_place.hpp>
#include <sol/traits.hpp> #include <sol/traits.hpp>
#if SOL_IS_ON(SOL_USE_BOOST_I_) #if SOL_IS_ON(SOL_USE_BOOST)
#include <boost/optional.hpp> #include <boost/optional.hpp>
#else #else
#include <sol/optional_implementation.hpp> #include <sol/optional_implementation.hpp>
@ -38,7 +38,7 @@
namespace sol { namespace sol {
#if SOL_IS_ON(SOL_USE_BOOST_I_) #if SOL_IS_ON(SOL_USE_BOOST)
template <typename T> template <typename T>
using optional = boost::optional<T>; using optional = boost::optional<T>;
using nullopt_t = boost::none_t; using nullopt_t = boost::none_t;
@ -59,14 +59,14 @@ namespace sol {
inline static constexpr std::nullopt_t value = std::nullopt; inline static constexpr std::nullopt_t value = std::nullopt;
}; };
#if SOL_IS_ON(SOL_USE_BOOST_I_) #if SOL_IS_ON(SOL_USE_BOOST)
template <typename T> template <typename T>
struct associated_nullopt<boost::optional<T>> { struct associated_nullopt<boost::optional<T>> {
inline static SOL_BOOST_NONE_CONSTEXPR_I_ boost::none_t value = boost::none; inline static SOL_BOOST_NONE_CONSTEXPR_I_ boost::none_t value = boost::none;
}; };
#endif // Boost nullopt #endif // Boost nullopt
#if SOL_IS_ON(SOL_USE_BOOST_I_) #if SOL_IS_ON(SOL_USE_BOOST)
template <typename T> template <typename T>
inline SOL_BOOST_NONE_CONSTEXPR_I_ auto associated_nullopt_v = associated_nullopt<T>::value; inline SOL_BOOST_NONE_CONSTEXPR_I_ auto associated_nullopt_v = associated_nullopt<T>::value;
#else #else
@ -76,7 +76,7 @@ namespace sol {
} // namespace detail } // namespace detail
} // namespace sol } // namespace sol
#if SOL_IS_ON(SOL_USE_BOOST_I_) #if SOL_IS_ON(SOL_USE_BOOST)
#undef SOL_BOOST_NONE_CONSTEXPR_I_ #undef SOL_BOOST_NONE_CONSTEXPR_I_
#endif #endif

View file

@ -1,6 +1,6 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -1375,7 +1375,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & { SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & {
if (has_value()) if (has_value())
return this->m_value; return this->m_value;
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();
@ -1386,7 +1386,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& { SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& {
if (has_value()) if (has_value())
return this->m_value; return this->m_value;
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();
@ -1396,7 +1396,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && { SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && {
if (has_value()) if (has_value())
return std::move(this->m_value); return std::move(this->m_value);
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();
@ -1408,7 +1408,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& { SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& {
if (has_value()) if (has_value())
return std::move(this->m_value); return std::move(this->m_value);
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();
@ -2186,12 +2186,9 @@ namespace sol {
/// one. /// one.
/// ///
/// \group emplace /// \group emplace
template <class... Args> T& emplace(T& arg) noexcept {
T& emplace(Args&&... args) noexcept {
static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
*this = nullopt; *this = nullopt;
new (static_cast<void*>(this)) optional(std::in_place, std::forward<Args>(args)...); m_value = &arg;
return **this; return **this;
} }
@ -2251,7 +2248,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR T& value() { SOL_TL_OPTIONAL_11_CONSTEXPR T& value() {
if (has_value()) if (has_value())
return *m_value; return *m_value;
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();
@ -2262,7 +2259,7 @@ namespace sol {
SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const { SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const {
if (has_value()) if (has_value())
return *m_value; return *m_value;
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_EXCEPTIONS)
std::abort(); std::abort();
#else #else
throw bad_optional_access(); throw bad_optional_access();

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -96,7 +96,7 @@ namespace sol {
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(T&& r) noexcept basic_packaged_coroutine(T&& r) noexcept
: base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { : base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_function<meta::unqualified_t<T>>::value) { if (!is_function<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
@ -160,7 +160,7 @@ namespace sol {
} }
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) { basic_packaged_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler); stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
@ -183,7 +183,7 @@ namespace sol {
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_packaged_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_packaged_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler); stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety #endif // Safety
@ -192,7 +192,7 @@ namespace sol {
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_packaged_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_packaged_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler); stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety #endif // Safety
@ -201,7 +201,7 @@ namespace sol {
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { : basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
} }
basic_packaged_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { basic_packaged_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler); stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -28,6 +28,7 @@
#include <utility> #include <utility>
#include <type_traits> #include <type_traits>
#include <memory>
namespace sol { namespace sol {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -32,10 +32,10 @@
#define SOL_PROLOGUE_I_ 1 #define SOL_PROLOGUE_I_ 1
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_) #if SOL_IS_ON(SOL_BUILD_CXX_MODE)
#define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ ) #define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ )
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG)
#define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ )
#else #else
#include <type_traits> #include <type_traits>

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -75,7 +75,7 @@ namespace sol {
meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)), m_error_handler(get_default_handler(r.lua_state())) { basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)), m_error_handler(get_default_handler(r.lua_state())) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
if (!is_function<meta::unqualified_t<T>>::value) { if (!is_function<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
@ -133,7 +133,7 @@ namespace sol {
} }
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(lua_State* L_, T&& r, handler_t eh) : base_t(L_, std::forward<T>(r)), m_error_handler(std::move(eh)) { basic_protected_function(lua_State* L_, T&& r, handler_t eh) : base_t(L_, std::forward<T>(r)), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_protected_function>(lua_state(), -1, handler); stack::check<basic_protected_function>(lua_state(), -1, handler);
@ -146,7 +146,7 @@ namespace sol {
basic_protected_function(lua_State* L_, int index_ = -1) : basic_protected_function(L_, index_, get_default_handler(L_)) { basic_protected_function(lua_State* L_, int index_ = -1) : basic_protected_function(L_, index_, get_default_handler(L_)) {
} }
basic_protected_function(lua_State* L_, int index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { basic_protected_function(lua_State* L_, int index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_protected_function>(L_, index_, handler); stack::check<basic_protected_function>(L_, index_, handler);
#endif // Safety #endif // Safety
@ -154,7 +154,7 @@ namespace sol {
basic_protected_function(lua_State* L_, absolute_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { basic_protected_function(lua_State* L_, absolute_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
} }
basic_protected_function(lua_State* L_, absolute_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { basic_protected_function(lua_State* L_, absolute_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_protected_function>(L_, index_, handler); stack::check<basic_protected_function>(L_, index_, handler);
#endif // Safety #endif // Safety
@ -162,7 +162,7 @@ namespace sol {
basic_protected_function(lua_State* L_, raw_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { basic_protected_function(lua_State* L_, raw_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
} }
basic_protected_function(lua_State* L_, raw_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { basic_protected_function(lua_State* L_, raw_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_protected_function>(L_, index_, handler); stack::check<basic_protected_function>(L_, index_, handler);
#endif // Safety #endif // Safety
@ -170,7 +170,7 @@ namespace sol {
basic_protected_function(lua_State* L_, ref_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { basic_protected_function(lua_State* L_, ref_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
} }
basic_protected_function(lua_State* L_, ref_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { basic_protected_function(lua_State* L_, ref_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) #if SOL_IS_ON(SOL_SAFE_REFERENCES)
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler {}; constructor_handler handler {};
stack::check<basic_protected_function>(lua_state(), -1, handler); stack::check<basic_protected_function>(lua_state(), -1, handler);
@ -339,14 +339,14 @@ namespace sol {
int firstreturn = 1; int firstreturn = 1;
int returncount = 0; int returncount = 0;
call_status code = call_status::ok; call_status code = call_status::ok;
#if SOL_IS_ON(SOL_EXCEPTIONS_I_) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) #if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS)
try { try {
#endif // No Exceptions #endif // No Exceptions
firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid() && !is_stack_handler_v))); firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid() && !is_stack_handler_v)));
code = luacall(n, LUA_MULTRET, h); code = luacall(n, LUA_MULTRET, h);
poststacksize = lua_gettop(lua_state()) - static_cast<int>(h.valid() && !is_stack_handler_v); poststacksize = lua_gettop(lua_state()) - static_cast<int>(h.valid() && !is_stack_handler_v);
returncount = poststacksize - (firstreturn - 1); returncount = poststacksize - (firstreturn - 1);
#if SOL_IS_ON(SOL_EXCEPTIONS_I_) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) #if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS)
} }
// Handle C++ errors thrown from C++ functions bound inside of lua // Handle C++ errors thrown from C++ functions bound inside of lua
catch (const char* error) { catch (const char* error) {
@ -364,7 +364,7 @@ namespace sol {
firstreturn = lua_gettop(lua_state()); firstreturn = lua_gettop(lua_state());
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
} }
#if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL_I_) #if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL)
// LuaJIT cannot have the catchall when the safe propagation is on // LuaJIT cannot have the catchall when the safe propagation is on
// but LuaJIT will swallow all C++ errors // but LuaJIT will swallow all C++ errors
// if we don't at least catch std::exception ones // if we don't at least catch std::exception ones

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -54,9 +54,9 @@ namespace sol {
typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
protected_function_result() noexcept = default; protected_function_result() noexcept : protected_function_result(nullptr) {}
protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept
: L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { : L( Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) {
} }
// We do not want anyone to copy these around willy-nilly // We do not want anyone to copy these around willy-nilly
@ -99,6 +99,13 @@ namespace sol {
return status() == call_status::ok || status() == call_status::yielded; return status() == call_status::ok || status() == call_status::yielded;
} }
#if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic push
#if !SOL_IS_ON(SOL_COMPILER_CLANG)
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#endif
template <typename T> template <typename T>
decltype(auto) get(int index_offset = 0) const { decltype(auto) get(int index_offset = 0) const {
using UT = meta::unqualified_t<T>; using UT = meta::unqualified_t<T>;
@ -109,7 +116,7 @@ namespace sol {
if (valid()) { if (valid()) {
return UT(); return UT();
} }
return UT(error(detail::direct_error, stack::get<std::string>(L, target))); return UT(stack::stack_detail::get_error(L, target));
} }
else { else {
if (!valid()) { if (!valid()) {
@ -120,16 +127,16 @@ namespace sol {
} }
else { else {
if constexpr (std::is_same_v<T, error>) { if constexpr (std::is_same_v<T, error>) {
#if SOL_IS_ON(SOL_SAFE_PROXIES_I_) #if SOL_IS_ON(SOL_SAFE_PROXIES)
if (valid()) { if (valid()) {
type t = type_of(L, target); type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)"); type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)");
} }
#endif // Check Argument Safety #endif // Check Argument Safety
return error(detail::direct_error, stack::get<std::string>(L, target)); return stack::stack_detail::get_error(L, target);
} }
else { else {
#if SOL_IS_ON(SOL_SAFE_PROXIES_I_) #if SOL_IS_ON(SOL_SAFE_PROXIES)
if (!valid()) { if (!valid()) {
type t = type_of(L, target); type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)"); type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)");
@ -140,6 +147,10 @@ namespace sol {
} }
} }
#if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif
type get_type(int index_offset = 0) const noexcept { type get_type(int index_offset = 0) const noexcept {
return type_of(L, index + static_cast<int>(index_offset)); return type_of(L, index + static_cast<int>(index_offset));
} }
@ -216,7 +227,7 @@ namespace sol {
template <> template <>
struct unqualified_pusher<protected_function_result> { struct unqualified_pusher<protected_function_result> {
static int push(lua_State* L, const protected_function_result& pfr) { static int push(lua_State* L, const protected_function_result& pfr) {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, static_cast<int>(pfr.pop_count()), detail::not_enough_stack_space_generic); luaL_checkstack(L, static_cast<int>(pfr.pop_count()), detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
int p = 0; int p = 0;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -92,7 +92,7 @@ namespace sol { namespace detail {
return; return;
} }
if (!ref.valid()) { if (!ref.valid()) {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushnil(L); lua_pushnil(L);

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -289,7 +289,7 @@ namespace sol {
} }
stateless_reference(lua_State* L_, global_tag_t) noexcept { stateless_reference(lua_State* L_, global_tag_t) noexcept {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushglobaltable(L_); lua_pushglobaltable(L_);
@ -352,7 +352,7 @@ namespace sol {
} }
stateless_reference(lua_State* L_, int index = -1) noexcept { stateless_reference(lua_State* L_, int index = -1) noexcept {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushvalue(L_, index); lua_pushvalue(L_, index);
@ -383,7 +383,7 @@ namespace sol {
} }
int push(lua_State* L_) const noexcept { int push(lua_State* L_) const noexcept {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_rawgeti(L_, LUA_REGISTRYINDEX, ref); lua_rawgeti(L_, LUA_REGISTRYINDEX, ref);
@ -407,7 +407,7 @@ namespace sol {
void reset(lua_State* L_, int index_) noexcept { void reset(lua_State* L_, int index_) noexcept {
reset(L_); reset(L_);
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushvalue(L_, index_); lua_pushvalue(L_, index_);
@ -616,7 +616,7 @@ namespace sol {
} }
basic_reference(lua_State* L_, int index = -1) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { basic_reference(lua_State* L_, int index = -1) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) {
// use L_ to stick with that state's execution stack // use L_ to stick with that state's execution stack
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushvalue(L_, index); lua_pushvalue(L_, index);
@ -693,7 +693,7 @@ namespace sol {
} }
int push(lua_State* L_) const noexcept { int push(lua_State* L_) const noexcept {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value");
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
if (lua_state() == nullptr) { if (lua_state() == nullptr) {
@ -828,6 +828,8 @@ namespace sol {
stateless_reference_equals(lua_State* L_) noexcept : stateless_stack_reference_equals(L_) { stateless_reference_equals(lua_State* L_) noexcept : stateless_stack_reference_equals(L_) {
} }
using stateless_stack_reference_equals::operator();
bool operator()(const lua_nil_t& lhs, const stateless_reference& rhs) const noexcept { bool operator()(const lua_nil_t& lhs, const stateless_reference& rhs) const noexcept {
return rhs.equals(lua_state(), lhs); return rhs.equals(lua_state(), lhs);
} }
@ -839,6 +841,14 @@ namespace sol {
bool operator()(const stateless_reference& lhs, const stateless_reference& rhs) const noexcept { bool operator()(const stateless_reference& lhs, const stateless_reference& rhs) const noexcept {
return lhs.equals(lua_state(), rhs); return lhs.equals(lua_state(), rhs);
} }
bool operator()(const stateless_stack_reference& lhs, const stateless_reference& rhs) const noexcept {
return rhs.equals(lua_state(), lhs);
}
bool operator()(const stateless_reference& lhs, const stateless_stack_reference& rhs) const noexcept {
return lhs.equals(lua_state(), rhs);
}
}; };
struct reference_equals : public stack_reference_equals { struct reference_equals : public stack_reference_equals {
@ -878,6 +888,8 @@ namespace sol {
stateless_reference_hash(lua_State* L_) noexcept : stateless_stack_reference_hash(L_) { stateless_reference_hash(lua_State* L_) noexcept : stateless_stack_reference_hash(L_) {
} }
using stateless_stack_reference_hash::operator();
result_type operator()(const stateless_reference& lhs) const noexcept { result_type operator()(const stateless_reference& lhs) const noexcept {
std::hash<const void*> h; std::hash<const void*> h;
return h(lhs.pointer(lua_state())); return h(lhs.pointer(lua_state()));

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -24,23 +24,23 @@
#include <sol/version.hpp> #include <sol/version.hpp>
#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE_I_) #if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE)
#ifdef check #ifdef check
#pragma push_macro("check") #pragma push_macro("check")
#undef check #undef check
#endif #endif
#endif // Unreal Engine 4 Bullshit #endif // Unreal Engine 4 Bullshit
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) #if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#if __GNUC__ > 6 #if __GNUC__ > 6
#pragma GCC diagnostic ignored "-Wnoexcept-type" #pragma GCC diagnostic ignored "-Wnoexcept-type"
#endif #endif
#elif SOL_IS_ON(SOL_COMPILER_CLANG_I_) #elif SOL_IS_ON(SOL_COMPILER_CLANG)
// we'll just let this alone for now // we'll just let this alone for now
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) #elif SOL_IS_ON(SOL_COMPILER_VCXX)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS #pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS
#endif // clang++ vs. g++ vs. VC++ #endif // clang++ vs. g++ vs. VC++
@ -65,13 +65,15 @@
#include <sol/variadic_results.hpp> #include <sol/variadic_results.hpp>
#include <sol/lua_value.hpp> #include <sol/lua_value.hpp>
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) #if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) #elif SOL_IS_ON(SOL_COMPILER_CLANG)
// we'll just let this alone for now
#elif SOL_IS_ON(SOL_COMPILER_VCXX)
#pragma warning(pop) #pragma warning(pop)
#endif // g++ #endif // g++
#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE_I_) #if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE)
#undef check #undef check
#pragma pop_macro("check") #pragma pop_macro("check")
#endif // Unreal Engine 4 Bullshit #endif // Unreal Engine 4 Bullshit

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -34,6 +34,8 @@
#include <sol/stack_pop.hpp> #include <sol/stack_pop.hpp>
#include <sol/stack_field.hpp> #include <sol/stack_field.hpp>
#include <sol/stack_probe.hpp> #include <sol/stack_probe.hpp>
#include <sol/error.hpp>
#include <sol/assert.hpp>
#include <cstring> #include <cstring>
#include <array> #include <array>
@ -149,7 +151,10 @@ namespace sol {
template <bool checked, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename Handler, typename Fx, typename... FxArgs> template <bool checked, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename Handler, typename Fx, typename... FxArgs>
static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L_, int start_index_, Handler&& handler_, static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L_, int start_index_, Handler&& handler_,
record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) { record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) {
#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS_I_) #if 0 && SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS)
// NOTE: THIS IS TERMPORARILY TURNED OFF BECAUSE IT IMPACTS ACTUAL SEMANTICS W.R.T. THINGS LIKE LUAJIT,
// SO IT MUST REMAIN OFF UNTIL WE CAN ESTABLISH SIMILAR BEHAVIOR IN MODES WHERE `checked == false`!
// We can save performance/time by letting errors unwind produced arguments // We can save performance/time by letting errors unwind produced arguments
// rather than checking everything once, and then potentially re-doing work // rather than checking everything once, and then potentially re-doing work
if constexpr (checked) { if constexpr (checked) {
@ -186,7 +191,7 @@ namespace sol {
"a reference and std::move it manually if this was your intention."); "a reference and std::move it manually if this was your intention.");
argument_handler<types<R, Args...>> handler {}; argument_handler<types<R, Args...>> handler {};
record tracking {}; record tracking {};
#if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS)
if constexpr (checkargs) { if constexpr (checkargs) {
multi_check<Args...>(L_, start_index_, handler); multi_check<Args...>(L_, start_index_, handler);
} }
@ -200,11 +205,21 @@ namespace sol {
argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...); argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
} }
} }
template <typename T>
void raw_table_set(lua_State* L, T&& arg, int tableindex = -2) {
int push_count = push(L, std::forward<T>(arg));
SOL_ASSERT(push_count == 1);
std::size_t unique_index = static_cast<std::size_t>(luaL_len(L, tableindex) + 1u);
lua_rawseti(L, tableindex, static_cast<int>(unique_index));
}
} // namespace stack_detail } // namespace stack_detail
template <typename T> template <typename T>
int set_ref(lua_State* L, T&& arg, int tableindex = -2) { int set_ref(lua_State* L, T&& arg, int tableindex = -2) {
push(L, std::forward<T>(arg)); int push_count = push(L, std::forward<T>(arg));
SOL_ASSERT(push_count == 1);
return luaL_ref(L, tableindex); return luaL_ref(L, tableindex);
} }
@ -319,11 +334,11 @@ namespace sol {
} }
inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_) #if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE)
if (L == nullptr) { if (L == nullptr) {
return; return;
} }
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
lua_pushlightuserdata(L, (void*)handler); lua_pushlightuserdata(L, (void*)handler);
@ -336,7 +351,7 @@ namespace sol {
} }
inline void luajit_exception_off(lua_State* L) { inline void luajit_exception_off(lua_State* L) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_) #if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE)
if (L == nullptr) { if (L == nullptr) {
return; return;
} }
@ -345,6 +360,24 @@ namespace sol {
(void)L; (void)L;
#endif #endif
} }
namespace stack_detail {
inline error get_error(lua_State* L, int target) {
auto maybe_exc = stack::check_get<error&>(L, target);
if (maybe_exc.has_value()) {
return maybe_exc.value();
}
return error(detail::direct_error, stack::get<std::string>(L, target));
}
inline detail::error_exception get_error_exception(lua_State* L, int target) {
auto maybe_exc = stack::check_get<detail::error_exception&>(L, target);
if (maybe_exc.has_value()) {
return maybe_exc.value();
}
return detail::error_exception(detail::direct_error, stack::get<std::string>(L, target));
}
}
} // namespace stack } // namespace stack
} // namespace sol } // namespace sol

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -84,7 +84,7 @@ namespace sol { namespace stack { namespace stack_detail {
pushed += 1; pushed += 1;
} }
int metatable_exists = lua_getmetatable(L_, 1); int metatable_exists = lua_getmetatable(L_, 1);
sol_c_assert(metatable_exists == 1); SOL_ASSERT(metatable_exists == 1);
const auto& index_key = to_string(sol::meta_function::index); const auto& index_key = to_string(sol::meta_function::index);
lua_getfield(L_, lua_gettop(L_), index_key.c_str()); lua_getfield(L_, lua_gettop(L_), index_key.c_str());
lua_remove(L_, -2); lua_remove(L_, -2);

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -30,6 +30,13 @@
namespace sol { namespace stack { namespace sol { namespace stack {
#if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic push
#if !SOL_IS_ON(SOL_COMPILER_CLANG)
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#endif
namespace stack_detail { namespace stack_detail {
template <typename OptionalType, typename T, typename Handler> template <typename OptionalType, typename T, typename Handler>
OptionalType get_optional(lua_State* L, int index, Handler&& handler, record& tracking) { OptionalType get_optional(lua_State* L, int index, Handler&& handler, record& tracking) {
@ -70,9 +77,8 @@ namespace sol { namespace stack {
actual* mem = static_cast<actual*>(memory); actual* mem = static_cast<actual*>(memory);
return static_cast<actual>(*mem); return static_cast<actual>(*mem);
} }
actual r {};
if constexpr (!derive<element>::value) { if constexpr (!derive<element>::value) {
return {}; return OptionalType();
} }
else { else {
memory = detail::align_usertype_unique_tag<true, false>(memory); memory = detail::align_usertype_unique_tag<true, false>(memory);
@ -80,6 +86,7 @@ namespace sol { namespace stack {
memory = detail::align_usertype_unique<actual, true, false>(memory); memory = detail::align_usertype_unique<actual, true, false>(memory);
string_view ti = usertype_traits<element>::qualified_name(); string_view ti = usertype_traits<element>::qualified_name();
int cast_operation; int cast_operation;
actual r {};
if constexpr (is_actual_type_rebindable_for_v<Tu>) { if constexpr (is_actual_type_rebindable_for_v<Tu>) {
using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>; using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>;
string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
@ -103,19 +110,23 @@ namespace sol { namespace stack {
default: default:
break; break;
} }
return {}; return OptionalType();
} }
} }
else { else {
if (!check<T>(L, index, std::forward<Handler>(handler))) { if (!check<T>(L, index, std::forward<Handler>(handler))) {
tracking.use(static_cast<int>(!lua_isnone(L, index))); tracking.use(static_cast<int>(!lua_isnone(L, index)));
return {}; return OptionalType();
} }
return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking)); return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking));
} }
} }
} // namespace stack_detail } // namespace stack_detail
#if SOL_IS_ON(SOL_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif
template <typename T, typename> template <typename T, typename>
struct qualified_check_getter { struct qualified_check_getter {
typedef decltype(stack_detail::unchecked_get<T>(nullptr, -1, std::declval<record&>())) R; typedef decltype(stack_detail::unchecked_get<T>(nullptr, -1, std::declval<record&>())) R;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -32,7 +32,7 @@
#include <cstdlib> #include <cstdlib>
#include <cmath> #include <cmath>
#include <optional> #include <optional>
#if SOL_IS_ON(SOL_STD_VARIANT_I_) #if SOL_IS_ON(SOL_STD_VARIANT)
#include <variant> #include <variant>
#endif // variant shenanigans (thanks, Mac OSX) #endif // variant shenanigans (thanks, Mac OSX)
@ -76,7 +76,7 @@ namespace sol { namespace stack {
int isnum = 0; int isnum = 0;
const lua_Number value = lua_tonumberx(L, index, &isnum); const lua_Number value = lua_tonumberx(L, index, &isnum);
if (isnum != 0) { if (isnum != 0) {
#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_) #if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS)
const auto integer_value = llround(value); const auto integer_value = llround(value);
if (static_cast<lua_Number>(integer_value) == value) { if (static_cast<lua_Number>(integer_value) == value) {
tracking.use(1); tracking.use(1);
@ -139,7 +139,7 @@ namespace sol { namespace stack {
} }
}; };
#if SOL_IS_ON(SOL_STD_VARIANT_I_) #if SOL_IS_ON(SOL_STD_VARIANT)
template <typename... Tn, typename C> template <typename... Tn, typename C>
struct unqualified_check_getter<std::variant<Tn...>, C> { struct unqualified_check_getter<std::variant<Tn...>, C> {
typedef std::variant<Tn...> V; typedef std::variant<Tn...> V;

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -28,7 +28,7 @@
namespace sol { namespace stack { namespace sol { namespace stack {
template <typename X, type expected, typename> template <typename X, typename>
struct qualified_checker { struct qualified_checker {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -32,7 +32,7 @@
#include <utility> #include <utility>
#include <cmath> #include <cmath>
#include <optional> #include <optional>
#if SOL_IS_ON(SOL_STD_VARIANT_I_) #if SOL_IS_ON(SOL_STD_VARIANT)
#include <variant> #include <variant>
#endif // variant shenanigans #endif // variant shenanigans
@ -116,7 +116,7 @@ namespace sol { namespace stack {
} }
else if constexpr (meta::any_same_v<T, else if constexpr (meta::any_same_v<T,
char char
#if SOL_IS_ON(SOL_CHAR8_T_I_) #if SOL_IS_ON(SOL_CHAR8_T)
, ,
char8_t char8_t
#endif #endif
@ -129,7 +129,7 @@ namespace sol { namespace stack {
tracking.use(1); tracking.use(1);
#if SOL_LUA_VERSION_I_ >= 503 #if SOL_LUA_VERSION_I_ >= 503
// Lua 5.3 and greater checks for numeric precision // Lua 5.3 and greater checks for numeric precision
#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_) #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS)
// imprecise, sloppy conversions // imprecise, sloppy conversions
int isnum = 0; int isnum = 0;
lua_tointegerx(L_, index, &isnum); lua_tointegerx(L_, index, &isnum);
@ -138,7 +138,7 @@ namespace sol { namespace stack {
// expected type, actual type // expected type, actual type
handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string_integral); handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string_integral);
} }
#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_) #elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS)
// this check is precise, do not convert // this check is precise, do not convert
if (lua_isinteger(L_, index) == 1) { if (lua_isinteger(L_, index) == 1) {
return true; return true;
@ -160,7 +160,7 @@ namespace sol { namespace stack {
return success; return success;
#else #else
// Lua 5.2 and below checks // Lua 5.2 and below checks
#if SOL_IS_OFF(SOL_STRINGS_ARE_NUMBERS_I_) #if SOL_IS_OFF(SOL_STRINGS_ARE_NUMBERS)
// must pre-check, because it will convert // must pre-check, because it will convert
type t = type_of(L_, index); type t = type_of(L_, index);
if (t != type::number) { if (t != type::number) {
@ -170,7 +170,7 @@ namespace sol { namespace stack {
} }
#endif // Do not allow strings to be numbers #endif // Do not allow strings to be numbers
#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_) #if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS)
int isnum = 0; int isnum = 0;
const lua_Number v = lua_tonumberx(L_, index, &isnum); const lua_Number v = lua_tonumberx(L_, index, &isnum);
const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v; const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v;
@ -179,9 +179,9 @@ namespace sol { namespace stack {
#endif // Safe numerics and number precision checking #endif // Safe numerics and number precision checking
if (!success) { if (!success) {
// Use defines to provide a better error message! // Use defines to provide a better error message!
#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_) #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS)
handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string); handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string);
#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_) #elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS)
handler(L_, index, type::number, t, detail::not_a_number_or_number_string); handler(L_, index, type::number, t, detail::not_a_number_or_number_string);
#else #else
handler(L_, index, type::number, t, detail::not_a_number); handler(L_, index, type::number, t, detail::not_a_number);
@ -192,7 +192,7 @@ namespace sol { namespace stack {
} }
else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) { else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
tracking.use(1); tracking.use(1);
#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_) #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS)
bool success = lua_isnumber(L_, index) == 1; bool success = lua_isnumber(L_, index) == 1;
if (!success) { if (!success) {
// expected type, actual type // expected type, actual type
@ -218,6 +218,7 @@ namespace sol { namespace stack {
} }
else if constexpr (is_unique_usertype_v<T>) { else if constexpr (is_unique_usertype_v<T>) {
using element = unique_usertype_element_t<T>; using element = unique_usertype_element_t<T>;
using element_no_cv = meta::unqualified_t<element>;
using actual = unique_usertype_actual_t<T>; using actual = unique_usertype_actual_t<T>;
const type indextype = type_of(L_, index); const type indextype = type_of(L_, index);
tracking.use(1); tracking.use(1);
@ -229,7 +230,7 @@ namespace sol { namespace stack {
return true; return true;
} }
int metatableindex = lua_gettop(L_); int metatableindex = lua_gettop(L_);
if (stack_detail::check_metatable<d::u<element>>(L_, metatableindex)) { if (stack_detail::check_metatable<d::u<element_no_cv>>(L_, metatableindex)) {
void* memory = lua_touserdata(L_, index); void* memory = lua_touserdata(L_, index);
memory = detail::align_usertype_unique_destructor(memory); memory = detail::align_usertype_unique_destructor(memory);
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
@ -371,7 +372,7 @@ namespace sol { namespace stack {
} }
return stack::unqualified_check<ValueType>(L_, index, &no_panic, tracking); return stack::unqualified_check<ValueType>(L_, index, &no_panic, tracking);
} }
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_) #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) { else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking); return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking);
} }
@ -388,9 +389,7 @@ namespace sol { namespace stack {
return success; return success;
} }
else if constexpr (meta::is_specialization_of_v<T, user>) { else if constexpr (meta::is_specialization_of_v<T, user>) {
unqualified_checker<lightuserdata_value, type::userdata> c; return stack::unqualified_check<detail::as_value_tag<lightuserdata_value>>(L_, index, std::forward<Handler>(handler), tracking);
(void)c;
return c.check(L_, index, std::forward<Handler>(handler), tracking);
} }
else { else {
if constexpr (std::is_pointer_v<T>) { if constexpr (std::is_pointer_v<T>) {
@ -508,13 +507,13 @@ namespace sol { namespace stack {
return true; return true;
} }
else { else {
#if SOL_IS_ON(SOL_USE_INTEROP_I_) #if SOL_IS_ON(SOL_USE_INTEROP)
if (stack_detail::interop_check<U>(L_, index, indextype, handler, tracking)) { if (stack_detail::interop_check<U>(L_, index, indextype, handler, tracking)) {
return true; return true;
} }
#endif // interop extensibility #endif // interop extensibility
tracking.use(1); tracking.use(1);
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_) #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
if (lua_iscfunction(L_, index) != 0) { if (lua_iscfunction(L_, index) != 0) {
// a potential match... // a potential match...
return true; return true;
@ -539,7 +538,7 @@ namespace sol { namespace stack {
bool success = false; bool success = false;
bool has_derived = derive<T>::value || weak_derive<T>::value; bool has_derived = derive<T>::value || weak_derive<T>::value;
if (has_derived) { if (has_derived) {
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(L_, 1, detail::not_enough_stack_space_string); luaL_checkstack(L_, 1, detail::not_enough_stack_space_string);
#endif // make sure stack doesn't overflow #endif // make sure stack doesn't overflow
auto pn = stack::pop_n(L_, 1); auto pn = stack::pop_n(L_, 1);
@ -579,6 +578,104 @@ namespace sol { namespace stack {
} }
}; };
template <typename T, std::size_t N, type expect>
struct unqualified_checker<exhaustive_until<T, N>, expect> {
template <typename K, typename V, typename Handler>
static bool check_two(types<K, V>, lua_State* arg_L, int relindex, type, Handler&& handler, record& tracking) {
tracking.use(1);
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(arg_L, 3, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow
int index = lua_absindex(arg_L, relindex);
lua_pushnil(arg_L);
while (lua_next(arg_L, index) != 0) {
const bool is_key_okay = stack::check<K>(arg_L, -2, std::forward<Handler>(handler), tracking);
if (!is_key_okay) {
lua_pop(arg_L, 2);
return false;
}
const bool is_value_okay = stack::check<V>(arg_L, -1, std::forward<Handler>(handler), tracking);
if (!is_value_okay) {
lua_pop(arg_L, 2);
return false;
}
lua_pop(arg_L, 1);
}
return true;
}
template <typename V, typename Handler>
static bool check_one(types<V>, lua_State* arg_L, int relindex, type, Handler&& handler, record& tracking) {
tracking.use(1);
size_t index = lua_absindex(arg_L, relindex);
// Zzzz slower but necessary thanks to the lower version API and missing functions qq
std::size_t idx = 0;
int vi = 0;
for (lua_Integer i = 0;; (void)(i += lua_size<V>::value), lua_pop(arg_L, static_cast<int>(vi))) {
vi = 0;
if (idx >= N) {
return true;
}
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
luaL_checkstack(arg_L, 2, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow
bool isnil = false;
for (; vi < static_cast<int>(lua_size<V>::value); ++vi) {
lua_pushinteger(arg_L, i);
lua_gettable(arg_L, static_cast<int>(index));
type vt = type_of(arg_L, -1);
isnil = vt == type::lua_nil;
if (isnil) {
if (i == 0) {
vi += 1;
goto loop_continue;
}
lua_pop(arg_L, static_cast<int>(vi + 1));
return true;
}
}
if (!stack::check<V>(arg_L, -lua_size<V>::value, std::forward<Handler>(handler), tracking)) {
lua_pop(arg_L, lua_size<V>::value);
return false;
}
++idx;
loop_continue:;
}
}
template <typename Handler>
static bool check(lua_State* arg_L, int index, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (is_container_v<Tu>) {
if constexpr (meta::is_associative<Tu>::value) {
typedef typename Tu::value_type P;
typedef typename P::first_type K;
typedef typename P::second_type V;
return check_two(types<K, V>(), arg_L, index, expect, std::forward<Handler>(handler), tracking);
}
else {
typedef typename Tu::value_type V;
return check_one(types<V>(), arg_L, index, expect, std::forward<Handler>(handler), tracking);
}
}
else {
unqualified_checker<Tu, expect> c {};
return c.check(arg_L, index, std::forward<Handler>(handler), tracking);
}
}
};
template <typename T, type expect>
struct unqualified_checker<non_exhaustive<T>, expect> {
template <typename Handler>
static bool check(lua_State* arg_L, int index, Handler&& handler, record& tracking) {
return stack::check<T>(arg_L, index, std::forward<Handler>(handler), tracking);
}
};
template <typename... Args> template <typename... Args>
struct unqualified_checker<std::tuple<Args...>, type::poly> { struct unqualified_checker<std::tuple<Args...>, type::poly> {
template <typename Handler> template <typename Handler>
@ -595,7 +692,7 @@ namespace sol { namespace stack {
} }
}; };
#if SOL_IS_ON(SOL_STD_VARIANT_I_) #if SOL_IS_ON(SOL_STD_VARIANT)
template <typename... Tn> template <typename... Tn>
struct unqualified_checker<std::variant<Tn...>, type::poly> { struct unqualified_checker<std::variant<Tn...>, type::poly> {

View file

@ -2,7 +2,7 @@
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of // Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in // this software and associated documentation files (the "Software"), to deal in
@ -127,7 +127,7 @@ namespace sol {
inline void* align_usertype_pointer(void* ptr) { inline void* align_usertype_pointer(void* ptr) {
using use_align = std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<void*>::value > 1) (std::alignment_of<void*>::value > 1)
@ -143,7 +143,7 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
void* align_usertype_unique_destructor(void* ptr) { void* align_usertype_unique_destructor(void* ptr) {
using use_align = std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<unique_destructor>::value > 1) (std::alignment_of<unique_destructor>::value > 1)
@ -165,7 +165,7 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
void* align_usertype_unique_tag(void* ptr) { void* align_usertype_unique_tag(void* ptr) {
using use_align = std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<unique_tag>::value > 1) (std::alignment_of<unique_tag>::value > 1)
@ -187,7 +187,7 @@ namespace sol {
template <typename T, bool pre_aligned = false, bool pre_shifted = false> template <typename T, bool pre_aligned = false, bool pre_shifted = false>
void* align_usertype_unique(void* ptr) { void* align_usertype_unique(void* ptr) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of_v<T> > 1) (std::alignment_of_v<T> > 1)
@ -210,7 +210,7 @@ namespace sol {
template <typename T> template <typename T>
void* align_user(void* ptr) { void* align_user(void* ptr) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of_v<T> > 1) (std::alignment_of_v<T> > 1)
@ -227,7 +227,7 @@ namespace sol {
template <typename T> template <typename T>
T** usertype_allocate_pointer(lua_State* L) { T** usertype_allocate_pointer(lua_State* L) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<T*>::value > 1) (std::alignment_of<T*>::value > 1)
@ -311,7 +311,7 @@ namespace sol {
template <typename T> template <typename T>
T* usertype_allocate(lua_State* L) { T* usertype_allocate(lua_State* L) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1) (std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
@ -352,7 +352,7 @@ namespace sol {
template <typename T, typename Real> template <typename T, typename Real>
Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) { Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1 (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1
@ -370,10 +370,10 @@ namespace sol {
constexpr std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>(); constexpr std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>();
void* pointer_adjusted; void* pointer_adjusted = nullptr;
void* dx_adjusted; void* dx_adjusted = nullptr;
void* id_adjusted; void* id_adjusted = nullptr;
void* data_adjusted; void* data_adjusted = nullptr;
bool result = attempt_alloc_unique(L, bool result = attempt_alloc_unique(L,
std::alignment_of_v<T*>, std::alignment_of_v<T*>,
sizeof(T*), sizeof(T*),
@ -406,7 +406,7 @@ namespace sol {
template <typename T> template <typename T>
T* user_allocate(lua_State* L) { T* user_allocate(lua_State* L) {
typedef std::integral_constant<bool, typedef std::integral_constant<bool,
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_) #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
false false
#else #else
(std::alignment_of_v<T> > 1) (std::alignment_of_v<T> > 1)
@ -571,7 +571,7 @@ namespace sol {
template <typename T, type t, typename = void> template <typename T, type t, typename = void>
struct unqualified_checker; struct unqualified_checker;
template <typename T, type t, typename = void> template <typename T, typename = void>
struct qualified_checker; struct qualified_checker;
template <typename T, typename = void> template <typename T, typename = void>
@ -709,7 +709,6 @@ namespace sol {
} }
else { else {
unqualified_getter<Tu> g {}; unqualified_getter<Tu> g {};
(void)g;
return g.get(L, index, tracking); return g.get(L, index, tracking);
} }
} }
@ -721,7 +720,6 @@ namespace sol {
} }
else { else {
qualified_getter<T> g {}; qualified_getter<T> g {};
(void)g;
return g.get(L, index, tracking); return g.get(L, index, tracking);
} }
} }
@ -877,7 +875,6 @@ namespace sol {
} }
else { else {
unqualified_pusher<Tu> p {}; unqualified_pusher<Tu> p {};
(void)p;
return p.push(L, std::forward<T>(t), std::forward<Args>(args)...); return p.push(L, std::forward<T>(t), std::forward<Args>(args)...);
} }
} }
@ -897,7 +894,6 @@ namespace sol {
} }
else { else {
unqualified_pusher<Tu> p {}; unqualified_pusher<Tu> p {};
(void)p;
return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
} }
} }
@ -928,7 +924,7 @@ namespace sol {
using use_reference_tag = using use_reference_tag =
meta::all< meta::all<
meta::neg<is_value_semantic_for_function<T>> meta::neg<is_value_semantic_for_function<T>>
#if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_) #if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS)
, std::is_lvalue_reference<T>, , std::is_lvalue_reference<T>,
meta::neg<std::is_const<std::remove_reference_t<T>>>, meta::neg<std::is_const<std::remove_reference_t<T>>>,
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
@ -983,9 +979,7 @@ namespace sol {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking); return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
} }
else { else {
unqualified_checker<Tu, lua_type_of_v<Tu>> c; unqualified_checker<Tu, lua_type_of_v<Tu>> c{};
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking); return c.check(L, index, std::forward<Handler>(handler), tracking);
} }
} }
@ -1008,10 +1002,7 @@ namespace sol {
return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking); return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking);
} }
else { else {
using Tu = meta::unqualified_t<T>; qualified_checker<T> c{};
qualified_checker<T, lua_type_of_v<Tu>> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking); return c.check(L, index, std::forward<Handler>(handler), tracking);
} }
} }
@ -1065,7 +1056,6 @@ namespace sol {
} }
else { else {
unqualified_check_getter<Tu> cg {}; unqualified_check_getter<Tu> cg {};
(void)cg;
return cg.get(L, index, std::forward<Handler>(handler), tracking); return cg.get(L, index, std::forward<Handler>(handler), tracking);
} }
} }
@ -1089,7 +1079,6 @@ namespace sol {
} }
else { else {
qualified_check_getter<T> cg {}; qualified_check_getter<T> cg {};
(void)cg;
return cg.get(L, index, std::forward<Handler>(handler), tracking); return cg.get(L, index, std::forward<Handler>(handler), tracking);
} }
} }
@ -1145,7 +1134,7 @@ namespace sol {
template <typename T> template <typename T>
auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) { auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
#if SOL_IS_ON(SOL_SAFE_GETTER_I_) #if SOL_IS_ON(SOL_SAFE_GETTER)
static constexpr bool is_op = meta::is_optional_v<T>; static constexpr bool is_op = meta::is_optional_v<T>;
if constexpr (is_op) { if constexpr (is_op) {
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
@ -1170,7 +1159,7 @@ namespace sol {
template <typename T> template <typename T>
auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) { auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
#if SOL_IS_ON(SOL_SAFE_GETTER_I_) #if SOL_IS_ON(SOL_SAFE_GETTER)
static constexpr bool is_op = meta::is_optional_v<T>; static constexpr bool is_op = meta::is_optional_v<T>;
if constexpr (is_op) { if constexpr (is_op) {
return stack_detail::unchecked_get<T>(L, index, tracking); return stack_detail::unchecked_get<T>(L, index, tracking);

Some files were not shown because too many files have changed in this diff Show more