Converting a decimal value to base 42

Introduction
This article will provide an example of how to convert a decimal value to a base 42 string. A base 42 string is useful for compressing a number into a smaller string. The following table provides a translation between decimal and base 42.

Base 10      Base 42                 Base 10        Base 42 1		$ 			22		H 2		%			23		I 3		-			24		J 4		0			25		K 5		1			26		L 6		2			27		M 7		3			28		N 8		4			29		O 9		5			30		P 10		6			31		Q 11		7			32		R 12		8			33		S 13		9			34		T 14		@			35		U 15		A			36		V 16		B			37		W 17		C			38		X 18		D			39		Y 19		E			40		Z 20		F			41		_ 21		G			42		!

Example
The following is an example of how to convert a decimal number to a base 42 string and visa-versa.

USER>Write ##class(Utils.Convert).Base(6234900123456700, 10, 42, "!$%-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_") A9XUCDBHK6

USER>Write ##class(Utils.Convert).Base("A9XUCDBHK6", 42, 10, "!$%-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_") 6234900123456700

Code
The code to achieve the base conversion is as follows.

Class Utils.Convert [ Abstract ] {

ClassMethod Base10ToN(pNum As %Integer = "", pBase As %Integer = "", pBaseStr As %String = "", pPos As %Integer = 0) As %String {	If pNum=0 Quit "" Set str=..Base10ToN(pNum\pBase, pBase, pBaseStr, pPos+1) Quit str_$Extract(pBaseStr, pNum#pBase+1) }

ClassMethod BaseNTo10(pStr As %String = "", pBase As %Integer = "", pBaseStr As %String = "", pPos As %Integer = 0) As %Integer {	If pStr="" Quit 0 Set num=..BaseNTo10($Extract(pStr, 1, *-1), pBase, pBaseStr, pPos+1) Set dec=$Find(pBaseStr, $Extract(pStr, *))-2 Quit num+(dec*(pBase**pPos)) }

ClassMethod Base(pStr As %String = "", pFrom As %Integer = 10, pTo As %Integer = 10, pBaseStr As %String = "", pLen As %Integer = 0) As %String {	// some initialisation If pBaseStr="" Set pBaseStr="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // check input values If pFrom=10 Set pStr=$Number(pStr, "i", 0) If pStr="" Quit "" Set pFrom=$Number(pFrom, "i", 2, 94) If pFrom="" Quit "" Set pTo=$Number(pTo, "i", 2, 94) If pTo="" Quit "" Set pLen=$Number(pLen, "i", 0, 32) If pLen="" Quit "" // does base number exceed base string? If pFrom>$Length(pBaseStr) Quit "" If pTo>$Length(pBaseStr) Quit "" // allow for upper/lowercase values If pTo=10 { If $Match(pStr, "^[0-9a-z]+$"), $Match($Extract(pBaseStr, 1, pFrom), "^[0-9A-Z]+$") { Set pStr=$ZConvert(pStr, "U") }		If $Match(pStr, "^[0-9A-Z]+$"), $Match($Extract(pBaseStr, 1, pFrom), "^[0-9a-z]+$") { Set pStr=$ZConvert(pStr, "L") }	}	// do the conversion If pFrom=pTo { Set pStr=pStr } ElseIf pFrom=10 { Set pStr=..Base10ToN($Select(pStr=0: "", 1: pStr), pTo, pBaseStr) } ElseIf pTo=10 { Set pStr=..BaseNTo10(pStr, pFrom, pBaseStr) } Else { Set pStr=..Base10ToN(..BaseNTo10(pStr, pFrom, pBaseStr), pTo, pBaseStr) }	// return value If pLen=0 Quit pStr If pTo'=10 Quit ..Pad(pStr, pLen, $Extract(pBaseStr)) Quit ..Pad(pStr, pLen) }

ClassMethod Pad(pNum As %Integer, pLen As %Integer, pZero As %String = 0) As %String [ Private ] {	If $Length(pNum)>pLen Quit pNum Quit $Translate($Justify(pNum, pLen), " ", pZero) }

}