Multimobile Development: Building Applications for any Smartphone
Why is BinaryWriter.Write7BitEncodedInt a protected method?
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.performance.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.

Chris
Why is the BinaryWriter.Write7BitEncodedInt a protected method? I wish
to use this functionality out of the box, yet I must override the
BinaryWriter class to do so, just curious why Microsoft?

Thanks in advance.

-Chris

Reply to this message...
Vote that this is a GOOD answer...
 
Really good experience at the Apple Store
MonoDroid – looking *awesome*
 
    
Brian Grunkemeyer (VIP)
We wrote this method as an internal implementation detail for the
Write(String) method. BinaryWriter prefixes strings with the number of
bytes, and we want a pretty compact representation of that length, since a
lot of strings are short. So we added this method. We didn't believe it
needed to be publically exposed, but we'll look at doing this in a future
release.

In the mean time, here's the implementation. It's a little tricky to get
right, at least if you want to support negative numbers, or if your "byte"
keyword suddenly changes from signed to unsigned as your product evolves.
Hopefully this will help you out.

protected void Write7BitEncodedInt(int value) {
// Write out an int 7 bits at a time. The high bit of the byte,
// when on, tells reader to continue reading more bytes.
uint v = (uint) value; // support negative numbers
while (v >= 0x80) {
Write((byte) (v | 0x80));
v >>= 7;
}
Write((byte)v);
}

protected int Read7BitEncodedInt() {
// Read out an int 7 bits at a time. The high bit
// of the byte when on means to continue reading more bytes.
int count = 0;
int shift = 0;
byte b;
do {
b = ReadByte();
count |= (b & 0x7F) << shift;
shift += 7;
} while ((b & 0x80) != 0);
return count;
}

Brian Grunkemeyer
MS CLR Base Class Library team

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Chris Tanger
Sorry for the delay, you were probably wondering if your answer was even
read. My computer hard disk crashed, it took me a while to rebuild, and I
was unabled to import my backed up news watch lists.

Thanks for the answer. I am writing some of my own Stream components and
needed the compressed int functionality for the same reasons you elected to
use it. I would also be *very* interested in a compressed double and
decimal. I believe using the code you provided I should be able to create a
compressed Int64 rather easily. The double would be rather complex due to
the way mantissa and exponents are stored internally. I think a decimal
shouldn't be too difficult though.

Thanks,

-Chris Tanger

"Brian Grunkemeyer" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Justin Rogers
Note Brian's code doesn't have any sort of stream corruption protection. In
fact
there is a way to hang a call to Read7Bit... by simply having a bunch of bytes
in
your file with high order bits set.

http://weblogs.asp.net/justin_rogers/archive/2004/02/19/76709.aspx" target="_blank">http://weblogs.asp.net/justin_rogers/archive/2004/02/19/76709.aspx
http://weblogs.asp.net/justin_rogers/archive/2004/02/21/77561.aspx

Above is the result of an examination of the function in question. I think
there may
also be a link to the initial examination. Because of the encoding methods used
it
is possible that other API's reliant on using the compression technique can also
hang.

I will say in the below code, that there is a fix for the negative number issue
that I
originally found in the rotor source, but still no shift register checking for
out of bounds
numbers.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Chris Tanger" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
First volume of Multimobile Development nearly ready to go to press
A mention on Developing for the iPhone and Android: The pros and cons
 
    
Chris Tanger
Yes, I did notice the lack of out of bounds checking, that did
surprise me considering the sometimes excessive checking done in other .NET
classes in safer contexts. I missed the inability to properly handle
negative numbers, that is a big one, thanks for the heads-up.

-Chris Tanger

"Justin Rogers" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
> Note Brian's code doesn't have any sort of stream corruption protection.
In
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
First chapters of Multimobile Development book now available on Apress Alpha program
iPad
 
    
Brian Grunkemeyer (VIP)
GOOD ANSWER
Fortunately, the code I posted had the fix for the negative number problem
(even though in our current usage, it's impossible to pass a negative
number to that method). I made this fix in our Whidbey tree quite a while
back.

I think Justin's code is fine for Justin's needs. One problem I ran into
when looking into this was that Read7BitEncodedInt was calling
BinaryReader's ReadByte, which is virtual. While ReadByte does do the
error checking for the end of the stream (which you probably thought I left
out), it does a lot of work to get the results you want. I don't know of
anyone who has attempted to subclass BinaryReader & override all the
methods, but perhaps we shouldn't break them if they exist. So I sped up
ReadByte a bit to avoid an extra method call & other branches as well (not
shown). You can look for this wherever you get the Whidbey Beta 2 sources
in a few months.

But the check for a corrupted input stream is interesting. I'll spend some
more time looking at this later, but here's what I came up with:

internal protected int Read7BitEncodedInt() {
// Read out an Int32 7 bits at a time. The high bit
// of the byte when on means to continue reading more bytes.
int count = 0;
int shift = 0;
byte b;
do {
// Check for a corrupted stream. Read a max of 5 bytes.
// @TODO: In a future version, add a DataFormatException.
if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7
throw new
FormatException(Environment.GetResourceString("Format_Bad7BitInt32"));

// ReadByte handles end of stream cases for us.
b = ReadByte();
count |= (b & 0x7F) << shift;
shift += 7;
} while ((b & 0x80) != 0);
return count;
}

Elsewhere, I've added this:

Format_Bad7BitInt32 = Too many bytes in what should have been a 7 bit
encoded Int32.

We should add a DataFormatException class that subclasses FormatException.
(It's not an IOException - you didn't have a disk failure, and we found the
file. Instead, it was corrupted or it wasn't the file you thought it was.)
I can't promise we'll add that in Whidbey, but I'll run it by a few
people. Note it's not a breaking change to move from throwing an exception
to throwing a subclass of that exception.

Brian Grunkemeyer
MS CLR Base Class Library team

Reply to this message...
Vote that this is a GOOD answer... (4 votes from other users already)
 
 
 
System.Environment
System.FormatException
System.IO.BinaryReader
System.IO.BinaryWriter
System.IO.IOException




Multimobile Development: Building Applications for any Smartphone
Ad
BootFX
Reliable and powerful .NET application framework.
iOS, Android and Windows Phone Development Training and Consultancy
Hosted by RackSRV Communications
 
Multimobile Development: Building Applications for any Smartphone
Copyright © AMX Software Ltd 2008-2010. Portions copyright © Matthew Baxter-Reynolds 2001-2010. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - 4.0.30129.1734