199 lines
4.0 KiB
C#
199 lines
4.0 KiB
C#
|
/*
|
||
|
* 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]);
|
||
|
}
|
||
|
}
|
||
|
}
|