Page 1 of 2

Help needed on web service response

Posted: Wed Feb 22, 2012 9:26 am
by Project Mayu
Purebasic 4.60 x64 and x86
1. The following code does not work if I compile as Unicode

2. Does anyone have a conversion from Dot Net Ticks to Purebasic DateTime

For convenience the response is hard coded into the sample

Code: Select all

Declare.l SplitPath(Array r.s(1), text.s, separator.s = ",")
Declare.s XML_GetValue(path.s,xml.s)

Procedure.s XML_GetValue(path.s,xml.s)
  result.s=""
  Dim p.s(0)
  If SplitPath(p(),path,"\")>0
    xmlPos.i=0
    If CatchXML(1,@xml,Len(xml),#PB_XML_StreamStart,#PB_UTF8)
      *xmlHandle = RootXMLNode(1)
      If *xmlHandle <> 0
        *rootnode=ChildXMLNode(*xmlHandle)
        If *rootnode <> 0
          If GetXMLNodeName(*rootnode)= p(xmlPos)
            xmlPos = xmlPos + 1
            If xmlPos > ArraySize(p())
              result = GetXMLNodeText(*rootnode)
            Else
              *childnode=ChildXMLNode(*rootnode)
              While *childnode <> 0
                If GetXMLNodeName(*childnode) = p(xmlPos)
                  xmlPos = xmlPos + 1
                  If xmlPos>ArraySize(p())
                    result = GetXMLNodeText(*childnode)
                    Break
                  Else
                    *childnode=ChildXMLNode(*childnode)
                  EndIf
                Else
                  *childnode=NextXMLNode(*childnode)
                EndIf
              Wend
            EndIf
          EndIf
        EndIf
      EndIf
    EndIf
  EndIf
  ProcedureReturn result
EndProcedure

Procedure.l SplitPath(Array r.s(1), text.s, separator.s = ",") ; String to Array
 
  Protected index.l, size.l = CountString(text, separator)
 
  ReDim r.s(size)
 
  For index = 0 To size
    r(index) = StringField(text, index + 1, separator)
  Next
 
  ProcedureReturn size
 
EndProcedure

testXML.s = "<s:Envelope xmlns:s="+Chr(34)+"http://schemas.xmlsoap.org/soap/envelope/"+Chr(34)+"><s:Header><ActivityId CorrelationId="+Chr(34)+"680096f1-7a4c-4c73-87ef-b82fdd4297c9"+Chr(34)+" xmlns="+Chr(34)+"http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics"+Chr(34)+">0a31f79a-80fe-43d2-8248-f989616bdd2d</ActivityId></s:Header><s:Body><DevicePingResponse xmlns="+Chr(34)+"http://tempuri.org/"+Chr(34)+"><DevicePingResult z:Id="+Chr(34)+"i1"+Chr(34)+" xmlns:a="+Chr(34)+"http://schemas.datacontract.org/2004/07/NetcardServer.Server.DataContracts"+Chr(34)+" xmlns:i="+Chr(34)+"http://www.w3.org/2001/XMLSchema-instance"+Chr(34)+" xmlns:z="+Chr(34)+"http://schemas.microsoft.com/2003/10/Serialization/"+Chr(34)+"><a:Ticks>634654947847413260</a:Ticks></DevicePingResult></DevicePingResponse></s:Body></s:Envelope>"
Ticks.s = XML_GetValue("s:Envelope\s:Body\DevicePingResponse\DevicePingResult\a:Ticks",testXML)
MessageRequester("",Ticks)

Re: Help needed on web service response

Posted: Wed Feb 22, 2012 2:28 pm
by Little John
Project Mayu wrote:2. Does anyone have a conversion from Dot Net Ticks to Purebasic DateTime
[u][url]http://www.purebasic.com/documentation/date/index.html[/url][/u] wrote:The Date library allows for the manipulation of Date and Time from 1970 up to 2038 using the unix method (i.e. the number of seconds elapsed since the 1st of January 1970).

Note: supported date/time values are 1970-01-01, 00:00:00 for the minimum and 2038-01-19, 03:14:07 for the maximum.
[u][url]http://stackoverflow.com/questions/2761498/convert-unix-timestamp-to-net-datetime-ticks-in-unmanaged-code-without-using[/url][/u] wrote:[...]
number of ticks since that the Unix Epoc starts at (which is 621,355,968,000,000,000)
[...]
ticks per second (which is 10,000,000)
This leads to the following PB code:

Code: Select all

#TICKS_UNTIL_1970_01_01 = 621355968000000000
#TICKS_PER_SECOND = 10000000

Macro PBtime2DotNetTicks (_seconds_)
   (_seconds_*#TICKS_PER_SECOND + #TICKS_UNTIL_1970_01_01)
EndMacro

Macro DotNetTicks2PBtime (_ticks_)
   Int((_ticks_-#TICKS_UNTIL_1970_01_01)/#TICKS_PER_SECOND)
EndMacro


;-- Demo
Define now_pb.i, now_ticks.q

now_pb = Date()
Debug now_pb
now_ticks = PBtime2DotNetTicks(now_pb)
Debug now_ticks
now_pb = DotNetTicks2PBtime(now_ticks)
Debug now_pb
Regards, Little John

Re: Help needed on web service response

Posted: Thu Feb 23, 2012 7:39 am
by Project Mayu
change
now_pb.i
to
now_pb.d

and it works on x64

Thanks Little John

Now just need to figure out the Unicode problem

Re: Help needed on web service response

Posted: Thu Feb 23, 2012 1:00 pm
by Little John
Hi, you are welcome!
Project Mayu wrote:change
now_pb.i
to
now_pb.d

and it works on x64
Yes, I only have an x86 system, and so unfortunately I couldn't test my code on x64.

Can you please tell me what the problem is with declaring now_pb as integer on x64?
Currently I can't imagine any source of a problem. And .d denotes a double-precision floating point variable. I can't see any reason for using that, since PB's Date() function as well as my macros return whole numbers, but not floating point values.

Regards, Little John

Re: Help needed on web service response

Posted: Thu Feb 23, 2012 1:21 pm
by Kiffi
Project Mayu wrote:Purebasic 4.60 x64 and x86
1. The following code does not work if I compile as Unicode

Code: Select all

Procedure.s GetValue(NodeName.s, Xml.s)
  
  Protected P1, P2
  
  P1 = FindString(Xml, "<" + NodeName + ">")
  If P1 
    P1 + Len("<" + NodeName + ">")
    P2 = FindString(Xml, "</" + NodeName + ">")
    If P2
      ProcedureReturn Mid(Xml, P1, P2-P1)
    EndIf
  EndIf
  
EndProcedure

[...]

Ticks.s = GetValue("a:Ticks",testXML)
;-)

Greetings ... Kiffi

Re: Help needed on web service response

Posted: Thu Feb 23, 2012 9:28 pm
by charvista
@Little John
I have a x64 machine and I cannot explain either why a double solved the problem.
The Debug of your initial solution was as follows:
1330032205
13300321910899840
-60805564608
Cheers

EDIT:
As I have a x64 computer, I cannot see what happens on the x86, when I use integers with quad sizes. The integers became negative values and very different looking.....

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 1:50 am
by Project Mayu
should not q and d and l output the same result, since they are all 64 bit? Help does not say there is any difference.

Sorry Kiffi but your example is a workaround, and would fail if the same name was used on different path levels.
I am looking to understand why my code, compiled as unicode, fails, and how to fix my code so that it works.

The code I am working on is a sample web service call, to be used as a template for future use.

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 2:36 am
by Little John
Hi charvista,

thanks for the info.

//edit:
In my above code, IntQ() was wrong. I replaced it with Int().
Can you please try again?

The output here on x86 is:
1330050867
634656476670000000
1330050867
Regards, Little John

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 2:44 am
by Project Mayu
Here is the list of types tested
i failed
l failed
q failed
f pass
d pass

And as I am relatively New to Purebasic I need to know why?

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 2:49 am
by Little John
Project Mayu:
I just edited my previous message. ;-)

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 2:58 am
by Project Mayu
With Int()
i fail
l fail
q fail
f pass
d pass

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 6:46 am
by charvista
Hi Little John
In my above code, IntQ() was wrong. I replaced it with Int().
Can you please try again?
I also removed the Q myself and it gave the same negative result (-60805564608) on the x64 processor. It is still a mystery that the Double worked correctly that Project Mayu discovered by accident...
Could it be because there was a division in the formula???

~EDIT:
I think that the values are too large. From a previous experience, when a value has more than 15 significant digits, unexpected results can occur, and #TICKS_UNTIL_1970_01_01 has 18 significant digits! So, maybe remove some zeroes?

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 10:58 am
by Little John
Hi!
charvista wrote:I think that the values are too large. From a previous experience, when a value has more than 15 significant digits, unexpected results can occur, and #TICKS_UNTIL_1970_01_01 has 18 significant digits! So, maybe remove some zeroes?
Yes, the value of #TICKS_UNTIL_1970_01_01 is rather big. But it's smaller than the maximum allowed number for Quads. And on my x86 system I get correct results (I just checked the results with a bignumber program, that can handle numbers of arbitrary size). So I have no clue why it doesn't work correctly on x64.

However, it just occurred to me that the Macros can also be written with a constant #SECONDS_UNTIL_1970_01_01, which of course is 10000000 times smaller than #TICKS_UNTIL_1970_01_01. :-)

Code: Select all

#SECONDS_UNTIL_1970_01_01 = 62135596800
#TICKS_PER_SECOND = 10000000

Macro PBtime2DotNetTicks (_seconds_)
   ((#SECONDS_UNTIL_1970_01_01+_seconds_) * #TICKS_PER_SECOND)
EndMacro

Macro DotNetTicks2PBtime (_ticks_)
   (Int(_ticks_/#TICKS_PER_SECOND) - #SECONDS_UNTIL_1970_01_01)
EndMacro


;-- Demo
Define now_pb.l, now_ticks.q

now_pb = Date()
Debug now_pb
now_ticks = PBtime2DotNetTicks(now_pb)
Debug now_ticks
now_pb = DotNetTicks2PBtime(now_ticks)
Debug now_pb
Does this work on your x86 systems :?:

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 1:42 pm
by Little John
Project Mayu wrote:1. The following code does not work if I compile as Unicode
Replace
If CatchXML(1,@xml,Len(xml),#PB_XML_StreamStart,#PB_UTF8)
with
If CatchXML(1,@xml,StringByteLength(xml),#PB_XML_StreamStart,#PB_UTF8)
That works in both ASCII and Unicode mode.
As with the other issue, I only could test it on Win XP x86, but I hope at least this suggestion will work on x64 as well. :-)

Regards, Little John

Re: Help needed on web service response

Posted: Fri Feb 24, 2012 3:17 pm
by Project Mayu
1. Thanks Little John, it did not occur to me to use a different length function for unicode.

2. I find myself changing the ticks to d, as the ticks are now wrong, with q it looked like the number was half the amount required.

#SECONDS_UNTIL_1970_01_01 = 62135596800
#TICKS_PER_SECOND = 10000000

Macro PBtime2DotNetTicks (_seconds_)
((#SECONDS_UNTIL_1970_01_01+_seconds_) * #TICKS_PER_SECOND)
EndMacro

Macro DotNetTicks2PBtime (_ticks_)
(Int(_ticks_/#TICKS_PER_SECOND) - #SECONDS_UNTIL_1970_01_01)
EndMacro


;-- Demo
Define now_pb.l, now_ticks.d

now_pb = Date()
Debug now_pb
now_ticks = PBtime2DotNetTicks(now_pb)
Debug now_ticks
now_pb = DotNetTicks2PBtime(now_ticks)
Debug now_pb
Debug FormatDate("Y=%yyyy, M= %mm, D=%dd %hh:%ii:%ss", now_pb)