summaryrefslogtreecommitdiff
path: root/src/md/compressedinteger.h
blob: 29a4f83dba97fb382ad4180e34ff894d3342d9d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// 
// File: CompressedInteger.h
// 

// 
// Class code:MetaData::CompressedInteger provides secure access to a compressed integer (as defined in CLI 
// ECMA specification). The integer is compressed into 1, 2 or 4 bytes. See code:CompressedInteger#Format 
// for full format description.
// 
// ======================================================================================

#pragma once

#include "external.h"

namespace MetaData
{

// --------------------------------------------------------------------------------------
// 
// This class provides secure access to a compressed integer (as defined in CLI ECMA specification). The 
// integer is compressed into 1, 2 or 4 bytes. See code:CompressedInteger#Format for full format description.
// 
class CompressedInteger
{
// #Format
// 
// The format/encoding of compressed integer is (defined in ECMA CLI specification):
//  The encoding is 1, 2 or 4 bytes long and depends on the first byte value. If the first byte is (binary):
//    * 0xxx xxxx ... then it's 1 byte long and the value is 0xxx xxxx.
//    * 10xx xxxx ... then it's 2 bytes long and the value is 00xx xxxx yyyy yyyy, where yyyy yyyy is the 
//                    second byte. Though values smaller than code:const_Max1Byte are technically invalid 
//                    when encoded with 2 bytes.
//    * 110x xxxx ... then it's 4 bytes long and the value is 000x xxxx yyyy yyyy zzzz zzzz wwww wwww, where 
//                    yyyy yyyy is the 2nd byte, zzzz zzzz is the 3rd byte and wwww wwww is the 4th byte.
//                    Though values smaller than code:const_Max2Bytes are technically invalid when encoded 
//                    with 4 bytes.
//    * 111x xxxx ... then it's invalid encoding.
// 
// Note: Some encodings are invalid, but CLR accepts them (see code:DataBlob::GetCompressedU), 
//  e.g. 1000 0000 0000 0000 (0x8000) encodes 0 while correct/valid encoding is 0000 0000 (0x00).
// 
private:
    // This class has only static methods and shouldn't be instantiated.
    CompressedInteger() {}
    
public:
    static const UINT32 const_MaxEncodingSize = 4;
    
    static const UINT32 const_Max1Byte  = 0x7f;
    static const UINT32 const_Max2Bytes = 0x3fff;
    static const UINT32 const_Max4Bytes = 0x1fffffff;
    
    static const UINT32 const_Max = const_Max4Bytes;
    
public:
    // 
    // Operations
    // 
    
    // Returns TRUE if the value (nValue) fits into 1-byte, 2-bytes or 4-bytes encoding and fills 
    // *pcbEncodingSize with 1, 2 or 4.
    // Returns FALSE if the value cannot be encoded as compressed integer, doesn't fill *pcbEncodingSize 
    // then.
    __checkReturn 
    __success(return)
    static inline BOOL GetEncodingSize(
              UINT32  nValue, 
        __out UINT32 *pcbEncodingSize);
    // Returns TRUE if the value (nValue) fits into 1-byte, 2-bytes or 4-bytes encoding and fills 
    // *pcbEncodingSize with 1, 2 or 4 and *pnEncodedValue with the encoded value.
    // Returns FALSE if the value cannot be encoded as compressed integer, doesn't fill *pcbEncodingSize 
    // nor *pnEncodedValue then.
    __success(return)
    static inline BOOL Encode(
              UINT32  nValue, 
        __out UINT32 *pnEncodedValue, 
        __out UINT32 *pcbEncodingSize);
    
};  // class CompressedInteger

};  // namespace MetaData

#include "compressedinteger.inl"