diff options
author | Raja R Harinath <harinath@hurrynot.org> | 2006-02-15 14:29:58 +0300 |
---|---|---|
committer | Raja R Harinath <harinath@hurrynot.org> | 2006-02-15 14:29:58 +0300 |
commit | d02c00d24a7494e30179437b4150725560d06144 (patch) | |
tree | 3d424d9753478ea859cf9a6ea6ec6befcbc29159 /mcs/class/PEAPI | |
parent | 5a71d6eba1f3f4615f35eca90ab07a40a39f0a13 (diff) |
* Metadata.cs (BoundArray.CompressSignedNum): Document the
transformation. Avoid a few casts.
svn path=/trunk/mcs/; revision=56888
Diffstat (limited to 'mcs/class/PEAPI')
-rw-r--r-- | mcs/class/PEAPI/ChangeLog | 5 | ||||
-rw-r--r-- | mcs/class/PEAPI/Metadata.cs | 47 |
2 files changed, 42 insertions, 10 deletions
diff --git a/mcs/class/PEAPI/ChangeLog b/mcs/class/PEAPI/ChangeLog index dae5b1005e0..e2b2e9e0fde 100644 --- a/mcs/class/PEAPI/ChangeLog +++ b/mcs/class/PEAPI/ChangeLog @@ -1,3 +1,8 @@ +2006-02-15 Raja R Harinath <rharinath@novell.com> + + * Metadata.cs (BoundArray.CompressSignedNum): Document the + transformation. Avoid a few casts. + 2006-02-15 Ankit Jain <jankit@novell.com> * Metadata.cs (BoundArray.CompressSignedNum): New. Encode signed values, diff --git a/mcs/class/PEAPI/Metadata.cs b/mcs/class/PEAPI/Metadata.cs index 98759fc0493..083f8ba8fbe 100644 --- a/mcs/class/PEAPI/Metadata.cs +++ b/mcs/class/PEAPI/Metadata.cs @@ -2352,20 +2352,47 @@ namespace PEAPI { private void CompressSignedNum (int val, MemoryStream str) { uint uval = (uint) val; - int sign = val < 0 ? 1 : 0; - uint fval = (uint) ((uval << 1) | sign); - int sval = (((val < 0 ? - val : val)) << 1) - sign; - - if (sval < 0x80) + byte sign = 0; + if (val < 0) { + val = -val; + sign = 1; + } + + /* Map the signed number to an unsigned number in two ways. + + fval: left-rotated 2's complement representation + sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, .... + the mapping is: x -> 2*|x| - signbit(x) + */ + uint fval = (uval << 1) | sign; + int sval = (val << 1) - sign; + + /* An overly clever transformation: + + a. sval is used to determine the number of bytes in the compressed representation. + b. fval is truncated to the appropriate number of bits and output using the + normal unsigned-int compressor. + + However, or certain values, the truncated fval doesn't carry enough information to round trip. + + (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values + + So, we use full 4 bytes to encode such values. + + LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case. + e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64 + */ + if (sval <= 0x7F) MetaData.CompressNum (fval & 0x7F, str); - else if (sval < 0x4000 && (fval & 0x3fff) >= 0x80) - /* If (fval & 0x3fff) < 0x80, then - encode with full 4 bytes */ + else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F) MetaData.CompressNum (fval & 0x3FFF, str); + else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF) + MetaData.CompressNum (fval & 0x1FFFFFFF, str); else - MetaData.CompressNum ((uint) (fval & 0x1FFFFFFF), str); + /* FIXME: number cannot be represented. Report a warning. */ + // throw new Exception ("cannot represent signed value" + -val); + MetaData.CompressNum (fval, str); } - } #endregion |