Page 1 of 1
Double to string, possible?
Posted: Sat Jun 11, 2005 12:23 pm
by Justin
i use this function to get huge filesizes,
Procedure GetFileSize64(file$, *fs.DOUBLE_)
hfile.l = CreateFile_(file$, 0, 0, #NULL, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, #NULL)
If hfile<>#INVALID_HANDLE_VALUE
*fs\l1 = GetFileSize_(hfile, @*fs\l2)
CloseHandle_(hfile)
ProcedureReturn *fs\l1
Else
ProcedureReturn #INVALID_FILE_SIZE
EndIf
EndProcedure
it is possible to turn the double into its string representation?, like
'2345645355332'
Posted: Sat Jun 11, 2005 3:12 pm
by MrMat
I knocked this up which may work:
Code: Select all
Procedure.s Multiply(string.s, mult.l, power.l)
answer.s = string
If power < 0
answer = "Power too small"
ElseIf mult < 1 Or mult > 10
answer = "Multiplier out of range"
ElseIf mult = 10
ext.s = Space(power)
ReplaceString(ext, " ", "0", 2)
answer = string + ext
ElseIf mult > 1 And power <> 0
For powloop = 1 To power
answer = ""
lenstr.l = Len(string)
carry.l = 0
For loopy = lenstr To 1 Step -1
value.l = Val(Mid(string, loopy, 1))
value * mult
value + carry
carry = value / 10
answer = Str(value % 10) + answer
Next
If carry <> 0
answer = Str(carry) + answer
EndIf
string = answer
Next
EndIf
ProcedureReturn answer
EndProcedure
Procedure.s Addition(str1.s, str2.s)
answer.s = ""
len1.l = Len(str1)
len2.l = Len(str2)
If len1 > len2
prefix.s = Space(len1-len2)
ReplaceString(prefix, " ", "0", 2)
str2 = prefix + str2
ElseIf len1 < len2
prefix.s = Space(len2-len1)
ReplaceString(prefix, " ", "0", 2)
str1 = prefix + str1
EndIf
carry.l = 0
For loopy = Len(str1) To 1 Step -1
value.l = Val(Mid(str1, loopy, 1)) + Val(Mid(str2, loopy, 1)) + carry
carry = value / 10
answer = Str(value % 10) + answer
Next
If carry <> 0
answer = Str(carry) + answer
EndIf
ProcedureReturn answer
EndProcedure
Procedure.s MemToStr(*mem, lenbytes.l)
string.s = "0"
For loopy = 0 To lenbytes - 1
value.l = PeekB(*mem + loopy) & $FF
string = Addition(string, Multiply(Str(value), 2, 8 * loopy))
Next
ProcedureReturn string
EndProcedure
#INVALID_FILE_SIZE = $FFFFFFFF
Procedure GetFileSize64(file$, *fs.LARGE_INTEGER)
hfile.l = CreateFile_(file$, 0, 0, #NULL, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, #NULL)
If hfile<>#INVALID_HANDLE_VALUE
*fs\lowpart = GetFileSize_(hfile, @*fs\highpart)
CloseHandle_(hfile)
ProcedureReturn *fs\lowpart
Else
ProcedureReturn #INVALID_FILE_SIZE
EndIf
EndProcedure
filename.s = OpenFileRequester("", "", "", 0)
If filename <> ""
GetFileSize64(filename, @fs.LARGE_INTEGER)
Debug(MemToStr(@fs, SizeOf(LARGE_INTEGER)))
EndIf
It's very inefficient and only briefly tested but it seems ok!
Posted: Sat Jun 11, 2005 7:04 pm
by Justin
it seems to work, i think there is an easier way using some variant arithmetic api calls, i'll post it if i get it to work. thanks
Posted: Sat Jun 11, 2005 8:07 pm
by MrMat
It looks like Pupil has written some far superior code to mine that does what you want:
viewtopic.php?t=5223
Posted: Sat Jun 11, 2005 9:22 pm
by jack
Justin wrote:Just a workaround to display filesizes >2gb as strings due to the lack of doubles
Code: Select all
#INVALID_FILE_SIZE = $FFFFFFFF
Structure DOUBLE_
l1.l
l2.l
EndStructure
Procedure GetFileSize64(file$, *fs.DOUBLE_)
hfile.l = CreateFile_(file$, #GENERIC_READ, 0, #NULL, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, #NULL)
If hfile<>#INVALID_HANDLE_VALUE
*fs\l1 = GetFileSize_(hfile, @*fs\l2)
CloseHandle_(hfile)
ProcedureReturn *fs\l1
Else
ProcedureReturn #INVALID_FILE_SIZE
EndIf
EndProcedure
Procedure.s GetFileSize64Str(file$)
If GetFileSize64(file$, @fs.DOUBLE_)<>#INVALID_FILE_SIZE
sz$ = Space(100)
If StrFormatByteSize64_(fs\l1, fs\l2, @sz$, 100)
ProcedureReturn sz$
Else
ProcedureReturn ""
EndIf
Else
ProcedureReturn ""
EndIf
EndProcedure
file$ = OpenFileRequester("", "", "", 0)
If file$
Debug GetFileSize64Str(file$)
EndIf
in Windows you can use msvcrt.dll, example.
Code: Select all
Structure DOUBLE_
l1.l
l2.l
EndStructure
y.DOUBLE_
b.s="2345645355332"
#LIB=0
OpenLibrary(#LIB,"msvcrt.dll")
y\l1=CallCFunction(#LIB,"_atoi64",b);convert string to I64, result in EAX,EDX
;y\l1 already has the value of EAX, so we are free to use the register EAX
;now store the value in EDX into y\l2
! lea eax,[v_y]
! mov dword [eax+4],edx ;y\l2=edx
a.s=Space(100)
#radix=10
;now convert 64bit integer back to string in a
CallCFunction(#LIB,"_ui64toa",y\l1,y\l2,a,#radix)
Debug a
CloseLibrary(#LIB)
Posted: Sun Jun 12, 2005 11:37 am
by Justin
Great, _ui64toa does what i need. the only problem is you need to use openlibrary(), there is some PB bug with api calls that use '_' , you can't use the dll importer. thanks
Edit: i think the bug comes from functions that have ansi/unicode versions
_ui64toa / _ui64tow
Posted: Sun Jun 12, 2005 1:54 pm
by jack
The solutions of MrMat or Pupil are probably the way to go, mine was more of a curiosity.
on that note you can use sprintf but your are limited to signed int64.
Code: Select all
Structure DOUBLE_
l1.l
l2.l
EndStructure
y.DOUBLE_
n.s="9223372036854775807" ;maximum positive integer
#LIB=0
OpenLibrary(#LIB,"msvcrt.dll")
y\l1=CallCFunction(#LIB,"_atoi64",n);convert string to I64, result in EAX,EDX
;y\l1 already has the value of EAX, so we are free to use the register EAX
;now store the value in EDX into y\l2
! lea eax,[v_y]
! mov dword [eax+4],edx ;y\l2=edx
;get the string length required by passing "0" where string argument should be.
StrLength.l=CallCFunction(#LIB,"sprintf",0,"%I64d",y\l1,y\l2)
a.s=Space(StrLength)
;now convert 64bit integer back to string in a
CallCFunction(#LIB,"sprintf",a,"%I64d",y\l1,y\l2)
;get the string length required by passing "0" where string argument should be.
StrLength=CallCFunction(#LIB,"sprintf",0,"%I64X",y\l1,y\l2)
b.s=Space(StrLength)
CallCFunction(#LIB,"sprintf",b,"%I64X",y\l1,y\l2)
Debug a
Debug b+" in hexadecimal"
CloseLibrary(#LIB)
Posted: Sun Jun 12, 2005 3:31 pm
by Justin
about the dll importer bug, maybe doesn't work because i think the function must be called in C style. using CallFunction() inside a procedure crashes, while CallCFunction() works
Posted: Mon Jun 13, 2005 12:43 pm
by jack
Justin wrote:about the dll importer bug, maybe doesn't work because i think the function must be called in C style. using CallFunction() inside a procedure crashes, while CallCFunction() works
yes, you are right, thanks for pointing it out.
I updated my 2 posts above, just in case someone decides to use that example.
Posted: Mon Jun 13, 2005 5:57 pm
by GedB
If it's for your own consumption then you can keep things simple by working in Hex.
Then you just need to use Hex() on the two longs and put the strings together.