Substr, but without padding

  • Follow


When you are trying to divide some data into a series of 4k blocks, the 
last block is usually short.

I was hoping to trick substr() into returning this short block by 
setting the pad character to null (''):

Length = length(data)
Offset = 1
Do while O <= Length
   Block = substr(data,offset,4096,'')
   Say 'Block length:' length(block)
   End

� but substr insists that the pad character be a single character (if it 
is specified).

Without this ability I have to use a different substr call for the last 
block, and that has always seemed a little messy to me.

Is there an easy way around this? My usual approach is to code my own 
function, such as xsubstr() which has the extra facility that I'm 
looking for.

I don't want to change the value of data inside the loop above, as that 
performs poorly when the data is very long (e.g. 600Mb from an ISO image)

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 9/30/2009 11:11:26 AM

On 30 Sep, 12:11, Swifty <steve.j.sw...@gmail.com> wrote:
> When you are trying to divide some data into a series of 4k blocks, the
> last block is usually short.
>
> I was hoping to trick substr() into returning this short block by
> setting the pad character to null (''):
>
> Length =3D length(data)
> Offset =3D 1
> Do while O <=3D Length
> =A0 =A0Block =3D substr(data,offset,4096,'')
> =A0 =A0Say 'Block length:' length(block)
> =A0 =A0End
>
> =85 but substr insists that the pad character be a single character (if i=
t
> is specified).
>
I was about to offer some suggestions, but then I realised that I
couldn't figure out what was happening here.

Where does O get a value?
How does offset ever become anything other than 1?
Assuming that O does get a value, how does it ever then become <=3D 0?
0
Reply Captain 9/30/2009 12:49:57 PM


Swifty wrote:
> When you are trying to divide some data into a series of 4k blocks, the 
> last block is usually short.
> 
> I was hoping to trick substr() into returning this short block by 
> setting the pad character to null (''):
> 
> Length = length(data)
> Offset = 1
> Do while O <= Length
>   Block = substr(data,offset,4096,'')
>   Say 'Block length:' length(block)
>   End
> 
> � but substr insists that the pad character be a single character (if it 
> is specified).
> 
> Without this ability I have to use a different substr call for the last 
> block, and that has always seemed a little messy to me.
> 
> Is there an easy way around this? My usual approach is to code my own 
> function, such as xsubstr() which has the extra facility that I'm 
> looking for.
> 
> I don't want to change the value of data inside the loop above, as that 
> performs poorly when the data is very long (e.g. 600Mb from an ISO image)
> 

data=Copies(0, 34567)
Do offset=1 To Length(data) By 4096
   Parse Var data =(offset) block =(offset+4096)
   Say 'Block length:' Length(block)
End



Jon Hosking
0
Reply Jonathan 9/30/2009 3:07:26 PM

How about using D2C(0) rather than the empty string?
0
Reply Dark 9/30/2009 3:29:48 PM

Captain Paralytic wrote:
> I was about to offer some suggestions, but then I realised that I
> couldn't figure out what was happening here.
> 
> Where does O get a value?
> How does offset ever become anything other than 1?
> Assuming that O does get a value, how does it ever then become <= 0?

My apologies. I coded it using "O" (less typing) but then screwed up the 
change to "Offset". So:

Change "O" to "Offset"

Insert: Offset = Offset + 4096

Not one of my better efforts.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 9/30/2009 6:22:32 PM

Dark Coffee wrote:
> How about using D2C(0) rather than the empty string?

That would pad with null characters. I'm transmitting a tgz file in 
4096-byte chunks, and I suspect that the additional trailing nulls would 
upset the tgz processing. I had wondered what would happen if I tried that.

The specification of substr() doesn't leave much (if any) room for some 
back-door mechanism. It I'd tried to pad with d2c(0) characters, and 
they got stripped, I'd be even more upset.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 9/30/2009 6:26:27 PM

Dark Coffee wrote:
> How about using D2C(0) rather than the empty string?

That would pad with null characters. I'm transmitting a tgz file in 
4096-byte chunks, and I suspect that the additional trailing nulls would 
upset the tgz processing. I had wondered what would happen if I tried that.

The specification of substr() doesn't leave much (if any) room for some 
back-door mechanism. It I'd tried to pad with d2c(0) characters, and 
they got stripped, I'd be even more upset.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 9/30/2009 6:26:49 PM

Jonathan Hosking wrote:
> data=Copies(0, 34567)
> Do offset=1 To Length(data) By 4096
>   Parse Var data =(offset) block =(offset+4096)
>   Say 'Block length:' Length(block)
> End

I'll do it that way. Thanks.

Incidentally, here is my first attempt at an xsubstr function that does 
no padding if the pad character is omitted, or null:

::Routine xsubstr public
Parse arg text,offset,length,pad
If length = '' then return substr(text,offset)
If length(text)>=offset+length-1 then return substr(text,offset,length)
If pad == '' then return substr(text,offset)
Return substr(text,offset,length,pad)

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 9/30/2009 6:30:45 PM

In Message-ID:<4ac3742f$1@kcnews01>,
Jonathan Hosking <jh910@juno.com> wrote: 

>Swifty wrote:
>> When you are trying to divide some data into a series of 4k blocks, the 
>> last block is usually short.
>> 
 <snip>
>> Is there an easy way around this? My usual approach is to code my own 
>> function, such as xsubstr() which has the extra facility that I'm 
>> looking for.
>> 
>> I don't want to change the value of data inside the loop above, as that 
>> performs poorly when the data is very long (e.g. 600Mb from an ISO image)
>> 
>
>data=Copies(0, 34567)
>Do offset=1 To Length(data) By 4096
>   Parse Var data =(offset) block =(offset+4096)
>   Say 'Block length:' Length(block)
>End

     That example gave me syntax errors under Regina.  This works
for me:

  data=Copies(0, 34567)
  Do offset=1 To Length(data) By 4096
    Parse Var data =(offset) block +4096
    Say 'Block length:' Length(block)
  End

     It also works when made a bit more friendly to changing block
sizes:

  data=Copies(0, 34567)
  blksize = 4096
  Do offset=1 To Length(data) By blksize
    Parse Var data =(offset) block +(blksize)
    Say 'Block length:' Length(block)
  End

-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 9/30/2009 6:39:31 PM

I'm curious... what does Regina complain about?

Les               (Change Arabic to Roman to email me)



Arthur T. wrote:
> In Message-ID:<4ac3742f$1@kcnews01>,
> Jonathan Hosking <jh910@juno.com> wrote: 
> 
>> Swifty wrote:
>>> When you are trying to divide some data into a series of 4k blocks, the 
>>> last block is usually short.
>>>
>  <snip>
>>> Is there an easy way around this? My usual approach is to code my own 
>>> function, such as xsubstr() which has the extra facility that I'm 
>>> looking for.
>>>
>>> I don't want to change the value of data inside the loop above, as that 
>>> performs poorly when the data is very long (e.g. 600Mb from an ISO image)
>>>
>> data=Copies(0, 34567)
>> Do offset=1 To Length(data) By 4096
>>   Parse Var data =(offset) block =(offset+4096)
>>   Say 'Block length:' Length(block)
>> End
> 
>      That example gave me syntax errors under Regina.  This works
> for me:
> 
>   data=Copies(0, 34567)
>   Do offset=1 To Length(data) By 4096
>     Parse Var data =(offset) block +4096
>     Say 'Block length:' Length(block)
>   End
> 
>      It also works when made a bit more friendly to changing block
> sizes:
> 
>   data=Copies(0, 34567)
>   blksize = 4096
>   Do offset=1 To Length(data) By blksize
>     Parse Var data =(offset) block +(blksize)
>     Say 'Block length:' Length(block)
>   End
> 
0
Reply LesK 9/30/2009 10:52:09 PM

In Message-ID:<4ac3e0aa$0$5635$9a6e19ea@unlimited.newshosting.com>,
LesK <5mre20@tampabay.rr.com> wrote: 

>I'm curious... what does Regina complain about?

 Error 38 running "F:\A.REX", line 3: Invalid template or pattern
 Error 38.1: Invalid parsing template detected at "+"

     Apparently it doesn't like the plus sign inside the parens.
Line 3, of course, is:
   Parse Var data =(offset) block =(offset+4096)




-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/1/2009 12:29:15 AM

On Oct 1, 10:29=A0am, Arthur T. <art...@munged.invalid> wrote:
> In Message-ID:<4ac3e0aa$0$5635$9a6e1...@unlimited.newshosting.com>,
>
> LesK <5mr...@tampabay.rr.com> wrote:
> >I'm curious... what does Regina complain about?
>
> =A0Error 38 running "F:\A.REX", line 3: Invalid template or pattern
> =A0Error 38.1: Invalid parsing template detected at "+"
>
> =A0 =A0 =A0Apparently it doesn't like the plus sign inside the parens.
> Line 3, of course, is:
> =A0 =A0Parse Var data =3D(offset) block =3D(offset+4096)
>
> --
> Arthur T. - ar23hur "at" intergate "dot" com
> Looking for a z/OS (IBM mainframe) systems programmer position

The use of an expression inside parentheses in a PARSE template is an
ooRexx extension to the ANSI specification. ANSI states that what can
be inside parentheses is a variable; not an expression.
0
Reply markh 10/1/2009 7:06:49 AM

Arthur T. wrote:
> It also works when made a bit more friendly to changing block sizes:
> 
>   data=Copies(0, 34567)
>   blksize = 4096
>   Do offset=1 To Length(data) By blksize
>     Parse Var data =(offset) block +(blksize)
>     Say 'Block length:' Length(block)
>   End

Well, I'm actually using a blocksize of 16384 but it was hard to avoid 
line splitting, so I shrank my blocksize for the example. I'm also using 
the blocksize specified in a variable.

So, you have basically written my whole routine for me. Do you take 
commissions? :-)

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/1/2009 8:22:39 AM

In Message-ID:<JZidnfjN5I5E-1nXnZ2dnUVZ8jVi4p2d@brightview.com>,
Swifty <steve.j.swift@gmail.com> wrote: 

>Arthur T. wrote:
>> It also works when made a bit more friendly to changing block sizes:
>> 
>>   data=Copies(0, 34567)
>>   blksize = 4096
>>   Do offset=1 To Length(data) By blksize
>>     Parse Var data =(offset) block +(blksize)
>>     Say 'Block length:' Length(block)
>>   End
>
>Well, I'm actually using a blocksize of 16384 but it was hard to avoid 
>line splitting, so I shrank my blocksize for the example. I'm also using 
>the blocksize specified in a variable.
>
>So, you have basically written my whole routine for me. 

     In this case, Jonathan Hosking did most of the work.

>Do you take 
>>commissions? :-)

     I'm out of a job, so I'll take almost anything.  But the price
for a routine this small wouldn't be worth the postage.

-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/1/2009 1:34:10 PM

In Message-ID:<JZidnfjN5I5E-1nXnZ2dnUVZ8jVi4p2d@brightview.com>,
Swifty <steve.j.swift@gmail.com> wrote: 

>Arthur T. wrote:
>> It also works when made a bit more friendly to changing block sizes:
>> 
>>   data=Copies(0, 34567)
>>   blksize = 4096
>>   Do offset=1 To Length(data) By blksize
>>     Parse Var data =(offset) block +(blksize)
>>     Say 'Block length:' Length(block)
>>   End
>
>Well, I'm actually using a blocksize of 16384 but it was hard to avoid 
>line splitting, so I shrank my blocksize for the example. I'm also using 
>the blocksize specified in a variable.
>
>So, you have basically written my whole routine for me. Do you take 
>commissions? :-)

     Of course, if you want *real* speed, try something like this
Q&D program:

 <code>

  file = "inputfile" /* large enough to populate DATA */
  tmpfile = "x:\testfile"  /* temp file */
  totsize = 0

  lenfile = chars(file)
  t0 = time('r')
  data = charin(file,,lenfile)
  /* DATA is now poplulated */

  t1 = time('r')
  x = charout(tmpfile,data)
  t2 = time('r')

  signal on NOTREADY
  blksize = 40960 * 4  /* a reasonable size for my DATA */
  Do forever
    left = chars(tmpfile)
    select
      when left = 0 then signal NOTREADY
      when left < blksize then blksize = left
      otherwise nop
    end /* select */
    block = charin(tmpfile,,blksize)
    Say 'Block length:' Length(block)
    totsize = totsize + blksize
  End

NOTREADY:
  t3 = time('r')

  say lenfile totsize
  say t1 t2 t3
  exit 0

 </code>

     Just make sure your tempfile is deleted between runs.

-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/1/2009 11:12:17 PM

In Message-ID:<f8dac5lv36705c1ooneku2sed00ob46c0g@4ax.com>,
Arthur T. <arthur@munged.invalid> wrote: 

>     Of course, if you want *real* speed, try something like this
>Q&D program:

     Slightly improved example showing that the write/read-back
method is about 70 times the speed of the PARSE technique (on my
machine).  Here's the output when I ran it:

1.344000 2.078000 1.687000 119.313000 70.7249555

     And here is "it":

  tmpfile = "x:\testfile"
  totsize = 0

  t0 = time('r')
  lenfile = 64*1024*1024
  data = copies(' ',lenfile)
  t1 = time('r')

  x = charout(tmpfile,data,1)

  t2 = time('r')

  signal on NOTREADY
  blksize = 40960 * 4
  Do forever
    left = chars(tmpfile)
    select
      when left = 0 then leave
      when left < blksize then blksize = left
      otherwise nop
    end /* select */
    block = charin(tmpfile,,blksize)
    Say 'Block length:' Length(block)
    totsize = totsize + blksize
  End

NOTREADY:
  t3 = time('r')

  say lenfile totsize

  blksize = 40960 * 4
  totsize = 0
  Do offset=1 To Length(data) By blksize
    Parse Var data =(offset) block +(blksize)
    Say 'Block length:' Length(block)
    totsize = totsize + length(block)
  End

  t4 = time('r')
  say lenfile totsize
  say t1 t2 t3 t4 t4/t3

  exit 0




-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/2/2009 5:03:42 AM

Parse isn't optimized for the pc like it is for the mainframe.

Les               (Change Arabic to Roman to email me)



Arthur T. wrote:
> In Message-ID:<f8dac5lv36705c1ooneku2sed00ob46c0g@4ax.com>,
> Arthur T. <arthur@munged.invalid> wrote: 
> 
>>     Of course, if you want *real* speed, try something like this
>> Q&D program:
> 
>      Slightly improved example showing that the write/read-back
> method is about 70 times the speed of the PARSE technique (on my
> machine).  Here's the output when I ran it:
> 
> 1.344000 2.078000 1.687000 119.313000 70.7249555
> 
>      And here is "it":
> 
>   tmpfile = "x:\testfile"
>   totsize = 0
> 
>   t0 = time('r')
>   lenfile = 64*1024*1024
>   data = copies(' ',lenfile)
>   t1 = time('r')
> 
>   x = charout(tmpfile,data,1)
> 
>   t2 = time('r')
> 
>   signal on NOTREADY
>   blksize = 40960 * 4
>   Do forever
>     left = chars(tmpfile)
>     select
>       when left = 0 then leave
>       when left < blksize then blksize = left
>       otherwise nop
>     end /* select */
>     block = charin(tmpfile,,blksize)
>     Say 'Block length:' Length(block)
>     totsize = totsize + blksize
>   End
> 
> NOTREADY:
>   t3 = time('r')
> 
>   say lenfile totsize
> 
>   blksize = 40960 * 4
>   totsize = 0
>   Do offset=1 To Length(data) By blksize
>     Parse Var data =(offset) block +(blksize)
>     Say 'Block length:' Length(block)
>     totsize = totsize + length(block)
>   End
> 
>   t4 = time('r')
>   say lenfile totsize
>   say t1 t2 t3 t4 t4/t3
> 
>   exit 0
> 
> 
> 
> 
0
Reply LesK 10/2/2009 6:37:27 AM

LesK wrote:
> Parse isn't optimized for the pc like it is for the mainframe.

I did a simple benchmark (the code is at the bottom). Here are the results:

System			Parse	Substr
Home PC	(4 year old)	1.608	1.969
Office server (7 years)	3.535	3.882
Swiftys.org.uk		0.774	0.879

The office server is showing its age. It was stupendously quick when it 
was purchased about 7 years ago. My "swiftys" website is on a new Dell 
server (not actually in production yet). My home PC is showing its age, 
but then I'm showing my age more, so I don't mind. All of the systems 
are "PC" architecture. Home/Office both run IBM Object REXX. "Swiftys" 
is ooRexx 4.0

Code:

/* Benchmark SUBSTR vs. Parse */
Buffer= copies('F0'x,2**21+1234)
Blocksize = 2**14
Loops = 1000
Say 'Buffer length:' length(buffer) 'Blocksize;' blocksize
Say
Time. = 0
Do loops
   Call Parse_It
   Call Substr_it
   End
Say 'Parse: ' time.parse
Say 'Substr:' time.substr
Call charout,'0A'x || 'Press any key to exit: '
Call sysgetkey 'NOECHO'
Exit

Parse_it: Procedure expose Buffer blocksize time.
Call time 'R'
Do offset=1 To Length(buffer) By blocksize
   Parse Var buffer =(offset) block +(blocksize)
   End
Time.parse = time.parse + time('E')
Return

Substr_It: Procedure expose Buffer blocksize time. blocks
Call time 'R'
L = Length(buffer)
Do offset = 1 to L by blocksize
   If Offset+blocksize < L then block = substr(buffer,offset,blocksize)
   Else block = substr(buffer,offset)
   End
Time.substr = time.substr + time('E')
Return


-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/2/2009 9:37:28 AM

In Message-ID:<MIydnXeqxZF7VFjXnZ2dnUVZ8mmdnZ2d@brightview.com>,
Swifty <steve.j.swift@gmail.com> wrote: 

>I did a simple benchmark (the code is at the bottom). Here are the results:
>
>System			Parse	Substr
>Home PC	(4 year old)	1.608	1.969
>Office server (7 years)	3.535	3.882
>Swiftys.org.uk		0.774	0.879

     My machine is about 7 years old, too, but I had to cut the
number of loops down to just 10 to get these numbers:

Parse:  11.718000
Substr: 11.673000

     Then I added the write/read method and got:

Parse:  11.344000
Substr: 11.688000
Read:   0.906000

     I'd be interested to see the numbers from your machines (with a
suitable LOOPS value).  If you run it, remember to code a reasonable
name for TMPFILE.

     Here's my code:

/* Benchmark SUBSTR vs. Parse */
Buffer= copies('F0'x,2**21+1234)
Blocksize = 2**14
Loops = 10
Say 'Buffer length:' length(buffer) 'Blocksize;' blocksize
Say
Time. = 0
Do loops
   Call Parse_It
   Call Substr_it
   Call Read_it
   End
Say 'Parse: ' time.parse
Say 'Substr:' time.substr
Say 'Read:  ' time.read
Call charout,'0A'x || 'Press any key to exit: '
Call sysgetkey 'NOECHO'
Exit

Parse_it: Procedure expose Buffer blocksize time.
Call time 'R'
Do offset=1 To Length(buffer) By blocksize
   Parse Var buffer =(offset) block +(blocksize)
   End
Time.parse = time.parse + time('E')
Return

Substr_It: Procedure expose Buffer blocksize time. blocks
Call time 'R'
L = Length(buffer)
Do offset = 1 to L by blocksize
   If Offset+blocksize < L then block =
substr(buffer,offset,blocksize)
   Else block = substr(buffer,offset)
   End
Time.substr = time.substr + time('E')
Return

Read_it: Procedure expose Buffer blocksize time.
Call time 'R'
signal on NOVALUE
  tmpfile = 'x:\testfile'
  x = charout(tmpfile,Buffer,1)
  blksize = blocksize
  Do forever
    left = chars(tmpfile)
    select
      when left = 0 then leave
      when left < blksize then blksize = left
      otherwise nop
    end /* select */
    block = charin(tmpfile,,blksize)
  End
NOVALUE:
Time.read = time.read + time('E')
Return


-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/2/2009 5:05:33 PM

"Arthur T." wrote:
>       when left < blksize then blksize = left

Is this necessary?  Doesn't charin() return "up to length" characters,
up to the end of the input stream?  I'd think this should suffice:

  Do while chars(tmpfile) > 0
    block = charin(tmpfile,,blksize)
    ...
  End

�R
0
Reply Glenn 10/2/2009 5:23:18 PM

I wrote:
> up to the end of the input stream?  I'd think this should suffice:
>   Do while chars(tmpfile) > 0

--not to mention that it would also work on platforms where CHARS()
doesn't have access to the actual size of the file, and returns only 0
or 1.

�R
0
Reply Glenn 10/2/2009 5:32:58 PM

These numbers looked a bit suspect to me, so I tried running this 
myself.  I got similar results, which puzzled me, but I tracked it down 
to the name of the temporary file "x:\testfile".  I don't have an X 
drive on my system, so the loop was terminating on the first pass.  When 
  I changed this to c:, I got the following results:

Parse:  0.016000
Substr: 0.016000
Read:   03590000

The parse and read results are right up at the limits of the PC time of 
day clock.

Rick


Arthur T. wrote:
> In Message-ID:<MIydnXeqxZF7VFjXnZ2dnUVZ8mmdnZ2d@brightview.com>,
> Swifty <steve.j.swift@gmail.com> wrote: 
> 
>> I did a simple benchmark (the code is at the bottom). Here are the results:
>>
>> System			Parse	Substr
>> Home PC	(4 year old)	1.608	1.969
>> Office server (7 years)	3.535	3.882
>> Swiftys.org.uk		0.774	0.879
> 
>      My machine is about 7 years old, too, but I had to cut the
> number of loops down to just 10 to get these numbers:
> 
> Parse:  11.718000
> Substr: 11.673000
> 
>      Then I added the write/read method and got:
> 
> Parse:  11.344000
> Substr: 11.688000
> Read:   0.906000
> 
>      I'd be interested to see the numbers from your machines (with a
> suitable LOOPS value).  If you run it, remember to code a reasonable
> name for TMPFILE.
> 
>      Here's my code:
> 
> /* Benchmark SUBSTR vs. Parse */
> Buffer= copies('F0'x,2**21+1234)
> Blocksize = 2**14
> Loops = 10
> Say 'Buffer length:' length(buffer) 'Blocksize;' blocksize
> Say
> Time. = 0
> Do loops
>    Call Parse_It
>    Call Substr_it
>    Call Read_it
>    End
> Say 'Parse: ' time.parse
> Say 'Substr:' time.substr
> Say 'Read:  ' time.read
> Call charout,'0A'x || 'Press any key to exit: '
> Call sysgetkey 'NOECHO'
> Exit
> 
> Parse_it: Procedure expose Buffer blocksize time.
> Call time 'R'
> Do offset=1 To Length(buffer) By blocksize
>    Parse Var buffer =(offset) block +(blocksize)
>    End
> Time.parse = time.parse + time('E')
> Return
> 
> Substr_It: Procedure expose Buffer blocksize time. blocks
> Call time 'R'
> L = Length(buffer)
> Do offset = 1 to L by blocksize
>    If Offset+blocksize < L then block =
> substr(buffer,offset,blocksize)
>    Else block = substr(buffer,offset)
>    End
> Time.substr = time.substr + time('E')
> Return
> 
> Read_it: Procedure expose Buffer blocksize time.
> Call time 'R'
> signal on NOVALUE
>   tmpfile = 'x:\testfile'
>   x = charout(tmpfile,Buffer,1)
>   blksize = blocksize
>   Do forever
>     left = chars(tmpfile)
>     select
>       when left = 0 then leave
>       when left < blksize then blksize = left
>       otherwise nop
>     end /* select */
>     block = charin(tmpfile,,blksize)
>   End
> NOVALUE:
> Time.read = time.read + time('E')
> Return
> 
> 
0
Reply Rick 10/2/2009 6:18:57 PM

In Message-ID:<lurxm.19409$Fg7.7247@newsfe03.iad>,
Rick McGuire <object.rexx@gmail.com> wrote: 

>These numbers looked a bit suspect to me, so I tried running this 
>myself.  I got similar results, which puzzled me, but I tracked it down 
>to the name of the temporary file "x:\testfile".  I don't have an X 
>drive on my system, so the loop was terminating on the first pass.  When 
>  I changed this to c:, I got the following results:
>
>Parse:  0.016000
>Substr: 0.016000
>Read:   03590000
>
>The parse and read results are right up at the limits of the PC time of 
>day clock.

     Those are numbers I'd more expect.  In my tests, I even did a
verify that the disk file was there and properly filled.  I wonder
what's slowing my machine down so much for the PARSE & SUBSTR
routines.  Thanks for running my version.

     I just noticed that there's no decimal point in the READ: line.
How long did it actually take?

-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/2/2009 7:18:56 PM

On 1 Oct, 09:06, markh <r...@users.sourceforge.net> wrote:
> On Oct 1, 10:29=A0am, Arthur T. <art...@munged.invalid> wrote:
>
> > In Message-ID:<4ac3e0aa$0$5635$9a6e1...@unlimited.newshosting.com>,
>
> > LesK <5mr...@tampabay.rr.com> wrote:
> > >I'm curious... what does Regina complain about?
>
> > =A0Error 38 running "F:\A.REX", line 3: Invalid template or pattern
> > =A0Error 38.1: Invalid parsing template detected at "+"
>
> > =A0 =A0 =A0Apparently it doesn't like the plus sign inside the parens.
> > Line 3, of course, is:
> > =A0 =A0Parse Var data =3D(offset) block =3D(offset+4096)
>
>
> The use of an expression inside parentheses in a PARSE template is an
> ooRexx extension to the ANSI specification. ANSI states that what can
> be inside parentheses is a variable; not an expression.

not tested (Internet Cafe without rexx) - would this be ANSI:
parse value (offset + 4096) data with b =3D(offset) block =3D(b)

but even easier would be be:
l =3D length(data)
do while l > offset /* or length(data) > offset - something to
optimize */
    parse var data block =3D(offset) data
    l =3D l - offset /* not so in the length() case */
    ...
end
block =3D data
....
btw., if blocksize should be like 4096, offset should be 4097
Wolfgang
0
Reply wolfgang 10/2/2009 8:06:49 PM

wolfgang.riedel wrote:
> On 1 Oct, 09:06, markh <r...@users.sourceforge.net> wrote:

> but even easier would be be:
> l = length(data)
> do while l > offset /* or length(data) > offset - something to
> optimize */
>     parse var data block =(offset) data
>     l = l - offset /* not so in the length() case */
>     ...
> end
> block = data
> ...

That is the sort of code that I try to avoid, especially when 
length(data) is likely to start at something like 600000000.

I know that the new value of "data" will be stored in the memory used by 
the old version (because it is always shorter), so the performance 
problem is nowhere near as bad as when you join the block using a 
similar technique. But I suspect that setting the variable "data" 146484 
times will slow things down.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/3/2009 8:53:21 AM

Rick McGuire wrote:
> Parse:  0.016000
> Substr: 0.016000
> Read:   03590000
> 
> The parse and read results are right up at the limits of the PC time of 
> day clock.

If you were using my code unaltered, then your system is nearly 50 times 
faster than the fastest system I have access to. Would you mind telling 
me what it is, so I can suggest it to my manager when my PC renewal 
comes up (some time in 2010).

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/3/2009 9:00:21 AM

Arthur T. wrote:
>      I'd be interested to see the numbers from your machines (with a
> suitable LOOPS value).  If you run it, remember to code a reasonable
> name for TMPFILE.

I'd only run that on a system that had a "Disk in Memory" filesystem 
(only the Office System).

I presume you're working on the assumption that the write won't get 
committed to disk if you don't close the file, but I'm not sure how true 
that might be on a 600Mb block of data.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/3/2009 9:03:32 AM

Arthur T. wrote:
> In Message-ID:<lurxm.19409$Fg7.7247@newsfe03.iad>,
> Rick McGuire <object.rexx@gmail.com> wrote: 
> 
>> These numbers looked a bit suspect to me, so I tried running this 
>> myself.  I got similar results, which puzzled me, but I tracked it down 
>> to the name of the temporary file "x:\testfile".  I don't have an X 
>> drive on my system, so the loop was terminating on the first pass.  When 
>>  I changed this to c:, I got the following results:
>>
>> Parse:  0.016000
>> Substr: 0.016000
>> Read:   03590000
>>
>> The parse and read results are right up at the limits of the PC time of 
>> day clock.
> 
>      Those are numbers I'd more expect.  In my tests, I even did a
> verify that the disk file was there and properly filled.  I wonder
> what's slowing my machine down so much for the PARSE & SUBSTR
> routines.  Thanks for running my version.
> 
>      I just noticed that there's no decimal point in the READ: line.
> How long did it actually take?
> 
Oops, the decimal should be after the first zero, so the result is 
0.359000.

Rick
0
Reply Rick 10/3/2009 6:50:37 PM

Swifty wrote:
> Rick McGuire wrote:
>> Parse:  0.016000
>> Substr: 0.016000
>> Read:   03590000
>>
>> The parse and read results are right up at the limits of the PC time 
>> of day clock.
> 
> If you were using my code unaltered, then your system is nearly 50 times 
> faster than the fastest system I have access to. Would you mind telling 
> me what it is, so I can suggest it to my manager when my PC renewal 
> comes up (some time in 2010).
> 
That was run on a ThinkPad 61P using ooRexx 4.0+ (and the debug version 
at that).

Rick
0
Reply Rick 10/3/2009 6:51:39 PM

Glenn Knickerbocker <NotR@bestweb.net> wrote:

> Is this necessary?  Doesn't charin() return "up to length" characters,
> up to the end of the input stream?  I'd think this should suffice:
> 
>   Do while chars(tmpfile) > 0
>     block = charin(tmpfile,,blksize)
>     ...
>   End

What's the overhead in the  chars(tmpfile)  call each time around the loop? 
Would it not be easier to use standartd EOF checking to discover when
there's no more data?  Or look for a short block?

-- 
Jeremy C B Nicoll - my opinions are my own.

Email sent to my from-address will be deleted. Instead, please reply
to newsreplynnn@wingsandbeaks.org.uk replacing "nnn" by "284".  
0
Reply Jeremy 10/3/2009 8:52:36 PM

In Message-ID:<ioadnTPtZ9fpjlrXnZ2dnUVZ8oednZ2d@brightview.com>,
Swifty <steve.j.swift@gmail.com> wrote: 

>Arthur T. wrote:
>>      I'd be interested to see the numbers from your machines (with a
>> suitable LOOPS value).  If you run it, remember to code a reasonable
>> name for TMPFILE.
>
>I'd only run that on a system that had a "Disk in Memory" filesystem 
>(only the Office System).
>
>I presume you're working on the assumption that the write won't get 
>committed to disk if you don't close the file, but I'm not sure how true 
>that might be on a 600Mb block of data.

     I wrote to a real disk.  I had no assumptions; I just tried it.
And, my original run was with a 64MB file, so I expect it was
actually written and read.

-- 
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
0
Reply Arthur 10/3/2009 9:08:00 PM

On Oct 3, 4:53=A0am, Swifty <steve.j.sw...@gmail.com> wrote:
> wolfgang.riedel wrote:
> > On 1 Oct, 09:06, markh <r...@users.sourceforge.net> wrote:
> > but even easier would be be:
> > l =3D length(data)
> > do while l > offset /* or length(data) > offset - something to
> > optimize */
> > =A0 =A0 parse var data block =3D(offset) data
> > =A0 =A0 l =3D l - offset /* not so in the length() case */
> > =A0 =A0 ...
> > end
> > block =3D data
> > ...
>
> That is the sort of code that I try to avoid, especially when
> length(data) is likely to start at something like 600000000.
>
> I know that the new value of "data" will be stored in the memory used by
> the old version (because it is always shorter), so the performance
> problem is nowhere near as bad as when you join the block using a
> similar technique. But I suspect that setting the variable "data" 146484
> times will slow things down.

Not necessarily true at all.  It is patently false for all versions of
Object Rexx.  That parse operation
creates two new string objects and the original is (potentially) made
available for garbage collection.

Rick


>
> --
> Steve Swifthttp://www.swiftys.org.uk/swifty.htmlhttp://www.ringers.org.uk

0
Reply Rick 10/3/2009 10:27:48 PM

In <gemini.kqyhzn00mxatm026g@wingsandbeaks.org.uk.invalid>, on 10/03/2009
   at 09:52 PM, Jeremy Nicoll - news posts
<jn.nntp.scrap004@wingsandbeaks.org.uk> said:

>What's the overhead in the  chars(tmpfile)  call each time around the
>loop?  Would it not be easier to use standartd EOF checking to discover
>when there's no more data?

What is "standartd EOF checking" in REXX?

Lrf, gur dhrfgvba vf eurgbevpny.

-- 
Shmuel (Seymour J.) Metz, SysProg and JOAT  <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action.  I reserve the
right to publicly post or ridicule any abusive E-mail.  Reply to
domain Patriot dot net user shmuel+news to contact me.  Do not
reply to spamtrap@library.lspace.org

0
Reply Shmuel 10/5/2009 1:29:25 AM

Rexx doesn't define i/o standards. Each platform has it's 
own. Pc's don't even understand 'records' at the OS level 
like CMS does, only data blocks.

Les               (Change Arabic to Roman to email me)



Shmuel (Seymour J.) Metz wrote:
> In <gemini.kqyhzn00mxatm026g@wingsandbeaks.org.uk.invalid>, on 10/03/2009
>    at 09:52 PM, Jeremy Nicoll - news posts
> <jn.nntp.scrap004@wingsandbeaks.org.uk> said:
> 
>> What's the overhead in the  chars(tmpfile)  call each time around the
>> loop?  Would it not be easier to use standartd EOF checking to discover
>> when there's no more data?
> 
> What is "standartd EOF checking" in REXX?
> 
> Lrf, gur dhrfgvba vf eurgbevpny.
> 
0
Reply LesK 10/5/2009 1:19:15 PM

LesK wrote:
> Rexx doesn't define i/o standards.
> Shmuel (Seymour J.) Metz wrote:
> > What is "standartd EOF checking" in REXX?
> > Lrf, gur dhrfgvba vf eurgbevpny.

I think the intended rhetorical answer was that CHARS()=0 *is* the
standard EOF check.

�R
0
Reply Glenn 10/5/2009 8:43:23 PM

Glenn Knickerbocker wrote:
> I think the intended rhetorical answer was that CHARS()=0 *is* the
> standard EOF check.

Or "Signal on Notready". I'm not a fan of this because it leaves you 
with "do forever" loops with no obvious exit mechanism.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 10/6/2009 7:28:18 AM

Swifty wrote:
> Glenn Knickerbocker wrote:
>> I think the intended rhetorical answer was that CHARS()=0 *is* the
>> standard EOF check.
> 
> Or "Signal on Notready". I'm not a fan of this because it leaves you 
> with "do forever" loops with no obvious exit mechanism.
> 

Well, a signal is an obvious exit mechanism, but if that really bothers 
you, then use call on to set a loop terminating condition.

call on notready
atend = .false

do while \atend

    -- read logic here


end

exit


notready:
     atEnd = .true


This gives you an obvious exit mechamism on an eof...but the signal 
mechanism is much cleaner, in my opinion.

Rick
0
Reply Rick 10/6/2009 9:49:03 AM

Jeremy Nicoll - news posts <jn.nntp.scrap004@wingsandbeaks.org.uk> wrote:

> Would it not be easier to use standartd EOF checking to discover when
> there's no more data? 

I meant using  notready  

-- 
Jeremy C B Nicoll - my opinions are my own.

Email sent to my from-address will be deleted. Instead, please reply
to newsreplynnn@wingsandbeaks.org.uk replacing "nnn" by "284".  
0
Reply Jeremy 10/6/2009 10:54:36 AM

Rick McGuire wrote:
> This gives you an obvious exit mechamism on an eof...but the signal
> mechanism is much cleaner, in my opinion.

Until your loop gets put inside another loop!

  Do i = 1 to file.0
    Signal on Notready name Thisloop
    Do forever
      ... charin(file.i ...
    End
    Thisloop:
    Say 'This works the FIRST time!'
  End

Actually, in the case at hand, how would you ever even get the last
incomplete block this way?  NOTREADY is raised as soon as you read it,
and it doesn't have a chance to be saved anywhere.

�R
0
Reply Glenn 10/6/2009 8:23:30 PM

Glenn Knickerbocker wrote:
> Rick McGuire wrote:
>> This gives you an obvious exit mechamism on an eof...but the signal
>> mechanism is much cleaner, in my opinion.
> 
> Until your loop gets put inside another loop!
> 
>   Do i = 1 to file.0
>     Signal on Notready name Thisloop
>     Do forever
>       ... charin(file.i ...
>     End
>     Thisloop:
>     Say 'This works the FIRST time!'
>   End
> 
> Actually, in the case at hand, how would you ever even get the last
> incomplete block this way?  NOTREADY is raised as soon as you read it,
> and it doesn't have a chance to be saved anywhere.
> 
> �R
NOTREADY is not raised until end-of-clause, as is any condition where 
CALL ON is supported.  The assignment has a chance to complete as a result.

Rick
0
Reply Rick 10/7/2009 9:30:17 AM

In <4ac9f259$0$4978$9a6e19ea@unlimited.newshosting.com>, on 10/05/2009
   at 09:19 AM, LesK <5mre20@tampabay.rr.com> said:

>Rexx doesn't define i/o standards.

ROTF,LMAO. Please tell that to ANSI.

>Pc's don't even understand 'records' at the OS level 
>like CMS does, only data blocks.

K3wl! How is that relevant? Every REXX that I've used on a PC has
implimented, e.g., chars, lines and NOTREADY.

-- 
Shmuel (Seymour J.) Metz, SysProg and JOAT  <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action.  I reserve the
right to publicly post or ridicule any abusive E-mail.  Reply to
domain Patriot dot net user shmuel+news to contact me.  Do not
reply to spamtrap@library.lspace.org

0
Reply Shmuel 10/7/2009 3:23:44 PM

In <4ACA5A6B.90F611F4@bestweb.net>, on 10/05/2009
   at 04:43 PM, Glenn Knickerbocker <NotR@bestweb.net> said:

>I think the intended rhetorical answer was that CHARS()=0 *is* the
>standard EOF check.

In ANSI Rexx chars and lines are the way to go, but in older Rexx
implementations you may have to rely on NOTREADY, which can be signalled
for other reasons than EOF.

-- 
Shmuel (Seymour J.) Metz, SysProg and JOAT  <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action.  I reserve the
right to publicly post or ridicule any abusive E-mail.  Reply to
domain Patriot dot net user shmuel+news to contact me.  Do not
reply to spamtrap@library.lspace.org

0
Reply Shmuel 10/7/2009 3:26:08 PM

Rick McGuire wrote:
> NOTREADY is not raised until end-of-clause, as is any condition where
> CALL ON is supported.  The assignment has a chance to complete as a result.

That's only true of CALL ON, not SIGNAL ON, right?  I don't see how you
would handle the last incomplete block when using SIGNAL ON NOTREADY.

�R
0
Reply Glenn 10/7/2009 3:32:59 PM





Shmuel (Seymour J.) Metz wrote:
> In <4ac9f259$0$4978$9a6e19ea@unlimited.newshosting.com>, on 10/05/2009
>    at 09:19 AM, LesK <5mre20@tampabay.rr.com> said:
> 
>> Rexx doesn't define i/o standards.
> 
> ROTF,LMAO. Please tell that to ANSI.
Oops! Sorry, I must have had a flashback to my VM days of 
Rex  and before ANSI.
> 
>> Pc's don't even understand 'records' at the OS level 
>> like CMS does, only data blocks.
> 
> K3wl! How is that relevant? Every REXX that I've used on a PC has
> implimented, e.g., chars, lines and NOTREADY.
Perhaps, but they aren't they arbitrary *conventions* for 
lines? They aren't defined by the OS, like they are for CMS.
> 
0
Reply LesK 10/8/2009 10:12:28 PM

In <4ace63cd$0$5648$9a6e19ea@unlimited.newshosting.com>, on 10/08/2009
   at 06:12 PM, LesK <5mre20@tampabay.rr.com> said:

>Perhaps, but they aren't they arbitrary *conventions* for 
>lines? They aren't defined by the OS, like they are for CMS.

But still referred to in the ANSI standard as well as all current PC
implementations.

-- 
Shmuel (Seymour J.) Metz, SysProg and JOAT  <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action.  I reserve the
right to publicly post or ridicule any abusive E-mail.  Reply to
domain Patriot dot net user shmuel+news to contact me.  Do not
reply to spamtrap@library.lspace.org

0
Reply Shmuel 10/9/2009 6:53:29 PM

44 Replies
236 Views

(page loaded in 0.796 seconds)


Reply: