Imports System.Globalization

Module StringFunctions
	Friend Function DetToUpper(ByVal T As String) As String
		DetToUpper = T.ToUpper(New CultureInfo("en-US", False))
	End Function
	
	'Deterministic conversion from string to double
	Friend Function StringToDouble(ByRef T As String) As Double
		Dim I As Integer
		Dim Negated As Boolean
		Dim ReachedDecimal As Boolean
		Dim DigitDivider As Integer
		Dim DigitDividerF As Double
		Dim DigitValue As Double
		Dim CurrentChar As Char
		StringToDouble = 0
		DigitDivider = 1
		For I = 0 To Len(T) - 1
			CurrentChar = T(I)
			If CurrentChar = "-"c Or CurrentChar = "~"c Then
				Negated = Not (Negated)
			ElseIf CurrentChar >= "0"c And CurrentChar <= "9"c Then
				DigitValue = AscW(CurrentChar) - AscW("0"c)
				If ReachedDecimal Then
					DigitDivider = DigitDivider * 10
					DigitDividerF = DigitDivider
					StringToDouble = StringToDouble + (DigitValue / DigitDividerF)
				Else
					StringToDouble = (StringToDouble * 10) + DigitValue
				End If
			ElseIf CurrentChar = ","c Or CurrentChar = "."c Then
				ReachedDecimal = True
			End If
		Next I
		If Negated Then
			StringToDouble = -StringToDouble
		End If
	End Function
	
	Friend Function RemoveRedundantZeroes(T As String) As String
		Dim I As Integer
		Dim FirstDecimal As Integer
		Dim LastValueDigit As Integer
		RemoveRedundantZeroes = ""
		FirstDecimal = -1
		For I = 0 to Len(T) - 1
			Select Case T(I)
			Case ","c, "."c
				FirstDecimal = I
				Exit For
			End Select
		Next I
		If FirstDecimal > -1 Then
			LastValueDigit = -1
			For I = Len(T) - 1 to FirstDecimal + 1 Step -1
				Select Case T(I)
				Case "1"c, "2"c, "3"c, "4"c, "5"c, "6"c, "7"c, "8"c, "9"c
					LastValueDigit = I
					Exit for
				End Select
			Next I
			If LastValueDigit > -1 Then
				RemoveRedundantZeroes = Mid(T, 1, LastValueDigit + 1)
			Else
				RemoveRedundantZeroes = Mid(T, 1, FirstDecimal)
			End If
		End If
	End Function
	
	'Deterministic conversion from integer to string
	Friend Function DoubleToString(ByVal D As Double, ByVal Decimals As Integer) As String
		If D < 0 Then
			DoubleToString = "-" & DoubleToString(System.Math.Abs(D), Decimals)
		Else
			Dim Rounded As Double
			Dim I As Integer
			Dim Whole As Long
			Dim Fraction As Double
			Rounded = System.Math.Round(D, Decimals)
			Whole = System.Math.Truncate(Rounded) 'Get whole integers
			Fraction = Rounded - Whole 'Get the fraction
			DoubleToString = IntegerToString(Whole) & "."
			For I = 1 to Decimals
				DoubleToString = DoubleToString & ChrW(AscW("0"c) + (System.Math.Truncate((Fraction * (10 ^ I)) mod 10)))
			Next
			DoubleToString = RemoveRedundantZeroes(DoubleToString)
		End If
	End Function
	
	'Deterministic conversion from string to integer
	Friend Function StringToInteger(ByRef T As String) As Integer
		Dim I As Integer
		Dim Negated As Boolean
		Dim DigitValue As Double
		Dim CurrentChar As Char
		StringToInteger = 0
		For I = 0 To Len(T) - 1
			CurrentChar = T(I)
			If CurrentChar = "-"c Or CurrentChar = "~"c Then
				Negated = Not (Negated)
			ElseIf CurrentChar >= "0"c And CurrentChar <= "9"c Then
				DigitValue = AscW(CurrentChar) - AscW("0"c)
				StringToInteger = (StringToInteger * 10) + DigitValue
			ElseIf CurrentChar = ","c Or CurrentChar = "."c Then
				Exit function 'Skip everything after decimals
			End If
		Next I
		If Negated Then
			StringToInteger = -StringToInteger
		End If
	End Function
	
	'Deterministic conversion from integer to string
	Friend Function IntegerToString(ByVal I As Integer) As String
		If I < 0 Then
			IntegerToString = "-" & -I
		Else
			IntegerToString = I
		End If
	End Function
	
	Friend Function ReplaceChar(ByVal T As String, ByRef OldChar As Char, ByRef NewChar As Char) As String
		Dim CurrentChar As Char
		ReplaceChar = ""
		For Each CurrentChar In T
			If CurrentChar = OldChar Then
				ReplaceChar = ReplaceChar & NewChar
			Else
				ReplaceChar = ReplaceChar & CurrentChar
			End If
		Next
	End Function
	
	'Returns the index of the first C in T using base 0
	'-1 is returned if there is no C in T
	Friend Function FindFirstChar(ByVal T As String, ByVal C As Char) As Integer
		Dim I As Integer
		For I = 0 To Len(T) - 1
			If T(I) = C Then
				Return I
			End If
		Next I
		Return -1
	End Function
	
	'Returns the index of the last C in T using base 0
	'-1 is returned if there is no C in T
	Friend Function FindLastChar(ByVal T As String, ByVal C As Char) As Integer
		Dim I As Integer
		For I = Len(T) - 1 to 0 Step -1
			If T(I) = C Then
				Return I
			End If
		Next I
		Return -1
	End Function
	
	'Returns the index of the slash C in T using base 0
	'-1 is returned if there is no slash in T
	Friend Function FindLastSlash(ByVal T As String) As Integer
		Dim I As Integer
		For I = Len(T) - 1 to 0 Step -1
			If T(I) = "/"c or T(I) = "\"c Then
				Return I
			End If
		Next I
		Return -1
	End Function
	
	'Returns everything before the last slash
	'Nothing is returned if there is no slash
	Friend Function FolderPathFromFileName(ByVal FileName As String) As String
		Dim LastSlashIndex As Integer
		LastSlashIndex = FindLastSlash(FileName)
		If LastSlashIndex = -1 Then
			Return ""
		Else
			Return Mid(FileName, 1, LastSlashIndex)
		End If
	End Function
	
	'Returns everything before the last dot
	'FileName is returned if there is no dot
	Friend Function ExtensionlessFileName(ByVal FileName As String) As String
		Dim LastDotIndex As Integer
		LastDotIndex = FindLastChar(FileName,"."c)
		If LastDotIndex = -1 Then
			Return FileName
		Else
			Return Mid(FileName, 1, LastDotIndex)
		End If
	End Function
	
	'Returns after before the last slash
	'FileName is returned if there is no slash
	Friend Function FileNameWithoutPath(ByVal FileName As String) As String
		Dim LastSlashIndex As Integer
		LastSlashIndex = FindLastSlash(FileName)
		If LastSlashIndex = -1 Then
			Return FileName
		Else
			Return Mid(FileName, LastSlashIndex + 2, Len(FileName) - (LastSlashIndex + 1))
		End If
	End Function
End Module
