-
-
Notifications
You must be signed in to change notification settings - Fork 433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added some new string manipulation stocks #1224
Conversation
Added the following stocks: - IsStringNumber - IsStringFloat - StringToLowerCase - StringToUpperCase - IndexOfChar - LastIndexOfChar Tested: Test plugin source link: https://pastebin.com/QWXUy0ta Test results: https://i.imgur.com/NKhvsl4.png
plugins/include/string.inc
Outdated
* @param szString Input string | ||
* @return Boolean | ||
*/ | ||
stock bool IsStringNumber(const char[] szString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need a temporary string? I think it would work to skip past spaces and then call StringToIntExt() and check the return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never heard of StringToIntExt and I cannot find it in the documentation.
The reason I used a temporary value is to avoid modifying the original string when trimming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, StringToIntEx. You don't need to modify the string if you skip spaces with a counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, I tried with StringToInt and StringToFloat and it did not work properly, the test which needed to pass, have failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Results of those functions: https://i.imgur.com/4l1JzGd.png
plugins/include/string.inc
Outdated
{ | ||
int iIterator = 0; | ||
int iLength = strlen(szInput); | ||
char[] szOutput = new char[iLength + 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a temporary needed here, given that the string is modified in place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, they are not needed. I am going to correct it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
plugins/include/string.inc
Outdated
{ | ||
int iIterator = 0; | ||
int iLength = strlen(szInput); | ||
char[] szOutput = new char[iLength + 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
plugins/include/string.inc
Outdated
int iP; | ||
int iLength = strlen(szString); | ||
|
||
while (0 < szString[iIterator] <= 255) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be much easier to write this as a wrapper around StringToFloatEx(), which will also make sure the parsing is consistent.
Removed unnecessary temporary variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've rolled these myself, but they can definitely be simpler and wrapped around our natives. so, + dvander's comments we already have some of this in the tree.
I have simplified the StringToUpper and StringToLower case. |
That's why dvander suggested using the
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why dvander suggested using the
Ex
variants of those natives. They return the number of characters consumed for the number, so checking if the whole string was consumed does what you want.stock bool IsStringInteger(const char[] str, int nBase=10) { int result; return StringToIntEx(str, result, nBase) == strlen(str); } stock bool IsStringFloat(const char[] str) { float result; return StringToFloatEx(str, result) == strlen(str); }
Yeah, but IsStringFloat fails and counts -1 and -3 as floats, and they are not.
Edit: Nevermind, fixed:
stock bool IsStringFloat(const char[] str)
{
float result;
return StringToFloatEx(str, result) == strlen(str) && FindCharInString(str, '.') != -1;
}
plugins/include/string.inc
Outdated
* @param szString Input string | ||
* @return Boolean | ||
*/ | ||
stock bool IsStringNumber(const char[] szString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, I tried with StringToInt and StringToFloat and it did not work properly, the test which needed to pass, have failed.
plugins/include/string.inc
Outdated
{ | ||
int iIterator = 0; | ||
int iLength = strlen(szInput); | ||
char[] szOutput = new char[iLength + 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, they are not needed. I am going to correct it.
plugins/include/string.inc
Outdated
* @param szString Input string | ||
* @return Boolean | ||
*/ | ||
stock bool IsStringNumber(const char[] szString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Results of those functions: https://i.imgur.com/4l1JzGd.png
plugins/include/string.inc
Outdated
{ | ||
int iIterator = 0; | ||
int iLength = strlen(szInput); | ||
char[] szOutput = new char[iLength + 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
If you want to be very strict, you can do:
But I'm not sure I'm in favor of this. Integers are a subset of floats, and it's kind of arbitrary to demand that decimals are added for whole numbers. |
Changed IsStringNumber and IsStringFloat to wrap StringToIntEx and StringToFloatEx. Changed IndexOfChar to wrap FindCharInString. Added CopyC
Changed the code to apply your advices. Changed IsStringNumber and IsStringFloat to wrap StringToIntEx and StringToFloatEx. Tested, everything works: |
If the string has a floating point value or not, we can still store it in a float. No need to check the additional stocks, they're built-in. CopyC already exists, that's simply strcopy.
@milutinke I've made some adjustments that I thought were appropriate. What do you think? |
@milutinke any update on this? |
Sorry for replying this late, I've not received a notification about this for some reason back then. |
If the goal is to add more string stocks for common stuff, I feel like borrowing a few more ideas from python would make sense. |
+1 I've missed StringEndsWith in almost every other plugin I made. |
Sorry to bump, can we get some update on this? I feel like converting String case is a very fundamental operation and it would be nice to have SM ship with it. |
Would adding wrappers for other available stock functions really help or make the API more confusing? I've reviewed this again and am in favor of adding more string utility stocks as suggested, but am hesitant on adding wrappers like |
People who come from other programming languages are used to IndexOfChar name, so it would not hurt having it in my opinion. |
I have an assortment of issues with the current functions, but I'm told I should put the improvements here instead of making a competing PR. Bug
Naming
Style
Misc
|
@sirdigbot Maybe you should make a PR after all, as this one appears cursed. |
Sure, go ahead. I'll take a look. Though I already have a massive list of proposed stocks from the last time I had a go at a PR. |
For some reason I did not get notifications until now (all of them) for this PR even I'm subscribed. |
If you pick any, I can clean them up and add docs. I especially like StrEndsWithEx as it lets me check for multiple file extensions without calculating string length repeatedly. Additionally I think FindCharInString stock can be optimized (in forward mode at least) by removing strlen at the beginning and checking for end of string inside the loop. |
StringEndsWith is already on my big list, as is StringStartsWith |
Here is my use case https://github.com/Alienmario/smartdm-redux/blob/main/scripting/include/smartdm_redux.inc#L110 |
Yeah so this seems to just be avoiding needing to call strlen(filepath) each time you check a different file extension. Which is technically an optimisation but probably not enough of one to be built into sourcemod directly. Especially because you're still calling strlen(extension), where the slowest component of that is going to be the SP -> C++ -> SP process anyway. While strlen is O(n), 5 redundant calls to it on even a long filepath are probably insignificant unless it's happening pretty frequently. |
Anyway, I've started a new PR where further comments should be added instead. |
Added the following stocks:
Tested:
Test plugin source link: https://pastebin.com/hqfSZNxY
Test results: https://i.imgur.com/4CawNKq.png