Code: Select all
; Author: Daniel Brall
; Date: 25.02.2007
; Descr.: Money class for formatting and calculating money
EnableExplicit
Interface IMoney
setValue.l(*money.IMoney)
; set it to a string value:
setValueString.l(String.s, SymbolCents.s = ",", SymbolThousands.s = ".")
; Convert to string:
getValueString.s(SymbolCents.s = ",", SymbolThousands.s = ".")
; set it to null:
null.l()
; Mathematicsfunctions source (subtract or divide from) = *this, dest = *money
add.l(*money.IMoney)
sub.l(*money.IMoney)
mul.l(*money.IMoney)
div.l(*money.IMoney)
percentage.l(percent.f)
; Set and get the amount of numbers before comma:
setCommaPosition.l(index.l)
getCommaPosition.l()
; Release
release.l()
EndInterface
Structure SMoney
*VTable
; Functions:
*Functions[SizeOf(IMoney)/4]
; Variables:
Value.q
Comma.l
EndStructure
; Private functions
Procedure.s IMoneyPrivate_InsertString(String.s, Index.l, Insert.s)
Protected Result.s
Result = Left(String, Index) + Insert + Right(String, Len(String) - Index)
ProcedureReturn Result
EndProcedure
Procedure.s IMoneyPrivate_MakeString(qValue.q, Comma.l, SymbolCents.s = ",", SymbolThousands.s = ".")
Protected Result.s, Value.s, k.l
Value.s = StrQ(qValue)
If Len(Value) <= Comma
Value = RSet(Value, Comma+1, "0")
EndIf
Result = Value
For k = 1 To Len(Value) - Comma - 1
If k % 3 = 0
Result = IMoneyPrivate_InsertString(Result, Len(Value) - (k + Comma), SymbolThousands)
EndIf
Next k
If Comma > 0
Result = IMoneyPrivate_InsertString(Result, Len(Result) - Comma, SymbolCents)
EndIf
Value = Result
For k = Len(Value) - Comma + 1 To Len(Value) - 1
If Int(k - (Len(Value) - Comma)) % 3 = 0
Result = IMoneyPrivate_InsertString(Result, k + (k / 3) - 1, SymbolThousands)
EndIf
Next k
ProcedureReturn Result
EndProcedure
; Public functions
Procedure.l IMoney_setValue(*IThis.IMoney, *money.IMoney)
Protected *SThis.SMoney, *SMoney.SMoney
*SThis = *IThis
*SMoney = *money
If *money
*SThis\Value = *SMoney\Value
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.l IMoney_setValueString(*IThis.IMoney, String.s, SymbolCents.s = ",", SymbolThousands.s = ".")
Protected *SThis.SMoney
*SThis = *IThis
String = RemoveString(String, SymbolCents)
String = RemoveString(String, SymbolThousands)
*SThis\Value = ValQ(String)
ProcedureReturn 1
EndProcedure
Procedure.s IMoney_getValueString(*IThis.IMoney, SymbolCents.s = ",", SymbolThousands.s = ".")
Protected *SThis.SMoney
*SThis = *IThis
ProcedureReturn IMoneyPrivate_MakeString(*SThis\Value, *SThis\Comma, SymbolCents, SymbolThousands)
EndProcedure
Procedure.l IMoney_setValueQuad(*IThis.IMoney, value.q)
Protected *SThis.SMoney
*SThis = *IThis
*SThis\Value = value
EndProcedure
Procedure.q IMoney_getValueQuad(*IThis.IMoney)
Protected *SThis.SMoney
*SThis = *IThis
ProcedureReturn *SThis\Value
EndProcedure
Procedure.l IMoney_null(*IThis.IMoney)
Protected *SThis.SMoney
*SThis = *IThis
*SThis\Value = 0
ProcedureReturn 1
EndProcedure
Procedure.l IMoney_add(*IThis.IMoney, *money.IMoney)
Protected *SThis.SMoney, *SMoney.SMoney
*SThis = *IThis
*SMoney = *money
If *money
*SThis\Value + *SMoney\Value
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.l IMoney_sub(*IThis.IMoney, *money.IMoney)
Protected *SThis.SMoney, *SMoney.SMoney
*SThis = *IThis
*SMoney = *money
If *money
*SThis\Value - *SMoney\Value
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.l IMoney_mul(*IThis.IMoney, *money.IMoney)
Protected *SThis.SMoney, *SMoney.SMoney
*SThis = *IThis
*SMoney = *money
If *money
*SThis\Value * *SMoney\Value
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.l IMoney_div(*IThis.IMoney, *money.IMoney)
Protected *SThis.SMoney, *SMoney.SMoney
*SThis = *IThis
*SMoney = *money
If *money
*SThis\Value / *SMoney\Value
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.l IMoney_percentage(*IThis.IMoney, percent.f)
Protected *SThis.SMoney
*SThis = *IThis
*SThis\Value = Int(Round((percent / 100.0) * *SThis\Value, 1))
EndProcedure
Procedure.l IMoney_setCommaPosition(*IThis.IMoney, index.l)
Protected *SThis.SMoney
*SThis = *IThis
*SThis\Comma = index
ProcedureReturn 1
EndProcedure
Procedure.l IMoney_getCommaPosition(*IThis.IMoney)
Protected *SThis.SMoney
*SThis = *IThis
ProcedureReturn *SThis\Comma
EndProcedure
; Destructor and constructor:
Procedure IMoney_Dcon(*IThis.IMoney)
ProcedureReturn FreeMemory(*IThis)
EndProcedure
Procedure IMoney_Con()
Protected *Result.SMoney
*Result = AllocateMemory(SizeOf(SMoney))
CopyMemory(?IMoneyData, *Result + OffsetOf(SMoney\Functions), SizeOf(SMoney) - OffsetOf(SMoney\Functions))
*Result\VTable = *Result + OffsetOf(SMoney\Functions)
ProcedureReturn *Result
DataSection
IMoneyData:
; Functions:
Data.l @IMoney_setValue()
Data.l @IMoney_setValueString()
Data.l @IMoney_getValueString()
Data.l @IMoney_null()
Data.l @IMoney_add()
Data.l @IMoney_sub()
Data.l @IMoney_mul()
Data.l @IMoney_div()
Data.l @IMoney_percentage()
Data.l @IMoney_setCommaPosition()
Data.l @IMoney_getCommaPosition()
Data.l @IMoney_Dcon()
; Variables:
Data.q 0
Data.l 2
EndDataSection
EndProcedure
Define *Object1.IMoney, *Object2.IMoney
*Object1 = IMoney_Con()
*Object2 = IMoney_Con()
Debug "Setting the Object1 to 0.10:"
*Object1\setValueString("0.10", ".", "'")
Debug "Object1: " + *Object1\getValueString(".", "'")
Debug ""
Debug "Setting the Object2 to the value of Object1:"
*Object2\setValue(*Object1)
Debug "Object2: " + *Object2\getValueString(".", "'")
Debug ""
Debug "Adding Object1 to Object2"
*Object2\add(*Object1)
Debug "Object2: " + *Object2\getValueString(".", "'")
Debug "Subtracting Object1 from Object2"
*Object2\sub(*Object1)
Debug "Object2: " + *Object2\getValueString(".", "'")
Debug "40% of Object2:"
*Object2\percentage(40)
Debug "Object2: " + *Object2\getValueString(".", "'")
Debug "Setting the Object1 to 12'345.23:"
*Object1\setValueString("12'345.23", ".", "'")
Debug "Object1: " + *Object1\getValueString(".", "'")
Debug ""
Debug "Setting the commaposition to 6:"
*Object1\setCommaPosition(6)
Debug "Object1: " + *Object1\getValueString(".", "'")
Debug ""
Debug "Getting the commaposition:"
Debug *Object1\getCommaPosition()
Debug ""
*Object1\release()
*Object2\release()
But I don't know if it's buggy or such. I don't think a currency type should be implemented by default in any programming language. There are just the standard types which can be handled by the processor directly.