sourcemod
sourcemod copied to clipboard
Added some new string manipulation stocks
Added the following stocks:
- IsStringNumber
- IsStringFloat
- StringToLowerCase
- StringToUpperCase
- IndexOfChar
- LastIndexOfChar
- CopyC
Tested: Test plugin source link: https://pastebin.com/hqfSZNxY Test results: https://i.imgur.com/4CawNKq.png
I have simplified the StringToUpper and StringToLower case. Regarding the FindCharInString, I did not know about that function, I can change IndexOfChar and LastIndexOfChar to wrap the FindCharInString. IsStringNumber and IsStringFloat do not work intended when they wrap StringToInt and StringToFloat. Results of the test with those: https://i.imgur.com/4l1JzGd.png
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);
}
If you want to be very strict, you can do:
stock bool IsStringFloat(const char[] str)
{
float result;
return StringToFloatEx(str, result) == strlen(str) && !IsStringInt(str);
}
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 the code to apply your advices.
Changed IsStringNumber and IsStringFloat to wrap StringToIntEx and StringToFloatEx. Changed IndexOfChar to wrap FindCharInString. Added CopyC
Tested, everything works: Test plugin source link: https://pastebin.com/hqfSZNxY Test results: https://i.imgur.com/4CawNKq.png
@milutinke I've made some adjustments that I thought were appropriate. What do you think?
@milutinke any update on this?
@milutinke any update on this?
Sorry for replying this late, I've not received a notification about this for some reason back then.
CopyC does not exist in Source Mod, at least to my knowledge.
Also, I think that return StringToFloatEx(str, result) == strlen(str); will not work properly in IsStringFloat without && FindCharInString(str, '.') != -1; if I remember correctly.
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. Such as IsStringAlpha/Numeric/AlNum, IsStringASCII, IsStringPrintable, StringEndsWith. There's already char versions of some of those, so making string equivalents doesn't seem unreasonable.
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. Such as IsStringAlpha/Numeric/AlNum, IsStringASCII, IsStringPrintable, StringEndsWith. There's already char versions of some of those, so making string equivalents doesn't seem unreasonable.
+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 IndexOfChar -> FindCharInString. Having multiple functions doing the same thing doesn't help readability of code. But FindCharInString is a mouthful and not the best choice of name for what it does after all.
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
IndexOfChar->FindCharInString. Having multiple functions doing the same thing doesn't help readability of code. ButFindCharInStringis a mouthful and not the best choice of name for what it does after all.
People who come from other programming languages are used to IndexOfChar name, so it would not hurt having it in my opinion. But yeah, I am fine without it being added too.
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. Sorry in advance.
Bug
IsStringNumber/IsStringFloatboth incorrectly consider an empty string as valid.
Naming
IsStringNumberonly detects integers so it should be calledIsStringIntegerIsStringFloatis misleading. As dvander mentioned it should (and does) handle integer values too (usually what's important is "can it convert to a float").IsStringDecimalwould be better asStringToFloatrequires base-10 numbers anyway.StringToLowerCaseshould beStringToLowerboth because it's shorter and because it matchesIsCharLowerandCharToLower- Ditto for
StringToUpperCase
Style
- Hungarian notation (prefixing with the type) should be removed from params and names should be made more consistent with the other functions. e.g.
szInput->str - Variables also should not use hungarian notation
EOSis never used anywhere in sourcemod's codebase except a single test case. I'm not sure if it's considered bad to use compared to'\0'but it might be.- Both the StringToLower/Upper functions could've just been for-loops for readability sake:
for (int i = 0; str[i] != '\0'; ++i)is a common idiom. - In
IndexOfChar's docstring, "Do we need the last index (Optional, default: false)" should probably borrow the description fromFindCharInString's parameter: "False (default) to search forward, true to search backward."
Misc
IsStringNumberis missing thenBaseparameter in its docstring- Docstrings have incorrect
@returndescriptions--the meaning of the return values (not the type) is supposed to be there. So forIsStringFloatfor example,@return Booleanshould be changed to something like@return True if string is a valid float number. @returnis not needed for void functions.- "Input string for conversion and also the output" is unclear and wordy. You could borrow from CharToLower/Upper: "Converts each character in a string to its lowercase counterpart."
- "Supports negative values" should not need to be clarified for
IsStringNumber/IsStringFloatsince not supporting them is incorrect. - The docstrings for every single function have the incorrect parameter names for every parameter.
- For
IndexOfChar, "index of the found character" is unclear because it actually finds the first occurrence of the character. - (Picky)
const char cCharacterdoesn't really need to beconstsince scalar values are always passed by-value (i.e. copied) anyway.