Example #1
0
        public void WriteZString([NotNull] string str, bool withLength, StringEncoderMode mode = StringEncoderMode.Normal)
        {
            MaybeProcessEscapeChars(ref str);

            var zstr = StringEncoder.Encode(str, mode);

            if (FinalPass && AbbreviateMode)
            {
                AbbrevFinder.AddText(str);
            }

            if (withLength)
            {
                WriteByte((byte)(zstr.Length / 2));
            }

            position += zstr.Length;
            stream?.Write(zstr, 0, zstr.Length);
        }
Example #2
0
        public byte[] Encode(string str, int?size, StringEncoderMode mode, out int zchars)
        {
            var noAbbrevs = mode == StringEncoderMode.NoAbbreviations;

            if (!noAbbrevs)
            {
                Frozen = true;
            }

            var temp = new List <byte>();
            var sb   = new StringBuilder(str);

            // temporarily replace abbreviated strings with Unicode private use characters (E000-E05F)
            if (!noAbbrevs)
            {
                for (int i = 0; i < abbrevs.Count; i++)
                {
                    var idx = abbrevs[i].Pattern.FindIn(sb);
                    while (idx >= 0)
                    {
                        sb.Remove(idx, abbrevs[i].Pattern.Text.Length - 1);
                        sb[idx] = (char)(0xE000 + abbrevs[i].Number);
                        idx     = abbrevs[i].Pattern.FindIn(sb);
                    }
                }
            }

            for (int i = 0; i < sb.Length; i++)
            {
                char c = sb[i];
                if (c == ' ')
                {
                    temp.Add(0);
                }
                else if (c == '\n')
                {
                    temp.Add(5);
                    temp.Add(7);
                }
                else if (!noAbbrevs && c >= '\ue000' && c < '\ue060')
                {
                    int abbrNum = c - '\ue000';
                    temp.Add((byte)(1 + abbrNum / 32));
                    temp.Add((byte)(abbrNum % 32));
                }
                else
                {
                    if (UnicodeTranslation.Table.TryGetValue(c, out byte b) == false)
                    {
                        b = (byte)c;
                    }

                    int idx;
                    if ((idx = Array.IndexOf(charset[0], b)) >= 0)
                    {
                        temp.Add((byte)(idx + 6));
                    }
                    else if ((idx = Array.IndexOf(charset[1], b)) >= 0)
                    {
                        temp.Add(4);
                        temp.Add((byte)(idx + 6));
                    }
                    else if ((idx = Array.IndexOf(charset[2], b)) >= 0)
                    {
                        temp.Add(5);
                        temp.Add((byte)(idx + 8));
                    }
                    else
                    {
                        temp.Add(5);
                        temp.Add(6);
                        temp.Add((byte)((b >> 5) & 31));
                        temp.Add((byte)(b & 31));
                    }
                }
            }

            zchars = temp.Count;

            int resultSize;

            if (size == null)
            {
                if (temp.Count == 0)
                {
                    temp.Add(5);
                }

                while (temp.Count % 3 != 0)
                {
                    temp.Add(5);
                }

                resultSize = temp.Count * 2 / 3;
            }
            else
            {
                while (temp.Count < size)
                {
                    temp.Add(5);
                }

                resultSize = size.Value * 2 / 3;
            }

            var result = new byte[Math.Min(resultSize, temp.Count * 2 / 3)];

            for (int i = 0, t = 0; i < result.Length;)
            {
                // _aaaaabb bbbccccc
                byte a = temp[t++], b = temp[t++], c = temp[t++];
                result[i++] = (byte)(a << 2 | b >> 3);
                result[i++] = (byte)(b << 5 | c);
            }

            if (result.Length >= 2)
            {
                result[result.Length - 2] |= 0x80;
            }
            return(result);
        }
Example #3
0
 public byte[] Encode(string str, StringEncoderMode mode) =>
 Encode(str, null, mode);
Example #4
0
 public byte[] Encode(string str, int?size, StringEncoderMode mode) =>
 Encode(str, size, mode, out _);