Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > confusing string parsing problem

Reply
Thread Tools

confusing string parsing problem

 
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
I don't understand how to do the following, any help is very
appreciated. I have been programming in ruby 1.8.7 for about a month.

I have a string that has in it:
2 byte UINT16
2 byte UINT16
1 byte UINT8 representing how many pairs of the next 2 strings there are
variable length string1 <- Although for now I know this always equals
BFO
variable length string2
2 byte UINT16

I want to display each value from the fields, while also removing it
from the string as I read it out. I believe the strings are terminated
with a 0, so the null character needs to be removed also to correctly
parse other fields. Although part of my problem is I don't understand
how to parse until a null character is found, is this \0 like in C? Or
is it \000 as I have scene some places? or 0.to_chr ?

The string comes from a "rest" variable length field from the bit-struct
class. So there was data before in the rest that I have processed and
taken out off the front of the string, and after this point there is
more data, but for now I am interested in this block of data.

Something else that is known that could help, is the total length of the
whole block is known, so the 7 bytes + however many bytes for the
variable length strings is known.

My attempt is horrible I know, and I don't think it really runs.
writelog() is method to display my value...

iterations_to_do = (bin_msg.element_length - 7) - 4
temparray = []
j = 0
if /^BFO/ =~ bin_msg.optional_sub_elements
writelog("\n\n Parameter Name = BFO")
bin_msg.optional_sub_elements.sub!(/^BFO/, '')

while j < iterations_to_do
bin_msg.optional_sub_elements.each_byte do |character|
unless character == 0.chr
temparray << character
j += 1
end
end
end
#here print first j number of elements in temparray?

Thanks again,
Matt
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
Also forgot to mention, the 2nd variable length string happens to be
formated as -8000 to 8000, so i have to see the sign and a variable
length of digits, but as ascii characters not as an int.

thanks again,
Matt
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
brabuhr@gmail.com
Guest
Posts: n/a
 
      09-02-2009
On Wed, Sep 2, 2009 at 10:01 AM, Matt Brooks<(E-Mail Removed)> wrote:
> I don't understand how to do the following, any help is very
> appreciated. =A0I have been programming in ruby 1.8.7 for about a month.
>
> I have a string that has in it:
> 2 byte UINT16
> 2 byte UINT16
> 1 byte UINT8 representing how many pairs of the next 2 strings there are
> variable length string1 <- Although for now I know this always equals
> BFO
> variable length string2
> 2 byte UINT16
>
> I want to display each value from the fields, while also removing it
> from the string as I read it out...
>
> My attempt is horrible I know, and I don't think it really runs.


Can you post an example of your data and code with the incorrect
output and expected output?

> cat z.rb

string =3D ""
string << 0.chr << 1.chr
string << 0.chr << 2.chr
string << 2.chr
string << "foo" << "BFO"
string << "bar" << "BFO"
string << 0.chr << 3.chr

p string

p string[0..1], string[0..1].unpack('n')
p string[2..3], string[2..3].unpack('n')
p string[0..3].unpack('n2')

p string[4..4], string[4..4].unpack('C')
p string[0..4].unpack('n2C')

p string[5..-2].split(/BFO/)

> ruby -v z.rb

ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
"\000\001\000\002\002fooBFObarBFO\000\003"
"\000\001"
[1]
"\000\002"
[2]
[1, 2]
"\002"
[2]
[1, 2, 2]
["foo", "bar", "\000"]

 
Reply With Quote
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
unknown wrote:
> On Wed, Sep 2, 2009 at 10:01 AM, Matt Brooks<(E-Mail Removed)>
> wrote:
>> 2 byte UINT16
>>
>> I want to display each value from the fields, while also removing it
>> from the string as I read it out...
>>
>> My attempt is horrible I know, and I don't think it really runs.

>
> Can you post an example of your data and code with the incorrect
> output and expected output?
>
>> cat z.rb

> string = ""
> string << 0.chr << 1.chr
> string << 0.chr << 2.chr
> string << 2.chr
> string << "foo" << "BFO"
> string << "bar" << "BFO"
> string << 0.chr << 3.chr
>
> p string
>
> p string[0..1], string[0..1].unpack('n')
> p string[2..3], string[2..3].unpack('n')
> p string[0..3].unpack('n2')
>
> p string[4..4], string[4..4].unpack('C')
> p string[0..4].unpack('n2C')
>
> p string[5..-2].split(/BFO/)
>
>> ruby -v z.rb

> ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
> "\000\001\000\002\002fooBFObarBFO\000\003"
> "\000\001"
> [1]
> "\000\002"
> [2]
> [1, 2]
> "\002"
> [2]
> [1, 2, 2]
> ["foo", "bar", "\000"]



Thanks a lot for your reply, i will look into it and see if i can
implement using unpack. in the meantime this is a sample output...



My current output is:
1st 2 byte field = 3
2nd 2 byte field = 0
Num Pairs = 1
sub_elements =
"BFO\0000\000\000\000\001\000\000\0005\000\003\000 \000\000\00
0\000\000\000\000\000\001\002\000\000\312+\335V\35 3\262\000\001\001Internal...and
so on for hundreds of bytes more...
I, [2009-09-02 11:56:10 #4864] INFO -- : Pairs to get: 1
I, [2009-09-02 11:56:10 #4864] INFO -- : Param Value Name: BFO


what i want output to be:
I, [2009-09-02 11:56:10 #4864] INFO -- : Pairs to get: 1
I, [2009-09-02 11:56:10 #4864] INFO -- : Param Value Name: BFO
I, [2009-09-02 11:56:10 #4864] INFO -- : String Value: whatever the
string is till it is null terminated
I, [2009-09-02 11:56:10 #4864] INFO -- : Last 2 byte field: 0


And At this point I need the sub_elements string to not contain any of
the above parameters printed out, ie. whatever I display is done with
and needs to be deleted out of the front of the string.


my code:
I was redoing my code, and only up to this point.
#prints first 5 bytes formated nicely
writelog("#{bin_msg.inspect_detailed})")

#How many pairs to expect
writelog("Pairs to get: #{bin_msg.num_optional_mod_params}")

#Remove BFO while printing it as well
writelog("Param Value Name: #{bin_msg.sub_elements.slice!(/^BFO/)}")


#THIS DOESN'T WORK!!! Needs to scan for possible minus sign, plus up to
#variable length number of digits, up to the null termination of the
string
bin_msg.sub_elements.scan(/-?[0-9]+\Z/)

#Needs to then print the next 2 bytes while taking that out of the
string as well
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
Also, I never made it clear but the string is in network byte order (big
Endian)
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      09-02-2009
Matt Brooks wrote:
> Also, I never made it clear but the string is in network byte order (big
> Endian)


data = ""

data << 0.chr << 3.chr #2 bytes
data << 0.chr << 0.chr #2 bytes
data << 1.chr #1 byte
data << "BFO" << 0.chr #null terminated string
data << "-8000" << "\000" #null terminated string
data << 0.chr << 0.chr #2 bytes

p data

--output:--
"\000\003\000\000\001BFO\000-8000\000\000\000"

results = data.unpack("n2CZ*Z*n")
p results

--output:--
[3, 0, 1, "BFO", "-8000", 0]


--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
7stud -- wrote:
> Matt Brooks wrote:
>> Also, I never made it clear but the string is in network byte order (big
>> Endian)

>
> data = ""
>
> data << 0.chr << 3.chr #2 bytes
> data << 0.chr << 0.chr #2 bytes
> data << 1.chr #1 byte
> data << "BFO" << 0.chr #null terminated string
> data << "-8000" << "\000" #null terminated string
> data << 0.chr << 0.chr #2 bytes
>
> p data
>
> --output:--
> "\000\003\000\000\001BFO\000-8000\000\000\000"
>
> results = data.unpack("n2CZ*Z*n")
> p results
>
> --output:--
> [3, 0, 1, "BFO", "-8000", 0]




7stud, Wow that is an elegant way! thank you for your time. I do
appreciate both responses very much. The first one clued me into using
unpack...correctly

I was just now excited to get my very verbose way to work, I will
probably switch to how you are doing it. Just for comment, here is what
i just got working...


#prints first 5 bytes formatted nicely
writelog("Sub Element Message: #{bin_msg.inspect_detailed})")

#How many pairs to iterate through
writelog("Pairs to get: #{bin_msg.pairs}")

times_iterated = 0
while times_iterated < bin_msg.pairs

#Get Value Name, variable length
current_unpacked_char =
bin_msg.optional_sub_elements.unpack("Z*")
#Print it
writelog("\n\nParam Value Name = #{current_unpacked_char}\n")
#Remove Name from front of string
bin_msg.optional_sub_elements =
bin_msg.optional_sub_elements.sub(/^#{current_unpacked_char}\000/, '')

#Get Value, variable length
current_unpacked_char =
bin_msg.optional_sub_elements.unpack("Z*")
#Print it
writelog("\n\nParam Value = #{current_unpacked_char}\n")
#Remove Value from front of string
bin_msg.optional_sub_elements =
bin_msg.optional_sub_elements.sub(/^#{current_unpacked_char}\000/, '')

#Get Last two byte value
current_unpacked_char =
bin_msg.optional_sub_elements.unpack("n")
#Print it
writelog("\n\nAudio Inversion Frequency =
#{current_unpacked_char}\n")
current_packed_char = current_unpacked_char.pack("n")
#Remove Last two byte value
bin_msg.optional_sub_elements =
bin_msg.optional_sub_elements.sub(/^#{current_packed_char}/, '')

times_iterated += 1
end
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      09-02-2009
Matt Brooks wrote:
> Last 2 byte field: 0
>
>
> And At this point I need the sub_elements string to not contain any of
> the above parameters printed out, ie. whatever I display is done with
> and needs to be deleted out of the front of the string.
>


You could do that simply like this:

chop_size = 2 +
2 +
1 +
results[3].length + 1 +
results[4].length + 1 +
1

puts chop_size

--output:--
16


For example:


data = ""
data << 0.chr << 3.chr
data << 0.chr << 0.chr
data << 1.chr
data << "BFO" << 0.chr
data << "-8000" << "\000"
data << 0.chr << 0.chr
data << "the rest"


results = data.unpack("n2CZ*Z*n")

chop_size = 2 +
2 +
1 +
results[3].length + 1 +
results[4].length + 1 +
1

puts chop_size

--output:--
16


puts "-->#{data[chop_size..-1]}<---"

--output:--
-->the rest<---

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      09-02-2009
7stud -- wrote:
> You could do that simply like this:
>
> chop_size = 2 +
> 2 +
> 1 +
> results[3].length + 1 +
> results[4].length + 1 +
> 1
>


Whoops. The last field is 2 bytes.

chop_size = 2 +
2 +
1 +
results[3].length + 1 +
results[4].length + 1 +
2

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Matt Brooks
Guest
Posts: n/a
 
      09-02-2009
7stud -- wrote:
> 7stud -- wrote:
>> You could do that simply like this:
>>
>> chop_size = 2 +
>> 2 +
>> 1 +
>> results[3].length + 1 +
>> results[4].length + 1 +
>> 1
>>

>
> Whoops. The last field is 2 bytes.
>
> chop_size = 2 +
> 2 +
> 1 +
> results[3].length + 1 +
> results[4].length + 1 +
> 2


Thanks 7stud, I like that way. Very nice, I will be using this!!!
Slowly Ruby is growing on me!
-Matt
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
A very confusing problem about sending message to an irreachable IP billdavidcn@gmail.com Java 1 01-09-2007 04:04 AM
Confusing problem with page_unload loading listbox VB Programmer ASP .Net 1 09-22-2004 12:14 PM
Please help with this confusing network problem JKJK Computer Support 5 03-01-2004 04:52 PM
confusing delete problem Joerg Toellner C++ 10 02-25-2004 08:31 AM
Confusing problem between Tkinter.Intvar() and self declared variable class Marc Python 2 01-27-2004 06:43 PM



Advertisments