Initial import.
[BearSSL] / T0 / ConstData.cs
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
42 internal ConstData(T0Comp ctx)
43 {
44 ID = ctx.NextBlobID();
45 buf = new byte[4];
46 len = 0;
47 }
48
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
60 internal void Add8(byte b)
61 {
62 Expand(1);
63 buf[len ++] = b;
64 }
65
66 internal void Add16(int x)
67 {
68 Expand(2);
69 buf[len ++] = (byte)(x >> 8);
70 buf[len ++] = (byte)x;
71 }
72
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
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
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
99 void CheckIndex(int off, int dlen)
100 {
101 if (off < 0 || off > (len - dlen)) {
102 throw new IndexOutOfRangeException();
103 }
104 }
105
106 internal void Set8(int off, byte v)
107 {
108 CheckIndex(off, 1);
109 buf[off] = v;
110 }
111
112 internal byte Read8(int off)
113 {
114 CheckIndex(off, 1);
115 return buf[off];
116 }
117
118 internal int Read16(int off)
119 {
120 CheckIndex(off, 2);
121 return (buf[off] << 8) | buf[off + 1];
122 }
123
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
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
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
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
192 internal void Encode(BlobWriter bw)
193 {
194 for (int i = 0; i < len; i ++) {
195 bw.Append(buf[i]);
196 }
197 }
198 }