REST-API is not my daily bread, so show me a few lines of your (problematic) code and I will try my best
- Log in to post comments
REST-API is not my daily bread, so show me a few lines of your (problematic) code and I will try my best
Your solution is nearly perfect, here my quick (untested) version.
ClassMethod Encode()
{
// You read N bytes (which MUST be divisible by 3) and write N*4/3 encoded bytes
// 3 * 8190 = 24570; 24570 * 4 / 3 = 32760; 32760 < 32768; to avoid (slow) long strings
set CHUNK=24570
set NOCR=1 // don't insert CRLF after each 72 written bytes
set encodedData=##class(%Stream.TmpBinary).%New() // adapt this to your needs: %Stream.Whatever...
set request=##class(%Net.HttpRequest).%New()
set request.Server="..."
do request.Get("/...")
if request.HttpResponse.StatusCode = 200 {
while 'request.HttpResponse.Data.AtEnd {
do encodedData.Write($system.Encryption.Base64Encode(request.HttpResponse.Data.Read(CHUNK),1))
}
}
QUIT encodedData
// as an alternative, you could return a string or a streamobject
set YOURMAXSTRING = 32767 // or 3641144
if encodedData.Size <= YOURMAXSTRING {
do encodedData.Rewind()
quit encodedData.Read(encodedData.Size)
} else { quit encodedData }
}Assuming, fields which contains commas are quoted ("aaa,bbb,ccc") and (for the simplicity) fields does not contains quotes, then something like this should do the job
ClassMethod CSV(filename)
{
s old=$system.Process.SetZEOF(1) // use $zeof instead of error trap
s result=[]
o filename:"r":0
i $t {
u filename
while '$zeof {
read line
i line]"" do result.%Push(..fields(line)) // ignore empty lines
}
}
c filename
d $system.Process.SetZEOF(old)
q result
}
ClassMethod fields(line)
{
s a="", f=0, row=[]
f i=1:1:$l(line) {
s c=$a(line,i)
i c=44,'f d row.%Push(a) s a="" continue
i c=34 s f='f continue
s a=a_$c(c)
}
q row
}
A test output:
USER>s res=##class(DC.Help).CSV(fn)
USER>zso res
(0).(0).............: 12162
(0).(1).............: CHAPTER I
(0).(2).............: Certain infectious and parasitic diseases (A00-B99)
(0).(3).............: 003 (A20-A28)
(0).(4).............: Certain zoonotic bacterial diseases
(0).(5).............: A28
(0).(6).............: Other zoonotic bacterial diseases, not elsewhere classified
(0).(7).............: A28
(0).(8).............: Other zoonotic bacterial diseases, not elsewhere classified
(0).(9).............: N
(0).(10)............: N
(0).(11)............: N
(0).(12)............: N
(0).(13)............: N
(0).(14)............:
(0).(15)............:
(0).(16)............:
(0).(17)............:
(0).(18)............:
(0).(19)............:
(0).(20)............:
(0).(21)............:
(0).(22)............:
Oh yes, some 45 years ago, 2K (for caretaker and despooler), 4K as regular partition. Nowdays you need 2GB or 4GB! Just a factor of 10^6. And yes, I feel as a real developer too. The problems solution matters, not the tools.
At least, you are one step further (in your initial post, you wrote "...because the code is hanging at Set tSc=Httprequest.Get(HttpURL)..."). Maybe the provided MAC number is wrong. The MAC Number CC:1B:E0:E2:3C:10 belongs to Cassia Networks. Is that the right number?
I know exactly nothing about Cassia Networks and Cassia SDK... sorry.
This is just a hint: your Get() argument should be URL-encoded (colons are not allowed in an URL):
Set tSc=Httprequest.Get($zcvt(HttpURL,"O","URL"))You are mixing two different things...
Property Data1 As list of %String;
Property Data2 As %List;
are two very different things. The first (Data1, equates to your DataObj.Services) is an object while the second one (Data2) is a simple scalar value (in this case a string which in its structure casually matches the inner structure of a $list() respective $listbuild() function).
write $listvalid(oref.Data1) ==> 0 // NOT a list
write $listvalid(oref.Data2) ==> 1 // a VALID list
write $isobject(oref.Data1) ==> 1 // a valid (list)object
write $isobject(oref.Data2) ==> 0 // not a valid (list)object$listnext() does NOT work on objects (your DataObj.Services) is an object
For a string like "hallo" Cache will use 5+2 = 7 bytes. If that "hallo..." is longer then 253 bytes then length_of_string + 4 bytes will be used and if your "hallo..." is longer then 65535 bytes then length_of_string + 6 bytes will be used.
But there is one more thing, you should know: the sum of the lengths of ALL properties, except the array(like) properties, can't be greater then that famous 3641144 magic number (if you use the standard Cache Storage). Array-like properties are those, which are stored in own nodes.
Use this link as a starting point and consider using either $FIND() or $LOCATE() to narrow down the string you're looking for and then use $EXTRACT() to extract the href value. By the way, it's enough a short example string, posting nearly the whole page is an overkill and wasting space.
Nice and congratulation. One problem less on this world...
Hence I wrote to OP, quote from my answer, "you ask WRC for a 'WriteStream()' method"
According to WebSocket protocol, the maximum payload size is (2**(8*8))-1 octets, if I recall it right.
The documentation of the %ToJSON() method is correct and yes, you can do
do obj.%ToJSON()
merely, this works only "on devices without protocol" like terminal, (sequential) file, etc. Everywhere, wehere the data bytes goes direct to the target. WebSocket isn't such a device. There is a "header part", with information fields like the command, masking, the length of the data, etc.
You have two possibilities, a) you ask WRC for a "WriteStream()" method or b) you handle the whole WebSocket by hand (is not impossible) or c) you change your application logic and send the those messages in chunks.
OK, somehow I miss the question. Do you need the VT100 escape sequences (see here, Table 3-6) or something else?
You try to store a whole stream in one property of an persistent class, that won't work! But the solution is already there, see this article
Yes, it would
kill
set $p(data,"x",2E6+1)=""
set dynArr=[].%Push(data).%Push(data).%Push(data)
set stream=##class(%Stream.GlobalCharacter).%New()
do dynArr.%ToJSON(stream)
try { set x=dynArr.%ToJSON() } catch e { write e.Name,! }
write stream.Size,!
write $length(data),!The output is
<MAXSTRING>
6000010
2000000
As Steven Hobbs wrote, the limit is only set by the size of the (virtual) memory.
It depends on two things,
a) the (user) interface, your user uses and (telnet, web, an application, etc)
b) where your inputs are handled (on server, on users device)
The only important thing is, do they accept data with the arbitrary length. It's not of importance for you, how their API the incomming data handles: as string, as longstring, as stream, as array of bytes, etc.
So one has a DEFAULT length of 50 and the other 3641144. But I thought more of the difference HOW MANY characters can they hold.
Just a dumb question, what is the very difference between %VarString and %String regarding the storable string length? As far as I know, both have a length limit of 3641144 characters.
I have nothing in common with HealtShare... but a property (Property rsXML As %String), like you mentioned, can hold up to 3.6E6 chars. If your data are longer then 3641144 characters then you definitely need to use streams (and if you intend to Base64 encode the data, then your data will be 33% longer)! You need to change the above property to something like
Property rsXML As %GlobalBinaryStream;
BUT this means, you have to adapt all your programs, methods, etc. where this property is in use!
That won't be a joy rather a pain
Hmm, ... will be difficult, but I give it a try
ClassMethod DNA(dna) As %String
{
q $tr(dna,"CGAT","GCTA")
}
The spirit of the time... we have to save water, energy, etc. Maybe we should save bytes too...
// instead of this line
if (($zabs($a($e(s1,cnt)) - $a($e(s2,cnt))) '= 32)) { return 0 }
// try this one
return:$zabs($a(s1,cnt)-$a(s2,cnt))-32 0That's is easy for the ASCII character set... (you didn't give any restrictions)
ClassMethod CheckOpposite(s1,s2) As %Boolean
{
q $zb(s1," ",6)=s2
}what you need is a SIMPLE compare of two strings
Set Ret=RSet.Execute()
set currentTS = $zdt($h,3) // get onece the current timestamp
While RSet.Next()
{ Set routeGuid=""
Set nextScheduled=RSet.GetData(9)
//I $ZDATETIME($h,3,1)>nextScheduled S ^badis("datetime",Id)=$ZDATETIME($h,3,1)_"|"_nextScheduled
if currentTS ] nextScheduled S ^badis("datetime",Id)=currentTS_"|"_nextScheduled
}
In words: if currentTS follows (i.e. greater) nextScheduled - that's all.
If you can't find the methods Vitaliy mentioned because (for example) your Cache version is too old, you can always reinvent the wheel and write your own encoder/decoder method. Where is the problem? This snippet could be a starting point
Parameter Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
ClassMethod Base64Enc(x)
{
s f=-$l(x)#3, x=x_$e($c(0,0),1,f), y=..#Base64, z="" zt:$ziswide(x) "WIDE"
f i=1:3:$l(x) s a=$a(x,i)*256+$a(x,i+1)*256+$a(x,i+2), c=262144 f j=1:1:4 s z=z_$e(y,a\c+1), a=a#c, c=c\64
s:f z=$e(z,1,$l(z)-f)_$e("==",1,f) q z
}I assume, you want to change ALL ..#WhiteSpace chars to the delimiter, used by $piece()
s $P(replace,",",$L(..#WhiteSpace) + 1)=""OK, it was a typo and there is nothing to shave ![]()
Some comments...
(1) you can generate a string with the necessary commas, (2) also, the variable "l" is unnecessary and (3) after assigning to "m" the length of the first word, start the for-loop with the next (second) word...
According to problem description, the string will never be empty, so an early "q 0" is also not necessary and for the case, this happens, the first piece of the string will have a length of 0.
Parameter WhiteSpace = {$C(9,10,13,32,160)};
ClassMethod Short(t) As %Integer
{
s t=$zstrip($TR(t,..#WhiteSpace,$tr($j("",$l(..#WhiteSpace))," ",",")),"<=>",",")
s m=$L($P(t,","))
f i=2:1:$L(t,",") {s n=$L($P(t,",",i)) s:n<m m=n}
q m
}In case, it's not a typo, tell me the secret of how to "shave symbols" ![]()