diff options
author | Simon J. Gerraty <sjg@FreeBSD.org> | 2019-01-21 20:23:49 +0000 |
---|---|---|
committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2019-01-21 20:23:49 +0000 |
commit | f55287d3221d3d9128a6529f97e55fb74250aec2 (patch) | |
tree | 9f1232240de5b9c8dc773240213b7eb3ad319df1 /T0/ConstData.cs |
Notes
Diffstat (limited to 'T0/ConstData.cs')
-rw-r--r-- | T0/ConstData.cs | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/T0/ConstData.cs b/T0/ConstData.cs new file mode 100644 index 000000000000..6a06b64ed145 --- /dev/null +++ b/T0/ConstData.cs @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +class ConstData { + + internal long ID { get; private set; } + internal int Address { get; set; } + internal int Length { + get { + return len; + } + } + + byte[] buf; + int len; + + internal ConstData(T0Comp ctx) + { + ID = ctx.NextBlobID(); + buf = new byte[4]; + len = 0; + } + + void Expand(int elen) + { + int tlen = len + elen; + if (tlen > buf.Length) { + int nlen = Math.Max(buf.Length << 1, tlen); + byte[] nbuf = new byte[nlen]; + Array.Copy(buf, 0, nbuf, 0, len); + buf = nbuf; + } + } + + internal void Add8(byte b) + { + Expand(1); + buf[len ++] = b; + } + + internal void Add16(int x) + { + Expand(2); + buf[len ++] = (byte)(x >> 8); + buf[len ++] = (byte)x; + } + + internal void Add24(int x) + { + Expand(3); + buf[len ++] = (byte)(x >> 16); + buf[len ++] = (byte)(x >> 8); + buf[len ++] = (byte)x; + } + + internal void Add32(int x) + { + Expand(4); + buf[len ++] = (byte)(x >> 24); + buf[len ++] = (byte)(x >> 16); + buf[len ++] = (byte)(x >> 8); + buf[len ++] = (byte)x; + } + + internal void AddString(string s) + { + byte[] sd = Encoding.UTF8.GetBytes(s); + Expand(sd.Length + 1); + Array.Copy(sd, 0, buf, len, sd.Length); + buf[len + sd.Length] = 0; + len += sd.Length + 1; + } + + void CheckIndex(int off, int dlen) + { + if (off < 0 || off > (len - dlen)) { + throw new IndexOutOfRangeException(); + } + } + + internal void Set8(int off, byte v) + { + CheckIndex(off, 1); + buf[off] = v; + } + + internal byte Read8(int off) + { + CheckIndex(off, 1); + return buf[off]; + } + + internal int Read16(int off) + { + CheckIndex(off, 2); + return (buf[off] << 8) | buf[off + 1]; + } + + internal int Read24(int off) + { + CheckIndex(off, 3); + return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2]; + } + + internal int Read32(int off) + { + CheckIndex(off, 4); + return (buf[off] << 24) | (buf[off + 1] << 16) + | (buf[off + 2] << 8) | buf[off + 3]; + } + + internal string ToString(int off) + { + StringBuilder sb = new StringBuilder(); + for (;;) { + int x = DecodeUTF8(ref off); + if (x == 0) { + return sb.ToString(); + } + if (x < 0x10000) { + sb.Append((char)x); + } else { + x -= 0x10000; + sb.Append((char)(0xD800 + (x >> 10))); + sb.Append((char)(0xDC00 + (x & 0x3FF))); + } + } + } + + int DecodeUTF8(ref int off) + { + if (off >= len) { + throw new IndexOutOfRangeException(); + } + int x = buf[off ++]; + if (x < 0xC0 || x > 0xF7) { + return x; + } + int elen, acc; + if (x >= 0xF0) { + elen = 3; + acc = x & 0x07; + } else if (x >= 0xE0) { + elen = 2; + acc = x & 0x0F; + } else { + elen = 1; + acc = x & 0x1F; + } + if (off + elen > len) { + return x; + } + for (int i = 0; i < elen; i ++) { + int y = buf[off + i]; + if (y < 0x80 || y >= 0xC0) { + return x; + } + acc = (acc << 6) + (y & 0x3F); + } + if (acc > 0x10FFFF) { + return x; + } + off += elen; + return acc; + } + + internal void Encode(BlobWriter bw) + { + for (int i = 0; i < len; i ++) { + bw.Append(buf[i]); + } + } +} |