1 /*
2  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 using System;
26 
27 abstract class CodeElement {
28 
29 	internal int Address { get; set; }
30 
31 	internal int LastLength { get; set; }
32 
33 	// internal abstract int Length { get; }
34 
CodeElement()35 	internal CodeElement()
36 	{
37 		Address = -1;
38 	}
39 
SetJumpTarget(CodeElement target)40 	internal virtual void SetJumpTarget(CodeElement target)
41 	{
42 		throw new Exception("Code element accepts no target");
43 	}
44 
GetLength(bool oneByteCode)45 	internal abstract int GetLength(bool oneByteCode);
46 
Encode(BlobWriter bw, bool oneByteCode)47 	internal abstract int Encode(BlobWriter bw, bool oneByteCode);
48 
EncodeOneByte(uint val, BlobWriter bw)49 	internal static int EncodeOneByte(uint val, BlobWriter bw)
50 	{
51 		if (val > 255) {
52 			throw new Exception(string.Format(
53 				"Cannot encode '{0}' over one byte", val));
54 		}
55 		bw.Append((byte)val);
56 		return 1;
57 	}
58 
Encode7EUnsigned(uint val, BlobWriter bw)59 	internal static int Encode7EUnsigned(uint val, BlobWriter bw)
60 	{
61 		int len = 1;
62 		for (uint w = val; w >= 0x80; w >>= 7) {
63 			len ++;
64 		}
65 		if (bw != null) {
66 			for (int k = (len - 1) * 7; k >= 0; k -= 7) {
67 				int x = (int)(val >> k) & 0x7F;
68 				if (k > 0) {
69 					x |= 0x80;
70 				}
71 				bw.Append((byte)x);
72 			}
73 		}
74 		return len;
75 	}
76 
Encode7ESigned(int val, BlobWriter bw)77 	internal static int Encode7ESigned(int val, BlobWriter bw)
78 	{
79 		int len = 1;
80 		if (val < 0) {
81 			for (int w = val; w < -0x40; w >>= 7) {
82 				len ++;
83 			}
84 		} else {
85 			for (int w = val; w >= 0x40; w >>= 7) {
86 				len ++;
87 			}
88 		}
89 		if (bw != null) {
90 			for (int k = (len - 1) * 7; k >= 0; k -= 7) {
91 				int x = (int)(val >> k) & 0x7F;
92 				if (k > 0) {
93 					x |= 0x80;
94 				}
95 				bw.Append((byte)x);
96 			}
97 		}
98 		return len;
99 	}
100 }
101