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 using System.Collections.Generic;
27 using System.Text;
28 
29 class ConstData {
30 
31 	internal long ID { get; private set; }
32 	internal int Address { get; set; }
33 	internal int Length {
34 		get {
35 			return len;
36 		}
37 	}
38 
39 	byte[] buf;
40 	int len;
41 
ConstData(T0Comp ctx)42 	internal ConstData(T0Comp ctx)
43 	{
44 		ID = ctx.NextBlobID();
45 		buf = new byte[4];
46 		len = 0;
47 	}
48 
Expand(int elen)49 	void Expand(int elen)
50 	{
51 		int tlen = len + elen;
52 		if (tlen > buf.Length) {
53 			int nlen = Math.Max(buf.Length << 1, tlen);
54 			byte[] nbuf = new byte[nlen];
55 			Array.Copy(buf, 0, nbuf, 0, len);
56 			buf = nbuf;
57 		}
58 	}
59 
Add8(byte b)60 	internal void Add8(byte b)
61 	{
62 		Expand(1);
63 		buf[len ++] = b;
64 	}
65 
Add16(int x)66 	internal void Add16(int x)
67 	{
68 		Expand(2);
69 		buf[len ++] = (byte)(x >> 8);
70 		buf[len ++] = (byte)x;
71 	}
72 
Add24(int x)73 	internal void Add24(int x)
74 	{
75 		Expand(3);
76 		buf[len ++] = (byte)(x >> 16);
77 		buf[len ++] = (byte)(x >> 8);
78 		buf[len ++] = (byte)x;
79 	}
80 
Add32(int x)81 	internal void Add32(int x)
82 	{
83 		Expand(4);
84 		buf[len ++] = (byte)(x >> 24);
85 		buf[len ++] = (byte)(x >> 16);
86 		buf[len ++] = (byte)(x >> 8);
87 		buf[len ++] = (byte)x;
88 	}
89 
AddString(string s)90 	internal void AddString(string s)
91 	{
92 		byte[] sd = Encoding.UTF8.GetBytes(s);
93 		Expand(sd.Length + 1);
94 		Array.Copy(sd, 0, buf, len, sd.Length);
95 		buf[len + sd.Length] = 0;
96 		len += sd.Length + 1;
97 	}
98 
CheckIndex(int off, int dlen)99 	void CheckIndex(int off, int dlen)
100 	{
101 		if (off < 0 || off > (len - dlen)) {
102 			throw new IndexOutOfRangeException();
103 		}
104 	}
105 
Set8(int off, byte v)106 	internal void Set8(int off, byte v)
107 	{
108 		CheckIndex(off, 1);
109 		buf[off] = v;
110 	}
111 
Read8(int off)112 	internal byte Read8(int off)
113 	{
114 		CheckIndex(off, 1);
115 		return buf[off];
116 	}
117 
Read16(int off)118 	internal int Read16(int off)
119 	{
120 		CheckIndex(off, 2);
121 		return (buf[off] << 8) | buf[off + 1];
122 	}
123 
Read24(int off)124 	internal int Read24(int off)
125 	{
126 		CheckIndex(off, 3);
127 		return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2];
128 	}
129 
Read32(int off)130 	internal int Read32(int off)
131 	{
132 		CheckIndex(off, 4);
133 		return (buf[off] << 24) | (buf[off + 1] << 16)
134 			| (buf[off + 2] << 8) | buf[off + 3];
135 	}
136 
ToString(int off)137 	internal string ToString(int off)
138 	{
139 		StringBuilder sb = new StringBuilder();
140 		for (;;) {
141 			int x = DecodeUTF8(ref off);
142 			if (x == 0) {
143 				return sb.ToString();
144 			}
145 			if (x < 0x10000) {
146 				sb.Append((char)x);
147 			} else {
148 				x -= 0x10000;
149 				sb.Append((char)(0xD800 + (x >> 10)));
150 				sb.Append((char)(0xDC00 + (x & 0x3FF)));
151 			}
152 		}
153 	}
154 
DecodeUTF8(ref int off)155 	int DecodeUTF8(ref int off)
156 	{
157 		if (off >= len) {
158 			throw new IndexOutOfRangeException();
159 		}
160 		int x = buf[off ++];
161 		if (x < 0xC0 || x > 0xF7) {
162 			return x;
163 		}
164 		int elen, acc;
165 		if (x >= 0xF0) {
166 			elen = 3;
167 			acc = x & 0x07;
168 		} else if (x >= 0xE0) {
169 			elen = 2;
170 			acc = x & 0x0F;
171 		} else {
172 			elen = 1;
173 			acc = x & 0x1F;
174 		}
175 		if (off + elen > len) {
176 			return x;
177 		}
178 		for (int i = 0; i < elen; i ++) {
179 			int y = buf[off + i];
180 			if (y < 0x80 || y >= 0xC0) {
181 				return x;
182 			}
183 			acc = (acc << 6) + (y & 0x3F);
184 		}
185 		if (acc > 0x10FFFF) {
186 			return x;
187 		}
188 		off += elen;
189 		return acc;
190 	}
191 
Encode(BlobWriter bw)192 	internal void Encode(BlobWriter bw)
193 	{
194 		for (int i = 0; i < len; i ++) {
195 			bw.Append(buf[i]);
196 		}
197 	}
198 }
199