Help needed on web service response

Just starting out? Need help? Post your questions and find answers here.
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Help needed on web service response

Post 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)
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post 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
Last edited by Little John on Fri Feb 24, 2012 2:45 am, edited 2 times in total.
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help needed on web service response

Post 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
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post 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
User avatar
Kiffi
Addict
Addict
Posts: 1485
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Help needed on web service response

Post 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
Hygge
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Help needed on web service response

Post 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.....
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help needed on web service response

Post 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.
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post 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
Last edited by Little John on Fri Feb 24, 2012 2:47 am, edited 1 time in total.
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help needed on web service response

Post 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?
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post by Little John »

Project Mayu:
I just edited my previous message. ;-)
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help needed on web service response

Post by Project Mayu »

With Int()
i fail
l fail
q fail
f pass
d pass
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Help needed on web service response

Post 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?
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post 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 :?:
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Help needed on web service response

Post 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
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help needed on web service response

Post 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)
Post Reply