summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/AllocationPool.h4
-rw-r--r--src/Bindings/ManualBindings.cpp12
-rw-r--r--src/BlockArea.cpp18
-rw-r--r--src/BlockArea.h2
-rw-r--r--src/Blocks/ClearMetaOnDrop.h2
-rw-r--r--src/Blocks/MetaRotator.h10
-rw-r--r--src/CheckBasicStyle.lua1
-rw-r--r--src/CraftingRecipes.cpp16
-rw-r--r--src/CraftingRecipes.h6
-rw-r--r--src/Defines.h2
-rw-r--r--src/Entities/Minecart.cpp94
-rw-r--r--src/LinearUpscale.h6
-rw-r--r--src/OSSupport/Queue.h2
-rw-r--r--src/StringUtils.h63
14 files changed, 197 insertions, 41 deletions
diff --git a/src/AllocationPool.h b/src/AllocationPool.h
index 3c9dbe8c9..61431a548 100644
--- a/src/AllocationPool.h
+++ b/src/AllocationPool.h
@@ -3,7 +3,7 @@
#include <memory>
-template<class T>
+template <class T>
class cAllocationPool
{
public:
@@ -34,7 +34,7 @@ public:
/** Allocates memory storing unused elements in a linked list. Keeps at least NumElementsInReserve
elements in the list unless malloc fails so that the program has a reserve to handle OOM.**/
-template<class T, size_t NumElementsInReserve>
+template <class T, size_t NumElementsInReserve>
class cListAllocationPool : public cAllocationPool<T>
{
public:
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index d56246dec..b2c57e52d 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -301,11 +301,11 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
-template<
+template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(const AString &, cItemCallback<Ty2> &)
- >
+>
static int tolua_DoWith(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
@@ -395,7 +395,7 @@ static int tolua_DoWith(lua_State* tolua_S)
-template<
+template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, cItemCallback<Ty2> &)
@@ -485,7 +485,7 @@ static int tolua_DoWithID(lua_State* tolua_S)
-template<
+template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &)
@@ -580,7 +580,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
-template<
+template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &)
@@ -676,7 +676,7 @@ static int tolua_ForEachInChunk(lua_State * tolua_S)
-template<
+template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(cItemCallback<Ty2> &)
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 90f7ca6c9..ba55528b8 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -28,7 +28,7 @@ typedef void (CombinatorFunc)(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLE
// This wild construct allows us to pass a function argument and still have it inlined by the compiler :)
/// Merges two blocktypes and blockmetas of the specified sizes and offsets using the specified combinator function
-template<bool MetasValid, CombinatorFunc Combinator>
+template <bool MetasValid, CombinatorFunc Combinator>
void InternalMergeBlocks(
BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes,
NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas,
@@ -74,7 +74,7 @@ void InternalMergeBlocks(
/// Combinator used for cBlockArea::msOverwrite merging
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
a_DstType = a_SrcType;
@@ -89,7 +89,7 @@ void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLE
/// Combinator used for cBlockArea::msFillAir merging
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
if (a_DstType == E_BLOCK_AIR)
@@ -108,7 +108,7 @@ void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETY
/// Combinator used for cBlockArea::msImprint merging
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
if (a_SrcType != E_BLOCK_AIR)
@@ -127,7 +127,7 @@ void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETY
/// Combinator used for cBlockArea::msLake merging
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
// Sponge is the NOP block
@@ -201,7 +201,7 @@ void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE
/** Combinator used for cBlockArea::msSpongePrint merging */
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
// Sponge overwrites nothing, everything else overwrites anything
@@ -220,7 +220,7 @@ void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBB
/** Combinator used for cBlockArea::msDifference merging */
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
if ((a_DstType == a_SrcType) && (!MetaValid || (a_DstMeta == a_SrcMeta)))
@@ -246,7 +246,7 @@ void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBL
/** Combinator used for cBlockArea::msMask merging */
-template<bool MetaValid>
+template <bool MetaValid>
void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
// If the blocks are the same, keep the dest; otherwise replace with air
@@ -2121,7 +2121,7 @@ void cBlockArea::RelSetData(
-template<bool MetasValid>
+template <bool MetasValid>
void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas)
{
// Block types are compulsory, block metas are voluntary
diff --git a/src/BlockArea.h b/src/BlockArea.h
index a95ba7788..86f7c4f2d 100644
--- a/src/BlockArea.h
+++ b/src/BlockArea.h
@@ -362,7 +362,7 @@ protected:
NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight
);
- template<bool MetasValid>
+ template <bool MetasValid>
void MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas);
// tolua_begin
} ;
diff --git a/src/Blocks/ClearMetaOnDrop.h b/src/Blocks/ClearMetaOnDrop.h
index f2afbc6ea..aa4f23848 100644
--- a/src/Blocks/ClearMetaOnDrop.h
+++ b/src/Blocks/ClearMetaOnDrop.h
@@ -7,7 +7,7 @@
// For example to use in class Foo which should inherit Bar use
// class Foo : public cClearMetaOnDrop<Bar>;
-template<class Base>
+template <class Base>
class cClearMetaOnDrop : public Base
{
public:
diff --git a/src/Blocks/MetaRotator.h b/src/Blocks/MetaRotator.h
index 599aa7ef9..4c268077a 100644
--- a/src/Blocks/MetaRotator.h
+++ b/src/Blocks/MetaRotator.h
@@ -20,7 +20,7 @@ Usage:
Inherit from this class providing your base class as Base, the BitMask for the direction bits in bitmask and the masked value for the directions in North, East, South, West. There is also an aptional parameter AssertIfNotMatched. Set this if it is invalid for a block to exist in any other state.
*/
-template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched = false>
+template <class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched = false>
class cMetaRotator : public Base
{
public:
@@ -41,7 +41,7 @@ public:
-template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+template <class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
@@ -63,7 +63,7 @@ NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatc
-template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+template <class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
@@ -85,7 +85,7 @@ NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatc
-template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+template <class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorXY(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
@@ -102,7 +102,7 @@ NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatc
-template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+template <class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorYZ(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
diff --git a/src/CheckBasicStyle.lua b/src/CheckBasicStyle.lua
index 08f014e33..b244b1fbc 100644
--- a/src/CheckBasicStyle.lua
+++ b/src/CheckBasicStyle.lua
@@ -119,6 +119,7 @@ local g_ViolationPatterns =
{"while%(", "Needs a space after \"while\""},
{"switch%(", "Needs a space after \"switch\""},
{"catch%(", "Needs a space after \"catch\""},
+ {"template<", "Needs a space after \"template\""},
-- No space after keyword's parenthesis:
{"[^%a#]if %( ", "Remove the space after \"(\""},
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index 1a31a6e90..2d80ecaf8 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -83,7 +83,7 @@ cItem & cCraftingGrid::GetItem(int x, int y) const
-void cCraftingGrid::SetItem(int x, int y, ENUM_ITEM_ID a_ItemType, int a_ItemCount, short a_ItemHealth)
+void cCraftingGrid::SetItem(int x, int y, ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemHealth)
{
// Accessible through scripting, must verify parameters:
if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height))
@@ -228,7 +228,7 @@ void cCraftingRecipe::Clear(void)
-void cCraftingRecipe::SetResult(ENUM_ITEM_ID a_ItemType, int a_ItemCount, short a_ItemHealth)
+void cCraftingRecipe::SetResult(ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemHealth)
{
m_Result = cItem(a_ItemType, a_ItemCount, a_ItemHealth);
}
@@ -324,7 +324,11 @@ void cCraftingRecipes::LoadRecipes(void)
return;
}
AString Everything;
- f.ReadRestOfFile(Everything);
+ if (!f.ReadRestOfFile(Everything))
+ {
+ LOGWARNING("Cannot read file \"crafting.txt\", no crafting recipes will be available!");
+ return;
+ }
f.Close();
// Split it into lines, then process each line as a single recipe:
@@ -388,8 +392,7 @@ void cCraftingRecipes::AddRecipeLine(int a_LineNum, const AString & a_RecipeLine
}
if (ResultSplit.size() > 1)
{
- Recipe->m_Result.m_ItemCount = atoi(ResultSplit[1].c_str());
- if (Recipe->m_Result.m_ItemCount == 0)
+ if (!StringToInteger<char>(ResultSplit[1].c_str(), Recipe->m_Result.m_ItemCount))
{
LOGWARNING("crafting.txt: line %d: Cannot parse result count, ignoring the recipe.", a_LineNum);
LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str());
@@ -441,8 +444,7 @@ bool cCraftingRecipes::ParseItem(const AString & a_String, cItem & a_Item)
if (Split.size() > 1)
{
AString Damage = TrimString(Split[1]);
- a_Item.m_ItemDamage = atoi(Damage.c_str());
- if ((a_Item.m_ItemDamage == 0) && (Damage.compare("0") != 0))
+ if (!StringToInteger<short>(Damage.c_str(), a_Item.m_ItemDamage))
{
// Parsing the number failed
return false;
diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h
index 0250d2f68..fe1e15817 100644
--- a/src/CraftingRecipes.h
+++ b/src/CraftingRecipes.h
@@ -33,7 +33,7 @@ public:
int GetWidth (void) const {return m_Width; }
int GetHeight(void) const {return m_Height; }
cItem & GetItem (int x, int y) const;
- void SetItem (int x, int y, ENUM_ITEM_ID a_ItemType, int a_ItemCount, short a_ItemHealth);
+ void SetItem (int x, int y, ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemHealth);
void SetItem (int x, int y, const cItem & a_Item);
void Clear (void);
@@ -72,13 +72,13 @@ public:
int GetIngredientsHeight(void) const {return m_Ingredients.GetHeight(); }
cItem & GetIngredient (int x, int y) const {return m_Ingredients.GetItem(x, y); }
const cItem & GetResult (void) const {return m_Result; }
- void SetResult (ENUM_ITEM_ID a_ItemType, int a_ItemCount, short a_ItemHealth);
+ void SetResult (ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemHealth);
void SetResult (const cItem & a_Item)
{
m_Result = a_Item;
}
- void SetIngredient (int x, int y, ENUM_ITEM_ID a_ItemType, int a_ItemCount, short a_ItemHealth)
+ void SetIngredient (int x, int y, ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemHealth)
{
m_Ingredients.SetItem(x, y, a_ItemType, a_ItemCount, a_ItemHealth);
}
diff --git a/src/Defines.h b/src/Defines.h
index 0981077c4..78c58034e 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -528,7 +528,7 @@ inline float GetSpecialSignf( float a_Val)
-template<class T> inline T Diff(T a_Val1, T a_Val2)
+template <class T> inline T Diff(T a_Val1, T a_Val2)
{
return std::abs(a_Val1 - a_Val2);
}
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index d4eadc5d5..21c58fdba 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -871,11 +871,101 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta)
return true;
}
case E_META_RAIL_CURVED_ZM_XM:
+ case E_META_RAIL_CURVED_ZP_XP:
+ {
+ Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ());
+
+ // Prevent division by small numbers
+ if (abs(Distance.z) < 0.001)
+ {
+ Distance.z = 0.001;
+ }
+
+ /* Check to which side the minecart is to be pushed.
+ Let's consider a z-x-coordinate system where the minecart is the center (0/0).
+ The minecart moves along the line x = -z, the perpendicular line to this is x = z.
+ In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */
+ if (
+ ((Distance.z > 0) && ((Distance.x / Distance.z) >= 1)) ||
+ ((Distance.z < 0) && ((Distance.x / Distance.z) <= 1))
+ )
+ {
+ // Moving -X +Z
+ if ((-GetSpeedX() * 0.4 / sqrt(2)) < 0.01)
+ {
+ // ~ SpeedX >= 0 Immobile or not moving in the "right" direction. Give it a bump!
+ AddSpeedX(-4 / sqrt(2));
+ AddSpeedZ(4 / sqrt(2));
+ }
+ else
+ {
+ // ~ SpeedX < 0 Moving in the "right" direction. Only accelerate it a bit.
+ SetSpeedX(GetSpeedX() * 0.4 / sqrt(2));
+ SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2));
+ }
+ }
+ else if ((GetSpeedX() * 0.4 / sqrt(2)) < 0.01)
+ {
+ // Moving +X -Z
+ // ~ SpeedX <= 0 Immobile or not moving in the "right" direction
+ AddSpeedX(4 / sqrt(2));
+ AddSpeedZ(-4 / sqrt(2));
+ }
+ else
+ {
+ // ~ SpeedX > 0 Moving in the "right" direction
+ SetSpeedX(GetSpeedX() * 0.4 / sqrt(2));
+ SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2));
+ }
+ break;
+ }
case E_META_RAIL_CURVED_ZM_XP:
case E_META_RAIL_CURVED_ZP_XM:
- case E_META_RAIL_CURVED_ZP_XP:
{
- // TODO - simply can't be bothered right now
+ Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ());
+
+ // Prevent division by small numbers
+ if (abs(Distance.z) < 0.001)
+ {
+ Distance.z = 0.001;
+ }
+
+ /* Check to which side the minecart is to be pushed.
+ Let's consider a z-x-coordinate system where the minecart is the center (0/0).
+ The minecart moves along the line x = z, the perpendicular line to this is x = -z.
+ In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */
+ if (
+ ((Distance.z > 0) && ((Distance.x / Distance.z) <= -1)) ||
+ ((Distance.z < 0) && ((Distance.x / Distance.z) >= -1))
+ )
+ {
+ // Moving +X +Z
+ if ((GetSpeedX() * 0.4) < 0.01)
+ {
+ // ~ SpeedX <= 0 Immobile or not moving in the "right" direction
+ AddSpeedX(4 / sqrt(2));
+ AddSpeedZ(4 / sqrt(2));
+ }
+ else
+ {
+ // ~ SpeedX > 0 Moving in the "right" direction
+ SetSpeedX(GetSpeedX() * 0.4 / sqrt(2));
+ SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2));
+ }
+ }
+ else if ((-GetSpeedX() * 0.4) < 0.01)
+ {
+ // Moving -X -Z
+ // ~ SpeedX >= 0 Immobile or not moving in the "right" direction
+ AddSpeedX(-4 / sqrt(2));
+ AddSpeedZ(-4 / sqrt(2));
+ }
+ else
+ {
+ // ~ SpeedX < 0 Moving in the "right" direction
+ SetSpeedX(GetSpeedX() * 0.4 / sqrt(2));
+ SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2));
+ }
break;
}
default: break;
diff --git a/src/LinearUpscale.h b/src/LinearUpscale.h
index 0b04408cf..a49f4bdf9 100644
--- a/src/LinearUpscale.h
+++ b/src/LinearUpscale.h
@@ -31,7 +31,7 @@ Linearly interpolates values in the array between the equidistant anchor points
Works in-place (input is already present at the correct output coords)
Uses templates to make it possible for the compiler to further optimizer the loops
*/
-template<
+template <
int SizeX, int SizeY, // Dimensions of the array
int AnchorStepX, int AnchorStepY,
typename TYPE
@@ -83,7 +83,7 @@ void LinearUpscale2DArrayInPlace(TYPE * a_Array)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
Works on two arrays, input is packed and output is to be completely constructed.
*/
-template<typename TYPE> void LinearUpscale2DArray(
+template <typename TYPE> void LinearUpscale2DArray(
TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY
int a_SrcSizeX, int a_SrcSizeY, ///< Dimensions of the src array
TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1)
@@ -153,7 +153,7 @@ template<typename TYPE> void LinearUpscale2DArray(
Linearly interpolates values in the array between the equidistant anchor points (upscales).
Works on two arrays, input is packed and output is to be completely constructed.
*/
-template<typename TYPE> void LinearUpscale3DArray(
+template <typename TYPE> void LinearUpscale3DArray(
TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY x a_SrcSizeZ
int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, ///< Dimensions of the src array
TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1) x (a_SrcSizeZ * a_UpscaleZ + 1)
diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h
index bf4d7f004..8d096fe29 100644
--- a/src/OSSupport/Queue.h
+++ b/src/OSSupport/Queue.h
@@ -20,7 +20,7 @@ cQueueFuncs and is used as the default behavior.
*/
/// This empty struct allows for the callback functions to be inlined
-template<class T>
+template <class T>
struct cQueueFuncs
{
public:
diff --git a/src/StringUtils.h b/src/StringUtils.h
index 3d4379352..4a4c267c7 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -9,6 +9,7 @@
#pragma once
#include <string>
+#include <limits>
@@ -98,6 +99,68 @@ extern int GetBEInt(const char * a_Mem);
/// Writes four bytes to the specified memory location so that they interpret as BigEndian int
extern void SetBEInt(char * a_Mem, Int32 a_Value);
+/// Parses any integer type. Checks bounds and returns errors out of band.
+template <class T>
+bool StringToInteger(const AString& a_str, T& a_Num)
+{
+ size_t i = 0;
+ bool positive = true;
+ T result = 0;
+ if (a_str[0] == '+')
+ {
+ i++;
+ }
+ else if (a_str[0] == '-')
+ {
+ i++;
+ positive = false;
+ }
+ if (positive)
+ {
+ for (size_t size = a_str.size(); i < size; i++)
+ {
+ if ((a_str[i] <= '0') || (a_str[i] >= '9'))
+ {
+ return false;
+ }
+ if (std::numeric_limits<T>::max() / 10 < result)
+ {
+ return false;
+ }
+ result *= 10;
+ T digit = a_str[i] - '0';
+ if (std::numeric_limits<T>::max() - digit < result)
+ {
+ return false;
+ }
+ result += digit;
+ }
+ }
+ else
+ {
+ for (size_t size = a_str.size(); i < size; i++)
+ {
+ if ((a_str[i] <= '0') || (a_str[i] >= '9'))
+ {
+ return false;
+ }
+ if (std::numeric_limits<T>::min() / 10 > result)
+ {
+ return false;
+ }
+ result *= 10;
+ T digit = a_str[i] - '0';
+ if (std::numeric_limits<T>::min() + digit > result)
+ {
+ return false;
+ }
+ result -= digit;
+ }
+ }
+ a_Num = result;
+ return true;
+}
+
// If you have any other string helper functions, declare them here