--@Name: "XLib.UpdateUtility" --@Version 1.01 on GetNumber (aThing, toFormat, fromFormat, lowerCaseOrPrecision) -- This function attempts to extract a 'number' from the supplied thing. You can supply the -- 'toFormat' and 'fromFormat' options. If you do not supply the 'toFormat', an -- #Integer is returned. If you do not supply the fromFormat, it will be inferred -- from the input. Note that some strings (such as "101" could be decimal, binary -- or hex. If there is a leading 0, binary is assumed. Otherwise integer is assumed). -- -- possible returned values: -- NAN, an Integer, a Float, a String (Hex or Binary representation of the number). if voidP(toFormat) then toFormat = #Integer if voidP(fromFormat) then fromFormat = GuessNumberType(aThing) -- put "Converting " & aThing & " (from " &fromFormat & " to " & toFormat & ")" if fromFormat = #NAN then return Sqrt(-1) -- NAN -- BaseList = [#Integer:10, #Float: 10, #Hex: 16, #Binary:2] if fromFormat <> #Float then oldbase = BaseList[fromFormat] newbase = BaseList[toFormat] r= ConvertBase (aThing, oldbase, newbase, lowerCaseOrPrecision) if toFormat = #Integer then return integer(r) else if toFormat = #Float then return float(r) else return r else if toFormat <> #Float then newbase = BaseList[toFormat] r = ConvertBase (toInteger (aThing), 10, newbase, lowerCaseOrPrecision) if toFormat = #Integer then return integer(r) else return r else if lowerCaseOrPrecision.ilk = #Integer then the floatPrecision = lowerCaseOrPrecision return float(value(aThing)) end if end if end on toInteger (aThing) -- converts a thing to an integer if athing.ilk = #Integer then return aThing if athing.ilk = #float then return integer(aThing) aThing = string(athing) v = value(athing) return integer(v) end on toFloat (athing) -- converts a thing to an float if athing.ilk = #Integer then return float(aThing) if athing.ilk = #float then return aThing aThing = string(athing) v = value(athing) return float(v) end on GuessNumberType (aThing) -- returns #Integer, #Float, #Hex, #Binary or #NAN. -- Some inputs, such as "111" could be integer, hex -- or binary. In this case, #Integer is assumed. -- possibles (in order, if more than one possible) possibles = [#Float, #Integer, #Hex, #Binary] -- first, see if the type is set if athing.ilk = #Integer then return #Integer if aThing.ilk = #Float then return #Float -- if that doesn't work, inspect the characters aThing = string(athing) if aThing contains "." then return #Float else possibles.deleteOne(#Float) strLength = length(athing) if strLength < 1 then return #NAN if athing starts "0x" then return #Hex end if if athing starts "-" then delete aThing.char[1] possibles.deleteOne(#Binary) possibles.deleteOne(#Hex) end if if athing starts "+" then delete aThing.char[1] possibles.deleteOne(#Binary) possibles.deleteOne(#Hex) end if digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "a", "b", "c", "d", "e", "f"] strLength = length(athing) if strLength < 1 then return 0 repeat with i = strLength down to 1 thisChar = aThing.char[i] thisDigit = digits.getOne(thisChar) if thisDigit < 1 then return #NAN end if if thisDigit > 10 then -- cannot be a #decimal possibles.deleteOne(#Float) possibles.deleteOne(#Integer) end if if thisDigit > 2 then -- cannot be a #binary possibles.deleteOne(#Binary) end if end repeat if possibles.count then if aThing.char[1] = "0" then return possibles[possibles.count] else return possibles[1] else return #NAN end if end on decimalToBinary aNum return ConvertBase (aNum, 10, 2) end on binaryToDec aStr return ConvertBase (aStr, 2, 10) end on decimalToHex decimal return ConvertBase (decimal, 10, 16) end on hexToDecimal hex return ConvertBase (hex, 16, 10) end on ConvertBase (inNum, oldBase, newBase, userLower) -- Using lingo posted by Bruce Epstein (http://zeusprod.com/) on Lingo-L if (newBase.ilk <> #Integer) OR (newBase < 1) then put "invalid base" && newBase return 0 end if if userLower then digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"] else digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"] -- No need to perform conversion inputString = string (inNum) if inputString starts "0x" AND oldBase = 16 then delete inputString.char[1..2] if newBase = oldBase then return inNum strLength = length (inputString) if oldBase = 10 then -- Ensure that input is an integer, if using base 10 if not integerP (inNum) then put "Input is not a decimal number" return VOID end if base10sum = value (inNum) if base10Sum < 0 then put "Absolute value will be used" base10Sum = abs (base10sum) end if else -- Convert the input number to base 10 base10sum = 0 -- Convert each digit in turn repeat with x = strLength down to 1 thisChar = char x of inputString thisASCII = charToNum(thisChar) -- Convert lower case letters to upper case if thisASCII >= 97 and thisASCII <= 122 then thisChar = numToChar (thisASCII - 32) end if thisDigit = getOne (digits, thisChar) - 1 if thisDigit >= oldBase or thisDigit < 0 then put "invalid digit" return VOID end if base10sum = base10sum + integer (power (oldBase, strLength - x) * thisDigit) end repeat end if -- We've converted it to base 10 if newBase = 10 then return integer(base10sum) else -- Convert it from, say, decimal to hex, if necessary working = base10sum outNum = EMPTY repeat while TRUE remainder = working mod newBase put getAt (digits, remainder+1) before outNum if working < newBase then exit repeat end if working = working / newBase end repeat -- Non-decimal values returned as a string return outNum end if end