* Creates next string key from the passed one using specified set of characters
*
* Parameters
* 1 - Current Key
* 2 - Defines the list of allowed characters
* BASEnn - See DO CASE in the body of the program
* CUSTOM - the list of character as parameter 3
* 3 - List of characters
*
* Returns Next key
*
* Note 1 Routine ignores (doesn't change) positions with the characters not in the specified list
* Note 2 When max possible value is reached, the next return value will be the min possible value
*
FUNCTION NextKey
LPARAMETERS tcOldVal, tcOpt, tcCharList
LOCAL lcNewVal, i, lcDigits, lcLetters, lnCharListLen, lcOldChar, lcNewChar, lcCharList, lnPos, lcOpt
LOCAL lnNextPos
lcOpt = IIF(EMPTY(tcOpt), "BASE10", UPPER(tcOpt))
* Get the list of appropriate characters
lcCharList = NextKeyFillCharList(lcOpt, tcCharList)
lnCharListLen = LEN(lcCharList)
lcNewVal = tcOldVal
* Scan string from the right to the left
FOR i = LEN(lcNewVal) TO 1 STEP -1
lcOldChar = SUBSTR(tcOldVal, i, 1)
* Is the current charater in the list?
lnPos = AT(lcOldChar, lcCharList)
IF lnPos = 0
* Not in the list, keep it
LOOP
ENDIF
* Get the next character position
lnNextPos = (lnPos % lnCharListLen) + 1
* Get the next character
lcNewChar = SUBSTR(lcCharList,lnNextPos,1)
* Stuff it back in the string
lcNewVal = STUFF(lcNewVal, i, 1, lcNewChar)
* Check if we have to carry over to the next position
IF lnNextPos > 1
* We are done
EXIT
ENDIF
ENDFOR
RETURN lcNewVal
*------------------------------------------------------------
* Fill the list of characters based on character set requested
FUNCTION NextKeyFillCharList
LPARAMETERS tcCharSet, tcCharList
LOCAL lcCharList, lcDigits, lcLetters
* Fill string 'lcCharList' with appropriate characters
lcDigits = "0123456789"
lcLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DO CASE
CASE tcCharSet = "CUSTOM"
lcCharList = tcCharList
CASE tcCharSet == "BASE10"
* Just Digits
lcCharList = lcDigits
CASE tcCharSet == "BASE16L"
* Hexadecimal in lower case
lcCharList = lcDigits + "abcdef"
CASE tcCharSet == "BASE16"
* Hexadecimal in upper case
lcCharList = lcDigits + "ABCDEF"
CASE tcCharSet == "BASE26L"
* Lower case letters
lcCharList = LOWER(lcLetters)
CASE tcCharSet == "BASE26"
* Upper case letters
lcCharList = lcLetters
CASE tcCharSet == "BASE36L"
* Digits + Lower case letters
lcCharList = lcDigits + LOWER(lcLetters)
CASE tcCharSet == "BASE36"
* Digits + Upper case letters
lcCharList = lcDigits + lcLetters
CASE tcCharSet == "BASE52"
* All letters
lcCharList = lcLetters + LOWER(lcLetters)
CASE tcCharSet == "BASE62"
* Digits + All letters
lcCharList = lcDigits + lcLetters + LOWER(lcLetters)
OTHERWISE
* The same as BASE10
lcCharList = lcDigits
ENDCASE
RETURN lcCharList
Examples:
* Rollover to min value (Base10)
? NextKey("999999") && 000000
* Next value (Base16)
? NextKey("999999", "Base16") && 99999A
* Dash ('-') has not been changed
? NextKey("999-FFF", "Base16") && 99A-000
Niciun comentariu:
Trimiteți un comentariu