'
' General functions
' version 0.1
' (c) 2009 Stefan Wurzinger
'

#Ifndef CRLF
#define CRLF chr(13,10)
#endif
#ifndef NULL
#define NULL (0)
#EndIf
#Ifndef max
#define max(a,b) iif((a)>(b), a, b)
#endif
#ifndef min
#define min(a,b) iif((a)<(b), a, b)
#EndIf

#Ifdef InStrRev
#Undef InStrRev
#endif


#Include Once "crt/stdio.bi"


Declare Function LPad OverLoad (Daten As String, PadZeichen As String, Length As Integer) As String
Declare Function LPad(Daten As String, PadZeichen As Integer, Length As Integer) As String

Declare Function RPad OverLoad (Daten As String, PadZeichen As String, Length As Integer) As String
Declare Function RPad(Daten As String, PadZeichen As Integer, Length As Integer) As String

Declare Function NullString(ByRef tmpStr As String) As String
Declare Function StrRev (ByRef tmpStr As String) As String

Declare Function InStrRev(ByRef searchstr As String, ByRef searchpat As String, ByVal startpos As UInteger = 0) As UInteger
Declare Function ReplaceAll(ByRef Daten As String, ByVal SearchPat As String, ByVal Replacement As String) As String

Declare Function GetTempFile OverLoad () As String
Declare Function GetTempFile(ByRef file As String) As String

Declare Function WriteInFile (daten As String, file As String) As Integer

Declare Function IsNumeric(ByRef Daten As String) As Integer
Declare Function CountOcc(ByRef Daten As String, ByRef SearchPat As String) As Integer
Declare Function FindOcc (ByRef Daten As String, ByRef SearchPat As String, ByRef OccNo As Integer) As Integer




Function LPad(Daten As String, PadZeichen As String, Length As Integer) As String
	Return LPad(Daten, Asc(PadZeichen), Length)
End Function

Function LPad(Daten As String, PadZeichen As Integer, Length As Integer) As String
	If Len(Daten) = Length Then Return Daten
	If Len(Daten) > Length Then Return Left(Daten, Length)
	Return Daten & String(Length - Len(Daten), PadZeichen)
End Function

Function RPad(Daten As String, PadZeichen As String, Length As Integer) As String
	Return RPad(Daten, Asc(PadZeichen), Length)
End Function

Function RPad(Daten As String, PadZeichen As Integer, Length As Integer) As String
	If Len(Daten) = Length Then Return Daten
	If Len(Daten) > Length Then Return Left(Daten, Length)
	Return String(Length - Len(Daten), PadZeichen) & Daten
End Function

Function NullString (ByRef tmpStr As String) As String
    Dim NullPos As Integer
    NullPos = InStr(tmpStr, Chr(0))
    'NullPos = InStrRev2(tmpStr, chr(0))
    If NullPos = 0 Then
        Return tmpStr
    Else
        Return Left(tmpStr, NullPos-1)
    End If
End Function


Function StrRev (ByRef tmpStr As String) As String
    Dim q As Integer
    Dim e As String
    For q = 1 To Len(tmpStr)
        e = Mid(tmpStr,q,1)+e
    Next
    Return e
End Function

Function InStrRev(ByRef searchstr As String, ByRef searchpat As String, ByVal startpos As UInteger = 0) As UInteger
    Dim SStrPtr As Integer = CInt(StrPtr(searchstr))
    Dim SPatPtr As Integer = CInt(StrPtr(searchpat))
    Dim SStrLen As Integer = Len(searchstr)
    Dim SPatLen As Integer = Len(searchpat)
    If startpos > 0 Then SStrLen = startpos + SPatLen - 1
    If SStrLen > Len(searchstr) Then SStrLen = Len(searchstr)
    If SPatLen > SStrLen Then Return 0
    Asm
        std                         'Rückwärts suchen
        mov ecx, [SStrLen]          'Länge des Strings
        mov ebx, [SPatLen]          'Länge des Suchstrings
        mov edi, [SStrPtr]          'Offset des Strings
        mov esi, [SPatPtr]          'Offset des Suchstrings
        Add edi, ecx                'Ans Ende des Strings springen
        Sub edi, ebx                'Vom Ende die Länge des Suchstrings zurücksprigen
        mov al,  [esi]              'Erstes Zeichen überprüfen
      instrrev_continue:  
        repne scasb
        jz instrrev_foundfirst
        jcxz instrrev_notfound
      instrrev_foundfirst:
        push ecx
        push edi
        mov ecx, ebx
        Add edi, ebx
        mov esi, [SPatPtr]
        Add esi, ebx
        dec esi
        repe cmpsb
        jz instrrev_found
        pop edi
        pop ecx
        jmp instrrev_continue
      instrrev_found:
        pop edi
        pop ecx
        mov edx, edi
        Sub edx, [SStrPtr]
        Add edx, 2
        mov [Function], edx
      instrrev_notfound:
        cld
    End Asm
End Function


Function GetTempFile() As String
	Return GetTempFile("")
End Function

Function GetTempFile(file As String) As String
	Dim q As Integer
	Dim w As Integer
	Dim DateiName As String
	Dim Datei As String
	Dim DateiExt As String
	Dim Temp As String
	Dim Zufall As Integer
	q=InStrRev(file, ".")
	If q <> 0 Then
		Datei = Left(file, q-1)
		DateiExt = Mid(file, q)
	Else
		Datei = file
		DateiExt = ".tmp"
	EndIf
	If Datei = "" Then
		Datei = "~TMP_"
		DateiExt = ".tmp"
	EndIf
	For q=1 To 1000
		DateiName = Datei
		For q = -2 To CInt(q/15)
			Zufall = Int(Rnd * 26+65)
			DateiName = DateiName & Chr(Zufall)
		Next
		DateiName = DateiName & DateiExt
		If Dir(DateiName) = "" Then Return DateiName
	Next
End Function

Function WriteInFile (daten As String, file As String) As Integer
	
	Dim f as FILE ptr
	f = fopen(StrPtr(file), @"wb")
	If f = NULL Then Return 30
	If fwrite(StrPtr(daten), Len(daten), 1, f) <> 1 Then Return 30
	If ferror(f) Then Return 30
	If fclose(f) Then Return 30
		
	'Dim TempDatei As String
	'Dim hDatei As HANDLE
	'Dim Length As Integer
	'
	'TempDatei = GetTempFile(file)
	'If CopyFile(StrPtr(file), StrPtr(TempDatei), FALSE) = 0 Then Return 30
	'hDatei = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
	'If hDatei = 0 Then Kill TempDatei: Return 30
	'If WriteFile(hDatei, StrPtr(daten), Len(daten), @Length, 0) = 0 Then CloseHandle(hDatei): Kill TempDatei: Return 30
	'If Length <> Len(daten) Then CloseHandle(hDatei): Kill TempDatei: Return 30
	'CloseHandle(hDatei)
	'Kill TempDatei
	
	Return 0
End Function


Function ReplaceAll(ByRef Daten As String, ByVal SearchPat As String, ByVal ReplacementStr As String) As String
	Dim q As Integer = 1
	
	Do
		q=InStr(q, Daten, SearchPat)
		If q=0 Then Exit Do
		daten = Left(Daten, q-1) & ReplacementStr & Mid(Daten, q+Len(SearchPat))
		q+=Len(ReplacementStr)
	Loop
	
	Return daten
End Function


Function CountOcc(ByRef Daten As String, ByRef SearchPat As String) As Integer
	Dim q As Integer = 1
	Dim cnt As Integer = 0
	Do
		q = InStr(q, Daten, SearchPat)
		If q = 0 Then Exit Do
		cnt += 1
		q += Len(SearchPat)
	Loop
	
	Return cnt
End Function

Function FindOcc (ByRef Daten As String, ByRef SearchPat As String, ByRef OccNo As Integer) As Integer
	Dim q As Integer = 1
	Dim cnt As Integer = 0
	Do
		q = InStr(q, Daten, SearchPat)
		If q = 0 Then Return 0
		cnt += 1
		If cnt = OccNo Then Return q
		q += Len(SearchPat)
	Loop
	
	Return cnt
End Function


Function IsNumeric(ByRef Daten As String) As Integer
	
	'TODO!!
	
	Return -1
	'Dim tmpStr As String = Trim(Daten)
	'Dim aHex As Integer = 0
	'Dim aBin As Integer = 0
	'Dim aOct As Integer = 0
	'If Left(tmpStr, 1) = "+" Or Left(tmpStr, 1) = "-" Then tmpStr = Mid(tmpStr, 2)
	'If Left(tmpStr, 1) = "&" Then
	'	If UCase(Mid(tmpStr, 2, 1)) = "H" Then aHex = 1
	'	If UCase(Mid(tmpStr, 2, 1)) = "B" Then aBin = 1
	'	tmpStr = Mid(tmpStr, 3)
	'EndIf
	'If Right(tmpStr, 1) = "!" Or Right(tmpStr, 1) = "#" Or UCase(Right(tmpStr, 1)) = "L" 
	'For q As Integer = start To Len(tmpStr)
	'	
	'Next
End Function
