Topaz Filer: if you use e-mail for business, we can save you money and decrease your risk.
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
GOOD ANSWER
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... (1 vote from another user already)
 
 
    
Brian Grunkemeyer (VIP)
GOOD ANSWER
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... (2 votes from other users already)
 
 
    
Chris Tanger
GOOD ANSWER
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... (1 vote from another user already)
 
 
    
Justin Rogers
GOOD ANSWER
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... (1 vote from another user already)
 
 
    
Chris Tanger
GOOD ANSWER
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... (2 votes from other users already)
 
 
    
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... (1 vote from another user already)
 
 
 
System.Environment
System.FormatException
System.IO.BinaryReader
System.IO.BinaryWriter
System.IO.IOException




Ad
BootFX
Reliable and powerful .NET application framework.
Recession Busting Bespoke Software
Get through the recession by investing in bespoke software to decrease costs and create commercial opportunities.
Other DN247 Network Sites
.NET 247
SQL Server Wins
Old Skool Developer
 
Copyright © AMX Software Ltd 2008-2009. Portions copyright © Matthew Baxter-Reynolds 2001-2009. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - .NET 247 is a member of the DN247 Network - 4.0.30129.1734