Ejemplo n.º 1
0
        /// <summary>
        /// Dekomprimiert eine Zeichenkette.
        /// </summary>
        /// <param name="bytes">Feld mit den dekomprimierten Werten.</param>
        /// <param name="index">Laufende Nummer des ersten zu dekomprimierenden Wertes.</param>
        /// <param name="count">Die Anzahl der zur Dekomprimierung zu verwenden Werte.</param>
        /// <returns>Die dekomprimierte Zeichenketten - bei Fehlern wird ein <i>...</i> angehängt.</returns>
        /// <exception cref="ArgumentException">Mindestens ein Parameter ist unzulässig.</exception>
        public override string GetString(byte[] bytes, int index, int count)
        {
            // Validate
            if (count < 1)
            {
                return(string.Empty);
            }

            // Get the table
            ushort[] table = null;
            if (1 == bytes[index])
            {
                table = BinaryTables[0];
            }
            else if (2 == bytes[index])
            {
                table = BinaryTables[1];
            }

            // Not table
            if (null == table)
            {
                return(Section.DefaultEncoding.GetString(bytes, index, count));
            }

            // Advance index
            ++index;
            --count;

            // Nothing in it
            if (count < 1)
            {
                return(string.Empty);
            }

            // Remember
            int initialIndex = index, initialCount = count;

            // Constructor
            List <byte> builder = new List <byte>();

            // Set current processing index
            ushort tableIndex = table[0];

            // Current index shift
            int indexShift = 0;

            // Previous pattern and width
            uint?previous = null;

            // Last checkpoint
            int lastCharPosition = 0;

            // Process
            for (; ;)
            {
                // Check for regular stop
                if (0 == tableIndex)
                {
                    // Load the initial check pattern
                    byte check = (byte)(0xff >> indexShift);

                    // All bytes must be zero
                    for (; count-- > 0; check = 0xff)
                    {
                        if (0 != (bytes[index++] & check))
                        {
                            break;
                        }
                    }

                    // Found something bad
                    if (count >= 0)
                    {
                        break;
                    }

                    // Load result
                    string decompressed = Encoding.UTF8.GetString(builder.ToArray());

                    // Load client
                    EventHandler <DecodingReportArgs> successHandler = OnSuccess;

                    // Report
                    if (null != successHandler)
                    {
                        // Create full data
                        byte[] compressed = new byte[initialCount];

                        // Fill it
                        Array.Copy(bytes, initialIndex, compressed, 0, compressed.Length);

                        // Create argument list
                        DecodingReportArgs args = new DecodingReportArgs();

                        // Fill it
                        args.CodePage       = (table == BinaryTables[0]) ? 1 : 2;
                        args.Uncompressed   = decompressed;
                        args.CompressedData = compressed;

                        // Report
                        successHandler(this, args);
                    }

                    // Report
                    return(decompressed);
                }

                // Unexpected end of input
                if (count < 1)
                {
                    break;
                }

                // Check for leaf
                if (tableIndex <= 127)
                {
                    // At this position
                    lastCharPosition = 8 * (index - initialIndex) + indexShift;

                    // Append
                    builder.Add((byte)('\x0001' + tableIndex - 1));

                    // Restart
                    tableIndex = table[tableIndex];
                }

                // In error
                if (tableIndex == TableCreator.ErrorIndicator)
                {
                    break;
                }

                // Check for escape mode
                bool inEscape = (tableIndex == TableCreator.EscapeIndicator);

                // Get the number of bits to process
                ushort bitWidth = inEscape ? (ushort)8 : table[tableIndex++];

                // Check limitation
                if (bitWidth > 24)
                {
                    break;
                }

                // Not possible
                if (bitWidth > 8 * count)
                {
                    break;
                }

                // The pattern
                uint pattern;

                // Quick load pattern
                if (previous.HasValue)
                {
                    // Use
                    pattern = previous.Value;
                }
                else
                {
                    // The pattern
                    pattern = bytes[index + 0];

                    // Append
                    pattern <<= 8;
                    if (count > 1)
                    {
                        pattern |= bytes[index + 1];
                    }

                    // Append
                    pattern <<= 8;
                    if (count > 2)
                    {
                        pattern |= bytes[index + 2];
                    }

                    // Append
                    pattern <<= 8;
                    if (count > 3)
                    {
                        pattern |= bytes[index + 3];
                    }

                    // Remember
                    previous = pattern;
                }

                // Correct it
                pattern <<= indexShift;

                // Adjust shift
                indexShift += bitWidth;

                // Adjust index
                if (indexShift >= 8)
                {
                    // Shift bytes
                    int bytesEaten = indexShift / 8;

                    // Adjust all
                    index      += bytesEaten;
                    count      -= bytesEaten;
                    indexShift %= 8;

                    // Clear cache
                    previous = null;
                }

                // Check for escape mode
                if (inEscape)
                {
                    // At this position
                    lastCharPosition = 8 * (index - initialIndex) + indexShift;

                    // Get character
                    pattern >>= 24;

                    // See if this is it
                    if (pattern < 128)
                    {
                        if (0 == pattern)
                        {
                            tableIndex = 0;
                        }
                        else
                        {
                            tableIndex = (ushort)(1 + (pattern - 1));
                        }
                    }
                    else
                    {
                        builder.Add((byte)pattern);
                    }

                    // Next
                    continue;
                }

                // Get the first link position
                ushort linkIndex = table[tableIndex++];

                // Translate the pattern
                uint patternIndex = pattern >> (32 - bitWidth);

                // Check mode
                if (linkIndex == TableCreator.EndIndicator)
                {
                    // Attach to the entry
                    tableIndex = table[tableIndex + patternIndex];
                }
                else
                {
                    // Try to find
                    do
                    {
                        // Test pattern - upper half
                        uint test = table[linkIndex - 4];

                        // Test pattern - lower half
                        test <<= 16;
                        test  |= table[linkIndex - 3];

                        // Next table
                        tableIndex = table[linkIndex - 2];

                        // Did it
                        if (test == patternIndex)
                        {
                            break;
                        }

                        // Advance
                        linkIndex = table[linkIndex - 1];
                    }while (linkIndex != TableCreator.EndIndicator);

                    // In error
                    if (linkIndex == TableCreator.EndIndicator)
                    {
                        break;
                    }
                }
            }

            // Load client
            EventHandler <DecodingFailureArgs> handler = OnFailure;

            // Report
            if (null != handler)
            {
                // Create full data
                byte[] compressed = new byte[initialCount];

                // Fill it
                Array.Copy(bytes, initialIndex, compressed, 0, compressed.Length);

                // Create argument list
                DecodingFailureArgs args = new DecodingFailureArgs();

                // Fill it
                args.Uncompressed   = Encoding.UTF8.GetString(builder.ToArray());
                args.CodePage       = (table == BinaryTables[0]) ? 1 : 2;
                args.BitPosition    = lastCharPosition;
                args.CompressedData = compressed;

                // Report
                handler(this, args);
            }

            // Report
            return(Encoding.UTF8.GetString(builder.ToArray()) + "....");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Dekomprimiert eine Zeichenkette.
        /// </summary>
        /// <param name="bytes">Feld mit den dekomprimierten Werten.</param>
        /// <param name="index">Laufende Nummer des ersten zu dekomprimierenden Wertes.</param>
        /// <param name="count">Die Anzahl der zur Dekomprimierung zu verwenden Werte.</param>
        /// <returns>Die dekomprimierte Zeichenketten - bei Fehlern wird ein <i>...</i> angehängt.</returns>
        /// <exception cref="ArgumentException">Mindestens ein Parameter ist unzulässig.</exception>
        public override string GetString( byte[] bytes, int index, int count )
        {
            // Validate
            if (count < 1)
                return string.Empty;

            // Get the table
            ushort[] table = null;
            if (1 == bytes[index])
                table = BinaryTables[0];
            else if (2 == bytes[index])
                table = BinaryTables[1];

            // Not table
            if (null == table)
                return Section.DefaultEncoding.GetString( bytes, index, count );

            // Advance index
            ++index;
            --count;

            // Nothing in it
            if (count < 1)
                return string.Empty;

            // Remember
            int initialIndex = index, initialCount = count;

            // Constructor
            List<byte> builder = new List<byte>();

            // Set current processing index
            ushort tableIndex = table[0];

            // Current index shift
            int indexShift = 0;

            // Previous pattern and width
            uint? previous = null;

            // Last checkpoint
            int lastCharPosition = 0;

            // Process
            for (; ; )
            {
                // Check for regular stop
                if (0 == tableIndex)
                {
                    // Load the initial check pattern
                    byte check = (byte) (0xff >> indexShift);

                    // All bytes must be zero
                    for (; count-- > 0; check = 0xff)
                        if (0 != (bytes[index++] & check))
                            break;

                    // Found something bad
                    if (count >= 0)
                        break;

                    // Load result
                    string decompressed = Encoding.UTF8.GetString( builder.ToArray() );

                    // Load client
                    EventHandler<DecodingReportArgs> successHandler = OnSuccess;

                    // Report
                    if (null != successHandler)
                    {
                        // Create full data
                        byte[] compressed = new byte[initialCount];

                        // Fill it
                        Array.Copy( bytes, initialIndex, compressed, 0, compressed.Length );

                        // Create argument list
                        DecodingReportArgs args = new DecodingReportArgs();

                        // Fill it
                        args.CodePage = (table == BinaryTables[0]) ? 1 : 2;
                        args.Uncompressed = decompressed;
                        args.CompressedData = compressed;

                        // Report
                        successHandler( this, args );
                    }

                    // Report
                    return decompressed;
                }

                // Unexpected end of input
                if (count < 1)
                    break;

                // Check for leaf
                if (tableIndex <= 127)
                {
                    // At this position
                    lastCharPosition = 8 * (index - initialIndex) + indexShift;

                    // Append
                    builder.Add( (byte) ('\x0001' + tableIndex - 1) );

                    // Restart
                    tableIndex = table[tableIndex];
                }

                // In error
                if (tableIndex == TableCreator.ErrorIndicator)
                    break;

                // Check for escape mode
                bool inEscape = (tableIndex == TableCreator.EscapeIndicator);

                // Get the number of bits to process
                ushort bitWidth = inEscape ? (ushort) 8 : table[tableIndex++];

                // Check limitation
                if (bitWidth > 24)
                    break;

                // Not possible
                if (bitWidth > 8 * count)
                    break;

                // The pattern
                uint pattern;

                // Quick load pattern
                if (previous.HasValue)
                {
                    // Use
                    pattern = previous.Value;
                }
                else
                {
                    // The pattern
                    pattern = bytes[index + 0];

                    // Append 
                    pattern <<= 8;
                    if (count > 1)
                        pattern |= bytes[index + 1];

                    // Append 
                    pattern <<= 8;
                    if (count > 2)
                        pattern |= bytes[index + 2];

                    // Append 
                    pattern <<= 8;
                    if (count > 3)
                        pattern |= bytes[index + 3];

                    // Remember
                    previous = pattern;
                }

                // Correct it
                pattern <<= indexShift;

                // Adjust shift
                indexShift += bitWidth;

                // Adjust index
                if (indexShift >= 8)
                {
                    // Shift bytes
                    int bytesEaten = indexShift / 8;

                    // Adjust all
                    index += bytesEaten;
                    count -= bytesEaten;
                    indexShift %= 8;

                    // Clear cache
                    previous = null;
                }

                // Check for escape mode
                if (inEscape)
                {
                    // At this position
                    lastCharPosition = 8 * (index - initialIndex) + indexShift;

                    // Get character
                    pattern >>= 24;

                    // See if this is it
                    if (pattern < 128)
                        if (0 == pattern)
                            tableIndex = 0;
                        else
                            tableIndex = (ushort) (1 + (pattern - 1));
                    else
                        builder.Add( (byte) pattern );

                    // Next
                    continue;
                }

                // Get the first link position
                ushort linkIndex = table[tableIndex++];

                // Translate the pattern
                uint patternIndex = pattern >> (32 - bitWidth);

                // Check mode
                if (linkIndex == TableCreator.EndIndicator)
                {
                    // Attach to the entry
                    tableIndex = table[tableIndex + patternIndex];
                }
                else
                {
                    // Try to find
                    do
                    {
                        // Test pattern - upper half
                        uint test = table[linkIndex - 4];

                        // Test pattern - lower half
                        test <<= 16;
                        test |= table[linkIndex - 3];

                        // Next table
                        tableIndex = table[linkIndex - 2];

                        // Did it
                        if (test == patternIndex)
                            break;

                        // Advance
                        linkIndex = table[linkIndex - 1];
                    }
                    while (linkIndex != TableCreator.EndIndicator);

                    // In error
                    if (linkIndex == TableCreator.EndIndicator)
                        break;
                }
            }

            // Load client
            EventHandler<DecodingFailureArgs> handler = OnFailure;

            // Report
            if (null != handler)
            {
                // Create full data
                byte[] compressed = new byte[initialCount];

                // Fill it
                Array.Copy( bytes, initialIndex, compressed, 0, compressed.Length );

                // Create argument list
                DecodingFailureArgs args = new DecodingFailureArgs();

                // Fill it
                args.Uncompressed = Encoding.UTF8.GetString( builder.ToArray() );
                args.CodePage = (table == BinaryTables[0]) ? 1 : 2;
                args.BitPosition = lastCharPosition;
                args.CompressedData = compressed;

                // Report
                handler( this, args );
            }

            // Report
            return Encoding.UTF8.GetString( builder.ToArray() ) + "....";
        }