Simple include with a stock that parses ranges into the individual values within that range, contained within an ArrayList. Supports multiple ranges separated by commas, as well as ! meaning exceptions. Supports negative values.
Latest version always available at
http://ddhoward.com/sourcemod/script...parseRange.inc
Example Input: "4-7, 12-22, !14-15, -3-3, -10--15"
Example Output: An ArrayList containing values -15 thru -10, -3 thru 7, 12 thru 13, and 16 thru 22.
PHP Code:
#if defined _ddhoward_parseRange_version
#endinput
#endif
#define _ddhoward_parseRange_version "18.0523.1"
//http://ddhoward.com/sourcemod/scripting/include/parseRange.inc
/**
* Parses a string representing numerical ranges, and returns an ArrayList containing all applicable
* numbers. Supports ! symbol indicating exceptions. The string is parsed from left to right.
*
* Example input: "4-7, 12-22, !14-15, -3-3, -10--15"
* Example output: Array contains values -15 thru -10, -3 thru 7, 12 thru 13, and 16 thru 22
*
* @param sRange String containing a range of integers, or multiple ranges separated by
* commas.
*
* @param soOrder SortOrder representing how the resulting ArrayList should be sorted, or
* the default value _ for no sort.
*
* @param iMin The minimum value that an integer can have and be placed in the Array.
*
* @param iMax The maximum value that an integer can have and be placed in the Array.
*
* @param alPassedArray Pre-existing ArrayList that you'd like this function to use. If you
* do not specify this, then a new one will be created and returned.
*
* @return An ArrayList containing all applicable integers. You muse close this
* Handle after you are done with it!
*/
stock ArrayList ParseRange(const char[] sRange, SortOrder soOrder = view_as<SortOrder>(-1), int iMin = -2147483648, int iMax = 2147483647, ArrayList alPassedArray = null) {
static bool prListenerCreated;
if (!prListenerCreated) {
AddCommandListener(print_parseRange_include_version, "parseRange_include_versions");
prListenerCreated = true;
}
//calculate size of array needed
int iNumSections = 1;
for (int c; c < strlen(sRange); c++) {
if (sRange[c] == ',') {
iNumSections++;
}
}
char[][] sSections = new char[iNumSections][25]; //strlen("!-2147483648--2147483648") + 1
iNumSections = ExplodeString(sRange, ",", sSections, iNumSections, 25);
ArrayList alValues;
if (alPassedArray == null) {
alValues = new ArrayList();
}
else {
alValues = alPassedArray;
}
for (int iSection; iSection < iNumSections; iSection++) {
char sNumOne[12], sNumTwo[12];
bool bRemove; bool bIsRange;
for (int c; c < strlen(sSections[iSection]); c++) {
switch (sSections[iSection][c]) {
case '!' : bRemove = true;
case '-' : {
if (strlen(sNumOne) == 0) {
sNumOne[0] = '-';
}
else if (!bIsRange) {
bIsRange = true;
}
else if (strlen(sNumTwo) == 0) {
sNumTwo[0] = '-';
}
}
default: {
if (IsCharNumeric(sSections[iSection][c])) {
if (!bIsRange) {
sNumOne[strlen(sNumOne)] = sSections[iSection][c];
}
else {
sNumTwo[strlen(sNumTwo)] = sSections[iSection][c];
}
}
}
}
}
int iFirst = StringToInt(sNumOne);
int iSecond;
if (bIsRange) {
iSecond = StringToInt(sNumTwo);
}
else {
iSecond = iFirst;
}
if (iFirst > iSecond) {
int iTemp;
iTemp = iFirst;
iFirst = iSecond;
iSecond = iTemp;
}
if (iFirst < iMin) {
iFirst = iMin;
}
if (iSecond > iMax) {
iSecond = iMax;
}
for (int i = iFirst; i <= iSecond; i++) {
int iPrevIndex = alValues.FindValue(i);
if (iPrevIndex == -1 && !bRemove) {
alValues.Push(i);
}
else if (iPrevIndex != -1 && bRemove) {
alValues.Erase(iPrevIndex);
}
}
}
if (soOrder > view_as<SortOrder>(-1)) {
SortADTArray(alValues, soOrder, Sort_Integer);
}
return alValues;
}
//command listener which prints information to the chat, ALL plugins with this include will respond
//command user must have access to override "parseRange_include_versions" or root access to use this
public Action print_parseRange_include_version(int client, const char[] cmdname, int Args) {
if (client == 0 || CheckCommandAccess(client, "parseRange_include_versions", ADMFLAG_ROOT, true)) {
char pluginFilename[PLATFORM_MAX_PATH];
GetPluginFilename(INVALID_HANDLE, pluginFilename, sizeof(pluginFilename));
char pluginName[64];
if (GetPluginInfo(INVALID_HANDLE, PlInfo_Name, pluginName, sizeof(pluginName))) {
Format(pluginName, sizeof(pluginName), "%s%s", pluginName, " - ");
}
char pluginVersion[32];
if (GetPluginInfo(INVALID_HANDLE, PlInfo_Version, pluginVersion, sizeof(pluginVersion))) {
Format(pluginName, sizeof(pluginName), " %s", pluginName);
}
ReplyToCommand(client, "%s - %s%s%s", _ddhoward_parseRange_version, pluginName, pluginFilename, pluginVersion);
}
return Plugin_Continue;
}
The stock also adds a command listener for "parseRange_include_versions" which, when used by a root user, displays in that user's console a printout of all plugins using this include, and what version was used. This is a standard that I've created for use in all of my includes.
__________________