2020-09-28 04:15:06 +02:00
|
|
|
#define HELP_DEFINITION
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "UtilityClass.h"
|
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include <SDL.h>
|
2020-01-01 21:29:24 +01:00
|
|
|
#include <sstream>
|
|
|
|
|
Refactor loading arrays from XML to not use the STL
The current way "arrays" from XML files are loaded (before this commit
is applied) goes something like this:
1. Read the buffer of the contents of the tag using TinyXML-2.
2. Allocate a buffer on the heap of the same size, and copy the
existing buffer to it. (This is what the statement `std::string
TextString = pText;` does.)
3. For each delimiter in the heap-allocated buffer...
a. Allocate another buffer on the heap, and copy the characters from
the previous delimiter to the delimiter you just hit.
b. Then allocate the buffer AGAIN, to copy it into an std::vector.
4. Then re-allocate every single buffer YET AGAIN, because you need to
make a copy of the std::vector in split() to return it to the caller.
As you can see, the existing way uses a lot of memory allocations and
data marshalling, just to split some text.
The problem here is mostly making a temporary std::vector of split text,
before doing any actual useful work (most likely, putting it into an
array or ANOTHER std::vector - if the latter, then that's yet another
memory allocation on top of the memory allocation you already did; this
memory allocation is unavoidable, unlike the ones mentioned earlier,
which should be removed).
So I noticed that since we're iterating over the entire string once
(just to shove its contents into a temporary std::vector), and then
basically iterating over it again - why can't the whole thing just be
more immediate, and just be iterated over once?
So that's what I've done here. I've axed the split() function (both of
them, actually), and made next_split() and next_split_s().
next_split() will take an existing string and a starting index, and it
will find the next occurrence of the given delimiter in the string. Once
it does so, it will return the length from the previous starting index,
and modify your starting index as well. The price for immediateness is
that you're supposed to handle keeping the index of the previous
starting index around in order to be able to use the function; updating
it after each iteration is also your responsibility.
(By the way, next_split() doesn't use SDL_strchr(), because we can't get
the length of the substring for the last substring. We could handle this
special case specifically, but it'd be uglier; it also introduces
iterating over the last substring twice, when we only need to do it
once.)
next_split_s() does the same thing as next_split(), except it will copy
the resulting substring into a buffer that you provide (along with its
size). Useful if you don't particularly care about the length of the
substring.
All callers have been updated accordingly. This new system does not make
ANY heap allocations at all; at worst, it allocates a temporary buffer
on the stack, but that's only if you use next_split_s(); plus, it'd be a
fixed-size buffer, and stack allocations are negligible anyway.
This improves performance when loading any sort of XML file, especially
loading custom levels - which, on my system at least, I can noticeably
tell (there's less of a freeze when I load in to a custom level with
lots of scripts). It also decreases memory usage, because the heap isn't
being used just to iterate over some delimiters when XML files are
loaded.
2021-02-13 01:37:29 +01:00
|
|
|
#include "Maths.h"
|
|
|
|
|
2021-02-07 22:03:33 +01:00
|
|
|
static const char* GCChar(const SDL_GameControllerButton button)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
case SDL_CONTROLLER_BUTTON_A:
|
|
|
|
return "A";
|
|
|
|
case SDL_CONTROLLER_BUTTON_B:
|
|
|
|
return "B";
|
|
|
|
case SDL_CONTROLLER_BUTTON_X:
|
|
|
|
return "X";
|
|
|
|
case SDL_CONTROLLER_BUTTON_Y:
|
|
|
|
return "Y";
|
|
|
|
case SDL_CONTROLLER_BUTTON_BACK:
|
|
|
|
return "BACK";
|
|
|
|
case SDL_CONTROLLER_BUTTON_GUIDE:
|
|
|
|
return "GUIDE";
|
|
|
|
case SDL_CONTROLLER_BUTTON_START:
|
|
|
|
return "START";
|
|
|
|
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
|
|
|
return "L3";
|
|
|
|
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
|
|
|
return "R3";
|
|
|
|
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
|
|
|
return "LB";
|
|
|
|
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
|
|
|
return "RB";
|
|
|
|
default:
|
|
|
|
SDL_assert(0 && "Unhandled button!");
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2021-02-07 22:09:47 +01:00
|
|
|
int ss_toi(const std::string& str)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
int retval = 0;
|
|
|
|
bool negative = false;
|
|
|
|
static const int radix = 10;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < str.size(); ++i)
|
|
|
|
{
|
|
|
|
const char chr = str[i];
|
|
|
|
|
|
|
|
if (i == 0 && chr == '-')
|
|
|
|
{
|
|
|
|
negative = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SDL_isdigit(chr))
|
|
|
|
{
|
|
|
|
retval *= radix;
|
|
|
|
retval += chr - '0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (negative)
|
|
|
|
{
|
|
|
|
return -retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Refactor loading arrays from XML to not use the STL
The current way "arrays" from XML files are loaded (before this commit
is applied) goes something like this:
1. Read the buffer of the contents of the tag using TinyXML-2.
2. Allocate a buffer on the heap of the same size, and copy the
existing buffer to it. (This is what the statement `std::string
TextString = pText;` does.)
3. For each delimiter in the heap-allocated buffer...
a. Allocate another buffer on the heap, and copy the characters from
the previous delimiter to the delimiter you just hit.
b. Then allocate the buffer AGAIN, to copy it into an std::vector.
4. Then re-allocate every single buffer YET AGAIN, because you need to
make a copy of the std::vector in split() to return it to the caller.
As you can see, the existing way uses a lot of memory allocations and
data marshalling, just to split some text.
The problem here is mostly making a temporary std::vector of split text,
before doing any actual useful work (most likely, putting it into an
array or ANOTHER std::vector - if the latter, then that's yet another
memory allocation on top of the memory allocation you already did; this
memory allocation is unavoidable, unlike the ones mentioned earlier,
which should be removed).
So I noticed that since we're iterating over the entire string once
(just to shove its contents into a temporary std::vector), and then
basically iterating over it again - why can't the whole thing just be
more immediate, and just be iterated over once?
So that's what I've done here. I've axed the split() function (both of
them, actually), and made next_split() and next_split_s().
next_split() will take an existing string and a starting index, and it
will find the next occurrence of the given delimiter in the string. Once
it does so, it will return the length from the previous starting index,
and modify your starting index as well. The price for immediateness is
that you're supposed to handle keeping the index of the previous
starting index around in order to be able to use the function; updating
it after each iteration is also your responsibility.
(By the way, next_split() doesn't use SDL_strchr(), because we can't get
the length of the substring for the last substring. We could handle this
special case specifically, but it'd be uglier; it also introduces
iterating over the last substring twice, when we only need to do it
once.)
next_split_s() does the same thing as next_split(), except it will copy
the resulting substring into a buffer that you provide (along with its
size). Useful if you don't particularly care about the length of the
substring.
All callers have been updated accordingly. This new system does not make
ANY heap allocations at all; at worst, it allocates a temporary buffer
on the stack, but that's only if you use next_split_s(); plus, it'd be a
fixed-size buffer, and stack allocations are negligible anyway.
This improves performance when loading any sort of XML file, especially
loading custom levels - which, on my system at least, I can noticeably
tell (there's less of a freeze when I load in to a custom level with
lots of scripts). It also decreases memory usage, because the heap isn't
being used just to iterate over some delimiters when XML files are
loaded.
2021-02-13 01:37:29 +01:00
|
|
|
bool next_split(
|
2021-09-07 03:56:39 +02:00
|
|
|
size_t* start,
|
|
|
|
size_t* len,
|
|
|
|
const char* str,
|
|
|
|
const char delim
|
Refactor loading arrays from XML to not use the STL
The current way "arrays" from XML files are loaded (before this commit
is applied) goes something like this:
1. Read the buffer of the contents of the tag using TinyXML-2.
2. Allocate a buffer on the heap of the same size, and copy the
existing buffer to it. (This is what the statement `std::string
TextString = pText;` does.)
3. For each delimiter in the heap-allocated buffer...
a. Allocate another buffer on the heap, and copy the characters from
the previous delimiter to the delimiter you just hit.
b. Then allocate the buffer AGAIN, to copy it into an std::vector.
4. Then re-allocate every single buffer YET AGAIN, because you need to
make a copy of the std::vector in split() to return it to the caller.
As you can see, the existing way uses a lot of memory allocations and
data marshalling, just to split some text.
The problem here is mostly making a temporary std::vector of split text,
before doing any actual useful work (most likely, putting it into an
array or ANOTHER std::vector - if the latter, then that's yet another
memory allocation on top of the memory allocation you already did; this
memory allocation is unavoidable, unlike the ones mentioned earlier,
which should be removed).
So I noticed that since we're iterating over the entire string once
(just to shove its contents into a temporary std::vector), and then
basically iterating over it again - why can't the whole thing just be
more immediate, and just be iterated over once?
So that's what I've done here. I've axed the split() function (both of
them, actually), and made next_split() and next_split_s().
next_split() will take an existing string and a starting index, and it
will find the next occurrence of the given delimiter in the string. Once
it does so, it will return the length from the previous starting index,
and modify your starting index as well. The price for immediateness is
that you're supposed to handle keeping the index of the previous
starting index around in order to be able to use the function; updating
it after each iteration is also your responsibility.
(By the way, next_split() doesn't use SDL_strchr(), because we can't get
the length of the substring for the last substring. We could handle this
special case specifically, but it'd be uglier; it also introduces
iterating over the last substring twice, when we only need to do it
once.)
next_split_s() does the same thing as next_split(), except it will copy
the resulting substring into a buffer that you provide (along with its
size). Useful if you don't particularly care about the length of the
substring.
All callers have been updated accordingly. This new system does not make
ANY heap allocations at all; at worst, it allocates a temporary buffer
on the stack, but that's only if you use next_split_s(); plus, it'd be a
fixed-size buffer, and stack allocations are negligible anyway.
This improves performance when loading any sort of XML file, especially
loading custom levels - which, on my system at least, I can noticeably
tell (there's less of a freeze when I load in to a custom level with
lots of scripts). It also decreases memory usage, because the heap isn't
being used just to iterate over some delimiters when XML files are
loaded.
2021-02-13 01:37:29 +01:00
|
|
|
) {
|
2021-09-07 03:56:39 +02:00
|
|
|
size_t idx = 0;
|
|
|
|
*len = 0;
|
|
|
|
|
|
|
|
if (str[idx] == '\0')
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (str[idx] == delim)
|
|
|
|
{
|
|
|
|
*start += 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (str[idx] == '\0')
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
idx += 1;
|
|
|
|
*start += 1;
|
|
|
|
*len += 1;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Refactor loading arrays from XML to not use the STL
The current way "arrays" from XML files are loaded (before this commit
is applied) goes something like this:
1. Read the buffer of the contents of the tag using TinyXML-2.
2. Allocate a buffer on the heap of the same size, and copy the
existing buffer to it. (This is what the statement `std::string
TextString = pText;` does.)
3. For each delimiter in the heap-allocated buffer...
a. Allocate another buffer on the heap, and copy the characters from
the previous delimiter to the delimiter you just hit.
b. Then allocate the buffer AGAIN, to copy it into an std::vector.
4. Then re-allocate every single buffer YET AGAIN, because you need to
make a copy of the std::vector in split() to return it to the caller.
As you can see, the existing way uses a lot of memory allocations and
data marshalling, just to split some text.
The problem here is mostly making a temporary std::vector of split text,
before doing any actual useful work (most likely, putting it into an
array or ANOTHER std::vector - if the latter, then that's yet another
memory allocation on top of the memory allocation you already did; this
memory allocation is unavoidable, unlike the ones mentioned earlier,
which should be removed).
So I noticed that since we're iterating over the entire string once
(just to shove its contents into a temporary std::vector), and then
basically iterating over it again - why can't the whole thing just be
more immediate, and just be iterated over once?
So that's what I've done here. I've axed the split() function (both of
them, actually), and made next_split() and next_split_s().
next_split() will take an existing string and a starting index, and it
will find the next occurrence of the given delimiter in the string. Once
it does so, it will return the length from the previous starting index,
and modify your starting index as well. The price for immediateness is
that you're supposed to handle keeping the index of the previous
starting index around in order to be able to use the function; updating
it after each iteration is also your responsibility.
(By the way, next_split() doesn't use SDL_strchr(), because we can't get
the length of the substring for the last substring. We could handle this
special case specifically, but it'd be uglier; it also introduces
iterating over the last substring twice, when we only need to do it
once.)
next_split_s() does the same thing as next_split(), except it will copy
the resulting substring into a buffer that you provide (along with its
size). Useful if you don't particularly care about the length of the
substring.
All callers have been updated accordingly. This new system does not make
ANY heap allocations at all; at worst, it allocates a temporary buffer
on the stack, but that's only if you use next_split_s(); plus, it'd be a
fixed-size buffer, and stack allocations are negligible anyway.
This improves performance when loading any sort of XML file, especially
loading custom levels - which, on my system at least, I can noticeably
tell (there's less of a freeze when I load in to a custom level with
lots of scripts). It also decreases memory usage, because the heap isn't
being used just to iterate over some delimiters when XML files are
loaded.
2021-02-13 01:37:29 +01:00
|
|
|
bool next_split_s(
|
2021-09-07 03:56:39 +02:00
|
|
|
char buffer[],
|
|
|
|
const size_t buffer_size,
|
|
|
|
size_t* start,
|
|
|
|
const char* str,
|
|
|
|
const char delim
|
Refactor loading arrays from XML to not use the STL
The current way "arrays" from XML files are loaded (before this commit
is applied) goes something like this:
1. Read the buffer of the contents of the tag using TinyXML-2.
2. Allocate a buffer on the heap of the same size, and copy the
existing buffer to it. (This is what the statement `std::string
TextString = pText;` does.)
3. For each delimiter in the heap-allocated buffer...
a. Allocate another buffer on the heap, and copy the characters from
the previous delimiter to the delimiter you just hit.
b. Then allocate the buffer AGAIN, to copy it into an std::vector.
4. Then re-allocate every single buffer YET AGAIN, because you need to
make a copy of the std::vector in split() to return it to the caller.
As you can see, the existing way uses a lot of memory allocations and
data marshalling, just to split some text.
The problem here is mostly making a temporary std::vector of split text,
before doing any actual useful work (most likely, putting it into an
array or ANOTHER std::vector - if the latter, then that's yet another
memory allocation on top of the memory allocation you already did; this
memory allocation is unavoidable, unlike the ones mentioned earlier,
which should be removed).
So I noticed that since we're iterating over the entire string once
(just to shove its contents into a temporary std::vector), and then
basically iterating over it again - why can't the whole thing just be
more immediate, and just be iterated over once?
So that's what I've done here. I've axed the split() function (both of
them, actually), and made next_split() and next_split_s().
next_split() will take an existing string and a starting index, and it
will find the next occurrence of the given delimiter in the string. Once
it does so, it will return the length from the previous starting index,
and modify your starting index as well. The price for immediateness is
that you're supposed to handle keeping the index of the previous
starting index around in order to be able to use the function; updating
it after each iteration is also your responsibility.
(By the way, next_split() doesn't use SDL_strchr(), because we can't get
the length of the substring for the last substring. We could handle this
special case specifically, but it'd be uglier; it also introduces
iterating over the last substring twice, when we only need to do it
once.)
next_split_s() does the same thing as next_split(), except it will copy
the resulting substring into a buffer that you provide (along with its
size). Useful if you don't particularly care about the length of the
substring.
All callers have been updated accordingly. This new system does not make
ANY heap allocations at all; at worst, it allocates a temporary buffer
on the stack, but that's only if you use next_split_s(); plus, it'd be a
fixed-size buffer, and stack allocations are negligible anyway.
This improves performance when loading any sort of XML file, especially
loading custom levels - which, on my system at least, I can noticeably
tell (there's less of a freeze when I load in to a custom level with
lots of scripts). It also decreases memory usage, because the heap isn't
being used just to iterate over some delimiters when XML files are
loaded.
2021-02-13 01:37:29 +01:00
|
|
|
) {
|
2021-09-07 03:56:39 +02:00
|
|
|
size_t len = 0;
|
|
|
|
const size_t prev_start = *start;
|
|
|
|
|
|
|
|
const bool retval = next_split(start, &len, &str[*start], delim);
|
|
|
|
|
|
|
|
if (retval)
|
|
|
|
{
|
|
|
|
/* Using SDL_strlcpy() here results in calling SDL_strlen() */
|
|
|
|
/* on the whole string, which results in a visible freeze */
|
|
|
|
/* if it's a very large string */
|
|
|
|
const size_t length = VVV_min(buffer_size - 1, len);
|
|
|
|
SDL_memcpy(buffer, &str[prev_start], length);
|
|
|
|
buffer[length] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
UtilityClass::UtilityClass(void) :
|
2020-01-01 21:29:24 +01:00
|
|
|
glow(0),
|
2021-09-07 03:56:39 +02:00
|
|
|
glowdir(0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(splitseconds); i++)
|
|
|
|
{
|
|
|
|
splitseconds[i] = (i * 100) / 30;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
slowsine = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string UtilityClass::String( int _v )
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
std::ostringstream os;
|
|
|
|
os << _v;
|
|
|
|
return(os.str());
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-08-07 06:56:35 +02:00
|
|
|
int UtilityClass::Int(const char* str, int fallback /*= 0*/)
|
2020-08-07 06:28:51 +02:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
if (!is_number(str))
|
|
|
|
{
|
|
|
|
return fallback;
|
|
|
|
}
|
2020-08-07 06:28:51 +02:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
return (int) SDL_strtol(str, NULL, 0);
|
2020-08-07 06:28:51 +02:00
|
|
|
}
|
|
|
|
|
2021-02-07 22:17:22 +01:00
|
|
|
std::string UtilityClass::GCString(const std::vector<SDL_GameControllerButton>& buttons)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
std::string retval = "";
|
|
|
|
for (size_t i = 0; i < buttons.size(); i += 1)
|
|
|
|
{
|
|
|
|
retval += GCChar(buttons[i]);
|
|
|
|
if ((i + 1) < buttons.size())
|
|
|
|
{
|
|
|
|
retval += ",";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string UtilityClass::twodigits( int t )
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
if (t < 10)
|
|
|
|
{
|
|
|
|
return "0" + String(t);
|
|
|
|
}
|
|
|
|
if (t >= 100)
|
|
|
|
{
|
|
|
|
return "??";
|
|
|
|
}
|
|
|
|
return String(t);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string UtilityClass::timestring( int t )
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
//given a time t in frames, return a time in seconds
|
|
|
|
std::string tempstring = "";
|
|
|
|
int temp = (t - (t % 30)) / 30;
|
|
|
|
if (temp < 60) //less than one minute
|
|
|
|
{
|
|
|
|
t = t % 30;
|
|
|
|
tempstring = String(temp) + ":" + twodigits(splitseconds[t]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int temp2 = (temp - (temp % 60)) / 60;
|
|
|
|
temp = temp % 60;
|
|
|
|
t = t % 30;
|
|
|
|
tempstring = String(temp2) + ":" + twodigits(temp) + ":" + twodigits(splitseconds[t]);
|
|
|
|
}
|
|
|
|
return tempstring;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string UtilityClass::number( int _t )
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
static const std::string ones_place[] = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
|
|
|
|
static const std::string tens_place[] = {"Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
|
|
|
|
static const std::string teens[] = {"Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
|
|
|
|
|
|
|
|
if (_t < 0)
|
|
|
|
{
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
else if (_t > 100)
|
|
|
|
{
|
|
|
|
return "Lots";
|
|
|
|
}
|
|
|
|
else if (_t == 0)
|
|
|
|
{
|
|
|
|
return "Zero";
|
|
|
|
}
|
|
|
|
else if (_t == 100)
|
|
|
|
{
|
|
|
|
return "One Hundred";
|
|
|
|
}
|
|
|
|
else if (_t >= 1 && _t <= 9)
|
|
|
|
{
|
|
|
|
return ones_place[_t-1];
|
|
|
|
}
|
|
|
|
else if (_t >= 11 && _t <= 19)
|
|
|
|
{
|
|
|
|
return teens[_t-11];
|
|
|
|
}
|
|
|
|
else if (_t % 10 == 0)
|
|
|
|
{
|
|
|
|
return tens_place[(_t/10)-1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return tens_place[(_t/10)-1] + " " + ones_place[(_t%10)-1];
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool UtilityClass::intersects( SDL_Rect A, SDL_Rect B )
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
return (SDL_HasIntersection(&A, &B) == SDL_TRUE);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void UtilityClass::updateglow(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
slowsine++;
|
|
|
|
if (slowsine >= 64) slowsine = 0;
|
|
|
|
|
|
|
|
if (glowdir == 0) {
|
|
|
|
glow+=2;
|
|
|
|
if (glow >= 62) glowdir = 1;
|
|
|
|
}else {
|
|
|
|
glow-=2;
|
|
|
|
if (glow < 2) glowdir = 0;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-17 23:52:09 +02:00
|
|
|
|
2020-08-07 06:22:10 +02:00
|
|
|
bool is_number(const char* str)
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
if (!SDL_isdigit(str[0]) && str[0] != '-')
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str[0] == '-' && str[1] == '\0')
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 1; str[i] != '\0'; ++i)
|
|
|
|
{
|
|
|
|
if (!SDL_isdigit(str[i]))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2020-08-07 06:22:10 +02:00
|
|
|
}
|
|
|
|
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
static bool VVV_isxdigit(const unsigned char digit)
|
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
return (digit >= 'a' && digit <= 'f')
|
|
|
|
|| (digit >= 'A' && digit <= 'F')
|
|
|
|
|| SDL_isdigit(digit);
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 01:36:22 +01:00
|
|
|
bool is_positive_num(const char* str, const bool hex)
|
2020-04-17 23:52:09 +02:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
if (str[0] == '\0')
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; str[i] != '\0'; ++i)
|
|
|
|
{
|
|
|
|
if (hex)
|
|
|
|
{
|
|
|
|
if (!VVV_isxdigit(str[i]))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!SDL_isdigit(str[i]))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2020-04-17 23:52:09 +02:00
|
|
|
}
|
2020-06-21 23:25:23 +02:00
|
|
|
|
2021-02-27 00:29:37 +01:00
|
|
|
bool endsWith(const char* str, const char* suffix)
|
2020-06-21 23:25:23 +02:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
const size_t str_size = SDL_strlen(str);
|
|
|
|
const size_t suffix_size = SDL_strlen(suffix);
|
2021-02-27 00:29:37 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
if (str_size < suffix_size)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-02-27 00:29:37 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
return SDL_strcmp(&str[str_size - suffix_size], suffix) == 0;
|
2020-06-21 23:25:23 +02:00
|
|
|
}
|
2021-04-12 02:19:53 +02:00
|
|
|
|
|
|
|
void VVV_fillstring(
|
2021-09-07 03:56:39 +02:00
|
|
|
char* buffer,
|
|
|
|
const size_t buffer_size,
|
|
|
|
const char fillchar
|
2021-04-12 02:19:53 +02:00
|
|
|
) {
|
2021-09-07 03:56:39 +02:00
|
|
|
SDL_memset(buffer, fillchar, buffer_size - 1);
|
|
|
|
buffer[buffer_size - 1] = '\0';
|
2021-04-12 02:19:53 +02:00
|
|
|
}
|
2021-05-20 23:14:08 +02:00
|
|
|
void _VVV_between(
|
2021-09-07 03:56:39 +02:00
|
|
|
const char* original,
|
|
|
|
const size_t left_length,
|
|
|
|
char* middle,
|
|
|
|
const size_t right_length,
|
|
|
|
const size_t middle_size
|
2021-05-20 23:14:08 +02:00
|
|
|
) {
|
2021-09-07 03:56:39 +02:00
|
|
|
size_t middle_length = SDL_strlen(original);
|
|
|
|
middle_length -= left_length + right_length;
|
|
|
|
SDL_strlcpy(
|
|
|
|
middle,
|
|
|
|
&original[left_length],
|
|
|
|
VVV_min(middle_length + 1, middle_size)
|
|
|
|
);
|
2021-05-20 23:14:08 +02:00
|
|
|
}
|